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 } ,
@@ -21,6 +20,7 @@ pub mod price;
2120pub mod proto;
2221#[ cfg( feature = "rpc" ) ]
2322pub mod server;
23+ pub mod signers;
2424pub mod store;
2525
2626use store:: AgreementStore ;
@@ -194,14 +194,16 @@ impl SignedIndexingAgreementVoucher {
194194 // TODO: Validate all values
195195 pub fn validate (
196196 & self ,
197+ signer_validator : & Arc < dyn signers:: SignerValidator > ,
197198 domain : & Eip712Domain ,
198199 expected_payee : & Address ,
199200 allowed_payers : impl AsRef < [ Address ] > ,
200201 ) -> Result < ( ) , DipsError > {
201202 let sig = Signature :: from_str ( & self . signature . to_string ( ) )
202203 . map_err ( |err| DipsError :: InvalidSignature ( err. to_string ( ) ) ) ?;
203204
204- let payer = sig
205+ let payer = self . voucher . payer ;
206+ let signer = sig
205207 . recover_address_from_prehash ( & self . voucher . eip712_signing_hash ( domain) )
206208 . map_err ( |err| DipsError :: InvalidSignature ( err. to_string ( ) ) ) ?;
207209
@@ -211,6 +213,10 @@ impl SignedIndexingAgreementVoucher {
211213 return Err ( DipsError :: PayerNotAuthorised ( payer) ) ;
212214 }
213215
216+ signer_validator
217+ . validate ( & payer, & signer)
218+ . map_err ( |_| DipsError :: SignerNotAuthorised ( signer) ) ?;
219+
214220 if !self . voucher . recipient . eq ( expected_payee) {
215221 return Err ( DipsError :: UnexpectedPayee {
216222 expected : * expected_payee,
@@ -288,14 +294,18 @@ impl CollectionRequest {
288294}
289295
290296pub async fn validate_and_create_agreement (
291- store : Arc < dyn AgreementStore > ,
297+ ctx : Arc < DipsServerContext > ,
292298 domain : & Eip712Domain ,
293299 expected_payee : & Address ,
294300 allowed_payers : impl AsRef < [ Address ] > ,
295301 voucher : Vec < u8 > ,
296- price_calculator : & PriceCalculator ,
297- ipfs_client : Arc < dyn IpfsFetcher > ,
298302) -> Result < Uuid , DipsError > {
303+ let DipsServerContext {
304+ store,
305+ ipfs_fetcher,
306+ price_calculator,
307+ signer_validator,
308+ } = ctx. as_ref ( ) ;
299309 let decoded_voucher = SignedIndexingAgreementVoucher :: abi_decode ( voucher. as_ref ( ) , true )
300310 . map_err ( |e| DipsError :: AbiDecoding ( e. to_string ( ) ) ) ?;
301311 let metadata = SubgraphIndexingVoucherMetadata :: abi_decode (
@@ -304,9 +314,9 @@ pub async fn validate_and_create_agreement(
304314 )
305315 . map_err ( |e| DipsError :: AbiDecoding ( e. to_string ( ) ) ) ?;
306316
307- decoded_voucher. validate ( domain, expected_payee, allowed_payers) ?;
317+ decoded_voucher. validate ( signer_validator , domain, expected_payee, allowed_payers) ?;
308318
309- let manifest = ipfs_client . fetch ( & metadata. subgraphDeploymentId ) . await ?;
319+ let manifest = ipfs_fetcher . fetch ( & metadata. subgraphDeploymentId ) . await ?;
310320 match manifest. network ( ) {
311321 Some ( chain_id) if chain_id == metadata. chainId => { }
312322 Some ( chain_id) => {
@@ -374,10 +384,11 @@ pub async fn validate_and_cancel_agreement(
374384#[ cfg( test) ]
375385mod test {
376386 use std:: {
377- sync :: Arc ,
387+ collections :: HashMap ,
378388 time:: { Duration , SystemTime , UNIX_EPOCH } ,
379389 } ;
380390
391+ use indexer_monitor:: EscrowAccounts ;
381392 use rand:: { distr:: Alphanumeric , Rng } ;
382393 use thegraph_core:: alloy:: {
383394 primitives:: { Address , FixedBytes , U256 } ,
@@ -388,9 +399,9 @@ mod test {
388399
389400 pub use crate :: store:: { AgreementStore , InMemoryAgreementStore } ;
390401 use crate :: {
391- dips_agreement_eip712_domain, dips_cancellation_eip712_domain, ipfs :: TestIpfsClient ,
392- price :: PriceCalculator , CancellationRequest , DipsError , IndexingAgreementVoucher ,
393- SignedIndexingAgreementVoucher , SubgraphIndexingVoucherMetadata ,
402+ dips_agreement_eip712_domain, dips_cancellation_eip712_domain, server :: DipsServerContext ,
403+ CancellationRequest , DipsError , IndexingAgreementVoucher , SignedIndexingAgreementVoucher ,
404+ SubgraphIndexingVoucherMetadata ,
394405 } ;
395406
396407 #[ tokio:: test]
@@ -428,22 +439,19 @@ mod test {
428439 let abi_voucher = voucher. abi_encode ( ) ;
429440 let id = Uuid :: from_bytes ( voucher. voucher . agreement_id . into ( ) ) ;
430441
431- let store = Arc :: new ( InMemoryAgreementStore :: default ( ) ) ;
432-
442+ let ctx = DipsServerContext :: for_testing ( ) ;
433443 let actual_id = super :: validate_and_create_agreement (
434- store . clone ( ) ,
444+ ctx . clone ( ) ,
435445 & domain,
436446 & payee_addr,
437447 vec ! [ payer_addr] ,
438448 abi_voucher,
439- & PriceCalculator :: for_testing ( ) ,
440- Arc :: new ( TestIpfsClient :: mainnet ( ) ) ,
441449 )
442450 . await
443451 . unwrap ( ) ;
444452 assert_eq ! ( actual_id, id) ;
445453
446- let stored_agreement = store. get_by_id ( actual_id) . await . unwrap ( ) . unwrap ( ) ;
454+ let stored_agreement = ctx . store . get_by_id ( actual_id) . await . unwrap ( ) . unwrap ( ) ;
447455
448456 assert_eq ! ( voucher, stored_agreement. voucher) ;
449457 assert ! ( !stored_agreement. cancelled) ;
@@ -452,6 +460,7 @@ mod test {
452460
453461 #[ test]
454462 fn voucher_signature_verification ( ) {
463+ let ctx = DipsServerContext :: for_testing ( ) ;
455464 let deployment_id = "Qmbg1qF4YgHjiVfsVt6a13ddrVcRtWyJQfD4LA3CwHM29f" . to_string ( ) ;
456465 let payee = PrivateKeySigner :: random ( ) ;
457466 let payee_addr = payee. address ( ) ;
@@ -484,23 +493,34 @@ mod test {
484493 let signed = voucher. sign ( & domain, payer) . unwrap ( ) ;
485494 assert_eq ! (
486495 signed
487- . validate( & domain, & payee_addr, vec![ ] )
496+ . validate( & ctx . signer_validator , & domain, & payee_addr, vec![ ] )
488497 . unwrap_err( )
489498 . to_string( ) ,
490499 DipsError :: PayerNotAuthorised ( voucher. payer) . to_string( )
491500 ) ;
492501 assert ! ( signed
493- . validate( & domain, & payee_addr, vec![ payer_addr] )
502+ . validate(
503+ & ctx. signer_validator,
504+ & domain,
505+ & payee_addr,
506+ vec![ payer_addr]
507+ )
494508 . is_ok( ) ) ;
495509 }
496510
497- #[ test]
498- fn check_voucher_modified ( ) {
499- let deployment_id = "Qmbg1qF4YgHjiVfsVt6a13ddrVcRtWyJQfD4LA3CwHM29f" . to_string ( ) ;
511+ #[ tokio:: test]
512+ async fn check_voucher_modified ( ) {
500513 let payee = PrivateKeySigner :: random ( ) ;
501514 let payee_addr = payee. address ( ) ;
502515 let payer = PrivateKeySigner :: random ( ) ;
503516 let payer_addr = payer. address ( ) ;
517+ let ctx = DipsServerContext :: for_testing_mocked_accounts ( EscrowAccounts :: new (
518+ HashMap :: default ( ) ,
519+ HashMap :: from_iter ( vec ! [ ( payer_addr, vec![ payer_addr] ) ] ) ,
520+ ) )
521+ . await ;
522+
523+ let deployment_id = "Qmbg1qF4YgHjiVfsVt6a13ddrVcRtWyJQfD4LA3CwHM29f" . to_string ( ) ;
504524
505525 let metadata = SubgraphIndexingVoucherMetadata {
506526 basePricePerEpoch : U256 :: from ( 10000_u64 ) ,
@@ -530,9 +550,14 @@ mod test {
530550
531551 assert ! ( matches!(
532552 signed
533- . validate( & domain, & payee_addr, vec![ payer_addr] )
553+ . validate(
554+ & ctx. signer_validator,
555+ & domain,
556+ & payee_addr,
557+ vec![ payer_addr]
558+ )
534559 . unwrap_err( ) ,
535- DipsError :: PayerNotAuthorised ( _)
560+ DipsError :: SignerNotAuthorised ( _)
536561 ) ) ;
537562 }
538563
@@ -603,9 +628,10 @@ mod test {
603628 dips_agreement_eip712_domain ( )
604629 }
605630
606- pub fn test_voucher (
631+ pub fn test_voucher_with_signer (
607632 & self ,
608633 metadata : SubgraphIndexingVoucherMetadata ,
634+ signer : PrivateKeySigner ,
609635 ) -> SignedIndexingAgreementVoucher {
610636 let agreement_id = Uuid :: now_v7 ( ) ;
611637
@@ -628,14 +654,21 @@ mod test {
628654 metadata : metadata. abi_encode ( ) . into ( ) ,
629655 } ;
630656
631- voucher. sign ( & domain, self . payer . clone ( ) ) . unwrap ( )
657+ voucher. sign ( & domain, signer) . unwrap ( )
658+ }
659+
660+ pub fn test_voucher (
661+ & self ,
662+ metadata : SubgraphIndexingVoucherMetadata ,
663+ ) -> SignedIndexingAgreementVoucher {
664+ self . test_voucher_with_signer ( metadata, self . payer . clone ( ) )
632665 }
633666 }
634667
635668 #[ tokio:: test]
636669 async fn test_create_and_cancel_agreement ( ) -> anyhow:: Result < ( ) > {
670+ let ctx = DipsServerContext :: for_testing ( ) ;
637671 let voucher_ctx = VoucherContext :: random ( ) ;
638- let store = Arc :: new ( InMemoryAgreementStore :: default ( ) ) ;
639672
640673 // Create metadata and voucher
641674 let metadata = SubgraphIndexingVoucherMetadata {
@@ -649,13 +682,11 @@ mod test {
649682
650683 // Create agreement
651684 let agreement_id = super :: validate_and_create_agreement (
652- store . clone ( ) ,
685+ ctx . clone ( ) ,
653686 & voucher_ctx. domain ( ) ,
654687 & voucher_ctx. payee . address ( ) ,
655688 vec ! [ voucher_ctx. payer. address( ) ] ,
656689 signed_voucher. encode_vec ( ) ,
657- & PriceCalculator :: for_testing ( ) ,
658- Arc :: new ( TestIpfsClient :: mainnet ( ) ) ,
659690 )
660691 . await ?;
661692
@@ -668,7 +699,7 @@ mod test {
668699
669700 // Cancel agreement
670701 let cancelled_id = super :: validate_and_cancel_agreement (
671- store. clone ( ) ,
702+ ctx . store . clone ( ) ,
672703 & cancel_domain,
673704 signed_cancel. encode_vec ( ) ,
674705 )
@@ -677,7 +708,7 @@ mod test {
677708 assert_eq ! ( agreement_id, cancelled_id) ;
678709
679710 // Verify agreement is cancelled
680- let stored_agreement = store. get_by_id ( agreement_id) . await ?. unwrap ( ) ;
711+ let stored_agreement = ctx . store . get_by_id ( agreement_id) . await ?. unwrap ( ) ;
681712 assert ! ( stored_agreement. cancelled) ;
682713
683714 Ok ( ( ) )
@@ -686,7 +717,14 @@ mod test {
686717 #[ tokio:: test]
687718 async fn test_create_validations_errors ( ) -> anyhow:: Result < ( ) > {
688719 let voucher_ctx = VoucherContext :: random ( ) ;
689- let store = Arc :: new ( InMemoryAgreementStore :: default ( ) ) ;
720+ let ctx = DipsServerContext :: for_testing_mocked_accounts ( EscrowAccounts :: new (
721+ HashMap :: default ( ) ,
722+ HashMap :: from_iter ( vec ! [ (
723+ voucher_ctx. payer. address( ) ,
724+ vec![ voucher_ctx. payer. address( ) ] ,
725+ ) ] ) ,
726+ ) )
727+ . await ;
690728
691729 let metadata = SubgraphIndexingVoucherMetadata {
692730 basePricePerEpoch : U256 :: from ( 10000_u64 ) ,
@@ -716,6 +754,9 @@ mod test {
716754 subgraphDeploymentId : voucher_ctx. deployment_id . clone ( ) ,
717755 } ;
718756
757+ let signer = PrivateKeySigner :: random ( ) ;
758+ let valid_voucher_invalid_signer =
759+ voucher_ctx. test_voucher_with_signer ( metadata. clone ( ) , signer. clone ( ) ) ;
719760 let valid_voucher = voucher_ctx. test_voucher ( metadata) ;
720761
721762 let expected_result: Vec < Result < [ u8 ; 16 ] , DipsError > > = vec ! [
@@ -728,23 +769,27 @@ mod test {
728769 100 ,
729770 "10" . to_string( ) ,
730771 ) ) ,
772+ Err ( DipsError :: SignerNotAuthorised ( signer. address( ) ) ) ,
731773 Ok ( valid_voucher
732774 . voucher
733775 . agreement_id
734776 . as_slice( )
735777 . try_into( )
736778 . unwrap( ) ) ,
737779 ] ;
738- let cases = vec ! [ wrong_network_voucher, low_price_voucher, valid_voucher] ;
780+ let cases = vec ! [
781+ wrong_network_voucher,
782+ low_price_voucher,
783+ valid_voucher_invalid_signer,
784+ valid_voucher,
785+ ] ;
739786 for ( voucher, result) in cases. into_iter ( ) . zip ( expected_result. into_iter ( ) ) {
740787 let out = super :: validate_and_create_agreement (
741- store . clone ( ) ,
788+ ctx . clone ( ) ,
742789 & voucher_ctx. domain ( ) ,
743790 & voucher_ctx. payee . address ( ) ,
744791 vec ! [ voucher_ctx. payer. address( ) ] ,
745792 voucher. encode_vec ( ) ,
746- & PriceCalculator :: for_testing ( ) ,
747- Arc :: new ( TestIpfsClient :: mainnet ( ) ) ,
748793 )
749794 . await ;
750795
0 commit comments