From 29d5da320f37c7501345147bf3e6e2fd17ac7b00 Mon Sep 17 00:00:00 2001 From: teor Date: Tue, 23 Nov 2021 14:30:59 +1000 Subject: [PATCH] Use prepared verifying key for non-batch Groth16 verification (#3092) --- zebra-consensus/src/primitives/groth16.rs | 53 +++++++++---------- .../src/primitives/groth16/tests.rs | 35 +++++------- 2 files changed, 38 insertions(+), 50 deletions(-) diff --git a/zebra-consensus/src/primitives/groth16.rs b/zebra-consensus/src/primitives/groth16.rs index eb588707..cb02828f 100644 --- a/zebra-consensus/src/primitives/groth16.rs +++ b/zebra-consensus/src/primitives/groth16.rs @@ -9,7 +9,7 @@ use std::{ }; use bellman::{ - groth16::{batch, prepare_verifying_key, VerifyingKey}, + groth16::{batch, VerifyingKey}, VerificationError, }; use bls12_381::Bls12; @@ -40,31 +40,28 @@ pub use params::{Groth16Parameters, GROTH16_PARAMETERS}; /// handle. pub static SPEND_VERIFIER: Lazy< Fallback, ServiceFn Ready>>>, -> = - Lazy::new(|| { - Fallback::new( - Batch::new( - Verifier::new(&GROTH16_PARAMETERS.sapling.spend.vk), - super::MAX_BATCH_SIZE, - super::MAX_BATCH_LATENCY, - ), - // We want to fallback to individual verification if batch verification - // fails, so we need a Service to use. The obvious way to do this would - // be to write a closure that returns an async block. But because we - // have to specify the type of a static, we need to be able to write the - // type of the closure and its return value, and both closures and async - // blocks have eldritch types whose names cannot be written. So instead, - // we use a Ready to avoid an async block and cast the closure to a - // function (which is possible because it doesn't capture any state). - tower::service_fn( - (|item: Item| { - ready(item.verify_single(&prepare_verifying_key( - &GROTH16_PARAMETERS.sapling.spend.vk, - ))) - }) as fn(_) -> _, - ), - ) - }); +> = Lazy::new(|| { + Fallback::new( + Batch::new( + Verifier::new(&GROTH16_PARAMETERS.sapling.spend.vk), + super::MAX_BATCH_SIZE, + super::MAX_BATCH_LATENCY, + ), + // We want to fallback to individual verification if batch verification + // fails, so we need a Service to use. The obvious way to do this would + // be to write a closure that returns an async block. But because we + // have to specify the type of a static, we need to be able to write the + // type of the closure and its return value, and both closures and async + // blocks have eldritch types whose names cannot be written. So instead, + // we use a Ready to avoid an async block and cast the closure to a + // function (which is possible because it doesn't capture any state). + tower::service_fn( + (|item: Item| { + ready(item.verify_single(&GROTH16_PARAMETERS.sapling.spend_prepared_verifying_key)) + }) as fn(_) -> _, + ), + ) +}); /// Global batch verification context for Groth16 proofs of Output statements. /// @@ -93,9 +90,7 @@ pub static OUTPUT_VERIFIER: Lazy< // function (which is possible because it doesn't capture any state). tower::service_fn( (|item: Item| { - ready(item.verify_single(&prepare_verifying_key( - &GROTH16_PARAMETERS.sapling.output.vk, - ))) + ready(item.verify_single(&GROTH16_PARAMETERS.sapling.output_prepared_verifying_key)) }) as fn(_) -> _, ), ) diff --git a/zebra-consensus/src/primitives/groth16/tests.rs b/zebra-consensus/src/primitives/groth16/tests.rs index 99bce0de..7f55eb62 100644 --- a/zebra-consensus/src/primitives/groth16/tests.rs +++ b/zebra-consensus/src/primitives/groth16/tests.rs @@ -62,21 +62,18 @@ where #[tokio::test] 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), - crate::primitives::MAX_BATCH_SIZE, - crate::primitives::MAX_BATCH_LATENCY, - ), - tower::service_fn( - (|item: Item| { - ready(item.verify_single(&prepare_verifying_key( - &GROTH16_PARAMETERS.sapling.spend.vk, - ))) - }) as fn(_) -> _, - ), - ); + let mut spend_verifier = Fallback::new( + Batch::new( + Verifier::new(&GROTH16_PARAMETERS.sapling.spend.vk), + crate::primitives::MAX_BATCH_SIZE, + crate::primitives::MAX_BATCH_LATENCY, + ), + tower::service_fn( + (|item: Item| { + ready(item.verify_single(&GROTH16_PARAMETERS.sapling.spend_prepared_verifying_key)) + }) as fn(_) -> _, + ), + ); let mut output_verifier = Fallback::new( Batch::new( Verifier::new(&GROTH16_PARAMETERS.sapling.output.vk), @@ -85,9 +82,7 @@ async fn verify_sapling_groth16() { ), tower::service_fn( (|item: Item| { - ready(item.verify_single(&prepare_verifying_key( - &GROTH16_PARAMETERS.sapling.output.vk, - ))) + ready(item.verify_single(&GROTH16_PARAMETERS.sapling.output_prepared_verifying_key)) }) as fn(_) -> _, ), ); @@ -163,9 +158,7 @@ async fn correctly_err_on_invalid_output_proof() { ), tower::service_fn( (|item: Item| { - ready(item.verify_single(&prepare_verifying_key( - &GROTH16_PARAMETERS.sapling.output.vk, - ))) + ready(item.verify_single(&GROTH16_PARAMETERS.sapling.output_prepared_verifying_key)) }) as fn(_) -> _, ), );