Skip to content

Commit 6309462

Browse files
authored
Merge pull request #2418 from subspace/consensus-tx-byte-fee
Ensure using the same `transaction_byte_fee` for both validating and executing consensus extrinsic
2 parents 6b5ef44 + 2e70efa commit 6309462

File tree

1 file changed

+57
-15
lines changed
  • crates/pallet-transaction-fees/src

1 file changed

+57
-15
lines changed

crates/pallet-transaction-fees/src/lib.rs

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ mod default_weights;
2424
use codec::{Codec, Decode, Encode};
2525
use frame_support::sp_runtime::traits::Zero;
2626
use frame_support::sp_runtime::SaturatedConversion;
27-
use frame_support::traits::{Currency, Get};
27+
use frame_support::traits::{tokens, Currency, Get};
2828
use frame_support::weights::Weight;
2929
use frame_system::pallet_prelude::*;
3030
pub 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]
5067
mod 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

Comments
 (0)