11// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
22// SPDX-License-Identifier: Apache-2.0
33
4- use eventuals:: { join , Eventual , EventualExt } ;
4+ use eventuals:: { Eventual , EventualExt , EventualWriter } ;
55use std:: collections:: HashMap ;
66use std:: sync:: Arc ;
77use thegraph_core:: { Address , ChainId } ;
8- use tokio:: sync:: Mutex ;
8+ use tokio:: sync:: watch;
9+ use tokio:: {
10+ select,
11+ sync:: { watch:: Receiver , Mutex } ,
12+ } ;
913use tracing:: warn;
1014
1115use crate :: prelude:: { Allocation , AttestationSigner } ;
@@ -15,47 +19,89 @@ pub fn attestation_signers(
1519 indexer_allocations : Eventual < HashMap < Address , Allocation > > ,
1620 indexer_mnemonic : String ,
1721 chain_id : ChainId ,
18- dispute_manager : Eventual < Address > ,
22+ mut dispute_manager_rx : Receiver < Option < Address > > ,
1923) -> Eventual < HashMap < Address , AttestationSigner > > {
2024 let attestation_signers_map: & ' static Mutex < HashMap < Address , AttestationSigner > > =
2125 Box :: leak ( Box :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ) ;
2226
23- let indexer_mnemonic = Arc :: new ( indexer_mnemonic) ;
24-
2527 // Whenever the indexer's active or recently closed allocations change, make sure
26- // we have attestation signers for all of them
27- join ( ( indexer_allocations, dispute_manager) ) . map ( move |( allocations, dispute_manager) | {
28- let indexer_mnemonic = indexer_mnemonic. clone ( ) ;
29- async move {
30- let mut signers = attestation_signers_map. lock ( ) . await ;
31-
32- // Remove signers for allocations that are no longer active or recently closed
33- signers. retain ( |id, _| allocations. contains_key ( id) ) ;
34-
35- // Create signers for new allocations
36- for ( id, allocation) in allocations. iter ( ) {
37- if !signers. contains_key ( id) {
38- let signer = AttestationSigner :: new (
39- & indexer_mnemonic,
40- allocation,
28+ // we have attestation signers for all of them.
29+ let ( mut signers_writer, signers_reader) =
30+ Eventual :: < HashMap < Address , AttestationSigner > > :: new ( ) ;
31+
32+ tokio:: spawn ( async move {
33+ // Listening to the allocation eventual and converting them to reciever.
34+ // Using pipe for updation.
35+ // For temporary pupose only.
36+ let ( allocations_tx, mut allocations_rx) =
37+ watch:: channel ( indexer_allocations. value ( ) . await . unwrap ( ) ) ;
38+ let _p1 = indexer_allocations. pipe ( move |allocatons| {
39+ let _ = allocations_tx. send ( allocatons) ;
40+ } ) ;
41+
42+ loop {
43+ select ! {
44+ Ok ( _) = allocations_rx. changed( ) =>{
45+ modify_sigers(
46+ Arc :: new( indexer_mnemonic. clone( ) ) ,
4147 chain_id,
42- dispute_manager,
43- ) ;
44- if let Err ( e) = signer {
45- warn ! (
46- "Failed to establish signer for allocation {}, deployment {}, createdAtEpoch {}: {}" ,
47- allocation. id, allocation. subgraph_deployment. id,
48- allocation. created_at_epoch, e
49- ) ;
50- } else {
51- signers. insert ( * id, signer. unwrap ( ) ) ;
52- }
48+ attestation_signers_map,
49+ allocations_rx. clone( ) ,
50+ dispute_manager_rx. clone( ) ,
51+ & mut signers_writer) . await ;
52+ } ,
53+ Ok ( _) = dispute_manager_rx. changed( ) =>{
54+ modify_sigers( Arc :: new( indexer_mnemonic. clone( ) ) ,
55+ chain_id,
56+ attestation_signers_map,
57+ allocations_rx. clone( ) ,
58+ dispute_manager_rx. clone( ) ,
59+ & mut signers_writer) . await ;
60+ } ,
61+ else=>{
62+ // Something is wrong.
63+ panic!( "dispute_manager_rx or allocations_rx was dropped" ) ;
5364 }
5465 }
66+ }
67+ } ) ;
5568
56- signers. clone ( )
69+ signers_reader
70+ }
71+ async fn modify_sigers (
72+ indexer_mnemonic : Arc < String > ,
73+ chain_id : ChainId ,
74+ attestation_signers_map : & ' static Mutex < HashMap < Address , AttestationSigner > > ,
75+ allocations_rx : Receiver < HashMap < Address , Allocation > > ,
76+ dispute_manager_rx : Receiver < Option < Address > > ,
77+ signers_writer : & mut EventualWriter < HashMap < Address , AttestationSigner > > ,
78+ ) {
79+ let mut signers = attestation_signers_map. lock ( ) . await ;
80+ let allocations = allocations_rx. borrow ( ) . clone ( ) ;
81+ let Some ( dispute_manager) = * dispute_manager_rx. borrow ( ) else {
82+ return ;
83+ } ;
84+ // Remove signers for allocations that are no longer active or recently closed
85+ signers. retain ( |id, _| allocations. contains_key ( id) ) ;
86+
87+ // Create signers for new allocations
88+ for ( id, allocation) in allocations. iter ( ) {
89+ if !signers. contains_key ( id) {
90+ let signer =
91+ AttestationSigner :: new ( & indexer_mnemonic, allocation, chain_id, dispute_manager) ;
92+ if let Err ( e) = signer {
93+ warn ! (
94+ "Failed to establish signer for allocation {}, deployment {}, createdAtEpoch {}: {}" ,
95+ allocation. id, allocation. subgraph_deployment. id,
96+ allocation. created_at_epoch, e
97+ ) ;
98+ } else {
99+ signers. insert ( * id, signer. unwrap ( ) ) ;
100+ }
57101 }
58- } )
102+ }
103+
104+ signers_writer. write ( signers. clone ( ) ) ;
59105}
60106
61107#[ cfg( test) ]
@@ -69,9 +115,11 @@ mod tests {
69115 #[ tokio:: test]
70116 async fn test_attestation_signers_update_with_allocations ( ) {
71117 let ( mut allocations_writer, allocations) = Eventual :: < HashMap < Address , Allocation > > :: new ( ) ;
72- let ( mut dispute_manager_writer, dispute_manager) = Eventual :: < Address > :: new ( ) ;
118+ let ( dispute_manager_writer, dispute_manager) = watch :: channel ( None ) ;
73119
74- dispute_manager_writer. write ( * DISPUTE_MANAGER_ADDRESS ) ;
120+ dispute_manager_writer
121+ . send ( Some ( * DISPUTE_MANAGER_ADDRESS ) )
122+ . unwrap ( ) ;
75123
76124 let signers = attestation_signers (
77125 allocations,
0 commit comments