@@ -3,6 +3,7 @@ use std::rc::Rc;
3
3
use ark_ff:: fields:: arithmetic:: InvalidBigInt ;
4
4
use ark_poly:: { EvaluationDomain , Radix2EvaluationDomain } ;
5
5
use ark_serialize:: Write ;
6
+ use itertools:: Itertools ;
6
7
use poly_commitment:: srs:: SRS ;
7
8
8
9
use crate :: {
@@ -519,6 +520,38 @@ fn verify_with(
519
520
)
520
521
}
521
522
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
+
522
555
fn run_checks (
523
556
proof : & PicklesProofProofsVerified2ReprStableV2 ,
524
557
verifier_index : & VerifierIndex < Fq > ,
@@ -713,7 +746,7 @@ pub fn verify_block(
713
746
let protocol_state_hash = MinaHash :: hash ( & protocol_state) ;
714
747
715
748
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 ) ;
717
750
let verified = verify_impl ( & protocol_state_hash, protocol_state_proof, & vk) . unwrap_or ( false ) ;
718
751
719
752
accum_check && verified
@@ -730,12 +763,27 @@ pub fn verify_transaction<'a>(
730
763
data : ( ) ,
731
764
} ;
732
765
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
739
787
}
740
788
741
789
/// 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(
753
801
data : ( ) ,
754
802
} ;
755
803
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 ) ;
757
806
let verified = verify_impl ( & zkapp_statement, sideloaded_proof, & vk) . unwrap_or ( false ) ;
758
807
759
808
let ok = accum_check && verified;
@@ -811,6 +860,57 @@ where
811
860
Ok ( result. is_ok ( ) && checks)
812
861
}
813
862
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
+
814
914
/// Dump data when it fails, to reproduce and compare in OCaml
815
915
fn dump_zkapp_verification (
816
916
verification_key : & VerificationKey ,
0 commit comments