3
3
4
4
use std:: { str:: FromStr , sync:: Arc } ;
5
5
6
- use ipfs:: IpfsFetcher ;
7
- use price:: PriceCalculator ;
6
+ use server:: DipsServerContext ;
8
7
use thegraph_core:: alloy:: {
9
8
core:: primitives:: Address ,
10
9
primitives:: { b256, ChainId , PrimitiveSignature as Signature , Uint , B256 } ,
@@ -21,6 +20,7 @@ pub mod price;
21
20
pub mod proto;
22
21
#[ cfg( feature = "rpc" ) ]
23
22
pub mod server;
23
+ pub mod signers;
24
24
pub mod store;
25
25
26
26
use store:: AgreementStore ;
@@ -194,14 +194,16 @@ impl SignedIndexingAgreementVoucher {
194
194
// TODO: Validate all values
195
195
pub fn validate (
196
196
& self ,
197
+ signer_validator : & Arc < dyn signers:: SignerValidator > ,
197
198
domain : & Eip712Domain ,
198
199
expected_payee : & Address ,
199
200
allowed_payers : impl AsRef < [ Address ] > ,
200
201
) -> Result < ( ) , DipsError > {
201
202
let sig = Signature :: from_str ( & self . signature . to_string ( ) )
202
203
. map_err ( |err| DipsError :: InvalidSignature ( err. to_string ( ) ) ) ?;
203
204
204
- let payer = sig
205
+ let payer = self . voucher . payer ;
206
+ let signer = sig
205
207
. recover_address_from_prehash ( & self . voucher . eip712_signing_hash ( domain) )
206
208
. map_err ( |err| DipsError :: InvalidSignature ( err. to_string ( ) ) ) ?;
207
209
@@ -211,6 +213,10 @@ impl SignedIndexingAgreementVoucher {
211
213
return Err ( DipsError :: PayerNotAuthorised ( payer) ) ;
212
214
}
213
215
216
+ signer_validator
217
+ . validate ( & payer, & signer)
218
+ . map_err ( |_| DipsError :: SignerNotAuthorised ( signer) ) ?;
219
+
214
220
if !self . voucher . recipient . eq ( expected_payee) {
215
221
return Err ( DipsError :: UnexpectedPayee {
216
222
expected : * expected_payee,
@@ -288,14 +294,18 @@ impl CollectionRequest {
288
294
}
289
295
290
296
pub async fn validate_and_create_agreement (
291
- store : Arc < dyn AgreementStore > ,
297
+ ctx : Arc < DipsServerContext > ,
292
298
domain : & Eip712Domain ,
293
299
expected_payee : & Address ,
294
300
allowed_payers : impl AsRef < [ Address ] > ,
295
301
voucher : Vec < u8 > ,
296
- price_calculator : & PriceCalculator ,
297
- ipfs_client : Arc < dyn IpfsFetcher > ,
298
302
) -> Result < Uuid , DipsError > {
303
+ let DipsServerContext {
304
+ store,
305
+ ipfs_fetcher,
306
+ price_calculator,
307
+ signer_validator,
308
+ } = ctx. as_ref ( ) ;
299
309
let decoded_voucher = SignedIndexingAgreementVoucher :: abi_decode ( voucher. as_ref ( ) , true )
300
310
. map_err ( |e| DipsError :: AbiDecoding ( e. to_string ( ) ) ) ?;
301
311
let metadata = SubgraphIndexingVoucherMetadata :: abi_decode (
@@ -304,9 +314,9 @@ pub async fn validate_and_create_agreement(
304
314
)
305
315
. map_err ( |e| DipsError :: AbiDecoding ( e. to_string ( ) ) ) ?;
306
316
307
- decoded_voucher. validate ( domain, expected_payee, allowed_payers) ?;
317
+ decoded_voucher. validate ( signer_validator , domain, expected_payee, allowed_payers) ?;
308
318
309
- let manifest = ipfs_client . fetch ( & metadata. subgraphDeploymentId ) . await ?;
319
+ let manifest = ipfs_fetcher . fetch ( & metadata. subgraphDeploymentId ) . await ?;
310
320
match manifest. network ( ) {
311
321
Some ( chain_id) if chain_id == metadata. chainId => { }
312
322
Some ( chain_id) => {
@@ -374,10 +384,11 @@ pub async fn validate_and_cancel_agreement(
374
384
#[ cfg( test) ]
375
385
mod test {
376
386
use std:: {
377
- sync :: Arc ,
387
+ collections :: HashMap ,
378
388
time:: { Duration , SystemTime , UNIX_EPOCH } ,
379
389
} ;
380
390
391
+ use indexer_monitor:: EscrowAccounts ;
381
392
use rand:: { distr:: Alphanumeric , Rng } ;
382
393
use thegraph_core:: alloy:: {
383
394
primitives:: { Address , FixedBytes , U256 } ,
@@ -388,9 +399,9 @@ mod test {
388
399
389
400
pub use crate :: store:: { AgreementStore , InMemoryAgreementStore } ;
390
401
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 ,
394
405
} ;
395
406
396
407
#[ tokio:: test]
@@ -428,22 +439,19 @@ mod test {
428
439
let abi_voucher = voucher. abi_encode ( ) ;
429
440
let id = Uuid :: from_bytes ( voucher. voucher . agreement_id . into ( ) ) ;
430
441
431
- let store = Arc :: new ( InMemoryAgreementStore :: default ( ) ) ;
432
-
442
+ let ctx = DipsServerContext :: for_testing ( ) ;
433
443
let actual_id = super :: validate_and_create_agreement (
434
- store . clone ( ) ,
444
+ ctx . clone ( ) ,
435
445
& domain,
436
446
& payee_addr,
437
447
vec ! [ payer_addr] ,
438
448
abi_voucher,
439
- & PriceCalculator :: for_testing ( ) ,
440
- Arc :: new ( TestIpfsClient :: mainnet ( ) ) ,
441
449
)
442
450
. await
443
451
. unwrap ( ) ;
444
452
assert_eq ! ( actual_id, id) ;
445
453
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 ( ) ;
447
455
448
456
assert_eq ! ( voucher, stored_agreement. voucher) ;
449
457
assert ! ( !stored_agreement. cancelled) ;
@@ -452,6 +460,7 @@ mod test {
452
460
453
461
#[ test]
454
462
fn voucher_signature_verification ( ) {
463
+ let ctx = DipsServerContext :: for_testing ( ) ;
455
464
let deployment_id = "Qmbg1qF4YgHjiVfsVt6a13ddrVcRtWyJQfD4LA3CwHM29f" . to_string ( ) ;
456
465
let payee = PrivateKeySigner :: random ( ) ;
457
466
let payee_addr = payee. address ( ) ;
@@ -484,23 +493,34 @@ mod test {
484
493
let signed = voucher. sign ( & domain, payer) . unwrap ( ) ;
485
494
assert_eq ! (
486
495
signed
487
- . validate( & domain, & payee_addr, vec![ ] )
496
+ . validate( & ctx . signer_validator , & domain, & payee_addr, vec![ ] )
488
497
. unwrap_err( )
489
498
. to_string( ) ,
490
499
DipsError :: PayerNotAuthorised ( voucher. payer) . to_string( )
491
500
) ;
492
501
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
+ )
494
508
. is_ok( ) ) ;
495
509
}
496
510
497
- #[ test]
498
- fn check_voucher_modified ( ) {
499
- let deployment_id = "Qmbg1qF4YgHjiVfsVt6a13ddrVcRtWyJQfD4LA3CwHM29f" . to_string ( ) ;
511
+ #[ tokio:: test]
512
+ async fn check_voucher_modified ( ) {
500
513
let payee = PrivateKeySigner :: random ( ) ;
501
514
let payee_addr = payee. address ( ) ;
502
515
let payer = PrivateKeySigner :: random ( ) ;
503
516
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 ( ) ;
504
524
505
525
let metadata = SubgraphIndexingVoucherMetadata {
506
526
basePricePerEpoch : U256 :: from ( 10000_u64 ) ,
@@ -530,9 +550,14 @@ mod test {
530
550
531
551
assert ! ( matches!(
532
552
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
+ )
534
559
. unwrap_err( ) ,
535
- DipsError :: PayerNotAuthorised ( _)
560
+ DipsError :: SignerNotAuthorised ( _)
536
561
) ) ;
537
562
}
538
563
@@ -603,9 +628,10 @@ mod test {
603
628
dips_agreement_eip712_domain ( )
604
629
}
605
630
606
- pub fn test_voucher (
631
+ pub fn test_voucher_with_signer (
607
632
& self ,
608
633
metadata : SubgraphIndexingVoucherMetadata ,
634
+ signer : PrivateKeySigner ,
609
635
) -> SignedIndexingAgreementVoucher {
610
636
let agreement_id = Uuid :: now_v7 ( ) ;
611
637
@@ -628,14 +654,21 @@ mod test {
628
654
metadata : metadata. abi_encode ( ) . into ( ) ,
629
655
} ;
630
656
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 ( ) )
632
665
}
633
666
}
634
667
635
668
#[ tokio:: test]
636
669
async fn test_create_and_cancel_agreement ( ) -> anyhow:: Result < ( ) > {
670
+ let ctx = DipsServerContext :: for_testing ( ) ;
637
671
let voucher_ctx = VoucherContext :: random ( ) ;
638
- let store = Arc :: new ( InMemoryAgreementStore :: default ( ) ) ;
639
672
640
673
// Create metadata and voucher
641
674
let metadata = SubgraphIndexingVoucherMetadata {
@@ -649,13 +682,11 @@ mod test {
649
682
650
683
// Create agreement
651
684
let agreement_id = super :: validate_and_create_agreement (
652
- store . clone ( ) ,
685
+ ctx . clone ( ) ,
653
686
& voucher_ctx. domain ( ) ,
654
687
& voucher_ctx. payee . address ( ) ,
655
688
vec ! [ voucher_ctx. payer. address( ) ] ,
656
689
signed_voucher. encode_vec ( ) ,
657
- & PriceCalculator :: for_testing ( ) ,
658
- Arc :: new ( TestIpfsClient :: mainnet ( ) ) ,
659
690
)
660
691
. await ?;
661
692
@@ -668,7 +699,7 @@ mod test {
668
699
669
700
// Cancel agreement
670
701
let cancelled_id = super :: validate_and_cancel_agreement (
671
- store. clone ( ) ,
702
+ ctx . store . clone ( ) ,
672
703
& cancel_domain,
673
704
signed_cancel. encode_vec ( ) ,
674
705
)
@@ -677,7 +708,7 @@ mod test {
677
708
assert_eq ! ( agreement_id, cancelled_id) ;
678
709
679
710
// 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 ( ) ;
681
712
assert ! ( stored_agreement. cancelled) ;
682
713
683
714
Ok ( ( ) )
@@ -686,7 +717,14 @@ mod test {
686
717
#[ tokio:: test]
687
718
async fn test_create_validations_errors ( ) -> anyhow:: Result < ( ) > {
688
719
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 ;
690
728
691
729
let metadata = SubgraphIndexingVoucherMetadata {
692
730
basePricePerEpoch : U256 :: from ( 10000_u64 ) ,
@@ -716,6 +754,9 @@ mod test {
716
754
subgraphDeploymentId : voucher_ctx. deployment_id . clone ( ) ,
717
755
} ;
718
756
757
+ let signer = PrivateKeySigner :: random ( ) ;
758
+ let valid_voucher_invalid_signer =
759
+ voucher_ctx. test_voucher_with_signer ( metadata. clone ( ) , signer. clone ( ) ) ;
719
760
let valid_voucher = voucher_ctx. test_voucher ( metadata) ;
720
761
721
762
let expected_result: Vec < Result < [ u8 ; 16 ] , DipsError > > = vec ! [
@@ -728,23 +769,27 @@ mod test {
728
769
100 ,
729
770
"10" . to_string( ) ,
730
771
) ) ,
772
+ Err ( DipsError :: SignerNotAuthorised ( signer. address( ) ) ) ,
731
773
Ok ( valid_voucher
732
774
. voucher
733
775
. agreement_id
734
776
. as_slice( )
735
777
. try_into( )
736
778
. unwrap( ) ) ,
737
779
] ;
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
+ ] ;
739
786
for ( voucher, result) in cases. into_iter ( ) . zip ( expected_result. into_iter ( ) ) {
740
787
let out = super :: validate_and_create_agreement (
741
- store . clone ( ) ,
788
+ ctx . clone ( ) ,
742
789
& voucher_ctx. domain ( ) ,
743
790
& voucher_ctx. payee . address ( ) ,
744
791
vec ! [ voucher_ctx. payer. address( ) ] ,
745
792
voucher. encode_vec ( ) ,
746
- & PriceCalculator :: for_testing ( ) ,
747
- Arc :: new ( TestIpfsClient :: mainnet ( ) ) ,
748
793
)
749
794
. await ;
750
795
0 commit comments