@@ -126,6 +126,27 @@ where
126126 panic ! ( "Contract {id} not found" )
127127 }
128128 }
129+
130+ #[ cfg( feature = "async" ) ]
131+ #[ allow( clippy:: await_holding_refcell_ref) ]
132+ async fn with_contract_mut_async < R > (
133+ & mut self ,
134+ id : ContractId ,
135+ f : impl AsyncFnOnce ( & mut Contract < Sp :: Stock , Sp :: Pile > ) -> R ,
136+ ) -> R {
137+ // We need this bullshit due to a failed rust `RefCell` implementation which panics if we do
138+ // this block any other way.
139+ if self . contracts . borrow ( ) . contains_key ( & id) {
140+ return f ( self . contracts . borrow_mut ( ) . get_mut ( & id) . unwrap ( ) ) . await ;
141+ }
142+ if let Some ( mut contract) = self . persistence . contract ( id) {
143+ let res = f ( & mut contract) . await ;
144+ self . contracts . borrow_mut ( ) . insert ( id, contract) ;
145+ res
146+ } else {
147+ panic ! ( "Contract {id} not found" )
148+ }
149+ }
129150}
130151
131152impl < Sp , S , C > Contracts < Sp , S , C >
@@ -270,13 +291,16 @@ where
270291 self . with_contract_mut ( contract_id, |contract| contract. call ( call, seals) )
271292 }
272293
273- /// Synchronize the status of all witnesses and single-use seal definitions.
294+ #[ cfg( not( feature = "async" ) ) ]
295+ /// Update the status of all witnesses and single-use seal definitions.
274296 ///
275297 /// Applies rollbacks or forwards if required and recomputes the state of the affected
276298 /// contracts.
277- pub fn sync_witnesses < E : core:: error:: Error > (
299+ pub fn update_witnesses < E : core:: error:: Error > (
278300 & mut self ,
279301 resolver : impl Fn ( <<Sp :: Pile as Pile >:: Seal as RgbSeal >:: WitnessId ) -> Result < WitnessStatus , E > ,
302+ last_block_height : u64 ,
303+ min_conformations : u32 ,
280304 ) -> Result < ( ) , MultiError < SyncError < E > , <Sp :: Stock as Stock >:: Error > > {
281305 let mut changed_statuses = IndexMap :: < _ , WitnessStatus > :: new ( ) ;
282306 let contract_ids = self . persistence . contract_ids ( ) . collect :: < IndexSet < _ > > ( ) ;
@@ -285,13 +309,16 @@ where
285309 contract_id,
286310 |contract| -> Result < ( ) , MultiError < SyncError < E > , <Sp :: Stock as Stock >:: Error > > {
287311 for witness_id in contract. witness_ids ( ) {
312+ let old_status = contract. witness_status ( witness_id) ;
313+ if matches ! ( old_status, WitnessStatus :: Mined ( height) if last_block_height - height. get( ) > min_conformations as u64 ) {
314+ continue
315+ }
288316 let new_status = match changed_statuses. get ( & witness_id) {
289317 None => resolver ( witness_id)
290318 . map_err ( SyncError :: Status )
291319 . map_err ( MultiError :: A ) ,
292320 Some ( witness_id) => Ok ( * witness_id) ,
293321 } ?;
294- let old_status = contract. witness_status ( witness_id) ;
295322 if new_status != old_status {
296323 changed_statuses. insert ( witness_id, new_status) ;
297324 }
@@ -306,6 +333,51 @@ where
306333 Ok ( ( ) )
307334 }
308335
336+ #[ cfg( feature = "async" ) ]
337+ /// Update the status of all witnesses and single-use seal definitions.
338+ ///
339+ /// Applies rollbacks or forwards if required and recomputes the state of the affected
340+ /// contracts.
341+ pub async fn update_witnesses_async < E : core:: error:: Error > (
342+ & mut self ,
343+ resolver : impl AsyncFn (
344+ <<Sp :: Pile as Pile >:: Seal as RgbSeal >:: WitnessId ,
345+ ) -> Result < WitnessStatus , E > ,
346+ last_block_height : u64 ,
347+ min_conformations : u32 ,
348+ ) -> Result < ( ) , MultiError < SyncError < E > , <Sp :: Stock as Stock >:: Error > > {
349+ let mut changed_statuses = IndexMap :: < _ , WitnessStatus > :: new ( ) ;
350+ let contract_ids = self . persistence . contract_ids ( ) . collect :: < IndexSet < _ > > ( ) ;
351+ for contract_id in contract_ids {
352+ self . with_contract_mut_async (
353+ contract_id,
354+ async |contract| -> Result < ( ) , MultiError < SyncError < E > , <Sp :: Stock as Stock >:: Error > > {
355+ for witness_id in contract. witness_ids ( ) {
356+ let old_status = contract. witness_status ( witness_id) ;
357+ if matches ! ( old_status, WitnessStatus :: Mined ( height) if last_block_height - height. get( ) > min_conformations as u64 ) {
358+ continue
359+ }
360+ let new_status = match changed_statuses. get ( & witness_id) {
361+ None => resolver ( witness_id)
362+ . await
363+ . map_err ( SyncError :: Status )
364+ . map_err ( MultiError :: A ) ,
365+ Some ( witness_id) => Ok ( * witness_id) ,
366+ } ?;
367+ if new_status != old_status {
368+ changed_statuses. insert ( witness_id, new_status) ;
369+ }
370+ }
371+ contract
372+ . sync ( changed_statuses. iter ( ) . map ( |( id, status) | ( * id, * status) ) )
373+ . map_err ( MultiError :: from_other_a) ?;
374+ Ok ( ( ) )
375+ } ,
376+ ) . await ?;
377+ }
378+ Ok ( ( ) )
379+ }
380+
309381 /// Include an operation and its witness to the history of known operations and the contract
310382 /// state.
311383 ///
0 commit comments