11use  { 
2-     crate :: api:: ChainId , 
2+     crate :: { 
3+         api:: ChainId , 
4+         keeper:: keeper_metrics:: { AccountLabel ,  KeeperMetrics } , 
5+     } , 
36    anyhow:: { ensure,  Result } , 
47    ethers:: types:: Address , 
58    sha3:: { Digest ,  Keccak256 } , 
9+     std:: sync:: Arc , 
610    tokio:: task:: spawn_blocking, 
711} ; 
812
@@ -127,11 +131,22 @@ impl PebbleHashChain {
127131/// which requires tracking multiple hash chains here. 
128132pub  struct  HashChainState  { 
129133    // The sequence number where the hash chain starts. Must be stored in sorted order. 
130-     pub   offsets :  Vec < usize > , 
131-     pub   hash_chains :  Vec < PebbleHashChain > , 
134+     offsets :  Vec < usize > , 
135+     hash_chains :  Vec < PebbleHashChain > , 
132136} 
133137
134138impl  HashChainState  { 
139+     pub  fn  new ( offsets :  Vec < usize > ,  hash_chains :  Vec < PebbleHashChain > )  -> Result < HashChainState >  { 
140+         if  offsets. len ( )  != hash_chains. len ( )  { 
141+             return  Err ( anyhow:: anyhow!( 
142+                 "Offsets and hash chains must have the same length." 
143+             ) ) ; 
144+         } 
145+         Ok ( HashChainState  { 
146+             offsets, 
147+             hash_chains, 
148+         } ) 
149+     } 
135150    pub  fn  from_chain_at_offset ( offset :  usize ,  chain :  PebbleHashChain )  -> HashChainState  { 
136151        HashChainState  { 
137152            offsets :  vec ! [ offset] , 
@@ -152,12 +167,54 @@ impl HashChainState {
152167    } 
153168} 
154169
170+ pub  struct  MonitoredHashChainState  { 
171+     hash_chain_state :  Arc < HashChainState > , 
172+     metrics :  Arc < KeeperMetrics > , 
173+     account_label :  AccountLabel , 
174+ } 
175+ impl  MonitoredHashChainState  { 
176+     pub  fn  new ( 
177+         hash_chain_state :  Arc < HashChainState > , 
178+         metrics :  Arc < KeeperMetrics > , 
179+         chain_id :  ChainId , 
180+         provider_address :  Address , 
181+     )  -> Self  { 
182+         Self  { 
183+             hash_chain_state, 
184+             metrics, 
185+             account_label :  AccountLabel  { 
186+                 chain_id, 
187+                 address :  provider_address. to_string ( ) , 
188+             } , 
189+         } 
190+     } 
191+ 
192+     pub  fn  reveal ( & self ,  sequence_number :  u64 )  -> Result < [ u8 ;  32 ] >  { 
193+         let  res = self . hash_chain_state . reveal ( sequence_number) ; 
194+         if  res. is_ok ( )  { 
195+             let  metric = self 
196+                 . metrics 
197+                 . highest_revealed_sequence_number 
198+                 . get_or_create ( & self . account_label ) ; 
199+             if  metric. get ( )  < sequence_number as  i64  { 
200+                 metric. set ( sequence_number as  i64 ) ; 
201+             } 
202+         } 
203+         res
204+     } 
205+ } 
206+ 
155207#[ cfg( test) ]  
156208mod  test { 
157209    use  { 
158-         crate :: state:: { HashChainState ,  PebbleHashChain } , 
210+         crate :: { 
211+             keeper:: keeper_metrics:: { AccountLabel ,  KeeperMetrics } , 
212+             state:: { HashChainState ,  MonitoredHashChainState ,  PebbleHashChain } , 
213+         } , 
159214        anyhow:: Result , 
215+         ethers:: types:: Address , 
160216        sha3:: { Digest ,  Keccak256 } , 
217+         std:: { sync:: Arc ,  vec} , 
161218    } ; 
162219
163220    fn  run_hash_chain_test ( secret :  [ u8 ;  32 ] ,  length :  usize ,  sample_interval :  usize )  { 
@@ -294,4 +351,65 @@ mod test {
294351
295352        Ok ( ( ) ) 
296353    } 
354+     #[ test]  
355+     fn  test_inconsistent_lengths ( )  -> Result < ( ) >  { 
356+         let  chain1 = PebbleHashChain :: new ( [ 0u8 ;  32 ] ,  10 ,  1 ) ; 
357+         let  chain2 = PebbleHashChain :: new ( [ 1u8 ;  32 ] ,  10 ,  1 ) ; 
358+ 
359+         let  hash_chain_state = HashChainState :: new ( vec ! [ 5 ] ,  vec ! [ chain1. clone( ) ,  chain2. clone( ) ] ) ; 
360+         assert ! ( hash_chain_state. is_err( ) ) ; 
361+         let  hash_chain_state = HashChainState :: new ( vec ! [ 5 ,  10 ] ,  vec ! [ chain1. clone( ) ] ) ; 
362+         assert ! ( hash_chain_state. is_err( ) ) ; 
363+         let  hash_chain_state =
364+             HashChainState :: new ( vec ! [ 5 ,  10 ] ,  vec ! [ chain1. clone( ) ,  chain2. clone( ) ] ) ; 
365+         assert ! ( hash_chain_state. is_ok( ) ) ; 
366+ 
367+         Ok ( ( ) ) 
368+     } 
369+ 
370+     #[ test]  
371+     fn  test_highest_revealed_sequence_number ( )  { 
372+         let  chain = PebbleHashChain :: new ( [ 0u8 ;  32 ] ,  100 ,  1 ) ; 
373+         let  hash_chain_state = HashChainState :: new ( vec ! [ 0 ] ,  vec ! [ chain] ) . unwrap ( ) ; 
374+         let  metrics = Arc :: new ( KeeperMetrics :: default ( ) ) ; 
375+         let  provider = Address :: random ( ) ; 
376+         let  monitored = MonitoredHashChainState :: new ( 
377+             Arc :: new ( hash_chain_state) , 
378+             metrics. clone ( ) , 
379+             "ethereum" . to_string ( ) , 
380+             provider, 
381+         ) ; 
382+         let  label = AccountLabel  { 
383+             chain_id :  "ethereum" . to_string ( ) , 
384+             address :  provider. to_string ( ) , 
385+         } ; 
386+ 
387+         assert ! ( monitored. reveal( 5 ) . is_ok( ) ) ; 
388+         let  current = metrics
389+             . highest_revealed_sequence_number 
390+             . get_or_create ( & label) 
391+             . get ( ) ; 
392+         assert_eq ! ( current,  5 ) ; 
393+ 
394+         assert ! ( monitored. reveal( 15 ) . is_ok( ) ) ; 
395+         let  current = metrics
396+             . highest_revealed_sequence_number 
397+             . get_or_create ( & label) 
398+             . get ( ) ; 
399+         assert_eq ! ( current,  15 ) ; 
400+ 
401+         assert ! ( monitored. reveal( 10 ) . is_ok( ) ) ; 
402+         let  current = metrics
403+             . highest_revealed_sequence_number 
404+             . get_or_create ( & label) 
405+             . get ( ) ; 
406+         assert_eq ! ( current,  15 ) ; 
407+ 
408+         assert ! ( monitored. reveal( 1000 ) . is_err( ) ) ; 
409+         let  current = metrics
410+             . highest_revealed_sequence_number 
411+             . get_or_create ( & label) 
412+             . get ( ) ; 
413+         assert_eq ! ( current,  15 ) ; 
414+     } 
297415} 
0 commit comments