Skip to content

Commit 5fc2d2a

Browse files
authored
Storage refactoring new hope for review (#1331)
* Import new unstable functions with transparent hashing. Updated the API to work with the generic key `K: Encode` instead of the old `Key`. Also, the change contains optimization to reduce the size of contracts. In most cases, it is `#[inline(always)]`; but `return_value` also got small optimization; removed usage of `extract_from_slice` where it is not needed. * primitives crate: Removed old 32 bytes `Key`. Replaced it with `u32`. Added `KeyComposer`, it is a helper struct that does all manipulation with the storage key. It allows concat two storage keys into one, compute storage key for fields based on the filed, struct, enum, variants names. Removed all tests and benches. Didn't add it for new primitives because the key is standard `u32` and all keys are calculated during compilation. storage crate: Removed `SpreadLayout`, `PackedLayout`, `SpreadAllocate`, `PackedAllocate`, and all related helper functions. Removed `Packed` struct cause it is the default behavior for storage right now. Added `Lazy` struct that allows `get`/`set` value from/into the storage. It is similar to `Mapping` but works with one storage key and one value. Introduced new main traits to work with storage in `storage/src/traits/storage.rs`. Also added a new `OnCallInitializer` trait to improve the flow with upgradable contracts and support initialization on demand by default. Added `pull_or_init` macro that inits the storage struct if it is impossible to load it. It also can be used as optimization for contracts without an explicit constructor. Replaced implementation of old traits for main primitives with a new one. Added blanket implementation of new traits for structures that are `Packed` by default. It reduces the amount of code and adds support of generic structures but adds problems with tuples(now tuples implement new traits only if inner items are `Packed`). Introduced `AutoKey` and `ManualKey` that allows specifying which key the user wants to use. Added support of it into all traits and structures. Refactored `Mapping` to follow new rules. * metadata crate: Updated storage layout in the metadata. Introduces the concept of roots and leafs. Root defines the storage key for all sub-tree until there will be another Root. Leafs are common types that are part of the sub-tree and serialized/deserialized together into one storage key. Replaced 32 bytes storage key with `u32`. Added validation that all root storage keys don't overlap. Maybe better to add that error or reuse that validator on the `cargo-contract` side to show a more user-friendly error. `RootLayout` and validator are used in codegen(next commit). The contract is wrapped into `RootLayout`, and we do validation for that tree. Metadata now contains name for each struct/enum/variant/field. It is useful information because now the storage key is calculated based on the name of struct/enum/variant/field. storage crate: Added a new helper crate `storage/codegen`. It contains some useful functional that is used in `ink_storage_derive` and in `ink_lang_codegen` crates. It has a method that returns all types of the struct/enum/unit and a method that finds "salt" in the generics of the struct/enum. It uses magic constant "KeyHolder"(about that you can read in issue) to find salt, so I tried to have only one place where we are using that constant. Replaced derive implementation of old trait with new one. You can check the tests to see how the implementation looks like. `Storable` recursively call `encode` and `decode` for all fields. `KeyHolder` return key of the salt. `Item` uses `AutoKey` or key specified by the user. I want to highlight that `PreferredKey` only is used with the `AutoItem` trait. If `PreferredKey` is `AutoKey`, then `AutoItem<AutoGenerated>` select auto-generated key, otherwise preferred. So `AutoItem` trait decides that key to use. It is why derive macro only set `PreferredKey`. Updated drive for `StorageLayout`, now it uses `u32` and pass name of the struct into metadata. * Removed `initialize_contract` and related to initialization stuff. Now the codegen uses `pull_or_init` in the `call`. Updated `execute_constructor` to work with new storage methods. Allowed usage of generics during the declaration of the primary contract storage. Users can specify the default storage key with `KeyHolder` via generic. Added parser for `storage_item` macro with its config. * Removed the old codegen related to spread and packed layout. If some object implements `Decode` and `Encode`, it is `Packed`, and it uses the blanket implementation of new traits. In dispatch, codegen started to use a new method to work with storage. In metadata codegen added usage of new `RootLayout`. We wrap the contract into that layout because the contract has its storage key for all inner fields by default. Also added a run of validation logic during metadata generation. Added `storage_item` macro. It transforms all types from autokey into manual key(if types support it). It calculates the storage key based on the name(it uses the `KeyComposer::compute_key` function from the primitives crate). Also, macro generates an additional `Check` structure that includes all raw fields. It helps show correct errors to the user in case of typos, wrong types, etc. * Updated all examples to use a new API. Simplified delegate call example very well causes of new `OnCallInitializer` trait and support of manual specifying key. * UI tests for a new codegen. Can't highlight something unusual here=) * Apply all suggestion from the review * Make CI happy * Fix tests * Fix tests * Fix tests * Fix tests * Apply suggestions: - In most cases it is comments=) - Moved `pull_or_init` on one level upper. - Put the tests into the `impls/mod.rs` * Fix doc * Add comment to autoref specialisation * Suggestion from the review * Revert back u8 * Remove unwrap * Collapse if let * Fixed overflow for enums * Fixing comments * Renamed `Item` to `StorableHint` and `AutoItem` to `AutoStorableHint` * Fix test * Renamed key_holder. Add UI test for double storage_item. Applied suggestion from the review. * Nightly fmt * Remove `Packed` path * Fix doc test * Apply suggestions from hte review * Fixed build * Fix build * Removed `initialize_contract` from linting and deleted all tests * Fix doc link * Fix mapping example * Applied suggestion. Removed `delegate-call` example with `OnCallInitializer` * Removed `delegate-calls` from the CI. Replaced it with `set-code-hash` * fix test * fix test * Fix CI to use stable for contract build * Fix CI to use stable for examples
1 parent 8612206 commit 5fc2d2a

File tree

154 files changed

+4753
-7292
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

154 files changed

+4753
-7292
lines changed

.config/cargo_spellcheck.dic

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ defragmentation
3838
deploy
3939
dereferencing
4040
deserialize/S
41+
deserialization
4142
dispatchable/S
4243
encodable
4344
evaluable
@@ -106,3 +107,4 @@ natively
106107
payability
107108
unpayable
108109
initializer
110+
storable

.github/workflows/examples.yml

+10-5
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,20 @@ jobs:
2626
# Once this is resolved we should re-enable building the examples on windows
2727
# - windows-latest
2828
toolchain:
29-
- nightly
29+
- stable
3030
job:
3131
- build
3232
- test
3333
runs-on: ${{ matrix.platform }}
3434
env:
35-
UPGRADEABLE_CONTRACTS: "forward-calls delegate-calls"
35+
UPGRADEABLE_CONTRACTS: "forward-calls set-code-hash"
3636
DELEGATOR_SUBCONTRACTS: "accumulator adder subber"
3737
RUST_BACKTRACE: full
38+
# We need to enable `RUSTC_BOOTSTRAP` so that the nightly ink!
39+
# features still work on stable. This is done automatically by
40+
# `cargo-contract`, but in our CI here we also use e.g.
41+
# `cargo check` directly.
42+
RUSTC_BOOTSTRAP: "1"
3843
steps:
3944

4045
- uses: actions/setup-node@v3
@@ -90,12 +95,12 @@ jobs:
9095
echo "Processing delegator contract: $contract";
9196
cargo contract ${{ matrix.job }} --verbose --manifest-path examples/delegator/${contract}/Cargo.toml;
9297
}
93-
$upgradeable_contracts = "forward-calls","delegate-calls"
98+
$upgradeable_contracts = "forward-calls","set-code-hash"
9499
foreach ($contract in $upgradeable_contracts) {
95100
echo "Processing upgradeable contract: $contract";
96101
cargo contract ${{ matrix.job }} --verbose --manifest-path examples/upgradeable-contracts/${contract}/Cargo.toml;
97102
}
98-
cargo contract ${{ matrix.job }} --verbose --manifest-path examples/upgradeable-contracts/delegate-calls/upgradeable-flipper/Cargo.toml;
103+
cargo contract ${{ matrix.job }} --verbose --manifest-path examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml;
99104
foreach ($example in Get-ChildItem -Directory "examples\*") {
100105
if ($example -Match 'upgradeable-contracts') { continue }
101106
echo "Processing example: $example";
@@ -114,7 +119,7 @@ jobs:
114119
echo "Processing upgradeable contract: $contract";
115120
cargo contract ${{ matrix.job }} --verbose --manifest-path=examples/upgradeable-contracts/$contract/Cargo.toml;
116121
done
117-
cargo contract ${{ matrix.job }} --verbose --manifest-path=examples/upgradeable-contracts/delegate-calls/upgradeable-flipper/Cargo.toml;
122+
cargo contract ${{ matrix.job }} --verbose --manifest-path=examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml;
118123
for example in examples/*/; do
119124
if [ "$example" = "examples/upgradeable-contracts/" ]; then continue; fi;
120125
echo "Processing example: $example";

.gitlab-ci.yml

+8-8
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ variables:
3333
ALSO_WASM_CRATES: "env storage storage/derive allocator prelude primitives lang lang/macro lang/ir"
3434
ALL_CRATES: "${PURELY_STD_CRATES} ${ALSO_WASM_CRATES}"
3535
DELEGATOR_SUBCONTRACTS: "accumulator adder subber"
36-
UPGRADEABLE_CONTRACTS: "forward-calls delegate-calls"
36+
UPGRADEABLE_CONTRACTS: "forward-calls set-code-hash"
3737
# We need to enable `RUSTC_BOOTSTRAP` so that the nightly ink!
3838
# features still work on stable. This is done automatically by
3939
# `cargo-contract`, but in our CI here we also use e.g.
@@ -127,7 +127,7 @@ examples-fmt:
127127
- for contract in ${UPGRADEABLE_CONTRACTS}; do
128128
cargo +nightly fmt --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml -- --check;
129129
done
130-
- cargo +nightly fmt --verbose --manifest-path ./examples/upgradeable-contracts/delegate-calls/upgradeable-flipper/Cargo.toml -- --check
130+
- cargo +nightly fmt --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml -- --check
131131
allow_failure: true
132132

133133
clippy-std:
@@ -164,7 +164,7 @@ examples-clippy-std:
164164
- for contract in ${UPGRADEABLE_CONTRACTS}; do
165165
cargo +nightly clippy --verbose --all-targets --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml -- -D warnings;
166166
done
167-
- cargo +nightly clippy --verbose --all-targets --manifest-path ./examples/upgradeable-contracts/delegate-calls/upgradeable-flipper/Cargo.toml -- -D warnings;
167+
- cargo +nightly clippy --verbose --all-targets --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml -- -D warnings;
168168
allow_failure: true
169169

170170
examples-clippy-wasm:
@@ -182,7 +182,7 @@ examples-clippy-wasm:
182182
- for contract in ${UPGRADEABLE_CONTRACTS}; do
183183
cargo +nightly clippy --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings;
184184
done
185-
- cargo +nightly clippy --verbose --manifest-path ./examples/upgradeable-contracts/delegate-calls/upgradeable-flipper/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings;
185+
- cargo +nightly clippy --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml --no-default-features --target wasm32-unknown-unknown -- -D warnings;
186186
allow_failure: true
187187

188188

@@ -281,7 +281,7 @@ docs:
281281
- cargo doc --no-deps --all-features
282282
-p scale-info -p ink_metadata
283283
-p ink_env -p ink_storage -p ink_storage_derive
284-
-p ink_primitives -p ink_prelude
284+
-p ink_primitives -p ink_prelude -p ink_primitives_derive
285285
-p ink_lang -p ink_lang_macro -p ink_lang_ir -p ink_lang_codegen
286286
- mv ${CARGO_TARGET_DIR}/doc ./crate-docs
287287
# FIXME: remove me after CI image gets nonroot
@@ -352,7 +352,7 @@ examples-test:
352352
- for contract in ${UPGRADEABLE_CONTRACTS}; do
353353
cargo test --verbose --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml;
354354
done
355-
- cargo test --verbose --manifest-path ./examples/upgradeable-contracts/delegate-calls/upgradeable-flipper/Cargo.toml;
355+
- cargo test --verbose --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml;
356356

357357
examples-contract-build:
358358
stage: examples
@@ -372,7 +372,7 @@ examples-contract-build:
372372
- for contract in ${UPGRADEABLE_CONTRACTS}; do
373373
cargo +stable contract build --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml;
374374
done
375-
- cargo +stable contract build --manifest-path ./examples/upgradeable-contracts/delegate-calls/upgradeable-flipper/Cargo.toml
375+
- cargo +stable contract build --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml
376376

377377
examples-docs:
378378
stage: examples
@@ -395,7 +395,7 @@ examples-docs:
395395
- for contract in ${UPGRADEABLE_CONTRACTS}; do
396396
cargo doc --manifest-path ./examples/upgradeable-contracts/${contract}/Cargo.toml --document-private-items --verbose --no-deps;
397397
done
398-
- cargo doc --manifest-path ./examples/upgradeable-contracts/delegate-calls/upgradeable-flipper/Cargo.toml --document-private-items --verbose --no-deps
398+
- cargo doc --manifest-path ./examples/upgradeable-contracts/set-code-hash/updated-incrementer/Cargo.toml --document-private-items --verbose --no-deps
399399

400400

401401
#### stage: ink-waterfall

crates/engine/src/ext.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ impl Engine {
229229

230230
/// Writes the encoded value into the storage at the given key.
231231
/// Returns the size of the previously stored value at the key if any.
232-
pub fn set_storage(&mut self, key: &[u8; 32], encoded_value: &[u8]) -> Option<u32> {
232+
pub fn set_storage(&mut self, key: &[u8], encoded_value: &[u8]) -> Option<u32> {
233233
let callee = self.get_callee();
234234
let account_id = AccountId::from_bytes(&callee[..]);
235235

@@ -243,7 +243,7 @@ impl Engine {
243243
}
244244

245245
/// Returns the decoded contract storage at the key if any.
246-
pub fn get_storage(&mut self, key: &[u8; 32], output: &mut &mut [u8]) -> Result {
246+
pub fn get_storage(&mut self, key: &[u8], output: &mut &mut [u8]) -> Result {
247247
let callee = self.get_callee();
248248
let account_id = AccountId::from_bytes(&callee[..]);
249249

@@ -258,7 +258,7 @@ impl Engine {
258258
}
259259

260260
/// Returns the size of the value stored in the contract storage at the key if any.
261-
pub fn contains_storage(&mut self, key: &[u8; 32]) -> Option<u32> {
261+
pub fn contains_storage(&mut self, key: &[u8]) -> Option<u32> {
262262
let callee = self.get_callee();
263263
let account_id = AccountId::from_bytes(&callee[..]);
264264

@@ -269,14 +269,17 @@ impl Engine {
269269
}
270270

271271
/// Removes the storage entries at the given key.
272-
pub fn clear_storage(&mut self, key: &[u8; 32]) {
272+
/// Returns the size of the previously stored value at the key if any.
273+
pub fn clear_storage(&mut self, key: &[u8]) -> Option<u32> {
273274
let callee = self.get_callee();
274275
let account_id = AccountId::from_bytes(&callee[..]);
275276
self.debug_info.inc_writes(account_id.clone());
276277
let _ = self
277278
.debug_info
278279
.remove_cell_for_account(account_id, key.to_vec());
279-
let _ = self.database.remove_contract_storage(&callee, key);
280+
self.database
281+
.remove_contract_storage(&callee, key)
282+
.map(|val| val.len() as u32)
280283
}
281284

282285
/// Remove the calling account and transfer remaining balance.

crates/env/src/api.rs

+26-17
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use crate::{
3939
Environment,
4040
Result,
4141
};
42-
use ink_primitives::Key;
42+
use ink_primitives::traits::Storable;
4343

4444
/// Returns the address of the caller of the executed contract.
4545
///
@@ -183,49 +183,58 @@ where
183183
})
184184
}
185185

186-
/// Writes the value to the contract storage under the given key and returns
187-
/// the size of pre-existing value at the specified key if any.
186+
/// Writes the value to the contract storage under the given storage key and returns the size
187+
/// of pre-existing value if any.
188188
///
189189
/// # Panics
190190
///
191191
/// - If the encode length of value exceeds the configured maximum value length of a storage entry.
192-
pub fn set_contract_storage<V>(key: &Key, value: &V) -> Option<u32>
192+
pub fn set_contract_storage<K, V>(key: &K, value: &V) -> Option<u32>
193193
where
194-
V: scale::Encode,
194+
K: scale::Encode,
195+
V: Storable,
195196
{
196197
<EnvInstance as OnInstance>::on_instance(|instance| {
197-
EnvBackend::set_contract_storage::<V>(instance, key, value)
198+
EnvBackend::set_contract_storage::<K, V>(instance, key, value)
198199
})
199200
}
200201

201-
/// Returns the value stored under the given key in the contract's storage if any.
202+
/// Returns the value stored under the given storage key in the contract's storage if any.
202203
///
203204
/// # Errors
204205
///
205206
/// - If the decoding of the typed value failed (`KeyNotFound`)
206-
pub fn get_contract_storage<R>(key: &Key) -> Result<Option<R>>
207+
pub fn get_contract_storage<K, R>(key: &K) -> Result<Option<R>>
207208
where
208-
R: scale::Decode,
209+
K: scale::Encode,
210+
R: Storable,
209211
{
210212
<EnvInstance as OnInstance>::on_instance(|instance| {
211-
EnvBackend::get_contract_storage::<R>(instance, key)
213+
EnvBackend::get_contract_storage::<K, R>(instance, key)
212214
})
213215
}
214216

215-
/// Checks whether there is a value stored under the given key in
216-
/// the contract's storage.
217+
/// Checks whether there is a value stored under the given storage key in the contract's storage.
217218
///
218219
/// If a value is stored under the specified key, the size of the value is returned.
219-
pub fn contract_storage_contains(key: &Key) -> Option<u32> {
220+
pub fn contains_contract_storage<K>(key: &K) -> Option<u32>
221+
where
222+
K: scale::Encode,
223+
{
220224
<EnvInstance as OnInstance>::on_instance(|instance| {
221-
EnvBackend::contract_storage_contains(instance, key)
225+
EnvBackend::contains_contract_storage::<K>(instance, key)
222226
})
223227
}
224228

225-
/// Clears the contract's storage key entry.
226-
pub fn clear_contract_storage(key: &Key) {
229+
/// Clears the contract's storage entry under the given storage key.
230+
///
231+
/// If a value was stored under the specified storage key, the size of the value is returned.
232+
pub fn clear_contract_storage<K>(key: &K) -> Option<u32>
233+
where
234+
K: scale::Encode,
235+
{
227236
<EnvInstance as OnInstance>::on_instance(|instance| {
228-
EnvBackend::clear_contract_storage(instance, key)
237+
EnvBackend::clear_contract_storage::<K>(instance, key)
229238
})
230239
}
231240

crates/env/src/backend.rs

+21-12
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::{
2727
Environment,
2828
Result,
2929
};
30-
use ink_primitives::Key;
30+
use ink_primitives::traits::Storable;
3131

3232
/// The flags to indicate further information about the end of a contract execution.
3333
#[derive(Default)]
@@ -162,26 +162,35 @@ impl CallFlags {
162162

163163
/// Environmental contract functionality that does not require `Environment`.
164164
pub trait EnvBackend {
165-
/// Writes the value to the contract storage under the given key and returns
166-
/// the size of the pre-existing value at the specified key if any.
167-
fn set_contract_storage<V>(&mut self, key: &Key, value: &V) -> Option<u32>
165+
/// Writes the value to the contract storage under the given storage key.
166+
///
167+
/// Returns the size of the pre-existing value at the specified key if any.
168+
fn set_contract_storage<K, V>(&mut self, key: &K, value: &V) -> Option<u32>
168169
where
169-
V: scale::Encode;
170+
K: scale::Encode,
171+
V: Storable;
170172

171-
/// Returns the value stored under the given key in the contract's storage if any.
173+
/// Returns the value stored under the given storage key in the contract's storage if any.
172174
///
173175
/// # Errors
174176
///
175177
/// - If the decoding of the typed value failed
176-
fn get_contract_storage<R>(&mut self, key: &Key) -> Result<Option<R>>
178+
fn get_contract_storage<K, R>(&mut self, key: &K) -> Result<Option<R>>
177179
where
178-
R: scale::Decode;
180+
K: scale::Encode,
181+
R: Storable;
179182

180-
/// Returns the size of a value stored under the specified key is returned if any.
181-
fn contract_storage_contains(&mut self, key: &Key) -> Option<u32>;
183+
/// Returns the size of a value stored under the given storage key is returned if any.
184+
fn contains_contract_storage<K>(&mut self, key: &K) -> Option<u32>
185+
where
186+
K: scale::Encode;
182187

183-
/// Clears the contract's storage key entry.
184-
fn clear_contract_storage(&mut self, key: &Key);
188+
/// Clears the contract's storage key entry under the given storage key.
189+
///
190+
/// Returns the size of the previously stored value at the specified key if any.
191+
fn clear_contract_storage<K>(&mut self, key: &K) -> Option<u32>
192+
where
193+
K: scale::Encode;
185194

186195
/// Returns the execution input to the executed contract and decodes it as `T`.
187196
///

crates/env/src/engine/off_chain/impls.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use ink_engine::{
4444
ext,
4545
ext::Engine,
4646
};
47-
use ink_primitives::Key;
47+
use ink_primitives::traits::Storable;
4848

4949
/// The capacity of the static buffer.
5050
/// This is the same size as the ink! on-chain environment. We chose to use the same size
@@ -184,34 +184,43 @@ impl EnvInstance {
184184
}
185185

186186
impl EnvBackend for EnvInstance {
187-
fn set_contract_storage<V>(&mut self, key: &Key, value: &V) -> Option<u32>
187+
fn set_contract_storage<K, V>(&mut self, key: &K, value: &V) -> Option<u32>
188188
where
189-
V: scale::Encode,
189+
K: scale::Encode,
190+
V: Storable,
190191
{
191-
let v = scale::Encode::encode(value);
192-
self.engine.set_storage(key.as_ref(), &v[..])
192+
let mut v = vec![];
193+
Storable::encode(value, &mut v);
194+
self.engine.set_storage(&key.encode(), &v[..])
193195
}
194196

195-
fn get_contract_storage<R>(&mut self, key: &Key) -> Result<Option<R>>
197+
fn get_contract_storage<K, R>(&mut self, key: &K) -> Result<Option<R>>
196198
where
197-
R: scale::Decode,
199+
K: scale::Encode,
200+
R: Storable,
198201
{
199202
let mut output: [u8; 9600] = [0; 9600];
200-
match self.engine.get_storage(key.as_ref(), &mut &mut output[..]) {
203+
match self.engine.get_storage(&key.encode(), &mut &mut output[..]) {
201204
Ok(_) => (),
202205
Err(ext::Error::KeyNotFound) => return Ok(None),
203206
Err(_) => panic!("encountered unexpected error"),
204207
}
205-
let decoded = scale::Decode::decode(&mut &output[..])?;
208+
let decoded = Storable::decode(&mut &output[..])?;
206209
Ok(Some(decoded))
207210
}
208211

209-
fn contract_storage_contains(&mut self, key: &Key) -> Option<u32> {
210-
self.engine.contains_storage(key.as_ref())
212+
fn contains_contract_storage<K>(&mut self, key: &K) -> Option<u32>
213+
where
214+
K: scale::Encode,
215+
{
216+
self.engine.contains_storage(&key.encode())
211217
}
212218

213-
fn clear_contract_storage(&mut self, key: &Key) {
214-
self.engine.clear_storage(key.as_ref())
219+
fn clear_contract_storage<K>(&mut self, key: &K) -> Option<u32>
220+
where
221+
K: scale::Encode,
222+
{
223+
self.engine.clear_storage(&key.encode())
215224
}
216225

217226
fn decode_input<T>(&mut self) -> Result<T>

0 commit comments

Comments
 (0)