mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-21 22:41:02 +00:00
Move double map to support module and generalize it (#1379)
* Move double map to support and generalize it * add docs back * reduces the number of required allocations
This commit is contained in:
@@ -17,11 +17,10 @@
|
|||||||
//! Auxilliaries to help with managing partial changes to accounts state.
|
//! Auxilliaries to help with managing partial changes to accounts state.
|
||||||
|
|
||||||
use super::{CodeOf, StorageOf, Trait};
|
use super::{CodeOf, StorageOf, Trait};
|
||||||
use double_map::StorageDoubleMap;
|
|
||||||
use rstd::cell::RefCell;
|
use rstd::cell::RefCell;
|
||||||
use rstd::collections::btree_map::{BTreeMap, Entry};
|
use rstd::collections::btree_map::{BTreeMap, Entry};
|
||||||
use rstd::prelude::*;
|
use rstd::prelude::*;
|
||||||
use runtime_support::StorageMap;
|
use runtime_support::{StorageMap, StorageDoubleMap};
|
||||||
use {balances, system};
|
use {balances, system};
|
||||||
|
|
||||||
pub struct ChangeEntry<T: Trait> {
|
pub struct ChangeEntry<T: Trait> {
|
||||||
|
|||||||
@@ -84,7 +84,6 @@ extern crate assert_matches;
|
|||||||
extern crate wabt;
|
extern crate wabt;
|
||||||
|
|
||||||
mod account_db;
|
mod account_db;
|
||||||
mod double_map;
|
|
||||||
mod exec;
|
mod exec;
|
||||||
mod vm;
|
mod vm;
|
||||||
mod gas;
|
mod gas;
|
||||||
@@ -94,15 +93,15 @@ mod tests;
|
|||||||
|
|
||||||
use exec::ExecutionContext;
|
use exec::ExecutionContext;
|
||||||
use account_db::{AccountDb, OverlayAccountDb};
|
use account_db::{AccountDb, OverlayAccountDb};
|
||||||
use double_map::StorageDoubleMap;
|
|
||||||
|
|
||||||
use rstd::prelude::*;
|
use rstd::prelude::*;
|
||||||
use rstd::marker::PhantomData;
|
use rstd::marker::PhantomData;
|
||||||
use codec::{Codec, HasCompact};
|
use codec::{Codec, HasCompact};
|
||||||
use runtime_primitives::traits::{Hash, As, SimpleArithmetic};
|
use runtime_primitives::traits::{Hash, As, SimpleArithmetic};
|
||||||
use runtime_support::dispatch::Result;
|
use runtime_support::dispatch::Result;
|
||||||
use runtime_support::{Parameter, StorageMap, StorageValue};
|
use runtime_support::{Parameter, StorageMap, StorageValue, StorageDoubleMap};
|
||||||
use system::ensure_signed;
|
use system::ensure_signed;
|
||||||
|
use runtime_io::{blake2_256, twox_128};
|
||||||
|
|
||||||
pub trait Trait: balances::Trait {
|
pub trait Trait: balances::Trait {
|
||||||
/// Function type to get the contract address given the creator.
|
/// Function type to get the contract address given the creator.
|
||||||
@@ -302,11 +301,22 @@ decl_storage! {
|
|||||||
///
|
///
|
||||||
/// TODO: keys should also be able to take AsRef<KeyType> to ensure Vec<u8>s can be passed as &[u8]
|
/// TODO: keys should also be able to take AsRef<KeyType> to ensure Vec<u8>s can be passed as &[u8]
|
||||||
pub(crate) struct StorageOf<T>(::rstd::marker::PhantomData<T>);
|
pub(crate) struct StorageOf<T>(::rstd::marker::PhantomData<T>);
|
||||||
impl<T: Trait> double_map::StorageDoubleMap for StorageOf<T> {
|
impl<T: Trait> StorageDoubleMap for StorageOf<T> {
|
||||||
const PREFIX: &'static [u8] = b"con:sto:";
|
const PREFIX: &'static [u8] = b"con:sto:";
|
||||||
type Key1 = T::AccountId;
|
type Key1 = T::AccountId;
|
||||||
type Key2 = Vec<u8>;
|
type Key2 = Vec<u8>;
|
||||||
type Value = Vec<u8>;
|
type Value = Vec<u8>;
|
||||||
|
|
||||||
|
/// Hashed by XX
|
||||||
|
fn derive_key1(key1_data: Vec<u8>) -> Vec<u8> {
|
||||||
|
twox_128(&key1_data).to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Blake2 is used for `Key2` is because it will be used as a key for contract's storage and
|
||||||
|
/// thus will be susceptible for a untrusted input.
|
||||||
|
fn derive_key2(key2_data: Vec<u8>) -> Vec<u8> {
|
||||||
|
blake2_256(&key2_data).to_vec()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Trait> balances::OnFreeBalanceZero<T::AccountId> for Module<T> {
|
impl<T: Trait> balances::OnFreeBalanceZero<T::AccountId> for Module<T> {
|
||||||
|
|||||||
@@ -14,12 +14,11 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use double_map::StorageDoubleMap;
|
|
||||||
use runtime_io::with_externalities;
|
use runtime_io::with_externalities;
|
||||||
use runtime_primitives::testing::{Digest, DigestItem, H256, Header};
|
use runtime_primitives::testing::{Digest, DigestItem, H256, Header};
|
||||||
use runtime_primitives::traits::{BlakeTwo256};
|
use runtime_primitives::traits::{BlakeTwo256};
|
||||||
use runtime_primitives::BuildStorage;
|
use runtime_primitives::BuildStorage;
|
||||||
use runtime_support::StorageMap;
|
use runtime_support::{StorageMap, StorageDoubleMap};
|
||||||
use substrate_primitives::{Blake2Hasher};
|
use substrate_primitives::{Blake2Hasher};
|
||||||
use system::{Phase, EventRecord};
|
use system::{Phase, EventRecord};
|
||||||
use wabt;
|
use wabt;
|
||||||
|
|||||||
+37
-37
@@ -15,36 +15,10 @@
|
|||||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! An implementation of double map backed by storage.
|
//! An implementation of double map backed by storage.
|
||||||
//!
|
|
||||||
//! This implementation is somewhat specialized to the tracking of the storage of accounts.
|
|
||||||
|
|
||||||
use rstd::prelude::*;
|
use rstd::prelude::*;
|
||||||
use codec::{Codec, Encode};
|
use codec::{Codec, Encode};
|
||||||
use runtime_support::storage::unhashed;
|
use storage::unhashed;
|
||||||
use runtime_io::{blake2_256, twox_128};
|
|
||||||
|
|
||||||
/// Returns only a first part of the storage key.
|
|
||||||
///
|
|
||||||
/// Hashed by XX.
|
|
||||||
fn first_part_of_key<M: StorageDoubleMap + ?Sized>(k1: M::Key1) -> [u8; 16] {
|
|
||||||
let mut raw_prefix = Vec::new();
|
|
||||||
raw_prefix.extend(M::PREFIX);
|
|
||||||
raw_prefix.extend(Encode::encode(&k1));
|
|
||||||
twox_128(&raw_prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a compound key that consist of the two parts: (prefix, `k1`) and `k2`.
|
|
||||||
///
|
|
||||||
/// The first part is hased by XX and then concatenated with a blake2 hash of `k2`.
|
|
||||||
fn full_key<M: StorageDoubleMap + ?Sized>(k1: M::Key1, k2: M::Key2) -> Vec<u8> {
|
|
||||||
let first_part = first_part_of_key::<M>(k1);
|
|
||||||
let second_part = blake2_256(&Encode::encode(&k2));
|
|
||||||
|
|
||||||
let mut k = Vec::new();
|
|
||||||
k.extend(&first_part);
|
|
||||||
k.extend(&second_part);
|
|
||||||
k
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An implementation of a map with a two keys.
|
/// An implementation of a map with a two keys.
|
||||||
///
|
///
|
||||||
@@ -54,11 +28,8 @@ fn full_key<M: StorageDoubleMap + ?Sized>(k1: M::Key1, k2: M::Key2) -> Vec<u8> {
|
|||||||
/// # Mapping of keys to a storage path
|
/// # Mapping of keys to a storage path
|
||||||
///
|
///
|
||||||
/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts.
|
/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts.
|
||||||
/// The first part is a XX hash of a concatenation of the `PREFIX` and `Key1`. And the second part
|
/// The first part is a hash of a concatenation of the `PREFIX` and `Key1`. And the second part
|
||||||
/// is a blake2 hash of a `Key2`.
|
/// is a hash of a `Key2`.
|
||||||
///
|
|
||||||
/// Blake2 is used for `Key2` is because it will be used as a key for contract's storage and
|
|
||||||
/// thus will be susceptible for a untrusted input.
|
|
||||||
pub trait StorageDoubleMap {
|
pub trait StorageDoubleMap {
|
||||||
type Key1: Codec;
|
type Key1: Codec;
|
||||||
type Key2: Codec;
|
type Key2: Codec;
|
||||||
@@ -68,28 +39,57 @@ pub trait StorageDoubleMap {
|
|||||||
|
|
||||||
/// Insert an entry into this map.
|
/// Insert an entry into this map.
|
||||||
fn insert(k1: Self::Key1, k2: Self::Key2, val: Self::Value) {
|
fn insert(k1: Self::Key1, k2: Self::Key2, val: Self::Value) {
|
||||||
unhashed::put(&full_key::<Self>(k1, k2)[..], &val);
|
unhashed::put(&Self::full_key(k1, k2)[..], &val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove an entry from this map.
|
/// Remove an entry from this map.
|
||||||
fn remove(k1: Self::Key1, k2: Self::Key2) {
|
fn remove(k1: Self::Key1, k2: Self::Key2) {
|
||||||
unhashed::kill(&full_key::<Self>(k1, k2)[..]);
|
unhashed::kill(&Self::full_key(k1, k2)[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an entry from this map.
|
/// Get an entry from this map.
|
||||||
///
|
///
|
||||||
/// If there is entry stored under the given keys, returns `None`.
|
/// If there is entry stored under the given keys, returns `None`.
|
||||||
fn get(k1: Self::Key1, k2: Self::Key2) -> Option<Self::Value> {
|
fn get(k1: Self::Key1, k2: Self::Key2) -> Option<Self::Value> {
|
||||||
unhashed::get(&full_key::<Self>(k1, k2)[..])
|
unhashed::get(&Self::full_key(k1, k2)[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if value under the specified keys exists.
|
/// Returns `true` if value under the specified keys exists.
|
||||||
fn exists(k1: Self::Key1, k2: Self::Key2) -> bool {
|
fn exists(k1: Self::Key1, k2: Self::Key2) -> bool {
|
||||||
unhashed::exists(&full_key::<Self>(k1, k2)[..])
|
unhashed::exists(&Self::full_key(k1, k2)[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes all entries that shares the `k1` as the first key.
|
/// Removes all entries that shares the `k1` as the first key.
|
||||||
fn remove_prefix(k1: Self::Key1) {
|
fn remove_prefix(k1: Self::Key1) {
|
||||||
unhashed::kill_prefix(&first_part_of_key::<Self>(k1))
|
unhashed::kill_prefix(&Self::derive_key1(Self::encode_key1(k1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encode key1 into Vec<u8> and prepend a prefix
|
||||||
|
fn encode_key1(key: Self::Key1) -> Vec<u8> {
|
||||||
|
let mut raw_prefix = Vec::new();
|
||||||
|
raw_prefix.extend(Self::PREFIX);
|
||||||
|
raw_prefix.extend(Encode::encode(&key));
|
||||||
|
raw_prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encode key2 into Vec<u8>
|
||||||
|
fn encode_key2(key: Self::Key2) -> Vec<u8> {
|
||||||
|
Encode::encode(&key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Derive the first part of the key
|
||||||
|
fn derive_key1(key1_data: Vec<u8>) -> Vec<u8>;
|
||||||
|
|
||||||
|
/// Derive the remaining part of the key
|
||||||
|
fn derive_key2(key2_data: Vec<u8>) -> Vec<u8>;
|
||||||
|
|
||||||
|
/// Returns a compound key that consist of the two parts: (prefix, `k1`) and `k2`.
|
||||||
|
/// The first part is hased and then concatenated with a hash of `k2`.
|
||||||
|
fn full_key(k1: Self::Key1, k2: Self::Key2) -> Vec<u8> {
|
||||||
|
let key1_data = Self::encode_key1(k1);
|
||||||
|
let key2_data = Self::encode_key2(k2);
|
||||||
|
let mut key = Self::derive_key1(key1_data);
|
||||||
|
key.extend(Self::derive_key2(key2_data));
|
||||||
|
key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,12 +67,14 @@ pub mod metadata;
|
|||||||
mod runtime;
|
mod runtime;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod inherent;
|
pub mod inherent;
|
||||||
|
mod double_map;
|
||||||
|
|
||||||
pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap};
|
pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap};
|
||||||
pub use self::hashable::Hashable;
|
pub use self::hashable::Hashable;
|
||||||
pub use self::dispatch::{Parameter, Dispatchable, Callable, IsSubType};
|
pub use self::dispatch::{Parameter, Dispatchable, Callable, IsSubType};
|
||||||
pub use self::metadata::RuntimeMetadata;
|
pub use self::metadata::RuntimeMetadata;
|
||||||
pub use runtime_io::print;
|
pub use runtime_io::print;
|
||||||
|
pub use double_map::StorageDoubleMap;
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use srml_support_procedural::decl_storage;
|
pub use srml_support_procedural::decl_storage;
|
||||||
|
|||||||
Reference in New Issue
Block a user