mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 09:57:56 +00:00
[contracts] Implement transparent hashing for contract storage (#11501)
* save * builds and old tests pass save: temporary value dropped while borrowed save: finally builds test updated but still fails * type names enhanced * VarSizedKey bounded to new Config param * improved wasm runtime updated funcs * unstable-interface tests fixed * benchmarks fixed * Apply suggestions from code review Co-authored-by: Alexander Theißen <alex.theissen@me.com> * fixes on feedback * fixes on feedback applied + make it build * benchmarks build but fail (old) * "Original code too large" * seal_clear_storage bench fixed (code size workaround hack removal tbd) * bench_seal_clear_storage pass * bench_seal_take_storage ... ok * added new seal_set_storage + updated benchmarks * added new seal_get_storage + updated benchmarks * added new seal_contains_storage + updated benchmarks * added tests for _transparent exec functions * wasm test for clear_storage * wasm test for take_storage * wasm test for new set_storage * wasm test for new get_storage * wasm test for new contains_storage * CI fix * ci fix * ci fix * ci fix * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark pallet --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 * fixes according to the review feedback * tests & benchmarks fixed * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark pallet --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 * refactoring * fix to runtime api * ci fix * ctx.get_storage() factored out * ctx.contains_storage() factored out * number of batches reduced for transparent hashing storage benchmarks * contracts RPC & pallet::get_storage to use transparent hashing * node and rpc updated to use get_storage with VarSizedKey * refactored (more concize) * refactored contains_storage (DRYed) * refactored contains_storage (DRYed) * fix rpc * fmt fix * more fixes in rpc * rollback `Pallet:get_storage` to Vec<u8> and rpc and node parts related to it * added `KeyDecodingFailed` error * Revert weird "fmt fix" This reverts commit c582cfff4b5cb2c9929fd5e3b45519bb24aeb657. * node-executor basic test update * fix node-executor basic test * benchmarks fix * more benchmarks fix * FixedSizedKey is hidden from pub, VarSizedKey is exported as StorageKey * ci fix * set_storage benchmark fix * ci fix * ci fix * comments improved * new error code to rpc: KEY_DECODING_FAILED * Put `rusty-cachier` before PR merge into `master` for `cargo-check-benches` job * cargo run --quiet --profile=production --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark pallet --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 * minor optimization Co-authored-by: Alexander Theißen <alex.theissen@me.com> Co-authored-by: Parity Bot <admin@parity.io> Co-authored-by: Vladimir Istyufeev <vladimir@parity.io> Co-authored-by: command-bot <>
This commit is contained in:
committed by
GitHub
parent
7d2ecc8995
commit
68ea2ab039
@@ -30,7 +30,7 @@ use self::{
|
||||
sandbox::Sandbox,
|
||||
};
|
||||
use crate::{
|
||||
exec::{AccountIdOf, StorageKey},
|
||||
exec::{AccountIdOf, FixSizedKey, VarSizedKey},
|
||||
schedule::{API_BENCHMARK_BATCH_SIZE, INSTR_BENCHMARK_BATCH_SIZE},
|
||||
storage::Storage,
|
||||
wasm::CallFlags,
|
||||
@@ -132,11 +132,17 @@ where
|
||||
}
|
||||
|
||||
/// Store the supplied storage items into this contracts storage.
|
||||
fn store(&self, items: &Vec<(StorageKey, Vec<u8>)>) -> Result<(), &'static str> {
|
||||
fn store(&self, items: &Vec<(FixSizedKey, Vec<u8>)>) -> Result<(), &'static str> {
|
||||
let info = self.info()?;
|
||||
for item in items {
|
||||
Storage::<T>::write(&info.trie_id, &item.0, Some(item.1.clone()), None, false)
|
||||
.map_err(|_| "Failed to write storage to restoration dest")?;
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
&item.0 as &FixSizedKey,
|
||||
Some(item.1.clone()),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.map_err(|_| "Failed to write storage to restoration dest")?;
|
||||
}
|
||||
<ContractInfoOf<T>>::insert(&self.account_id, info);
|
||||
Ok(())
|
||||
@@ -896,33 +902,37 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// Only the overhead of calling the function itself with minimal arguments.
|
||||
// The contract is a bit more complex because I needs to use different keys in order
|
||||
// The contract is a bit more complex because it needs to use different keys in order
|
||||
// to generate unique storage accesses. However, it is still dominated by the storage
|
||||
// accesses.
|
||||
// accesses. We store all the keys that we are about to write at beforehand
|
||||
// because re-writing at an existing key is always more expensive than writing
|
||||
// it at a virgin key.
|
||||
#[skip_meta]
|
||||
seal_set_storage {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let r in 0 .. API_BENCHMARK_BATCHES/2;
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0);
|
||||
let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
.map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec();
|
||||
h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h })
|
||||
.collect::<Vec<_>>();
|
||||
let keys_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory::max::<T>()),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "seal1",
|
||||
module: "__unstable__",
|
||||
name: "seal_set_storage",
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
DataSegment {
|
||||
offset: 0,
|
||||
value: key_bytes,
|
||||
value: keys_bytes,
|
||||
},
|
||||
],
|
||||
call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
|
||||
Counter(0, key_len as u32), // key_ptr
|
||||
Counter(0, max_key_len as u32), // key_ptr
|
||||
Regular(Instruction::I32Const(max_key_len as i32)), // key_len
|
||||
Regular(Instruction::I32Const(0)), // value_ptr
|
||||
Regular(Instruction::I32Const(0)), // value_len
|
||||
Regular(Instruction::Call(0)),
|
||||
@@ -935,7 +945,7 @@ benchmarks! {
|
||||
for key in keys {
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
&VarSizedKey::<T>::try_from(key).map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![]),
|
||||
None,
|
||||
false,
|
||||
@@ -947,18 +957,19 @@ benchmarks! {
|
||||
|
||||
#[skip_meta]
|
||||
seal_set_storage_per_new_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 1024;
|
||||
let keys = (0 .. API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0);
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
let keys = (0 .. n * API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec();
|
||||
h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h })
|
||||
.collect::<Vec<_>>();
|
||||
let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory::max::<T>()),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "seal1",
|
||||
module: "__unstable__",
|
||||
name: "seal_set_storage",
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
@@ -968,9 +979,10 @@ benchmarks! {
|
||||
},
|
||||
],
|
||||
call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![
|
||||
Counter(0, key_len as u32), // key_ptr
|
||||
Counter(0, max_key_len as u32), // key_ptr
|
||||
Regular(Instruction::I32Const(max_key_len as i32)), // key_len
|
||||
Regular(Instruction::I32Const(0)), // value_ptr
|
||||
Regular(Instruction::I32Const((n * 1024) as i32)), // value_len
|
||||
Regular(Instruction::I32Const((n * 2048) as i32)), // value_len increments by 2kb up to max payload_len
|
||||
Regular(Instruction::Call(0)),
|
||||
Regular(Instruction::Drop),
|
||||
])),
|
||||
@@ -981,7 +993,7 @@ benchmarks! {
|
||||
for key in keys {
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
&VarSizedKey::<T>::try_from(key).map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![]),
|
||||
None,
|
||||
false,
|
||||
@@ -993,18 +1005,19 @@ benchmarks! {
|
||||
|
||||
#[skip_meta]
|
||||
seal_set_storage_per_old_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 1024;
|
||||
let keys = (0 .. API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0);
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
let keys = (0 .. n * API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec();
|
||||
h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h })
|
||||
.collect::<Vec<_>>();
|
||||
let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory::max::<T>()),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "seal1",
|
||||
module: "__unstable__",
|
||||
name: "seal_set_storage",
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
@@ -1014,9 +1027,10 @@ benchmarks! {
|
||||
},
|
||||
],
|
||||
call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![
|
||||
Counter(0, key_len as u32), // key_ptr
|
||||
Counter(0, max_key_len as u32), // key_ptr
|
||||
Regular(Instruction::I32Const(max_key_len as i32)), // key_len
|
||||
Regular(Instruction::I32Const(0)), // value_ptr
|
||||
Regular(Instruction::I32Const(0)), // value_len
|
||||
Regular(Instruction::I32Const(0)), // value_len is 0 as testing vs pre-existing value len
|
||||
Regular(Instruction::Call(0)),
|
||||
Regular(Instruction::Drop),
|
||||
])),
|
||||
@@ -1027,8 +1041,8 @@ benchmarks! {
|
||||
for key in keys {
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![42u8; (n * 1024) as usize]),
|
||||
&VarSizedKey::<T>::try_from(key).map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![42u8; (n * 2048) as usize]), // value_len increments by 2kb up to max payload_len
|
||||
None,
|
||||
false,
|
||||
)
|
||||
@@ -1037,23 +1051,25 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// Similar to seal_set_storage. However, we store all the keys that we are about to
|
||||
// Similar to seal_set_storage. We store all the keys that we are about to
|
||||
// delete beforehand in order to prevent any optimizations that could occur when
|
||||
// deleting a non existing key.
|
||||
// deleting a non existing key. We generate keys of a maximum length, and have to
|
||||
// reduce batch size in order to make resulting contract code size less than MaxCodeLen.
|
||||
#[skip_meta]
|
||||
seal_clear_storage {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let r in 0 .. API_BENCHMARK_BATCHES/2;
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
.map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec();
|
||||
h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h })
|
||||
.collect::<Vec<_>>();
|
||||
let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0);
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory::max::<T>()),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "__unstable__",
|
||||
name: "seal_clear_storage",
|
||||
params: vec![ValueType::I32],
|
||||
params: vec![ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
@@ -1063,7 +1079,8 @@ benchmarks! {
|
||||
},
|
||||
],
|
||||
call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
|
||||
Counter(0, key_len as u32),
|
||||
Counter(0, max_key_len as u32), // key_ptr
|
||||
Regular(Instruction::I32Const(max_key_len as i32)), // key_len
|
||||
Regular(Instruction::Call(0)),
|
||||
Regular(Instruction::Drop),
|
||||
])),
|
||||
@@ -1074,7 +1091,7 @@ benchmarks! {
|
||||
for key in keys {
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
&VarSizedKey::<T>::try_from(key).map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![]),
|
||||
None,
|
||||
false,
|
||||
@@ -1087,18 +1104,19 @@ benchmarks! {
|
||||
|
||||
#[skip_meta]
|
||||
seal_clear_storage_per_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 1024;
|
||||
let keys = (0 .. API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0);
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
let keys = (0 .. n * API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec();
|
||||
h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h })
|
||||
.collect::<Vec<_>>();
|
||||
let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory::max::<T>()),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "__unstable__",
|
||||
name: "seal_clear_storage",
|
||||
params: vec![ValueType::I32],
|
||||
params: vec![ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
@@ -1108,7 +1126,8 @@ benchmarks! {
|
||||
},
|
||||
],
|
||||
call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![
|
||||
Counter(0, key_len as u32), // key_ptr
|
||||
Counter(0, max_key_len as u32), // key_ptr
|
||||
Regular(Instruction::I32Const(max_key_len as i32)), // key_len
|
||||
Regular(Instruction::Call(0)),
|
||||
Regular(Instruction::Drop),
|
||||
])),
|
||||
@@ -1119,8 +1138,8 @@ benchmarks! {
|
||||
for key in keys {
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![42u8; (n * 1024) as usize]),
|
||||
&VarSizedKey::<T>::try_from(key).map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![42u8; (n * 2048) as usize]), // value_len increments by 2kb up to max payload_len
|
||||
None,
|
||||
false,
|
||||
)
|
||||
@@ -1132,19 +1151,20 @@ benchmarks! {
|
||||
// We make sure that all storage accesses are to unique keys.
|
||||
#[skip_meta]
|
||||
seal_get_storage {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let r in 0 .. API_BENCHMARK_BATCHES/2;
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0);
|
||||
.map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec();
|
||||
h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h })
|
||||
.collect::<Vec<_>>();
|
||||
let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
let key_bytes_len = key_bytes.len();
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory::max::<T>()),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "seal0",
|
||||
module: "__unstable__",
|
||||
name: "seal_get_storage",
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
@@ -1158,7 +1178,8 @@ benchmarks! {
|
||||
},
|
||||
],
|
||||
call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
|
||||
Counter(0, key_len as u32), // key_ptr
|
||||
Counter(0, max_key_len as u32), // key_ptr
|
||||
Regular(Instruction::I32Const(max_key_len as i32)), // key_len
|
||||
Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr
|
||||
Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr
|
||||
Regular(Instruction::Call(0)),
|
||||
@@ -1171,7 +1192,7 @@ benchmarks! {
|
||||
for key in keys {
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
&VarSizedKey::<T>::try_from(key).map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![]),
|
||||
None,
|
||||
false,
|
||||
@@ -1184,19 +1205,20 @@ benchmarks! {
|
||||
|
||||
#[skip_meta]
|
||||
seal_get_storage_per_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 1024;
|
||||
let keys = (0 .. API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0);
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
let keys = (0 .. n * API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec();
|
||||
h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h })
|
||||
.collect::<Vec<_>>();
|
||||
let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
let key_bytes_len = key_bytes.len();
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory::max::<T>()),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "seal0",
|
||||
module: "__unstable__",
|
||||
name: "seal_get_storage",
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
@@ -1210,7 +1232,8 @@ benchmarks! {
|
||||
},
|
||||
],
|
||||
call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![
|
||||
Counter(0, key_len as u32), // key_ptr
|
||||
Counter(0, max_key_len as u32), // key_ptr
|
||||
Regular(Instruction::I32Const(max_key_len as i32)), // key_len
|
||||
Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr
|
||||
Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr
|
||||
Regular(Instruction::Call(0)),
|
||||
@@ -1223,8 +1246,8 @@ benchmarks! {
|
||||
for key in keys {
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![42u8; (n * 1024) as usize]),
|
||||
&VarSizedKey::<T>::try_from(key).map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![42u8; (n * 2048) as usize]), // value_len increments by 2kb up to max payload_len
|
||||
None,
|
||||
false,
|
||||
)
|
||||
@@ -1237,19 +1260,20 @@ benchmarks! {
|
||||
// We make sure that all storage accesses are to unique keys.
|
||||
#[skip_meta]
|
||||
seal_contains_storage {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let r in 0 .. API_BENCHMARK_BATCHES/2;
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0);
|
||||
.map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec();
|
||||
h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h })
|
||||
.collect::<Vec<_>>();
|
||||
let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
let key_bytes_len = key_bytes.len();
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory::max::<T>()),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "seal0",
|
||||
module: "__unstable__",
|
||||
name: "seal_contains_storage",
|
||||
params: vec![ValueType::I32],
|
||||
params: vec![ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
@@ -1259,7 +1283,8 @@ benchmarks! {
|
||||
},
|
||||
],
|
||||
call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
|
||||
Counter(0, key_len as u32), // key_ptr
|
||||
Counter(0, max_key_len as u32), // key_ptr
|
||||
Regular(Instruction::I32Const(max_key_len as i32)), // key_len
|
||||
Regular(Instruction::Call(0)),
|
||||
Regular(Instruction::Drop),
|
||||
])),
|
||||
@@ -1270,7 +1295,7 @@ benchmarks! {
|
||||
for key in keys {
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
&VarSizedKey::<T>::try_from(key).map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![]),
|
||||
None,
|
||||
false,
|
||||
@@ -1283,18 +1308,19 @@ benchmarks! {
|
||||
|
||||
#[skip_meta]
|
||||
seal_contains_storage_per_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 1024;
|
||||
let keys = (0 .. API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0);
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
let keys = (0 .. n * API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec();
|
||||
h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h })
|
||||
.collect::<Vec<_>>();
|
||||
let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
memory: Some(ImportedMemory::max::<T>()),
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "seal0",
|
||||
module: "__unstable__",
|
||||
name: "seal_contains_storage",
|
||||
params: vec![ValueType::I32],
|
||||
params: vec![ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
@@ -1304,7 +1330,8 @@ benchmarks! {
|
||||
},
|
||||
],
|
||||
call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![
|
||||
Counter(0, key_len as u32), // key_ptr
|
||||
Counter(0, max_key_len as u32), // key_ptr
|
||||
Regular(Instruction::I32Const(max_key_len as i32)), // key_len
|
||||
Regular(Instruction::Call(0)),
|
||||
Regular(Instruction::Drop),
|
||||
])),
|
||||
@@ -1315,8 +1342,8 @@ benchmarks! {
|
||||
for key in keys {
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![42u8; (n * 1024) as usize]),
|
||||
&VarSizedKey::<T>::try_from(key).map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![42u8; (n * 2048) as usize]), // value_len increments by 2kb up to max payload_len
|
||||
None,
|
||||
false,
|
||||
)
|
||||
@@ -1328,11 +1355,12 @@ benchmarks! {
|
||||
|
||||
#[skip_meta]
|
||||
seal_take_storage {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let r in 0 .. API_BENCHMARK_BATCHES/2;
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0);
|
||||
.map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec();
|
||||
h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h })
|
||||
.collect::<Vec<_>>();
|
||||
let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
let key_bytes_len = key_bytes.len();
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
@@ -1340,7 +1368,7 @@ benchmarks! {
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "__unstable__",
|
||||
name: "seal_take_storage",
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
@@ -1354,7 +1382,8 @@ benchmarks! {
|
||||
},
|
||||
],
|
||||
call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
|
||||
Counter(0, key_len as u32), // key_ptr
|
||||
Counter(0, max_key_len as u32), // key_ptr
|
||||
Regular(Instruction::I32Const(max_key_len as i32)), // key_len
|
||||
Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr
|
||||
Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr
|
||||
Regular(Instruction::Call(0)),
|
||||
@@ -1367,7 +1396,7 @@ benchmarks! {
|
||||
for key in keys {
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
&VarSizedKey::<T>::try_from(key).map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![]),
|
||||
None,
|
||||
false,
|
||||
@@ -1380,11 +1409,12 @@ benchmarks! {
|
||||
|
||||
#[skip_meta]
|
||||
seal_take_storage_per_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 1024;
|
||||
let keys = (0 .. API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
let key_len = keys.get(0).map(|i| i.len() as u32).unwrap_or(0);
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
let keys = (0 .. n * API_BENCHMARK_BATCH_SIZE)
|
||||
.map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec();
|
||||
h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h })
|
||||
.collect::<Vec<_>>();
|
||||
let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();
|
||||
let key_bytes_len = key_bytes.len();
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
@@ -1392,7 +1422,7 @@ benchmarks! {
|
||||
imported_functions: vec![ImportedFunction {
|
||||
module: "__unstable__",
|
||||
name: "seal_take_storage",
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
|
||||
return_type: Some(ValueType::I32),
|
||||
}],
|
||||
data_segments: vec![
|
||||
@@ -1406,7 +1436,8 @@ benchmarks! {
|
||||
},
|
||||
],
|
||||
call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![
|
||||
Counter(0, key_len as u32), // key_ptr
|
||||
Counter(0, max_key_len as u32), // key_ptr
|
||||
Regular(Instruction::I32Const(max_key_len as i32)), // key_len
|
||||
Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr
|
||||
Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr
|
||||
Regular(Instruction::Call(0)),
|
||||
@@ -1419,8 +1450,8 @@ benchmarks! {
|
||||
for key in keys {
|
||||
Storage::<T>::write(
|
||||
&info.trie_id,
|
||||
key.as_slice().try_into().map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![42u8; (n * 1024) as usize]),
|
||||
&VarSizedKey::<T>::try_from(key).map_err(|e| "Key has wrong length")?,
|
||||
Some(vec![42u8; (n * 2048) as usize]), // value_len increments by 2kb up to max payload_len
|
||||
None,
|
||||
false,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user