@@ -9,6 +9,7 @@ use std::str::FromStr;
9
9
#[ cfg( not( target_os = "zkvm" ) ) ]
10
10
use alloy:: {
11
11
contract:: Error as ContractErr ,
12
+ primitives:: SignatureError ,
12
13
signers:: { Error as SignerErr , Signature , SignerSync } ,
13
14
sol_types:: { Error as DecoderErr , SolInterface , SolStruct } ,
14
15
transports:: TransportError ,
@@ -182,6 +183,25 @@ impl ProvingRequest {
182
183
let hash = self . eip712_signing_hash ( & domain. alloy_struct ( ) ) ;
183
184
signer. sign_hash_sync ( & hash)
184
185
}
186
+
187
+ /// Verifies the proving request signature with the given signer and EIP-712 domain derived from
188
+ /// the given contract address and chain ID.
189
+ pub fn verify_signature (
190
+ & self ,
191
+ signature : & Bytes ,
192
+ contract_addr : Address ,
193
+ chain_id : u64 ,
194
+ ) -> Result < ( ) , SignerErr > {
195
+ let sig = Signature :: try_from ( signature. as_ref ( ) ) ?;
196
+ let domain = eip712_domain ( contract_addr, chain_id) ;
197
+ let hash = self . eip712_signing_hash ( & domain. alloy_struct ( ) ) ;
198
+ let addr = sig. recover_address_from_prehash ( & hash) ?;
199
+ if addr == self . client_address ( ) {
200
+ Ok ( ( ) )
201
+ } else {
202
+ Err ( SignerErr :: SignatureError ( SignatureError :: FromBytes ( "Address mismatch" ) ) )
203
+ }
204
+ }
185
205
}
186
206
187
207
impl Requirements {
@@ -587,3 +607,76 @@ pub mod test_utils {
587
607
}
588
608
}
589
609
}
610
+
611
+ #[ cfg( test) ]
612
+ mod tests {
613
+ use super :: * ;
614
+ use alloy:: signers:: local:: PrivateKeySigner ;
615
+
616
+ fn create_order (
617
+ signer : & impl SignerSync ,
618
+ signer_addr : Address ,
619
+ order_id : u32 ,
620
+ contract_addr : Address ,
621
+ chain_id : u64 ,
622
+ ) -> ( ProvingRequest , [ u8 ; 65 ] ) {
623
+ let request_id = request_id ( & signer_addr, order_id) ;
624
+
625
+ let req = ProvingRequest {
626
+ id : request_id,
627
+ requirements : Requirements {
628
+ imageId : B256 :: ZERO ,
629
+ predicate : Predicate {
630
+ predicateType : PredicateType :: PrefixMatch ,
631
+ data : Default :: default ( ) ,
632
+ } ,
633
+ } ,
634
+ imageUrl : "test" . to_string ( ) ,
635
+ input : Input { inputType : InputType :: Url , data : Default :: default ( ) } ,
636
+ offer : Offer {
637
+ minPrice : U96 :: from ( 0 ) ,
638
+ maxPrice : U96 :: from ( 1 ) ,
639
+ biddingStart : 0 ,
640
+ timeout : 1000 ,
641
+ rampUpPeriod : 1 ,
642
+ lockinStake : U96 :: from ( 0 ) ,
643
+ } ,
644
+ } ;
645
+
646
+ let client_sig = req. sign_request ( & signer, contract_addr, chain_id) . unwrap ( ) ;
647
+
648
+ ( req, client_sig. as_bytes ( ) )
649
+ }
650
+
651
+ #[ test]
652
+ fn validate_sig ( ) {
653
+ let signer: PrivateKeySigner =
654
+ "6f142508b4eea641e33cb2a0161221105086a84584c74245ca463a49effea30b" . parse ( ) . unwrap ( ) ;
655
+ let order_id: u32 = 1 ;
656
+ let contract_addr = Address :: ZERO ;
657
+ let chain_id = 1 ;
658
+ let signer_addr = signer. address ( ) ;
659
+
660
+ let ( req, client_sig) =
661
+ create_order ( & signer, signer_addr, order_id, contract_addr, chain_id) ;
662
+
663
+ req. verify_signature ( & Bytes :: from ( client_sig) , contract_addr, chain_id) . unwrap ( ) ;
664
+ }
665
+
666
+ #[ test]
667
+ #[ should_panic( expected = "SignatureError" ) ]
668
+ fn invalid_sig ( ) {
669
+ let signer: PrivateKeySigner =
670
+ "6f142508b4eea641e33cb2a0161221105086a84584c74245ca463a49effea30b" . parse ( ) . unwrap ( ) ;
671
+ let order_id: u32 = 1 ;
672
+ let contract_addr = Address :: ZERO ;
673
+ let chain_id = 1 ;
674
+ let signer_addr = signer. address ( ) ;
675
+
676
+ let ( req, mut client_sig) =
677
+ create_order ( & signer, signer_addr, order_id, contract_addr, chain_id) ;
678
+
679
+ client_sig[ 0 ] = 1 ;
680
+ req. verify_signature ( & Bytes :: from ( client_sig) , contract_addr, chain_id) . unwrap ( ) ;
681
+ }
682
+ }
0 commit comments