1010
1111use std:: sync:: LazyLock ;
1212
13- use base64:: { Engine , prelude:: BASE64_STANDARD } ;
1413use itertools:: Itertools ;
1514use num:: bigint:: BigUint ;
1615use plonky2:: {
@@ -52,16 +51,18 @@ use pod2::{
5251 } ,
5352 mainpod:: CalculateIdGadget ,
5453 } ,
55- mainpod,
56- mainpod:: calculate_id,
54+ deserialize_proof, mainpod,
55+ mainpod:: { calculate_id, get_common_data} ,
56+ serialize_proof,
5757 } ,
5858 measure_gates_begin, measure_gates_end,
5959 middleware:: {
60- self , AnchoredKey , DynError , EMPTY_HASH , F , Hash , KEY_TYPE , Key , NativePredicate , Params ,
61- Pod , PodId , RawValue , RecursivePod , SELF , Statement , ToFields , Value ,
60+ self , AnchoredKey , DynError , F , Hash , KEY_TYPE , Key , NativePredicate , Params , Pod , PodId ,
61+ RawValue , RecursivePod , SELF , Statement , ToFields , Value ,
6262 } ,
6363 timed,
6464} ;
65+ use serde:: { Deserialize , Serialize } ;
6566
6667use crate :: PodType ;
6768
@@ -192,16 +193,18 @@ impl EcdsaPodVerifyTarget {
192193 }
193194}
194195
195- #[ derive( Clone , Debug ) ]
196+ /// EcdsaPod implements the trait RecursivePod
197+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
196198pub struct EcdsaPod {
197199 params : Params ,
198200 id : PodId ,
199201 msg : Secp256K1Scalar ,
200202 pk : ECDSAPublicKey < Secp256K1 > ,
201203 proof : Proof ,
202- vds_hash : Hash ,
204+ vds_root : Hash ,
203205}
204- impl middleware:: RecursivePod for EcdsaPod {
206+
207+ impl RecursivePod for EcdsaPod {
205208 fn verifier_data ( & self ) -> VerifierOnlyCircuitData < C , D > {
206209 let ( _, circuit_data) = & * STANDARD_ECDSA_POD_DATA ;
207210 circuit_data. verifier_data ( ) . verifier_only
@@ -210,10 +213,65 @@ impl middleware::RecursivePod for EcdsaPod {
210213 self . proof . clone ( )
211214 }
212215 fn vds_root ( & self ) -> Hash {
213- self . vds_hash
216+ self . vds_root
217+ }
218+ fn deserialize_data (
219+ params : Params ,
220+ data : serde_json:: Value ,
221+ vds_root : Hash ,
222+ id : PodId ,
223+ ) -> Result < Box < dyn RecursivePod > , Box < DynError > > {
224+ let data: Data = serde_json:: from_value ( data) ?;
225+ let common = get_common_data ( & params) ?;
226+ let proof = deserialize_proof ( & common, & data. proof ) ?;
227+ Ok ( Box :: new ( Self {
228+ params,
229+ id,
230+ msg : data. msg ,
231+ pk : data. pk ,
232+ proof,
233+ vds_root,
234+ } ) )
214235 }
215236}
216237
238+ impl Pod for EcdsaPod {
239+ fn params ( & self ) -> & Params {
240+ & self . params
241+ }
242+ fn verify ( & self ) -> Result < ( ) , Box < DynError > > {
243+ Ok ( self . _verify ( ) . map_err ( Box :: new) ?)
244+ }
245+
246+ fn id ( & self ) -> PodId {
247+ self . id
248+ }
249+
250+ fn pod_type ( & self ) -> ( usize , & ' static str ) {
251+ ( PodType :: Ecdsa as usize , "Ecdsa" )
252+ }
253+
254+ fn pub_self_statements ( & self ) -> Vec < middleware:: Statement > {
255+ pub_self_statements ( self . msg , self . pk )
256+ }
257+
258+ fn serialize_data ( & self ) -> serde_json:: Value {
259+ serde_json:: to_value ( Data {
260+ proof : serialize_proof ( & self . proof ) ,
261+ msg : self . msg ,
262+ pk : self . pk ,
263+ } )
264+ . expect ( "serialization to json" )
265+ }
266+ }
267+
268+ #[ derive( Serialize , Deserialize ) ]
269+ struct Data {
270+ msg : Secp256K1Scalar ,
271+ pk : ECDSAPublicKey < Secp256K1 > ,
272+ proof : String ,
273+ }
274+
217275static STANDARD_ECDSA_POD_DATA : LazyLock < ( EcdsaPodVerifyTarget , CircuitData < F , C , D > ) > =
218276 LazyLock :: new ( || build ( ) . expect ( "successful build" ) ) ;
219277
@@ -288,7 +346,7 @@ impl EcdsaPod {
288346 msg,
289347 pk,
290348 proof : proof_with_pis. proof ,
291- vds_hash : EMPTY_HASH ,
349+ vds_root ,
292350 } )
293351 }
294352
@@ -330,32 +388,9 @@ impl EcdsaPod {
330388 . map_err ( |e| Error :: custom ( format ! ( "EcdsaPod proof verification failure: {:?}" , e) ) )
331389 }
332390}
333- impl Pod for EcdsaPod {
334- fn params ( & self ) -> & Params {
335- & self . params
336- }
337- fn verify ( & self ) -> Result < ( ) , Box < DynError > > {
338- Ok ( self . _verify ( ) . map_err ( Box :: new) ?)
339- }
340-
341- fn id ( & self ) -> PodId {
342- self . id
343- }
344-
345- fn pub_self_statements ( & self ) -> Vec < middleware:: Statement > {
346- pub_self_statements ( self . msg , self . pk )
347- }
348-
349- fn serialized_proof ( & self ) -> String {
350- let mut buffer = Vec :: new ( ) ;
351- use plonky2:: util:: serialization:: Write ;
352- buffer. write_proof ( & self . proof ) . unwrap ( ) ;
353- BASE64_STANDARD . encode ( buffer)
354- }
355- }
356391
357392fn type_statement ( ) -> Statement {
358- Statement :: ValueOf (
393+ Statement :: equal (
359394 AnchoredKey :: from ( ( SELF , KEY_TYPE ) ) ,
360395 Value :: from ( PodType :: Ecdsa ) ,
361396 )
@@ -379,14 +414,14 @@ fn pub_self_statements_target(
379414 let ak_msg = StatementArgTarget :: anchored_key ( builder, & ak_podid, & ak_key) ;
380415 let value = StatementArgTarget :: literal ( builder, & ValueTarget :: from_slice ( & msg_hash. elements ) ) ;
381416 let st_msg =
382- StatementTarget :: new_native ( builder, params, NativePredicate :: ValueOf , & [ ak_msg, value] ) ;
417+ StatementTarget :: new_native ( builder, params, NativePredicate :: Equal , & [ ak_msg, value] ) ;
383418
384419 let pk_hash = builder. hash_n_to_hash_no_pad :: < PoseidonHash > ( pk. to_vec ( ) ) ;
385420 let ak_key = builder. constant_value ( Key :: from ( KEY_ECDSA_PK ) . raw ( ) ) ;
386421 let ak_pk = StatementArgTarget :: anchored_key ( builder, & ak_podid, & ak_key) ;
387422 let value = StatementArgTarget :: literal ( builder, & ValueTarget :: from_slice ( & pk_hash. elements ) ) ;
388423 let st_pk =
389- StatementTarget :: new_native ( builder, params, NativePredicate :: ValueOf , & [ ak_pk, value] ) ;
424+ StatementTarget :: new_native ( builder, params, NativePredicate :: Equal , & [ ak_pk, value] ) ;
390425
391426 vec ! [ st_type, st_msg, st_pk]
392427}
@@ -402,7 +437,7 @@ fn pub_self_statements(
402437 let msg_limbs = secp_field_to_limbs ( msg. 0 ) ;
403438 let msg_hash = PoseidonHash :: hash_no_pad ( & msg_limbs) ;
404439
405- let st_msg = Statement :: ValueOf (
440+ let st_msg = Statement :: equal (
406441 AnchoredKey :: from ( ( SELF , KEY_SIGNED_MSG ) ) ,
407442 Value :: from ( RawValue ( msg_hash. elements ) ) ,
408443 ) ;
@@ -412,7 +447,7 @@ fn pub_self_statements(
412447 let pk_y_limbs = secp_field_to_limbs ( pk. 0 . y . 0 ) ;
413448 let pk_hash = PoseidonHash :: hash_no_pad ( & [ pk_x_limbs, pk_y_limbs] . concat ( ) ) ;
414449
415- let st_pk = Statement :: ValueOf (
450+ let st_pk = Statement :: equal (
416451 AnchoredKey :: from ( ( SELF , KEY_ECDSA_PK ) ) ,
417452 Value :: from ( RawValue ( pk_hash. elements ) ) ,
418453 ) ;
@@ -452,10 +487,12 @@ pub mod tests {
452487 ecdsa:: { ECDSAPublicKey , ECDSASecretKey , ECDSASignature , sign_message} ,
453488 secp256k1:: Secp256K1 ,
454489 } ;
455- use pod2:: { self , frontend:: MainPodBuilder , op} ;
490+ use pod2:: { self , frontend:: MainPodBuilder , middleware :: VDSet , op} ;
456491
457492 use super :: * ;
458493
494+ /// test to ensure that the pub_self_statements methods match between the
495+ /// in-circuit and the out-circuit implementations
459496 #[ test]
460497 fn test_pub_self_statements_target ( ) -> Result < ( ) > {
461498 let params = & Default :: default ( ) ;
@@ -514,8 +551,10 @@ pub mod tests {
514551 Ok ( ( ) )
515552 }
516553
517- #[ test]
518- fn test_ecdsa_pod_verify ( ) -> Result < ( ) > {
554+ fn compute_new_ecdsa_pod (
555+ sk : ECDSASecretKey < Secp256K1 > ,
556+ msg : Secp256K1Scalar ,
557+ ) -> Result < ( Box < dyn RecursivePod > , Params , VDSet ) > {
519558 // first generate all the circuits data so that it does not need to be
520559 // computed at further stages of the test (affecting the time reports)
521560 timed ! (
@@ -526,25 +565,42 @@ pub mod tests {
526565 let _ = & * pod2:: backends:: plonky2:: STANDARD_REC_MAIN_POD_CIRCUIT_DATA ;
527566 }
528567 ) ;
529-
530568 let params = Params {
531569 max_input_signed_pods : 0 ,
532570 ..Default :: default ( )
533571 } ;
534572
535- let sk = ECDSASecretKey :: < Secp256K1 > ( Secp256K1Scalar ( [ 123 , 456 , 789 , 123 ] ) ) ;
536- let msg = Secp256K1Scalar ( [ 321 , 654 , 987 , 321 ] ) ;
537-
538573 // compute the pk & signature
539574 let pk: ECDSAPublicKey < Secp256K1 > =
540575 ECDSAPublicKey ( ( CurveScalar ( sk. 0 ) * Secp256K1 :: GENERATOR_PROJECTIVE ) . to_affine ( ) ) ;
541576 let signature: ECDSASignature < Secp256K1 > = sign_message ( msg, sk) ;
542577
543- let vds_root = EMPTY_HASH ;
578+ let vds = vec ! [
579+ pod2:: backends:: plonky2:: STANDARD_REC_MAIN_POD_CIRCUIT_DATA
580+ . verifier_only
581+ . clone( ) ,
582+ pod2:: backends:: plonky2:: emptypod:: STANDARD_EMPTY_POD_DATA
583+ . 1
584+ . verifier_only
585+ . clone( ) ,
586+ STANDARD_ECDSA_POD_DATA . 1 . verifier_only. clone( ) ,
587+ ] ;
588+ let vdset = VDSet :: new ( params. max_depth_mt_vds , & vds) . unwrap ( ) ;
589+
590+ // generate a new EcdsaPod from the given msg, pk, signature
544591 let ecdsa_pod = timed ! (
545592 "EcdsaPod::new" ,
546- EcdsaPod :: new( & params, vds_root , msg, pk, signature) . unwrap( )
593+ EcdsaPod :: new( & params, vdset . root ( ) , msg, pk, signature) . unwrap( )
547594 ) ;
595+ Ok ( ( ecdsa_pod, params, vdset) )
596+ }
597+
598+ #[ test]
599+ fn test_ecdsa_pod ( ) -> Result < ( ) > {
600+ let sk = ECDSASecretKey :: < Secp256K1 > ( Secp256K1Scalar ( [ 123 , 456 , 789 , 123 ] ) ) ;
601+ let msg = Secp256K1Scalar ( [ 321 , 654 , 987 , 321 ] ) ;
602+
603+ let ( ecdsa_pod, params, vdset) = compute_new_ecdsa_pod ( sk, msg) ?;
548604
549605 ecdsa_pod. verify ( ) . unwrap ( ) ;
550606 // pod2::measure_gates_print!();
@@ -557,7 +613,7 @@ pub mod tests {
557613 } ;
558614
559615 // now generate a new MainPod from the ecdsa_pod
560- let mut main_pod_builder = MainPodBuilder :: new ( & params) ;
616+ let mut main_pod_builder = MainPodBuilder :: new ( & params, & vdset ) ;
561617 main_pod_builder. add_main_pod ( main_ecdsa_pod. clone ( ) ) ;
562618
563619 // add operation that ensures that the msg is as expected in the EcdsaPod
@@ -566,7 +622,8 @@ pub mod tests {
566622 let msg_copy = main_pod_builder
567623 . pub_op ( op ! (
568624 new_entry,
569- ( KEY_SIGNED_MSG , Value :: from( RawValue ( msg_hash. elements) ) )
625+ KEY_SIGNED_MSG ,
626+ Value :: from( RawValue ( msg_hash. elements) )
570627 ) )
571628 . unwrap ( ) ;
572629 main_pod_builder
@@ -595,4 +652,26 @@ pub mod tests {
595652
596653 Ok ( ( ) )
597654 }
655+
656+ #[ test]
657+ fn test_serialization ( ) -> Result < ( ) > {
658+ let sk = ECDSASecretKey :: < Secp256K1 > ( Secp256K1Scalar ( [ 123 , 456 , 789 , 123 ] ) ) ;
659+ let msg = Secp256K1Scalar ( [ 321 , 654 , 987 , 321 ] ) ;
660+
661+ let ( ecdsa_pod, params, vdset) = compute_new_ecdsa_pod ( sk, msg) ?;
662+
663+ ecdsa_pod. verify ( ) . unwrap ( ) ;
664+
665+ let ecdsa_pod = ( ecdsa_pod as Box < dyn Any > ) . downcast :: < EcdsaPod > ( ) . unwrap ( ) ;
666+ let data = ecdsa_pod. serialize_data ( ) ;
667+ let recovered_ecdsa_pod =
668+ EcdsaPod :: deserialize_data ( params, data, vdset. root ( ) , ecdsa_pod. id ) . unwrap ( ) ;
669+ let recovered_ecdsa_pod = ( recovered_ecdsa_pod as Box < dyn Any > )
670+ . downcast :: < EcdsaPod > ( )
671+ . unwrap ( ) ;
672+
673+ assert_eq ! ( recovered_ecdsa_pod, ecdsa_pod) ;
674+
675+ Ok ( ( ) )
676+ }
598677}
0 commit comments