@@ -13,7 +13,10 @@ use plonky2::{
1313 self ,
1414 field:: { extension:: quintic:: QuinticExtension , types:: Field } ,
1515 gates:: { gate:: GateRef , noop:: NoopGate } ,
16- hash:: hash_types:: HashOutTarget ,
16+ hash:: {
17+ hash_types:: { HashOut , HashOutTarget } ,
18+ poseidon:: PoseidonHash ,
19+ } ,
1720 iop:: {
1821 target:: Target ,
1922 witness:: { PartialWitness , WitnessWrite } ,
@@ -24,6 +27,7 @@ use plonky2::{
2427 CircuitConfig , CircuitData , CommonCircuitData , ProverCircuitData , VerifierCircuitData ,
2528 VerifierCircuitTarget , VerifierOnlyCircuitData ,
2629 } ,
30+ config:: Hasher ,
2731 proof:: { ProofWithPublicInputs , ProofWithPublicInputsTarget } ,
2832 } ,
2933 util:: log2_ceil,
@@ -201,7 +205,18 @@ impl<I: InnerCircuit> RecursiveCircuit<I> {
201205 let verified_proofs = ( 0 ..arity)
202206 . map ( |i| VerifiedProofTarget {
203207 public_inputs : proofs_targ[ i] . public_inputs . clone ( ) ,
204- verifier_data_hash : verifier_datas_targ[ i] . circuit_digest ,
208+ // note: here we're hashing the verifier_data as Hash(vd.circuit_digest,
209+ // vd.constant_sigmas_cap), despite the circuit_digest is already a hash containing
210+ // the constant_sigmas_cap. Conceptually we would use the circuit_digest as the hash
211+ // of the verifier_data, but unfortunately, the recursion verification circuit does
212+ // not ensure this link. Alternatively we could calculate an modified
213+ // circuit_digest, hashing as in the original plonky2's circuit_digest but
214+ // additionally checking it in-circuit. But since in terms of circuit costs would
215+ // require a hash (with similar amount of elements), the approach that we do is take
216+ // the already computed circuit_digest and hash it together with the
217+ // constant_sigmas_cap, doing the same computation in-circuit, obtaining a new hash
218+ // that we use to represent the verifier_data.
219+ verifier_data_hash : hash_verifier_data_gadget ( builder, & verifier_datas_targ[ i] ) ,
205220 } )
206221 . collect_vec ( ) ;
207222
@@ -478,6 +493,38 @@ pub fn pad_circuit(builder: &mut CircuitBuilder<F, D>, common_data: &CommonCircu
478493 }
479494}
480495
496+ fn hash_verifier_data_gadget (
497+ builder : & mut CircuitBuilder < F , D > ,
498+ verifier_data : & VerifierCircuitTarget ,
499+ ) -> HashOutTarget {
500+ let f: Vec < Target > = [
501+ verifier_data. circuit_digest . elements . to_vec ( ) ,
502+ verifier_data
503+ . constants_sigmas_cap
504+ . 0
505+ . iter ( )
506+ . flat_map ( |e| e. elements )
507+ . collect ( ) ,
508+ ]
509+ . concat ( ) ;
510+ builder. hash_n_to_hash_no_pad :: < PoseidonHash > ( f)
511+ }
512+
513+ // compatible with hash_verifier_data_gadget.
514+ pub ( crate ) fn hash_verifier_data ( verifier_only_data : & VerifierOnlyCircuitData < C , D > ) -> HashOut < F > {
515+ let f: Vec < F > = [
516+ verifier_only_data. circuit_digest . elements . to_vec ( ) ,
517+ verifier_only_data
518+ . constants_sigmas_cap
519+ . 0
520+ . iter ( )
521+ . flat_map ( |e| e. elements )
522+ . collect ( ) ,
523+ ]
524+ . concat ( ) ;
525+ PoseidonHash :: hash_no_pad ( & f)
526+ }
527+
481528#[ cfg( test) ]
482529mod tests {
483530 use std:: time:: Instant ;
0 commit comments