mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-21 14:25:41 +00:00
Integrate pallet_contracts gas with the weight system (#5712)
Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com> Co-Authored-By: Sergei Pepyakin <sergei@parity.io>
This commit is contained in:
committed by
GitHub
parent
e731817e24
commit
000c924b62
@@ -64,15 +64,6 @@
|
||||
//! initialize the contract.
|
||||
//! * `call` - Makes a call to an account, optionally transferring some balance.
|
||||
//!
|
||||
//! ### Signed Extensions
|
||||
//!
|
||||
//! The contracts module defines the following extension:
|
||||
//!
|
||||
//! - [`CheckBlockGasLimit`]: Ensures that the transaction does not exceeds the block gas limit.
|
||||
//!
|
||||
//! The signed extension needs to be added as signed extra to the transaction type to be used in the
|
||||
//! runtime.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! The Contract module is a work in progress. The following examples show how this Contract module
|
||||
@@ -114,21 +105,20 @@ use codec::{Codec, Encode, Decode};
|
||||
use sp_io::hashing::blake2_256;
|
||||
use sp_runtime::{
|
||||
traits::{
|
||||
Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, SignedExtension,
|
||||
DispatchInfoOf,
|
||||
},
|
||||
transaction_validity::{
|
||||
ValidTransaction, InvalidTransaction, TransactionValidity, TransactionValidityError,
|
||||
Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member,
|
||||
},
|
||||
RuntimeDebug,
|
||||
};
|
||||
use frame_support::dispatch::{DispatchResult, Dispatchable};
|
||||
use frame_support::dispatch::{
|
||||
PostDispatchInfo, DispatchResult, Dispatchable, DispatchResultWithPostInfo
|
||||
};
|
||||
use frame_support::weights::MINIMUM_WEIGHT;
|
||||
use frame_support::{
|
||||
Parameter, decl_module, decl_event, decl_storage, decl_error,
|
||||
parameter_types, IsSubType, storage::child::{self, ChildInfo},
|
||||
};
|
||||
use frame_support::traits::{OnUnbalanced, Currency, Get, Time, Randomness};
|
||||
use frame_support::weights::{FunctionOf, DispatchClass, Weight, GetDispatchInfo, Pays};
|
||||
use frame_system::{self as system, ensure_signed, RawOrigin, ensure_root};
|
||||
use pallet_contracts_primitives::{RentProjection, ContractAccessError};
|
||||
|
||||
@@ -295,9 +285,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;
|
||||
pub type BalanceOf<T> = <<T as pallet_transaction_payment::Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;
|
||||
pub type NegativeImbalanceOf<T> =
|
||||
<<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::NegativeImbalance;
|
||||
<<T as pallet_transaction_payment::Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::NegativeImbalance;
|
||||
|
||||
parameter_types! {
|
||||
/// A reasonable default value for [`Trait::SignedClaimedHandicap`].
|
||||
@@ -312,35 +302,21 @@ parameter_types! {
|
||||
pub const DefaultRentDepositOffset: u32 = 1000;
|
||||
/// A reasonable default value for [`Trait::SurchargeReward`].
|
||||
pub const DefaultSurchargeReward: u32 = 150;
|
||||
/// A reasonable default value for [`Trait::TransferFee`].
|
||||
pub const DefaultTransferFee: u32 = 0;
|
||||
/// A reasonable default value for [`Trait::InstantiationFee`].
|
||||
pub const DefaultInstantiationFee: u32 = 0;
|
||||
/// A reasonable default value for [`Trait::TransactionBaseFee`].
|
||||
pub const DefaultTransactionBaseFee: u32 = 0;
|
||||
/// A reasonable default value for [`Trait::TransactionByteFee`].
|
||||
pub const DefaultTransactionByteFee: u32 = 0;
|
||||
/// A reasonable default value for [`Trait::ContractFee`].
|
||||
pub const DefaultContractFee: u32 = 21;
|
||||
/// A reasonable default value for [`Trait::CallBaseFee`].
|
||||
pub const DefaultCallBaseFee: u32 = 1000;
|
||||
/// A reasonable default value for [`Trait::InstantiateBaseFee`].
|
||||
pub const DefaultInstantiateBaseFee: u32 = 1000;
|
||||
/// A reasonable default value for [`Trait::MaxDepth`].
|
||||
pub const DefaultMaxDepth: u32 = 32;
|
||||
/// A reasonable default value for [`Trait::MaxValueSize`].
|
||||
pub const DefaultMaxValueSize: u32 = 16_384;
|
||||
/// A reasonable default value for [`Trait::BlockGasLimit`].
|
||||
pub const DefaultBlockGasLimit: u32 = 10_000_000;
|
||||
}
|
||||
|
||||
pub trait Trait: frame_system::Trait {
|
||||
type Currency: Currency<Self::AccountId>;
|
||||
pub trait Trait: frame_system::Trait + pallet_transaction_payment::Trait {
|
||||
type Time: Time;
|
||||
type Randomness: Randomness<Self::Hash>;
|
||||
|
||||
/// The outer call dispatch type.
|
||||
type Call: Parameter + Dispatchable<Origin=<Self as frame_system::Trait>::Origin> + IsSubType<Module<Self>, Self>;
|
||||
type Call:
|
||||
Parameter +
|
||||
Dispatchable<PostInfo=PostDispatchInfo, Origin=<Self as frame_system::Trait>::Origin> +
|
||||
IsSubType<Module<Self>, Self> + GetDispatchInfo;
|
||||
|
||||
/// The overarching event type.
|
||||
type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
|
||||
@@ -348,18 +324,9 @@ pub trait Trait: frame_system::Trait {
|
||||
/// A function type to get the contract address given the instantiator.
|
||||
type DetermineContractAddress: ContractAddressFor<CodeHash<Self>, Self::AccountId>;
|
||||
|
||||
/// A function type that computes the fee for dispatching the given `Call`.
|
||||
///
|
||||
/// It is recommended (though not required) for this function to return a fee that would be
|
||||
/// taken by the Executive module for regular dispatch.
|
||||
type ComputeDispatchFee: ComputeDispatchFee<<Self as Trait>::Call, BalanceOf<Self>>;
|
||||
|
||||
/// trie id generator
|
||||
type TrieIdGenerator: TrieIdGenerator<Self::AccountId>;
|
||||
|
||||
/// Handler for the unbalanced reduction when making a gas payment.
|
||||
type GasPayment: OnUnbalanced<NegativeImbalanceOf<Self>>;
|
||||
|
||||
/// Handler for rent payments.
|
||||
type RentPayment: OnUnbalanced<NegativeImbalanceOf<Self>>;
|
||||
|
||||
@@ -392,29 +359,11 @@ pub trait Trait: frame_system::Trait {
|
||||
/// to removal of a contract.
|
||||
type SurchargeReward: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The fee to be paid for making a transaction; the base.
|
||||
type TransactionBaseFee: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The fee to be paid for making a transaction; the per-byte portion.
|
||||
type TransactionByteFee: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The fee required to instantiate a contract instance.
|
||||
type ContractFee: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The base fee charged for calling into a contract.
|
||||
type CallBaseFee: Get<Gas>;
|
||||
|
||||
/// The base fee charged for instantiating a contract.
|
||||
type InstantiateBaseFee: Get<Gas>;
|
||||
|
||||
/// The maximum nesting level of a call/instantiate stack.
|
||||
type MaxDepth: Get<u32>;
|
||||
|
||||
/// The maximum size of a storage value in bytes.
|
||||
type MaxValueSize: Get<u32>;
|
||||
|
||||
/// The maximum amount of gas that could be expended per block.
|
||||
type BlockGasLimit: Get<Gas>;
|
||||
}
|
||||
|
||||
/// Simple contract address determiner.
|
||||
@@ -440,19 +389,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// The default dispatch fee computor computes the fee in the same way that
|
||||
/// the implementation of `ChargeTransactionPayment` for the Balances module does. Note that this only takes a fixed
|
||||
/// fee based on size. Unlike the balances module, weight-fee is applied.
|
||||
pub struct DefaultDispatchFeeComputor<T: Trait>(PhantomData<T>);
|
||||
impl<T: Trait> ComputeDispatchFee<<T as Trait>::Call, BalanceOf<T>> for DefaultDispatchFeeComputor<T> {
|
||||
fn compute_dispatch_fee(call: &<T as Trait>::Call) -> BalanceOf<T> {
|
||||
let encoded_len = call.using_encoded(|encoded| encoded.len() as u32);
|
||||
let base_fee = T::TransactionBaseFee::get();
|
||||
let byte_fee = T::TransactionByteFee::get();
|
||||
base_fee + byte_fee * encoded_len.into()
|
||||
}
|
||||
}
|
||||
|
||||
decl_error! {
|
||||
/// Error for the contracts module.
|
||||
pub enum Error for Module<T: Trait> {
|
||||
@@ -505,24 +441,6 @@ decl_module! {
|
||||
/// to removal of a contract.
|
||||
const SurchargeReward: BalanceOf<T> = T::SurchargeReward::get();
|
||||
|
||||
/// The fee to be paid for making a transaction; the base.
|
||||
const TransactionBaseFee: BalanceOf<T> = T::TransactionBaseFee::get();
|
||||
|
||||
/// The fee to be paid for making a transaction; the per-byte portion.
|
||||
const TransactionByteFee: BalanceOf<T> = T::TransactionByteFee::get();
|
||||
|
||||
/// The fee required to instantiate a contract instance. A reasonable default value
|
||||
/// is 21.
|
||||
const ContractFee: BalanceOf<T> = T::ContractFee::get();
|
||||
|
||||
/// The base fee charged for calling into a contract. A reasonable default
|
||||
/// value is 135.
|
||||
const CallBaseFee: Gas = T::CallBaseFee::get();
|
||||
|
||||
/// The base fee charged for instantiating a contract. A reasonable default value
|
||||
/// is 175.
|
||||
const InstantiateBaseFee: Gas = T::InstantiateBaseFee::get();
|
||||
|
||||
/// The maximum nesting level of a call/instantiate stack. A reasonable default
|
||||
/// value is 100.
|
||||
const MaxDepth: u32 = T::MaxDepth::get();
|
||||
@@ -530,10 +448,6 @@ decl_module! {
|
||||
/// The maximum size of a storage value in bytes. A reasonable default is 16 KiB.
|
||||
const MaxValueSize: u32 = T::MaxValueSize::get();
|
||||
|
||||
/// The maximum amount of gas that could be expended per block. A reasonable
|
||||
/// default value is 10_000_000.
|
||||
const BlockGasLimit: Gas = T::BlockGasLimit::get();
|
||||
|
||||
fn deposit_event() = default;
|
||||
|
||||
/// Updates the schedule for metering contracts.
|
||||
@@ -554,24 +468,21 @@ decl_module! {
|
||||
|
||||
/// Stores the given binary Wasm code into the chain's storage and returns its `codehash`.
|
||||
/// You can instantiate contracts only with stored code.
|
||||
#[weight = MINIMUM_WEIGHT]
|
||||
#[weight = FunctionOf(
|
||||
|args: (&Vec<u8>,)| Module::<T>::calc_code_put_costs(args.0) + MINIMUM_WEIGHT,
|
||||
DispatchClass::Normal,
|
||||
Pays::Yes
|
||||
)]
|
||||
pub fn put_code(
|
||||
origin,
|
||||
#[compact] gas_limit: Gas,
|
||||
code: Vec<u8>
|
||||
) -> DispatchResult {
|
||||
let origin = ensure_signed(origin)?;
|
||||
|
||||
let (mut gas_meter, imbalance) = gas::buy_gas::<T>(&origin, gas_limit)?;
|
||||
|
||||
ensure_signed(origin)?;
|
||||
let schedule = <Module<T>>::current_schedule();
|
||||
let result = wasm::save_code::<T>(code, &mut gas_meter, &schedule);
|
||||
let result = wasm::save_code::<T>(code, &schedule);
|
||||
if let Ok(code_hash) = result {
|
||||
Self::deposit_event(RawEvent::CodeStored(code_hash));
|
||||
}
|
||||
|
||||
gas::refund_unused_gas::<T>(&origin, gas_meter, imbalance);
|
||||
|
||||
result.map(|_| ()).map_err(Into::into)
|
||||
}
|
||||
|
||||
@@ -582,20 +493,27 @@ decl_module! {
|
||||
/// * If the account is a regular account, any value will be transferred.
|
||||
/// * If no account exists and the call value is not less than `existential_deposit`,
|
||||
/// a regular account will be created and any value will be transferred.
|
||||
#[weight = MINIMUM_WEIGHT]
|
||||
#[weight = FunctionOf(
|
||||
|args: (&<T::Lookup as StaticLookup>::Source, &BalanceOf<T>, &Weight, &Vec<u8>)|
|
||||
args.2 + MINIMUM_WEIGHT,
|
||||
DispatchClass::Normal,
|
||||
Pays::Yes
|
||||
)]
|
||||
pub fn call(
|
||||
origin,
|
||||
dest: <T::Lookup as StaticLookup>::Source,
|
||||
#[compact] value: BalanceOf<T>,
|
||||
#[compact] gas_limit: Gas,
|
||||
data: Vec<u8>
|
||||
) -> DispatchResult {
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let origin = ensure_signed(origin)?;
|
||||
let dest = T::Lookup::lookup(dest)?;
|
||||
let mut gas_meter = GasMeter::new(gas_limit);
|
||||
|
||||
Self::bare_call(origin, dest, value, gas_limit, data)
|
||||
.map(|_| ())
|
||||
.map_err(|e| e.reason.into())
|
||||
let result = Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| {
|
||||
ctx.call(dest, value, gas_meter, data)
|
||||
});
|
||||
gas_meter.into_dispatch_result(result.map_err(|e| e.reason))
|
||||
}
|
||||
|
||||
/// Instantiates a new contract from the `codehash` generated by `put_code`, optionally transferring some balance.
|
||||
@@ -608,22 +526,26 @@ decl_module! {
|
||||
/// after the execution is saved as the `code` of the account. That code will be invoked
|
||||
/// upon any call received by this account.
|
||||
/// - The contract is initialized.
|
||||
#[weight = MINIMUM_WEIGHT]
|
||||
#[weight = FunctionOf(
|
||||
|args: (&BalanceOf<T>, &Weight, &CodeHash<T>, &Vec<u8>)| args.1 + MINIMUM_WEIGHT,
|
||||
DispatchClass::Normal,
|
||||
Pays::Yes
|
||||
)]
|
||||
pub fn instantiate(
|
||||
origin,
|
||||
#[compact] endowment: BalanceOf<T>,
|
||||
#[compact] gas_limit: Gas,
|
||||
code_hash: CodeHash<T>,
|
||||
data: Vec<u8>
|
||||
) -> DispatchResult {
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let origin = ensure_signed(origin)?;
|
||||
let mut gas_meter = GasMeter::new(gas_limit);
|
||||
|
||||
Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| {
|
||||
let result = Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| {
|
||||
ctx.instantiate(endowment, gas_meter, &code_hash, data)
|
||||
.map(|(_address, output)| output)
|
||||
})
|
||||
.map(|_| ())
|
||||
.map_err(|e| e.reason.into())
|
||||
});
|
||||
gas_meter.into_dispatch_result(result.map_err(|e| e.reason))
|
||||
}
|
||||
|
||||
/// Allows block producers to claim a small reward for evicting a contract. If a block producer
|
||||
@@ -658,10 +580,6 @@ decl_module! {
|
||||
T::Currency::deposit_into_existing(&rewarded, T::SurchargeReward::get())?;
|
||||
}
|
||||
}
|
||||
|
||||
fn on_finalize() {
|
||||
GasSpent::kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,7 +596,8 @@ impl<T: Trait> Module<T> {
|
||||
gas_limit: Gas,
|
||||
input_data: Vec<u8>,
|
||||
) -> ExecResult {
|
||||
Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| {
|
||||
let mut gas_meter = GasMeter::new(gas_limit);
|
||||
Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| {
|
||||
ctx.call(dest, value, gas_meter, input_data)
|
||||
})
|
||||
}
|
||||
@@ -710,40 +629,27 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
fn calc_code_put_costs(code: &Vec<u8>) -> Gas {
|
||||
<Module<T>>::current_schedule().put_code_per_byte_cost.saturating_mul(code.len() as Gas)
|
||||
}
|
||||
|
||||
fn execute_wasm(
|
||||
origin: T::AccountId,
|
||||
gas_limit: Gas,
|
||||
gas_meter: &mut GasMeter<T>,
|
||||
func: impl FnOnce(&mut ExecutionContext<T, WasmVm, WasmLoader>, &mut GasMeter<T>) -> ExecResult
|
||||
) -> ExecResult {
|
||||
// Pay for the gas upfront.
|
||||
//
|
||||
// NOTE: it is very important to avoid any state changes before
|
||||
// paying for the gas.
|
||||
let (mut gas_meter, imbalance) =
|
||||
try_or_exec_error!(
|
||||
gas::buy_gas::<T>(&origin, gas_limit),
|
||||
// We don't have a spare buffer here in the first place, so create a new empty one.
|
||||
Vec::new()
|
||||
);
|
||||
|
||||
let cfg = Config::preload();
|
||||
let vm = WasmVm::new(&cfg.schedule);
|
||||
let loader = WasmLoader::new(&cfg.schedule);
|
||||
let mut ctx = ExecutionContext::top_level(origin.clone(), &cfg, &vm, &loader);
|
||||
|
||||
let result = func(&mut ctx, &mut gas_meter);
|
||||
let result = func(&mut ctx, gas_meter);
|
||||
|
||||
if result.as_ref().map(|output| output.is_success()).unwrap_or(false) {
|
||||
// Commit all changes that made it thus far into the persistent storage.
|
||||
DirectAccountDb.commit(ctx.overlay.into_change_set());
|
||||
}
|
||||
|
||||
// Refund cost of the unused gas.
|
||||
//
|
||||
// NOTE: This should go after the commit to the storage, since the storage changes
|
||||
// can alter the balance of the caller.
|
||||
gas::refund_unused_gas::<T>(&origin, gas_meter, imbalance);
|
||||
|
||||
// Execute deferred actions.
|
||||
ctx.deferred.into_iter().for_each(|deferred| {
|
||||
use self::exec::DeferredAction::*;
|
||||
@@ -759,7 +665,13 @@ impl<T: Trait> Module<T> {
|
||||
origin: who,
|
||||
call,
|
||||
} => {
|
||||
let info = call.get_dispatch_info();
|
||||
let result = call.dispatch(RawOrigin::Signed(who.clone()).into());
|
||||
let post_info = match result {
|
||||
Ok(post_info) => post_info,
|
||||
Err(err) => err.post_info,
|
||||
};
|
||||
gas_meter.refund(post_info.calc_unspent(&info));
|
||||
Self::deposit_event(RawEvent::Dispatched(who, result.is_ok()));
|
||||
}
|
||||
RestoreTo {
|
||||
@@ -917,8 +829,6 @@ decl_event! {
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Contracts {
|
||||
/// Gas spent so far in this block.
|
||||
GasSpent get(fn gas_spent): Gas;
|
||||
/// Current cost schedule for contracts.
|
||||
CurrentSchedule get(fn current_schedule) config(): Schedule = Schedule::default();
|
||||
/// A mapping from an original code hash to the original code, untouched by instrumentation.
|
||||
@@ -929,8 +839,6 @@ decl_storage! {
|
||||
pub AccountCounter: u64 = 0;
|
||||
/// The code associated with a given account.
|
||||
pub ContractInfoOf: map hasher(twox_64_concat) T::AccountId => Option<ContractInfo<T>>;
|
||||
/// The price of one unit of gas.
|
||||
GasPrice get(fn gas_price) config(): BalanceOf<T> = 1.into();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -944,7 +852,6 @@ pub struct Config<T: Trait> {
|
||||
pub tombstone_deposit: BalanceOf<T>,
|
||||
pub max_depth: u32,
|
||||
pub max_value_size: u32,
|
||||
pub contract_account_instantiate_fee: BalanceOf<T>,
|
||||
}
|
||||
|
||||
impl<T: Trait> Config<T> {
|
||||
@@ -955,7 +862,6 @@ impl<T: Trait> Config<T> {
|
||||
tombstone_deposit: T::TombstoneDeposit::get(),
|
||||
max_depth: T::MaxDepth::get(),
|
||||
max_value_size: T::MaxValueSize::get(),
|
||||
contract_account_instantiate_fee: T::ContractFee::get(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -994,6 +900,9 @@ pub struct Schedule {
|
||||
/// Base gas cost to instantiate a contract.
|
||||
pub instantiate_base_cost: Gas,
|
||||
|
||||
/// Base gas cost to dispatch a runtime call.
|
||||
pub dispatch_base_cost: Gas,
|
||||
|
||||
/// Gas cost per one byte read from the sandbox memory.
|
||||
pub sandbox_data_read_cost: Gas,
|
||||
|
||||
@@ -1003,6 +912,9 @@ pub struct Schedule {
|
||||
/// Cost for a simple balance transfer.
|
||||
pub transfer_cost: Gas,
|
||||
|
||||
/// Cost for instantiating a new contract.
|
||||
pub instantiate_cost: Gas,
|
||||
|
||||
/// The maximum number of topics supported by an event.
|
||||
pub max_event_topics: u32,
|
||||
|
||||
@@ -1026,22 +938,29 @@ pub struct Schedule {
|
||||
pub max_subject_len: u32,
|
||||
}
|
||||
|
||||
// 500 (2 instructions per nano second on 2GHZ) * 1000x slowdown through wasmi
|
||||
// This is a wild guess and should be viewed as a rough estimation.
|
||||
// Proper benchmarks are needed before this value and its derivatives can be used in production.
|
||||
const WASM_INSTRUCTION_COST: Gas = 500_000;
|
||||
|
||||
impl Default for Schedule {
|
||||
fn default() -> Schedule {
|
||||
Schedule {
|
||||
version: 0,
|
||||
put_code_per_byte_cost: 1,
|
||||
grow_mem_cost: 1,
|
||||
regular_op_cost: 1,
|
||||
return_data_per_byte_cost: 1,
|
||||
event_data_per_byte_cost: 1,
|
||||
event_per_topic_cost: 1,
|
||||
event_base_cost: 1,
|
||||
call_base_cost: 135,
|
||||
instantiate_base_cost: 175,
|
||||
sandbox_data_read_cost: 1,
|
||||
sandbox_data_write_cost: 1,
|
||||
transfer_cost: 100,
|
||||
put_code_per_byte_cost: WASM_INSTRUCTION_COST,
|
||||
grow_mem_cost: WASM_INSTRUCTION_COST,
|
||||
regular_op_cost: WASM_INSTRUCTION_COST,
|
||||
return_data_per_byte_cost: WASM_INSTRUCTION_COST,
|
||||
event_data_per_byte_cost: WASM_INSTRUCTION_COST,
|
||||
event_per_topic_cost: WASM_INSTRUCTION_COST,
|
||||
event_base_cost: WASM_INSTRUCTION_COST,
|
||||
call_base_cost: 135 * WASM_INSTRUCTION_COST,
|
||||
dispatch_base_cost: 135 * WASM_INSTRUCTION_COST,
|
||||
instantiate_base_cost: 175 * WASM_INSTRUCTION_COST,
|
||||
sandbox_data_read_cost: WASM_INSTRUCTION_COST,
|
||||
sandbox_data_write_cost: WASM_INSTRUCTION_COST,
|
||||
transfer_cost: 100 * WASM_INSTRUCTION_COST,
|
||||
instantiate_cost: 200 * WASM_INSTRUCTION_COST,
|
||||
max_event_topics: 4,
|
||||
max_stack_height: 64 * 1024,
|
||||
max_memory_pages: 16,
|
||||
@@ -1052,67 +971,3 @@ impl Default for Schedule {
|
||||
}
|
||||
}
|
||||
|
||||
/// `SignedExtension` that checks if a transaction would exhausts the block gas limit.
|
||||
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
|
||||
pub struct CheckBlockGasLimit<T: Trait + Send + Sync>(PhantomData<T>);
|
||||
|
||||
impl<T: Trait + Send + Sync> Default for CheckBlockGasLimit<T> {
|
||||
fn default() -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait + Send + Sync> sp_std::fmt::Debug for CheckBlockGasLimit<T> {
|
||||
#[cfg(feature = "std")]
|
||||
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
|
||||
write!(f, "CheckBlockGasLimit")
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait + Send + Sync> SignedExtension for CheckBlockGasLimit<T> {
|
||||
const IDENTIFIER: &'static str = "CheckBlockGasLimit";
|
||||
type AccountId = T::AccountId;
|
||||
type Call = <T as Trait>::Call;
|
||||
type AdditionalSigned = ();
|
||||
type Pre = ();
|
||||
|
||||
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
_: &Self::AccountId,
|
||||
call: &Self::Call,
|
||||
_: &DispatchInfoOf<Self::Call>,
|
||||
_: usize,
|
||||
) -> TransactionValidity {
|
||||
let call = match call.is_sub_type() {
|
||||
Some(call) => call,
|
||||
None => return Ok(ValidTransaction::default()),
|
||||
};
|
||||
|
||||
match call {
|
||||
Call::claim_surcharge(_, _) | Call::update_schedule(_) =>
|
||||
Ok(ValidTransaction::default()),
|
||||
Call::put_code(gas_limit, _)
|
||||
| Call::call(_, _, gas_limit, _)
|
||||
| Call::instantiate(_, gas_limit, _, _)
|
||||
=> {
|
||||
// Check if the specified amount of gas is available in the current block.
|
||||
// This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`.
|
||||
let gas_available = T::BlockGasLimit::get() - <Module<T>>::gas_spent();
|
||||
if *gas_limit > gas_available {
|
||||
// gas limit reached, revert the transaction and retry again in the future
|
||||
InvalidTransaction::ExhaustsResources.into()
|
||||
} else {
|
||||
Ok(ValidTransaction::default())
|
||||
}
|
||||
},
|
||||
Call::__PhantomItem(_, _) => unreachable!("Variant is never constructed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user