@@ -229,7 +229,7 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
229229 #crate_:: std_enabled! {
230230 pub struct RuntimeApiImpl <Block : #crate_:: BlockT , C : #crate_:: CallApiAt <Block > + ' static > {
231231 call: & ' static C ,
232- commit_on_success : std:: cell:: RefCell <bool >,
232+ transaction_depth : std:: cell:: RefCell <u16 >,
233233 changes: std:: cell:: RefCell <#crate_:: OverlayedChanges >,
234234 storage_transaction_cache: std:: cell:: RefCell <
235235 #crate_:: StorageTransactionCache <Block , C :: StateBackend >
@@ -248,11 +248,15 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
248248 ) -> R where Self : Sized {
249249 self . start_transaction( ) ;
250250
251- * std:: cell:: RefCell :: borrow_mut( & self . commit_on_success ) = false ;
251+ * std:: cell:: RefCell :: borrow_mut( & self . transaction_depth ) += 1 ;
252252 let res = call( self ) ;
253- * std:: cell:: RefCell :: borrow_mut( & self . commit_on_success) = true ;
253+ std:: cell:: RefCell :: borrow_mut( & self . transaction_depth)
254+ . checked_sub( 1 )
255+ . expect( "Transactions are opened and closed together; qed" ) ;
254256
255- self . commit_or_rollback( std:: matches!( res, #crate_:: TransactionOutcome :: Commit ( _) ) ) ;
257+ self . commit_or_rollback_transaction(
258+ std:: matches!( res, #crate_:: TransactionOutcome :: Commit ( _) )
259+ ) ;
256260
257261 res. into_inner( )
258262 }
@@ -332,7 +336,7 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
332336 ) -> #crate_:: ApiRef <' a, Self :: RuntimeApi > {
333337 RuntimeApiImpl {
334338 call: unsafe { std:: mem:: transmute( call) } ,
335- commit_on_success : true . into( ) ,
339+ transaction_depth : 0 . into( ) ,
336340 changes: std:: default :: Default :: default ( ) ,
337341 recorder: std:: default :: Default :: default ( ) ,
338342 storage_transaction_cache: std:: default :: Default :: default ( ) ,
@@ -341,52 +345,47 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
341345 }
342346
343347 impl <Block : #crate_:: BlockT , C : #crate_:: CallApiAt <Block >> RuntimeApiImpl <Block , C > {
344- fn commit_or_rollback ( & self , commit: bool ) {
348+ fn commit_or_rollback_transaction ( & self , commit: bool ) {
345349 let proof = "\
346350 We only close a transaction when we opened one ourself.
347351 Other parts of the runtime that make use of transactions (state-machine)
348352 also balance their transactions. The runtime cannot close client initiated
349353 transactions; qed" ;
350- if * std:: cell:: RefCell :: borrow( & self . commit_on_success) {
351- let res = if commit {
352- let res = if let Some ( recorder) = & self . recorder {
353- #crate_:: ProofRecorder :: <Block >:: commit_transaction( & recorder)
354- } else {
355- Ok ( ( ) )
356- } ;
357354
358- let res2 = #crate_:: OverlayedChanges :: commit_transaction(
359- & mut std:: cell:: RefCell :: borrow_mut( & self . changes)
360- ) ;
361-
362- // Will panic on an `Err` below, however we should call commit
363- // on the recorder and the changes together.
364- std:: result:: Result :: and( res, std:: result:: Result :: map_err( res2, drop) )
355+ let res = if commit {
356+ let res = if let Some ( recorder) = & self . recorder {
357+ #crate_:: ProofRecorder :: <Block >:: commit_transaction( & recorder)
365358 } else {
366- let res = if let Some ( recorder) = & self . recorder {
367- #crate_:: ProofRecorder :: <Block >:: rollback_transaction( & recorder)
368- } else {
369- Ok ( ( ) )
370- } ;
359+ Ok ( ( ) )
360+ } ;
371361
372- let res2 = #crate_:: OverlayedChanges :: rollback_transaction (
373- & mut std:: cell:: RefCell :: borrow_mut( & self . changes)
374- ) ;
362+ let res2 = #crate_:: OverlayedChanges :: commit_transaction (
363+ & mut std:: cell:: RefCell :: borrow_mut( & self . changes)
364+ ) ;
375365
376- // Will panic on an `Err` below, however we should call commit
377- // on the recorder and the changes together.
378- std:: result:: Result :: and( res, std:: result:: Result :: map_err( res2, drop) )
366+ // Will panic on an `Err` below, however we should call commit
367+ // on the recorder and the changes together.
368+ std:: result:: Result :: and( res, std:: result:: Result :: map_err( res2, drop) )
369+ } else {
370+ let res = if let Some ( recorder) = & self . recorder {
371+ #crate_:: ProofRecorder :: <Block >:: rollback_transaction( & recorder)
372+ } else {
373+ Ok ( ( ) )
379374 } ;
380375
381- std:: result:: Result :: expect( res, proof) ;
382- }
376+ let res2 = #crate_:: OverlayedChanges :: rollback_transaction(
377+ & mut std:: cell:: RefCell :: borrow_mut( & self . changes)
378+ ) ;
379+
380+ // Will panic on an `Err` below, however we should call commit
381+ // on the recorder and the changes together.
382+ std:: result:: Result :: and( res, std:: result:: Result :: map_err( res2, drop) )
383+ } ;
384+
385+ std:: result:: Result :: expect( res, proof) ;
383386 }
384387
385388 fn start_transaction( & self ) {
386- if !* std:: cell:: RefCell :: borrow( & self . commit_on_success) {
387- return
388- }
389-
390389 #crate_:: OverlayedChanges :: start_transaction(
391390 & mut std:: cell:: RefCell :: borrow_mut( & self . changes)
392391 ) ;
@@ -486,7 +485,13 @@ impl<'a> ApiRuntimeImplToApiRuntimeApiImpl<'a> {
486485 params: std:: vec:: Vec <u8 >,
487486 fn_name: & dyn Fn ( #crate_:: RuntimeVersion ) -> & ' static str ,
488487 ) -> std:: result:: Result <std:: vec:: Vec <u8 >, #crate_:: ApiError > {
489- self . start_transaction( ) ;
488+ // If we are not already in a transaction, we should create a new transaction
489+ // and then commit/roll it back at the end!
490+ let transaction_depth = * std:: cell:: RefCell :: borrow( & self . transaction_depth) ;
491+
492+ if transaction_depth == 0 {
493+ self . start_transaction( ) ;
494+ }
490495
491496 let res = ( || {
492497 let version = #crate_:: CallApiAt :: <__SrApiBlock__>:: runtime_version_at(
@@ -510,7 +515,9 @@ impl<'a> ApiRuntimeImplToApiRuntimeApiImpl<'a> {
510515 )
511516 } ) ( ) ;
512517
513- self . commit_or_rollback( std:: result:: Result :: is_ok( & res) ) ;
518+ if transaction_depth == 0 {
519+ self . commit_or_rollback_transaction( std:: result:: Result :: is_ok( & res) ) ;
520+ }
514521
515522 res
516523 }
0 commit comments