mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 16:21:02 +00:00
contracts: Refactor the exec module (#8604)
* contracts: Add default implementation for Executable::occupied_storage() * contracts: Refactor the exec module * Let runtime specify the backing type of the call stack This removes the need for a runtime check of the specified `MaxDepth`. We can now garantuee that we don't need to allocate when a new call frame is pushed. * Fix doc typo Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Review nits * Fix defect in contract info caching behaviour * Add more docs * Fix wording and typos Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> Co-authored-by: Parity Benchmarking Bot <admin@parity.io>
This commit is contained in:
committed by
GitHub
parent
17a1997d18
commit
9e894ce135
@@ -20,7 +20,7 @@
|
||||
use crate::{
|
||||
Config, CodeHash, BalanceOf, Error,
|
||||
exec::{Ext, StorageKey, TopicOf, ExecResult, ExecError},
|
||||
gas::{GasMeter, Token, ChargedAmount},
|
||||
gas::{Token, ChargedAmount},
|
||||
wasm::env_def::ConvertibleToWasm,
|
||||
schedule::HostFnWeights,
|
||||
};
|
||||
@@ -28,7 +28,6 @@ use parity_wasm::elements::ValueType;
|
||||
use frame_support::{dispatch::DispatchError, ensure, traits::Get, weights::Weight};
|
||||
use sp_std::prelude::*;
|
||||
use codec::{Decode, DecodeAll, Encode};
|
||||
use sp_runtime::traits::SaturatedConversion;
|
||||
use sp_core::{Bytes, crypto::UncheckedFrom};
|
||||
use sp_io::hashing::{
|
||||
keccak_256,
|
||||
@@ -132,7 +131,7 @@ impl<T: Into<DispatchError>> From<T> for TrapReason {
|
||||
|
||||
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum RuntimeToken {
|
||||
pub enum RuntimeCosts {
|
||||
/// Charge the gas meter with the cost of a metering block. The charged costs are
|
||||
/// the supplied cost of the block plus the overhead of the metering itself.
|
||||
MeteringBlock(u32),
|
||||
@@ -220,15 +219,14 @@ pub enum RuntimeToken {
|
||||
RentParams,
|
||||
}
|
||||
|
||||
impl<T: Config> Token<T> for RuntimeToken
|
||||
where
|
||||
T::AccountId: UncheckedFrom<T::Hash>, T::AccountId: AsRef<[u8]>
|
||||
{
|
||||
type Metadata = HostFnWeights<T>;
|
||||
|
||||
fn calculate_amount(&self, s: &Self::Metadata) -> Weight {
|
||||
use self::RuntimeToken::*;
|
||||
match *self {
|
||||
impl RuntimeCosts {
|
||||
fn token<T>(&self, s: &HostFnWeights<T>) -> RuntimeToken
|
||||
where
|
||||
T: Config,
|
||||
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
|
||||
{
|
||||
use self::RuntimeCosts::*;
|
||||
let weight = match *self {
|
||||
MeteringBlock(amount) => s.gas.saturating_add(amount.into()),
|
||||
Caller => s.caller,
|
||||
Address => s.address,
|
||||
@@ -287,14 +285,37 @@ where
|
||||
ChainExtension(amount) => amount,
|
||||
CopyIn(len) => s.return_per_byte.saturating_mul(len.into()),
|
||||
RentParams => s.rent_params,
|
||||
};
|
||||
RuntimeToken {
|
||||
#[cfg(test)]
|
||||
_created_from: *self,
|
||||
weight,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
|
||||
#[derive(Copy, Clone)]
|
||||
struct RuntimeToken {
|
||||
#[cfg(test)]
|
||||
_created_from: RuntimeCosts,
|
||||
weight: Weight,
|
||||
}
|
||||
|
||||
impl<T> Token<T> for RuntimeToken
|
||||
where
|
||||
T: Config,
|
||||
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
|
||||
{
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
}
|
||||
|
||||
/// This is only appropriate when writing out data of constant size that does not depend on user
|
||||
/// input. In this case the costs for this copy was already charged as part of the token at
|
||||
/// the beginning of the API entry point.
|
||||
fn already_charged(_: u32) -> Option<RuntimeToken> {
|
||||
fn already_charged(_: u32) -> Option<RuntimeCosts> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -303,7 +324,6 @@ pub struct Runtime<'a, E: Ext + 'a> {
|
||||
ext: &'a mut E,
|
||||
input_data: Option<Vec<u8>>,
|
||||
memory: sp_sandbox::Memory,
|
||||
gas_meter: &'a mut GasMeter<E::T>,
|
||||
trap_reason: Option<TrapReason>,
|
||||
}
|
||||
|
||||
@@ -317,13 +337,11 @@ where
|
||||
ext: &'a mut E,
|
||||
input_data: Vec<u8>,
|
||||
memory: sp_sandbox::Memory,
|
||||
gas_meter: &'a mut GasMeter<E::T>,
|
||||
) -> Self {
|
||||
Runtime {
|
||||
ext,
|
||||
input_data: Some(input_data),
|
||||
memory,
|
||||
gas_meter,
|
||||
trap_reason: None,
|
||||
}
|
||||
}
|
||||
@@ -406,21 +424,16 @@ where
|
||||
/// Charge the gas meter with the specified token.
|
||||
///
|
||||
/// Returns `Err(HostError)` if there is not enough gas.
|
||||
pub fn charge_gas<Tok>(&mut self, token: Tok) -> Result<ChargedAmount, DispatchError>
|
||||
where
|
||||
Tok: Token<E::T, Metadata=HostFnWeights<E::T>>,
|
||||
{
|
||||
self.gas_meter.charge(&self.ext.schedule().host_fn_weights, token)
|
||||
pub fn charge_gas(&mut self, costs: RuntimeCosts) -> Result<ChargedAmount, DispatchError> {
|
||||
let token = costs.token(&self.ext.schedule().host_fn_weights);
|
||||
self.ext.gas_meter().charge(token)
|
||||
}
|
||||
|
||||
/// Correct previously charged gas amount.
|
||||
pub fn adjust_gas<Tok>(&mut self, charged_amount: ChargedAmount, adjusted_amount: Tok)
|
||||
where
|
||||
Tok: Token<E::T, Metadata=HostFnWeights<E::T>>,
|
||||
{
|
||||
self.gas_meter.adjust_gas(
|
||||
pub fn adjust_gas(&mut self, charged_amount: ChargedAmount, adjusted_amount: RuntimeCosts) {
|
||||
let adjusted_amount = adjusted_amount.token(&self.ext.schedule().host_fn_weights);
|
||||
self.ext.gas_meter().adjust_gas(
|
||||
charged_amount,
|
||||
&self.ext.schedule().host_fn_weights,
|
||||
adjusted_amount,
|
||||
);
|
||||
}
|
||||
@@ -474,11 +487,11 @@ where
|
||||
pub fn read_sandbox_memory_as<D: Decode>(&mut self, ptr: u32, len: u32)
|
||||
-> Result<D, DispatchError>
|
||||
{
|
||||
let amount = self.charge_gas(RuntimeToken::CopyIn(len))?;
|
||||
let amount = self.charge_gas(RuntimeCosts::CopyIn(len))?;
|
||||
let buf = self.read_sandbox_memory(ptr, len)?;
|
||||
let decoded = D::decode_all(&mut &buf[..])
|
||||
.map_err(|_| DispatchError::from(Error::<E::T>::DecodingFailed))?;
|
||||
self.gas_meter.refund(amount);
|
||||
self.ext.gas_meter().refund(amount);
|
||||
Ok(decoded)
|
||||
}
|
||||
|
||||
@@ -507,7 +520,7 @@ where
|
||||
out_len_ptr: u32,
|
||||
buf: &[u8],
|
||||
allow_skip: bool,
|
||||
create_token: impl FnOnce(u32) -> Option<RuntimeToken>,
|
||||
create_token: impl FnOnce(u32) -> Option<RuntimeCosts>,
|
||||
) -> Result<(), DispatchError>
|
||||
{
|
||||
if allow_skip && out_ptr == u32::max_value() {
|
||||
@@ -521,8 +534,8 @@ where
|
||||
Err(Error::<E::T>::OutputBufferTooSmall)?
|
||||
}
|
||||
|
||||
if let Some(token) = create_token(buf_len) {
|
||||
self.charge_gas(token)?;
|
||||
if let Some(costs) = create_token(buf_len) {
|
||||
self.charge_gas(costs)?;
|
||||
}
|
||||
|
||||
self.memory.set(out_ptr, buf).and_then(|_| {
|
||||
@@ -631,7 +644,7 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// - amount: How much gas is used.
|
||||
[seal0] gas(ctx, amount: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::MeteringBlock(amount))?;
|
||||
ctx.charge_gas(RuntimeCosts::MeteringBlock(amount))?;
|
||||
Ok(())
|
||||
},
|
||||
|
||||
@@ -651,7 +664,7 @@ define_env!(Env, <E: Ext>,
|
||||
// - If value length exceeds the configured maximum value length of a storage entry.
|
||||
// - Upon trying to set an empty storage entry (value length is 0).
|
||||
[seal0] seal_set_storage(ctx, key_ptr: u32, value_ptr: u32, value_len: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::SetStorage(value_len))?;
|
||||
ctx.charge_gas(RuntimeCosts::SetStorage(value_len))?;
|
||||
if value_len > ctx.ext.max_value_size() {
|
||||
Err(Error::<E::T>::ValueTooLarge)?;
|
||||
}
|
||||
@@ -667,7 +680,7 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// - `key_ptr`: pointer into the linear memory where the location to clear the value is placed.
|
||||
[seal0] seal_clear_storage(ctx, key_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::ClearStorage)?;
|
||||
ctx.charge_gas(RuntimeCosts::ClearStorage)?;
|
||||
let mut key: StorageKey = [0; 32];
|
||||
ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?;
|
||||
ctx.ext.set_storage(key, None).map_err(Into::into)
|
||||
@@ -686,12 +699,12 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// `ReturnCode::KeyNotFound`
|
||||
[seal0] seal_get_storage(ctx, key_ptr: u32, out_ptr: u32, out_len_ptr: u32) -> ReturnCode => {
|
||||
ctx.charge_gas(RuntimeToken::GetStorageBase)?;
|
||||
ctx.charge_gas(RuntimeCosts::GetStorageBase)?;
|
||||
let mut key: StorageKey = [0; 32];
|
||||
ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?;
|
||||
if let Some(value) = ctx.ext.get_storage(&key) {
|
||||
ctx.write_sandbox_output(out_ptr, out_len_ptr, &value, false, |len| {
|
||||
Some(RuntimeToken::GetStorageCopyOut(len))
|
||||
Some(RuntimeCosts::GetStorageCopyOut(len))
|
||||
})?;
|
||||
Ok(ReturnCode::Success)
|
||||
} else {
|
||||
@@ -721,7 +734,7 @@ define_env!(Env, <E: Ext>,
|
||||
value_ptr: u32,
|
||||
value_len: u32
|
||||
) -> ReturnCode => {
|
||||
ctx.charge_gas(RuntimeToken::Transfer)?;
|
||||
ctx.charge_gas(RuntimeCosts::Transfer)?;
|
||||
let callee: <<E as Ext>::T as frame_system::Config>::AccountId =
|
||||
ctx.read_sandbox_memory_as(account_ptr, account_len)?;
|
||||
let value: BalanceOf<<E as Ext>::T> =
|
||||
@@ -780,45 +793,27 @@ define_env!(Env, <E: Ext>,
|
||||
output_ptr: u32,
|
||||
output_len_ptr: u32
|
||||
) -> ReturnCode => {
|
||||
ctx.charge_gas(RuntimeToken::CallBase(input_data_len))?;
|
||||
ctx.charge_gas(RuntimeCosts::CallBase(input_data_len))?;
|
||||
let callee: <<E as Ext>::T as frame_system::Config>::AccountId =
|
||||
ctx.read_sandbox_memory_as(callee_ptr, callee_len)?;
|
||||
let value: BalanceOf<<E as Ext>::T> = ctx.read_sandbox_memory_as(value_ptr, value_len)?;
|
||||
let input_data = ctx.read_sandbox_memory(input_data_ptr, input_data_len)?;
|
||||
if value > 0u32.into() {
|
||||
ctx.charge_gas(RuntimeToken::CallSurchargeTransfer)?;
|
||||
ctx.charge_gas(RuntimeCosts::CallSurchargeTransfer)?;
|
||||
}
|
||||
let charged = ctx.charge_gas(
|
||||
RuntimeToken::CallSurchargeCodeSize(<E::T as Config>::MaxCodeSize::get())
|
||||
RuntimeCosts::CallSurchargeCodeSize(<E::T as Config>::MaxCodeSize::get())
|
||||
)?;
|
||||
let nested_gas_limit = if gas == 0 {
|
||||
ctx.gas_meter.gas_left()
|
||||
} else {
|
||||
gas.saturated_into()
|
||||
};
|
||||
let ext = &mut ctx.ext;
|
||||
let call_outcome = ctx.gas_meter.with_nested(nested_gas_limit, |nested_meter| {
|
||||
match nested_meter {
|
||||
Some(nested_meter) => {
|
||||
ext.call(
|
||||
&callee,
|
||||
value,
|
||||
nested_meter,
|
||||
input_data,
|
||||
)
|
||||
}
|
||||
// there is not enough gas to allocate for the nested call.
|
||||
None => Err((Error::<<E as Ext>::T>::OutOfGas.into(), 0)),
|
||||
}
|
||||
});
|
||||
let call_outcome = ext.call(gas, callee, value, input_data);
|
||||
let code_len = match &call_outcome {
|
||||
Ok((_, len)) => len,
|
||||
Err((_, len)) => len,
|
||||
};
|
||||
ctx.adjust_gas(charged, RuntimeToken::CallSurchargeCodeSize(*code_len));
|
||||
ctx.adjust_gas(charged, RuntimeCosts::CallSurchargeCodeSize(*code_len));
|
||||
if let Ok((output, _)) = &call_outcome {
|
||||
ctx.write_sandbox_output(output_ptr, output_len_ptr, &output.data, true, |len| {
|
||||
Some(RuntimeToken::CallCopyOut(len))
|
||||
Some(RuntimeCosts::CallCopyOut(len))
|
||||
})?;
|
||||
}
|
||||
Ok(Runtime::<E>::exec_into_return_code(call_outcome.map(|r| r.0).map_err(|r| r.0))?)
|
||||
@@ -885,41 +880,22 @@ define_env!(Env, <E: Ext>,
|
||||
salt_ptr: u32,
|
||||
salt_len: u32
|
||||
) -> ReturnCode => {
|
||||
ctx.charge_gas(RuntimeToken::InstantiateBase {input_data_len, salt_len})?;
|
||||
ctx.charge_gas(RuntimeCosts::InstantiateBase {input_data_len, salt_len})?;
|
||||
let code_hash: CodeHash<<E as Ext>::T> =
|
||||
ctx.read_sandbox_memory_as(code_hash_ptr, code_hash_len)?;
|
||||
let value: BalanceOf<<E as Ext>::T> = ctx.read_sandbox_memory_as(value_ptr, value_len)?;
|
||||
let input_data = ctx.read_sandbox_memory(input_data_ptr, input_data_len)?;
|
||||
let salt = ctx.read_sandbox_memory(salt_ptr, salt_len)?;
|
||||
let charged = ctx.charge_gas(
|
||||
RuntimeToken::InstantiateSurchargeCodeSize(<E::T as Config>::MaxCodeSize::get())
|
||||
RuntimeCosts::InstantiateSurchargeCodeSize(<E::T as Config>::MaxCodeSize::get())
|
||||
)?;
|
||||
let nested_gas_limit = if gas == 0 {
|
||||
ctx.gas_meter.gas_left()
|
||||
} else {
|
||||
gas.saturated_into()
|
||||
};
|
||||
let ext = &mut ctx.ext;
|
||||
let instantiate_outcome = ctx.gas_meter.with_nested(nested_gas_limit, |nested_meter| {
|
||||
match nested_meter {
|
||||
Some(nested_meter) => {
|
||||
ext.instantiate(
|
||||
code_hash,
|
||||
value,
|
||||
nested_meter,
|
||||
input_data,
|
||||
&salt,
|
||||
)
|
||||
}
|
||||
// there is not enough gas to allocate for the nested call.
|
||||
None => Err((Error::<<E as Ext>::T>::OutOfGas.into(), 0)),
|
||||
}
|
||||
});
|
||||
let instantiate_outcome = ext.instantiate(gas, code_hash, value, input_data, &salt);
|
||||
let code_len = match &instantiate_outcome {
|
||||
Ok((_, _, code_len)) => code_len,
|
||||
Err((_, code_len)) => code_len,
|
||||
};
|
||||
ctx.adjust_gas(charged, RuntimeToken::InstantiateSurchargeCodeSize(*code_len));
|
||||
ctx.adjust_gas(charged, RuntimeCosts::InstantiateSurchargeCodeSize(*code_len));
|
||||
if let Ok((address, output, _)) = &instantiate_outcome {
|
||||
if !output.flags.contains(ReturnFlags::REVERT) {
|
||||
ctx.write_sandbox_output(
|
||||
@@ -927,7 +903,7 @@ define_env!(Env, <E: Ext>,
|
||||
)?;
|
||||
}
|
||||
ctx.write_sandbox_output(output_ptr, output_len_ptr, &output.data, true, |len| {
|
||||
Some(RuntimeToken::InstantiateCopyOut(len))
|
||||
Some(RuntimeCosts::InstantiateCopyOut(len))
|
||||
})?;
|
||||
}
|
||||
Ok(Runtime::<E>::exec_into_return_code(
|
||||
@@ -956,18 +932,18 @@ define_env!(Env, <E: Ext>,
|
||||
beneficiary_ptr: u32,
|
||||
beneficiary_len: u32
|
||||
) => {
|
||||
ctx.charge_gas(RuntimeToken::Terminate)?;
|
||||
ctx.charge_gas(RuntimeCosts::Terminate)?;
|
||||
let beneficiary: <<E as Ext>::T as frame_system::Config>::AccountId =
|
||||
ctx.read_sandbox_memory_as(beneficiary_ptr, beneficiary_len)?;
|
||||
|
||||
let charged = ctx.charge_gas(
|
||||
RuntimeToken::TerminateSurchargeCodeSize(<E::T as Config>::MaxCodeSize::get())
|
||||
RuntimeCosts::TerminateSurchargeCodeSize(<E::T as Config>::MaxCodeSize::get())
|
||||
)?;
|
||||
let (result, code_len) = match ctx.ext.terminate(&beneficiary) {
|
||||
Ok(len) => (Ok(()), len),
|
||||
Err((err, len)) => (Err(err), len),
|
||||
};
|
||||
ctx.adjust_gas(charged, RuntimeToken::TerminateSurchargeCodeSize(code_len));
|
||||
ctx.adjust_gas(charged, RuntimeCosts::TerminateSurchargeCodeSize(code_len));
|
||||
result?;
|
||||
Err(TrapReason::Termination)
|
||||
},
|
||||
@@ -983,10 +959,10 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// This function can only be called once. Calling it multiple times will trigger a trap.
|
||||
[seal0] seal_input(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::InputBase)?;
|
||||
ctx.charge_gas(RuntimeCosts::InputBase)?;
|
||||
if let Some(input) = ctx.input_data.take() {
|
||||
ctx.write_sandbox_output(out_ptr, out_len_ptr, &input, false, |len| {
|
||||
Some(RuntimeToken::InputCopyOut(len))
|
||||
Some(RuntimeCosts::InputCopyOut(len))
|
||||
})?;
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -1012,7 +988,7 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// Using a reserved bit triggers a trap.
|
||||
[seal0] seal_return(ctx, flags: u32, data_ptr: u32, data_len: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::Return(data_len))?;
|
||||
ctx.charge_gas(RuntimeCosts::Return(data_len))?;
|
||||
Err(TrapReason::Return(ReturnData {
|
||||
flags,
|
||||
data: ctx.read_sandbox_memory(data_ptr, data_len)?,
|
||||
@@ -1030,7 +1006,7 @@ define_env!(Env, <E: Ext>,
|
||||
// extrinsic will be returned. Otherwise, if this call is initiated by another contract then the
|
||||
// address of the contract will be returned. The value is encoded as T::AccountId.
|
||||
[seal0] seal_caller(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::Caller)?;
|
||||
ctx.charge_gas(RuntimeCosts::Caller)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.caller().encode(), false, already_charged
|
||||
)?)
|
||||
@@ -1043,7 +1019,7 @@ define_env!(Env, <E: Ext>,
|
||||
// `out_ptr`. This call overwrites it with the size of the value. If the available
|
||||
// space at `out_ptr` is less than the size of the value a trap is triggered.
|
||||
[seal0] seal_address(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::Address)?;
|
||||
ctx.charge_gas(RuntimeCosts::Address)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.address().encode(), false, already_charged
|
||||
)?)
|
||||
@@ -1063,7 +1039,7 @@ define_env!(Env, <E: Ext>,
|
||||
// It is recommended to avoid specifying very small values for `gas` as the prices for a single
|
||||
// gas can be smaller than one.
|
||||
[seal0] seal_weight_to_fee(ctx, gas: u64, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::WeightToFee)?;
|
||||
ctx.charge_gas(RuntimeCosts::WeightToFee)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.get_weight_price(gas).encode(), false, already_charged
|
||||
)?)
|
||||
@@ -1078,9 +1054,10 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// The data is encoded as Gas.
|
||||
[seal0] seal_gas_left(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::GasLeft)?;
|
||||
ctx.charge_gas(RuntimeCosts::GasLeft)?;
|
||||
let gas_left = &ctx.ext.gas_meter().gas_left().encode();
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.gas_meter.gas_left().encode(), false, already_charged
|
||||
out_ptr, out_len_ptr, &gas_left, false, already_charged,
|
||||
)?)
|
||||
},
|
||||
|
||||
@@ -1093,7 +1070,7 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// The data is encoded as T::Balance.
|
||||
[seal0] seal_balance(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::Balance)?;
|
||||
ctx.charge_gas(RuntimeCosts::Balance)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.balance().encode(), false, already_charged
|
||||
)?)
|
||||
@@ -1108,7 +1085,7 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// The data is encoded as T::Balance.
|
||||
[seal0] seal_value_transferred(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::ValueTransferred)?;
|
||||
ctx.charge_gas(RuntimeCosts::ValueTransferred)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.value_transferred().encode(), false, already_charged
|
||||
)?)
|
||||
@@ -1127,7 +1104,7 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// This function is deprecated. Users should migrate to the version in the "seal1" module.
|
||||
[seal0] seal_random(ctx, subject_ptr: u32, subject_len: u32, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::Random)?;
|
||||
ctx.charge_gas(RuntimeCosts::Random)?;
|
||||
if subject_len > ctx.ext.schedule().limits.subject_len {
|
||||
Err(Error::<E::T>::RandomSubjectTooLong)?;
|
||||
}
|
||||
@@ -1159,7 +1136,7 @@ define_env!(Env, <E: Ext>,
|
||||
// call this on later blocks until the block number returned is later than the latest
|
||||
// commitment.
|
||||
[seal1] seal_random(ctx, subject_ptr: u32, subject_len: u32, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::Random)?;
|
||||
ctx.charge_gas(RuntimeCosts::Random)?;
|
||||
if subject_len > ctx.ext.schedule().limits.subject_len {
|
||||
Err(Error::<E::T>::RandomSubjectTooLong)?;
|
||||
}
|
||||
@@ -1176,7 +1153,7 @@ define_env!(Env, <E: Ext>,
|
||||
// `out_ptr`. This call overwrites it with the size of the value. If the available
|
||||
// space at `out_ptr` is less than the size of the value a trap is triggered.
|
||||
[seal0] seal_now(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::Now)?;
|
||||
ctx.charge_gas(RuntimeCosts::Now)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.now().encode(), false, already_charged
|
||||
)?)
|
||||
@@ -1186,7 +1163,7 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// The data is encoded as T::Balance.
|
||||
[seal0] seal_minimum_balance(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::MinimumBalance)?;
|
||||
ctx.charge_gas(RuntimeCosts::MinimumBalance)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.minimum_balance().encode(), false, already_charged
|
||||
)?)
|
||||
@@ -1208,7 +1185,7 @@ define_env!(Env, <E: Ext>,
|
||||
// below the sum of existential deposit and the tombstone deposit. The sum
|
||||
// is commonly referred as subsistence threshold in code.
|
||||
[seal0] seal_tombstone_deposit(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::TombstoneDeposit)?;
|
||||
ctx.charge_gas(RuntimeCosts::TombstoneDeposit)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.tombstone_deposit().encode(), false, already_charged
|
||||
)?)
|
||||
@@ -1256,7 +1233,7 @@ define_env!(Env, <E: Ext>,
|
||||
delta_ptr: u32,
|
||||
delta_count: u32
|
||||
) => {
|
||||
ctx.charge_gas(RuntimeToken::RestoreTo(delta_count))?;
|
||||
ctx.charge_gas(RuntimeCosts::RestoreTo(delta_count))?;
|
||||
let dest: <<E as Ext>::T as frame_system::Config>::AccountId =
|
||||
ctx.read_sandbox_memory_as(dest_ptr, dest_len)?;
|
||||
let code_hash: CodeHash<<E as Ext>::T> =
|
||||
@@ -1290,7 +1267,7 @@ define_env!(Env, <E: Ext>,
|
||||
};
|
||||
|
||||
let max_len = <E::T as Config>::MaxCodeSize::get();
|
||||
let charged = ctx.charge_gas(RuntimeToken::RestoreToSurchargeCodeSize {
|
||||
let charged = ctx.charge_gas(RuntimeCosts::RestoreToSurchargeCodeSize {
|
||||
caller_code: max_len,
|
||||
tombstone_code: max_len,
|
||||
})?;
|
||||
@@ -1300,7 +1277,7 @@ define_env!(Env, <E: Ext>,
|
||||
Ok((code, tomb)) => (Ok(()), code, tomb),
|
||||
Err((err, code, tomb)) => (Err(err), code, tomb),
|
||||
};
|
||||
ctx.adjust_gas(charged, RuntimeToken::RestoreToSurchargeCodeSize {
|
||||
ctx.adjust_gas(charged, RuntimeCosts::RestoreToSurchargeCodeSize {
|
||||
caller_code,
|
||||
tombstone_code,
|
||||
});
|
||||
@@ -1341,7 +1318,7 @@ define_env!(Env, <E: Ext>,
|
||||
let num_topic = topics_len
|
||||
.checked_div(sp_std::mem::size_of::<TopicOf<E::T>>() as u32)
|
||||
.ok_or_else(|| "Zero sized topics are not allowed")?;
|
||||
ctx.charge_gas(RuntimeToken::DepositEvent {
|
||||
ctx.charge_gas(RuntimeCosts::DepositEvent {
|
||||
num_topic,
|
||||
len: data_len,
|
||||
})?;
|
||||
@@ -1379,7 +1356,7 @@ define_env!(Env, <E: Ext>,
|
||||
// Should be decodable as a `T::Balance`. Traps otherwise.
|
||||
// - value_len: length of the value buffer.
|
||||
[seal0] seal_set_rent_allowance(ctx, value_ptr: u32, value_len: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::SetRentAllowance)?;
|
||||
ctx.charge_gas(RuntimeCosts::SetRentAllowance)?;
|
||||
let value: BalanceOf<<E as Ext>::T> =
|
||||
ctx.read_sandbox_memory_as(value_ptr, value_len)?;
|
||||
ctx.ext.set_rent_allowance(value);
|
||||
@@ -1396,9 +1373,10 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// The data is encoded as T::Balance.
|
||||
[seal0] seal_rent_allowance(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::RentAllowance)?;
|
||||
ctx.charge_gas(RuntimeCosts::RentAllowance)?;
|
||||
let rent_allowance = ctx.ext.rent_allowance().encode();
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.rent_allowance().encode(), false, already_charged
|
||||
out_ptr, out_len_ptr, &rent_allowance, false, already_charged
|
||||
)?)
|
||||
},
|
||||
|
||||
@@ -1420,7 +1398,7 @@ define_env!(Env, <E: Ext>,
|
||||
// `out_ptr`. This call overwrites it with the size of the value. If the available
|
||||
// space at `out_ptr` is less than the size of the value a trap is triggered.
|
||||
[seal0] seal_block_number(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::BlockNumber)?;
|
||||
ctx.charge_gas(RuntimeCosts::BlockNumber)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.block_number().encode(), false, already_charged
|
||||
)?)
|
||||
@@ -1447,7 +1425,7 @@ define_env!(Env, <E: Ext>,
|
||||
// data is placed. The function will write the result
|
||||
// directly into this buffer.
|
||||
[seal0] seal_hash_sha2_256(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::HashSha256(input_len))?;
|
||||
ctx.charge_gas(RuntimeCosts::HashSha256(input_len))?;
|
||||
Ok(ctx.compute_hash_on_intermediate_buffer(sha2_256, input_ptr, input_len, output_ptr)?)
|
||||
},
|
||||
|
||||
@@ -1472,7 +1450,7 @@ define_env!(Env, <E: Ext>,
|
||||
// data is placed. The function will write the result
|
||||
// directly into this buffer.
|
||||
[seal0] seal_hash_keccak_256(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::HashKeccak256(input_len))?;
|
||||
ctx.charge_gas(RuntimeCosts::HashKeccak256(input_len))?;
|
||||
Ok(ctx.compute_hash_on_intermediate_buffer(keccak_256, input_ptr, input_len, output_ptr)?)
|
||||
},
|
||||
|
||||
@@ -1497,7 +1475,7 @@ define_env!(Env, <E: Ext>,
|
||||
// data is placed. The function will write the result
|
||||
// directly into this buffer.
|
||||
[seal0] seal_hash_blake2_256(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::HashBlake256(input_len))?;
|
||||
ctx.charge_gas(RuntimeCosts::HashBlake256(input_len))?;
|
||||
Ok(ctx.compute_hash_on_intermediate_buffer(blake2_256, input_ptr, input_len, output_ptr)?)
|
||||
},
|
||||
|
||||
@@ -1522,7 +1500,7 @@ define_env!(Env, <E: Ext>,
|
||||
// data is placed. The function will write the result
|
||||
// directly into this buffer.
|
||||
[seal0] seal_hash_blake2_128(ctx, input_ptr: u32, input_len: u32, output_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::HashBlake128(input_len))?;
|
||||
ctx.charge_gas(RuntimeCosts::HashBlake128(input_len))?;
|
||||
Ok(ctx.compute_hash_on_intermediate_buffer(blake2_128, input_ptr, input_len, output_ptr)?)
|
||||
},
|
||||
|
||||
@@ -1574,7 +1552,7 @@ define_env!(Env, <E: Ext>,
|
||||
// started execution. Any change to those values that happens due to actions of the
|
||||
// current call or contracts that are called by this contract are not considered.
|
||||
[seal0] seal_rent_params(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeToken::RentParams)?;
|
||||
ctx.charge_gas(RuntimeCosts::RentParams)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.rent_params().encode(), false, already_charged
|
||||
)?)
|
||||
|
||||
Reference in New Issue
Block a user