From 9d80b65fc7333fba3072e8ba8034e5ca82e5cf12 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 14 May 2024 17:07:33 -0300 Subject: [PATCH 1/5] update zcash_proofs to 0.14 using custom sapling --- Cargo.lock | 160 +++++++++++++++--- zebra-consensus/Cargo.toml | 3 +- zebra-consensus/src/primitives/groth16.rs | 38 ++++- .../src/primitives/groth16/params.rs | 8 +- .../src/primitives/groth16/tests.rs | 33 +++- 5 files changed, 199 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e393f2aad2d..95d24d3e3e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1365,6 +1365,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "equihash" +version = "0.2.0" +source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" +dependencies = [ + "blake2b_simd", + "byteorder", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1400,6 +1409,14 @@ dependencies = [ "blake2b_simd", ] +[[package]] +name = "f4jumble" +version = "0.1.0" +source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" +dependencies = [ + "blake2b_simd", +] + [[package]] name = "fastrand" version = "2.1.0" @@ -3928,6 +3945,37 @@ dependencies = [ "zip32", ] +[[package]] +name = "sapling-crypto" +version = "0.1.3" +source = "git+https://github.com/oxarbitrage/sapling-crypto?branch=add-verifying-key-methods#f93fd95314994010006a8b9dea7e4b5b54f26b52" +dependencies = [ + "aes", + "bellman", + "bitvec", + "blake2b_simd", + "blake2s_simd", + "bls12_381", + "byteorder", + "document-features", + "ff", + "fpe", + "group", + "hex", + "incrementalmerkletree", + "jubjub", + "lazy_static", + "memuse", + "rand 0.8.5", + "rand_core 0.6.4", + "redjubjub", + "subtle", + "tracing", + "zcash_note_encryption", + "zcash_spec", + "zip32", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -5728,6 +5776,17 @@ version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" +[[package]] +name = "zcash_address" +version = "0.3.1" +source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" +dependencies = [ + "bech32", + "bs58", + "f4jumble 0.1.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", + "zcash_encoding 0.2.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", +] + [[package]] name = "zcash_address" version = "0.3.2" @@ -5736,8 +5795,8 @@ checksum = "827c17a1f7e3a69f0d44e991ff610c7a842228afdc9dc2325ffdd1a67fee01e9" dependencies = [ "bech32", "bs58", - "f4jumble", - "zcash_encoding", + "f4jumble 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_protocol", ] @@ -5768,8 +5827,8 @@ dependencies = [ "tonic-build 0.10.2", "tracing", "which", - "zcash_address", - "zcash_encoding", + "zcash_address 0.3.2", + "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_note_encryption", "zcash_primitives 0.13.0", ] @@ -5784,6 +5843,15 @@ dependencies = [ "nonempty", ] +[[package]] +name = "zcash_encoding" +version = "0.2.0" +source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" +dependencies = [ + "byteorder", + "nonempty", +] + [[package]] name = "zcash_history" version = "0.4.0" @@ -5821,7 +5889,7 @@ dependencies = [ "blake2s_simd", "bls12_381", "byteorder", - "equihash", + "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ff", "fpe", "group", @@ -5839,8 +5907,8 @@ dependencies = [ "secp256k1", "sha2", "subtle", - "zcash_address", - "zcash_encoding", + "zcash_address 0.3.2", + "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_note_encryption", ] @@ -5855,7 +5923,7 @@ dependencies = [ "blake2b_simd", "byteorder", "document-features", - "equihash", + "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ff", "fpe", "group", @@ -5870,13 +5938,47 @@ dependencies = [ "rand_core 0.6.4", "redjubjub", "ripemd", - "sapling-crypto", + "sapling-crypto 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "secp256k1", "sha2", "subtle", "tracing", - "zcash_address", - "zcash_encoding", + "zcash_address 0.3.2", + "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_note_encryption", + "zcash_spec", + "zip32", +] + +[[package]] +name = "zcash_primitives" +version = "0.14.0" +source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" +dependencies = [ + "aes", + "bip0039", + "blake2b_simd", + "byteorder", + "document-features", + "equihash 0.2.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", + "ff", + "fpe", + "group", + "hex", + "incrementalmerkletree", + "jubjub", + "memuse", + "nonempty", + "orchard 0.7.1", + "rand 0.8.5", + "rand_core 0.6.4", + "redjubjub", + "sapling-crypto 0.1.3 (git+https://github.com/oxarbitrage/sapling-crypto?branch=add-verifying-key-methods)", + "sha2", + "subtle", + "tracing", + "zcash_address 0.3.1", + "zcash_encoding 0.2.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", "zcash_note_encryption", "zcash_spec", "zip32", @@ -5884,13 +5986,14 @@ dependencies = [ [[package]] name = "zcash_proofs" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0c99f65a840ff256c106b28d67d702d9759d206112473d4982c92003262406" +checksum = "b8a02eb1f151d9b9a6e16408d2c55ff440bd2fb232b7377277146d0fa2df9bc8" dependencies = [ "bellman", "blake2b_simd", "bls12_381", + "document-features", "group", "home", "jubjub", @@ -5898,16 +6001,16 @@ dependencies = [ "lazy_static", "rand_core 0.6.4", "redjubjub", + "sapling-crypto 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", "xdg", - "zcash_primitives 0.13.0", + "zcash_primitives 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "zcash_proofs" version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a02eb1f151d9b9a6e16408d2c55ff440bd2fb232b7377277146d0fa2df9bc8" +source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" dependencies = [ "bellman", "blake2b_simd", @@ -5920,10 +6023,10 @@ dependencies = [ "lazy_static", "rand_core 0.6.4", "redjubjub", - "sapling-crypto", + "sapling-crypto 0.1.3 (git+https://github.com/oxarbitrage/sapling-crypto?branch=add-verifying-key-methods)", "tracing", "xdg", - "zcash_primitives 0.14.0", + "zcash_primitives 0.14.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", ] [[package]] @@ -5964,15 +6067,15 @@ dependencies = [ "rand_core 0.6.4", "rayon", "redjubjub", - "sapling-crypto", + "sapling-crypto 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "subtle", "syn 1.0.109", "tracing", - "zcash_address", - "zcash_encoding", + "zcash_address 0.3.2", + "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_note_encryption", - "zcash_primitives 0.14.0", - "zcash_proofs 0.14.0", + "zcash_primitives 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_proofs 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6001,7 +6104,7 @@ dependencies = [ "criterion", "displaydoc", "ed25519-zebra", - "equihash", + "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures", "group", "halo2_proofs", @@ -6037,9 +6140,9 @@ dependencies = [ "tracing", "uint", "x25519-dalek", - "zcash_address", + "zcash_address 0.3.2", "zcash_client_backend", - "zcash_encoding", + "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_history", "zcash_note_encryption", "zcash_primitives 0.13.0", @@ -6072,6 +6175,7 @@ dependencies = [ "proptest-derive", "rand 0.8.5", "rayon", + "sapling-crypto 0.1.3 (git+https://github.com/oxarbitrage/sapling-crypto?branch=add-verifying-key-methods)", "serde", "spandoc", "thiserror", @@ -6085,7 +6189,7 @@ dependencies = [ "tracing-futures", "tracing-subscriber", "wagyu-zcash-parameters", - "zcash_proofs 0.13.0", + "zcash_proofs 0.14.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", "zebra-chain", "zebra-node-services", "zebra-script", @@ -6190,7 +6294,7 @@ dependencies = [ "tokio", "tower", "tracing", - "zcash_address", + "zcash_address 0.3.2", "zebra-chain", "zebra-consensus", "zebra-network", diff --git a/zebra-consensus/Cargo.toml b/zebra-consensus/Cargo.toml index b2931f1f2e7..5fc276f6eb0 100644 --- a/zebra-consensus/Cargo.toml +++ b/zebra-consensus/Cargo.toml @@ -59,8 +59,9 @@ tracing = "0.1.39" tracing-futures = "0.2.5" orchard = "0.6.0" +sapling = { package = "sapling-crypto", git = "https://github.com/oxarbitrage/sapling-crypto", branch = "add-verifying-key-methods" } -zcash_proofs = { version = "0.13.0-rc.1", features = ["multicore" ] } +zcash_proofs = { package = "zcash_proofs", git = "https://github.com/oxarbitrage/librustzcash", branch = "use-custom-sapling" } wagyu-zcash-parameters = "0.2.0" tower-fallback = { path = "../tower-fallback/", version = "0.2.41-beta.13" } diff --git a/zebra-consensus/src/primitives/groth16.rs b/zebra-consensus/src/primitives/groth16.rs index e2ec64144fb..0c0ebcb8b85 100644 --- a/zebra-consensus/src/primitives/groth16.rs +++ b/zebra-consensus/src/primitives/groth16.rs @@ -68,6 +68,22 @@ pub type BatchVerifyingKey = VerifyingKey; /// This is the key used to verify individual items. pub type ItemVerifyingKey = PreparedVerifyingKey; +lazy_static::lazy_static! { + /// The Sapling Groth16 verifying key for spends. + pub static ref SAPLING_SPEND_VERIFYING_KEY: std::sync::OnceLock> = { + let cell = std::sync::OnceLock::new(); + let _ = cell.set(GROTH16_PARAMETERS.sapling.spend.verifying_key().inner().clone()); + cell + }; + + /// The Sapling Groth16 verifying key for outputs. + pub static ref SAPLING_OUTPUT_VERIFYING_KEY: std::sync::OnceLock> = { + let cell = std::sync::OnceLock::new(); + let _ = cell.set(GROTH16_PARAMETERS.sapling.output.verifying_key().inner().clone()); + cell + }; +} + /// Global batch verification context for Groth16 proofs of Spend statements. /// /// This service transparently batches contemporaneous proof verifications, @@ -84,7 +100,11 @@ pub static SPEND_VERIFIER: Lazy< > = Lazy::new(|| { Fallback::new( Batch::new( - Verifier::new(&GROTH16_PARAMETERS.sapling.spend.vk), + Verifier::new( + SAPLING_SPEND_VERIFYING_KEY + .get() + .expect("Sapling verifying key for spends was set above"), + ), super::MAX_BATCH_SIZE, None, super::MAX_BATCH_LATENCY, @@ -102,7 +122,10 @@ pub static SPEND_VERIFIER: Lazy< (|item: Item| { Verifier::verify_single_spawning( item, - &GROTH16_PARAMETERS.sapling.spend_prepared_verifying_key, + &GROTH16_PARAMETERS + .sapling + .spend_prepared_verifying_key + .inner(), ) .boxed() }) as fn(_) -> _, @@ -126,7 +149,11 @@ pub static OUTPUT_VERIFIER: Lazy< > = Lazy::new(|| { Fallback::new( Batch::new( - Verifier::new(&GROTH16_PARAMETERS.sapling.output.vk), + Verifier::new( + SAPLING_OUTPUT_VERIFYING_KEY + .get() + .expect("Sapling verifying key for outputs was set above"), + ), super::MAX_BATCH_SIZE, None, super::MAX_BATCH_LATENCY, @@ -139,7 +166,10 @@ pub static OUTPUT_VERIFIER: Lazy< (|item: Item| { Verifier::verify_single_spawning( item, - &GROTH16_PARAMETERS.sapling.output_prepared_verifying_key, + &GROTH16_PARAMETERS + .sapling + .output_prepared_verifying_key + .inner(), ) .boxed() }) as fn(_) -> _, diff --git a/zebra-consensus/src/primitives/groth16/params.rs b/zebra-consensus/src/primitives/groth16/params.rs index 3129491d490..58f2c4872df 100644 --- a/zebra-consensus/src/primitives/groth16/params.rs +++ b/zebra-consensus/src/primitives/groth16/params.rs @@ -25,11 +25,11 @@ pub struct Groth16Parameters { /// Groth16 Zero-Knowledge Proof spend and output parameters for the Sapling circuit. pub struct SaplingParameters { - pub spend: groth16::Parameters, - pub spend_prepared_verifying_key: groth16::PreparedVerifyingKey, + pub spend: sapling::circuit::SpendParameters, + pub spend_prepared_verifying_key: sapling::circuit::PreparedSpendVerifyingKey, - pub output: groth16::Parameters, - pub output_prepared_verifying_key: groth16::PreparedVerifyingKey, + pub output: sapling::circuit::OutputParameters, + pub output_prepared_verifying_key: sapling::circuit::PreparedOutputVerifyingKey, } /// Groth16 Zero-Knowledge Proof spend parameters for the Sprout circuit. diff --git a/zebra-consensus/src/primitives/groth16/tests.rs b/zebra-consensus/src/primitives/groth16/tests.rs index 52c00d575a3..8522f267645 100644 --- a/zebra-consensus/src/primitives/groth16/tests.rs +++ b/zebra-consensus/src/primitives/groth16/tests.rs @@ -73,27 +73,41 @@ async fn verify_sapling_groth16() { // Use separate verifiers so shared batch tasks aren't killed when the test ends (#2390) let mut spend_verifier = Fallback::new( Batch::new( - Verifier::new(&GROTH16_PARAMETERS.sapling.spend.vk), + Verifier::new(SAPLING_SPEND_VERIFYING_KEY.get().unwrap()), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, ), tower::service_fn( (|item: Item| { - ready(item.verify_single(&GROTH16_PARAMETERS.sapling.spend_prepared_verifying_key)) + ready( + item.verify_single( + &GROTH16_PARAMETERS + .sapling + .spend_prepared_verifying_key + .inner(), + ), + ) }) as fn(_) -> _, ), ); let mut output_verifier = Fallback::new( Batch::new( - Verifier::new(&GROTH16_PARAMETERS.sapling.output.vk), + Verifier::new(SAPLING_OUTPUT_VERIFYING_KEY.get().unwrap()), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, ), tower::service_fn( (|item: Item| { - ready(item.verify_single(&GROTH16_PARAMETERS.sapling.output_prepared_verifying_key)) + ready( + item.verify_single( + &GROTH16_PARAMETERS + .sapling + .output_prepared_verifying_key + .inner(), + ), + ) }) as fn(_) -> _, ), ); @@ -179,14 +193,21 @@ async fn correctly_err_on_invalid_output_proof() { // Also, since we expect these to fail, we don't want to slow down the communal verifiers. let mut output_verifier = Fallback::new( Batch::new( - Verifier::new(&GROTH16_PARAMETERS.sapling.output.vk), + Verifier::new(SAPLING_SPEND_VERIFYING_KEY.get().unwrap()), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, ), tower::service_fn( (|item: Item| { - ready(item.verify_single(&GROTH16_PARAMETERS.sapling.output_prepared_verifying_key)) + ready( + item.verify_single( + &GROTH16_PARAMETERS + .sapling + .output_prepared_verifying_key + .inner(), + ), + ) }) as fn(_) -> _, ), ); From d7ad18976facdeee9fb533fdda8ec4aec56ad0fb Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Fri, 17 May 2024 12:32:47 -0300 Subject: [PATCH 2/5] remove OnceLock --- zebra-consensus/src/primitives/groth16.rs | 27 +++++-------------- .../src/primitives/groth16/tests.rs | 6 ++--- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/zebra-consensus/src/primitives/groth16.rs b/zebra-consensus/src/primitives/groth16.rs index 0c0ebcb8b85..e4b502c1db5 100644 --- a/zebra-consensus/src/primitives/groth16.rs +++ b/zebra-consensus/src/primitives/groth16.rs @@ -70,18 +70,11 @@ pub type ItemVerifyingKey = PreparedVerifyingKey; lazy_static::lazy_static! { /// The Sapling Groth16 verifying key for spends. - pub static ref SAPLING_SPEND_VERIFYING_KEY: std::sync::OnceLock> = { - let cell = std::sync::OnceLock::new(); - let _ = cell.set(GROTH16_PARAMETERS.sapling.spend.verifying_key().inner().clone()); - cell - }; - + pub static ref SAPLING_SPEND_VERIFYING_KEY: crate::groth16::VerifyingKey = + GROTH16_PARAMETERS.sapling.spend.verifying_key().inner().clone(); /// The Sapling Groth16 verifying key for outputs. - pub static ref SAPLING_OUTPUT_VERIFYING_KEY: std::sync::OnceLock> = { - let cell = std::sync::OnceLock::new(); - let _ = cell.set(GROTH16_PARAMETERS.sapling.output.verifying_key().inner().clone()); - cell - }; + pub static ref SAPLING_OUTPUT_VERIFYING_KEY: crate::groth16::VerifyingKey = + GROTH16_PARAMETERS.sapling.output.verifying_key().inner().clone(); } /// Global batch verification context for Groth16 proofs of Spend statements. @@ -100,11 +93,7 @@ pub static SPEND_VERIFIER: Lazy< > = Lazy::new(|| { Fallback::new( Batch::new( - Verifier::new( - SAPLING_SPEND_VERIFYING_KEY - .get() - .expect("Sapling verifying key for spends was set above"), - ), + Verifier::new(&SAPLING_SPEND_VERIFYING_KEY), super::MAX_BATCH_SIZE, None, super::MAX_BATCH_LATENCY, @@ -149,11 +138,7 @@ pub static OUTPUT_VERIFIER: Lazy< > = Lazy::new(|| { Fallback::new( Batch::new( - Verifier::new( - SAPLING_OUTPUT_VERIFYING_KEY - .get() - .expect("Sapling verifying key for outputs was set above"), - ), + Verifier::new(&SAPLING_OUTPUT_VERIFYING_KEY), super::MAX_BATCH_SIZE, None, super::MAX_BATCH_LATENCY, diff --git a/zebra-consensus/src/primitives/groth16/tests.rs b/zebra-consensus/src/primitives/groth16/tests.rs index 8522f267645..62ad60142ec 100644 --- a/zebra-consensus/src/primitives/groth16/tests.rs +++ b/zebra-consensus/src/primitives/groth16/tests.rs @@ -73,7 +73,7 @@ async fn verify_sapling_groth16() { // Use separate verifiers so shared batch tasks aren't killed when the test ends (#2390) let mut spend_verifier = Fallback::new( Batch::new( - Verifier::new(SAPLING_SPEND_VERIFYING_KEY.get().unwrap()), + Verifier::new(&SAPLING_SPEND_VERIFYING_KEY), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, @@ -93,7 +93,7 @@ async fn verify_sapling_groth16() { ); let mut output_verifier = Fallback::new( Batch::new( - Verifier::new(SAPLING_OUTPUT_VERIFYING_KEY.get().unwrap()), + Verifier::new(&SAPLING_OUTPUT_VERIFYING_KEY), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, @@ -193,7 +193,7 @@ async fn correctly_err_on_invalid_output_proof() { // Also, since we expect these to fail, we don't want to slow down the communal verifiers. let mut output_verifier = Fallback::new( Batch::new( - Verifier::new(SAPLING_SPEND_VERIFYING_KEY.get().unwrap()), + Verifier::new(&SAPLING_SPEND_VERIFYING_KEY), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, From 7b17e4ddecf982cd08f694bff902695c4a31264e Mon Sep 17 00:00:00 2001 From: Arya Date: Sat, 18 May 2024 08:27:22 -0400 Subject: [PATCH 3/5] Copies `parse_parameters()` function and other private functions it depends on from `zcash_proofs` (#8548) --- zebra-consensus/src/primitives/groth16.rs | 23 +-- .../src/primitives/groth16/params.rs | 23 +-- .../groth16/params/parse_parameters.rs | 189 ++++++++++++++++++ .../src/primitives/groth16/tests.rs | 33 +-- 4 files changed, 208 insertions(+), 60 deletions(-) create mode 100644 zebra-consensus/src/primitives/groth16/params/parse_parameters.rs diff --git a/zebra-consensus/src/primitives/groth16.rs b/zebra-consensus/src/primitives/groth16.rs index e4b502c1db5..e2ec64144fb 100644 --- a/zebra-consensus/src/primitives/groth16.rs +++ b/zebra-consensus/src/primitives/groth16.rs @@ -68,15 +68,6 @@ pub type BatchVerifyingKey = VerifyingKey; /// This is the key used to verify individual items. pub type ItemVerifyingKey = PreparedVerifyingKey; -lazy_static::lazy_static! { - /// The Sapling Groth16 verifying key for spends. - pub static ref SAPLING_SPEND_VERIFYING_KEY: crate::groth16::VerifyingKey = - GROTH16_PARAMETERS.sapling.spend.verifying_key().inner().clone(); - /// The Sapling Groth16 verifying key for outputs. - pub static ref SAPLING_OUTPUT_VERIFYING_KEY: crate::groth16::VerifyingKey = - GROTH16_PARAMETERS.sapling.output.verifying_key().inner().clone(); -} - /// Global batch verification context for Groth16 proofs of Spend statements. /// /// This service transparently batches contemporaneous proof verifications, @@ -93,7 +84,7 @@ pub static SPEND_VERIFIER: Lazy< > = Lazy::new(|| { Fallback::new( Batch::new( - Verifier::new(&SAPLING_SPEND_VERIFYING_KEY), + Verifier::new(&GROTH16_PARAMETERS.sapling.spend.vk), super::MAX_BATCH_SIZE, None, super::MAX_BATCH_LATENCY, @@ -111,10 +102,7 @@ pub static SPEND_VERIFIER: Lazy< (|item: Item| { Verifier::verify_single_spawning( item, - &GROTH16_PARAMETERS - .sapling - .spend_prepared_verifying_key - .inner(), + &GROTH16_PARAMETERS.sapling.spend_prepared_verifying_key, ) .boxed() }) as fn(_) -> _, @@ -138,7 +126,7 @@ pub static OUTPUT_VERIFIER: Lazy< > = Lazy::new(|| { Fallback::new( Batch::new( - Verifier::new(&SAPLING_OUTPUT_VERIFYING_KEY), + Verifier::new(&GROTH16_PARAMETERS.sapling.output.vk), super::MAX_BATCH_SIZE, None, super::MAX_BATCH_LATENCY, @@ -151,10 +139,7 @@ pub static OUTPUT_VERIFIER: Lazy< (|item: Item| { Verifier::verify_single_spawning( item, - &GROTH16_PARAMETERS - .sapling - .output_prepared_verifying_key - .inner(), + &GROTH16_PARAMETERS.sapling.output_prepared_verifying_key, ) .boxed() }) as fn(_) -> _, diff --git a/zebra-consensus/src/primitives/groth16/params.rs b/zebra-consensus/src/primitives/groth16/params.rs index 58f2c4872df..9cbadc165aa 100644 --- a/zebra-consensus/src/primitives/groth16/params.rs +++ b/zebra-consensus/src/primitives/groth16/params.rs @@ -3,6 +3,10 @@ use bellman::groth16; use bls12_381::Bls12; +mod parse_parameters; + +use parse_parameters::parse_sapling_parameters; + lazy_static::lazy_static! { /// Groth16 Zero-Knowledge Proof parameters for the Sapling and Sprout circuits. /// @@ -25,11 +29,11 @@ pub struct Groth16Parameters { /// Groth16 Zero-Knowledge Proof spend and output parameters for the Sapling circuit. pub struct SaplingParameters { - pub spend: sapling::circuit::SpendParameters, - pub spend_prepared_verifying_key: sapling::circuit::PreparedSpendVerifyingKey, + pub spend: groth16::Parameters, + pub spend_prepared_verifying_key: groth16::PreparedVerifyingKey, - pub output: sapling::circuit::OutputParameters, - pub output_prepared_verifying_key: sapling::circuit::PreparedOutputVerifyingKey, + pub output: groth16::Parameters, + pub output_prepared_verifying_key: groth16::PreparedVerifyingKey, } /// Groth16 Zero-Knowledge Proof spend parameters for the Sprout circuit. @@ -53,20 +57,11 @@ impl Groth16Parameters { wagyu_zcash_parameters::load_sapling_parameters(); let sprout_vk_bytes = include_bytes!("sprout-groth16.vk"); - let sapling_parameters = zcash_proofs::parse_parameters( + let sapling = parse_sapling_parameters( sapling_spend_bytes.as_slice(), sapling_output_bytes.as_slice(), - // This API expects the full sprout parameter file, not just the verifying key. - None, ); - let sapling = SaplingParameters { - spend: sapling_parameters.spend_params, - spend_prepared_verifying_key: sapling_parameters.spend_vk, - output: sapling_parameters.output_params, - output_prepared_verifying_key: sapling_parameters.output_vk, - }; - let sprout_vk = groth16::VerifyingKey::::read(&sprout_vk_bytes[..]) .expect("should be able to parse Sprout verification key"); let sprout_vk = groth16::prepare_verifying_key(&sprout_vk); diff --git a/zebra-consensus/src/primitives/groth16/params/parse_parameters.rs b/zebra-consensus/src/primitives/groth16/params/parse_parameters.rs new file mode 100644 index 00000000000..6a10db35020 --- /dev/null +++ b/zebra-consensus/src/primitives/groth16/params/parse_parameters.rs @@ -0,0 +1,189 @@ +//! Copied from `zcash_proofs` v1.14.0 with minor modifications to the `parse_parameters` function (renamed to `parse_sapling_parameters`). + +use std::{ + fmt::Write, + io::{self, Read}, +}; + +use bellman::groth16; +use blake2b_simd::State; +use bls12_381::Bls12; +use zcash_proofs::{SAPLING_OUTPUT_NAME, SAPLING_SPEND_NAME}; + +use super::SaplingParameters; + +// Circuit names + +// Circuit hashes +const SAPLING_SPEND_HASH: &str = "8270785a1a0d0bc77196f000ee6d221c9c9894f55307bd9357c3f0105d31ca63991ab91324160d8f53e2bbd3c2633a6eb8bdf5205d822e7f3f73edac51b2b70c"; +const SAPLING_OUTPUT_HASH: &str = "657e3d38dbb5cb5e7dd2970e8b03d69b4787dd907285b5a7f0790dcc8072f60bf593b32cc2d1c030e00ff5ae64bf84c5c3beb84ddc841d48264b4a171744d028"; + +// Circuit parameter file sizes +const SAPLING_SPEND_BYTES: u64 = 47958396; +const SAPLING_OUTPUT_BYTES: u64 = 3592860; + +/// Parse Bls12 keys from bytes as serialized by [`groth16::Parameters::write`]. +/// +/// This function will panic if it encounters unparsable data. +/// +/// [`groth16::Parameters::write`]: bellman::groth16::Parameters::write +pub fn parse_sapling_parameters(spend_fs: R, output_fs: R) -> SaplingParameters { + let mut spend_fs = HashReader::new(spend_fs); + let mut output_fs = HashReader::new(output_fs); + + // Deserialize params + let spend_params = groth16::Parameters::::read(&mut spend_fs, false) + .expect("couldn't deserialize Sapling spend parameters"); + let output_params = groth16::Parameters::::read(&mut output_fs, false) + .expect("couldn't deserialize Sapling spend parameters"); + + // There is extra stuff (the transcript) at the end of the parameter file which is + // used to verify the parameter validity, but we're not interested in that. We do + // want to read it, though, so that the BLAKE2b computed afterward is consistent + // with `b2sum` on the files. + let mut sink = io::sink(); + + // TODO: use the correct paths for Windows and macOS + // use the actual file paths supplied by the caller + verify_hash( + spend_fs, + &mut sink, + SAPLING_SPEND_HASH, + SAPLING_SPEND_BYTES, + SAPLING_SPEND_NAME, + "a file", + ) + .expect( + "Sapling spend parameter file is not correct, \ + please clean your `~/.zcash-params/` and re-run `fetch-params`.", + ); + + verify_hash( + output_fs, + &mut sink, + SAPLING_OUTPUT_HASH, + SAPLING_OUTPUT_BYTES, + SAPLING_OUTPUT_NAME, + "a file", + ) + .expect( + "Sapling output parameter file is not correct, \ + please clean your `~/.zcash-params/` and re-run `fetch-params`.", + ); + + // Prepare verifying keys + let spend_vk = groth16::prepare_verifying_key(&spend_params.vk); + let output_vk = groth16::prepare_verifying_key(&output_params.vk); + + SaplingParameters { + spend: spend_params, + spend_prepared_verifying_key: spend_vk, + output: output_params, + output_prepared_verifying_key: output_vk, + } +} + +/// Abstraction over a reader which hashes the data being read. +pub struct HashReader { + reader: R, + hasher: State, + byte_count: u64, +} + +impl HashReader { + /// Construct a new `HashReader` given an existing `reader` by value. + pub fn new(reader: R) -> Self { + HashReader { + reader, + hasher: State::new(), + byte_count: 0, + } + } + + /// Destroy this reader and return the hash of what was read. + pub fn into_hash(self) -> String { + let hash = self.hasher.finalize(); + + let mut s = String::new(); + for c in hash.as_bytes().iter() { + write!(&mut s, "{:02x}", c).expect("writing to a string never fails"); + } + + s + } + + /// Return the number of bytes read so far. + pub fn byte_count(&self) -> u64 { + self.byte_count + } +} + +impl Read for HashReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let bytes = self.reader.read(buf)?; + + if bytes > 0 { + self.hasher.update(&buf[0..bytes]); + let byte_count = u64::try_from(bytes).map_err(|_| { + io::Error::new( + io::ErrorKind::InvalidData, + "Could not fit the number of read bytes into u64.", + ) + })?; + self.byte_count += byte_count; + } + + Ok(bytes) + } +} + +/// Check if the Blake2b hash from `hash_reader` matches `expected_hash`, +/// while streaming from `hash_reader` into `sink`. +/// +/// `hash_reader` can be used to partially read its inner reader's data, +/// before verifying the hash using this function. +/// +/// Returns an error containing `name` and `params_source` on failure. +fn verify_hash( + mut hash_reader: HashReader, + mut sink: W, + expected_hash: &str, + expected_bytes: u64, + name: &str, + params_source: &str, +) -> Result<(), io::Error> { + let read_result = io::copy(&mut hash_reader, &mut sink); + + if let Err(read_error) = read_result { + return Err(io::Error::new( + read_error.kind(), + format!( + "{} failed reading:\n\ + expected: {} bytes,\n\ + actual: {} bytes from {:?},\n\ + error: {:?}", + name, + expected_bytes, + hash_reader.byte_count(), + params_source, + read_error, + ), + )); + } + + let byte_count = hash_reader.byte_count(); + let hash = hash_reader.into_hash(); + if hash != expected_hash { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + format!( + "{} failed validation:\n\ + expected: {} hashing {} bytes,\n\ + actual: {} hashing {} bytes from {:?}", + name, expected_hash, expected_bytes, hash, byte_count, params_source, + ), + )); + } + + Ok(()) +} diff --git a/zebra-consensus/src/primitives/groth16/tests.rs b/zebra-consensus/src/primitives/groth16/tests.rs index 62ad60142ec..52c00d575a3 100644 --- a/zebra-consensus/src/primitives/groth16/tests.rs +++ b/zebra-consensus/src/primitives/groth16/tests.rs @@ -73,41 +73,27 @@ async fn verify_sapling_groth16() { // Use separate verifiers so shared batch tasks aren't killed when the test ends (#2390) let mut spend_verifier = Fallback::new( Batch::new( - Verifier::new(&SAPLING_SPEND_VERIFYING_KEY), + Verifier::new(&GROTH16_PARAMETERS.sapling.spend.vk), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, ), tower::service_fn( (|item: Item| { - ready( - item.verify_single( - &GROTH16_PARAMETERS - .sapling - .spend_prepared_verifying_key - .inner(), - ), - ) + ready(item.verify_single(&GROTH16_PARAMETERS.sapling.spend_prepared_verifying_key)) }) as fn(_) -> _, ), ); let mut output_verifier = Fallback::new( Batch::new( - Verifier::new(&SAPLING_OUTPUT_VERIFYING_KEY), + Verifier::new(&GROTH16_PARAMETERS.sapling.output.vk), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, ), tower::service_fn( (|item: Item| { - ready( - item.verify_single( - &GROTH16_PARAMETERS - .sapling - .output_prepared_verifying_key - .inner(), - ), - ) + ready(item.verify_single(&GROTH16_PARAMETERS.sapling.output_prepared_verifying_key)) }) as fn(_) -> _, ), ); @@ -193,21 +179,14 @@ async fn correctly_err_on_invalid_output_proof() { // Also, since we expect these to fail, we don't want to slow down the communal verifiers. let mut output_verifier = Fallback::new( Batch::new( - Verifier::new(&SAPLING_SPEND_VERIFYING_KEY), + Verifier::new(&GROTH16_PARAMETERS.sapling.output.vk), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, ), tower::service_fn( (|item: Item| { - ready( - item.verify_single( - &GROTH16_PARAMETERS - .sapling - .output_prepared_verifying_key - .inner(), - ), - ) + ready(item.verify_single(&GROTH16_PARAMETERS.sapling.output_prepared_verifying_key)) }) as fn(_) -> _, ), ); From 5a2ba8672bfa5290ae729123d4e23bb346e6617b Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 18 May 2024 09:55:03 -0300 Subject: [PATCH 4/5] add links to copied code --- .../src/primitives/groth16/params/parse_parameters.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/zebra-consensus/src/primitives/groth16/params/parse_parameters.rs b/zebra-consensus/src/primitives/groth16/params/parse_parameters.rs index 6a10db35020..77c593ca14c 100644 --- a/zebra-consensus/src/primitives/groth16/params/parse_parameters.rs +++ b/zebra-consensus/src/primitives/groth16/params/parse_parameters.rs @@ -1,5 +1,9 @@ //! Copied from `zcash_proofs` v1.14.0 with minor modifications to the `parse_parameters` function (renamed to `parse_sapling_parameters`). - +//! +//! Sapling related constants: +//! Parse parameters: +//! Hash reader: +//! Verify hash: use std::{ fmt::Write, io::{self, Read}, From bea3e528126f5f309a318b9975193629277e4b8d Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 18 May 2024 14:15:38 -0300 Subject: [PATCH 5/5] use upstream proofs and sapling --- Cargo.lock | 172 ++++++------------------------------- zebra-consensus/Cargo.toml | 4 +- 2 files changed, 26 insertions(+), 150 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 95d24d3e3e4..83bf0622842 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1365,15 +1365,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "equihash" -version = "0.2.0" -source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" -dependencies = [ - "blake2b_simd", - "byteorder", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1409,14 +1400,6 @@ dependencies = [ "blake2b_simd", ] -[[package]] -name = "f4jumble" -version = "0.1.0" -source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" -dependencies = [ - "blake2b_simd", -] - [[package]] name = "fastrand" version = "2.1.0" @@ -3945,37 +3928,6 @@ dependencies = [ "zip32", ] -[[package]] -name = "sapling-crypto" -version = "0.1.3" -source = "git+https://github.com/oxarbitrage/sapling-crypto?branch=add-verifying-key-methods#f93fd95314994010006a8b9dea7e4b5b54f26b52" -dependencies = [ - "aes", - "bellman", - "bitvec", - "blake2b_simd", - "blake2s_simd", - "bls12_381", - "byteorder", - "document-features", - "ff", - "fpe", - "group", - "hex", - "incrementalmerkletree", - "jubjub", - "lazy_static", - "memuse", - "rand 0.8.5", - "rand_core 0.6.4", - "redjubjub", - "subtle", - "tracing", - "zcash_note_encryption", - "zcash_spec", - "zip32", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -5776,17 +5728,6 @@ version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" -[[package]] -name = "zcash_address" -version = "0.3.1" -source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" -dependencies = [ - "bech32", - "bs58", - "f4jumble 0.1.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", - "zcash_encoding 0.2.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", -] - [[package]] name = "zcash_address" version = "0.3.2" @@ -5795,8 +5736,8 @@ checksum = "827c17a1f7e3a69f0d44e991ff610c7a842228afdc9dc2325ffdd1a67fee01e9" dependencies = [ "bech32", "bs58", - "f4jumble 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "f4jumble", + "zcash_encoding", "zcash_protocol", ] @@ -5827,8 +5768,8 @@ dependencies = [ "tonic-build 0.10.2", "tracing", "which", - "zcash_address 0.3.2", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_address", + "zcash_encoding", "zcash_note_encryption", "zcash_primitives 0.13.0", ] @@ -5843,15 +5784,6 @@ dependencies = [ "nonempty", ] -[[package]] -name = "zcash_encoding" -version = "0.2.0" -source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" -dependencies = [ - "byteorder", - "nonempty", -] - [[package]] name = "zcash_history" version = "0.4.0" @@ -5889,7 +5821,7 @@ dependencies = [ "blake2s_simd", "bls12_381", "byteorder", - "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "equihash", "ff", "fpe", "group", @@ -5907,8 +5839,8 @@ dependencies = [ "secp256k1", "sha2", "subtle", - "zcash_address 0.3.2", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_address", + "zcash_encoding", "zcash_note_encryption", ] @@ -5923,7 +5855,7 @@ dependencies = [ "blake2b_simd", "byteorder", "document-features", - "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "equihash", "ff", "fpe", "group", @@ -5938,47 +5870,13 @@ dependencies = [ "rand_core 0.6.4", "redjubjub", "ripemd", - "sapling-crypto 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sapling-crypto", "secp256k1", "sha2", "subtle", "tracing", - "zcash_address 0.3.2", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_note_encryption", - "zcash_spec", - "zip32", -] - -[[package]] -name = "zcash_primitives" -version = "0.14.0" -source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" -dependencies = [ - "aes", - "bip0039", - "blake2b_simd", - "byteorder", - "document-features", - "equihash 0.2.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", - "ff", - "fpe", - "group", - "hex", - "incrementalmerkletree", - "jubjub", - "memuse", - "nonempty", - "orchard 0.7.1", - "rand 0.8.5", - "rand_core 0.6.4", - "redjubjub", - "sapling-crypto 0.1.3 (git+https://github.com/oxarbitrage/sapling-crypto?branch=add-verifying-key-methods)", - "sha2", - "subtle", - "tracing", - "zcash_address 0.3.1", - "zcash_encoding 0.2.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", + "zcash_address", + "zcash_encoding", "zcash_note_encryption", "zcash_spec", "zip32", @@ -6001,32 +5899,10 @@ dependencies = [ "lazy_static", "rand_core 0.6.4", "redjubjub", - "sapling-crypto 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing", - "xdg", - "zcash_primitives 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "zcash_proofs" -version = "0.14.0" -source = "git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling#1dda0cf83b113b5a8637e657b48002ce94115983" -dependencies = [ - "bellman", - "blake2b_simd", - "bls12_381", - "document-features", - "group", - "home", - "jubjub", - "known-folders", - "lazy_static", - "rand_core 0.6.4", - "redjubjub", - "sapling-crypto 0.1.3 (git+https://github.com/oxarbitrage/sapling-crypto?branch=add-verifying-key-methods)", + "sapling-crypto", "tracing", "xdg", - "zcash_primitives 0.14.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", + "zcash_primitives 0.14.0", ] [[package]] @@ -6067,15 +5943,15 @@ dependencies = [ "rand_core 0.6.4", "rayon", "redjubjub", - "sapling-crypto 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sapling-crypto", "subtle", "syn 1.0.109", "tracing", - "zcash_address 0.3.2", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_address", + "zcash_encoding", "zcash_note_encryption", - "zcash_primitives 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_proofs 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_primitives 0.14.0", + "zcash_proofs", ] [[package]] @@ -6104,7 +5980,7 @@ dependencies = [ "criterion", "displaydoc", "ed25519-zebra", - "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "equihash", "futures", "group", "halo2_proofs", @@ -6140,9 +6016,9 @@ dependencies = [ "tracing", "uint", "x25519-dalek", - "zcash_address 0.3.2", + "zcash_address", "zcash_client_backend", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_encoding", "zcash_history", "zcash_note_encryption", "zcash_primitives 0.13.0", @@ -6175,7 +6051,7 @@ dependencies = [ "proptest-derive", "rand 0.8.5", "rayon", - "sapling-crypto 0.1.3 (git+https://github.com/oxarbitrage/sapling-crypto?branch=add-verifying-key-methods)", + "sapling-crypto", "serde", "spandoc", "thiserror", @@ -6189,7 +6065,7 @@ dependencies = [ "tracing-futures", "tracing-subscriber", "wagyu-zcash-parameters", - "zcash_proofs 0.14.0 (git+https://github.com/oxarbitrage/librustzcash?branch=use-custom-sapling)", + "zcash_proofs", "zebra-chain", "zebra-node-services", "zebra-script", @@ -6294,7 +6170,7 @@ dependencies = [ "tokio", "tower", "tracing", - "zcash_address 0.3.2", + "zcash_address", "zebra-chain", "zebra-consensus", "zebra-network", diff --git a/zebra-consensus/Cargo.toml b/zebra-consensus/Cargo.toml index 5fc276f6eb0..fbab316c90a 100644 --- a/zebra-consensus/Cargo.toml +++ b/zebra-consensus/Cargo.toml @@ -59,9 +59,9 @@ tracing = "0.1.39" tracing-futures = "0.2.5" orchard = "0.6.0" -sapling = { package = "sapling-crypto", git = "https://github.com/oxarbitrage/sapling-crypto", branch = "add-verifying-key-methods" } +sapling = { package = "sapling-crypto", version = "0.1" } -zcash_proofs = { package = "zcash_proofs", git = "https://github.com/oxarbitrage/librustzcash", branch = "use-custom-sapling" } +zcash_proofs = { version = "0.14.0", features = ["multicore" ] } wagyu-zcash-parameters = "0.2.0" tower-fallback = { path = "../tower-fallback/", version = "0.2.41-beta.13" }