Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
eef15f1
upgrade to wasmi 0.29
agryaznov May 3, 2023
dee28ff
prepare cleanup
agryaznov May 3, 2023
efeb0bd
sync ref_time w engine from the stack frame
agryaznov May 3, 2023
4fdd5c8
proc_macro: sync gas in host funcs
agryaznov May 4, 2023
cac61c6
clean benchmarks & schedule: w_base = w_i64const
agryaznov May 5, 2023
be0df3c
scale gas values btw engine and gas meter
agryaznov May 5, 2023
8a32757
(re)instrumentation & code_cache removed
agryaznov May 5, 2023
f8abec4
remove gas() host fn, continue clean-up
agryaznov May 8, 2023
22440ae
address review comments
agryaznov Jun 9, 2023
c94821d
Merge branch 'master' into ag-wasmeter
agryaznov Jun 9, 2023
2010ff7
move from CodeStorage&PrefabWasmModule to PristineCode&WasmBlob
agryaznov Jun 9, 2023
100cdcd
refactor: no reftime_limit&schedule passes, no CodeStorage
agryaznov Jun 9, 2023
85a0340
bugs fixing
agryaznov Jun 10, 2023
505f750
fix tests: expected deposit amount
agryaznov Jun 10, 2023
c25f634
fix prepare::tests
agryaznov Jun 10, 2023
7f46e7e
update tests and fix bugs
agryaznov Jun 10, 2023
7bf4fbe
update docs
agryaznov Jun 11, 2023
cc05e88
bump wasmi 0.30.0
agryaznov Jun 12, 2023
0e2b0ab
benchmarks updated, tests pass
agryaznov Jun 12, 2023
e6e3563
refactoring
agryaznov Jun 12, 2023
f4ffcf2
s/OwnerInfo/CodeInfo/g;
agryaznov Jun 12, 2023
a50b7cf
migration: draft, compiles
agryaznov Jun 12, 2023
c6b9f74
migration: draft, runs
agryaznov Jun 13, 2023
132e9ce
migration: draft, runs (fixing)
agryaznov Jun 13, 2023
9935e92
deposits repaid non pro rata
agryaznov Jun 13, 2023
0b9125a
deposits repaid pro rata
agryaznov Jun 13, 2023
08a15b7
better try-runtime output
agryaznov Jun 13, 2023
5f6c1ac
even better try-runtime output
agryaznov Jun 13, 2023
b1290f0
benchmark migration
agryaznov Jun 14, 2023
9ffca5d
Merge branch 'master' into ag-wasmeter
agryaznov Jun 14, 2023
94f8476
fix merge leftover
agryaznov Jun 14, 2023
ba67751
add forgotten fixtures, fix docs
agryaznov Jun 14, 2023
0ee3293
address review comments
agryaznov Jun 14, 2023
a45c538
ci fixes
agryaznov Jun 14, 2023
f24a267
cleanup
agryaznov Jun 15, 2023
e6c21f3
benchmarks::prepare to return DispatchError
agryaznov Jun 15, 2023
444a97b
Merge branch 'master' into ag-wasmeter
agryaznov Jun 15, 2023
d3f59b2
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jun 15, 2023
f12927d
store memory limits to CodeInfo
agryaznov Jun 16, 2023
0a9b351
ci: roll back weights
agryaznov Jun 16, 2023
cff9da7
Merge branch 'master' of https://github.com/paritytech/substrate into…
Jun 16, 2023
f0e24c5
".git/.scripts/commands/bench-vm/bench-vm.sh" pallet dev pallet_contr…
Jun 16, 2023
2e07393
drive-by: update Readme and pallet rustdoc
agryaznov Jun 16, 2023
f465ecf
Merge branch 'master' into ag-wasmeter
agryaznov Jun 17, 2023
94be691
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jun 17, 2023
721d4b6
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jun 17, 2023
e226c0e
use wasmi 0.29
agryaznov Jun 18, 2023
e57596f
Merge branch 'master' of https://github.com/paritytech/substrate into…
Jun 18, 2023
d687f1c
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jun 18, 2023
76a8c20
use wasmi 0.30 again
agryaznov Jun 20, 2023
fbc43ae
query memory limits from wasmi
agryaznov Jun 20, 2023
cd54ff2
save: scan_exports ported, compiles
agryaznov Jun 20, 2023
b548064
save (wip, not compiles)
agryaznov Jun 20, 2023
0b4bb91
query memory limits from wasmi
agryaznov Jun 20, 2023
b15d5a9
better migration types
agryaznov Jun 20, 2023
8eb8710
ci: pull weights from master
agryaznov Jun 20, 2023
dae3f32
Merge branch 'master' into ag-wasmeter
agryaznov Jun 21, 2023
f42db5d
refactoring
agryaznov Jun 21, 2023
b789e6b
".git/.scripts/commands/bench-vm/bench-vm.sh" pallet dev pallet_contr…
Jun 21, 2023
3cadbb1
Merge branch 'ag-wasmeter' into ag-wasmi-validation
agryaznov Jun 21, 2023
eba148b
scan_imports ported
agryaznov Jun 21, 2023
ca5938d
scan_export ported, other checks removed
agryaznov Jun 22, 2023
c2c3d9b
tests fixed
agryaznov Jun 22, 2023
56dc2df
drop wasmparser and parity-wasm dependencies
agryaznov Jun 23, 2023
086e219
typo fix
agryaznov Jun 27, 2023
2544972
addressing review comments
agryaznov Jun 27, 2023
387bec9
refactor
agryaznov Jun 27, 2023
8be0537
address review comments
agryaznov Jun 29, 2023
ffdb8d1
optimize migration
agryaznov Jun 30, 2023
eaf7a31
Merge branch 'master' into ag-wasmeter
agryaznov Jun 30, 2023
f4dad0f
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jun 30, 2023
b5ad1de
another review round comments addressed
agryaznov Jun 30, 2023
0e0155f
ci fix one
agryaznov Jun 30, 2023
d139757
clippy fix
agryaznov Jun 30, 2023
670ff1a
ci fix two
agryaznov Jun 30, 2023
18236e1
Merge branch 'ag-wasmeter' into ag-wasmi-validation
agryaznov Jul 3, 2023
0f83c77
allow stored modules to have no memory imports
agryaznov Jul 3, 2023
ca111cf
Merge branch 'master' into ag-wasmi-validation
agryaznov Jul 3, 2023
bf52770
rollback: allow stored modules to have no memory imports
agryaznov Jul 3, 2023
824ef6d
Merge branch 'master' of https://github.com/paritytech/substrate into…
Jul 3, 2023
b55dbcb
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jul 3, 2023
39fb730
address review comments
agryaznov Jul 4, 2023
ac9d5c2
Merge branch 'ag-wasmi-validation'
agryaznov Jul 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
address review comments
  • Loading branch information
agryaznov committed Jun 14, 2023
commit 0ee3293f4950c1b117b49d4289d27c95950c478c
2 changes: 0 additions & 2 deletions frame/contracts/proc-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,13 +626,11 @@ fn expand_functions(def: &EnvDef, expand_blocks: bool, host_state: TokenStream2)
quote! {
let result = #body;
if ::log::log_enabled!(target: "runtime::contracts::strace", ::log::Level::Trace) {
{
use sp_std::fmt::Write;
let mut w = sp_std::Writer::default();
let _ = core::write!(&mut w, #trace_fmt_str, #( #trace_fmt_args, )* result);
let msg = core::str::from_utf8(&w.inner()).unwrap_or_default();
ctx.ext().append_debug_buffer(msg);
}
}
result
}
Expand Down
26 changes: 0 additions & 26 deletions frame/contracts/src/benchmarking/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,31 +358,6 @@ impl<T: Config> WasmModule<T> {
.into()
}

#[allow(dead_code)]
pub fn unary_instr(instr: Instruction, repeat: u32) -> Self {
use body::DynInstr::{RandomI64Repeated, Regular};
ModuleDefinition {
call_body: Some(body::repeated_dyn(
repeat,
vec![RandomI64Repeated(1), Regular(instr), Regular(Instruction::Drop)],
)),
..Default::default()
}
.into()
}

#[allow(dead_code)]
pub fn binary_instr(instr: Instruction, repeat: u32) -> Self {
use body::DynInstr::{RandomI64Repeated, Regular};
ModuleDefinition {
call_body: Some(body::repeated_dyn(
repeat,
vec![RandomI64Repeated(2), Regular(instr), Regular(Instruction::Drop)],
)),
..Default::default()
}
.into()
}
}

/// Mechanisms to generate a function body that can be used inside a `ModuleDefinition`.
Expand All @@ -392,7 +367,6 @@ pub mod body {
/// When generating contract code by repeating a wasm sequence, it's sometimes necessary
/// to change those instructions on each repetition. The variants of this enum describe
/// various ways in which this can happen.
#[allow(dead_code)]
pub enum DynInstr {
/// Insert the associated instruction.
Regular(Instruction),
Expand Down
36 changes: 15 additions & 21 deletions frame/contracts/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,6 @@ pub trait Executable<T: Config>: Sized {
/// Charges size base load weight from the gas meter.
fn from_storage(
code_hash: CodeHash<T>,
schedule: &Schedule<T>,
gas_meter: &mut GasMeter<T>,
) -> Result<Self, DispatchError>;

Expand All @@ -348,7 +347,6 @@ pub trait Executable<T: Config>: Sized {
fn remove_user(code_hash: CodeHash<T>);

/// Execute the specified exported function and return the result.
/// `reftime_limit` is passed to the execution engine to account for gas.
///
/// When the specified function is `Constructor` the executable is stored and its
/// refcount incremented.
Expand All @@ -367,7 +365,7 @@ pub trait Executable<T: Config>: Sized {
/// The code hash of the executable.
fn code_hash(&self) -> CodeHash<T>;

/// Size of the conract code in bytes.
/// Size of the contract code in bytes.
fn code_len(&self) -> u32;

/// The code does not contain any instructions which could lead to indeterminism.
Expand Down Expand Up @@ -707,7 +705,6 @@ where
Weight::zero(),
storage_meter,
BalanceOf::<T>::zero(),
schedule,
determinism,
)?;

Expand Down Expand Up @@ -740,7 +737,6 @@ where
gas_limit: Weight,
storage_meter: &mut storage::meter::GenericMeter<T, S>,
deposit_limit: BalanceOf<T>,
schedule: &Schedule<T>,
determinism: Determinism,
) -> Result<(Frame<T>, E, Option<u64>), ExecError> {
let (account_id, contract_info, executable, delegate_caller, entry_point, nonce) =
Expand All @@ -756,7 +752,7 @@ where
if let Some(DelegatedCall { executable, caller }) = delegated_call {
(executable, Some(caller))
} else {
(E::from_storage(contract.code_hash, schedule, gas_meter)?, None)
(E::from_storage(contract.code_hash, gas_meter)?, None)
};

(dest, contract, executable, delegate_caller, ExportedFunction::Call, None)
Expand Down Expand Up @@ -836,7 +832,6 @@ where
gas_limit,
nested_storage,
deposit_limit,
self.schedule,
self.determinism,
)?;
self.frames.push(frame);
Expand Down Expand Up @@ -1198,7 +1193,7 @@ where
code_hash: CodeHash<Self::T>,
input_data: Vec<u8>,
) -> Result<ExecReturnValue, ExecError> {
let executable = E::from_storage(code_hash, self.schedule, self.gas_meter_mut())?;
let executable = E::from_storage(code_hash, self.gas_meter_mut())?;
let top_frame = self.top_frame_mut();
let contract_info = top_frame.contract_info().clone();
let account_id = top_frame.account_id.clone();
Expand All @@ -1225,7 +1220,7 @@ where
input_data: Vec<u8>,
salt: &[u8],
) -> Result<(AccountIdOf<T>, ExecReturnValue), ExecError> {
let executable = E::from_storage(code_hash, self.schedule, self.gas_meter_mut())?;
let executable = E::from_storage(code_hash, self.gas_meter_mut())?;
let nonce = self.next_nonce();
let executable = self.push_frame(
FrameArgs::Instantiate {
Expand Down Expand Up @@ -1432,7 +1427,7 @@ where

fn set_code_hash(&mut self, hash: CodeHash<Self::T>) -> Result<(), DispatchError> {
let frame = top_frame_mut!(self);
if !E::from_storage(hash, self.schedule, &mut frame.nested_gas)?.is_deterministic() {
if !E::from_storage(hash, &mut frame.nested_gas)?.is_deterministic() {
return Err(<Error<T>>::Indeterministic.into())
}
E::add_user(hash)?;
Expand Down Expand Up @@ -1600,7 +1595,6 @@ mod tests {
impl Executable<Test> for MockExecutable {
fn from_storage(
code_hash: CodeHash<Test>,
_schedule: &Schedule<Test>,
_gas_meter: &mut GasMeter<Test>,
) -> Result<Self, DispatchError> {
Loader::mutate(|loader| {
Expand Down Expand Up @@ -1962,7 +1956,7 @@ mod tests {
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable =
MockExecutable::from_storage(input_data_ch, &schedule, &mut gas_meter).unwrap();
MockExecutable::from_storage(input_data_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
Expand Down Expand Up @@ -2376,7 +2370,7 @@ mod tests {
let schedule = <Test as Config>::Schedule::get();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable =
MockExecutable::from_storage(dummy_ch, &schedule, &mut gas_meter).unwrap();
MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
Expand Down Expand Up @@ -2409,7 +2403,7 @@ mod tests {
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable =
MockExecutable::from_storage(dummy_ch, &schedule, &mut gas_meter).unwrap();
MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 1000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
Expand Down Expand Up @@ -2455,7 +2449,7 @@ mod tests {
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable =
MockExecutable::from_storage(dummy_ch, &schedule, &mut gas_meter).unwrap();
MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 1000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
Expand Down Expand Up @@ -2624,7 +2618,7 @@ mod tests {
let schedule = <Test as Config>::Schedule::get();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable =
MockExecutable::from_storage(terminate_ch, &schedule, &mut gas_meter).unwrap();
MockExecutable::from_storage(terminate_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
Expand Down Expand Up @@ -2726,7 +2720,7 @@ mod tests {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable = MockExecutable::from_storage(code, &schedule, &mut gas_meter).unwrap();
let executable = MockExecutable::from_storage(code, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
Expand Down Expand Up @@ -3151,13 +3145,13 @@ mod tests {
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let fail_executable =
MockExecutable::from_storage(fail_code, &schedule, &mut gas_meter).unwrap();
MockExecutable::from_storage(fail_code, &mut gas_meter).unwrap();
let success_executable =
MockExecutable::from_storage(success_code, &schedule, &mut gas_meter).unwrap();
MockExecutable::from_storage(success_code, &mut gas_meter).unwrap();
let succ_fail_executable =
MockExecutable::from_storage(succ_fail_code, &schedule, &mut gas_meter).unwrap();
MockExecutable::from_storage(succ_fail_code, &mut gas_meter).unwrap();
let succ_succ_executable =
MockExecutable::from_storage(succ_succ_code, &schedule, &mut gas_meter).unwrap();
MockExecutable::from_storage(succ_succ_code, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
Expand Down
5 changes: 0 additions & 5 deletions frame/contracts/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,6 @@ impl<T: Config> GasMeter<T> {
self.gas_left
}

/// Returns current tracked engine fuel consumption.
pub fn engine_consumed(&self) -> u64 {
self.engine_consumed
}

/// Turn this GasMeter into a DispatchResult that contains the actually used gas.
pub fn into_dispatch_result<R, E>(
self,
Expand Down
8 changes: 4 additions & 4 deletions frame/contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,17 +360,17 @@ pub mod pallet {

// Check that given configured `MaxCodeLen`, runtime heap memory limit can't be broken.
//
// In worst case, the decoded wasm contract code would be `x16` times larger than the
// In worst case, the decoded Wasm contract code would be `x16` times larger than the
// encoded one. This is because even a single-byte wasm instruction has 16-byte size in
// wasmi. This gives us `MaxCodeLen*16` safety margin.
//
// Next, the pallet keeps the Wasm blob for each
// contract, hence we add up one `MaxCodeLen` more to the safety margin.
// contract, hence we add up `MaxCodeLen` to the safety margin.
//
// Finally, the inefficiencies of the freeing-bump allocator
// being used in the client for the runtime memory allocations, could lead to possible
// memory allocations for contract code grow up to `x4` times in some extreme cases,
// which gives us total multiplier of `18*4` for `MaxCodeLen`.
// which gives us total multiplier of `17*4` for `MaxCodeLen`.
//
// That being said, for every contract executed in runtime, at least `MaxCodeLen*17*4`
// memory should be available. Note that maximum allowed heap memory and stack size per
Expand Down Expand Up @@ -1233,7 +1233,7 @@ impl<T: Config> Invokable<T> for InstantiateInput<T> {
(executable.open_deposit(code_info), executable)
},
Code::Existing(hash) =>
(Default::default(), WasmBlob::from_storage(*hash, &schedule, &mut gas_meter)?),
(Default::default(), WasmBlob::from_storage(*hash, &mut gas_meter)?),
};
let contract_origin = Origin::from_account_id(origin.clone());
let mut storage_meter = StorageMeter::new(
Expand Down
5 changes: 2 additions & 3 deletions frame/contracts/src/migration/v12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ impl<T: Config> Migrate for Migration<T> {
} else {
log::warn!(
target: LOG_TARGET,
"new deposit: {:?} is more than old deposit: {:?}",
"new deposit: {:?} >= old deposit: {:?}",
&info.deposit,
&old.deposit
);
Expand Down Expand Up @@ -289,8 +289,7 @@ impl<T: Config> Migrate for Migration<T> {
PristineCode::<T>::iter().for_each(|(_k, v)| {
storage_code += v.len() as u32;
});
let old_deposit = state.1;
let storage_module = state.2;
let (_, old_deposit, storage_module) = state;
// CodeInfoOf::max_encoded_len == OwnerInfoOf::max_encoded_len + 1
// I.e. code info adds up 1 byte per record.
let info_bytes_added = items.clone();
Expand Down
2 changes: 1 addition & 1 deletion frame/contracts/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ pub mod test_utils {
<<Test as SysConfig>::Hashing as Hash>::hash_of(s)
}
pub fn expected_deposit(code_len: usize) -> u64 {
// For onwer info, the deposit for max_encoded_len is taken.
// For code_info, the deposit for max_encoded_len is taken.
let code_info_len = CodeInfo::<Test>::max_encoded_len() as u64;
// Calculate deposit to be reserved.
// We add 2 storage items: one for code, other for code_info
Expand Down
23 changes: 8 additions & 15 deletions frame/contracts/src/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,26 +125,20 @@ impl ExportedFunction {
}
}

/// Costs for operations that are related to code handling.
/// Cost of code loading from storage.
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
#[derive(Clone, Copy)]
enum CodeToken {
/// Weight for loading a contract per byte.
Load(u32),
}
struct CodeLoadToken(u32);

impl<T: Config> Token<T> for CodeToken {
impl<T: Config> Token<T> for CodeLoadToken {
fn weight(&self) -> Weight {
use self::CodeToken::*;
// In case of `Load` we already covered the general costs of
// When loading the contract, we already covered the general costs of
// calling the storage but still need to account for the actual size of the
// contract code. This is why we subtract `T::*::(0)`. We need to do this at this
// point because when charging the general weight for calling the contract we don't know the
// size of the contract.
match *self {
Load(len) => T::WeightInfo::call_with_code_per_byte(len)
.saturating_sub(T::WeightInfo::call_with_code_per_byte(0)),
}
T::WeightInfo::call_with_code_per_byte(self.0)
.saturating_sub(T::WeightInfo::call_with_code_per_byte(0))
}
}

Expand Down Expand Up @@ -316,11 +310,11 @@ impl<T: Config> WasmBlob<T> {
gas_meter: &mut GasMeter<T>,
) -> Result<CodeVec<T>, DispatchError> {
let max_code_len = T::MaxCodeLen::get();
let charged = gas_meter.charge(CodeToken::Load(max_code_len))?;
let charged = gas_meter.charge(CodeLoadToken(max_code_len))?;

let code = <PristineCode<T>>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
let code_len = code.len() as u32;
gas_meter.adjust_gas(charged, CodeToken::Load(code_len));
gas_meter.adjust_gas(charged, CodeLoadToken(code_len));

Ok(code)
}
Expand Down Expand Up @@ -395,7 +389,6 @@ impl<T: Config> CodeInfo<T> {
impl<T: Config> Executable<T> for WasmBlob<T> {
fn from_storage(
code_hash: CodeHash<T>,
_schedule: &Schedule<T>,
gas_meter: &mut GasMeter<T>,
) -> Result<Self, DispatchError> {
let code = Self::load_code(code_hash, gas_meter)?;
Expand Down
1 change: 0 additions & 1 deletion frame/contracts/src/wasm/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ pub trait Environment<HostState> {
}

/// Type of a storage key.
#[allow(dead_code)]
enum KeyType {
/// Legacy fix sized key `[u8;32]`.
Fix,
Expand Down