2021-03-06 09:48:58 +05:30
|
|
|
<div align="center">
|
2021-03-06 17:07:28 +05:30
|
|
|
<h1>PoW-SHA256</h1>
|
2021-03-06 09:48:58 +05:30
|
|
|
<p>
|
2021-03-06 17:07:28 +05:30
|
|
|
<strong>PoW-SHA256 - SHA256 based Proof-of-Work</strong>
|
2021-03-06 09:48:58 +05:30
|
|
|
</p>
|
|
|
|
|
|
|
|
[![Documentation](https://img.shields.io/badge/docs-master-blue)](https://mcaptcha.github.io/pow_sha256/pow_sha256/index.html)
|
2021-03-07 20:18:35 +05:30
|
|
|
![CI (Linux)](<https://github.com/mCaptcha/pow_sha256/workflows/CI%20(Linux)/badge.svg>)
|
|
|
|
[![dependency status](https://deps.rs/repo/github/mCaptcha/pow_sha256/status.svg)](https://deps.rs/repo/github/mCaptcha/pow_sha256)
|
2021-03-06 09:48:58 +05:30
|
|
|
<br />
|
2021-03-07 20:18:35 +05:30
|
|
|
[![codecov](https://codecov.io/gh/mCaptcha/pow_sha256/branch/master/graph/badge.svg)](https://codecov.io/gh/mCaptcha/pow_sha256)
|
2021-03-06 09:48:58 +05:30
|
|
|
|
|
|
|
</div>
|
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
> pow_sha256's copy of `pow_sha256` by
|
|
|
|
> [robkorn](https://github.com/robkorn/pow_sha256)
|
2021-03-06 09:48:58 +05:30
|
|
|
> which is a modified version of [`pow` library](https://github.com/bddap/pow).
|
|
|
|
> All copyrights belong to the original authors.
|
2020-09-02 11:52:31 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
Rust crate which generates SHA256 Proofs of Work on serializable datatypes.
|
2019-07-23 00:59:16 +05:30
|
|
|
|
2021-03-06 09:48:58 +05:30
|
|
|
Whether for blockchain-related projects or Hashcash-like schemes, this
|
|
|
|
crate can be used to prove work was done on a given serializable input.
|
|
|
|
The input merely needs to implement `serde::Deserialize` to be used.
|
2019-05-11 02:58:06 +05:30
|
|
|
|
2021-03-06 09:48:58 +05:30
|
|
|
This is a fork of the [`pow` library](https://github.com/bddap/pow) by
|
2021-03-06 17:07:28 +05:30
|
|
|
[@robkorn](https://github.com/robkorn/pow_sha256)) with some new
|
|
|
|
additions. Primary of these being:
|
2019-07-23 00:34:45 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
- PoW datatype now offers a constructor
|
|
|
|
- Salt is no longer hard coded into the library, users can provide
|
|
|
|
unique salts.
|
2019-07-23 00:34:45 +05:30
|
|
|
|
2021-03-06 09:48:58 +05:30
|
|
|
Other small changes have also been included of various importance but
|
|
|
|
mostly just stylistic/ease of use improvements.
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
## Examples
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
Prove work specifically targeting a phrase.
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2019-05-13 22:53:00 +05:30
|
|
|
```rust
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
use pow_sha256::{ConfigBuilder, PoW};
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
fn main() {
|
|
|
|
let config = ConfigBuilder::default()
|
|
|
|
.salt("myrandomsaltisnotlongenoug".into())
|
|
|
|
.build()
|
|
|
|
.unwrap();
|
2019-07-23 02:43:00 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
let phrase = "ironmansucks";
|
2019-07-23 02:43:00 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
const DIFFICULTY: u128 = u128::MAX / 32;
|
|
|
|
|
|
|
|
let work = config.prove_work(&phrase, DIFFICULTY).unwrap();
|
|
|
|
assert!(config.calculate(&work, &phrase).unwrap() >= DIFFICULTY);
|
|
|
|
assert!(config.is_valid_proof(&work, &phrase));
|
|
|
|
assert!(config.is_sufficient_difficulty(&work, DIFFICULTY));
|
|
|
|
}
|
2019-05-13 22:40:19 +05:30
|
|
|
```
|
|
|
|
|
|
|
|
Prove more difficult work. This time targeting a time.
|
|
|
|
|
2019-05-13 22:53:00 +05:30
|
|
|
```rust
|
2021-03-06 09:48:58 +05:30
|
|
|
// Greater difficulty this time around. Takes around 100,000 hashes
|
|
|
|
// to find a nonce of the correct difficulty.
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2019-05-17 21:47:27 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
use pow_sha256::{ConfigBuilder, PoW};
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let config = ConfigBuilder::default()
|
|
|
|
.salt("myrandomsaltisnotlongenoug".into())
|
|
|
|
.build()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let phrase = "ironmansucks";
|
2019-05-17 21:47:27 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
const DIFFICULTY: u128 = u128::max_value() - u128::max_value() / 100_000;
|
2019-07-23 02:43:00 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
let work = config.prove_work(&phrase, DIFFICULTY).unwrap();
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
assert!(config.calculate(&work, &phrase).unwrap() >= DIFFICULTY);
|
|
|
|
assert!(config.is_valid_proof(&work, &phrase));
|
|
|
|
assert!(config.is_sufficient_difficulty(&work, DIFFICULTY));
|
|
|
|
}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
## Hashing Scheme
|
|
|
|
|
|
|
|
`SALT` is used as prefix to prevent PoW reuse from other systems such as
|
|
|
|
proof of work blockchains.
|
2019-07-23 03:36:25 +05:30
|
|
|
|
2019-07-23 00:59:16 +05:30
|
|
|
SHA256 is calculated over the concatenation of the:
|
2021-03-06 17:07:28 +05:30
|
|
|
|
2019-07-23 00:59:16 +05:30
|
|
|
- SALT
|
2021-03-06 17:07:28 +05:30
|
|
|
- Serialized Input `T`
|
2019-07-23 00:59:16 +05:30
|
|
|
- Nonce
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2021-03-06 09:48:58 +05:30
|
|
|
The first 16 bytes of the resulting hash are interpreted as a 128 bit
|
|
|
|
unsigned integer and saved as the final result.
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
## Choosing a difficulty setting.
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2021-03-06 09:48:58 +05:30
|
|
|
Depending on your use case, difficulty settings often are best set
|
|
|
|
dynamically a la bitcoin.
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2021-03-06 09:48:58 +05:30
|
|
|
However if your use case requires manual setting then it is trivial to
|
|
|
|
set one yourself. One way to do so is to choose the average number of
|
|
|
|
hashes desired with a function like this:
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2019-05-13 22:53:00 +05:30
|
|
|
```rust
|
2019-07-23 02:43:00 +05:30
|
|
|
fn get_difficulty(average: u128) -> u128 {
|
2019-05-13 22:40:19 +05:30
|
|
|
debug_assert_ne!(average, 0, "It is impossible to prove work in zero attempts.");
|
|
|
|
let m = u128::max_value();
|
|
|
|
m - m / average
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2021-03-06 17:07:28 +05:30
|
|
|
Conversely we can use the same equation to calculate the probable number
|
|
|
|
of hashes required to satisfy a given difficulty:
|
2019-05-13 22:40:19 +05:30
|
|
|
|
2019-05-13 22:53:00 +05:30
|
|
|
```rust
|
2019-07-23 02:43:00 +05:30
|
|
|
fn est_average(difficulty: u128) -> u128 {
|
2019-05-13 22:40:19 +05:30
|
|
|
let m = u128::max_value();
|
|
|
|
if difficulty == m {
|
|
|
|
return m;
|
2021-03-06 17:07:28 +05:30
|
|
|
}
|
2019-05-13 22:40:19 +05:30
|
|
|
m / (m - difficulty)
|
|
|
|
}
|
|
|
|
```
|
2019-07-20 03:06:57 +05:30
|
|
|
|
|
|
|
# License
|
|
|
|
|
2019-07-25 00:11:28 +05:30
|
|
|
This project is dual-licensed under `Apache License Version 2.0` or `MIT license`.
|