diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index d8f9d53..ff54f5a 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -42,7 +42,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: check - args: --all --bins --examples --tests + args: --all --bins --examples --tests --all-features - name: tests uses: actions-rs/cargo@v1 @@ -56,7 +56,7 @@ jobs: uses: actions-rs/tarpaulin@v0.1 with: version: '0.15.0' - args: '-t 1200' + args: '-t 1200 --all-features' - name: Upload to Codecov if: matrix.version == 'stable' && (github.ref == 'refs/heads/master' || github.event_name == 'pull_request') diff --git a/Cargo.toml b/Cargo.toml index a470965..4ed7d2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,7 @@ serde = { version = "1.0", features = ["derive"] } bincode = "1.3" derive_builder = "0.12" num = { version = "0.4.0", default-features = false, features = ["serde", "num-bigint"]} + +[features] +default = [] +incremental = [] diff --git a/Makefile b/Makefile index 78f6ed1..3ac8e7c 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later define test_core - cargo test --no-fail-fast + cargo test --no-fail-fast --all-features endef default: ## Build library in debug mode diff --git a/src/lib.rs b/src/lib.rs index bdd356c..5df5dd6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,19 +50,32 @@ pub struct Config { pub salt: String, } -pub enum SteppedSolve { +/// Return value of incremental prooving. When proof is ready, IncrementalSolve::Work is returned +/// and when proof is not ready, IncrementalSolve::Intermediate is returned +#[cfg(feature = "incremental")] +pub enum IncrementalSolve { + /// Intermediate result Intermediate(u128, u64, Sha256, u128), + /// Final result Work(PoW), } impl Config { + /// + /// step is used to control the number of cycles after which the function should exit, even + /// when the proof isn't ready + /// inter is used to keep track of state and complete proof generation. Set inter to None + /// during first cyle and pass the returned value of the previous cycle to continue proof + /// generation + + #[cfg(feature = "incremental")] pub fn stepped_prove_work( &self, t: &T, difficulty: u32, step: usize, - inter: Option>, - ) -> bincode::Result> + inter: Option>, + ) -> bincode::Result> where T: Serialize, { @@ -70,23 +83,34 @@ impl Config { .map(|v| self.stepped_prove_work_serialized(&v, difficulty, step, inter)) } - /// Create Proof of Work on an already serialized item of type T. + #[cfg(feature = "incremental")] + /// 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 on a general purpose processor. /// 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 on a general purpose processor. - pub fn stepped_prove_work_serialized( + /// step is used to control the number of cycles after which the function should exit, even + /// when the proof isn't ready + /// inter is used to keep track of state and complete proof generation. Set inter to None + /// during first cyle and pass the returned value of the previous cycle to continue proof + /// generation + /// Returns bincode::Error if serialization fails. + /// Create Proof of Work on an already serialized item of type T. + fn stepped_prove_work_serialized( &self, prefix: &[u8], difficulty: u32, step: usize, - inter: Option>, - ) -> SteppedSolve + inter: Option>, + ) -> IncrementalSolve where T: Serialize, { let (mut result, mut n, prefix_sha, difficulty) = match inter { - Some(SteppedSolve::Intermediate(result, nonce, prefix, difficulty)) => { + Some(IncrementalSolve::Intermediate(result, nonce, prefix, difficulty)) => { (result, nonce, prefix, difficulty) } _ => { @@ -98,20 +122,16 @@ impl Config { } }; let mut count = 0; - // let prefix_sha = Sha256::new().chain(&self.salt).chain(prefix); - // let mut n = 0; - // let mut result = 0; - // let difficulty = get_difficulty(difficulty); while result < difficulty { if count > step { - return SteppedSolve::Intermediate(result, n, prefix_sha, difficulty); + return IncrementalSolve::Intermediate(result, n, prefix_sha, difficulty); } else { count += 1; } n += 1; result = dev::score(prefix_sha.clone(), n); } - SteppedSolve::Work(PoW { + IncrementalSolve::Work(PoW { nonce: n, result: result.to_string(), _spook: PhantomData, @@ -331,6 +351,7 @@ mod test { } #[test] + #[cfg(feature = "incremental")] fn stepped_solve() { let phrase = "Ex nihilo nihil fit.".to_owned(); let config = get_config(); @@ -338,15 +359,15 @@ mod test { let mut inter = None; loop { match config.stepped_prove_work(&phrase, 50000, 1000, inter) { - Ok(SteppedSolve::Intermediate(result, nonce, prefix, difficulty)) => { + Ok(IncrementalSolve::Intermediate(result, nonce, prefix, difficulty)) => { println!("Current nonce {nonce}"); - inter = Some(SteppedSolve::Intermediate( + inter = Some(IncrementalSolve::Intermediate( result, nonce, prefix, difficulty, )); continue; } - Ok(SteppedSolve::Work(w)) => { + Ok(IncrementalSolve::Work(w)) => { assert!(config.is_valid_proof(&w, &phrase)); assert!(config.is_sufficient_difficulty(&w, DIFFICULTY)); break;