33
44use std:: { str:: FromStr , sync:: Arc } ;
55
6- use ipfs:: IpfsFetcher ;
7- use price:: PriceCalculator ;
6+ use server:: DipsServerContext ;
87use thegraph_core:: alloy:: {
98 core:: primitives:: Address ,
109 primitives:: { b256, ChainId , PrimitiveSignature as Signature , Uint , B256 } ,
@@ -18,6 +17,7 @@ pub mod ipfs;
1817pub mod price;
1918pub mod proto;
2019pub mod server;
20+ pub mod signers;
2121pub mod store;
2222
2323use store:: AgreementStore ;
@@ -190,14 +190,16 @@ impl SignedIndexingAgreementVoucher {
190190 // TODO: Validate all values
191191 pub fn validate (
192192 & self ,
193+ signer_validator : & Arc < dyn signers:: SignerValidator > ,
193194 domain : & Eip712Domain ,
194195 expected_payee : & Address ,
195196 allowed_payers : impl AsRef < [ Address ] > ,
196197 ) -> Result < ( ) , DipsError > {
197198 let sig = Signature :: from_str ( & self . signature . to_string ( ) )
198199 . map_err ( |err| DipsError :: InvalidSignature ( err. to_string ( ) ) ) ?;
199200
200- let payer = sig
201+ let payer = self . voucher . payer ;
202+ let signer = sig
201203 . recover_address_from_prehash ( & self . voucher . eip712_signing_hash ( domain) )
202204 . map_err ( |err| DipsError :: InvalidSignature ( err. to_string ( ) ) ) ?;
203205
@@ -207,6 +209,10 @@ impl SignedIndexingAgreementVoucher {
207209 return Err ( DipsError :: PayerNotAuthorised ( payer) ) ;
208210 }
209211
212+ signer_validator
213+ . validate ( & payer, & signer)
214+ . map_err ( |_| DipsError :: SignerNotAuthorised ( signer) ) ?;
215+
210216 if !self . voucher . recipient . eq ( expected_payee) {
211217 return Err ( DipsError :: UnexpectedPayee {
212218 expected : * expected_payee,
@@ -284,14 +290,18 @@ impl CollectionRequest {
284290}
285291
286292pub async fn validate_and_create_agreement (
287- store : Arc < dyn AgreementStore > ,
293+ ctx : Arc < DipsServerContext > ,
288294 domain : & Eip712Domain ,
289295 expected_payee : & Address ,
290296 allowed_payers : impl AsRef < [ Address ] > ,
291297 voucher : Vec < u8 > ,
292- price_calculator : & PriceCalculator ,
293- ipfs_client : Arc < dyn IpfsFetcher > ,
294298) -> Result < Uuid , DipsError > {
299+ let DipsServerContext {
300+ store,
301+ ipfs_fetcher,
302+ price_calculator,
303+ signer_validator,
304+ } = ctx. as_ref ( ) ;
295305 let decoded_voucher = SignedIndexingAgreementVoucher :: abi_decode ( voucher. as_ref ( ) , true )
296306 . map_err ( |e| DipsError :: AbiDecoding ( e. to_string ( ) ) ) ?;
297307 let metadata = SubgraphIndexingVoucherMetadata :: abi_decode (
@@ -300,9 +310,9 @@ pub async fn validate_and_create_agreement(
300310 )
301311 . map_err ( |e| DipsError :: AbiDecoding ( e. to_string ( ) ) ) ?;
302312
303- decoded_voucher. validate ( domain, expected_payee, allowed_payers) ?;
313+ decoded_voucher. validate ( signer_validator , domain, expected_payee, allowed_payers) ?;
304314
305- let manifest = ipfs_client . fetch ( & metadata. subgraphDeploymentId ) . await ?;
315+ let manifest = ipfs_fetcher . fetch ( & metadata. subgraphDeploymentId ) . await ?;
306316 match manifest. network ( ) {
307317 Some ( chain_id) if chain_id == metadata. chainId => { }
308318 Some ( chain_id) => {
@@ -370,10 +380,11 @@ pub async fn validate_and_cancel_agreement(
370380#[ cfg( test) ]
371381mod test {
372382 use std:: {
373- sync :: Arc ,
383+ collections :: HashMap ,
374384 time:: { Duration , SystemTime , UNIX_EPOCH } ,
375385 } ;
376386
387+ use indexer_monitor:: EscrowAccounts ;
377388 use rand:: { distr:: Alphanumeric , Rng } ;
378389 use thegraph_core:: alloy:: {
379390 primitives:: { Address , FixedBytes , U256 } ,
@@ -384,9 +395,9 @@ mod test {
384395
385396 pub use crate :: store:: { AgreementStore , InMemoryAgreementStore } ;
386397 use crate :: {
387- dips_agreement_eip712_domain, dips_cancellation_eip712_domain, ipfs :: TestIpfsClient ,
388- price :: PriceCalculator , CancellationRequest , DipsError , IndexingAgreementVoucher ,
389- SignedIndexingAgreementVoucher , SubgraphIndexingVoucherMetadata ,
398+ dips_agreement_eip712_domain, dips_cancellation_eip712_domain, server :: DipsServerContext ,
399+ CancellationRequest , DipsError , IndexingAgreementVoucher , SignedIndexingAgreementVoucher ,
400+ SubgraphIndexingVoucherMetadata ,
390401 } ;
391402
392403 #[ tokio:: test]
@@ -424,22 +435,19 @@ mod test {
424435 let abi_voucher = voucher. abi_encode ( ) ;
425436 let id = Uuid :: from_bytes ( voucher. voucher . agreement_id . into ( ) ) ;
426437
427- let store = Arc :: new ( InMemoryAgreementStore :: default ( ) ) ;
428-
438+ let ctx = DipsServerContext :: for_testing ( ) ;
429439 let actual_id = super :: validate_and_create_agreement (
430- store . clone ( ) ,
440+ ctx . clone ( ) ,
431441 & domain,
432442 & payee_addr,
433443 vec ! [ payer_addr] ,
434444 abi_voucher,
435- & PriceCalculator :: for_testing ( ) ,
436- Arc :: new ( TestIpfsClient :: mainnet ( ) ) ,
437445 )
438446 . await
439447 . unwrap ( ) ;
440448 assert_eq ! ( actual_id, id) ;
441449
442- let stored_agreement = store. get_by_id ( actual_id) . await . unwrap ( ) . unwrap ( ) ;
450+ let stored_agreement = ctx . store . get_by_id ( actual_id) . await . unwrap ( ) . unwrap ( ) ;
443451
444452 assert_eq ! ( voucher, stored_agreement. voucher) ;
445453 assert ! ( !stored_agreement. cancelled) ;
@@ -448,6 +456,7 @@ mod test {
448456
449457 #[ test]
450458 fn voucher_signature_verification ( ) {
459+ let ctx = DipsServerContext :: for_testing ( ) ;
451460 let deployment_id = "Qmbg1qF4YgHjiVfsVt6a13ddrVcRtWyJQfD4LA3CwHM29f" . to_string ( ) ;
452461 let payee = PrivateKeySigner :: random ( ) ;
453462 let payee_addr = payee. address ( ) ;
@@ -480,23 +489,34 @@ mod test {
480489 let signed = voucher. sign ( & domain, payer) . unwrap ( ) ;
481490 assert_eq ! (
482491 signed
483- . validate( & domain, & payee_addr, vec![ ] )
492+ . validate( & ctx . signer_validator , & domain, & payee_addr, vec![ ] )
484493 . unwrap_err( )
485494 . to_string( ) ,
486495 DipsError :: PayerNotAuthorised ( voucher. payer) . to_string( )
487496 ) ;
488497 assert ! ( signed
489- . validate( & domain, & payee_addr, vec![ payer_addr] )
498+ . validate(
499+ & ctx. signer_validator,
500+ & domain,
501+ & payee_addr,
502+ vec![ payer_addr]
503+ )
490504 . is_ok( ) ) ;
491505 }
492506
493- #[ test]
494- fn check_voucher_modified ( ) {
495- let deployment_id = "Qmbg1qF4YgHjiVfsVt6a13ddrVcRtWyJQfD4LA3CwHM29f" . to_string ( ) ;
507+ #[ tokio:: test]
508+ async fn check_voucher_modified ( ) {
496509 let payee = PrivateKeySigner :: random ( ) ;
497510 let payee_addr = payee. address ( ) ;
498511 let payer = PrivateKeySigner :: random ( ) ;
499512 let payer_addr = payer. address ( ) ;
513+ let ctx = DipsServerContext :: for_testing_mocked_accounts ( EscrowAccounts :: new (
514+ HashMap :: default ( ) ,
515+ HashMap :: from_iter ( vec ! [ ( payer_addr, vec![ payer_addr] ) ] ) ,
516+ ) )
517+ . await ;
518+
519+ let deployment_id = "Qmbg1qF4YgHjiVfsVt6a13ddrVcRtWyJQfD4LA3CwHM29f" . to_string ( ) ;
500520
501521 let metadata = SubgraphIndexingVoucherMetadata {
502522 basePricePerEpoch : U256 :: from ( 10000_u64 ) ,
@@ -526,9 +546,14 @@ mod test {
526546
527547 assert ! ( matches!(
528548 signed
529- . validate( & domain, & payee_addr, vec![ payer_addr] )
549+ . validate(
550+ & ctx. signer_validator,
551+ & domain,
552+ & payee_addr,
553+ vec![ payer_addr]
554+ )
530555 . unwrap_err( ) ,
531- DipsError :: PayerNotAuthorised ( _)
556+ DipsError :: SignerNotAuthorised ( _)
532557 ) ) ;
533558 }
534559
@@ -599,9 +624,10 @@ mod test {
599624 dips_agreement_eip712_domain ( )
600625 }
601626
602- pub fn test_voucher (
627+ pub fn test_voucher_with_signer (
603628 & self ,
604629 metadata : SubgraphIndexingVoucherMetadata ,
630+ signer : PrivateKeySigner ,
605631 ) -> SignedIndexingAgreementVoucher {
606632 let agreement_id = Uuid :: now_v7 ( ) ;
607633
@@ -624,14 +650,21 @@ mod test {
624650 metadata : metadata. abi_encode ( ) . into ( ) ,
625651 } ;
626652
627- voucher. sign ( & domain, self . payer . clone ( ) ) . unwrap ( )
653+ voucher. sign ( & domain, signer) . unwrap ( )
654+ }
655+
656+ pub fn test_voucher (
657+ & self ,
658+ metadata : SubgraphIndexingVoucherMetadata ,
659+ ) -> SignedIndexingAgreementVoucher {
660+ self . test_voucher_with_signer ( metadata, self . payer . clone ( ) )
628661 }
629662 }
630663
631664 #[ tokio:: test]
632665 async fn test_create_and_cancel_agreement ( ) -> anyhow:: Result < ( ) > {
666+ let ctx = DipsServerContext :: for_testing ( ) ;
633667 let voucher_ctx = VoucherContext :: random ( ) ;
634- let store = Arc :: new ( InMemoryAgreementStore :: default ( ) ) ;
635668
636669 // Create metadata and voucher
637670 let metadata = SubgraphIndexingVoucherMetadata {
@@ -645,13 +678,11 @@ mod test {
645678
646679 // Create agreement
647680 let agreement_id = super :: validate_and_create_agreement (
648- store . clone ( ) ,
681+ ctx . clone ( ) ,
649682 & voucher_ctx. domain ( ) ,
650683 & voucher_ctx. payee . address ( ) ,
651684 vec ! [ voucher_ctx. payer. address( ) ] ,
652685 signed_voucher. encode_vec ( ) ,
653- & PriceCalculator :: for_testing ( ) ,
654- Arc :: new ( TestIpfsClient :: mainnet ( ) ) ,
655686 )
656687 . await ?;
657688
@@ -664,7 +695,7 @@ mod test {
664695
665696 // Cancel agreement
666697 let cancelled_id = super :: validate_and_cancel_agreement (
667- store. clone ( ) ,
698+ ctx . store . clone ( ) ,
668699 & cancel_domain,
669700 signed_cancel. encode_vec ( ) ,
670701 )
@@ -673,7 +704,7 @@ mod test {
673704 assert_eq ! ( agreement_id, cancelled_id) ;
674705
675706 // Verify agreement is cancelled
676- let stored_agreement = store. get_by_id ( agreement_id) . await ?. unwrap ( ) ;
707+ let stored_agreement = ctx . store . get_by_id ( agreement_id) . await ?. unwrap ( ) ;
677708 assert ! ( stored_agreement. cancelled) ;
678709
679710 Ok ( ( ) )
@@ -682,7 +713,14 @@ mod test {
682713 #[ tokio:: test]
683714 async fn test_create_validations_errors ( ) -> anyhow:: Result < ( ) > {
684715 let voucher_ctx = VoucherContext :: random ( ) ;
685- let store = Arc :: new ( InMemoryAgreementStore :: default ( ) ) ;
716+ let ctx = DipsServerContext :: for_testing_mocked_accounts ( EscrowAccounts :: new (
717+ HashMap :: default ( ) ,
718+ HashMap :: from_iter ( vec ! [ (
719+ voucher_ctx. payer. address( ) ,
720+ vec![ voucher_ctx. payer. address( ) ] ,
721+ ) ] ) ,
722+ ) )
723+ . await ;
686724
687725 let metadata = SubgraphIndexingVoucherMetadata {
688726 basePricePerEpoch : U256 :: from ( 10000_u64 ) ,
@@ -712,6 +750,9 @@ mod test {
712750 subgraphDeploymentId : voucher_ctx. deployment_id . clone ( ) ,
713751 } ;
714752
753+ let signer = PrivateKeySigner :: random ( ) ;
754+ let valid_voucher_invalid_signer =
755+ voucher_ctx. test_voucher_with_signer ( metadata. clone ( ) , signer. clone ( ) ) ;
715756 let valid_voucher = voucher_ctx. test_voucher ( metadata) ;
716757
717758 let expected_result: Vec < Result < [ u8 ; 16 ] , DipsError > > = vec ! [
@@ -724,23 +765,27 @@ mod test {
724765 100 ,
725766 "10" . to_string( ) ,
726767 ) ) ,
768+ Err ( DipsError :: SignerNotAuthorised ( signer. address( ) ) ) ,
727769 Ok ( valid_voucher
728770 . voucher
729771 . agreement_id
730772 . as_slice( )
731773 . try_into( )
732774 . unwrap( ) ) ,
733775 ] ;
734- let cases = vec ! [ wrong_network_voucher, low_price_voucher, valid_voucher] ;
776+ let cases = vec ! [
777+ wrong_network_voucher,
778+ low_price_voucher,
779+ valid_voucher_invalid_signer,
780+ valid_voucher,
781+ ] ;
735782 for ( voucher, result) in cases. into_iter ( ) . zip ( expected_result. into_iter ( ) ) {
736783 let out = super :: validate_and_create_agreement (
737- store . clone ( ) ,
784+ ctx . clone ( ) ,
738785 & voucher_ctx. domain ( ) ,
739786 & voucher_ctx. payee . address ( ) ,
740787 vec ! [ voucher_ctx. payer. address( ) ] ,
741788 voucher. encode_vec ( ) ,
742- & PriceCalculator :: for_testing ( ) ,
743- Arc :: new ( TestIpfsClient :: mainnet ( ) ) ,
744789 )
745790 . await ;
746791
0 commit comments