mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 17:31:05 +00:00
contracts: Remove state rent (#9669)
* Remove storage rent * Add storage migration * cargo run --quiet --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 * cargo run --quiet --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 * cargo run --quiet --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 * Add migration for deletetion queue * Fix compilation * Increase gas supplied to out_of_gas to be sure that it won't deplete too early * cargo run --quiet --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 Co-authored-by: Parity Bot <admin@parity.io>
This commit is contained in:
committed by
GitHub
parent
13f3e25ebb
commit
522e77e243
@@ -64,22 +64,6 @@ where
|
||||
});
|
||||
}
|
||||
|
||||
/// Decrement the refcount and store.
|
||||
///
|
||||
/// Removes the code instead of storing it when the refcount drops to zero.
|
||||
pub fn store_decremented<T: Config>(mut prefab_module: PrefabWasmModule<T>)
|
||||
where
|
||||
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
|
||||
{
|
||||
prefab_module.refcount = prefab_module.refcount.saturating_sub(1);
|
||||
if prefab_module.refcount > 0 {
|
||||
<CodeStorage<T>>::insert(prefab_module.code_hash, prefab_module);
|
||||
} else {
|
||||
<CodeStorage<T>>::remove(prefab_module.code_hash);
|
||||
finish_removal::<T>(prefab_module.code_hash);
|
||||
}
|
||||
}
|
||||
|
||||
/// Increment the refcount of a code in-storage by one.
|
||||
pub fn increment_refcount<T: Config>(
|
||||
code_hash: CodeHash<T>,
|
||||
|
||||
@@ -61,7 +61,7 @@ pub struct PrefabWasmModule<T: Config> {
|
||||
/// The maximum memory size of a contract's sandbox.
|
||||
#[codec(compact)]
|
||||
maximum: u32,
|
||||
/// The number of alive contracts that use this as their contract code.
|
||||
/// The number of contracts that use this as their contract code.
|
||||
///
|
||||
/// If this number drops to zero this module is removed from storage.
|
||||
#[codec(compact)]
|
||||
@@ -164,10 +164,6 @@ where
|
||||
code_cache::load(code_hash, None)
|
||||
}
|
||||
|
||||
fn drop_from_storage(self) {
|
||||
code_cache::store_decremented(self);
|
||||
}
|
||||
|
||||
fn add_user(code_hash: CodeHash<T>, gas_meter: &mut GasMeter<T>) -> Result<(), DispatchError> {
|
||||
code_cache::increment_refcount::<T>(code_hash, gas_meter)
|
||||
}
|
||||
@@ -240,11 +236,9 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
exec::{
|
||||
AccountIdOf, BlockNumberOf, ErrorOrigin, ExecError, Executable, Ext, RentParams,
|
||||
SeedOf, StorageKey,
|
||||
AccountIdOf, BlockNumberOf, ErrorOrigin, ExecError, Executable, Ext, SeedOf, StorageKey,
|
||||
},
|
||||
gas::GasMeter,
|
||||
rent::RentStatus,
|
||||
tests::{Call, Test, ALICE, BOB},
|
||||
BalanceOf, CodeHash, Error, Pallet as Contracts,
|
||||
};
|
||||
@@ -261,14 +255,6 @@ mod tests {
|
||||
use sp_runtime::DispatchError;
|
||||
use std::{borrow::BorrowMut, cell::RefCell, collections::HashMap};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct RestoreEntry {
|
||||
dest: AccountIdOf<Test>,
|
||||
code_hash: H256,
|
||||
rent_allowance: u64,
|
||||
delta: Vec<StorageKey>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct InstantiateEntry {
|
||||
code_hash: H256,
|
||||
@@ -299,17 +285,14 @@ mod tests {
|
||||
|
||||
pub struct MockExt {
|
||||
storage: HashMap<StorageKey, Vec<u8>>,
|
||||
rent_allowance: u64,
|
||||
instantiates: Vec<InstantiateEntry>,
|
||||
terminations: Vec<TerminationEntry>,
|
||||
calls: Vec<CallEntry>,
|
||||
transfers: Vec<TransferEntry>,
|
||||
restores: Vec<RestoreEntry>,
|
||||
// (topics, data)
|
||||
events: Vec<(Vec<H256>, Vec<u8>)>,
|
||||
runtime_calls: RefCell<Vec<Call>>,
|
||||
schedule: Schedule<Test>,
|
||||
rent_params: RentParams<Test>,
|
||||
gas_meter: GasMeter<Test>,
|
||||
debug_buffer: Vec<u8>,
|
||||
}
|
||||
@@ -323,16 +306,13 @@ mod tests {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
storage: Default::default(),
|
||||
rent_allowance: Default::default(),
|
||||
instantiates: Default::default(),
|
||||
terminations: Default::default(),
|
||||
calls: Default::default(),
|
||||
transfers: Default::default(),
|
||||
restores: Default::default(),
|
||||
events: Default::default(),
|
||||
runtime_calls: Default::default(),
|
||||
schedule: Default::default(),
|
||||
rent_params: Default::default(),
|
||||
gas_meter: GasMeter::new(10_000_000_000),
|
||||
debug_buffer: Default::default(),
|
||||
}
|
||||
@@ -381,16 +361,6 @@ mod tests {
|
||||
self.terminations.push(TerminationEntry { beneficiary: beneficiary.clone() });
|
||||
Ok(())
|
||||
}
|
||||
fn restore_to(
|
||||
&mut self,
|
||||
dest: AccountIdOf<Self::T>,
|
||||
code_hash: H256,
|
||||
rent_allowance: u64,
|
||||
delta: Vec<StorageKey>,
|
||||
) -> Result<(), DispatchError> {
|
||||
self.restores.push(RestoreEntry { dest, code_hash, rent_allowance, delta });
|
||||
Ok(())
|
||||
}
|
||||
fn get_storage(&mut self, key: &StorageKey) -> Option<Vec<u8>> {
|
||||
self.storage.get(key).cloned()
|
||||
}
|
||||
@@ -416,7 +386,7 @@ mod tests {
|
||||
fn minimum_balance(&self) -> u64 {
|
||||
666
|
||||
}
|
||||
fn tombstone_deposit(&self) -> u64 {
|
||||
fn contract_deposit(&self) -> u64 {
|
||||
16
|
||||
}
|
||||
fn random(&self, subject: &[u8]) -> (SeedOf<Self::T>, BlockNumberOf<Self::T>) {
|
||||
@@ -425,12 +395,6 @@ mod tests {
|
||||
fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
|
||||
self.events.push((topics, data))
|
||||
}
|
||||
fn set_rent_allowance(&mut self, rent_allowance: u64) {
|
||||
self.rent_allowance = rent_allowance;
|
||||
}
|
||||
fn rent_allowance(&mut self) -> u64 {
|
||||
self.rent_allowance
|
||||
}
|
||||
fn block_number(&self) -> u64 {
|
||||
121
|
||||
}
|
||||
@@ -443,12 +407,6 @@ mod tests {
|
||||
fn schedule(&self) -> &Schedule<Self::T> {
|
||||
&self.schedule
|
||||
}
|
||||
fn rent_params(&self) -> &RentParams<Self::T> {
|
||||
&self.rent_params
|
||||
}
|
||||
fn rent_status(&mut self, _at_refcount: u32) -> RentStatus<Self::T> {
|
||||
Default::default()
|
||||
}
|
||||
fn gas_meter(&mut self) -> &mut GasMeter<Self::T> {
|
||||
&mut self.gas_meter
|
||||
}
|
||||
@@ -1380,9 +1338,9 @@ mod tests {
|
||||
assert_ok!(execute(CODE_MINIMUM_BALANCE, vec![], MockExt::default()));
|
||||
}
|
||||
|
||||
const CODE_TOMBSTONE_DEPOSIT: &str = r#"
|
||||
const CODE_CONTRACT_DEPOSIT: &str = r#"
|
||||
(module
|
||||
(import "seal0" "seal_tombstone_deposit" (func $seal_tombstone_deposit (param i32 i32)))
|
||||
(import "seal0" "seal_contract_deposit" (func $seal_contract_deposit (param i32 i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
|
||||
;; size of our buffer is 32 bytes
|
||||
@@ -1398,7 +1356,7 @@ mod tests {
|
||||
)
|
||||
|
||||
(func (export "call")
|
||||
(call $seal_tombstone_deposit (i32.const 0) (i32.const 32))
|
||||
(call $seal_contract_deposit (i32.const 0) (i32.const 32))
|
||||
|
||||
;; assert len == 8
|
||||
(call $assert
|
||||
@@ -1421,8 +1379,8 @@ mod tests {
|
||||
"#;
|
||||
|
||||
#[test]
|
||||
fn tombstone_deposit() {
|
||||
assert_ok!(execute(CODE_TOMBSTONE_DEPOSIT, vec![], MockExt::default()));
|
||||
fn contract_deposit() {
|
||||
assert_ok!(execute(CODE_CONTRACT_DEPOSIT, vec![], MockExt::default()));
|
||||
}
|
||||
|
||||
const CODE_RANDOM: &str = r#"
|
||||
@@ -1856,81 +1814,6 @@ mod tests {
|
||||
assert_ok!(result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
fn rent_params_work() {
|
||||
const CODE_RENT_PARAMS: &str = r#"
|
||||
(module
|
||||
(import "__unstable__" "seal_rent_params" (func $seal_rent_params (param i32 i32)))
|
||||
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
|
||||
;; [0, 4) buffer size = 128 bytes
|
||||
(data (i32.const 0) "\80")
|
||||
|
||||
;; [4; inf) buffer where the result is copied
|
||||
|
||||
(func (export "call")
|
||||
;; Load the rent params into memory
|
||||
(call $seal_rent_params
|
||||
(i32.const 4) ;; Pointer to the output buffer
|
||||
(i32.const 0) ;; Pointer to the size of the buffer
|
||||
)
|
||||
|
||||
;; Return the contents of the buffer
|
||||
(call $seal_return
|
||||
(i32.const 0) ;; return flags
|
||||
(i32.const 4) ;; buffer pointer
|
||||
(i32.load (i32.const 0)) ;; buffer size
|
||||
)
|
||||
)
|
||||
|
||||
(func (export "deploy"))
|
||||
)
|
||||
"#;
|
||||
let output = execute(CODE_RENT_PARAMS, vec![], MockExt::default()).unwrap();
|
||||
let rent_params = Bytes(<RentParams<Test>>::default().encode());
|
||||
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: rent_params });
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
fn rent_status_works() {
|
||||
const CODE_RENT_STATUS: &str = r#"
|
||||
(module
|
||||
(import "__unstable__" "seal_rent_status" (func $seal_rent_status (param i32 i32 i32)))
|
||||
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
|
||||
;; [0, 4) buffer size = 128 bytes
|
||||
(data (i32.const 0) "\80")
|
||||
|
||||
;; [4; inf) buffer where the result is copied
|
||||
|
||||
(func (export "call")
|
||||
;; Load the rent params into memory
|
||||
(call $seal_rent_status
|
||||
(i32.const 1) ;; at_refcount
|
||||
(i32.const 4) ;; Pointer to the output buffer
|
||||
(i32.const 0) ;; Pointer to the size of the buffer
|
||||
)
|
||||
|
||||
;; Return the contents of the buffer
|
||||
(call $seal_return
|
||||
(i32.const 0) ;; return flags
|
||||
(i32.const 4) ;; buffer pointer
|
||||
(i32.load (i32.const 0)) ;; buffer size
|
||||
)
|
||||
)
|
||||
|
||||
(func (export "deploy"))
|
||||
)
|
||||
"#;
|
||||
let output = execute(CODE_RENT_STATUS, vec![], MockExt::default()).unwrap();
|
||||
let rent_status = Bytes(<RentStatus<Test>>::default().encode());
|
||||
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: rent_status });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn debug_message_works() {
|
||||
const CODE_DEBUG_MESSAGE: &str = r#"
|
||||
|
||||
@@ -31,6 +31,7 @@ use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags};
|
||||
use pwasm_utils::parity_wasm::elements::ValueType;
|
||||
use sp_core::{crypto::UncheckedFrom, Bytes};
|
||||
use sp_io::hashing::{blake2_128, blake2_256, keccak_256, sha2_256};
|
||||
use sp_runtime::traits::Bounded;
|
||||
use sp_std::prelude::*;
|
||||
|
||||
/// Every error that can be returned to a contract when it calls any of the host functions.
|
||||
@@ -64,8 +65,7 @@ pub enum ReturnCode {
|
||||
NewContractNotFunded = 6,
|
||||
/// No code could be found at the supplied code hash.
|
||||
CodeNotFound = 7,
|
||||
/// The contract that was called is either no contract at all (a plain account)
|
||||
/// or is a tombstone.
|
||||
/// The contract that was called is no contract (a plain account).
|
||||
NotCallable = 8,
|
||||
/// The call to `seal_debug_message` had no effect because debug message
|
||||
/// recording was disabled.
|
||||
@@ -121,8 +121,6 @@ pub enum TrapReason {
|
||||
/// Signals that a trap was generated in response to a successful call to the
|
||||
/// `seal_terminate` host function.
|
||||
Termination,
|
||||
/// Signals that a trap was generated because of a successful restoration.
|
||||
Restoration,
|
||||
}
|
||||
|
||||
impl<T: Into<DispatchError>> From<T> for TrapReason {
|
||||
@@ -149,10 +147,8 @@ pub enum RuntimeCosts {
|
||||
ValueTransferred,
|
||||
/// Weight of calling `seal_minimum_balance`.
|
||||
MinimumBalance,
|
||||
/// Weight of calling `seal_tombstone_deposit`.
|
||||
TombstoneDeposit,
|
||||
/// Weight of calling `seal_rent_allowance`.
|
||||
RentAllowance,
|
||||
/// Weight of calling `seal_contract_deposit`.
|
||||
ContractDeposit,
|
||||
/// Weight of calling `seal_block_number`.
|
||||
BlockNumber,
|
||||
/// Weight of calling `seal_now`.
|
||||
@@ -167,16 +163,12 @@ pub enum RuntimeCosts {
|
||||
Return(u32),
|
||||
/// Weight of calling `seal_terminate`.
|
||||
Terminate,
|
||||
/// Weight of calling `seal_restore_to` per number of supplied delta entries.
|
||||
RestoreTo(u32),
|
||||
/// Weight of calling `seal_random`. It includes the weight for copying the subject.
|
||||
Random,
|
||||
/// Weight of calling `seal_deposit_event` with the given number of topics and event size.
|
||||
DepositEvent { num_topic: u32, len: u32 },
|
||||
/// Weight of calling `seal_debug_message`.
|
||||
DebugMessage,
|
||||
/// Weight of calling `seal_set_rent_allowance`.
|
||||
SetRentAllowance,
|
||||
/// Weight of calling `seal_set_storage` for the given storage item size.
|
||||
SetStorage(u32),
|
||||
/// Weight of calling `seal_clear_storage`.
|
||||
@@ -232,8 +224,7 @@ impl RuntimeCosts {
|
||||
Balance => s.balance,
|
||||
ValueTransferred => s.value_transferred,
|
||||
MinimumBalance => s.minimum_balance,
|
||||
TombstoneDeposit => s.tombstone_deposit,
|
||||
RentAllowance => s.rent_allowance,
|
||||
ContractDeposit => s.contract_deposit,
|
||||
BlockNumber => s.block_number,
|
||||
Now => s.now,
|
||||
WeightToFee => s.weight_to_fee,
|
||||
@@ -241,15 +232,12 @@ impl RuntimeCosts {
|
||||
InputCopyOut(len) => s.input_per_byte.saturating_mul(len.into()),
|
||||
Return(len) => s.r#return.saturating_add(s.return_per_byte.saturating_mul(len.into())),
|
||||
Terminate => s.terminate,
|
||||
RestoreTo(delta) =>
|
||||
s.restore_to.saturating_add(s.restore_to_per_delta.saturating_mul(delta.into())),
|
||||
Random => s.random,
|
||||
DepositEvent { num_topic, len } => s
|
||||
.deposit_event
|
||||
.saturating_add(s.deposit_event_per_topic.saturating_mul(num_topic.into()))
|
||||
.saturating_add(s.deposit_event_per_byte.saturating_mul(len.into())),
|
||||
DebugMessage => s.debug_message,
|
||||
SetRentAllowance => s.set_rent_allowance,
|
||||
SetStorage(len) =>
|
||||
s.set_storage.saturating_add(s.set_storage_per_byte.saturating_mul(len.into())),
|
||||
ClearStorage => s.clear_storage,
|
||||
@@ -395,8 +383,6 @@ where
|
||||
},
|
||||
TrapReason::Termination =>
|
||||
Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(Vec::new()) }),
|
||||
TrapReason::Restoration =>
|
||||
Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(Vec::new()) }),
|
||||
TrapReason::SupervisorError(error) => Err(error)?,
|
||||
}
|
||||
}
|
||||
@@ -617,15 +603,13 @@ where
|
||||
let not_funded = Error::<E::T>::NewContractNotFunded.into();
|
||||
let no_code = Error::<E::T>::CodeNotFound.into();
|
||||
let not_found = Error::<E::T>::ContractNotFound.into();
|
||||
let is_tombstone = Error::<E::T>::ContractIsTombstone.into();
|
||||
let rent_not_paid = Error::<E::T>::RentNotPaid.into();
|
||||
|
||||
match from {
|
||||
x if x == below_sub => Ok(BelowSubsistenceThreshold),
|
||||
x if x == transfer_failed => Ok(TransferFailed),
|
||||
x if x == not_funded => Ok(NewContractNotFunded),
|
||||
x if x == no_code => Ok(CodeNotFound),
|
||||
x if (x == not_found || x == is_tombstone || x == rent_not_paid) => Ok(NotCallable),
|
||||
x if x == not_found => Ok(NotCallable),
|
||||
err => Err(err),
|
||||
}
|
||||
}
|
||||
@@ -737,49 +721,6 @@ where
|
||||
self.ext.terminate(&beneficiary)?;
|
||||
Err(TrapReason::Termination)
|
||||
}
|
||||
|
||||
fn restore_to(
|
||||
&mut self,
|
||||
dest_ptr: u32,
|
||||
code_hash_ptr: u32,
|
||||
rent_allowance_ptr: u32,
|
||||
delta_ptr: u32,
|
||||
delta_count: u32,
|
||||
) -> Result<(), TrapReason> {
|
||||
self.charge_gas(RuntimeCosts::RestoreTo(delta_count))?;
|
||||
let dest: <<E as Ext>::T as frame_system::Config>::AccountId =
|
||||
self.read_sandbox_memory_as(dest_ptr)?;
|
||||
let code_hash: CodeHash<<E as Ext>::T> = self.read_sandbox_memory_as(code_hash_ptr)?;
|
||||
let rent_allowance: BalanceOf<<E as Ext>::T> =
|
||||
self.read_sandbox_memory_as(rent_allowance_ptr)?;
|
||||
let delta = {
|
||||
const KEY_SIZE: usize = 32;
|
||||
|
||||
// We can eagerly allocate because we charged for the complete delta count already
|
||||
// We still need to make sure that the allocation isn't larger than the memory
|
||||
// allocator can handle.
|
||||
let max_memory = self.ext.schedule().limits.max_memory_size();
|
||||
ensure!(
|
||||
delta_count.saturating_mul(KEY_SIZE as u32) <= max_memory,
|
||||
Error::<E::T>::OutOfBounds,
|
||||
);
|
||||
let mut delta = vec![[0; KEY_SIZE]; delta_count as usize];
|
||||
let mut key_ptr = delta_ptr;
|
||||
|
||||
for i in 0..delta_count {
|
||||
// Read the delta into the provided buffer
|
||||
// This cannot panic because of the loop condition
|
||||
self.read_sandbox_memory_into_buf(key_ptr, &mut delta[i as usize])?;
|
||||
|
||||
// Offset key_ptr to the next element.
|
||||
key_ptr = key_ptr.checked_add(KEY_SIZE as u32).ok_or(Error::<E::T>::OutOfBounds)?;
|
||||
}
|
||||
|
||||
delta
|
||||
};
|
||||
self.ext.restore_to(dest, code_hash, rent_allowance, delta)?;
|
||||
Err(TrapReason::Restoration)
|
||||
}
|
||||
}
|
||||
|
||||
// ***********************************************************
|
||||
@@ -1369,7 +1310,20 @@ define_env!(Env, <E: Ext>,
|
||||
)?)
|
||||
},
|
||||
|
||||
// Stores the tombstone deposit into the supplied buffer.
|
||||
// Stores the contract deposit into the supplied buffer.
|
||||
//
|
||||
// # Deprecation
|
||||
//
|
||||
// This is equivalent to calling `seal_contract_deposit` and only exists for backwards
|
||||
// compatibility. See that function for documentation.
|
||||
[seal0] seal_tombstone_deposit(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeCosts::ContractDeposit)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.contract_deposit().encode(), false, already_charged
|
||||
)?)
|
||||
},
|
||||
|
||||
// Stores the contract deposit into the supplied buffer.
|
||||
//
|
||||
// The value is stored to linear memory at the address pointed to by `out_ptr`.
|
||||
// `out_len_ptr` must point to a u32 value that describes the available space at
|
||||
@@ -1380,95 +1334,53 @@ define_env!(Env, <E: Ext>,
|
||||
//
|
||||
// # Note
|
||||
//
|
||||
// The tombstone deposit is on top of the existential deposit. So in order for
|
||||
// a contract to leave a tombstone the balance of the contract must not go
|
||||
// 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(RuntimeCosts::TombstoneDeposit)?;
|
||||
// The contract deposit is on top of the existential deposit. The sum
|
||||
// is commonly referred as subsistence threshold in code. No contract initiated
|
||||
// balance transfer can go below this threshold.
|
||||
[seal0] seal_contract_deposit(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeCosts::ContractDeposit)?;
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.tombstone_deposit().encode(), false, already_charged
|
||||
out_ptr, out_len_ptr, &ctx.ext.contract_deposit().encode(), false, already_charged
|
||||
)?)
|
||||
},
|
||||
|
||||
// Try to restore the given destination contract sacrificing the caller.
|
||||
//
|
||||
// # Deprecation
|
||||
//
|
||||
// This is equivalent to calling the newer version of this function. The newer version
|
||||
// drops the now unnecessary length fields.
|
||||
// Was used to restore the given destination contract sacrificing the caller.
|
||||
//
|
||||
// # Note
|
||||
//
|
||||
// The values `_dest_len`, `_code_hash_len` and `_rent_allowance_len` are ignored because
|
||||
// the encoded sizes of those types are fixed through `[`MaxEncodedLen`]. The fields
|
||||
// exist for backwards compatibility. Consider switching to the newest version of this function.
|
||||
// The state rent functionality was removed. This is stub only exists for
|
||||
// backwards compatiblity
|
||||
[seal0] seal_restore_to(
|
||||
ctx,
|
||||
dest_ptr: u32,
|
||||
_dest_ptr: u32,
|
||||
_dest_len: u32,
|
||||
code_hash_ptr: u32,
|
||||
_code_hash_ptr: u32,
|
||||
_code_hash_len: u32,
|
||||
rent_allowance_ptr: u32,
|
||||
_rent_allowance_ptr: u32,
|
||||
_rent_allowance_len: u32,
|
||||
delta_ptr: u32,
|
||||
delta_count: u32
|
||||
_delta_ptr: u32,
|
||||
_delta_count: u32
|
||||
) => {
|
||||
ctx.restore_to(
|
||||
dest_ptr,
|
||||
code_hash_ptr,
|
||||
rent_allowance_ptr,
|
||||
delta_ptr,
|
||||
delta_count,
|
||||
)
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage)?;
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// Try to restore the given destination contract sacrificing the caller.
|
||||
// Was used to restore the given destination contract sacrificing the caller.
|
||||
//
|
||||
// This function will compute a tombstone hash from the caller's storage and the given code hash
|
||||
// and if the hash matches the hash found in the tombstone at the specified address - kill
|
||||
// the caller contract and restore the destination contract and set the specified `rent_allowance`.
|
||||
// All caller's funds are transferred to the destination.
|
||||
// # Note
|
||||
//
|
||||
// The tombstone hash is derived as `hash(code_hash, storage_root_hash)`. In order to match
|
||||
// this hash to its own hash the restorer must make its storage equal to the one of the
|
||||
// evicted destination contract. In order to allow for additional storage items in the
|
||||
// restoring contract a delta can be specified to this function. All keys specified as
|
||||
// delta are disregarded when calculating the storage root hash.
|
||||
//
|
||||
// On success, the destination contract is restored. This function is diverging and
|
||||
// stops execution even on success.
|
||||
//
|
||||
// - `dest_ptr` - the pointer to a buffer that encodes `T::AccountId`
|
||||
// with the address of the to be restored contract.
|
||||
// - `code_hash_ptr` - the pointer to a buffer that encodes
|
||||
// a code hash of the to be restored contract.
|
||||
// - `rent_allowance_ptr` - the pointer to a buffer that
|
||||
// encodes the rent allowance that must be set in the case of successful restoration.
|
||||
// - `delta_ptr` is the pointer to the start of a buffer that has `delta_count` storage keys
|
||||
// laid out sequentially.
|
||||
//
|
||||
// # Traps
|
||||
//
|
||||
// - There is no tombstone at the destination address.
|
||||
// - Tombstone hashes do not match.
|
||||
// - The calling contract is already present on the call stack.
|
||||
// - The supplied code_hash does not exist on-chain.
|
||||
// The state rent functionality was removed. This is stub only exists for
|
||||
// backwards compatiblity
|
||||
[seal1] seal_restore_to(
|
||||
ctx,
|
||||
dest_ptr: u32,
|
||||
code_hash_ptr: u32,
|
||||
rent_allowance_ptr: u32,
|
||||
delta_ptr: u32,
|
||||
delta_count: u32
|
||||
_dest_ptr: u32,
|
||||
_code_hash_ptr: u32,
|
||||
_rent_allowance_ptr: u32,
|
||||
_delta_ptr: u32,
|
||||
_delta_count: u32
|
||||
) => {
|
||||
ctx.restore_to(
|
||||
dest_ptr,
|
||||
code_hash_ptr,
|
||||
rent_allowance_ptr,
|
||||
delta_ptr,
|
||||
delta_count,
|
||||
)
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage)?;
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// Deposit a contract event with the data buffer and optional list of topics. There is a limit
|
||||
@@ -1536,47 +1448,37 @@ define_env!(Env, <E: Ext>,
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// Set rent allowance of the contract.
|
||||
//
|
||||
// # Deprecation
|
||||
//
|
||||
// This is equivalent to calling the newer version of this function. The newer version
|
||||
// drops the now unnecessary length fields.
|
||||
// Was used to set rent allowance of the contract.
|
||||
//
|
||||
// # Note
|
||||
//
|
||||
// The value `_VALUE_len` is ignored because the encoded sizes
|
||||
// this type is fixed through `[`MaxEncodedLen`]. The field exist for backwards
|
||||
// compatibility. Consider switching to the newest version of this function.
|
||||
[seal0] seal_set_rent_allowance(ctx, value_ptr: u32, _value_len: u32) => {
|
||||
ctx.charge_gas(RuntimeCosts::SetRentAllowance)?;
|
||||
let value: BalanceOf<<E as Ext>::T> = ctx.read_sandbox_memory_as(value_ptr)?;
|
||||
ctx.ext.set_rent_allowance(value);
|
||||
// The state rent functionality was removed. This is stub only exists for
|
||||
// backwards compatiblity.
|
||||
[seal0] seal_set_rent_allowance(ctx, _value_ptr: u32, _value_len: u32) => {
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage)?;
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// Set rent allowance of the contract.
|
||||
// Was used to set rent allowance of the contract.
|
||||
//
|
||||
// - value_ptr: a pointer to the buffer with value, how much to allow for rent
|
||||
// Should be decodable as a `T::Balance`. Traps otherwise.
|
||||
[seal1] seal_set_rent_allowance(ctx, value_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeCosts::SetRentAllowance)?;
|
||||
let value: BalanceOf<<E as Ext>::T> = ctx.read_sandbox_memory_as(value_ptr)?;
|
||||
ctx.ext.set_rent_allowance(value);
|
||||
// # Note
|
||||
//
|
||||
// The state rent functionality was removed. This is stub only exists for
|
||||
// backwards compatiblity.
|
||||
[seal1] seal_set_rent_allowance(ctx, _value_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeCosts::DebugMessage)?;
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// Stores the rent allowance into the supplied buffer.
|
||||
// Was used to store the rent allowance into the supplied buffer.
|
||||
//
|
||||
// The value is stored to linear memory at the address pointed to by `out_ptr`.
|
||||
// `out_len_ptr` must point to a u32 value that describes the available space at
|
||||
// `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.
|
||||
// # Note
|
||||
//
|
||||
// The data is encoded as T::Balance.
|
||||
// The state rent functionality was removed. This is stub only exists for
|
||||
// backwards compatiblity.
|
||||
[seal0] seal_rent_allowance(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
ctx.charge_gas(RuntimeCosts::RentAllowance)?;
|
||||
let rent_allowance = ctx.ext.rent_allowance().encode();
|
||||
ctx.charge_gas(RuntimeCosts::Balance)?;
|
||||
let rent_allowance = <BalanceOf<E::T>>::max_value().encode();
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &rent_allowance, false, already_charged
|
||||
)?)
|
||||
@@ -1757,55 +1659,6 @@ define_env!(Env, <E: Ext>,
|
||||
Ok(ReturnCode::LoggingDisabled)
|
||||
},
|
||||
|
||||
// Stores the rent params into the supplied buffer.
|
||||
//
|
||||
// The value is stored to linear memory at the address pointed to by `out_ptr`.
|
||||
// `out_len_ptr` must point to a u32 value that describes the available space at
|
||||
// `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.
|
||||
//
|
||||
// The data is encoded as [`crate::exec::RentParams`].
|
||||
//
|
||||
// # Note
|
||||
//
|
||||
// The returned information was collected and cached when the current contract call
|
||||
// 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.
|
||||
//
|
||||
// # Unstable
|
||||
//
|
||||
// This function is unstable and subject to change (or removal) in the future. Do not
|
||||
// deploy a contract using it to a production chain.
|
||||
[__unstable__] seal_rent_params(ctx, out_ptr: u32, out_len_ptr: u32) => {
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &ctx.ext.rent_params().encode(), false, already_charged
|
||||
)?)
|
||||
},
|
||||
|
||||
// Stores the rent status into the supplied buffer.
|
||||
//
|
||||
// The value is stored to linear memory at the address pointed to by `out_ptr`.
|
||||
// `out_len_ptr` must point to a u32 value that describes the available space at
|
||||
// `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.
|
||||
//
|
||||
// The data is encoded as [`crate::rent::RentStatus`].
|
||||
//
|
||||
// # Parameters
|
||||
//
|
||||
// - `at_refcount`: The refcount assumed for the returned `custom_refcount_*` fields
|
||||
//
|
||||
// # Unstable
|
||||
//
|
||||
// This function is unstable and subject to change (or removal) in the future. Do not
|
||||
// deploy a contract using it to a production chain.
|
||||
[__unstable__] seal_rent_status(ctx, at_refcount: u32, out_ptr: u32, out_len_ptr: u32) => {
|
||||
let rent_status = ctx.ext.rent_status(at_refcount).encode();
|
||||
Ok(ctx.write_sandbox_output(
|
||||
out_ptr, out_len_ptr, &rent_status, false, already_charged
|
||||
)?)
|
||||
},
|
||||
|
||||
// Call some dispatchable of the runtime.
|
||||
//
|
||||
// This function decodes the passed in data as the overarching `Call` type of the
|
||||
|
||||
Reference in New Issue
Block a user