#tags #pwset #powtag

pow

生成或验证基于任意类型数据的 sha256 工作证明

7 个版本

0.2.0 2019年12月6日
0.1.5 2019年5月17日

#1025 in 编码

每月 22 次下载

MIT/Apache

13KB
92

Pow

基于类型数据的 sha256 工作证明。

任何实现了 serde::Deserialize 的类型都可以被标记为工作证明。

示例

证明我们对一个短语进行了工作。

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);

证明更困难的工作。这次针对时间。

// 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);

定义一个区块链区块。

struct Block<T> {
    prev: [u8; 32], // hash of last block
    payload: T,     // generic data
    proof_of_work: Pow<([u8; 32], T)>,
}

评分方案

为了给给定的(目标,Pow)对评分:对 SALT + 目标 + Pow 的连接进行 Sha256 计算。哈希的前 16 个字节被解释为 128 位无符号整数。该整数是分数。使用一个常数 SALT 作为前缀,以防止工作证明在其他系统(如工作量证明区块链)中的重复使用。

换句话说

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])
}

序列化编码。

对于此库的用户来说,这不是很重要,但 bincode crate 用于廉价的确定序列化。所有值都使用网络字节顺序进行序列化。

阈值方案

给定一个最小分数 m。如果 score(t, p) >= m,则 Pow p 满足目标 t 的最小分数。

选择难度设置。

难度设置通常最好像比特币一样动态调整。

要手动选择难度,选择所需的平均哈希数量。

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
}

相反,要计算满足给定最小难度的可能哈希数量。

fn average(difficulty: u128) -> u128 {
    let m = u128::max_value();
    if difficulty == m {
        return m;
    } 
    m / (m - difficulty)
}

许可证

本项目可根据您的选择,在 Apache License,Version 2.0 或 MIT 许可证下许可。

依赖项

~1.1–1.8MB
~40K SLoC