@@ -48,6 +48,8 @@ use sp_transaction_storage_proof::{
4848pub use pallet:: * ;
4949pub use weights:: WeightInfo ;
5050
51+ const LOG_TARGET : & str = "runtime::transaction-storage" ;
52+
5153/// Maximum bytes that can be stored in one transaction.
5254// Setting higher limit also requires raising the allocator limit.
5355pub const DEFAULT_MAX_TRANSACTION_SIZE : u32 = 8 * 1024 * 1024 ;
@@ -621,6 +623,35 @@ pub mod pallet {
621623 now >= expiration
622624 }
623625
626+ fn authorization_added ( scope : & AuthorizationScopeFor < T > ) {
627+ match scope {
628+ AuthorizationScope :: Account ( who) => {
629+ // Allow nonce storage for transaction replay protection
630+ frame_system:: Pallet :: < T > :: inc_providers ( who) ;
631+ } ,
632+ AuthorizationScope :: Preimage ( _) => ( ) ,
633+ }
634+ }
635+
636+ fn authorization_removed ( scope : & AuthorizationScopeFor < T > ) {
637+ match scope {
638+ AuthorizationScope :: Account ( who) => {
639+ // Cleanup nonce storage. Authorized accounts should be careful to use a short
640+ // enough lifetime for their store/renew transactions that they aren't at risk
641+ // of replay when the account is next authorized.
642+ if let Err ( err) = frame_system:: Pallet :: < T > :: dec_providers ( who) {
643+ log:: warn!(
644+ target: LOG_TARGET ,
645+ "Failed to decrement provider reference count for authorized account {:?}, \
646+ leaking reference: {:?}",
647+ who, err
648+ ) ;
649+ }
650+ } ,
651+ AuthorizationScope :: Preimage ( _) => ( ) ,
652+ }
653+ }
654+
624655 /// Authorize data storage.
625656 fn authorize ( scope : AuthorizationScopeFor < T > , transactions : u32 , bytes : u64 ) {
626657 let expiration = frame_system:: Pallet :: < T > :: block_number ( )
@@ -629,34 +660,37 @@ pub mod pallet {
629660 Authorizations :: < T > :: mutate ( & scope, |maybe_authorization| {
630661 if let Some ( authorization) = maybe_authorization {
631662 if Self :: expired ( authorization. expiration ) {
632- * maybe_authorization = None ;
633- }
634- }
635-
636- if let Some ( authorization) = maybe_authorization {
637- // An unexpired authorization already exists. Extend it.
638- match scope {
639- AuthorizationScope :: Account ( _) => {
640- // Add
641- authorization. extent . transactions =
642- authorization. extent . transactions . saturating_add ( transactions) ;
643- authorization. extent . bytes =
644- authorization. extent . bytes . saturating_add ( bytes) ;
645- } ,
646- AuthorizationScope :: Preimage ( _) => {
647- // Max
648- authorization. extent . transactions =
649- authorization. extent . transactions . max ( transactions) ;
650- authorization. extent . bytes = authorization. extent . bytes . max ( bytes) ;
651- } ,
663+ // Previous authorization expired. Overwrite it.
664+ * authorization = Authorization {
665+ extent : AuthorizationExtent { transactions, bytes } ,
666+ expiration,
667+ } ;
668+ } else {
669+ // An unexpired authorization already exists. Extend it.
670+ match scope {
671+ AuthorizationScope :: Account ( _) => {
672+ // Add
673+ authorization. extent . transactions =
674+ authorization. extent . transactions . saturating_add ( transactions) ;
675+ authorization. extent . bytes =
676+ authorization. extent . bytes . saturating_add ( bytes) ;
677+ } ,
678+ AuthorizationScope :: Preimage ( _) => {
679+ // Max
680+ authorization. extent . transactions =
681+ authorization. extent . transactions . max ( transactions) ;
682+ authorization. extent . bytes = authorization. extent . bytes . max ( bytes) ;
683+ } ,
684+ }
685+ authorization. expiration = expiration;
652686 }
653- authorization. expiration = expiration;
654687 } else {
655- // No previous authorization, or it expired . Create a fresh one.
688+ // No previous authorization. Create a fresh one.
656689 * maybe_authorization = Some ( Authorization {
657690 extent : AuthorizationExtent { transactions, bytes } ,
658691 expiration,
659692 } ) ;
693+ Self :: authorization_added ( & scope) ;
660694 }
661695 } ) ;
662696 }
@@ -669,6 +703,7 @@ pub mod pallet {
669703 return Err ( Error :: < T > :: AuthorizationNotFound . into ( ) )
670704 } ;
671705 ensure ! ( Self :: expired( authorization. expiration) , Error :: <T >:: AuthorizationNotExpired ) ;
706+ Self :: authorization_removed ( & scope) ;
672707 Ok ( ( ) )
673708 }
674709
@@ -741,7 +776,8 @@ pub mod pallet {
741776 size : u32 ,
742777 consume : bool ,
743778 ) -> Result < ( ) , TransactionValidityError > {
744- let consume_authorization = |maybe_authorization : & mut Option < Authorization < _ > > | -> Result < ( ) , TransactionValidityError > {
779+ // Returns true if authorization was removed
780+ let consume_authorization = |maybe_authorization : & mut Option < Authorization < _ > > | -> Result < bool , TransactionValidityError > {
745781 let Some ( authorization) = maybe_authorization else {
746782 return Err ( InvalidTransaction :: Payment . into ( ) )
747783 } ;
@@ -764,21 +800,26 @@ pub mod pallet {
764800 // left.
765801 if transactions == 0 || bytes == 0 {
766802 * maybe_authorization = None ;
803+ Ok ( true )
767804 } else {
768805 authorization. extent . transactions = transactions;
769806 authorization. extent . bytes = bytes;
807+ Ok ( false )
770808 }
771- Ok ( ( ) )
772809 } ;
773810
774811 if consume {
775- Authorizations :: < T > :: mutate ( & scope, consume_authorization)
812+ if Authorizations :: < T > :: mutate ( & scope, consume_authorization) ? {
813+ Self :: authorization_removed ( & scope) ;
814+ }
776815 } else {
777816 // Note we call consume_authorization on a temporary; the authorization in storage
778817 // is untouched and doesn't actually get consumed
779818 let mut authorization = Authorizations :: < T > :: get ( & scope) ;
780- consume_authorization ( & mut authorization)
819+ consume_authorization ( & mut authorization) ? ;
781820 }
821+
822+ Ok ( ( ) )
782823 }
783824
784825 /// Check that authorization with the given scope exists in storage but has expired.
0 commit comments