From 2587f5a948939c4d85b8558f718537a4e813090b Mon Sep 17 00:00:00 2001 From: David Date: Fri, 14 Feb 2025 00:00:11 +0100 Subject: [PATCH] Benchmarks for ZK proofs (#173) --- Cargo.lock | 27 + synedrion/Cargo.toml | 13 +- synedrion/benches/zk_proofs.rs | 158 ++++++ synedrion/src/cggmp21.rs | 8 +- synedrion/src/cggmp21/sigma/aff_g.rs | 10 + synedrion/src/cggmp21/sigma/dec.rs | 11 +- synedrion/src/cggmp21/sigma/fac.rs | 12 +- synedrion/src/cggmp21/sigma/mod_.rs | 8 + synedrion/src/cggmp21/sigma/prm.rs | 8 + synedrion/src/cggmp21/sigma/sch.rs | 8 + synedrion/src/lib.rs | 5 + synedrion/src/paillier/encryption.rs | 2 +- synedrion/src/private_benches.rs | 783 +++++++++++++++++++++++++++ synedrion/src/uint/public_signed.rs | 2 +- 14 files changed, 1048 insertions(+), 7 deletions(-) create mode 100644 synedrion/benches/zk_proofs.rs create mode 100644 synedrion/src/private_benches.rs diff --git a/Cargo.lock b/Cargo.lock index 1e0f74ab..97b18d5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1148,6 +1148,12 @@ dependencies = [ "rand_core", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "spki" version = "0.7.3" @@ -1204,6 +1210,7 @@ dependencies = [ "test-log", "tokio", "tracing", + "tracing-subscriber", "zeroize", ] @@ -1304,6 +1311,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", ] [[package]] @@ -1317,9 +1336,11 @@ dependencies = [ "once_cell", "regex", "sharded-slab", + "smallvec", "thread_local", "tracing", "tracing-core", + "tracing-log", ] [[package]] @@ -1346,6 +1367,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" version = "0.9.5" diff --git a/synedrion/Cargo.toml b/synedrion/Cargo.toml index c08706c3..f7dd9112 100644 --- a/synedrion/Cargo.toml +++ b/synedrion/Cargo.toml @@ -40,6 +40,7 @@ serde = { version = "1", default-features = false, features = ["derive"] } serde-encoded-bytes = { version = "0.1", default-features = false, features = ["hex", "base64"] } bincode = { version = "2.0.0-rc.3", default-features = false, features = ["serde", "alloc"] } displaydoc = { version = "0.2", default-features = false } +criterion = { version = "0.5", optional = true } [dev-dependencies] manul = { git = "https://github.com/entropyxyz/manul.git", rev = "f4c9515eaeb97a17ab3eef908b73be6159f7d9d2", features = ["dev"] } @@ -51,9 +52,19 @@ k256 = { version = "0.13", default-features = false, features = ["ecdsa", "arith impls = "1" hex = { version = "0.4", default-features = false, features = ["alloc"] } test-log = { version = "0.2.16", default-features = false, features = ["trace", "color"] } +tracing-subscriber = "0.3.19" + +[features] +private_benches = ["criterion"] [[bench]] bench = true name = "bench" harness = false -path = "benches/bench.rs" + + +[[bench]] +bench = true +name = "zk_proofs" +harness = false +required-features = ["private_benches"] diff --git a/synedrion/benches/zk_proofs.rs b/synedrion/benches/zk_proofs.rs new file mode 100644 index 00000000..2e97dfc0 --- /dev/null +++ b/synedrion/benches/zk_proofs.rs @@ -0,0 +1,158 @@ +#[cfg(feature = "private_benches")] +mod bench { + use criterion::{criterion_group, Criterion}; + use rand::SeedableRng; + use synedrion::private_benches::*; + use tracing_subscriber::EnvFilter; + + fn bench_aff_g(c: &mut Criterion) { + use aff_g_proof::*; + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + let mut group = c.benchmark_group("AffG proof"); + group.sample_size(10); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("prove", aff_g_proof_prove(rng)); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("verify", aff_g_proof_verify(rng)); + } + + fn bench_aff_g_star(c: &mut Criterion) { + use aff_g_star_proof::*; + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + let mut group = c.benchmark_group("AffG* proof"); + group.sample_size(10); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("prove", aff_g_star_proof_prove(rng)); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("verify", aff_g_star_proof_verify(rng)); + } + + fn bench_dec(c: &mut Criterion) { + use dec_proof::*; + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + let mut group = c.benchmark_group("Dec proof"); + group.sample_size(10); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("prove", dec_proof_prove(rng)); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("verify", dec_proof_verify(rng)); + } + + fn bench_elog(c: &mut Criterion) { + use elog_proof::*; + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + let mut group = c.benchmark_group("Elog proof"); + group.sample_size(10); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("prove", elog_proof_prove(rng)); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("verify", elog_proof_verify(rng)); + } + + fn bench_enc_elg(c: &mut Criterion) { + use enc_elg_proof::*; + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + let mut group = c.benchmark_group("EncElg proof"); + group.sample_size(10); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("prove", enc_elg_proof_prove(rng)); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("verify", enc_elg_proof_verify(rng)); + } + + fn bench_fac(c: &mut Criterion) { + use fac_proof::*; + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + + let mut group = c.benchmark_group("Fac proof"); + group.sample_size(10); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("prove", fac_proof_prove(rng)); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("verify", fac_proof_verify(rng)); + } + + fn bench_paillier_blum_modulus(c: &mut Criterion) { + use paillier_blum_modulus_proof::*; + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + let mut group = c.benchmark_group("Paillier-Blum modulus proof"); + group.sample_size(10); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("prove", paillier_blum_modulus_proof_prove(rng)); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("verify", paillier_blum_modulus_proof_verify(rng)); + } + + fn bench_prm(c: &mut Criterion) { + use prm_proof::*; + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + let mut group = c.benchmark_group("Pedersen Ring params (prm) proof"); + group.sample_size(10); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("prove", prm_proof_prove(rng)); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("verify", prm_proof_verify(rng)); + } + + fn bench_sch(c: &mut Criterion) { + use sch_proof::*; + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + let mut group = c.benchmark_group("Schnorr (sch) proof"); + group.sample_size(10); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("prove", sch_proof_prove(rng)); + + let rng = rand_chacha::ChaCha8Rng::seed_from_u64(1234567890); + group.bench_function("verify", sch_proof_verify(rng)); + } + + criterion_group!( + benches, + bench_aff_g, + bench_aff_g_star, + bench_dec, + bench_elog, + bench_enc_elg, + bench_fac, + bench_paillier_blum_modulus, + bench_prm, + bench_sch + ); +} + +criterion::criterion_main!(bench::benches); diff --git a/synedrion/src/cggmp21.rs b/synedrion/src/cggmp21.rs index f68e0e8a..77420771 100644 --- a/synedrion/src/cggmp21.rs +++ b/synedrion/src/cggmp21.rs @@ -8,13 +8,13 @@ //! refers to the version of the paper published at mod aux_gen; -mod conversion; +pub(crate) mod conversion; mod entities; mod interactive_signing; mod key_init; mod key_refresh; mod params; -mod sigma; +pub(crate) mod sigma; #[cfg(test)] mod aux_gen_tests; @@ -30,9 +30,13 @@ mod key_refresh_tests; pub use aux_gen::{AuxGen, AuxGenAssociatedData, AuxGenProtocol}; pub use entities::{AuxInfo, KeyShare, KeyShareChange}; + pub use interactive_signing::{ InteractiveSigning, InteractiveSigningAssociatedData, InteractiveSigningProtocol, PrehashedMessage, }; pub use key_init::{KeyInit, KeyInitAssociatedData, KeyInitProtocol}; pub use key_refresh::{KeyRefresh, KeyRefreshAssociatedData, KeyRefreshProtocol}; pub use params::{ProductionParams112, SchemeParams, TestParams}; + +#[cfg(feature = "private_benches")] +pub(crate) use params::PaillierProduction112; diff --git a/synedrion/src/cggmp21/sigma/aff_g.rs b/synedrion/src/cggmp21/sigma/aff_g.rs index 9e9be192..e99c48ed 100644 --- a/synedrion/src/cggmp21/sigma/aff_g.rs +++ b/synedrion/src/cggmp21/sigma/aff_g.rs @@ -256,6 +256,7 @@ impl AffGProof

{ #[cfg(test)] mod tests { + use manul::{dev::BinaryFormat, session::WireFormat}; use rand_core::OsRng; use super::{AffGProof, AffGPublicInputs, AffGSecretInputs}; @@ -311,6 +312,15 @@ mod tests { &rp_params, &aux, ); + + // Roundtrip works + let res = BinaryFormat::serialize(proof); + assert!(res.is_ok()); + let payload = res.unwrap(); + let proof: AffGProof = BinaryFormat::deserialize(&payload).unwrap(); + + let rp_params = rp_params.to_wire().to_precomputed(); + assert!(proof.verify( AffGPublicInputs { pk0, diff --git a/synedrion/src/cggmp21/sigma/dec.rs b/synedrion/src/cggmp21/sigma/dec.rs index ab47ad97..68125452 100644 --- a/synedrion/src/cggmp21/sigma/dec.rs +++ b/synedrion/src/cggmp21/sigma/dec.rs @@ -254,6 +254,7 @@ impl DecProof

{ #[cfg(test)] mod tests { + use manul::{dev::BinaryFormat, session::WireFormat}; use rand_core::OsRng; use super::{DecProof, DecPublicInputs, DecSecretInputs}; @@ -311,6 +312,14 @@ mod tests { &setup, &aux, ); + + // Roundtrip works + let res = BinaryFormat::serialize(proof); + assert!(res.is_ok()); + let payload = res.unwrap(); + let proof: DecProof = BinaryFormat::deserialize(&payload).unwrap(); + let rp_params = setup.to_wire().to_precomputed(); + assert!(proof.verify( DecPublicInputs { pk0: pk, @@ -320,7 +329,7 @@ mod tests { cap_s: &cap_s, cap_g: &cap_g }, - &setup, + &rp_params, &aux )); } diff --git a/synedrion/src/cggmp21/sigma/fac.rs b/synedrion/src/cggmp21/sigma/fac.rs index 95b1bc3c..0e291bf9 100644 --- a/synedrion/src/cggmp21/sigma/fac.rs +++ b/synedrion/src/cggmp21/sigma/fac.rs @@ -200,6 +200,7 @@ impl FacProof

{ #[cfg(test)] mod tests { + use manul::{dev::BinaryFormat, session::WireFormat}; use rand_core::OsRng; use super::FacProof; @@ -221,6 +222,15 @@ mod tests { let aux: &[u8] = b"abcde"; let proof = FacProof::::new(&mut OsRng, &sk, &setup, &aux); - assert!(proof.verify(pk, &setup, &aux)); + + // Roundtrip works + let res = BinaryFormat::serialize(proof); + assert!(res.is_ok()); + let payload = res.unwrap(); + let proof: FacProof = BinaryFormat::deserialize(&payload).unwrap(); + + let rp_params = setup.to_wire().to_precomputed(); + let pubkey = pk.clone().into_wire().into_precomputed(); + assert!(proof.verify(&pubkey, &rp_params, &aux)); } } diff --git a/synedrion/src/cggmp21/sigma/mod_.rs b/synedrion/src/cggmp21/sigma/mod_.rs index 306e61d0..4ab20507 100644 --- a/synedrion/src/cggmp21/sigma/mod_.rs +++ b/synedrion/src/cggmp21/sigma/mod_.rs @@ -201,6 +201,7 @@ impl ModProof

{ #[cfg(test)] mod tests { + use manul::{dev::BinaryFormat, session::WireFormat}; use rand_core::OsRng; use super::ModProof; @@ -220,6 +221,13 @@ mod tests { let aux: &[u8] = b"abcde"; let proof = ModProof::::new(&mut OsRng, &sk, &aux); + + // Roundtrip works + let res = BinaryFormat::serialize(proof); + assert!(res.is_ok()); + let payload = res.unwrap(); + let proof: ModProof = BinaryFormat::deserialize(&payload).unwrap(); + assert!(proof.verify(pk, &aux)); } } diff --git a/synedrion/src/cggmp21/sigma/prm.rs b/synedrion/src/cggmp21/sigma/prm.rs index f61ffbfa..4affd403 100644 --- a/synedrion/src/cggmp21/sigma/prm.rs +++ b/synedrion/src/cggmp21/sigma/prm.rs @@ -131,6 +131,7 @@ impl PrmProof

{ #[cfg(test)] mod tests { + use manul::{dev::BinaryFormat, session::WireFormat}; use rand_core::OsRng; use super::PrmProof; @@ -149,6 +150,13 @@ mod tests { let aux: &[u8] = b"abcde"; let proof = PrmProof::::new(&mut OsRng, &secret, &setup, &aux); + + // Roundtrip works + let res = BinaryFormat::serialize(proof); + assert!(res.is_ok()); + let payload = res.unwrap(); + let proof: PrmProof = BinaryFormat::deserialize(&payload).unwrap(); + assert!(proof.verify(&setup, &aux)); } } diff --git a/synedrion/src/cggmp21/sigma/sch.rs b/synedrion/src/cggmp21/sigma/sch.rs index 25440513..5e47f01c 100644 --- a/synedrion/src/cggmp21/sigma/sch.rs +++ b/synedrion/src/cggmp21/sigma/sch.rs @@ -81,6 +81,7 @@ impl SchProof { #[cfg(test)] mod tests { + use manul::{dev::BinaryFormat, session::WireFormat}; use rand_core::OsRng; use super::{SchCommitment, SchProof, SchSecret}; @@ -95,6 +96,13 @@ mod tests { let proof_secret = SchSecret::random(&mut OsRng); let commitment = SchCommitment::new(&proof_secret); let proof = SchProof::new(&proof_secret, &secret, &commitment, &public, &aux); + + // Roundtrip works + let res = BinaryFormat::serialize(proof); + assert!(res.is_ok()); + let payload = res.unwrap(); + let proof: SchProof = BinaryFormat::deserialize(&payload).unwrap(); + assert!(proof.verify(&commitment, &public, &aux)); } } diff --git a/synedrion/src/lib.rs b/synedrion/src/lib.rs index bd6bf39a..1623877a 100644 --- a/synedrion/src/lib.rs +++ b/synedrion/src/lib.rs @@ -35,3 +35,8 @@ pub use cggmp21::{ }; pub use curve::RecoverableSignature; pub use www02::{DeriveChildKey, KeyResharing, KeyResharingProtocol, NewHolder, OldHolder, ThresholdKeyShare}; + +#[cfg(feature = "private_benches")] +#[allow(missing_docs)] +// Hack to expose internals for benchmarking purposes +pub mod private_benches; diff --git a/synedrion/src/paillier/encryption.rs b/synedrion/src/paillier/encryption.rs index a4660930..3cbf47f6 100644 --- a/synedrion/src/paillier/encryption.rs +++ b/synedrion/src/paillier/encryption.rs @@ -186,7 +186,7 @@ impl Ciphertext

{ } /// Encrypts the plaintext with a random randomizer. - #[cfg(test)] + #[cfg(any(test, feature = "private_benches"))] pub fn new(rng: &mut impl CryptoRngCore, pk: &PublicKeyPaillier

, plaintext: &SecretSigned) -> Self { Self::new_with_randomizer(pk, plaintext, &Randomizer::random(rng, pk)) } diff --git a/synedrion/src/private_benches.rs b/synedrion/src/private_benches.rs new file mode 100644 index 00000000..9401ed4c --- /dev/null +++ b/synedrion/src/private_benches.rs @@ -0,0 +1,783 @@ +use criterion::{black_box, BatchSize, Bencher}; +use rand_core::CryptoRngCore; + +use crate::{ + cggmp21::{ + conversion::secret_scalar_from_signed, + sigma::{ + AffGProof, AffGPublicInputs, AffGSecretInputs, DecProof, DecPublicInputs, DecSecretInputs, FacProof, + ModProof, PrmProof, SchCommitment, SchProof, SchSecret, + }, + PaillierProduction112, ProductionParams112, + }, + curve::{Point, Scalar}, + paillier::{Ciphertext, PaillierParams, PublicKeyPaillier, RPParams, RPSecret, Randomizer, SecretKeyPaillierWire}, + tools::Secret, + uint::SecretSigned, + SchemeParams, +}; + +type Params = ProductionParams112; +type Paillier = ::Paillier; +type PUint = <::Paillier as PaillierParams>::Uint; + +pub mod fac_proof { + use super::*; + + /// Benchmark Fac-proof construction + pub fn fac_proof_prove(mut rng: R) -> impl FnMut(&mut Bencher<'_>) { + let mut rng2 = rng.clone(); + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let sk = SecretKeyPaillierWire::::random(&mut rng).into_precomputed(); + + let setup = RPParams::random(&mut rng); + + let aux: &[u8] = b"abcde"; + (sk, setup, aux) + }, + |(sk, setup, aux)| black_box(FacProof::::new(&mut rng2, &sk, &setup, &aux)), + BatchSize::SmallInput, + ); + } + } + + /// Benchmark Fac-proof verification + pub fn fac_proof_verify(mut rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let sk = SecretKeyPaillierWire::::random(&mut rng).into_precomputed(); + + let setup = RPParams::random(&mut rng); + + let aux: &[u8] = b"abcde"; + let proof = FacProof::::new(&mut rng, &sk, &setup, &aux); + (proof, sk.public_key().clone(), setup, aux) + }, + |(proof, pk0, setup, aux): ( + FacProof, + PublicKeyPaillier, + RPParams, + &[u8], + )| { + proof.verify(&pk0, &setup, &aux); + }, + BatchSize::SmallInput, + ); + } + } +} + +pub mod aff_g_proof { + use super::*; + + #[allow(clippy::type_complexity)] + fn proof_inputs( + mut rng: impl CryptoRngCore + 'static, + ) -> ( + (impl CryptoRngCore + 'static), + SecretSigned, + SecretSigned, + Randomizer, + Randomizer, + PublicKeyPaillier, + PublicKeyPaillier, + Ciphertext, + Ciphertext, + Ciphertext, + Point, + RPParams, + &'static [u8], + ) { + let sk0 = SecretKeyPaillierWire::::random(&mut rng).into_precomputed(); + let pk0 = sk0.public_key().clone(); + + let sk1 = SecretKeyPaillierWire::::random(&mut rng).into_precomputed(); + let pk1 = sk1.public_key().clone(); + + let rp_params = RPParams::random(&mut rng); + + let aux: &[u8] = b"abcde"; + + let x = SecretSigned::random_in_exponent_range(&mut rng, Params::L_BOUND); + let y = SecretSigned::random_in_exponent_range(&mut rng, Params::LP_BOUND); + + let rho = Randomizer::random(&mut rng, &pk0); + let rho_y = Randomizer::random(&mut rng, &pk1); + let secret = SecretSigned::random_in_exponent_range(&mut rng, Params::L_BOUND); + let cap_c = Ciphertext::new_with_randomizer(&pk0, &secret, &Randomizer::random(&mut rng, &pk0)); + let cap_d = &cap_c * &x + Ciphertext::new_with_randomizer(&pk0, &-&y, &rho); + let cap_y = Ciphertext::new_with_randomizer(&pk1, &y, &rho_y); + let cap_x = secret_scalar_from_signed::(&x).mul_by_generator(); + + ( + rng, x, y, rho, rho_y, pk0, pk1, cap_c, cap_d, cap_y, cap_x, rp_params, aux, + ) + } + + pub fn aff_g_proof_prove(rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let rng2 = rng.clone(); + proof_inputs(rng2) + }, + |(mut rng, x, y, rho, rho_y, pk0, pk1, cap_c, cap_d, cap_y, cap_x, rp_params, aux)| { + black_box(AffGProof::::new( + &mut rng, + AffGSecretInputs { + x: &x, + y: &y, + rho: &rho, + rho_y: &rho_y, + }, + AffGPublicInputs { + pk0: &pk0, + pk1: &pk1, + cap_c: &cap_c, + cap_d: &cap_d, + cap_y: &cap_y, + cap_x: &cap_x, + }, + &rp_params, + &aux, + )) + }, + BatchSize::SmallInput, + ); + } + } + pub fn aff_g_proof_verify(mut rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let (_, x, y, rho, rho_y, pk0, pk1, cap_c, cap_d, cap_y, cap_x, rp_params, aux) = + proof_inputs(rng.clone()); + + let pub_inputs = AffGPublicInputs { + pk0: &pk0, + pk1: &pk1, + cap_c: &cap_c, + cap_d: &cap_d, + cap_y: &cap_y, + cap_x: &cap_x, + }; + + let proof = AffGProof::::new( + &mut rng, + AffGSecretInputs { + x: &x, + y: &y, + rho: &rho, + rho_y: &rho_y, + }, + pub_inputs, + &rp_params, + b"abcde", + ); + + let inputs = ( + pk0.clone(), + pk1.clone(), + cap_c.clone(), + cap_d.clone(), + cap_y.clone(), + cap_x, + ); + let rp_params2 = rp_params.clone(); + (proof, inputs, rp_params2, aux) + }, + |(proof, inputs, rp_params, aux)| { + let pub_inputs = AffGPublicInputs { + pk0: &inputs.0, + pk1: &inputs.1, + cap_c: &inputs.2, + cap_d: &inputs.3, + cap_y: &inputs.4, + cap_x: &inputs.5, + }; + + black_box(proof.verify(pub_inputs, &rp_params, &aux)) + }, + BatchSize::SmallInput, + ); + } + } +} + +pub mod aff_g_star_proof { + use crate::cggmp21::sigma::{AffGStarProof, AffGStarPublicInputs, AffGStarSecretInputs}; + + use super::*; + + #[allow(clippy::type_complexity)] + fn proof_input( + mut rng: impl CryptoRngCore, + ) -> ( + impl CryptoRngCore, + SecretSigned, + SecretSigned, + Randomizer, + Randomizer, + PublicKeyPaillier, + PublicKeyPaillier, + Ciphertext, + Ciphertext, + Ciphertext, + Point, + &'static [u8], + ) { + let sk0 = SecretKeyPaillierWire::::random(&mut rng).into_precomputed(); + let pk0 = sk0.public_key(); + + let sk1 = SecretKeyPaillierWire::::random(&mut rng).into_precomputed(); + let pk1 = sk1.public_key(); + + let x = SecretSigned::random_in_exponent_range(&mut rng, Params::L_BOUND); + let y = SecretSigned::random_in_exponent_range(&mut rng, Params::LP_BOUND); + let rho = Randomizer::random(&mut rng, pk0); + let mu = Randomizer::random(&mut rng, pk1); + + let secret = SecretSigned::random_in_exponent_range(&mut rng, Params::L_BOUND); + let cap_c = Ciphertext::new(&mut rng, pk0, &secret); + + let cap_d = &cap_c * &x + Ciphertext::new_with_randomizer(pk0, &-&y, &rho); + let cap_y = Ciphertext::new_with_randomizer(pk1, &y, &mu); + let cap_x = secret_scalar_from_signed::(&x).mul_by_generator(); + + ( + rng, + x, + y, + rho, + mu, + pk0.clone(), + pk1.clone(), + cap_c, + cap_d, + cap_y, + cap_x, + b"abcde", + ) + } + + pub fn aff_g_star_proof_prove(rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || proof_input(rng.clone()), + |(mut rng, x, y, rho, mu, pk0, pk1, cap_c, cap_d, cap_y, cap_x, aux)| { + black_box(AffGStarProof::::new( + &mut rng, + AffGStarSecretInputs { + x: &x, + y: &y, + rho: &rho, + mu: &mu, + }, + AffGStarPublicInputs { + pk0: &pk0, + pk1: &pk1, + cap_c: &cap_c, + cap_d: &cap_d, + cap_y: &cap_y, + cap_x: &cap_x, + }, + &aux, + )) + }, + BatchSize::SmallInput, + ); + } + } + pub fn aff_g_star_proof_verify(rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let (mut rng, x, y, rho, mu, pk0, pk1, cap_c, cap_d, cap_y, cap_x, aux) = proof_input(rng.clone()); + let proof = AffGStarProof::::new( + &mut rng, + AffGStarSecretInputs { + x: &x, + y: &y, + rho: &rho, + mu: &mu, + }, + AffGStarPublicInputs { + pk0: &pk0, + pk1: &pk1, + cap_c: &cap_c, + cap_d: &cap_d, + cap_y: &cap_y, + cap_x: &cap_x, + }, + &aux, + ); + (proof, pk0, pk1, cap_c, cap_d, cap_y, cap_x, aux) + }, + |(proof, pk0, pk1, cap_c, cap_d, cap_y, cap_x, aux)| { + black_box(proof.verify( + AffGStarPublicInputs { + pk0: &pk0, + pk1: &pk1, + cap_c: &cap_c, + cap_d: &cap_d, + cap_y: &cap_y, + cap_x: &cap_x, + }, + &aux, + )) + }, + BatchSize::SmallInput, + ); + } + } +} + +pub mod dec_proof { + use super::*; + + #[allow(clippy::type_complexity)] + fn proof_input( + mut rng: impl CryptoRngCore, + ) -> ( + impl CryptoRngCore, + SecretSigned, + SecretSigned, + Randomizer, + PublicKeyPaillier, + Ciphertext, + Point, + Ciphertext, + Point, + Point, + RPParams, + &'static [u8], + ) { + let sk = SecretKeyPaillierWire::::random(&mut rng).into_precomputed(); + let pk = sk.public_key(); + + let setup = RPParams::random(&mut rng); + let aux: &[u8] = b"abcde"; + + let x = SecretSigned::random_in_exponent_range(&mut rng, Params::L_BOUND); + let y = SecretSigned::random_in_exponent_range(&mut rng, Params::LP_BOUND); + let rho = Randomizer::random(&mut rng, pk); + + let k = SecretSigned::random_in_exponent_range(&mut rng, Paillier::PRIME_BITS * 2 - 1); + let cap_k = Ciphertext::new(&mut rng, pk, &k); + let cap_d = Ciphertext::new_with_randomizer(pk, &y, &rho) + &cap_k * &-&x; + + let cap_x = secret_scalar_from_signed::(&x).mul_by_generator(); + + let cap_g = Scalar::random(&mut rng).mul_by_generator(); + let cap_s = cap_g * secret_scalar_from_signed::(&y); + + ( + rng, + x, + y, + rho, + pk.clone(), + cap_k, + cap_x, + cap_d, + cap_s, + cap_g, + setup, + aux, + ) + } + + pub fn dec_proof_prove(rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || proof_input(rng.clone()), + |(mut rng, x, y, rho, pk, cap_k, cap_x, cap_d, cap_s, cap_g, setup, aux)| { + black_box(DecProof::::new( + &mut rng, + DecSecretInputs { + x: &x, + y: &y, + rho: &rho, + }, + DecPublicInputs { + pk0: &pk, + cap_k: &cap_k, + cap_x: &cap_x, + cap_d: &cap_d, + cap_s: &cap_s, + cap_g: &cap_g, + }, + &setup, + &aux, + )) + }, + BatchSize::SmallInput, + ); + } + } + + pub fn dec_proof_verify(rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let (mut rng, x, y, rho, pk, cap_k, cap_x, cap_d, cap_s, cap_g, setup, aux) = + proof_input(rng.clone()); + + let proof = DecProof::::new( + &mut rng, + DecSecretInputs { + x: &x, + y: &y, + rho: &rho, + }, + DecPublicInputs { + pk0: &pk, + cap_k: &cap_k, + cap_x: &cap_x, + cap_d: &cap_d, + cap_s: &cap_s, + cap_g: &cap_g, + }, + &setup, + &aux, + ); + (proof, pk, cap_k, cap_x, cap_d, cap_s, cap_g, setup) + }, + |(proof, pk, cap_k, cap_x, cap_d, cap_s, cap_g, rp_params)| { + let pub_inputs = DecPublicInputs { + pk0: &pk, + cap_k: &cap_k, + cap_x: &cap_x, + cap_d: &cap_d, + cap_s: &cap_s, + cap_g: &cap_g, + }; + black_box(proof.verify(pub_inputs, &rp_params, b"abcde")); + }, + BatchSize::SmallInput, + ); + } + } +} + +pub mod elog_proof { + use crate::cggmp21::sigma::{ElogProof, ElogPublicInputs, ElogSecretInputs}; + + use super::*; + pub fn elog_proof_prove(mut rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let y = Secret::init_with(|| Scalar::random(&mut rng)); + let lambda = Secret::init_with(|| Scalar::random(&mut rng)); + + let cap_l = lambda.mul_by_generator(); + let cap_x = Scalar::random(&mut rng).mul_by_generator(); + let cap_m = y.mul_by_generator() + cap_x * λ + let h = Scalar::random(&mut rng).mul_by_generator(); + let cap_y = h * &y; + (rng.clone(), y, lambda, cap_l, cap_m, cap_x, cap_y, h, b"abcde") + }, + |(mut rng, y, lambda, cap_l, cap_m, cap_x, cap_y, h, aux)| { + black_box(ElogProof::::new( + &mut rng, + ElogSecretInputs { y: &y, lambda: &lambda }, + ElogPublicInputs { + cap_l: &cap_l, + cap_m: &cap_m, + cap_x: &cap_x, + cap_y: &cap_y, + h: &h, + }, + &aux, + )) + }, + BatchSize::SmallInput, + ); + } + } + pub fn elog_proof_verify(mut rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let y = Secret::init_with(|| Scalar::random(&mut rng)); + let lambda = Secret::init_with(|| Scalar::random(&mut rng)); + + let cap_l = lambda.mul_by_generator(); + let cap_x = Scalar::random(&mut rng).mul_by_generator(); + let cap_m = y.mul_by_generator() + cap_x * λ + let h = Scalar::random(&mut rng).mul_by_generator(); + let cap_y = h * &y; + let proof = ElogProof::::new( + &mut rng, + ElogSecretInputs { y: &y, lambda: &lambda }, + ElogPublicInputs { + cap_l: &cap_l, + cap_m: &cap_m, + cap_x: &cap_x, + cap_y: &cap_y, + h: &h, + }, + b"abcde", + ); + (proof, cap_l, cap_m, cap_x, cap_y, h, b"abcde") + }, + |(proof, cap_l, cap_m, cap_x, cap_y, h, aux)| { + black_box(proof.verify( + ElogPublicInputs { + cap_l: &cap_l, + cap_m: &cap_m, + cap_x: &cap_x, + cap_y: &cap_y, + h: &h, + }, + &aux, + )) + }, + BatchSize::SmallInput, + ); + } + } +} + +pub mod enc_elg_proof { + use crate::cggmp21::sigma::{EncElgProof, EncElgPublicInputs, EncElgSecretInputs}; + + use super::*; + pub fn enc_elg_proof_prove(mut rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let sk = SecretKeyPaillierWire::::random(&mut rng).into_precomputed(); + let pk = sk.public_key(); + + let setup = RPParams::random(&mut rng); + + let aux: &[u8] = b"abcde"; + + let x = SecretSigned::random_in_exponent_range(&mut rng, Params::L_BOUND); + let rho = Randomizer::random(&mut rng, pk); + let a = Secret::init_with(|| Scalar::random(&mut rng)); + let b = Secret::init_with(|| Scalar::random(&mut rng)); + + let cap_c = Ciphertext::new_with_randomizer(pk, &x, &rho); + let cap_a = a.mul_by_generator(); + let cap_b = b.mul_by_generator(); + let cap_x = (&a * &b + secret_scalar_from_signed::(&x)).mul_by_generator(); + + ( + rng.clone(), + x, + rho, + b, + pk.clone(), + cap_c, + cap_a, + cap_b, + cap_x, + setup, + aux, + ) + }, + |(mut rng, x, rho, b, pk, cap_c, cap_a, cap_b, cap_x, setup, aux)| { + black_box(EncElgProof::::new( + &mut rng, + EncElgSecretInputs { + x: &x, + rho: &rho, + b: &b, + }, + EncElgPublicInputs { + pk0: &pk, + cap_c: &cap_c, + cap_a: &cap_a, + cap_b: &cap_b, + cap_x: &cap_x, + }, + &setup, + &aux, + )) + }, + BatchSize::SmallInput, + ); + } + } + pub fn enc_elg_proof_verify(mut rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let sk = SecretKeyPaillierWire::::random(&mut rng).into_precomputed(); + let pk = sk.public_key(); + + let setup = RPParams::random(&mut rng); + + let aux: &[u8] = b"abcde"; + + let x = SecretSigned::random_in_exponent_range(&mut rng, Params::L_BOUND); + let rho = Randomizer::random(&mut rng, pk); + let a = Secret::init_with(|| Scalar::random(&mut rng)); + let b = Secret::init_with(|| Scalar::random(&mut rng)); + + let cap_c = Ciphertext::new_with_randomizer(pk, &x, &rho); + let cap_a = a.mul_by_generator(); + let cap_b = b.mul_by_generator(); + let cap_x = (&a * &b + secret_scalar_from_signed::(&x)).mul_by_generator(); + + let proof = EncElgProof::::new( + &mut rng, + EncElgSecretInputs { + x: &x, + rho: &rho, + b: &b, + }, + EncElgPublicInputs { + pk0: pk, + cap_c: &cap_c, + cap_a: &cap_a, + cap_b: &cap_b, + cap_x: &cap_x, + }, + &setup, + &aux, + ); + (proof, pk.clone(), cap_c, cap_a, cap_b, cap_x, setup, aux) + }, + |(proof, pk, cap_c, cap_a, cap_b, cap_x, setup, aux)| { + black_box(proof.verify( + EncElgPublicInputs { + pk0: &pk, + cap_c: &cap_c, + cap_a: &cap_a, + cap_b: &cap_b, + cap_x: &cap_x, + }, + &setup, + &aux, + )) + }, + BatchSize::SmallInput, + ); + } + } +} + +pub mod paillier_blum_modulus_proof { + use super::*; + pub fn paillier_blum_modulus_proof_prove( + mut rng: R, + ) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let sk = SecretKeyPaillierWire::::random(&mut rng).into_precomputed(); + let aux: &[u8] = b"abcde"; + + (rng.clone(), sk, aux) + }, + |(mut rng, sk, aux)| black_box(ModProof::::new(&mut rng, &sk, &aux)), + BatchSize::SmallInput, + ); + } + } + + pub fn paillier_blum_modulus_proof_verify( + mut rng: R, + ) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let sk = SecretKeyPaillierWire::::random(&mut rng).into_precomputed(); + let aux: &[u8] = b"abcde"; + let proof = ModProof::::new(&mut rng, &sk, &aux); + (proof, sk.public_key().clone(), aux) + }, + |(proof, pk, aux)| black_box(proof.verify(&pk, &aux)), + BatchSize::SmallInput, + ); + } + } +} + +pub mod prm_proof { + use super::*; + + pub fn prm_proof_prove(mut rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let secret = RPSecret::random(&mut rng); + let setup = RPParams::random_with_secret(&mut rng, &secret); + + let aux: &[u8] = b"abcde"; + + (rng.clone(), secret, setup, aux) + }, + |(mut rng, secret, setup, aux)| black_box(PrmProof::::new(&mut rng, &secret, &setup, &aux)), + BatchSize::SmallInput, + ); + } + } + + pub fn prm_proof_verify(mut rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let secret = RPSecret::random(&mut rng); + let setup = RPParams::random_with_secret(&mut rng, &secret); + + let aux: &[u8] = b"abcde"; + let proof = PrmProof::::new(&mut rng, &secret, &setup, &aux); + (proof, setup, aux) + }, + |(proof, setup, aux)| black_box(proof.verify(&setup, &aux)), + BatchSize::SmallInput, + ); + } + } +} + +pub mod sch_proof { + use super::*; + + pub fn sch_proof_prove(mut rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let secret = Secret::init_with(|| Scalar::random(&mut rng)); + let public = secret.mul_by_generator(); + let aux: &[u8] = b"abcde"; + + let proof_secret = SchSecret::random(&mut rng); + let commitment = SchCommitment::new(&proof_secret); + (proof_secret, secret, commitment, public, aux) + }, + |(proof_secret, secret, commitment, public, aux)| { + black_box(SchProof::new(&proof_secret, &secret, &commitment, &public, &aux)) + }, + BatchSize::SmallInput, + ); + } + } + + pub fn sch_proof_verify(mut rng: R) -> impl FnMut(&mut Bencher<'_>) { + move |b: &mut Bencher<'_>| { + b.iter_batched( + || { + let secret = Secret::init_with(|| Scalar::random(&mut rng)); + let public = secret.mul_by_generator(); + let aux: &[u8] = b"abcde"; + + let proof_secret = SchSecret::random(&mut rng); + let commitment = SchCommitment::new(&proof_secret); + let proof = SchProof::new(&proof_secret, &secret, &commitment, &public, &aux); + (proof, commitment, public, aux) + }, + |(proof, commitment, public, aux)| black_box(proof.verify(&commitment, &public, &aux)), + BatchSize::SmallInput, + ); + } + } +} diff --git a/synedrion/src/uint/public_signed.rs b/synedrion/src/uint/public_signed.rs index f9f5ba1e..74a775e3 100644 --- a/synedrion/src/uint/public_signed.rs +++ b/synedrion/src/uint/public_signed.rs @@ -26,7 +26,7 @@ where { fn from(val: PublicSigned) -> Self { let repr = val.abs().to_be_bytes(); - let bound_bytes = (val.bound + 7) / 8; + let bound_bytes = val.bound.div_ceil(8); let slice = repr .as_ref() .get((repr.as_ref().len() - bound_bytes as usize)..)