From d2a73beb43c68b8cf43ddf7edc9ff17f05372a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 26 Oct 2023 12:22:51 +0200 Subject: [PATCH 1/5] Add mode for watching PID and exit if it dies --- Cargo.lock | 25 +++++++++++++++ service/Cargo.toml | 1 + service/src/main.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 49dfcc3d..f14171b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1535,6 +1535,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + [[package]] name = "num-complex" version = "0.4.4" @@ -2503,6 +2512,7 @@ dependencies = [ "prost", "rcgen", "rstest 0.18.2", + "sysinfo", "tempfile", "tokio", "tokio-stream", @@ -2638,6 +2648,21 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sysinfo" +version = "0.29.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a18d114d420ada3a891e6bc8e96a2023402203296a47cdd65083377dad18ba5" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "winapi", +] + [[package]] name = "tap" version = "1.0.1" diff --git a/service/Cargo.toml b/service/Cargo.toml index 6bbbd05d..b36b568a 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -25,6 +25,7 @@ env_logger = "0.10.0" clap = { version = "4.4.4", features = ["derive"] } hex = "0.4.3" mockall = "0.11.4" +sysinfo = "0.29.10" [build-dependencies] tonic-build = "0.10.0" diff --git a/service/src/main.rs b/service/src/main.rs index 75cf63ac..b9ceca3a 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -2,6 +2,7 @@ use std::{fs::read_to_string, path::PathBuf, time::Duration}; use clap::{Args, Parser, ValueEnum}; use eyre::Context; +use sysinfo::{Pid, ProcessExt, ProcessStatus, System, SystemExt}; use tonic::transport::{Certificate, Identity}; use post::pow::randomx::RandomXFlag; @@ -29,6 +30,10 @@ struct Cli { #[command(flatten, next_help_heading = "TLS configuration")] tls: Option, + + /// watch PID and exit if it dies + #[arg(long)] + watch_pid: Option, } #[derive(Args, Debug)] @@ -200,6 +205,73 @@ async fn main() -> eyre::Result<()> { }; let client = client::ServiceClient::new(args.address, args.reconnect_interval_s, tls, service)?; + let client_handle = tokio::spawn(client.run()); + + if let Some(pid) = args.watch_pid { + tokio::task::spawn_blocking(move || watch_pid(pid, Duration::from_secs(1))).await?; + Ok(()) + } else { + client_handle.await? + } +} + +// watch given PID and return when it dies +fn watch_pid(pid: Pid, interval: Duration) { + log::info!("watching PID {pid}"); + + let mut sys = System::new(); + while sys.refresh_process(pid) { + if let Some(p) = sys.process(pid) { + match p.status() { + ProcessStatus::Zombie | ProcessStatus::Dead => { + break; + } + _ => {} + } + } + std::thread::sleep(interval); + } - client.run().await + log::info!("PID {pid} died"); +} + +#[cfg(test)] +mod tests { + use std::process::Command; + + use sysinfo::PidExt; + + #[tokio::test] + async fn watching_pid_zombie() { + let mut proc = Command::new("sleep").arg("99999").spawn().unwrap(); + let pid = proc.id(); + + let handle = tokio::task::spawn_blocking(move || { + super::watch_pid( + sysinfo::Pid::from_u32(pid), + std::time::Duration::from_millis(10), + ) + }); + // just kill leaves a zombie process + proc.kill().unwrap(); + handle.await.unwrap(); + } + + #[tokio::test] + async fn watching_pid_reaped() { + let mut proc = Command::new("sleep").arg("99999").spawn().unwrap(); + let pid = proc.id(); + + let handle = tokio::task::spawn_blocking(move || { + super::watch_pid( + sysinfo::Pid::from_u32(pid), + std::time::Duration::from_millis(10), + ) + }); + + // kill and wait + proc.kill().unwrap(); + proc.wait().unwrap(); + handle.await.unwrap(); + } } From ee5bb4fb2ba350a90f0e57851bad6b34e7d5f930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 26 Oct 2023 15:55:19 +0200 Subject: [PATCH 2/5] Release v0.5.2 --- Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- ffi/Cargo.toml | 2 +- initializer/Cargo.toml | 2 +- profiler/Cargo.toml | 2 +- scrypt-ocl/Cargo.toml | 2 +- service/Cargo.toml | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f14171b8..aba687ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1294,7 +1294,7 @@ dependencies = [ [[package]] name = "initializer" -version = "0.5.1" +version = "0.5.2" dependencies = [ "base64 0.21.3", "clap 4.4.4", @@ -1801,7 +1801,7 @@ dependencies = [ [[package]] name = "post-cbindings" -version = "0.5.1" +version = "0.5.2" dependencies = [ "cbindgen", "log", @@ -1812,7 +1812,7 @@ dependencies = [ [[package]] name = "post-rs" -version = "0.5.1" +version = "0.5.2" dependencies = [ "aes", "bitvec", @@ -1941,7 +1941,7 @@ dependencies = [ [[package]] name = "profiler" -version = "0.5.1" +version = "0.5.2" dependencies = [ "clap 4.4.4", "env_logger", @@ -2412,7 +2412,7 @@ dependencies = [ [[package]] name = "scrypt-ocl" -version = "0.5.1" +version = "0.5.2" dependencies = [ "log", "ocl", @@ -2499,7 +2499,7 @@ dependencies = [ [[package]] name = "service" -version = "0.5.1" +version = "0.5.2" dependencies = [ "async-stream", "clap 4.4.4", diff --git a/Cargo.toml b/Cargo.toml index b6933c9b..a7fd192c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [".", "ffi", "scrypt-ocl", "initializer", "profiler", "service"] [package] name = "post-rs" -version = "0.5.1" +version = "0.5.2" edition = "2021" [lib] diff --git a/ffi/Cargo.toml b/ffi/Cargo.toml index 0021a0b1..66f3fd38 100644 --- a/ffi/Cargo.toml +++ b/ffi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "post-cbindings" -version = "0.5.1" +version = "0.5.2" edition = "2021" diff --git a/initializer/Cargo.toml b/initializer/Cargo.toml index f78f395f..8d6015b2 100644 --- a/initializer/Cargo.toml +++ b/initializer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "initializer" -version = "0.5.1" +version = "0.5.2" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/profiler/Cargo.toml b/profiler/Cargo.toml index c1503917..cd837fff 100644 --- a/profiler/Cargo.toml +++ b/profiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profiler" -version = "0.5.1" +version = "0.5.2" edition = "2021" [dependencies] diff --git a/scrypt-ocl/Cargo.toml b/scrypt-ocl/Cargo.toml index 8acb9e74..f7951cc7 100644 --- a/scrypt-ocl/Cargo.toml +++ b/scrypt-ocl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scrypt-ocl" -version = "0.5.1" +version = "0.5.2" edition = "2021" [dependencies] diff --git a/service/Cargo.toml b/service/Cargo.toml index b36b568a..67c57f0e 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "service" -version = "0.5.1" +version = "0.5.2" edition = "2021" [lib] From 3cf5917342b502545550798b4b72e9304f2f02bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Thu, 2 Nov 2023 11:40:09 +0100 Subject: [PATCH 3/5] Use N,R,P scrypt params instead of factors in config --- benches/verifying.rs | 5 ++--- ffi/src/initialization.rs | 16 ++++++---------- ffi/src/post_impl.rs | 16 +++++++++------- initializer/src/main.rs | 10 +++------- scrypt-ocl/src/lib.rs | 14 +++++++------- service/src/main.rs | 8 ++++---- service/tests/test_client.rs | 2 +- service/tests/test_service.rs | 8 ++++---- src/config.rs | 30 +++++++++++++++++++++++++++++- src/initialize.rs | 16 ++++++++-------- src/lib.rs | 3 --- src/pos_verification.rs | 2 +- src/prove.rs | 11 ++++++----- src/verification.rs | 16 ++++++++-------- tests/generate_and_verify.rs | 6 +++--- tests/initialize_and_verify.rs | 7 ++++--- 16 files changed, 95 insertions(+), 75 deletions(-) diff --git a/benches/verifying.rs b/benches/verifying.rs index 9b690dc2..22a6f97f 100644 --- a/benches/verifying.rs +++ b/benches/verifying.rs @@ -1,5 +1,6 @@ use criterion::{criterion_group, criterion_main, Criterion}; use post::{ + config::ScryptParams, metadata::ProofMetadata, pow::randomx::{PoW, RandomXFlag}, prove::Proof, @@ -8,8 +9,6 @@ use post::{ #[cfg(not(windows))] use pprof::criterion::{Output, PProfProfiler}; -use scrypt_jane::scrypt::ScryptParams; - fn verifying(c: &mut Criterion) { let challenge = b"hello world, challenge me!!!!!!!"; let metadata = ProofMetadata { @@ -37,7 +36,7 @@ fn verifying(c: &mut Criterion) { k2, k3, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(12, 0, 0), + scrypt: ScryptParams::new(8192, 1, 1), }; c.bench_function("verify", |b| { diff --git a/ffi/src/initialization.rs b/ffi/src/initialization.rs index 7d9c99ec..3b2b2853 100644 --- a/ffi/src/initialization.rs +++ b/ffi/src/initialization.rs @@ -1,9 +1,9 @@ use std::{error::Error, ffi::c_char, fmt::Debug}; use post::{ + config::ScryptParams, initialize::{CpuInitializer, Initialize}, pos_verification::VerificationError, - ScryptParams, }; use scrypt_ocl::{ocl::DeviceType, OpenClInitializer, ProviderId}; @@ -186,11 +186,7 @@ fn _new_initializer( }; let instance: Box = match provider_id { - CPU_PROVIDER_ID => Box::new(CpuInitializer::new(ScryptParams::new( - n.ilog2() as u8 - 1, - 0, - 0, - ))), + CPU_PROVIDER_ID => Box::new(CpuInitializer::new(ScryptParams::new(n, 1, 1))), id => Box::new(OpenClInitializer::new( Some(ProviderId(id)), n, @@ -260,8 +256,8 @@ mod tests { }; use post::{ + config::ScryptParams, initialize::{CpuInitializer, Initialize, MockInitialize}, - ScryptParams, }; use tempfile::tempdir; @@ -299,7 +295,7 @@ mod tests { let mut expected = Vec::::with_capacity(indices.clone().count()); - CpuInitializer::new(ScryptParams::new(4, 0, 0)) + CpuInitializer::new(ScryptParams::new(32, 1, 1)) .initialize_to( &mut expected, &[0u8; 32], @@ -426,7 +422,7 @@ mod tests { k2: 32, k3: 10, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(0, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; CpuInitializer::new(cfg.scrypt) @@ -439,7 +435,7 @@ mod tests { assert_eq!(VerifyResult::Ok, result); // verify with wrong scrypt params - let wrong_scrypt = ScryptParams::new(2, 0, 0); + let wrong_scrypt = ScryptParams::new(4, 1, 1); let result = verify_pos(datapath.as_ptr(), null(), null(), 100.0, wrong_scrypt); assert_eq!(VerifyResult::Invalid, result); diff --git a/ffi/src/post_impl.rs b/ffi/src/post_impl.rs index 0dc4ca0b..f6d461c5 100644 --- a/ffi/src/post_impl.rs +++ b/ffi/src/post_impl.rs @@ -8,10 +8,9 @@ use std::{ sync::atomic::AtomicBool, }; -pub use post::config::Config; -pub use post::metadata::ProofMetadata; -pub use post::ScryptParams; use post::{ + config::Config, + metadata::ProofMetadata, pow::randomx::{PoW, RandomXFlag}, prove, verification::{Verifier, VerifyingParams}, @@ -208,7 +207,10 @@ pub unsafe extern "C" fn verify_proof( #[cfg(test)] mod tests { - use post::{initialize::Initialize, metadata::ProofMetadata, pow::randomx::RandomXFlag}; + use post::{ + config::ScryptParams, initialize::Initialize, metadata::ProofMetadata, + pow::randomx::RandomXFlag, + }; #[test] fn datadir_must_be_utf8() { @@ -218,7 +220,7 @@ mod tests { k2: 20, k3: 20, pow_difficulty: [0xFF; 32], - scrypt: super::ScryptParams::new(1, 1, 1), + scrypt: ScryptParams::new(2, 1, 1), }; let result = super::_generate_proof( datadir.as_ptr(), @@ -256,7 +258,7 @@ mod tests { k2: 2, k3: 2, pow_difficulty: [0xFF; 32], - scrypt: super::ScryptParams::new(1, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }, ) }; @@ -278,7 +280,7 @@ mod tests { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ], - scrypt: post::ScryptParams::new(0, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; let meta = post::initialize::CpuInitializer::new(cfg.scrypt) diff --git a/initializer/src/main.rs b/initializer/src/main.rs index f9fe615f..7dc19423 100644 --- a/initializer/src/main.rs +++ b/initializer/src/main.rs @@ -9,8 +9,8 @@ use base64::{engine::general_purpose, Engine}; use clap::{Args, Parser, Subcommand, ValueEnum}; use eyre::Context; use post::{ + config::ScryptParams, initialize::{CpuInitializer, Initialize, LABEL_SIZE}, - ScryptParams, }; use rand::seq::IteratorRandom; use rayon::prelude::{ParallelBridge, ParallelIterator}; @@ -128,7 +128,7 @@ fn verify_data(args: VerifyData) -> eyre::Result<()> { let input_file_size = input_file.metadata()?.len(); let labels_in_file = input_file_size / 16; let labels_to_verify = (labels_in_file as f64 * (args.fraction / 100.0)) as usize; - let scrypt_params = ScryptParams::new(args.n.ilog2() as u8 - 1, 0, 0); + let scrypt_params = ScryptParams::new(args.n, 1, 1); let mut rng = rand::thread_rng(); (0..labels_in_file) @@ -171,11 +171,7 @@ fn initialize(args: InitializeArgs) -> eyre::Result<()> { eyre::ensure!(args.n.is_power_of_two(), "scrypt N must be a power of two"); let mut initializer: Box = match args.method { - InitializationMethod::Cpu => Box::new(CpuInitializer::new(ScryptParams::new( - args.n.ilog2() as u8 - 1, - 0, - 0, - ))), + InitializationMethod::Cpu => Box::new(CpuInitializer::new(ScryptParams::new(args.n, 1, 1))), InitializationMethod::Gpu => Box::new(OpenClInitializer::new( args.provider.map(ProviderId), args.n, diff --git a/scrypt-ocl/src/lib.rs b/scrypt-ocl/src/lib.rs index a3e84442..ef3dc8e2 100644 --- a/scrypt-ocl/src/lib.rs +++ b/scrypt-ocl/src/lib.rs @@ -356,8 +356,8 @@ impl Initialize for OpenClInitializer { #[cfg(test)] mod tests { use post::{ + config::ScryptParams, initialize::{CpuInitializer, Initialize}, - ScryptParams, }; use rstest::rstest; @@ -386,7 +386,7 @@ mod tests { .unwrap(); let mut expected = Vec::with_capacity(1); - CpuInitializer::new(ScryptParams::new(12, 0, 0)) + CpuInitializer::new(ScryptParams::new(8192, 1, 1)) .initialize_to(&mut expected, &[0u8; 32], 0..1, None) .unwrap(); @@ -411,7 +411,7 @@ mod tests { let mut expected = Vec::::with_capacity(usize::try_from(indices.end - indices.start).unwrap()); - CpuInitializer::new(ScryptParams::new(n.ilog2() as u8 - 1, 0, 0)) + CpuInitializer::new(ScryptParams::new(n, 1, 1)) .initialize_to(&mut expected, &[0u8; 32], indices, None) .unwrap(); @@ -436,7 +436,7 @@ mod tests { let mut expected = Vec::::with_capacity(usize::try_from(indices.end - indices.start).unwrap()); - CpuInitializer::new(ScryptParams::new(n.ilog2() as u8 - 1, 0, 0)) + CpuInitializer::new(ScryptParams::new(n, 1, 1)) .initialize_to(&mut expected, &[0u8; 32], indices, None) .unwrap(); @@ -457,7 +457,7 @@ mod tests { let mut expected = Vec::::with_capacity(usize::try_from(indices.end - indices.start).unwrap()); - CpuInitializer::new(ScryptParams::new(12, 0, 0)) + CpuInitializer::new(ScryptParams::new(8192, 1, 1)) .initialize_to(&mut expected, commitment, indices, None) .unwrap(); @@ -485,7 +485,7 @@ mod tests { let nonce = opencl_nonce.expect("vrf nonce not found"); let mut label = Vec::::with_capacity(LABEL_SIZE); - let mut cpu_initializer = CpuInitializer::new(ScryptParams::new(n.ilog2() as u8 - 1, 0, 0)); + let mut cpu_initializer = CpuInitializer::new(ScryptParams::new(n, 1, 1)); cpu_initializer .initialize_to(&mut label, commitment, nonce.index..nonce.index + 1, None) .unwrap(); @@ -525,7 +525,7 @@ mod tests { let mut expected = Vec::::with_capacity(usize::try_from(indices.end - indices.start).unwrap()); - CpuInitializer::new(ScryptParams::new(N.ilog2() as u8 - 1, 0, 0)) + CpuInitializer::new(ScryptParams::new(N, 1, 1)) .initialize_to(&mut expected, &[0u8; 32], indices, None) .unwrap(); diff --git a/service/src/main.rs b/service/src/main.rs index b9ceca3a..c514f8be 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -171,10 +171,10 @@ async fn main() -> eyre::Result<()> { k2: args.post_config.k2, k3: args.post_config.k3, pow_difficulty: args.post_config.pow_difficulty, - scrypt: post::ScryptParams::new( - args.post_config.scrypt.n.ilog2() as u8 - 1, - args.post_config.scrypt.r.ilog2() as u8, - args.post_config.scrypt.p.ilog2() as u8, + scrypt: post::config::ScryptParams::new( + args.post_config.scrypt.n, + args.post_config.scrypt.r, + args.post_config.scrypt.p, ), }, args.post_settings.nonces, diff --git a/service/tests/test_client.rs b/service/tests/test_client.rs index 29339c2f..80a1fdc4 100644 --- a/service/tests/test_client.rs +++ b/service/tests/test_client.rs @@ -229,7 +229,7 @@ async fn test_get_metadata(#[case] vrf_difficulty: Option<[u8; 32]>) { k2: 32, k3: 10, pow_difficulty: [0xFF; 32], - scrypt: post::ScryptParams::new(0, 0, 0), + scrypt: post::config::ScryptParams::new(2, 1, 1), }; let metadata = CpuInitializer::new(cfg.scrypt) diff --git a/service/tests/test_service.rs b/service/tests/test_service.rs index c479a5bf..60ad31aa 100644 --- a/service/tests/test_service.rs +++ b/service/tests/test_service.rs @@ -1,10 +1,10 @@ use std::{thread::sleep, time::Duration}; use post::{ + config::ScryptParams, initialize::{CpuInitializer, Initialize}, metadata::ProofMetadata, pow::randomx::RandomXFlag, - ScryptParams, }; use post_service::{client::PostService, service::ProofGenState}; @@ -19,7 +19,7 @@ fn test_generate_and_verify() { k2: 4, k3: 4, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(0, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; let metadata = CpuInitializer::new(cfg.scrypt) @@ -65,7 +65,7 @@ fn reject_invalid_challenge() { k2: 4, k3: 4, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(0, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; CpuInitializer::new(cfg.scrypt) @@ -103,7 +103,7 @@ fn cannot_run_parallel_proof_gens() { k2: 4, k3: 4, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(0, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; CpuInitializer::new(cfg.scrypt) diff --git a/src/config.rs b/src/config.rs index ecb840ab..b451a6dd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,5 +11,33 @@ pub struct Config { /// `pow` for [Proof][crate::prove::Proof]. pub pow_difficulty: [u8; 32], /// Scrypt paramters for initilizing labels - pub scrypt: scrypt_jane::scrypt::ScryptParams, + pub scrypt: ScryptParams, +} + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct ScryptParams { + pub n: usize, + pub r: usize, + pub p: usize, +} + +impl ScryptParams { + pub fn new(n: usize, r: usize, p: usize) -> Self { + assert!(n >= 2); + assert!(n.is_power_of_two()); + assert!(r.is_power_of_two()); + assert!(p.is_power_of_two()); + Self { n, r, p } + } +} + +impl From for scrypt_jane::scrypt::ScryptParams { + fn from(params: ScryptParams) -> Self { + Self::new( + params.n.ilog2() as u8 - 1, + params.r.ilog2() as u8, + params.p.ilog2() as u8, + ) + } } diff --git a/src/initialize.rs b/src/initialize.rs index 409dd20d..884661f0 100644 --- a/src/initialize.rs +++ b/src/initialize.rs @@ -8,9 +8,9 @@ use std::{ use mockall::automock; use rayon::prelude::{IntoParallelIterator, ParallelIterator}; -use scrypt_jane::scrypt::{scrypt, ScryptParams}; +use scrypt_jane::scrypt::scrypt; -use crate::metadata::PostMetadata; +use crate::{config::ScryptParams, metadata::PostMetadata}; pub const LABEL_SIZE: usize = 16; pub const ENTIRE_LABEL_SIZE: usize = 32; @@ -115,7 +115,7 @@ impl Initialize for CpuInitializer { let mut scrypt_data = [0u8; 72]; scrypt_data[0..32].copy_from_slice(commitment); scrypt_data[32..40].copy_from_slice(&index.to_le_bytes()); - scrypt(&scrypt_data, &[], self.scrypt_params, &mut label); + scrypt(&scrypt_data, &[], self.scrypt_params.into(), &mut label); label }) .collect::>(); @@ -168,7 +168,7 @@ mod tests { let mut pos_file = tempfile::tempfile().unwrap(); let commitment = [0u8; 32]; - let scrypt_params = ScryptParams::new(1, 0, 0); + let scrypt_params = ScryptParams::new(4, 1, 1); CpuInitializer::new(scrypt_params) .initialize_to(&mut pos_file, &commitment, labels, None) .unwrap(); @@ -178,7 +178,7 @@ mod tests { #[test] fn test_initialize_fits_in_single_file() { - let scrypt_params = ScryptParams::new(1, 0, 0); + let scrypt_params = ScryptParams::new(4, 1, 1); let data_dir = tempfile::tempdir().unwrap(); let data_path = data_dir.path(); CpuInitializer::new(scrypt_params) @@ -201,7 +201,7 @@ mod tests { #[test] fn test_initialize_returns_metadata() { - let scrypt_params = ScryptParams::new(1, 0, 0); + let scrypt_params = ScryptParams::new(4, 1, 1); let data_dir = tempfile::tempdir().unwrap(); let node_id = rand::random::<[u8; 32]>(); let commitment_atx_id = rand::random::<[u8; 32]>(); @@ -228,7 +228,7 @@ mod tests { #[test] fn test_initialize_split_many_files() { - let scrypt_params = ScryptParams::new(1, 0, 0); + let scrypt_params = ScryptParams::new(4, 1, 1); let data_dir = tempfile::tempdir().unwrap(); let data_path = data_dir.path(); CpuInitializer::new(scrypt_params) @@ -262,7 +262,7 @@ mod tests { #[test] fn initialization_to_many_files_gives_same_result_as_single_file() { - let scrypt_params = ScryptParams::new(1, 0, 0); + let scrypt_params = ScryptParams::new(4, 1, 1); let data_dir = tempfile::tempdir().unwrap(); let data_path = data_dir.path(); diff --git a/src/lib.rs b/src/lib.rs index a0beab4c..7bb1db03 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,3 @@ pub mod prove; mod random_values_gen; pub mod reader; pub mod verification; - -// Reexport scrypt-jane params -pub use scrypt_jane::scrypt::ScryptParams; diff --git a/src/pos_verification.rs b/src/pos_verification.rs index 96bafd28..a6cb69e3 100644 --- a/src/pos_verification.rs +++ b/src/pos_verification.rs @@ -5,9 +5,9 @@ use std::{io::Read, io::Seek, path::Path}; use itertools::Itertools; use rand::seq::IteratorRandom; use rayon::prelude::{ParallelBridge, ParallelIterator}; -use scrypt_jane::scrypt::ScryptParams; use crate::{ + config::ScryptParams, initialize::{calc_commitment, CpuInitializer, Initialize}, metadata, }; diff --git a/src/prove.rs b/src/prove.rs index cf461582..b21ac060 100644 --- a/src/prove.rs +++ b/src/prove.rs @@ -354,10 +354,11 @@ where #[cfg(test)] mod tests { use super::*; - use crate::{compression::decompress_indexes, difficulty::proving_difficulty}; + use crate::{ + compression::decompress_indexes, config::ScryptParams, difficulty::proving_difficulty, + }; use mockall::predicate::{always, eq}; use rand::{thread_rng, RngCore}; - use scrypt_jane::scrypt::ScryptParams; use std::{collections::HashMap, iter::repeat}; #[test] @@ -388,7 +389,7 @@ mod tests { k2: 300, k3: 65, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(1, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; let params = ProvingParams::new(&meta, &cfg).unwrap(); let mut pow_prover = pow::MockProver::new(); @@ -424,7 +425,7 @@ mod tests { k2: 300, k3: 65, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(1, 0, 0), + scrypt: ScryptParams::new(4, 1, 1), }; let mut pow_prover = pow::MockProver::new(); pow_prover @@ -443,7 +444,7 @@ mod tests { k2: 32, k3: 10, pow_difficulty: [0x0F; 32], - scrypt: ScryptParams::new(2, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; let metadata = PostMetadata { num_units: 1, diff --git a/src/verification.rs b/src/verification.rs index 6ce6d694..87d7d3c5 100644 --- a/src/verification.rs +++ b/src/verification.rs @@ -40,12 +40,11 @@ use std::cmp::Ordering; use cipher::BlockEncrypt; use itertools::Itertools; use primitive_types::U256; -use scrypt_jane::scrypt::ScryptParams; use crate::{ cipher::AesCipher, compression::{decompress_indexes, required_bits}, - config::Config, + config::{Config, ScryptParams}, difficulty::proving_difficulty, initialize::{calc_commitment, generate_label}, metadata::ProofMetadata, @@ -239,10 +238,11 @@ fn expected_indices_bytes(required_bits: usize, k2: u32) -> usize { mod tests { use std::borrow::Cow; - use scrypt_jane::scrypt::ScryptParams; - use crate::{ - config::Config, metadata::ProofMetadata, pow::MockPowVerifier, prove::Proof, + config::{Config, ScryptParams}, + metadata::ProofMetadata, + pow::MockPowVerifier, + prove::Proof, verification::Error, }; @@ -268,7 +268,7 @@ mod tests { k2: 3, k3: 3, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(1, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; let fake_metadata = ProofMetadata { @@ -302,7 +302,7 @@ mod tests { k2: 10, k3: 10, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(1, 0, 0), + scrypt: ScryptParams::new(4, 1, 1), }; let fake_metadata = ProofMetadata { @@ -366,7 +366,7 @@ mod tests { k2: 0, k3: 0, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(2, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; let metadata = ProofMetadata { node_id: [0u8; 32], diff --git a/tests/generate_and_verify.rs b/tests/generate_and_verify.rs index b22dcf02..ffd7fe0a 100644 --- a/tests/generate_and_verify.rs +++ b/tests/generate_and_verify.rs @@ -1,13 +1,13 @@ use std::sync::atomic::AtomicBool; use post::{ + config::ScryptParams, initialize::{CpuInitializer, Initialize}, metadata::ProofMetadata, pow::randomx::{PoW, RandomXFlag}, prove::generate_proof, verification::{Verifier, VerifyingParams}, }; -use scrypt_jane::scrypt::ScryptParams; use tempfile::tempdir; #[test] @@ -22,7 +22,7 @@ fn test_generate_and_verify() { k2: 32, k3: 10, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(0, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; let metadata = CpuInitializer::new(cfg.scrypt) @@ -79,7 +79,7 @@ fn test_generate_and_verify_difficulty_msb_not_zero() { k2: 30, k3: 30, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(0, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; let metadata = CpuInitializer::new(cfg.scrypt) diff --git a/tests/initialize_and_verify.rs b/tests/initialize_and_verify.rs index 71b80fd8..9d0a5de9 100644 --- a/tests/initialize_and_verify.rs +++ b/tests/initialize_and_verify.rs @@ -1,10 +1,11 @@ use std::io::Write; use post::{ + config::ScryptParams, initialize::{CpuInitializer, Initialize}, pos_verification::verify_files, }; -use scrypt_jane::scrypt::ScryptParams; + use tempfile::tempdir; #[test] @@ -17,7 +18,7 @@ fn test_generate_and_verify() { k2: 32, k3: 10, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(0, 0, 0), + scrypt: ScryptParams::new(2, 1, 1), }; CpuInitializer::new(cfg.scrypt) @@ -30,7 +31,7 @@ fn test_generate_and_verify() { verify_files(datadir.path(), 1.0, Some(0), Some(1), cfg.scrypt).unwrap(); // Try verification with wrong scrypt params - let wrong_scrypt = ScryptParams::new(2, 0, 0); + let wrong_scrypt = ScryptParams::new(4, 1, 1); assert!(verify_files(datadir.path(), 100.0, None, None, wrong_scrypt).is_err()); assert!(verify_files(datadir.path(), 1.0, None, None, wrong_scrypt).is_err()); assert!(verify_files(datadir.path(), 100.0, Some(0), Some(0), wrong_scrypt).is_err()); From aae130a67e2b8811c2be3f3e1a7d71c3f5d37e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Fri, 3 Nov 2023 10:57:51 +0100 Subject: [PATCH 4/5] Refactor Config into ProofConfig and InitConfig --- benches/verifying.rs | 65 +++++++----- ffi/src/initialization.rs | 15 +-- ffi/src/post_impl.rs | 57 ++++++----- service/src/main.rs | 33 +++++-- service/src/service.rs | 11 ++- service/tests/test_client.rs | 10 +- service/tests/test_service.rs | 58 +++++++---- src/config.rs | 17 +++- src/difficulty.rs | 60 +++++++++-- src/prove.rs | 21 ++-- src/verification.rs | 176 +++++++++++++++------------------ tests/generate_and_verify.rs | 64 +++++------- tests/initialize_and_verify.rs | 29 +++--- 13 files changed, 336 insertions(+), 280 deletions(-) diff --git a/benches/verifying.rs b/benches/verifying.rs index 22a6f97f..a1c36d8f 100644 --- a/benches/verifying.rs +++ b/benches/verifying.rs @@ -1,48 +1,59 @@ +use std::sync::atomic::AtomicBool; + use criterion::{criterion_group, criterion_main, Criterion}; use post::{ - config::ScryptParams, + config::{InitConfig, ProofConfig, ScryptParams}, + initialize::{CpuInitializer, Initialize}, metadata::ProofMetadata, pow::randomx::{PoW, RandomXFlag}, - prove::Proof, - verification::{Verifier, VerifyingParams}, + prove::generate_proof, + verification::Verifier, }; #[cfg(not(windows))] use pprof::criterion::{Output, PProfProfiler}; +use tempfile::tempdir; fn verifying(c: &mut Criterion) { let challenge = b"hello world, challenge me!!!!!!!"; - let metadata = ProofMetadata { - node_id: [0u8; 32], - commitment_atx_id: [0u8; 32], - challenge: *challenge, - num_units: 1, - labels_per_unit: 1024 * 1024 * 1024, - }; - let num_labels = metadata.num_units as u64 * metadata.labels_per_unit; - - let verifier = Verifier::new(Box::new( - PoW::new(RandomXFlag::get_recommended_flags()).unwrap(), - )); + let datadir = tempdir().unwrap(); - let (k2, k3) = (37, 37); - let proof = Proof::new( - 0, - (0..k2 as u64).collect::>().as_slice(), - num_labels, - 0, - ); - let params = VerifyingParams { - difficulty: u64::MAX, - k2, - k3, + let cfg = ProofConfig { + k1: 199, + k2: 37, + k3: 37, pow_difficulty: [0xFF; 32], + }; + let init_cfg = InitConfig { + min_num_units: 1, + max_num_units: 1, + labels_per_unit: 200, scrypt: ScryptParams::new(8192, 1, 1), }; + let metadata = CpuInitializer::new(init_cfg.scrypt) + .initialize( + datadir.path(), + &[0u8; 32], + &[0u8; 32], + init_cfg.labels_per_unit, + 1, + init_cfg.labels_per_unit, + None, + ) + .unwrap(); + + let pow_flags = RandomXFlag::get_recommended_flags(); + // Generate a proof + let stop = AtomicBool::new(false); + let proof = generate_proof(datadir.path(), challenge, cfg, 32, 1, pow_flags, stop).unwrap(); + let metadata = ProofMetadata::new(metadata, *challenge); + + // Bench verifying the proof + let verifier = Verifier::new(Box::new(PoW::new(pow_flags).unwrap())); c.bench_function("verify", |b| { b.iter(|| { verifier - .verify(&proof, &metadata, params) + .verify(&proof, &metadata, &cfg, &init_cfg) .expect("proof should be valid"); }); }); diff --git a/ffi/src/initialization.rs b/ffi/src/initialization.rs index 3b2b2853..32bcd8e5 100644 --- a/ffi/src/initialization.rs +++ b/ffi/src/initialization.rs @@ -416,22 +416,15 @@ mod tests { fn initialize_and_verify() { // Initialize some data let datadir = tempdir().unwrap(); + let scrypt = ScryptParams::new(2, 1, 1); - let cfg = post::config::Config { - k1: 23, - k2: 32, - k3: 10, - pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(2, 1, 1), - }; - - CpuInitializer::new(cfg.scrypt) + CpuInitializer::new(scrypt) .initialize(datadir.path(), &[0u8; 32], &[0u8; 32], 256, 31, 700, None) .unwrap(); // Verify the data let datapath = CString::new(datadir.path().to_str().unwrap()).unwrap(); - let result = verify_pos(datapath.as_ptr(), null(), null(), 100.0, cfg.scrypt); + let result = verify_pos(datapath.as_ptr(), null(), null(), 100.0, scrypt); assert_eq!(VerifyResult::Ok, result); // verify with wrong scrypt params @@ -441,7 +434,7 @@ mod tests { // verify with non-existent path let path = CString::new("non-existent-path").unwrap(); - let result = verify_pos(path.as_ptr(), null(), null(), 100.0, cfg.scrypt); + let result = verify_pos(path.as_ptr(), null(), null(), 100.0, scrypt); assert_eq!(VerifyResult::Failed, result); } } diff --git a/ffi/src/post_impl.rs b/ffi/src/post_impl.rs index f6d461c5..7ed6e81e 100644 --- a/ffi/src/post_impl.rs +++ b/ffi/src/post_impl.rs @@ -9,11 +9,11 @@ use std::{ }; use post::{ - config::Config, + config::{InitConfig, ProofConfig}, metadata::ProofMetadata, pow::randomx::{PoW, RandomXFlag}, prove, - verification::{Verifier, VerifyingParams}, + verification::Verifier, }; use crate::ArrayU8; @@ -72,7 +72,7 @@ pub unsafe extern "C" fn free_proof(proof: *mut Proof) { pub extern "C" fn generate_proof( datadir: *const c_char, challenge: *const c_uchar, - cfg: Config, + cfg: ProofConfig, nonces: usize, threads: usize, pow_flags: RandomXFlag, @@ -90,7 +90,7 @@ pub extern "C" fn generate_proof( fn _generate_proof( datadir: *const c_char, challenge: *const c_uchar, - cfg: Config, + cfg: ProofConfig, nonces: usize, threads: usize, pow_flags: RandomXFlag, @@ -168,7 +168,8 @@ pub unsafe extern "C" fn verify_proof( verifier: *const Verifier, proof: Proof, metadata: *const ProofMetadata, - cfg: Config, + cfg: ProofConfig, + init_cfg: InitConfig, ) -> VerifyResult { let verifier = match verifier.as_ref() { Some(verifier) => verifier, @@ -191,12 +192,7 @@ pub unsafe extern "C" fn verify_proof( None => return VerifyResult::InvalidArgument, }; - let params = match VerifyingParams::new(metadata, &cfg) { - Ok(params) => params, - Err(_) => return VerifyResult::InvalidArgument, - }; - - match verifier.verify(&proof, metadata, params) { + match verifier.verify(&proof, metadata, &cfg, &init_cfg) { Ok(_) => VerifyResult::Ok, Err(err) => { log::error!("Proof is invalid: {err}"); @@ -215,12 +211,11 @@ mod tests { #[test] fn datadir_must_be_utf8() { let datadir = std::ffi::CString::new([159, 146, 150]).unwrap(); - let cfg = super::Config { + let cfg = super::ProofConfig { k1: 10, k2: 20, k3: 20, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(2, 1, 1), }; let result = super::_generate_proof( datadir.as_ptr(), @@ -253,11 +248,16 @@ mod tests { pow: 0, }, std::ptr::null(), - super::Config { + super::ProofConfig { k1: 1, k2: 2, k3: 2, pow_difficulty: [0xFF; 32], + }, + super::InitConfig { + min_num_units: 1, + max_num_units: 1, + labels_per_unit: 1, scrypt: ScryptParams::new(2, 1, 1), }, ) @@ -268,10 +268,9 @@ mod tests { #[test] fn test_end_to_end() { // Initialize some data first - let labels_per_unit = 200; let datadir = tempfile::tempdir().unwrap(); - let cfg = post::config::Config { + let cfg = post::config::ProofConfig { k1: 10, k2: 10, k3: 10, @@ -280,17 +279,23 @@ mod tests { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ], + }; + + let init_cfg = post::config::InitConfig { + min_num_units: 1, + max_num_units: 2, + labels_per_unit: 200, scrypt: ScryptParams::new(2, 1, 1), }; - let meta = post::initialize::CpuInitializer::new(cfg.scrypt) + let meta = post::initialize::CpuInitializer::new(init_cfg.scrypt) .initialize( datadir.path(), &[77; 32], &[0u8; 32], - labels_per_unit, + init_cfg.labels_per_unit, 2, - labels_per_unit, + 100, None, ) .unwrap(); @@ -316,17 +321,11 @@ mod tests { pow_flags, ); - let proof_metadata = ProofMetadata { - node_id: meta.node_id, - commitment_atx_id: meta.commitment_atx_id, - challenge: *challenge, - num_units: meta.num_units, - labels_per_unit: meta.labels_per_unit, + let proof_metadata = ProofMetadata::new(meta, *challenge); + let result = unsafe { + crate::post_impl::verify_proof(verifier, *cproof, &proof_metadata, cfg, init_cfg) }; - let result = - unsafe { crate::post_impl::verify_proof(verifier, *cproof, &proof_metadata as _, cfg) }; - assert_eq!(result, super::VerifyResult::Ok); // Modify the proof to have different k2pow @@ -338,7 +337,7 @@ mod tests { }; let result = unsafe { - crate::post_impl::verify_proof(verifier, invalid_proof, &proof_metadata as _, cfg) + crate::post_impl::verify_proof(verifier, invalid_proof, &proof_metadata, cfg, init_cfg) }; assert_eq!(result, super::VerifyResult::Invalid); diff --git a/service/src/main.rs b/service/src/main.rs index c514f8be..7f59c41b 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -39,14 +39,23 @@ struct Cli { #[derive(Args, Debug)] /// POST configuration - network parameters struct PostConfig { + /// The minimal number of units that must be initialized. + #[arg(long, default_value_t = 4)] + pub min_num_units: u32, + /// The maximal number of units that can be initialized. + #[arg(long, default_value_t = u32::MAX)] + pub max_num_units: u32, + /// The number of labels per unit. + #[arg(long, default_value_t = 4294967296)] + pub labels_per_unit: u64, /// K1 specifies the difficulty for a label to be a candidate for a proof - #[arg(long, default_value = "26")] + #[arg(long, default_value_t = 26)] k1: u32, /// K2 is the number of labels below the required difficulty required for a proof - #[arg(long, default_value = "37")] + #[arg(long, default_value_t = 37)] k2: u32, /// K3 is the size of the subset of proof indices that is validated - #[arg(long, default_value = "37")] + #[arg(long, default_value_t = 37)] k3: u32, /// difficulty for the nonce proof of work (aka "k2pow") #[arg( @@ -164,18 +173,24 @@ async fn main() -> eyre::Result<()> { log::info!("POST network parameters: {:?}", args.post_config); log::info!("POST proving settings: {:?}", args.post_settings); + let scrypt = post::config::ScryptParams::new( + args.post_config.scrypt.n, + args.post_config.scrypt.r, + args.post_config.scrypt.p, + ); let service = post_service::service::PostService::new( args.dir, - post::config::Config { + post::config::ProofConfig { k1: args.post_config.k1, k2: args.post_config.k2, k3: args.post_config.k3, pow_difficulty: args.post_config.pow_difficulty, - scrypt: post::config::ScryptParams::new( - args.post_config.scrypt.n, - args.post_config.scrypt.r, - args.post_config.scrypt.p, - ), + }, + post::config::InitConfig { + min_num_units: args.post_config.min_num_units, + max_num_units: args.post_config.max_num_units, + labels_per_unit: args.post_config.labels_per_unit, + scrypt, }, args.post_settings.nonces, args.post_settings.threads, diff --git a/service/src/service.rs b/service/src/service.rs index f8062795..e27766f5 100644 --- a/service/src/service.rs +++ b/service/src/service.rs @@ -10,7 +10,7 @@ use post::{ metadata::{PostMetadata, ProofMetadata}, pow::randomx::{PoW, RandomXFlag}, prove::Proof, - verification::{Verifier, VerifyingParams}, + verification::Verifier, }; #[derive(Debug)] @@ -27,7 +27,8 @@ struct ProofGenProcess { pub struct PostService { datadir: PathBuf, - cfg: post::config::Config, + cfg: post::config::ProofConfig, + init_cfg: post::config::InitConfig, nonces: usize, threads: usize, pow_flags: RandomXFlag, @@ -40,7 +41,8 @@ pub struct PostService { impl PostService { pub fn new( datadir: PathBuf, - cfg: post::config::Config, + cfg: post::config::ProofConfig, + init_cfg: post::config::InitConfig, nonces: usize, threads: usize, pow_flags: RandomXFlag, @@ -49,6 +51,7 @@ impl PostService { proof_generation: Mutex::new(None), datadir, cfg, + init_cfg, nonces, threads, pow_flags, @@ -113,7 +116,7 @@ impl crate::client::PostService for PostService { fn verify_proof(&self, proof: &Proof, metadata: &ProofMetadata) -> eyre::Result<()> { self.verifier - .verify(proof, metadata, VerifyingParams::new(metadata, &self.cfg)?) + .verify(proof, metadata, &self.cfg, &self.init_cfg) .wrap_err("verifying proof") } diff --git a/service/tests/test_client.rs b/service/tests/test_client.rs index 80a1fdc4..eb8c659e 100644 --- a/service/tests/test_client.rs +++ b/service/tests/test_client.rs @@ -224,15 +224,20 @@ async fn test_broken_request_no_kind() { #[tokio::test] async fn test_get_metadata(#[case] vrf_difficulty: Option<[u8; 32]>) { let datadir = tempdir().unwrap(); - let cfg = post::config::Config { + let cfg = post::config::ProofConfig { k1: 23, k2: 32, k3: 10, pow_difficulty: [0xFF; 32], + }; + let init_cfg = post::config::InitConfig { + min_num_units: 1, + max_num_units: 1000, + labels_per_unit: 256 * 16, scrypt: post::config::ScryptParams::new(2, 1, 1), }; - let metadata = CpuInitializer::new(cfg.scrypt) + let metadata = CpuInitializer::new(init_cfg.scrypt) .initialize( datadir.path(), &[77; 32], @@ -249,6 +254,7 @@ async fn test_get_metadata(#[case] vrf_difficulty: Option<[u8; 32]>) { let service = post_service::service::PostService::new( datadir.path().into(), cfg, + init_cfg, 16, 1, post::pow::randomx::RandomXFlag::get_recommended_flags(), diff --git a/service/tests/test_service.rs b/service/tests/test_service.rs index 60ad31aa..65dbe832 100644 --- a/service/tests/test_service.rs +++ b/service/tests/test_service.rs @@ -1,7 +1,7 @@ use std::{thread::sleep, time::Duration}; use post::{ - config::ScryptParams, + config::{InitConfig, ProofConfig, ScryptParams}, initialize::{CpuInitializer, Initialize}, metadata::ProofMetadata, pow::randomx::RandomXFlag, @@ -11,25 +11,29 @@ use post_service::{client::PostService, service::ProofGenState}; #[test] fn test_generate_and_verify() { // Initialize some data - let labels_per_unit = 256; let datadir = tempfile::tempdir().unwrap(); - let cfg = post::config::Config { + let cfg = ProofConfig { k1: 8, k2: 4, k3: 4, pow_difficulty: [0xFF; 32], + }; + let init_cfg = InitConfig { + min_num_units: 1, + max_num_units: 1000, + labels_per_unit: 256, scrypt: ScryptParams::new(2, 1, 1), }; - let metadata = CpuInitializer::new(cfg.scrypt) + let metadata = CpuInitializer::new(init_cfg.scrypt) .initialize( datadir.path(), &[0xBE; 32], &[0xCE; 32], - labels_per_unit, + init_cfg.labels_per_unit, 4, - labels_per_unit, + init_cfg.labels_per_unit, None, ) .unwrap(); @@ -37,9 +41,15 @@ fn test_generate_and_verify() { let pow_flags = RandomXFlag::get_recommended_flags(); // Generate a proof - let service = - post_service::service::PostService::new(datadir.into_path(), cfg, 16, 1, pow_flags) - .unwrap(); + let service = post_service::service::PostService::new( + datadir.into_path(), + cfg, + init_cfg, + 16, + 1, + pow_flags, + ) + .unwrap(); let (proof, metadata) = loop { if let ProofGenState::Finished { proof } = service.gen_proof(vec![0xCA; 32]).unwrap() { @@ -57,25 +67,29 @@ fn test_generate_and_verify() { #[test] fn reject_invalid_challenge() { // Initialize some data - let labels_per_unit = 256; let datadir = tempfile::tempdir().unwrap(); - let cfg = post::config::Config { + let cfg = ProofConfig { k1: 8, k2: 4, k3: 4, pow_difficulty: [0xFF; 32], + }; + let init_cfg = InitConfig { + min_num_units: 1, + max_num_units: 1000, + labels_per_unit: 256, scrypt: ScryptParams::new(2, 1, 1), }; - CpuInitializer::new(cfg.scrypt) + CpuInitializer::new(init_cfg.scrypt) .initialize( datadir.path(), &[0xBE; 32], &[0xCE; 32], - labels_per_unit, + init_cfg.labels_per_unit, 4, - labels_per_unit, + init_cfg.labels_per_unit, None, ) .unwrap(); @@ -84,6 +98,7 @@ fn reject_invalid_challenge() { let service = post_service::service::PostService::new( datadir.into_path(), cfg, + init_cfg, 16, 1, RandomXFlag::get_recommended_flags(), @@ -95,25 +110,29 @@ fn reject_invalid_challenge() { #[test] fn cannot_run_parallel_proof_gens() { // Initialize some data - let labels_per_unit = 256; let datadir = tempfile::tempdir().unwrap(); - let cfg = post::config::Config { + let cfg = ProofConfig { k1: 8, k2: 4, k3: 4, pow_difficulty: [0xFF; 32], + }; + let init_cfg = InitConfig { + min_num_units: 1, + max_num_units: 1000, + labels_per_unit: 256, scrypt: ScryptParams::new(2, 1, 1), }; - CpuInitializer::new(cfg.scrypt) + CpuInitializer::new(init_cfg.scrypt) .initialize( datadir.path(), &[0xBE; 32], &[0xCE; 32], - labels_per_unit, + init_cfg.labels_per_unit, 4, - labels_per_unit, + init_cfg.labels_per_unit, None, ) .unwrap(); @@ -122,6 +141,7 @@ fn cannot_run_parallel_proof_gens() { let service = post_service::service::PostService::new( datadir.into_path(), cfg, + init_cfg, 16, 1, RandomXFlag::get_recommended_flags(), diff --git a/src/config.rs b/src/config.rs index b451a6dd..65519eaf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,19 @@ #[repr(C)] #[derive(Debug, Clone, Copy)] -pub struct Config { +pub struct InitConfig { + /// The minimal number of units that must be initialized. + pub min_num_units: u32, + /// The maximal number of units that can be initialized. + pub max_num_units: u32, + /// The number of labels per unit. + pub labels_per_unit: u64, + /// Scrypt paramters for initilizing labels + pub scrypt: ScryptParams, +} + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct ProofConfig { /// K1 specifies the difficulty for a label to be a candidate for a proof. pub k1: u32, /// K2 is the number of labels below the required difficulty required for a proof. @@ -10,8 +23,6 @@ pub struct Config { /// Difficulty for the nonce proof of work. Lower values increase difficulty of finding /// `pow` for [Proof][crate::prove::Proof]. pub pow_difficulty: [u8; 32], - /// Scrypt paramters for initilizing labels - pub scrypt: ScryptParams, } #[repr(C)] diff --git a/src/difficulty.rs b/src/difficulty.rs index dd7aca2e..aabc91da 100644 --- a/src/difficulty.rs +++ b/src/difficulty.rs @@ -1,4 +1,4 @@ -use eyre::Context; +use primitive_types::U256; /// Calculate proving difficulty. /// @@ -7,14 +7,30 @@ use eyre::Context; /// /// The difficulty is calculated as: /// difficulty = 2^64 * K1 / num_labels -pub(crate) fn proving_difficulty(k1: u32, num_labels: u64) -> eyre::Result { - eyre::ensure!(num_labels > 0, "number of label blocks must be > 0"); - eyre::ensure!( - num_labels > k1 as u64, - format!("number of labels ({num_labels}) must be bigger than k1 ({k1})") - ); +pub(crate) fn proving_difficulty(k1: u32, num_labels: u64) -> Result { + if num_labels == 0 { + return Err("number of label blocks must be > 0".to_string()); + } + if num_labels <= k1 as u64 { + return Err(format!( + "number of labels ({num_labels}) must be bigger than k1 ({k1})" + )); + } let difficulty = (1u128 << 64) * k1 as u128 / num_labels as u128; - u64::try_from(difficulty).wrap_err("difficulty doesn't fit in u64") + u64::try_from(difficulty).or(Err("difficulty doesn't fit in u64".to_string())) +} + +/// Scale PoW difficulty by the number of units. +/// +/// The more units of data, the more difficult the PoW should be (linearly). +/// Because the PoW looks for values < difficulty, we need to scale the difficulty down. +/// The difficulty threshold is calculated as: +/// difficulty = difficulty / num_units +pub(crate) fn scale_pow_difficulty(difficulty: &[u8; 32], num_units: u32) -> [u8; 32] { + let difficulty_scaled = U256::from_big_endian(difficulty) / num_units; + let mut difficulty = [0u8; 32]; + difficulty_scaled.to_big_endian(&mut difficulty); + difficulty } #[test] @@ -34,3 +50,31 @@ fn difficulty_calculation() { assert_eq!(proving_difficulty(1, 4).unwrap(), 1u64 << (64 - 2)); assert_eq!(proving_difficulty(1, 128).unwrap(), 1u64 << (64 - 7)); } + +/// Test that PoW threshold is scaled with num_units. +#[test] +fn scaling_pow_thresholds() { + { + // don't scale when num_units is 1 + let difficulty = scale_pow_difficulty(&[0xFF; 32], 1); + assert_eq!(difficulty, [0xFF; 32]); + } + { + // scale with num_units + let difficulty = scale_pow_difficulty(&[0xFF; 32], 2); + assert!(difficulty < [0xFF; 32]); + assert_eq!( + difficulty.as_slice(), + [&[0x7F], [0xFF; 31].as_slice()].concat() + ); + } + { + // scale with num_units + let difficulty = scale_pow_difficulty(&[0xFF; 32], 2_u32.pow(5)); + assert!(difficulty < [0xFF; 32]); + assert_eq!( + difficulty.as_slice(), + [&[0xFF >> 5], [0xFF; 31].as_slice()].concat() + ); + } +} diff --git a/src/prove.rs b/src/prove.rs index b21ac060..d74b8eda 100644 --- a/src/prove.rs +++ b/src/prove.rs @@ -25,7 +25,7 @@ use rayon::prelude::{ParallelBridge, ParallelIterator}; use crate::{ cipher::AesCipher, compression::{compress_indices, required_bits}, - config::Config, + config::ProofConfig, difficulty::proving_difficulty, metadata::{self, PostMetadata}, pow, @@ -61,13 +61,13 @@ pub struct ProvingParams { } impl ProvingParams { - pub fn new(metadata: &PostMetadata, cfg: &Config) -> eyre::Result { + pub fn new(metadata: &PostMetadata, cfg: &ProofConfig) -> eyre::Result { let num_labels = metadata.num_units as u64 * metadata.labels_per_unit; let mut pow_difficulty = [0u8; 32]; let difficulty_scaled = U256::from_big_endian(&cfg.pow_difficulty) / metadata.num_units; difficulty_scaled.to_big_endian(&mut pow_difficulty); Ok(Self { - difficulty: proving_difficulty(cfg.k1, num_labels)?, + difficulty: proving_difficulty(cfg.k1, num_labels).map_err(|e| eyre::eyre!(e))?, pow_difficulty, }) } @@ -264,7 +264,7 @@ impl Prover for Prover8_56 { pub fn generate_proof( datadir: &Path, challenge: &[u8; 32], - cfg: Config, + cfg: ProofConfig, nonces: usize, threads: usize, pow_flags: RandomXFlag, @@ -354,9 +354,7 @@ where #[cfg(test)] mod tests { use super::*; - use crate::{ - compression::decompress_indexes, config::ScryptParams, difficulty::proving_difficulty, - }; + use crate::{compression::decompress_indexes, difficulty::proving_difficulty}; use mockall::predicate::{always, eq}; use rand::{thread_rng, RngCore}; use std::{collections::HashMap, iter::repeat}; @@ -384,12 +382,11 @@ mod tests { max_file_size: 1024, ..Default::default() }; - let cfg = Config { + let cfg = ProofConfig { k1: 279, k2: 300, k3: 65, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(2, 1, 1), }; let params = ProvingParams::new(&meta, &cfg).unwrap(); let mut pow_prover = pow::MockProver::new(); @@ -420,12 +417,11 @@ mod tests { max_file_size: 1024, ..Default::default() }; - let cfg = Config { + let cfg = ProofConfig { k1: 279, k2: 300, k3: 65, pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(4, 1, 1), }; let mut pow_prover = pow::MockProver::new(); pow_prover @@ -439,12 +435,11 @@ mod tests { /// Test that PoW threshold is scaled with num_units. #[test] fn scaling_pows_thresholds() { - let cfg = Config { + let cfg = ProofConfig { k1: 32, k2: 32, k3: 10, pow_difficulty: [0x0F; 32], - scrypt: ScryptParams::new(2, 1, 1), }; let metadata = PostMetadata { num_units: 1, diff --git a/src/verification.rs b/src/verification.rs index 87d7d3c5..48c4ba0b 100644 --- a/src/verification.rs +++ b/src/verification.rs @@ -39,13 +39,12 @@ use std::cmp::Ordering; use cipher::BlockEncrypt; use itertools::Itertools; -use primitive_types::U256; use crate::{ cipher::AesCipher, compression::{decompress_indexes, required_bits}, - config::{Config, ScryptParams}, - difficulty::proving_difficulty, + config::{InitConfig, ProofConfig}, + difficulty::{proving_difficulty, scale_pow_difficulty}, initialize::{calc_commitment, generate_label}, metadata::ProofMetadata, pow::PowVerifier, @@ -55,35 +54,6 @@ use crate::{ const NONCES_PER_AES: u32 = Prover8_56::NONCES_PER_AES; -#[derive(Debug, Clone, Copy)] -pub struct VerifyingParams { - pub difficulty: u64, - pub k2: u32, - pub k3: u32, - pub pow_difficulty: [u8; 32], - pub scrypt: ScryptParams, -} - -impl VerifyingParams { - pub fn new(metadata: &ProofMetadata, cfg: &Config) -> eyre::Result { - let num_labels = metadata.num_units as u64 * metadata.labels_per_unit; - - // Scale PoW difficulty by number of units - eyre::ensure!(metadata.num_units > 0, "num_units must be > 0"); - let difficulty_scaled = U256::from_big_endian(&cfg.pow_difficulty) / metadata.num_units; - let mut pow_difficulty = [0u8; 32]; - difficulty_scaled.to_big_endian(&mut pow_difficulty); - - Ok(Self { - difficulty: proving_difficulty(cfg.k1, num_labels)?, - k2: cfg.k2, - k3: cfg.k3, - pow_difficulty, - scrypt: cfg.scrypt, - }) - } -} - pub struct Verifier { pow_verifier: Box, } @@ -110,6 +80,45 @@ pub enum Error { difficulty_lsb: u64, label: [u8; 16], }, + #[error(transparent)] + InvalidMetadata(#[from] MetadataValidationError), + #[error("invalid number of labels: (0)")] + InvalidNumLabels(String), +} + +#[derive(thiserror::Error, Debug)] +pub enum MetadataValidationError { + #[error("numunits too small: {got} < {min}")] + NumUnitsTooSmall { min: u32, got: u32 }, + #[error("numunits too large: {got} < {max}")] + NumUnitsTooLarge { max: u32, got: u32 }, + #[error("invalid labels_per_unit: {got} != {expected}")] + LabelsPerUnitInvalid { expected: u64, got: u64 }, +} + +pub fn verify_metadata( + metadata: &ProofMetadata, + init_cfg: &InitConfig, +) -> Result<(), MetadataValidationError> { + if metadata.num_units < init_cfg.min_num_units { + return Err(MetadataValidationError::NumUnitsTooSmall { + min: init_cfg.min_num_units, + got: metadata.num_units, + }); + } + if metadata.num_units > init_cfg.max_num_units { + return Err(MetadataValidationError::NumUnitsTooLarge { + max: init_cfg.max_num_units, + got: metadata.num_units, + }); + } + if metadata.labels_per_unit != init_cfg.labels_per_unit { + return Err(MetadataValidationError::LabelsPerUnitInvalid { + expected: init_cfg.labels_per_unit, + got: metadata.labels_per_unit, + }); + } + Ok(()) } impl Verifier { @@ -129,9 +138,13 @@ impl Verifier { &self, proof: &Proof, metadata: &ProofMetadata, - params: VerifyingParams, + cfg: &ProofConfig, + init_cfg: &InitConfig, ) -> Result<(), Error> { + verify_metadata(metadata, init_cfg)?; + let challenge = metadata.challenge; + let pow_difficulty = scale_pow_difficulty(&cfg.pow_difficulty, metadata.num_units); // Verify K2 PoW let nonce_group = proof.nonce / NONCES_PER_AES; @@ -141,14 +154,14 @@ impl Verifier { .try_into() .map_err(|_| Error::NonceGroupOutOfBounds(nonce_group))?, &challenge[..8].try_into().unwrap(), - ¶ms.pow_difficulty, + &pow_difficulty, &metadata.node_id, )?; // Verify the number of indices against K2 - let num_lables = metadata.num_units as u64 * metadata.labels_per_unit; - let bits_per_index = required_bits(num_lables); - let expected = expected_indices_bytes(bits_per_index, params.k2); + let num_labels = metadata.num_units as u64 * init_cfg.labels_per_unit; + let bits_per_index = required_bits(num_labels); + let expected = expected_indices_bytes(bits_per_index, cfg.k2); if proof.indices.len() != expected { return Err(Error::InvalidIndicesLen { expected, @@ -157,12 +170,14 @@ impl Verifier { } let indices_unpacked = decompress_indexes(&proof.indices, bits_per_index) - .take(params.k2 as usize) + .take(cfg.k2 as usize) .collect_vec(); let commitment = calc_commitment(&metadata.node_id, &metadata.commitment_atx_id); let cipher = AesCipher::new(&challenge, nonce_group, proof.pow); let lazy_cipher = AesCipher::new_lazy(&challenge, proof.nonce, nonce_group, proof.pow); - let (difficulty_msb, difficulty_lsb) = Prover8_56::split_difficulty(params.difficulty); + + let difficulty = proving_difficulty(cfg.k1, num_labels).map_err(Error::InvalidNumLabels)?; + let (difficulty_msb, difficulty_lsb) = Prover8_56::split_difficulty(difficulty); let output_index = (proof.nonce % NONCES_PER_AES) as usize; @@ -174,11 +189,11 @@ impl Verifier { &proof.pow.to_le_bytes(), ]; - let k3_indices = RandomValuesIterator::new(indices_unpacked, seed).take(params.k3 as usize); + let k3_indices = RandomValuesIterator::new(indices_unpacked, seed).take(cfg.k3 as usize); k3_indices.into_iter().try_for_each(|index| { let mut output = [0u8; 16]; - let label = generate_label(&commitment, params.scrypt, index); + let label = generate_label(&commitment, init_cfg.scrypt, index); cipher .aes .encrypt_block_b2b(&label.into(), (&mut output).into()); @@ -239,14 +254,14 @@ mod tests { use std::borrow::Cow; use crate::{ - config::{Config, ScryptParams}, + config::{InitConfig, ProofConfig, ScryptParams}, metadata::ProofMetadata, pow::MockPowVerifier, prove::Proof, verification::Error, }; - use super::{expected_indices_bytes, next_multiple_of, Verifier, VerifyingParams}; + use super::{expected_indices_bytes, next_multiple_of, Verifier}; #[test] fn test_next_mutliple_of() { @@ -263,11 +278,16 @@ mod tests { #[test] fn reject_invalid_pow() { - let params = VerifyingParams { - difficulty: u64::MAX, + let cfg = ProofConfig { + k1: 3, k2: 3, k3: 3, pow_difficulty: [0xFF; 32], + }; + let init_cfg = InitConfig { + min_num_units: 1, + max_num_units: 10, + labels_per_unit: 2048, scrypt: ScryptParams::new(2, 1, 1), }; @@ -290,18 +310,24 @@ mod tests { pow: 0, }, &fake_metadata, - params, + &cfg, + &init_cfg, ); assert!(matches!(result, Err(Error::InvalidPoW(_)))); } #[test] fn reject_invalid_proof() { - let params = VerifyingParams { - difficulty: u64::MAX, + let pcfg = ProofConfig { + k1: 10, k2: 10, k3: 10, pow_difficulty: [0xFF; 32], + }; + let icfg = InitConfig { + min_num_units: 1, + max_num_units: 10, + labels_per_unit: 2048, scrypt: ScryptParams::new(4, 1, 1), }; @@ -323,7 +349,7 @@ mod tests { indices: Cow::from(vec![]), pow: 0, }; - let result = verifier.verify(&empty_proof, &fake_metadata, params); + let result = verifier.verify(&empty_proof, &fake_metadata, &pcfg, &icfg); assert!(matches!( result, Err(Error::InvalidIndicesLen { @@ -338,7 +364,7 @@ mod tests { indices: Cow::from(vec![]), pow: 0, }; - let res = verifier.verify(&nonce_out_of_bounds_proof, &fake_metadata, params); + let res = verifier.verify(&nonce_out_of_bounds_proof, &fake_metadata, &pcfg, &icfg); assert!(matches!(res, Err(Error::NonceGroupOutOfBounds(256)))); } { @@ -347,7 +373,8 @@ mod tests { indices: Cow::from(vec![1, 2, 3]), pow: 0, }; - let result = verifier.verify(&proof_with_not_enough_indices, &fake_metadata, params); + let result = + verifier.verify(&proof_with_not_enough_indices, &fake_metadata, &pcfg, &icfg); assert!(matches!( result, Err(Error::InvalidIndicesLen { @@ -357,51 +384,4 @@ mod tests { )); } } - - /// Test that PoW threshold is scaled with num_units. - #[test] - fn scaling_pow_thresholds() { - let cfg = Config { - k1: 0, - k2: 0, - k3: 0, - pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(2, 1, 1), - }; - let metadata = ProofMetadata { - node_id: [0u8; 32], - commitment_atx_id: [0u8; 32], - challenge: [0u8; 32], - num_units: 1, - labels_per_unit: 100, - }; - { - // reject zero num_units - let params = VerifyingParams::new( - &ProofMetadata { - num_units: 0, - ..metadata - }, - &cfg, - ); - assert!(params.is_err()); - } - { - // don't scale when num_units is 1 - let params = VerifyingParams::new(&metadata, &cfg).unwrap(); - assert_eq!(params.pow_difficulty, cfg.pow_difficulty); - } - { - // scale with num_units - let params = VerifyingParams::new( - &ProofMetadata { - num_units: 10, - ..metadata - }, - &cfg, - ) - .unwrap(); - assert!(params.pow_difficulty < cfg.pow_difficulty); - } - } } diff --git a/tests/generate_and_verify.rs b/tests/generate_and_verify.rs index ffd7fe0a..425863e5 100644 --- a/tests/generate_and_verify.rs +++ b/tests/generate_and_verify.rs @@ -1,12 +1,12 @@ use std::sync::atomic::AtomicBool; use post::{ - config::ScryptParams, + config::{InitConfig, ScryptParams}, initialize::{CpuInitializer, Initialize}, metadata::ProofMetadata, pow::randomx::{PoW, RandomXFlag}, prove::generate_proof, - verification::{Verifier, VerifyingParams}, + verification::Verifier, }; use tempfile::tempdir; @@ -14,25 +14,29 @@ use tempfile::tempdir; fn test_generate_and_verify() { // Initialize some data let challenge = b"hello world, challenge me!!!!!!!"; - let labels_per_unit = 256 * 16; let datadir = tempdir().unwrap(); - let cfg = post::config::Config { + let cfg = post::config::ProofConfig { k1: 23, k2: 32, k3: 10, pow_difficulty: [0xFF; 32], + }; + let init_cfg = InitConfig { + min_num_units: 1, + max_num_units: 1000, + labels_per_unit: 256 * 16, scrypt: ScryptParams::new(2, 1, 1), }; - let metadata = CpuInitializer::new(cfg.scrypt) + let metadata = CpuInitializer::new(init_cfg.scrypt) .initialize( datadir.path(), &[77; 32], &[0u8; 32], - labels_per_unit, + init_cfg.labels_per_unit, 31, - labels_per_unit, + 1000, None, ) .unwrap(); @@ -46,22 +50,14 @@ fn test_generate_and_verify() { let metadata = ProofMetadata::new(metadata, *challenge); let verifier = Verifier::new(Box::new(PoW::new(pow_flags).unwrap())); verifier - .verify( - &proof, - &metadata, - VerifyingParams::new(&metadata, &cfg).unwrap(), - ) + .verify(&proof, &metadata, &cfg, &init_cfg) .expect("proof should be valid"); // Check that the proof is invalid if we modify one index let mut invalid_proof = proof; invalid_proof.pow -= 1; verifier - .verify( - &invalid_proof, - &metadata, - VerifyingParams::new(&metadata, &cfg).unwrap(), - ) + .verify(&invalid_proof, &metadata, &cfg, &init_cfg) .expect_err("proof should be invalid"); } @@ -71,25 +67,29 @@ fn test_generate_and_verify() { fn test_generate_and_verify_difficulty_msb_not_zero() { // Initialize some data let challenge = b"hello world, challenge me!!!!!!!"; - let labels_per_unit = 200; let datadir = tempdir().unwrap(); - let cfg = post::config::Config { + let cfg = post::config::ProofConfig { k1: 20, k2: 30, k3: 30, pow_difficulty: [0xFF; 32], + }; + let init_cfg = InitConfig { + min_num_units: 1, + max_num_units: 1000, + labels_per_unit: 200, scrypt: ScryptParams::new(2, 1, 1), }; - let metadata = CpuInitializer::new(cfg.scrypt) + let metadata = CpuInitializer::new(init_cfg.scrypt) .initialize( datadir.path(), &[0u8; 32], &[0u8; 32], - labels_per_unit, + init_cfg.labels_per_unit, 2, - labels_per_unit, + init_cfg.labels_per_unit, None, ) .unwrap(); @@ -100,30 +100,16 @@ fn test_generate_and_verify_difficulty_msb_not_zero() { let proof = generate_proof(datadir.path(), challenge, cfg, 32, 1, pow_flags, stop).unwrap(); // Verify the proof - let metadata = ProofMetadata { - node_id: metadata.node_id, - commitment_atx_id: metadata.commitment_atx_id, - challenge: *challenge, - num_units: metadata.num_units, - labels_per_unit: metadata.labels_per_unit, - }; + let metadata = ProofMetadata::new(metadata, *challenge); let verifier = Verifier::new(Box::new(PoW::new(pow_flags).unwrap())); verifier - .verify( - &proof, - &metadata, - VerifyingParams::new(&metadata, &cfg).unwrap(), - ) + .verify(&proof, &metadata, &cfg, &init_cfg) .expect("proof should be valid"); // Check that the proof is invalid if we modify one index let mut invalid_proof = proof; invalid_proof.indices.to_mut()[0] += 1; verifier - .verify( - &invalid_proof, - &metadata, - VerifyingParams::new(&metadata, &cfg).unwrap(), - ) + .verify(&invalid_proof, &metadata, &cfg, &init_cfg) .expect_err("proof should be invalid"); } diff --git a/tests/initialize_and_verify.rs b/tests/initialize_and_verify.rs index 9d0a5de9..3103543c 100644 --- a/tests/initialize_and_verify.rs +++ b/tests/initialize_and_verify.rs @@ -12,23 +12,16 @@ use tempfile::tempdir; fn test_generate_and_verify() { // Initialize some data let datadir = tempdir().unwrap(); + let scrypt = ScryptParams::new(2, 1, 1); - let cfg = post::config::Config { - k1: 23, - k2: 32, - k3: 10, - pow_difficulty: [0xFF; 32], - scrypt: ScryptParams::new(2, 1, 1), - }; - - CpuInitializer::new(cfg.scrypt) + CpuInitializer::new(scrypt) .initialize(datadir.path(), &[0u8; 32], &[0u8; 32], 256, 31, 700, None) .unwrap(); // Verify the data - verify_files(datadir.path(), 100.0, None, None, cfg.scrypt).unwrap(); - verify_files(datadir.path(), 1.0, None, None, cfg.scrypt).unwrap(); - verify_files(datadir.path(), 1.0, Some(0), Some(1), cfg.scrypt).unwrap(); + verify_files(datadir.path(), 100.0, None, None, scrypt).unwrap(); + verify_files(datadir.path(), 1.0, None, None, scrypt).unwrap(); + verify_files(datadir.path(), 1.0, Some(0), Some(1), scrypt).unwrap(); // Try verification with wrong scrypt params let wrong_scrypt = ScryptParams::new(4, 1, 1); @@ -44,12 +37,12 @@ fn test_generate_and_verify() { file.write_all(&[0u8; 16]).unwrap(); - assert!(verify_files(datadir.path(), 100.0, None, None, cfg.scrypt).is_err()); - assert!(verify_files(datadir.path(), 100.0, Some(1), Some(1), cfg.scrypt).is_err()); - assert!(verify_files(datadir.path(), 100.0, None, Some(1), cfg.scrypt).is_err()); - assert!(verify_files(datadir.path(), 100.0, Some(1), None, cfg.scrypt).is_err()); + assert!(verify_files(datadir.path(), 100.0, None, None, scrypt).is_err()); + assert!(verify_files(datadir.path(), 100.0, Some(1), Some(1), scrypt).is_err()); + assert!(verify_files(datadir.path(), 100.0, None, Some(1), scrypt).is_err()); + assert!(verify_files(datadir.path(), 100.0, Some(1), None, scrypt).is_err()); // skip corrupted files - pass - verify_files(datadir.path(), 100.0, None, Some(0), cfg.scrypt).unwrap(); - verify_files(datadir.path(), 100.0, Some(2), None, cfg.scrypt).unwrap(); + verify_files(datadir.path(), 100.0, None, Some(0), scrypt).unwrap(); + verify_files(datadir.path(), 100.0, Some(2), None, scrypt).unwrap(); } From f4026b9c76143cf0a3dc521daf1462309641caeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Fri, 3 Nov 2023 14:14:52 +0100 Subject: [PATCH 5/5] Add UT for verify_metadata --- src/verification.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/verification.rs b/src/verification.rs index 48c4ba0b..fbc4bd34 100644 --- a/src/verification.rs +++ b/src/verification.rs @@ -384,4 +384,43 @@ mod tests { )); } } + + #[test] + fn verify_metadata() { + let valid_meta = ProofMetadata { + node_id: [0; 32], + commitment_atx_id: [0; 32], + challenge: [0; 32], + num_units: 1, + labels_per_unit: 100, + }; + let init_cfg = InitConfig { + min_num_units: 1, + max_num_units: 10, + labels_per_unit: 100, + scrypt: ScryptParams::new(2, 1, 1), + }; + assert!(super::verify_metadata(&valid_meta, &init_cfg).is_ok()); + { + let num_units_small = ProofMetadata { + num_units: 0, + ..valid_meta + }; + assert!(super::verify_metadata(&num_units_small, &init_cfg).is_err()); + } + { + let num_units_large = ProofMetadata { + num_units: 99, + ..valid_meta + }; + assert!(super::verify_metadata(&num_units_large, &init_cfg).is_err()); + } + { + let invalid_labels_per_unit = ProofMetadata { + labels_per_unit: 99, + ..valid_meta + }; + assert!(super::verify_metadata(&invalid_labels_per_unit, &init_cfg).is_err()); + } + } }