Copy docs to readme, link to repo from Cargo.toml.
https://www.reddit.com/r/rust/comments/bn48nz/pow_sha256_based_proofs_of_work_over_typed_data/en2bcxx?utm_source=share&utm_medium=web2x
This commit is contained in:
parent
86a7d9bfcb
commit
cd7b218e51
3 changed files with 88 additions and 5 deletions
|
@ -1,15 +1,17 @@
|
||||||
[package]
|
[package]
|
||||||
name = "pow"
|
name = "pow"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
authors = ["Andrew Dirksen <andrew@dirksen.com>"]
|
authors = ["Andrew Dirksen <andrew@dirksen.com>"]
|
||||||
description = """
|
description = """
|
||||||
Generate or verify sha256 based proofs of work over arbitrary typed data.
|
Generate or verify sha256 based proofs of work over arbitrary typed data.
|
||||||
"""
|
"""
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
documentation = "https://docs.rs/pow"
|
documentation = "https://docs.rs/pow"
|
||||||
tags = ["proof of work", "pw set", "powtag", "tag"]
|
keywords = ["pwset", "powtag", "tag"]
|
||||||
readme = "readme.md"
|
readme = "readme.md"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/bddap/pow"
|
||||||
|
categories = [] # pr me!
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sha2 = "0.8.0"
|
sha2 = "0.8.0"
|
||||||
|
|
85
readme.md
85
readme.md
|
@ -1,5 +1,86 @@
|
||||||
# Pow
|
# Pow
|
||||||
|
|
||||||
Typed proof of work tags.
|
Sha256 based proof of work over a typed piece of data.
|
||||||
|
|
||||||
[docs](https://docs.rs/pow)
|
Any type that implementes serde::Deserialize can be tagged with a proof of work.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
Prove we did work targeting a phrase.
|
||||||
|
|
||||||
|
```
|
||||||
|
use pow::Pow;
|
||||||
|
|
||||||
|
// very easy mode
|
||||||
|
let difficulty = u128::max_value() - u128::max_value() / 2;
|
||||||
|
|
||||||
|
let phrase = b"Phrase to tag.".to_vec();
|
||||||
|
let pw = Pow::prove_work(&phrase, difficulty).unwrap();
|
||||||
|
assert!(pw.score(&phrase).unwrap() >= difficulty);
|
||||||
|
```
|
||||||
|
|
||||||
|
Prove more difficult work. This time targeting a time.
|
||||||
|
|
||||||
|
```
|
||||||
|
// more diffcult, takes around 100_000 hashes to generate proof
|
||||||
|
let difficulty = u128::max_value() - u128::max_value() / 100_000;
|
||||||
|
|
||||||
|
let now: u64 = get_unix_time_seconds();
|
||||||
|
let pw = Pow::prove_work(&now, difficulty).unwrap();
|
||||||
|
assert!(pw.score(&now).unwrap() >= difficulty);
|
||||||
|
```
|
||||||
|
|
||||||
|
# Score scheme
|
||||||
|
|
||||||
|
To score a proof of work for a given (target, Pow) pair:
|
||||||
|
Sha256 is calculated over the concatenation SALT + target + Pow.
|
||||||
|
The first 16 bytes of the hash are interpreted as a 128 bit unsigned integer.
|
||||||
|
That integer is the score.
|
||||||
|
A constant, SALT, is used as prefix to prevent pow reuse from other systems such as proof
|
||||||
|
of work blockchains.
|
||||||
|
|
||||||
|
In other words:
|
||||||
|
|
||||||
|
```
|
||||||
|
fn score<T: Serialize>(target: &T, pow_tag: &Pow<T>) -> u128 {
|
||||||
|
let bytes = serialize(&SALT) + serialize(target) + serialize(pow_tag);
|
||||||
|
let hash = sha256(&bytes);
|
||||||
|
deserialize(&hash[..16])
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Serialization encoding.
|
||||||
|
|
||||||
|
It shouldn't matter to users of this library, but the bincode crate is used for cheap
|
||||||
|
deterministic serialization. All values are serialized using network byte order.
|
||||||
|
|
||||||
|
# Threshold scheme
|
||||||
|
|
||||||
|
Given a minimum score m. A Pow p satisfies the minimum score for target t iff score(t, p) >= m.
|
||||||
|
|
||||||
|
# Choosing a difficulty setting.
|
||||||
|
|
||||||
|
Difficulty settings are usually best adjusted dynamically a la bitcoin.
|
||||||
|
|
||||||
|
To manually select a difficulty, choose the average number of hashes required.
|
||||||
|
|
||||||
|
```
|
||||||
|
fn difficulty(average: u128) -> u128 {
|
||||||
|
debug_assert_ne!(average, 0, "It is impossible to prove work in zero attempts.");
|
||||||
|
let m = u128::max_value();
|
||||||
|
m - m / average
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Conversely, to calculate probable number of hashes required to satisfy a given minimum
|
||||||
|
difficulty.
|
||||||
|
|
||||||
|
```
|
||||||
|
fn average(difficulty: u128) -> u128 {
|
||||||
|
let m = u128::max_value();
|
||||||
|
if difficulty == m {
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
m / (m - difficulty)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
//! # Serialization encoding.
|
//! # Serialization encoding.
|
||||||
//!
|
//!
|
||||||
//! It shouldn't matter to users of this library, but the bincode crate is used for cheap
|
//! It shouldn't matter to users of this library, but the bincode crate is used for cheap
|
||||||
//! derterministic serialization. All values are serialized using network byte order.
|
//! deterministic serialization. All values are serialized using network byte order.
|
||||||
//!
|
//!
|
||||||
//! # Threshold scheme
|
//! # Threshold scheme
|
||||||
//!
|
//!
|
||||||
|
|
Loading…
Reference in a new issue