mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-16 20:11:03 +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
@@ -103,10 +103,10 @@ pub mod weights;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use crate::{pallet::*, schedule::Schedule};
|
||||
pub use crate::{pallet::*, schedule::Schedule, exec::Frame};
|
||||
use crate::{
|
||||
gas::GasMeter,
|
||||
exec::{ExecutionContext, Executable},
|
||||
exec::{Stack as ExecStack, Executable},
|
||||
rent::Rent,
|
||||
storage::{Storage, DeletedContract, ContractInfo, AliveContractInfo, TombstoneContractInfo},
|
||||
weights::WeightInfo,
|
||||
@@ -210,9 +210,12 @@ pub mod pallet {
|
||||
#[pallet::constant]
|
||||
type SurchargeReward: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The maximum nesting level of a call/instantiate stack.
|
||||
#[pallet::constant]
|
||||
type MaxDepth: Get<u32>;
|
||||
/// The type of the call stack determines the maximum nesting depth of contract calls.
|
||||
///
|
||||
/// The allowed depth is `CallStack::size() + 1`.
|
||||
/// Therefore a size of `0` means that a contract cannot use call or instantiate.
|
||||
/// In other words only the origin called "root contract" is allowed to execute then.
|
||||
type CallStack: smallvec::Array<Item=Frame<Self>>;
|
||||
|
||||
/// The maximum size of a storage value and event payload in bytes.
|
||||
#[pallet::constant]
|
||||
@@ -313,8 +316,9 @@ pub mod pallet {
|
||||
let dest = T::Lookup::lookup(dest)?;
|
||||
let mut gas_meter = GasMeter::new(gas_limit);
|
||||
let schedule = <CurrentSchedule<T>>::get();
|
||||
let mut ctx = ExecutionContext::<T, PrefabWasmModule<T>>::top_level(origin, &schedule);
|
||||
let (result, code_len) = match ctx.call(dest, value, &mut gas_meter, data) {
|
||||
let (result, code_len) = match ExecStack::<T, PrefabWasmModule<T>>::run_call(
|
||||
origin, dest, &mut gas_meter, &schedule, value, data
|
||||
) {
|
||||
Ok((output, len)) => (Ok(output), len),
|
||||
Err((err, len)) => (Err(err), len),
|
||||
};
|
||||
@@ -365,9 +369,9 @@ pub mod pallet {
|
||||
let executable = PrefabWasmModule::from_code(code, &schedule)?;
|
||||
let code_len = executable.code_len();
|
||||
ensure!(code_len <= T::MaxCodeSize::get(), Error::<T>::CodeTooLarge);
|
||||
let mut ctx = ExecutionContext::<T, PrefabWasmModule<T>>::top_level(origin, &schedule);
|
||||
let result = ctx.instantiate(endowment, &mut gas_meter, executable, data, &salt)
|
||||
.map(|(_address, output)| output);
|
||||
let result = ExecStack::<T, PrefabWasmModule<T>>::run_instantiate(
|
||||
origin, executable, &mut gas_meter, &schedule, endowment, data, &salt,
|
||||
).map(|(_address, output)| output);
|
||||
gas_meter.into_dispatch_result(
|
||||
result,
|
||||
T::WeightInfo::instantiate_with_code(code_len / 1024, salt.len() as u32 / 1024)
|
||||
@@ -395,10 +399,10 @@ pub mod pallet {
|
||||
let mut gas_meter = GasMeter::new(gas_limit);
|
||||
let schedule = <CurrentSchedule<T>>::get();
|
||||
let executable = PrefabWasmModule::from_storage(code_hash, &schedule, &mut gas_meter)?;
|
||||
let mut ctx = ExecutionContext::<T, PrefabWasmModule<T>>::top_level(origin, &schedule);
|
||||
let code_len = executable.code_len();
|
||||
let result = ctx.instantiate(endowment, &mut gas_meter, executable, data, &salt)
|
||||
.map(|(_address, output)| output);
|
||||
let result = ExecStack::<T, PrefabWasmModule<T>>::run_instantiate(
|
||||
origin, executable, &mut gas_meter, &schedule, endowment, data, &salt,
|
||||
).map(|(_address, output)| output);
|
||||
gas_meter.into_dispatch_result(
|
||||
result,
|
||||
T::WeightInfo::instantiate(code_len / 1024, salt.len() as u32 / 1024),
|
||||
@@ -606,6 +610,10 @@ pub mod pallet {
|
||||
StorageExhausted,
|
||||
/// A contract with the same AccountId already exists.
|
||||
DuplicateContract,
|
||||
/// A contract self destructed in its constructor.
|
||||
///
|
||||
/// This can be triggered by a call to `seal_terminate` or `seal_restore_to`.
|
||||
TerminatedInConstructor,
|
||||
}
|
||||
|
||||
/// Current cost schedule for contracts.
|
||||
@@ -680,8 +688,9 @@ where
|
||||
) -> ContractExecResult {
|
||||
let mut gas_meter = GasMeter::new(gas_limit);
|
||||
let schedule = <CurrentSchedule<T>>::get();
|
||||
let mut ctx = ExecutionContext::<T, PrefabWasmModule<T>>::top_level(origin, &schedule);
|
||||
let result = ctx.call(dest, value, &mut gas_meter, input_data);
|
||||
let result = ExecStack::<T, PrefabWasmModule<T>>::run_call(
|
||||
origin, dest, &mut gas_meter, &schedule, value, input_data,
|
||||
);
|
||||
let gas_consumed = gas_meter.gas_spent();
|
||||
ContractExecResult {
|
||||
result: result.map(|r| r.0).map_err(|r| r.0.error),
|
||||
@@ -711,7 +720,6 @@ where
|
||||
) -> ContractInstantiateResult<T::AccountId, T::BlockNumber> {
|
||||
let mut gas_meter = GasMeter::new(gas_limit);
|
||||
let schedule = <CurrentSchedule<T>>::get();
|
||||
let mut ctx = ExecutionContext::<T, PrefabWasmModule<T>>::top_level(origin, &schedule);
|
||||
let executable = match code {
|
||||
Code::Upload(Bytes(binary)) => PrefabWasmModule::from_code(binary, &schedule),
|
||||
Code::Existing(hash) => PrefabWasmModule::from_storage(hash, &schedule, &mut gas_meter),
|
||||
@@ -724,20 +732,21 @@ where
|
||||
debug_message: Bytes(Vec::new()),
|
||||
}
|
||||
};
|
||||
let result = ctx.instantiate(endowment, &mut gas_meter, executable, data, &salt)
|
||||
.and_then(|(account_id, result)| {
|
||||
let rent_projection = if compute_projection {
|
||||
Some(Rent::<T, PrefabWasmModule<T>>::compute_projection(&account_id)
|
||||
.map_err(|_| <Error<T>>::NewContractNotFunded)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let result = ExecStack::<T, PrefabWasmModule<T>>::run_instantiate(
|
||||
origin, executable, &mut gas_meter, &schedule, endowment, data, &salt,
|
||||
).and_then(|(account_id, result)| {
|
||||
let rent_projection = if compute_projection {
|
||||
Some(Rent::<T, PrefabWasmModule<T>>::compute_projection(&account_id)
|
||||
.map_err(|_| <Error<T>>::NewContractNotFunded)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(InstantiateReturnValue {
|
||||
result,
|
||||
account_id,
|
||||
rent_projection,
|
||||
})
|
||||
Ok(InstantiateReturnValue {
|
||||
result,
|
||||
account_id,
|
||||
rent_projection,
|
||||
})
|
||||
});
|
||||
ContractInstantiateResult {
|
||||
result: result.map_err(|e| e.error),
|
||||
|
||||
Reference in New Issue
Block a user