Updated naming and minor details on several things
This commit is contained in:
parent
c1ec5d2a68
commit
1f1b1ade27
5 changed files with 153 additions and 154 deletions
17
Cargo.toml
17
Cargo.toml
|
@ -1,19 +1,18 @@
|
||||||
[package]
|
[package]
|
||||||
name = "pow"
|
name = "PoW-SHA256"
|
||||||
version = "0.1.5"
|
version = "0.1.0"
|
||||||
authors = ["Andrew Dirksen <andrew@dirksen.com>"]
|
authors = ["Robert Kornacki <robk@syre.io>"]
|
||||||
description = """
|
description = """
|
||||||
Generate or verify sha256 based proofs of work over arbitrary typed data.
|
SHA256 PoW on any serializable datatype.
|
||||||
"""
|
"""
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
documentation = "https://docs.rs/pow"
|
# documentation = "https://docs.rs/PoW"
|
||||||
keywords = ["pwset", "powtag", "tag"]
|
keywords = ["PoW", "sha256", "proof-of-work"]
|
||||||
readme = "readme.md"
|
readme = "readme.md"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
repository = "https://github.com/bddap/pow"
|
repository = "https://github.com/robkorn/pow"
|
||||||
categories = [] # pr me!
|
categories = [] # pr me!
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sha2 = "0.8.0"
|
sha2 = "0.8.0"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
bincode = "1.1.3"
|
bincode = "1.1.4"
|
||||||
|
|
|
@ -15,7 +15,7 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
other entities that control, are controlled by, or are under common
|
other entities that control, are controlled by, or are under common
|
||||||
control with that entity. For the purposes of this definition,
|
control with that entity. For the purposes of this definition,
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
"control" means (i) the PoWer, direct or indirect, to cause the
|
||||||
direction or management of such entity, whether by contract or
|
direction or management of such entity, whether by contract or
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
22
readme.md
22
readme.md
|
@ -1,4 +1,4 @@
|
||||||
# Pow
|
# PoW
|
||||||
|
|
||||||
Sha256 based proof of work over a typed piece of data.
|
Sha256 based proof of work over a typed piece of data.
|
||||||
|
|
||||||
|
@ -9,13 +9,13 @@ Any type that implementes serde::Deserialize can be tagged with a proof of work.
|
||||||
Prove we did work targeting a phrase.
|
Prove we did work targeting a phrase.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use pow::Pow;
|
use PoW::PoW;
|
||||||
|
|
||||||
// very easy mode
|
// very easy mode
|
||||||
let difficulty = u128::max_value() - u128::max_value() / 2;
|
let difficulty = u128::max_value() - u128::max_value() / 2;
|
||||||
|
|
||||||
let phrase = b"Phrase to tag.".to_vec();
|
let phrase = b"Phrase to tag.".to_vec();
|
||||||
let pw = Pow::prove_work(&phrase, difficulty).unwrap();
|
let pw = PoW::prove_work(&phrase, difficulty).unwrap();
|
||||||
assert!(pw.score(&phrase).unwrap() >= difficulty);
|
assert!(pw.score(&phrase).unwrap() >= difficulty);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ Prove more difficult work. This time targeting a time.
|
||||||
let difficulty = u128::max_value() - u128::max_value() / 100_000;
|
let difficulty = u128::max_value() - u128::max_value() / 100_000;
|
||||||
|
|
||||||
let now: u64 = get_unix_time_seconds();
|
let now: u64 = get_unix_time_seconds();
|
||||||
let pw = Pow::prove_work(&now, difficulty).unwrap();
|
let pw = PoW::prove_work(&now, difficulty).unwrap();
|
||||||
assert!(pw.score(&now).unwrap() >= difficulty);
|
assert!(pw.score(&now).unwrap() >= difficulty);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -36,24 +36,24 @@ Define a blockchain block.
|
||||||
struct Block<T> {
|
struct Block<T> {
|
||||||
prev: [u8; 32], // hash of last block
|
prev: [u8; 32], // hash of last block
|
||||||
payload: T, // generic data
|
payload: T, // generic data
|
||||||
proof_of_work: Pow<([u8; 32], T)>,
|
proof_of_work: PoW<([u8; 32], T)>,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
# Score scheme
|
# Score scheme
|
||||||
|
|
||||||
To score a proof of work for a given (target, Pow) pair:
|
To score a proof of work for a given (target, PoW) pair:
|
||||||
Sha256 is calculated over the concatenation SALT + target + Pow.
|
Sha256 is calculated over the concatenation SALT + target + PoW.
|
||||||
The first 16 bytes of the hash are interpreted as a 128 bit unsigned integer.
|
The first 16 bytes of the hash are interpreted as a 128 bit unsigned integer.
|
||||||
That integer is the score.
|
That integer is the score.
|
||||||
A constant, SALT, is used as prefix to prevent pow reuse from other systems such as proof
|
A constant, SALT, is used as prefix to prevent PoW reuse from other systems such as proof
|
||||||
of work blockchains.
|
of work blockchains.
|
||||||
|
|
||||||
In other words:
|
In other words:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn score<T: Serialize>(target: &T, pow_tag: &Pow<T>) -> u128 {
|
fn score<T: Serialize>(target: &T, PoW_tag: &PoW<T>) -> u128 {
|
||||||
let bytes = serialize(&SALT) + serialize(target) + serialize(pow_tag);
|
let bytes = serialize(&SALT) + serialize(target) + serialize(PoW_tag);
|
||||||
let hash = sha256(&bytes);
|
let hash = sha256(&bytes);
|
||||||
deserialize(&hash[..16])
|
deserialize(&hash[..16])
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ deterministic serialization. All values are serialized using network byte order.
|
||||||
|
|
||||||
# Threshold scheme
|
# Threshold scheme
|
||||||
|
|
||||||
Given a minimum score m. A Pow p satisfies the minimum score for target t iff score(t, p) >= m.
|
Given a minimum score m. A PoW p satisfies the minimum score for target t iff score(t, p) >= m.
|
||||||
|
|
||||||
# Choosing a difficulty setting.
|
# Choosing a difficulty setting.
|
||||||
|
|
||||||
|
|
218
src/lib.rs
218
src/lib.rs
|
@ -1,112 +1,112 @@
|
||||||
//! Sha256 based proof of work over a typed piece of data.
|
// Sha256 based proof of work over a typed piece of data.
|
||||||
//!
|
|
||||||
//! Any type that implementes serde::Deserialize can be tagged with a proof of work.
|
// Any type that implementes serde::Deserialize can be tagged with a proof of work.
|
||||||
//!
|
|
||||||
//! # Examples
|
// # Examples
|
||||||
//!
|
|
||||||
//! Prove we did work targeting a phrase.
|
// Prove we did work targeting a phrase.
|
||||||
//!
|
|
||||||
//! ```rust
|
// ```rust
|
||||||
//! use pow::Pow;
|
// use PoW::PoW;
|
||||||
//!
|
|
||||||
//! // very easy mode
|
// // very easy mode
|
||||||
//! let difficulty = u128::max_value() - u128::max_value() / 2;
|
// let difficulty = u128::max_value() - u128::max_value() / 2;
|
||||||
//!
|
|
||||||
//! let phrase = b"Phrase to tag.".to_vec();
|
// let phrase = b"Phrase to tag.".to_vec();
|
||||||
//! let pw = Pow::prove_work(&phrase, difficulty).unwrap();
|
// let pw = PoW::prove_work(&phrase, difficulty).unwrap();
|
||||||
//! assert!(pw.score(&phrase).unwrap() >= difficulty);
|
// assert!(pw.calculate(&phrase).unwrap() >= difficulty);
|
||||||
//! ```
|
// ```
|
||||||
//!
|
|
||||||
//! Prove more difficult work. This time targeting a time.
|
// Prove more difficult work. This time targeting a time.
|
||||||
//!
|
|
||||||
//! ```rust
|
// ```rust
|
||||||
//! # fn get_unix_time_seconds() -> u64 {
|
// # fn get_unix_time_seconds() -> u64 {
|
||||||
//! # use std::time::{Duration, SystemTime};
|
// # use std::time::{Duration, SystemTime};
|
||||||
//! # SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs()
|
// # SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs()
|
||||||
//! # }
|
// # }
|
||||||
//! # use pow::Pow;
|
// # use PoW::PoW;
|
||||||
//!
|
|
||||||
//! // more diffcult, takes around 100_000 hashes to generate proof
|
// // more diffcult, takes around 100_000 hashes to generate proof
|
||||||
//! let difficulty = u128::max_value() - u128::max_value() / 100_000;
|
// let difficulty = u128::max_value() - u128::max_value() / 100_000;
|
||||||
//!
|
|
||||||
//! let now: u64 = get_unix_time_seconds();
|
// let now: u64 = get_unix_time_seconds();
|
||||||
//! let pw = Pow::prove_work(&now, difficulty).unwrap();
|
// let pw = PoW::prove_work(&now, difficulty).unwrap();
|
||||||
//! assert!(pw.score(&now).unwrap() >= difficulty);
|
// assert!(pw.calculate(&now).unwrap() >= difficulty);
|
||||||
//! ```
|
// ```
|
||||||
//!
|
|
||||||
//! Define a blockchain block.
|
// Define a blockchain block.
|
||||||
//!
|
|
||||||
//! ```rust
|
// ```rust
|
||||||
//! # use pow::Pow;
|
// # use PoW::PoW;
|
||||||
//! struct Block<T> {
|
// struct Block<T> {
|
||||||
//! prev: [u8; 32], // hash of last block
|
// prev: [u8; 32], // hash of last block
|
||||||
//! payload: T, // generic data
|
// payload: T, // generic data
|
||||||
//! proof_of_work: Pow<([u8; 32], T)>,
|
// proof_of_work: PoW<([u8; 32], T)>,
|
||||||
//! }
|
// }
|
||||||
//! ```
|
// ```
|
||||||
//!
|
|
||||||
//! # Score scheme
|
// # Score scheme
|
||||||
//!
|
|
||||||
//! To score a proof of work for a given (target, Pow) pair:
|
// To score a proof of work for a given (target, PoW) pair:
|
||||||
//! Sha256 is calculated over the concatenation SALT + target + Pow.
|
// Sha256 is calculated over the concatenation SALT + target + PoW.
|
||||||
//! The first 16 bytes of the hash are interpreted as a 128 bit unsigned integer.
|
// The first 16 bytes of the hash are interpreted as a 128 bit unsigned integer.
|
||||||
//! That integer is the score.
|
// That integer is the score.
|
||||||
//! A constant, SALT, is used as prefix to prevent pow reuse from other systems such as proof
|
// A constant, SALT, is used as prefix to prevent PoW reuse from other systems such as proof
|
||||||
//! of work blockchains.
|
// of work blockchains.
|
||||||
//!
|
|
||||||
//! In other words:
|
// In other words:
|
||||||
//!
|
|
||||||
//! ```rust
|
// ```rust
|
||||||
//! # use serde::Serialize;
|
// # use serde::Serialize;
|
||||||
//! # use pow::Pow;
|
// # use PoW::PoW;
|
||||||
//! # use core::any::Any;
|
// # use core::any::Any;
|
||||||
//! # const SALT: &'static str = "not the actual salt used";
|
// # const SALT: &'static str = "not the actual salt used";
|
||||||
//! # fn serialize<T: Serialize>(_: &T) -> u8 { 0 } // not the actual serialize function
|
// # fn serialize<T: Serialize>(_: &T) -> u8 { 0 } // not the actual serialize function
|
||||||
//! # fn deserialize(_: &[u8]) -> u128 { 0 } // not the actual deserialize function
|
// # fn deserialize(_: &[u8]) -> u128 { 0 } // not the actual deserialize function
|
||||||
//! # fn sha256(_: &u8) -> [u8; 32] { [0; 32] } // not the actual sha256 function
|
// # fn sha256(_: &u8) -> [u8; 32] { [0; 32] } // not the actual sha256 function
|
||||||
//! fn score<T: Serialize>(target: &T, pow_tag: &Pow<T>) -> u128 {
|
// fn score<T: Serialize>(target: &T, PoW_tag: &PoW<T>) -> u128 {
|
||||||
//! let bytes = serialize(&SALT) + serialize(target) + serialize(pow_tag);
|
// let bytes = serialize(&SALT) + serialize(target) + serialize(PoW_tag);
|
||||||
//! let hash = sha256(&bytes);
|
// let hash = sha256(&bytes);
|
||||||
//! deserialize(&hash[..16])
|
// deserialize(&hash[..16])
|
||||||
//! }
|
// }
|
||||||
//! ```
|
// ```
|
||||||
//!
|
|
||||||
//! # 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
|
||||||
//! deterministic serialization. All values are serialized using network byte order.
|
// deterministic serialization. All values are serialized using network byte order.
|
||||||
//!
|
|
||||||
//! # Threshold scheme
|
// # Threshold scheme
|
||||||
//!
|
|
||||||
//! Given a minimum score m. A Pow p satisfies the minimum score for target t iff score(t, p) >= m.
|
// Given a minimum score m. A PoW p satisfies the minimum score for target t iff score(t, p) >= m.
|
||||||
//!
|
|
||||||
//! # Choosing a difficulty setting.
|
// # Choosing a difficulty setting.
|
||||||
//!
|
|
||||||
//! Difficulty settings are usually best adjusted dynamically a la bitcoin.
|
// Difficulty settings are usually best adjusted dynamically a la bitcoin.
|
||||||
//!
|
|
||||||
//! To manually select a difficulty, choose the average number of hashes required.
|
// To manually select a difficulty, choose the average number of hashes required.
|
||||||
//!
|
|
||||||
//! ```rust
|
// ```rust
|
||||||
//! fn difficulty(average: u128) -> u128 {
|
// fn difficulty(average: u128) -> u128 {
|
||||||
//! debug_assert_ne!(average, 0, "It is impossible to prove work in zero attempts.");
|
// debug_assert_ne!(average, 0, "It is impossible to prove work in zero attempts.");
|
||||||
//! let m = u128::max_value();
|
// let m = u128::max_value();
|
||||||
//! m - m / average
|
// m - m / average
|
||||||
//! }
|
// }
|
||||||
//! ```
|
// ```
|
||||||
//!
|
|
||||||
//! Conversely, to calculate probable number of hashes required to satisfy a given minimum
|
// Conversely, to calculate probable number of hashes required to satisfy a given minimum
|
||||||
//! difficulty.
|
// difficulty.
|
||||||
//!
|
|
||||||
//! ```rust
|
// ```rust
|
||||||
//! fn average(difficulty: u128) -> u128 {
|
// fn average(difficulty: u128) -> u128 {
|
||||||
//! let m = u128::max_value();
|
// let m = u128::max_value();
|
||||||
//! if difficulty == m {
|
// if difficulty == m {
|
||||||
//! return m;
|
// return m;
|
||||||
//! }
|
// }
|
||||||
//! m / (m - difficulty)
|
// m / (m - difficulty)
|
||||||
//! }
|
// }
|
||||||
//! ```
|
// ```
|
||||||
|
|
||||||
mod proof_of_work;
|
mod proof_of_work;
|
||||||
|
|
||||||
pub use proof_of_work::Pow;
|
pub use proof_of_work::PoW;
|
||||||
|
|
|
@ -4,37 +4,37 @@ use std::marker::PhantomData;
|
||||||
|
|
||||||
const SALT: &str = "79ziepia7vhjgviiwjhnend3ofjqocsi2winc4ptqhmkvcajihywxcizewvckg9h6gs4j83v9";
|
const SALT: &str = "79ziepia7vhjgviiwjhnend3ofjqocsi2winc4ptqhmkvcajihywxcizewvckg9h6gs4j83v9";
|
||||||
|
|
||||||
/// Proof of work over concrete type T. T can be any type that implements serde::Serialize.
|
/// Proof of Work over concrete type T. T can be any type that implements serde::Serialize.
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Clone, Copy, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Clone, Copy, Debug)]
|
||||||
pub struct Pow<T> {
|
pub struct PoW<T> {
|
||||||
nonce: u128,
|
nonce: u128,
|
||||||
result: u128,
|
result: u128,
|
||||||
_spook: PhantomData<T>,
|
_spook: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// prove_work and score could theoretically be without allocations, by serializing to a Write
|
// prove_work and calculate could theoretically be without allocations, by serializing to a Write
|
||||||
// implementaion that performs sha256 lazily.
|
// implementaion that performs sha256 lazily.
|
||||||
// `impl io::Write for sha2::Sha256 { ... }`
|
// `impl io::Write for sha2::Sha256 { ... }`
|
||||||
|
|
||||||
impl<T: Serialize> Pow<T> {
|
impl<T: Serialize> PoW<T> {
|
||||||
/// Prove work over T.
|
/// Create Proof of Work over item of type T.
|
||||||
///
|
///
|
||||||
/// Make sure difficulty is not too high. A 64 bit difficulty, for example, takes a long time
|
/// Make sure difficulty is not too high. A 64 bit difficulty, for example, takes a long time
|
||||||
/// on a general purpose processor.
|
/// on a general purpose processor.
|
||||||
///
|
///
|
||||||
/// Returns bincode::Error if serialization fails.
|
/// Returns bincode::Error if serialization fails.
|
||||||
pub fn prove_work(t: &T, difficulty: u128) -> bincode::Result<Pow<T>> {
|
pub fn prove_work(t: &T, difficulty: u128) -> bincode::Result<PoW<T>> {
|
||||||
bincode_cfg()
|
bincode_cfg()
|
||||||
.serialize(t)
|
.serialize(t)
|
||||||
.map(|v| Self::prove_work_serialized(&v, difficulty))
|
.map(|v| Self::prove_work_serialized(&v, difficulty))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prove work on an already serialized item of type T.
|
/// Create Proof of Work on an already serialized item of type T.
|
||||||
/// The input is assumed to be serialized using network byte order.
|
/// The input is assumed to be serialized using network byte order.
|
||||||
///
|
///
|
||||||
/// Make sure difficulty is not too high. A 64 bit difficulty, for example, takes a long time
|
/// Make sure difficulty is not too high. A 64 bit difficulty, for example, takes a long time
|
||||||
/// on a general purpose processor.
|
/// on a general purpose processor.
|
||||||
pub fn prove_work_serialized(prefix: &[u8], difficulty: u128) -> Pow<T> {
|
pub fn prove_work_serialized(prefix: &[u8], difficulty: u128) -> PoW<T> {
|
||||||
let prefix_sha = Sha256::new().chain(SALT).chain(prefix);
|
let prefix_sha = Sha256::new().chain(SALT).chain(prefix);
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
let mut result = 0;
|
let mut result = 0;
|
||||||
|
@ -42,23 +42,23 @@ impl<T: Serialize> Pow<T> {
|
||||||
n += 1;
|
n += 1;
|
||||||
result = score(prefix_sha.clone(), n);
|
result = score(prefix_sha.clone(), n);
|
||||||
}
|
}
|
||||||
Pow {
|
PoW {
|
||||||
nonce: n,
|
nonce: n,
|
||||||
result: result,
|
result: result,
|
||||||
_spook: PhantomData,
|
_spook: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the pow score of t and self.
|
/// Calculate the PoW score of t and self.
|
||||||
pub fn score(&self, t: &T) -> bincode::Result<u128> {
|
pub fn calculate(&self, t: &T) -> bincode::Result<u128> {
|
||||||
bincode_cfg()
|
bincode_cfg()
|
||||||
.serialize(t)
|
.serialize(t)
|
||||||
.map(|v| self.score_serialized(&v))
|
.map(|v| self.calculate_serialized(&v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the pow score of an already serialized T and self.
|
/// Calculate the PoW score of an already serialized T and self.
|
||||||
/// The input is assumed to be serialized using network byte order.
|
/// The input is assumed to be serialized using network byte order.
|
||||||
pub fn score_serialized(&self, target: &[u8]) -> u128 {
|
pub fn calculate_serialized(&self, target: &[u8]) -> u128 {
|
||||||
score(Sha256::new().chain(SALT).chain(target), self.nonce)
|
score(Sha256::new().chain(SALT).chain(target), self.nonce)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,27 +95,27 @@ mod test {
|
||||||
fn base_functionality() {
|
fn base_functionality() {
|
||||||
// Let's prove we did work targeting a phrase.
|
// Let's prove we did work targeting a phrase.
|
||||||
let phrase = b"Corver bandar palladianism retroform.".to_vec();
|
let phrase = b"Corver bandar palladianism retroform.".to_vec();
|
||||||
let pw = Pow::prove_work(&phrase, DIFFICULTY).unwrap();
|
let pw = PoW::prove_work(&phrase, DIFFICULTY).unwrap();
|
||||||
assert!(pw.score(&phrase).unwrap() >= DIFFICULTY);
|
assert!(pw.calculate(&phrase).unwrap() >= DIFFICULTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn double_pow() {
|
fn double_pow() {
|
||||||
let phrase = "Corver bandar palladianism retroform.".to_owned();
|
let phrase = "Corver bandar palladianism retroform.".to_owned();
|
||||||
let pow = Pow::prove_work(&phrase, DIFFICULTY).unwrap();
|
let PoW = PoW::prove_work(&phrase, DIFFICULTY).unwrap();
|
||||||
let powpow: Pow<Pow<String>> = Pow::prove_work(&pow, DIFFICULTY).unwrap();
|
let PoWPoW: PoW<PoW<String>> = PoW::prove_work(&PoW, DIFFICULTY).unwrap();
|
||||||
assert!(pow.score(&phrase).unwrap() >= DIFFICULTY);
|
assert!(PoW.calculate(&phrase).unwrap() >= DIFFICULTY);
|
||||||
assert!(powpow.score(&pow).unwrap() >= DIFFICULTY);
|
assert!(PoWPoW.calculate(&PoW).unwrap() >= DIFFICULTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ser_de() {
|
fn ser_de() {
|
||||||
let target: u8 = 1;
|
let target: u8 = 1;
|
||||||
let pw = Pow::prove_work(&target, DIFFICULTY).unwrap();
|
let pw = PoW::prove_work(&target, DIFFICULTY).unwrap();
|
||||||
let message: (u8, Pow<u8>) = (target, pw);
|
let message: (u8, PoW<u8>) = (target, pw);
|
||||||
let message_ser = bincode_cfg().serialize(&message).unwrap();
|
let message_ser = bincode_cfg().serialize(&message).unwrap();
|
||||||
let recieved_message: (u8, Pow<u8>) = bincode_cfg().deserialize(&message_ser).unwrap();
|
let recieved_message: (u8, PoW<u8>) = bincode_cfg().deserialize(&message_ser).unwrap();
|
||||||
assert_eq!(recieved_message, message);
|
assert_eq!(recieved_message, message);
|
||||||
assert!(message.1.score(&message.0).unwrap() >= DIFFICULTY);
|
assert!(message.1.calculate(&message.0).unwrap() >= DIFFICULTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue