@@ -24,7 +24,7 @@ mod default_weights;
2424use codec:: { Codec , Decode , Encode } ;
2525use frame_support:: sp_runtime:: traits:: Zero ;
2626use frame_support:: sp_runtime:: SaturatedConversion ;
27- use frame_support:: traits:: { Currency , Get } ;
27+ use frame_support:: traits:: { tokens , Currency , Get } ;
2828use frame_support:: weights:: Weight ;
2929use frame_system:: pallet_prelude:: * ;
3030pub use pallet:: * ;
@@ -46,9 +46,26 @@ struct CollectedFees<Balance: Codec> {
4646 tips : Balance ,
4747}
4848
49+ #[ derive( Encode , Decode , TypeInfo ) ]
50+ struct BlockTransactionByteFee < Balance : Codec > {
51+ // The value of `transaction_byte_fee` for the current block
52+ current : Balance ,
53+ // The value of `transaction_byte_fee` for the next block
54+ next : Balance ,
55+ }
56+
57+ impl < Balance : Codec + tokens:: Balance > Default for BlockTransactionByteFee < Balance > {
58+ fn default ( ) -> Self {
59+ BlockTransactionByteFee {
60+ current : Balance :: max_value ( ) ,
61+ next : Balance :: max_value ( ) ,
62+ }
63+ }
64+ }
65+
4966#[ frame_support:: pallet]
5067mod pallet {
51- use super :: { BalanceOf , CollectedFees , WeightInfo } ;
68+ use super :: { BalanceOf , BlockTransactionByteFee , CollectedFees , WeightInfo } ;
5269 use frame_support:: pallet_prelude:: * ;
5370 use frame_support:: traits:: Currency ;
5471 use frame_system:: pallet_prelude:: * ;
@@ -100,10 +117,23 @@ mod pallet {
100117 #[ pallet:: getter( fn storage_fees_escrow) ]
101118 pub ( super ) type CollectedStorageFeesEscrow < T > = StorageValue < _ , BalanceOf < T > , ValueQuery > ;
102119
103- /// Temporary value (cleared at block finalization) which contains cached value of
104- /// `TransactionByteFee` for current block.
120+ /// The value of `transaction_byte_fee` for both the current and the next block.
121+ ///
122+ /// The `next` value of `transaction_byte_fee` is updated at block finalization and used to
123+ /// validate extrinsic to be included in the next block, the value is move to `current` at
124+ /// block initialization and used to execute extrinsic in the current block. Together it
125+ /// ensure we use the same value for both validating and executing the extrinsic.
126+ ///
127+ /// NOTE: both the `current` and `next` value is set to the default `Balance::max_value` in
128+ /// the genesis block which means there will be no signed extrinsic included in block #1.
129+ #[ pallet:: storage]
130+ pub ( super ) type TransactionByteFee < T > =
131+ StorageValue < _ , BlockTransactionByteFee < BalanceOf < T > > , ValueQuery > ;
132+
133+ /// Temporary value (cleared at block finalization) used to determine if the `transaction_byte_fee`
134+ /// is used to validate extrinsic or execute extrinsic.
105135 #[ pallet:: storage]
106- pub ( super ) type TransactionByteFee < T > = StorageValue < _ , BalanceOf < T > > ;
136+ pub ( super ) type IsDuringBlockExecution < T : Config > = StorageValue < _ , bool , ValueQuery > ;
107137
108138 /// Temporary value (cleared at block finalization) which contains current block author, so we
109139 /// can issue rewards during block finalization.
@@ -185,11 +215,21 @@ where
185215 compute : BalanceOf :: < T > :: zero ( ) ,
186216 tips : BalanceOf :: < T > :: zero ( ) ,
187217 } ) ;
218+
219+ // Update the `current` value to the `next`
220+ TransactionByteFee :: < T > :: mutate ( |transaction_byte_fee| {
221+ transaction_byte_fee. current = transaction_byte_fee. next
222+ } ) ;
223+ IsDuringBlockExecution :: < T > :: set ( true ) ;
188224 }
189225
190226 // TODO: Fees will be split between farmers and executors in the future
191227 fn do_finalize ( _n : BlockNumberFor < T > ) {
192- TransactionByteFee :: < T > :: take ( ) ;
228+ // Update the value for the next `transaction_byte_fee`
229+ TransactionByteFee :: < T > :: mutate ( |transaction_byte_fee| {
230+ transaction_byte_fee. next = Self :: calculate_transaction_byte_fee ( )
231+ } ) ;
232+ IsDuringBlockExecution :: < T > :: take ( ) ;
193233
194234 let collected_fees = CollectedBlockFees :: < T > :: take ( )
195235 . expect ( "`CollectedBlockFees` was set in `on_initialize`; qed" ) ;
@@ -268,27 +308,29 @@ where
268308 }
269309 }
270310
311+ /// Return the current `transaction_byte_fee` value for executing extrinsic and
312+ /// return the next `transaction_byte_fee` value for validating extrinsic to be
313+ /// included in the next block
271314 pub fn transaction_byte_fee ( ) -> BalanceOf < T > {
272- if let Some ( transaction_byte_fee) = TransactionByteFee :: < T > :: get ( ) {
273- return transaction_byte_fee;
315+ if IsDuringBlockExecution :: < T > :: get ( ) {
316+ TransactionByteFee :: < T > :: get ( ) . current
317+ } else {
318+ TransactionByteFee :: < T > :: get ( ) . next
274319 }
320+ }
275321
322+ pub fn calculate_transaction_byte_fee ( ) -> BalanceOf < T > {
276323 let credit_supply = T :: CreditSupply :: get ( ) ;
277324
278- let transaction_byte_fee = match T :: TotalSpacePledged :: get ( ) . checked_sub (
325+ match T :: TotalSpacePledged :: get ( ) . checked_sub (
279326 T :: BlockchainHistorySize :: get ( )
280327 . saturating_mul ( u128:: from ( T :: MinReplicationFactor :: get ( ) ) ) ,
281328 ) {
282329 Some ( free_space) if free_space > 0 => {
283330 credit_supply / BalanceOf :: < T > :: saturated_from ( free_space)
284331 }
285332 _ => credit_supply,
286- } ;
287-
288- // Cache value for this block.
289- TransactionByteFee :: < T > :: put ( transaction_byte_fee) ;
290-
291- transaction_byte_fee
333+ }
292334 }
293335
294336 pub fn note_transaction_fees (
0 commit comments