use crate::{
limits, metering::Token, weightinfo_extension::OnFinalizeBlockParts, weights::WeightInfo,
Config,
};
use frame_support::weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight};
const GAS_PER_SECOND: u64 = 40_000_000;
const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND / GAS_PER_SECOND;
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
#[derive(Copy, Clone)]
pub enum RuntimeCosts {
HostFn,
ExtCodeCopy(u32),
CopyFromContract(u32),
CopyToContract(u32),
CallDataLoad,
CallDataCopy(u32),
Caller,
CallDataSize,
ReturnDataSize,
ToAccountId,
Origin,
CodeHash,
OwnCodeHash,
CodeSize,
CallerIsOrigin,
CallerIsRoot,
Address,
RefTimeLeft,
WeightLeft,
Balance,
BalanceOf,
ValueTransferred,
MinimumBalance,
BlockNumber,
BlockHash,
BlockAuthor,
GasPrice,
BaseFee,
Now,
GasLimit,
Terminate { code_removed: bool },
DepositEvent { num_topic: u32, len: u32 },
SetStorage { old_bytes: u32, new_bytes: u32 },
ClearStorage(u32),
ContainsStorage(u32),
GetStorage(u32),
TakeStorage(u32),
SetTransientStorage { old_bytes: u32, new_bytes: u32 },
ClearTransientStorage(u32),
ContainsTransientStorage(u32),
GetTransientStorage(u32),
TakeTransientStorage(u32),
CallBase,
DelegateCallBase,
PrecompileBase,
PrecompileWithInfoBase,
PrecompileDecode(u32),
CallTransferSurcharge { dust_transfer: bool },
CallInputCloned(u32),
Instantiate { input_data_len: u32, balance_transfer: bool, dust_transfer: bool },
Create { init_code_len: u32, balance_transfer: bool, dust_transfer: bool },
Ripemd160(u32),
HashSha256(u32),
HashKeccak256(u32),
HashBlake256(u32),
HashBlake128(u32),
EcdsaRecovery,
P256Verify,
Sr25519Verify(u32),
Precompile(Weight),
EcdsaToEthAddress,
GetImmutableData(u32),
SetImmutableData(u32),
Bn128Add,
Bn128Mul,
Bn128Pairing(u32),
Identity(u32),
Blake2F(u32),
Modexp(u64),
}
macro_rules! cost_storage {
(write_transient, $name:ident $(, $arg:expr )*) => {
T::WeightInfo::$name($( $arg ),*)
.saturating_add(T::WeightInfo::rollback_transient_storage())
.saturating_add(T::WeightInfo::set_transient_storage_full()
.saturating_sub(T::WeightInfo::set_transient_storage_empty()))
};
(read_transient, $name:ident $(, $arg:expr )*) => {
T::WeightInfo::$name($( $arg ),*)
.saturating_add(T::WeightInfo::get_transient_storage_full()
.saturating_sub(T::WeightInfo::get_transient_storage_empty()))
};
(write, $name:ident $(, $arg:expr )*) => {
T::WeightInfo::$name($( $arg ),*)
.saturating_add(T::WeightInfo::set_storage_full()
.saturating_sub(T::WeightInfo::set_storage_empty()))
};
(read, $name:ident $(, $arg:expr )*) => {
T::WeightInfo::$name($( $arg ),*)
.saturating_add(T::WeightInfo::get_storage_full()
.saturating_sub(T::WeightInfo::get_storage_empty()))
};
}
macro_rules! cost_args {
($name:ident, $( $arg: expr ),+) => {
(T::WeightInfo::$name($( $arg ),+).saturating_sub(cost_args!(@call_zero $name, $( $arg ),+)))
};
(@call_zero $name:ident, $( $arg:expr ),*) => {
T::WeightInfo::$name($( cost_args!(@replace_token $arg) ),*)
};
(@replace_token $_in:tt) => { 0 };
}
impl<T: Config> Token<T> for RuntimeCosts {
fn influence_lowest_weight_limit(&self) -> bool {
true
}
fn weight(&self) -> Weight {
use self::RuntimeCosts::*;
match *self {
HostFn => cost_args!(noop_host_fn, 1),
ExtCodeCopy(len) => T::WeightInfo::extcodecopy(len),
CopyToContract(len) => T::WeightInfo::seal_copy_to_contract(len),
CopyFromContract(len) => T::WeightInfo::seal_return(len),
CallDataSize => T::WeightInfo::seal_call_data_size(),
ReturnDataSize => T::WeightInfo::seal_return_data_size(),
CallDataLoad => T::WeightInfo::seal_call_data_load(),
CallDataCopy(len) => T::WeightInfo::seal_call_data_copy(len),
Caller => T::WeightInfo::seal_caller(),
Origin => T::WeightInfo::seal_origin(),
ToAccountId => T::WeightInfo::to_account_id(),
CodeHash => T::WeightInfo::seal_code_hash(),
CodeSize => T::WeightInfo::seal_code_size(),
OwnCodeHash => T::WeightInfo::own_code_hash(),
CallerIsOrigin => T::WeightInfo::caller_is_origin(),
CallerIsRoot => T::WeightInfo::caller_is_root(),
Address => T::WeightInfo::seal_address(),
RefTimeLeft => T::WeightInfo::seal_ref_time_left(),
WeightLeft => T::WeightInfo::weight_left(),
Balance => T::WeightInfo::seal_balance(),
BalanceOf => T::WeightInfo::seal_balance_of(),
ValueTransferred => T::WeightInfo::seal_value_transferred(),
MinimumBalance => T::WeightInfo::minimum_balance(),
BlockNumber => T::WeightInfo::seal_block_number(),
BlockHash => T::WeightInfo::seal_block_hash(),
BlockAuthor => T::WeightInfo::seal_block_author(),
GasPrice => T::WeightInfo::seal_gas_price(),
BaseFee => T::WeightInfo::seal_base_fee(),
Now => T::WeightInfo::seal_now(),
GasLimit => T::WeightInfo::seal_gas_limit(),
Terminate { code_removed } => {
if code_removed {
T::WeightInfo::seal_terminate(code_removed.into())
.saturating_add(T::WeightInfo::seal_terminate_logic())
} else {
T::WeightInfo::seal_terminate(code_removed.into())
}
},
DepositEvent { num_topic, len } => T::WeightInfo::seal_deposit_event(num_topic, len)
.saturating_add(T::WeightInfo::on_finalize_block_per_event(len))
.saturating_add(Weight::from_parts(
limits::EXTRA_EVENT_CHARGE_PER_BYTE.saturating_mul(len.into()).into(),
0,
)),
SetStorage { new_bytes, old_bytes } => {
cost_storage!(write, seal_set_storage, new_bytes, old_bytes)
},
ClearStorage(len) => cost_storage!(write, clear_storage, len),
ContainsStorage(len) => cost_storage!(read, contains_storage, len),
GetStorage(len) => cost_storage!(read, seal_get_storage, len),
TakeStorage(len) => cost_storage!(write, take_storage, len),
SetTransientStorage { new_bytes, old_bytes } => {
cost_storage!(write_transient, seal_set_transient_storage, new_bytes, old_bytes)
},
ClearTransientStorage(len) => {
cost_storage!(write_transient, seal_clear_transient_storage, len)
},
ContainsTransientStorage(len) => {
cost_storage!(read_transient, seal_contains_transient_storage, len)
},
GetTransientStorage(len) => {
cost_storage!(read_transient, seal_get_transient_storage, len)
},
TakeTransientStorage(len) => {
cost_storage!(write_transient, seal_take_transient_storage, len)
},
CallBase => T::WeightInfo::seal_call(0, 0, 0),
DelegateCallBase => T::WeightInfo::seal_delegate_call(),
PrecompileBase => T::WeightInfo::seal_call_precompile(0, 0),
PrecompileWithInfoBase => T::WeightInfo::seal_call_precompile(1, 0),
PrecompileDecode(len) => cost_args!(seal_call_precompile, 0, len),
CallTransferSurcharge { dust_transfer } =>
cost_args!(seal_call, 1, dust_transfer.into(), 0),
CallInputCloned(len) => cost_args!(seal_call, 0, 0, len),
Instantiate { input_data_len, balance_transfer, dust_transfer } =>
T::WeightInfo::seal_instantiate(
balance_transfer.into(),
dust_transfer.into(),
input_data_len,
),
Create { init_code_len, balance_transfer, dust_transfer } =>
T::WeightInfo::evm_instantiate(
balance_transfer.into(),
dust_transfer.into(),
init_code_len,
),
HashSha256(len) => T::WeightInfo::sha2_256(len),
Ripemd160(len) => T::WeightInfo::ripemd_160(len),
HashKeccak256(len) => T::WeightInfo::seal_hash_keccak_256(len),
HashBlake256(len) => T::WeightInfo::hash_blake2_256(len),
HashBlake128(len) => T::WeightInfo::hash_blake2_128(len),
EcdsaRecovery => T::WeightInfo::ecdsa_recover(),
P256Verify => T::WeightInfo::p256_verify(),
Sr25519Verify(len) => T::WeightInfo::seal_sr25519_verify(len),
Precompile(weight) => weight,
EcdsaToEthAddress => T::WeightInfo::seal_ecdsa_to_eth_address(),
GetImmutableData(len) => T::WeightInfo::seal_get_immutable_data(len),
SetImmutableData(len) => T::WeightInfo::seal_set_immutable_data(len),
Bn128Add => T::WeightInfo::bn128_add(),
Bn128Mul => T::WeightInfo::bn128_mul(),
Bn128Pairing(len) => T::WeightInfo::bn128_pairing(len),
Identity(len) => T::WeightInfo::identity(len),
Blake2F(rounds) => T::WeightInfo::blake2f(rounds),
Modexp(gas) => Weight::from_parts(gas.saturating_mul(WEIGHT_PER_GAS), 0),
}
}
}