mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 05:51:02 +00:00
contracts: Add salt argument to contract instantiation (#7482)
* pallet-contracts: Fix seal_restore_to to output proper module errors Those errors where part of the decl_error for some time but where never actually returned. This allows proper debugging of failed restorations. Previously, any error did return the misleading `ContractTrapped`. * Bind UncheckedFrom<T::Hash> + AsRef<[u8]> everywhere This allows us to make assumptions about the AccoutId that are necessary for testing and in order to benchmark the module properly. This also groups free standing functions into inherent functions in order to minimize the places where the new bounds need to be specified. * Rework contract address determination * Do not allow override by runtime author * Instantiate gained a new parameter "salt" This change is done now in expecation of the upcoming code rent which needs to change the instantiation dispatchable and host function anyways. The situation in where we have only something that is like CREATE2 makes it impossible for UIs to help the user to create an arbitrary amount of instantiations from the same code. With this change we have the same functionality as ethereum with a CREATE and CREATE2 instantation semantic. * Remove TrieIdGenerator The new trait bounds allows us to remove this workaround from the configuration trait. * Remove default parameters for config trait It should be solely the responsiblity to determine proper values for these parameter. As a matter of fact most runtime weren't using these values anyways. * Fix tests for new account id type Because of the new bounds on the trait tests can't get away by using u64 as accound id. Replacing the 8 byte value by a 32 byte value creates out quite a bit of code churn. * Fix benchmarks The benchmarks need adaption to the new instantiate semantics. * Fix compile errors caused by adding new trait bounds * Fix compile errors caused by renaming storage and rent functions * Adapt host functions and dispatchables to the new salt * Add tests for instantiate host functions (was not possible before) * Add benchmark results * Adapt to the new WeightInfo The new benchmarks add a new parameter for salt "s" to the instantiate weights that needs to be applied. * Fix deploying_wasm_contract_should_work integration test This test is adapted to use the new instantiate signature. * Break overlong line * Break more long lines Co-authored-by: Parity Benchmarking Bot <admin@parity.io>
This commit is contained in:
committed by
GitHub
parent
26830a20df
commit
c3ca78fae3
@@ -25,7 +25,9 @@ mod sandbox;
|
||||
use crate::{
|
||||
*, Module as Contracts,
|
||||
exec::StorageKey,
|
||||
rent::Rent,
|
||||
schedule::{API_BENCHMARK_BATCH_SIZE, INSTR_BENCHMARK_BATCH_SIZE},
|
||||
storage::Storage,
|
||||
};
|
||||
use self::{
|
||||
code::{
|
||||
@@ -75,7 +77,11 @@ impl Endow {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Contract<T> {
|
||||
impl<T: Trait> Contract<T>
|
||||
where
|
||||
T: Trait,
|
||||
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
|
||||
{
|
||||
/// Create new contract and use a default account id as instantiator.
|
||||
fn new(
|
||||
module: WasmModule<T>,
|
||||
@@ -123,7 +129,8 @@ impl<T: Trait> Contract<T> {
|
||||
Endow::Max => (0u32.into(), Endow::max::<T>()),
|
||||
};
|
||||
T::Currency::make_free_balance_be(&caller, caller_funding::<T>());
|
||||
let addr = T::DetermineContractAddress::contract_address_for(&module.hash, &data, &caller);
|
||||
let salt = vec![0xff];
|
||||
let addr = Contracts::<T>::contract_address(&caller, &module.hash, &salt);
|
||||
|
||||
// The default block number is zero. The benchmarking system bumps the block number
|
||||
// to one for the benchmarking closure when it is set to zero. In order to prevent this
|
||||
@@ -139,6 +146,7 @@ impl<T: Trait> Contract<T> {
|
||||
Weight::max_value(),
|
||||
module.hash,
|
||||
data,
|
||||
salt,
|
||||
)?;
|
||||
|
||||
let result = Contract {
|
||||
@@ -160,7 +168,7 @@ impl<T: Trait> Contract<T> {
|
||||
fn store(&self, items: &Vec<(StorageKey, Vec<u8>)>) -> Result<(), &'static str> {
|
||||
let info = self.alive_info()?;
|
||||
for item in items {
|
||||
crate::storage::write_contract_storage::<T>(
|
||||
Storage::<T>::write(
|
||||
&self.account_id,
|
||||
&info.trie_id,
|
||||
&item.0,
|
||||
@@ -192,7 +200,7 @@ impl<T: Trait> Contract<T> {
|
||||
/// Get the block number when this contract will be evicted. Returns an error when
|
||||
/// the rent collection won't happen because the contract has to much endowment.
|
||||
fn eviction_at(&self) -> Result<T::BlockNumber, &'static str> {
|
||||
let projection = crate::rent::compute_rent_projection::<T>(&self.account_id)
|
||||
let projection = Rent::<T>::compute_projection(&self.account_id)
|
||||
.map_err(|_| "Invalid acc for rent")?;
|
||||
match projection {
|
||||
RentProjection::EvictionAt(at) => Ok(at),
|
||||
@@ -211,7 +219,11 @@ struct Tombstone<T: Trait> {
|
||||
storage: Vec<(StorageKey, Vec<u8>)>,
|
||||
}
|
||||
|
||||
impl<T: Trait> Tombstone<T> {
|
||||
impl<T: Trait> Tombstone<T>
|
||||
where
|
||||
T: Trait,
|
||||
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
|
||||
{
|
||||
/// Create and evict a new contract with the supplied storage item count and size each.
|
||||
fn new(stor_num: u32, stor_size: u32) -> Result<Self, &'static str> {
|
||||
let contract = Contract::<T>::new(WasmModule::dummy(), vec![], Endow::CollectRent)?;
|
||||
@@ -220,7 +232,7 @@ impl<T: Trait> Tombstone<T> {
|
||||
System::<T>::set_block_number(
|
||||
contract.eviction_at()? + T::SignedClaimHandicap::get() + 5u32.into()
|
||||
);
|
||||
crate::rent::collect_rent::<T>(&contract.account_id);
|
||||
Rent::<T>::collect(&contract.account_id);
|
||||
contract.ensure_tombstone()?;
|
||||
|
||||
Ok(Tombstone {
|
||||
@@ -250,6 +262,11 @@ fn caller_funding<T: Trait>() -> BalanceOf<T> {
|
||||
}
|
||||
|
||||
benchmarks! {
|
||||
where_clause { where
|
||||
T::AccountId: UncheckedFrom<T::Hash>,
|
||||
T::AccountId: AsRef<[u8]>,
|
||||
}
|
||||
|
||||
_ {
|
||||
}
|
||||
|
||||
@@ -276,17 +293,20 @@ benchmarks! {
|
||||
// The size of the input data influences the runtime because it is hashed in order to determine
|
||||
// the contract address.
|
||||
// `n`: Size of the data passed to constructor in kilobytes.
|
||||
// `s`: Size of the salt in kilobytes.
|
||||
instantiate {
|
||||
let n in 0 .. code::max_pages::<T>() * 64;
|
||||
let s in 0 .. code::max_pages::<T>() * 64;
|
||||
let data = vec![42u8; (n * 1024) as usize];
|
||||
let salt = vec![42u8; (s * 1024) as usize];
|
||||
let endowment = Config::<T>::subsistence_threshold_uncached();
|
||||
let caller = whitelisted_caller();
|
||||
T::Currency::make_free_balance_be(&caller, caller_funding::<T>());
|
||||
let WasmModule { code, hash, .. } = WasmModule::<T>::dummy_with_mem();
|
||||
let origin = RawOrigin::Signed(caller.clone());
|
||||
let addr = T::DetermineContractAddress::contract_address_for(&hash, &data, &caller);
|
||||
let addr = Contracts::<T>::contract_address(&caller, &hash, &salt);
|
||||
Contracts::<T>::put_code_raw(code)?;
|
||||
}: _(origin, endowment, Weight::max_value(), hash, data)
|
||||
}: _(origin, endowment, Weight::max_value(), hash, data, salt)
|
||||
verify {
|
||||
// endowment was removed from the caller
|
||||
assert_eq!(T::Currency::free_balance(&caller), caller_funding::<T>() - endowment);
|
||||
@@ -1000,7 +1020,7 @@ benchmarks! {
|
||||
let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
|
||||
let trie_id = instance.alive_info()?.trie_id;
|
||||
for key in keys {
|
||||
crate::storage::write_contract_storage::<T>(
|
||||
Storage::<T>::write(
|
||||
&instance.account_id,
|
||||
&trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
@@ -1045,7 +1065,7 @@ benchmarks! {
|
||||
let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
|
||||
let trie_id = instance.alive_info()?.trie_id;
|
||||
for key in keys {
|
||||
crate::storage::write_contract_storage::<T>(
|
||||
Storage::<T>::write(
|
||||
&instance.account_id,
|
||||
&trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
@@ -1089,7 +1109,7 @@ benchmarks! {
|
||||
});
|
||||
let instance = Contract::<T>::new(code, vec![], Endow::Max)?;
|
||||
let trie_id = instance.alive_info()?.trie_id;
|
||||
crate::storage::write_contract_storage::<T>(
|
||||
Storage::<T>::write(
|
||||
&instance.account_id,
|
||||
&trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
@@ -1341,7 +1361,9 @@ benchmarks! {
|
||||
ValueType::I32,
|
||||
ValueType::I32,
|
||||
ValueType::I32,
|
||||
ValueType::I32
|
||||
ValueType::I32,
|
||||
ValueType::I32,
|
||||
ValueType::I32,
|
||||
],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
@@ -1371,6 +1393,8 @@ benchmarks! {
|
||||
Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr
|
||||
Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr
|
||||
Regular(Instruction::I32Const(0)), // output_len_ptr
|
||||
Regular(Instruction::I32Const(0)), // salt_ptr
|
||||
Regular(Instruction::I32Const(0)), // salt_ptr_len
|
||||
Regular(Instruction::Call(0)),
|
||||
Regular(Instruction::Drop),
|
||||
])),
|
||||
@@ -1381,8 +1405,8 @@ benchmarks! {
|
||||
let callee = instance.addr.clone();
|
||||
let addresses = hashes
|
||||
.iter()
|
||||
.map(|hash| T::DetermineContractAddress::contract_address_for(
|
||||
hash, &[], &instance.account_id
|
||||
.map(|hash| Contracts::<T>::contract_address(
|
||||
&instance.account_id, hash, &[],
|
||||
))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -1398,9 +1422,10 @@ benchmarks! {
|
||||
}
|
||||
}
|
||||
|
||||
seal_instantiate_per_input_output_kb {
|
||||
seal_instantiate_per_input_output_salt_kb {
|
||||
let i in 0 .. (code::max_pages::<T>() - 1) * 64;
|
||||
let o in 0 .. (code::max_pages::<T>() - 1) * 64;
|
||||
let s in 0 .. (code::max_pages::<T>() - 1) * 64;
|
||||
let callee_code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory::max::<T>()),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
@@ -1458,7 +1483,9 @@ benchmarks! {
|
||||
ValueType::I32,
|
||||
ValueType::I32,
|
||||
ValueType::I32,
|
||||
ValueType::I32
|
||||
ValueType::I32,
|
||||
ValueType::I32,
|
||||
ValueType::I32,
|
||||
],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
@@ -1496,6 +1523,8 @@ benchmarks! {
|
||||
Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr
|
||||
Regular(Instruction::I32Const(output_offset as i32)), // output_ptr
|
||||
Regular(Instruction::I32Const(output_len_offset as i32)), // output_len_ptr
|
||||
Counter(input_offset as u32, input_len as u32), // salt_ptr
|
||||
Regular(Instruction::I32Const((s * 1024).max(input_len as u32) as i32)), // salt_len
|
||||
Regular(Instruction::Call(0)),
|
||||
Regular(Instruction::I32Eqz),
|
||||
Regular(Instruction::If(BlockType::NoResult)),
|
||||
@@ -2401,6 +2430,8 @@ mod tests {
|
||||
create_test!(seal_transfer);
|
||||
create_test!(seal_call);
|
||||
create_test!(seal_call_per_transfer_input_output_kb);
|
||||
create_test!(seal_instantiate);
|
||||
create_test!(seal_instantiate_per_input_output_salt_kb);
|
||||
create_test!(seal_clear_storage);
|
||||
create_test!(seal_hash_sha2_256);
|
||||
create_test!(seal_hash_sha2_256_per_kb);
|
||||
|
||||
Reference in New Issue
Block a user