diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index 4a37f665..1a73d7b6 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -276,7 +276,7 @@ pub struct ProverOnlyCircuitData< } /// Circuit data required by the verifier, but not the prover. -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub struct VerifierOnlyCircuitData, const D: usize> { /// A commitment to each constant polynomial and each permutation polynomial. pub constants_sigmas_cap: MerkleCap, diff --git a/plonky2/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs index 373ed69e..29d89c92 100644 --- a/plonky2/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -464,37 +464,190 @@ mod tests { // type FF = >::FE; let config = CircuitConfig::standard_recursion_config(); - let (proof, vd, cd) = dummy_proof::(&config, 1 << 13)?; + let (proof, vd, cd) = dummy_proof::(&config, 1 << 14)?; let (proof, vd, cd) = recursive_proof::(proof, vd, cd, &config, None, false, false)?; - let (_proof, _vd, cd) = - recursive_proof::(proof, vd, cd, &config, None, false, false)?; + let (_proof, _vd, mut cd) = + recursive_proof::(proof, vd, cd, &config, Some(14), false, false)?; + cd.num_public_inputs = 69; + // First proof let config = CircuitConfig::standard_recursion_config(); let mut pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let verifier_data = VerifierCircuitTarget { constants_sigmas_cap: builder.add_virtual_cap(builder.config.fri_config.cap_height), + circuit_digest: builder.add_virtual_hash(), }; + builder.register_public_inputs(&verifier_data.circuit_digest.elements); for i in 0..1 << builder.config.fri_config.cap_height { builder.register_public_inputs(&verifier_data.constants_sigmas_cap.0[i].elements); } - let pt = builder.add_virtual_proof_with_pis(&cd); - builder.verify_proof(pt, &verifier_data, &cd); + let dummy_verifier_data = VerifierCircuitTarget { + constants_sigmas_cap: builder.add_virtual_cap(builder.config.fri_config.cap_height), + circuit_digest: builder.add_virtual_hash(), + }; + let condition = builder.add_virtual_bool_target(); + builder.register_public_input(condition.target); + pw.set_bool_target(condition, false); - let inner_gates = cd.gates.iter().map(|g| g.0.id()).collect::>(); - for gate in &builder.gates { - assert!(inner_gates.contains(&gate.0.id()), "{}", gate.0.id()); - } - for _ in builder.num_gates()..(1 << 13) - 100 { + let (dummy_proof, dummy_data) = + crate::plonk::conditional_recursive_verifier::dummy_proof(&cd)?; + let pt0 = builder.add_virtual_proof_with_pis(&cd); + let pt1 = builder.add_virtual_proof_with_pis(&cd); + + pw.set_proof_with_pis_target(&pt0, &dummy_proof); + pw.set_proof_with_pis_target(&pt1, &dummy_proof); + pw.set_hash_target( + dummy_verifier_data.circuit_digest, + dummy_data.verifier_only.circuit_digest, + ); + pw.set_cap_target( + &dummy_verifier_data.constants_sigmas_cap, + &dummy_data.verifier_only.constants_sigmas_cap, + ); + + builder.conditionally_verify_proof( + condition, + pt0, + &verifier_data, + pt1, + &dummy_verifier_data, + &cd, + ); + + while builder.num_gates() < 1 << 13 { builder.add_gate(NoopGate, vec![]); } - let data = builder.build::(); - dbg!(data.common.degree_bits); - let proof = data.prove(pw)?; + let data = builder.build::(); + dbg!(cd.degree_bits); + dbg!(data.common.degree_bits); + assert_eq!(&data.common, &cd); + pw.set_verifier_data_target(&verifier_data, &data.verifier_only); + let proof = data.prove(pw)?; + assert_eq!( + data.verifier_only.circuit_digest.elements[0], + proof.public_inputs[0] + ); + data.verify(proof.clone())?; + + // Second proof + let config = CircuitConfig::standard_recursion_config(); + let mut pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let verifier_data = VerifierCircuitTarget { + constants_sigmas_cap: builder.add_virtual_cap(builder.config.fri_config.cap_height), + circuit_digest: builder.add_virtual_hash(), + }; + builder.register_public_inputs(&verifier_data.circuit_digest.elements); + for i in 0..1 << builder.config.fri_config.cap_height { + builder.register_public_inputs(&verifier_data.constants_sigmas_cap.0[i].elements); + } + let dummy_verifier_data = VerifierCircuitTarget { + constants_sigmas_cap: builder.add_virtual_cap(builder.config.fri_config.cap_height), + circuit_digest: builder.add_virtual_hash(), + }; + let condition = builder.add_virtual_bool_target(); + builder.register_public_input(condition.target); + pw.set_bool_target(condition, true); + + let pt0 = builder.add_virtual_proof_with_pis(&data.common); + let pt1 = builder.add_virtual_proof_with_pis(&data.common); + + pw.set_proof_with_pis_target(&pt0, &proof); + pw.set_proof_with_pis_target(&pt1, &proof); + + builder.conditionally_verify_proof( + condition, + pt0, + &verifier_data, + pt1, + &dummy_verifier_data, + &data.common, + ); + + while builder.num_gates() < 1 << 13 { + builder.add_gate(NoopGate, vec![]); + } + + let data1 = builder.build::(); + assert_eq!(data.common, data1.common); + assert_eq!(data.verifier_only, data1.verifier_only); + dbg!(cd.degree_bits); + dbg!(data1.common.degree_bits); + pw.set_verifier_data_target(&verifier_data, &data.verifier_only); + pw.set_verifier_data_target(&dummy_verifier_data, &data.verifier_only); + let proof = data.prove(pw)?; + assert_eq!( + data.verifier_only.circuit_digest.elements[0], + proof.public_inputs[0] + ); + assert_eq!( + data1.verifier_only.circuit_digest.elements[0], + proof.public_inputs[0] + ); + data.verify(proof.clone())?; + + // Second proof + let config = CircuitConfig::standard_recursion_config(); + let mut pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let verifier_data = VerifierCircuitTarget { + constants_sigmas_cap: builder.add_virtual_cap(builder.config.fri_config.cap_height), + circuit_digest: builder.add_virtual_hash(), + }; + builder.register_public_inputs(&verifier_data.circuit_digest.elements); + for i in 0..1 << builder.config.fri_config.cap_height { + builder.register_public_inputs(&verifier_data.constants_sigmas_cap.0[i].elements); + } + let dummy_verifier_data = VerifierCircuitTarget { + constants_sigmas_cap: builder.add_virtual_cap(builder.config.fri_config.cap_height), + circuit_digest: builder.add_virtual_hash(), + }; + let condition = builder.add_virtual_bool_target(); + builder.register_public_input(condition.target); + pw.set_bool_target(condition, true); + + let pt0 = builder.add_virtual_proof_with_pis(&data.common); + let pt1 = builder.add_virtual_proof_with_pis(&data.common); + + pw.set_proof_with_pis_target(&pt0, &proof); + pw.set_proof_with_pis_target(&pt1, &proof); + + builder.conditionally_verify_proof( + condition, + pt0, + &verifier_data, + pt1, + &dummy_verifier_data, + &data.common, + ); + + while builder.num_gates() < 1 << 13 { + builder.add_gate(NoopGate, vec![]); + } + + let data2 = builder.build::(); + assert_eq!(data.common, data2.common); + assert_eq!(data.verifier_only, data2.verifier_only); + dbg!(cd.degree_bits); + dbg!(data1.common.degree_bits); + pw.set_verifier_data_target(&verifier_data, &data.verifier_only); + pw.set_verifier_data_target(&dummy_verifier_data, &data.verifier_only); + let proof = data.prove(pw)?; + assert_eq!( + data.verifier_only.circuit_digest.elements[0], + proof.public_inputs[0] + ); + assert_eq!( + data1.verifier_only.circuit_digest.elements[0], + proof.public_inputs[0] + ); data.verify(proof) } }