@@ -3,6 +3,7 @@ use std::rc::Rc;
33use ark_ff:: fields:: arithmetic:: InvalidBigInt ;
44use ark_poly:: { EvaluationDomain , Radix2EvaluationDomain } ;
55use ark_serialize:: Write ;
6+ use itertools:: Itertools ;
67use poly_commitment:: srs:: SRS ;
78
89use crate :: {
@@ -519,6 +520,38 @@ fn verify_with(
519520 )
520521}
521522
523+ pub struct VerificationContext < ' a > {
524+ pub verifier_index : & ' a VerifierIndex < Fq > ,
525+ pub proof : & ' a ProverProof < Fq > ,
526+ pub public_input : & ' a [ Fq ] ,
527+ }
528+
529+ fn batch_verify ( proofs : & [ VerificationContext ] ) -> Result < ( ) , VerifyError > {
530+ use kimchi:: groupmap:: GroupMap ;
531+ use kimchi:: mina_curves:: pasta:: PallasParameters ;
532+ use kimchi:: verifier:: Context ;
533+ use mina_poseidon:: sponge:: { DefaultFqSponge , DefaultFrSponge } ;
534+ use poly_commitment:: evaluation_proof:: OpeningProof ;
535+
536+ type SpongeParams = mina_poseidon:: constants:: PlonkSpongeConstantsKimchi ;
537+ type EFqSponge = DefaultFqSponge < PallasParameters , SpongeParams > ;
538+ type EFrSponge = DefaultFrSponge < Fq , SpongeParams > ;
539+
540+ let group_map = GroupMap :: < Fp > :: setup ( ) ;
541+ let proofs = proofs
542+ . iter ( )
543+ . map ( |p| Context {
544+ verifier_index : p. verifier_index ,
545+ proof : p. proof ,
546+ public_input : p. public_input ,
547+ } )
548+ . collect_vec ( ) ;
549+
550+ kimchi:: verifier:: batch_verify :: < Pallas , EFqSponge , EFrSponge , OpeningProof < Pallas > > (
551+ & group_map, & proofs,
552+ )
553+ }
554+
522555fn run_checks (
523556 proof : & PicklesProofProofsVerified2ReprStableV2 ,
524557 verifier_index : & VerifierIndex < Fq > ,
@@ -713,7 +746,7 @@ pub fn verify_block(
713746 let protocol_state_hash = MinaHash :: hash ( & protocol_state) ;
714747
715748 let accum_check =
716- accumulator_check:: accumulator_check ( srs, protocol_state_proof) . unwrap_or ( false ) ;
749+ accumulator_check:: accumulator_check ( srs, & [ protocol_state_proof] ) . unwrap_or ( false ) ;
717750 let verified = verify_impl ( & protocol_state_hash, protocol_state_proof, & vk) . unwrap_or ( false ) ;
718751
719752 accum_check && verified
@@ -730,12 +763,27 @@ pub fn verify_transaction<'a>(
730763 data : ( ) ,
731764 } ;
732765
733- proofs. into_iter ( ) . all ( |( statement, transaction_proof) | {
734- let accum_check =
735- accumulator_check:: accumulator_check ( srs, transaction_proof) . unwrap_or ( false ) ;
736- let verified = verify_impl ( statement, transaction_proof, & vk) . unwrap_or ( false ) ;
737- accum_check && verified
738- } )
766+ let mut inputs: Vec < (
767+ & Statement < SokDigest > ,
768+ & PicklesProofProofsVerified2ReprStableV2 ,
769+ & VK ,
770+ ) > = Vec :: with_capacity ( 128 ) ;
771+
772+ let mut accum_check_proofs: Vec < & PicklesProofProofsVerified2ReprStableV2 > =
773+ Vec :: with_capacity ( 128 ) ;
774+
775+ proofs
776+ . into_iter ( )
777+ . for_each ( |( statement, transaction_proof) | {
778+ accum_check_proofs. push ( transaction_proof) ;
779+ inputs. push ( ( statement, transaction_proof, & vk) ) ;
780+ } ) ;
781+
782+ let accum_check =
783+ accumulator_check:: accumulator_check ( srs, & accum_check_proofs) . unwrap_or ( false ) ;
784+
785+ let verified = batch_verify_impl ( inputs. as_slice ( ) ) . unwrap_or ( false ) ;
786+ accum_check && verified
739787}
740788
741789/// https://github.com/MinaProtocol/mina/blob/bfd1009abdbee78979ff0343cc73a3480e862f58/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_proof.rs#L116
@@ -753,7 +801,8 @@ pub fn verify_zkapp(
753801 data : ( ) ,
754802 } ;
755803
756- let accum_check = accumulator_check:: accumulator_check ( srs, sideloaded_proof) . unwrap_or ( false ) ;
804+ let accum_check =
805+ accumulator_check:: accumulator_check ( srs, & [ sideloaded_proof] ) . unwrap_or ( false ) ;
757806 let verified = verify_impl ( & zkapp_statement, sideloaded_proof, & vk) . unwrap_or ( false ) ;
758807
759808 let ok = accum_check && verified;
@@ -811,6 +860,57 @@ where
811860 Ok ( result. is_ok ( ) && checks)
812861}
813862
863+ fn batch_verify_impl < AppState > (
864+ proofs : & [ ( & AppState , & PicklesProofProofsVerified2ReprStableV2 , & VK ) ] ,
865+ ) -> Result < bool , InvalidBigInt >
866+ where
867+ AppState : ToFieldElements < Fp > ,
868+ {
869+ let mut verification_contexts = Vec :: with_capacity ( proofs. len ( ) ) ;
870+ let mut checks = true ;
871+
872+ for ( app_state, proof, vk) in proofs {
873+ let deferred_values = compute_deferred_values ( proof) ?;
874+ checks = checks && run_checks ( proof, vk. index ) ;
875+
876+ let message_for_next_step_proof = get_message_for_next_step_proof (
877+ & proof. statement . messages_for_next_step_proof ,
878+ & vk. commitments ,
879+ app_state,
880+ ) ?;
881+
882+ let message_for_next_wrap_proof = get_message_for_next_wrap_proof (
883+ & proof. statement . proof_state . messages_for_next_wrap_proof ,
884+ ) ?;
885+
886+ let prepared_statement = get_prepared_statement (
887+ & message_for_next_step_proof,
888+ & message_for_next_wrap_proof,
889+ deferred_values,
890+ & proof. statement . proof_state . sponge_digest_before_evaluations ,
891+ ) ;
892+
893+ let npublic_input = vk. index . public ;
894+ let public_inputs = prepared_statement. to_public_input ( npublic_input) ?;
895+ let proof_padded = make_padded_proof_from_p2p ( proof) ?;
896+
897+ verification_contexts. push ( ( vk. index , proof_padded, public_inputs) ) ;
898+ }
899+
900+ let proofs: Vec < VerificationContext > = verification_contexts
901+ . iter ( )
902+ . map ( |( vk, proof, public_input) | VerificationContext {
903+ verifier_index : vk,
904+ proof,
905+ public_input,
906+ } )
907+ . collect ( ) ;
908+
909+ let result = batch_verify ( & proofs) ;
910+
911+ Ok ( result. is_ok ( ) && checks)
912+ }
913+
814914/// Dump data when it fails, to reproduce and compare in OCaml
815915fn dump_zkapp_verification (
816916 verification_key : & VerificationKey ,
0 commit comments