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
78 commits
Select commit Hold shift + click to select a range
9a0da02
save
agryaznov May 19, 2022
da608cb
builds and old tests pass
agryaznov May 21, 2022
e15f881
type names enhanced
agryaznov May 22, 2022
78fa5d5
Merge branch 'master' into ag-transparent-hashing
agryaznov May 22, 2022
ceb1588
VarSizedKey bounded to new Config param
agryaznov May 22, 2022
ea8c5be
improved wasm runtime updated funcs
agryaznov May 22, 2022
7d5a613
unstable-interface tests fixed
agryaznov May 22, 2022
0d8206c
benchmarks fixed
agryaznov May 22, 2022
e1a735f
Apply suggestions from code review
agryaznov May 24, 2022
e195d5c
fixes on feedback
agryaznov May 24, 2022
1534c24
Merge branch 'ag-transparent-hashing' of github.com:paritytech/substr…
agryaznov May 24, 2022
b6c2915
Merge branch 'master' into ag-transparent-hashing
agryaznov May 24, 2022
cb01583
fixes on feedback applied + make it build
agryaznov May 25, 2022
75fadc8
benchmarks build but fail (old)
agryaznov May 25, 2022
7a8ea0f
"Original code too large"
agryaznov May 25, 2022
4d548c8
seal_clear_storage bench fixed (code size workaround hack removal tbd)
agryaznov May 25, 2022
ed3539c
bench_seal_clear_storage pass
agryaznov May 27, 2022
86b9275
bench_seal_take_storage ... ok
agryaznov May 27, 2022
a0ffe4b
added new seal_set_storage + updated benchmarks
agryaznov May 27, 2022
01db020
added new seal_get_storage + updated benchmarks
agryaznov May 27, 2022
67ee754
added new seal_contains_storage + updated benchmarks
agryaznov May 27, 2022
25f4e85
added tests for _transparent exec functions
agryaznov May 27, 2022
036c4a0
Merge branch 'master' into ag-transparent-hashing
agryaznov May 27, 2022
970f8b7
wasm test for clear_storage
agryaznov May 30, 2022
d9206b4
Merge branch 'master' into ag-transparent-hashing
agryaznov May 30, 2022
840488a
wasm test for take_storage
agryaznov May 30, 2022
d1068d8
wasm test for new set_storage
agryaznov May 30, 2022
c7663fc
wasm test for new get_storage
agryaznov May 31, 2022
a38bda6
wasm test for new contains_storage
agryaznov May 31, 2022
1e47811
Merge branch 'master' into ag-transparent-hashing
agryaznov May 31, 2022
a2f5143
CI fix
agryaznov May 31, 2022
76fbbb0
ci fix
agryaznov May 31, 2022
7b76ea9
ci fix
agryaznov May 31, 2022
d5d4bae
ci fix
agryaznov May 31, 2022
f79d9d7
Merge branch 'master' of https://github.com/paritytech/substrate into…
Jun 7, 2022
f35dccd
cargo run --quiet --profile=production --features=runtime-benchmarks…
Jun 7, 2022
954c185
fixes according to the review feedback
agryaznov Jun 9, 2022
513c256
Merge branch 'master' into ag-transparent-hashing
agryaznov Jun 9, 2022
c429e99
tests & benchmarks fixed
agryaznov Jun 9, 2022
abc1a22
Merge branch 'ag-transparent-hashing' of github.com:paritytech/substr…
agryaznov Jun 9, 2022
bfb1550
Merge branch 'master' of https://github.com/paritytech/substrate into…
Jun 10, 2022
f6336eb
cargo run --quiet --profile=production --features=runtime-benchmarks…
Jun 10, 2022
7b3ddf8
refactoring
agryaznov Jun 11, 2022
7b99cb4
Merge branch 'master' into ag-transparent-hashing
agryaznov Jun 11, 2022
62735c2
fix to runtime api
agryaznov Jun 11, 2022
d5f240c
ci fix
agryaznov Jun 11, 2022
929ec62
ctx.get_storage() factored out
agryaznov Jun 14, 2022
e81d2c2
ctx.contains_storage() factored out
agryaznov Jun 14, 2022
52a6982
number of batches reduced for transparent hashing storage benchmarks
agryaznov Jun 14, 2022
8a5ce46
Merge branch 'master' into ag-transparent-hashing
agryaznov Jun 14, 2022
456f4c9
contracts RPC & pallet::get_storage to use transparent hashing
agryaznov Jun 14, 2022
e99e7a9
Merge branch 'master' into ag-transparent-hashing
agryaznov Jun 21, 2022
2b764ff
node and rpc updated to use get_storage with VarSizedKey
agryaznov Jun 21, 2022
4652e6f
refactored (more concize)
agryaznov Jun 21, 2022
4ff9bf3
refactored contains_storage (DRYed)
agryaznov Jun 21, 2022
5f28ab8
refactored contains_storage (DRYed)
agryaznov Jun 21, 2022
744bf2e
Merge branch 'master' into ag-transparent-hashing
agryaznov Jun 21, 2022
2e59a8e
fix rpc
agryaznov Jun 21, 2022
c582cff
fmt fix
agryaznov Jun 21, 2022
a5c2659
more fixes in rpc
agryaznov Jun 21, 2022
205d428
rollback `Pallet:get_storage` to Vec<u8> and rpc and node parts relat…
agryaznov Jun 21, 2022
cb6945b
added `KeyDecodingFailed` error
agryaznov Jun 21, 2022
72682de
Revert weird "fmt fix"
agryaznov Jun 21, 2022
23d2209
node-executor basic test update
agryaznov Jun 21, 2022
a7c58b4
fix node-executor basic test
agryaznov Jun 21, 2022
0497517
benchmarks fix
agryaznov Jun 22, 2022
13777b3
more benchmarks fix
agryaznov Jun 22, 2022
12c246e
FixedSizedKey is hidden from pub, VarSizedKey is exported as StorageKey
agryaznov Jun 22, 2022
b91af13
ci fix
agryaznov Jun 22, 2022
591b4b7
set_storage benchmark fix
agryaznov Jun 22, 2022
5802637
ci fix
agryaznov Jun 22, 2022
d95fe82
ci fix
agryaznov Jun 22, 2022
d659578
comments improved
agryaznov Jun 22, 2022
ada2139
new error code to rpc: KEY_DECODING_FAILED
agryaznov Jun 22, 2022
3f578bd
Put `rusty-cachier` before PR merge into `master` for `cargo-check-be…
rcny Jun 22, 2022
363ac54
Merge branch 'vi-fix-cargo-check-benches-ordering' into ag-transparen…
agryaznov Jun 22, 2022
b19f503
cargo run --quiet --profile=production --features=runtime-benchmarks…
Jun 22, 2022
f34676c
minor optimization
agryaznov Jun 23, 2022
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
fixes on feedback applied + make it build
  • Loading branch information
agryaznov committed May 25, 2022
commit cb01583d21c81cb7f899f935b12d5aa234c96551
25 changes: 15 additions & 10 deletions frame/contracts/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use crate::{
use frame_support::{
crypto::ecdsa::ECDSAExt,
dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable},
pallet_prelude::ConstU32,
storage::{with_transaction, TransactionOutcome},
traits::{Contains, Currency, ExistenceRequirement, OriginTrait, Randomness, Time},
weights::Weight,
Expand All @@ -50,17 +49,23 @@ pub type TopicOf<T> = <T as frame_system::Config>::Hash;
pub type FixSizedKey = [u8; 32];
pub type VarSizedKey<T> = BoundedVec<u8, <T as Config>::MaxStorageKeyLen>;

pub trait StorageHash {
pub trait StorageHash<T>
where
T: Config,
{
fn hash(self) -> Vec<u8>;
}

impl StorageHash for FixSizedKey {
impl<T: Config> StorageHash<T> for FixSizedKey {
fn hash(self) -> Vec<u8> {
blake2_256(self.as_slice()).to_vec()
}
}

impl StorageHash for VarSizedKey {
impl<T> StorageHash<T> for VarSizedKey<T>
where
T: Config,
{
fn hash(self) -> Vec<u8> {
Blake2_128Concat::hash(self.as_slice())
}
Expand Down Expand Up @@ -168,7 +173,7 @@ pub trait Ext: sealing::Sealed {
///
/// Returns `None` if the `key` wasn't previously set by `set_storage` or
/// was deleted.
fn get_storage_transparent(&mut self, key: VarSizedKey) -> Option<Vec<u8>>;
fn get_storage_transparent(&mut self, key: VarSizedKey<Self::T>) -> Option<Vec<u8>>;

/// Returns `Some(len)` (in bytes) if a storage item exists at `key`.
///
Expand All @@ -182,7 +187,7 @@ pub trait Ext: sealing::Sealed {
///
/// Returns `None` if the `key` wasn't previously set by `set_storage` or
/// was deleted.
fn get_storage_size_transparent(&mut self, key: VarSizedKey) -> Option<u32>;
fn get_storage_size_transparent(&mut self, key: VarSizedKey<Self::T>) -> Option<u32>;

/// Sets the storage entry by the given key to the specified value. If `value` is `None` then
/// the storage entry is deleted.
Expand All @@ -196,7 +201,7 @@ pub trait Ext: sealing::Sealed {
///
fn set_storage_transparent(
&mut self,
key: VarSizedKey,
key: VarSizedKey<Self::T>,
value: Option<Vec<u8>>,
take_old: bool,
) -> Result<WriteOutcome, DispatchError>;
Expand Down Expand Up @@ -1133,15 +1138,15 @@ where
Storage::<T>::read(&self.top_frame_mut().contract_info().trie_id, key)
}

fn get_storage_transparent(&mut self, key: VarSizedKey) -> Option<Vec<u8>> {
fn get_storage_transparent(&mut self, key: VarSizedKey<T>) -> Option<Vec<u8>> {
Storage::<T>::read(&self.top_frame_mut().contract_info().trie_id, key)
}

fn get_storage_size(&mut self, key: FixSizedKey) -> Option<u32> {
Storage::<T>::size(&self.top_frame_mut().contract_info().trie_id, key)
}

fn get_storage_size_transparent(&mut self, key: VarSizedKey) -> Option<u32> {
fn get_storage_size_transparent(&mut self, key: VarSizedKey<T>) -> Option<u32> {
Storage::<T>::size(&self.top_frame_mut().contract_info().trie_id, key)
}

Expand All @@ -1163,7 +1168,7 @@ where

fn set_storage_transparent(
&mut self,
key: VarSizedKey,
key: VarSizedKey<T>,
value: Option<Vec<u8>>,
take_old: bool,
) -> Result<WriteOutcome, DispatchError> {
Expand Down
2 changes: 1 addition & 1 deletion frame/contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ where
}

/// Query storage of a specified contract under a specified key.
pub fn get_storage<K: StorageHash>(address: T::AccountId, key: K) -> GetStorageResult {
pub fn get_storage<K: StorageHash<T>>(address: T::AccountId, key: K) -> GetStorageResult {
let contract_info =
ContractInfoOf::<T>::get(&address).ok_or(ContractAccessError::DoesntExist)?;

Expand Down
6 changes: 3 additions & 3 deletions frame/contracts/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,15 @@ where
///
/// The read is performed from the `trie_id` only. The `address` is not necessary. If the
/// contract doesn't store under the given `key` `None` is returned.
pub fn read<K: StorageHash>(trie_id: &TrieId, key: K) -> Option<Vec<u8>> {
pub fn read<K: StorageHash<T>>(trie_id: &TrieId, key: K) -> Option<Vec<u8>> {
child::get_raw(&child_trie_info(trie_id), key.hash().as_slice())
}

/// Returns `Some(len)` (in bytes) if a storage item exists at `key`.
///
/// Returns `None` if the `key` wasn't previously set by `set_storage` or
/// was deleted.
pub fn size<K: StorageHash>(trie_id: &TrieId, key: K) -> Option<u32> {
pub fn size<K: StorageHash<T>>(trie_id: &TrieId, key: K) -> Option<u32> {
child::len(&child_trie_info(trie_id), key.hash().as_slice())
}

Expand All @@ -142,7 +142,7 @@ where
///
/// This function also records how much storage was created or removed if a `storage_meter`
/// is supplied. It should only be absent for testing or benchmarking code.
pub fn write<K: StorageHash>(
pub fn write<K: StorageHash<T>>(
trie_id: &TrieId,
key: K,
new_value: Option<Vec<u8>>,
Expand Down
73 changes: 41 additions & 32 deletions frame/contracts/src/wasm/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::{

use bitflags::bitflags;
use codec::{Decode, DecodeAll, Encode, MaxEncodedLen};
use frame_support::{dispatch::DispatchError, ensure, weights::Weight};
use frame_support::{dispatch::DispatchError, ensure, traits::Get, weights::Weight};
use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags};
use sp_core::{crypto::UncheckedFrom, Bytes};
use sp_io::hashing::{blake2_128, blake2_256, keccak_256, sha2_256};
Expand All @@ -41,7 +41,7 @@ use wasm_instrument::parity_wasm::elements::ValueType;
/// VarSized is a key used for transparent hashing, which is a u8 vector maximum length of
/// MaxStorageKeyLen.
enum KeyType {
Fixed,
Fix,
Variable(u32),
}

Expand Down Expand Up @@ -707,7 +707,6 @@ where
&mut self,
key_type: KeyType,
key_ptr: u32,
key_len: u32,
value_ptr: u32,
value_len: u32,
) -> Result<u32, TrapReason> {
Expand All @@ -717,19 +716,26 @@ where
if value_len > max_size {
return Err(Error::<E::T>::ValueTooLarge.into())
}

ensure!(key_len <= <E::T>::MaxStorageKeyLen, Error::<E::T>::DecodingFailed);
let key = self.read_sandbox_memory(key_ptr, key_len)?

let key_len = match key_type {
KeyType::Fix => 32u32,
KeyType::Variable(len) => {
ensure!(
len <= <E::T as Config>::MaxStorageKeyLen::get(),
Error::<E::T>::DecodingFailed
);
len
},
};
let key = self.read_sandbox_memory(key_ptr, key_len)?;
let value = Some(self.read_sandbox_memory(value_ptr, value_len)?);
let write_outcome = match key_type {
KeyType::FixSized => self.ext.set_storage(
KeyType::Fix => self.ext.set_storage(
FixSizedKey::try_from(key).map_err(|_| Error::<E::T>::DecodingFailed)?,
value,
false,
)?,
KeyType::VarSized => self.ext.set_storage_transparent(
VarSizedKey::try_from(key).map_err(|_| Error::<E::T>::DecodingFailed)?,
KeyType::Variable(_) => self.ext.set_storage_transparent(
VarSizedKey::<E::T>::try_from(key).map_err(|_| Error::<E::T>::DecodingFailed)?,
value,
false,
)?,
Expand All @@ -742,25 +748,27 @@ where
Ok(write_outcome.old_len_with_sentinel())
}

fn clear_storage(
&mut self,
key_type: KeyType,
key_ptr: u32,
key_len: u32,
) -> Result<u32, TrapReason> {
fn clear_storage(&mut self, key_type: KeyType, key_ptr: u32) -> Result<u32, TrapReason> {
let charged = self.charge_gas(RuntimeCosts::ClearStorage(self.ext.max_value_size()))?;

let mut key = vec![0; key_len.try_into().map_err(|_| Error::<E::T>::ValueTooLarge)?];
self.read_sandbox_memory_into_buf(key_ptr, &mut key)?;

let key_len = match key_type {
KeyType::Fix => 32u32,
KeyType::Variable(len) => {
ensure!(
len <= <E::T as Config>::MaxStorageKeyLen::get(),
Error::<E::T>::DecodingFailed
);
len
},
};
let key = self.read_sandbox_memory(key_ptr, key_len)?;
let outcome = match key_type {
KeyType::FixSized => self.ext.set_storage(
KeyType::Fix => self.ext.set_storage(
FixSizedKey::try_from(key).map_err(|_| Error::<E::T>::DecodingFailed)?,
None,
false,
)?,
KeyType::VarSized => self.ext.set_storage_transparent(
VarSizedKey::try_from(key).map_err(|_| Error::<E::T>::DecodingFailed)?,
KeyType::Variable(_) => self.ext.set_storage_transparent(
VarSizedKey::<E::T>::try_from(key).map_err(|_| Error::<E::T>::DecodingFailed)?,
None,
false,
)?,
Expand Down Expand Up @@ -908,7 +916,7 @@ define_env!(Env, <E: Ext>,
// Equivalent to the newer version of `seal_set_storage` with the exception of the return
// type. Still a valid thing to call when not interested in the return value.
[seal0] seal_set_storage(ctx, key_ptr: u32, value_ptr: u32, value_len: u32) => {
ctx.set_storage(KeyType::FixSized, key_ptr, 32u32, value_ptr, value_len).map(|_| ())
ctx.set_storage(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
},

// Set the value at the given key in the contract storage.
Expand All @@ -927,29 +935,30 @@ define_env!(Env, <E: Ext>,
// Returns the size of the pre-existing value at the specified key if any. Otherwise
// `SENTINEL` is returned as a sentinel value.
[seal1] seal_set_storage(ctx, key_ptr: u32, value_ptr: u32, value_len: u32) -> u32 => {
ctx.set_storage(KeyType::FixSized, key_ptr, 32u32, value_ptr, value_len)
ctx.set_storage(KeyType::Fix, key_ptr, value_ptr, value_len)
},

// Clear the value at the given key in the contract storage.
//
// Equivalent to the newer version of `seal_clear_storage` with the exception of the return
// type. Still a valid thing to call when not interested in the return value.
[seal0] seal_clear_storage(ctx, key_ptr: u32) => {
ctx.clear_storage(KeyType::FixSized, key_ptr, 32u32).map(|_| ()).map_err(Into::into)
ctx.clear_storage(KeyType::Fix, key_ptr).map(|_| ()).map_err(Into::into)
},

// Clear the value at the given key in the contract storage.
//
// # Parameters
//
// - `key_ptr`: pointer into the linear memory where the location to clear the value is placed.
// - `key_ptr`: pointer into the linear memory where the key is placed.
// - `key_len`: the length of the key in bytes.
//
// # Return Value
//
// Returns the size of the pre-existing value at the specified key if any. Otherwise
// `SENTINEL` is returned as a sentinel value.
[__unstable__] seal_clear_storage(ctx, key_ptr: u32) -> u32 => {
ctx.clear_storage(KeyType::FixSized, key_ptr, 32u32).map_err(Into::into)
[__unstable__] seal_clear_storage(ctx, key_ptr: u32, key_len: u32) -> u32 => {
ctx.clear_storage(KeyType::Variable(key_len), key_ptr).map_err(Into::into)
},

// Retrieve the value under the given key from storage.
Expand Down Expand Up @@ -1006,17 +1015,17 @@ define_env!(Env, <E: Ext>,
// # Parameters
//
// - `key_ptr`: pointer into the linear memory where the key of the requested value is placed.
// - `key_len`: the length of the key in bytes.
// - `out_ptr`: pointer to the linear memory where the value is written to.
// - `out_len_ptr`: in-out pointer into linear memory where the buffer length
// is read from and the value length is written to.
//
// # Errors
//
// `ReturnCode::KeyNotFound`
[__unstable__] seal_take_storage(ctx, key_ptr: u32, out_ptr: u32, out_len_ptr: u32) -> ReturnCode => {
[__unstable__] seal_take_storage(ctx, key_ptr: u32, key_len: u32, out_ptr: u32, out_len_ptr: u32) -> ReturnCode => {
let charged = ctx.charge_gas(RuntimeCosts::TakeStorage(ctx.ext.max_value_size()))?;
let mut key = FixSizedKey::default();
ctx.read_sandbox_memory_into_buf(key_ptr, &mut key)?;
let key = ctx.read_sandbox_memory(key_ptr, key_len)?;
if let crate::storage::WriteOutcome::Taken(value) = ctx.ext.set_storage(key, None, true)? {
ctx.adjust_gas(charged, RuntimeCosts::TakeStorage(value.len() as u32));
ctx.write_sandbox_output(out_ptr, out_len_ptr, &value, false, already_charged)?;
Expand Down