@@ -19,9 +19,9 @@ use plonky2::{
1919 plonk:: proof:: { ProofWithPublicInputs , ProofWithPublicInputsTarget } ,
2020} ;
2121
22- use crate :: backends:: plonky2:: basetypes:: { Hash , Value , C , D , EMPTY_HASH , EMPTY_VALUE , F } ;
22+ use super :: signature:: { PublicKey , SecretKey , Signature , DUMMY_PUBLIC_INPUTS , DUMMY_SIGNATURE } ;
23+ use crate :: backends:: plonky2:: basetypes:: { Hash , Proof , Value , C , D , EMPTY_HASH , EMPTY_VALUE , F } ;
2324use crate :: backends:: plonky2:: circuits:: common:: { CircuitBuilderPod , ValueTarget } ;
24- use crate :: backends:: plonky2:: primitives:: signature:: { PublicKey , Signature } ;
2525
2626lazy_static ! {
2727 /// SignatureVerifyGadget VerifierCircuitData
@@ -34,7 +34,9 @@ pub struct SignatureTarget {
3434 verifier_data_targ : VerifierCircuitTarget ,
3535 selector : BoolTarget ,
3636 pk : ValueTarget ,
37+ // proof of the SignatureInternalCircuit (=signature::Signature.0)
3738 proof : ProofWithPublicInputsTarget < D > ,
39+ dummy_proof : ProofWithPublicInputsTarget < D > ,
3840}
3941
4042impl SignatureVerifyGadget {
@@ -62,23 +64,29 @@ impl SignatureVerifyGadget {
6264 builder. add_virtual_verifier_data ( common_data. config . fri_config . cap_height ) ;
6365
6466 let proof_targ = builder. add_virtual_proof_with_pis ( & common_data) ;
65- builder . verify_proof :: < C > ( & proof_targ , & verifier_data_targ , & common_data ) ;
67+
6668 // NOTE: we would use the `conditional_verify_proof_or_dummy` method,
6769 // but since we're using the `standard_recursion_zk_config` (with zk),
68- // internally it fails to generate the `dummy_circuit`. So for the
69- // moment we use `verify_proof` (not-conditional).
70- // builder.conditionally_verify_proof_or_dummy::<C>(
71- // selector,
72- // &proof_targ,
73- // &verifier_data_targ,
74- // &common_data,
75- // )?;
70+ // internally it fails to generate the `dummy_circuit`, which mentions
71+ // that degree calculation could be off if zk is enabled. So we use
72+ // `conditional_verify_proof` feeding in our own dummy_proof
73+ // (signature::DUMMY_PROOF).
74+ let dummy_proof_targ = builder. add_virtual_proof_with_pis ( & common_data) ;
75+ builder. conditionally_verify_proof :: < C > (
76+ selector,
77+ & proof_targ,
78+ & verifier_data_targ,
79+ & dummy_proof_targ,
80+ & verifier_data_targ,
81+ & common_data,
82+ ) ;
7683
7784 Ok ( SignatureTarget {
7885 selector,
7986 proof : proof_targ,
8087 pk : pk_targ,
8188 verifier_data_targ,
89+ dummy_proof : dummy_proof_targ,
8290 } )
8391 }
8492}
@@ -108,6 +116,14 @@ impl SignatureTarget {
108116 } ,
109117 ) ?;
110118
119+ pw. set_proof_with_pis_target (
120+ & self . dummy_proof ,
121+ & ProofWithPublicInputs {
122+ proof : DUMMY_SIGNATURE . 0 . clone ( ) ,
123+ public_inputs : DUMMY_PUBLIC_INPUTS . clone ( ) ,
124+ } ,
125+ ) ?;
126+
111127 pw. set_verifier_data_target (
112128 & self . verifier_data_targ ,
113129 & super :: signature:: VP . 0 . verifier_only ,
@@ -124,9 +140,8 @@ pub mod tests {
124140
125141 use super :: * ;
126142
127- // Note: this test must be run with the `--release` flag.
128143 #[ test]
129- fn test_signature_gate ( ) -> Result < ( ) > {
144+ fn test_signature_gadget ( ) -> Result < ( ) > {
130145 // generate a valid signature
131146 let sk = SecretKey :: new ( ) ;
132147 let pk = sk. public_key ( ) ;
@@ -155,4 +170,54 @@ pub mod tests {
155170
156171 Ok ( ( ) )
157172 }
173+
174+ #[ test]
175+ fn test_signature_gadget_disabled ( ) -> Result < ( ) > {
176+ // generate a valid signature
177+ let sk = SecretKey :: new ( ) ;
178+ let pk = sk. public_key ( ) ;
179+ let msg = Value :: from ( 42 ) ;
180+ let sig = sk. sign ( msg) ?;
181+ // verification should pass
182+ sig. verify ( & pk, msg) ?;
183+
184+ // replace the message, so that verifications should fail
185+ let msg = Value :: from ( 24 ) ;
186+ // expect signature native verification to fail
187+ let v = sig. verify ( & pk, Value :: from ( 24 ) ) ;
188+ assert ! ( v. is_err( ) , "should fail to verify" ) ;
189+
190+ // circuit
191+ let config = CircuitConfig :: standard_recursion_zk_config ( ) ;
192+ let mut builder = CircuitBuilder :: < F , D > :: new ( config) ;
193+ let mut pw = PartialWitness :: < F > :: new ( ) ;
194+ let targets = SignatureVerifyGadget { } . eval ( & mut builder) ?;
195+ targets. set_targets ( & mut pw, true , pk. clone ( ) , msg, sig. clone ( ) ) ?; // selector=true
196+
197+ // generate proof, and expect it to fail
198+ let data = builder. build :: < C > ( ) ;
199+ assert ! ( data. prove( pw) . is_err( ) ) ; // expect prove to fail
200+
201+ // build the circuit again, but now disable the selector that disables
202+ // the in-circuit signature verification
203+ let config = CircuitConfig :: standard_recursion_zk_config ( ) ;
204+ let mut builder = CircuitBuilder :: < F , D > :: new ( config) ;
205+ let mut pw = PartialWitness :: < F > :: new ( ) ;
206+
207+ let targets = SignatureVerifyGadget { } . eval ( & mut builder) ?;
208+ targets. set_targets ( & mut pw, false , pk, msg, sig) ?; // selector=false
209+
210+ // generate & verify proof
211+ let data = builder. build :: < C > ( ) ;
212+ let proof = data. prove ( pw) ?;
213+ data. verify ( proof. clone ( ) ) ?;
214+
215+ // verify the proof with the lazy_static loaded verifier_data (S_VD)
216+ S_VD . verify ( ProofWithPublicInputs {
217+ proof : proof. proof . clone ( ) ,
218+ public_inputs : vec ! [ ] ,
219+ } ) ?;
220+
221+ Ok ( ( ) )
222+ }
158223}
0 commit comments