diff --git a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs index ec9be8e465..1b550edffa 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs @@ -17,7 +17,9 @@ //! Endian manager. /// Trait to allow conversion to a know endian representation when sensitive. -// note: the copy bound and static lifetimes are necessary for safety of `Slicable` blanket implementation. +/// Types implementing this trait must have a size > 0. +// note: the copy bound and static lifetimes are necessary for safety of `Slicable` blanket +// implementation. pub trait EndianSensitive: Copy + 'static { fn to_le(self) -> Self { self } fn to_be(self) -> Self { self } diff --git a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs index 3ac3d880e4..0f1ef812a6 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs @@ -49,6 +49,7 @@ pub trait NonTrivialSlicable: Slicable {} impl Slicable for T { fn set_as_slice bool>(fill_slice: &F) -> Option { let size = mem::size_of::(); + assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); let mut result: T = unsafe { mem::zeroed() }; let result_slice = unsafe { let ptr = &mut result as *mut _ as *mut u8; @@ -62,6 +63,7 @@ impl Slicable for T { } fn as_slice_then R>(&self, f: F) -> R { let size = mem::size_of::(); + assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); self.as_le_then(|le| { let value_slice = unsafe { let ptr = le as *const _ as *const u8; diff --git a/substrate/wasm-runtime/polkadot/src/primitives/function.rs b/substrate/wasm-runtime/polkadot/src/primitives/function.rs index 35273e2cfa..e906cdc718 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/function.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/function.rs @@ -37,15 +37,14 @@ pub enum Function { impl Function { /// Derive `Some` value from a `u8`, or `None` if it's invalid. pub fn from_u8(value: u8) -> Option { - match value { - x if x == Function::StakingStake as u8 => Some(Function::StakingStake), - x if x == Function::StakingUnstake as u8 => Some(Function::StakingUnstake), - x if x == Function::StakingTransfer as u8 => Some(Function::StakingTransfer), - x if x == Function::SessionSetKey as u8 => Some(Function::SessionSetKey), - x if x == Function::TimestampSet as u8 => Some(Function::TimestampSet), - x if x == Function::GovernancePropose as u8 => Some(Function::GovernancePropose), - x if x == Function::GovernanceApprove as u8 => Some(Function::GovernanceApprove), - _ => None, + use self::*; + let functions = [Function::StakingStake, Function::StakingUnstake, + Function::StakingTransfer, Function::SessionSetKey, Function::TimestampSet, + Function::GovernancePropose, Function::GovernanceApprove]; + if (value as usize) < functions.len() { + Some(functions[value as usize]) + } else { + None } } } diff --git a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs index 33539c2f17..1b8aa6b13e 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs @@ -38,14 +38,19 @@ pub enum InternalFunction { impl InternalFunction { /// Derive `Some` value from a `u8`, or `None` if it's invalid. pub fn from_u8(value: u8) -> Option { - match value { - x if x == InternalFunction::SystemSetCode as u8 => Some(InternalFunction::SystemSetCode), - x if x == InternalFunction::StakingSetSessionsPerEra as u8 => Some(InternalFunction::StakingSetSessionsPerEra), - x if x == InternalFunction::StakingSetBondingDuration as u8 => Some(InternalFunction::StakingSetBondingDuration), - x if x == InternalFunction::StakingSetValidatorCount as u8 => Some(InternalFunction::StakingSetValidatorCount), - x if x == InternalFunction::GovernanceSetApprovalPpmRequired as u8 => Some(InternalFunction::GovernanceSetApprovalPpmRequired), - x if x == InternalFunction::SessionSetLength as u8 => Some(InternalFunction::SessionSetLength), - _ => None, + use self::*; + let functions = [ + InternalFunction::SystemSetCode, + InternalFunction::StakingSetSessionsPerEra, + InternalFunction::StakingSetBondingDuration, + InternalFunction::StakingSetValidatorCount, + InternalFunction::GovernanceSetApprovalPpmRequired, + InternalFunction::SessionSetLength + ]; + if (value as usize) < functions.len() { + Some(functions[value as usize]) + } else { + None } } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index 4b78e4944f..b811daf1c2 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -27,14 +27,14 @@ use runtime_std::prelude::*; use codec::KeyedVec; -use support::{Storable, StorageVec, kill}; +use support::storage; use primitives::{AccountID, Hash, BlockNumber, Proposal}; use runtime::{staking, system, session}; /// The proportion of validators required for a propsal to be approved measured as the number out /// of 1000. pub fn approval_ppm_required() -> u32 { - Storable::lookup(b"gov:apr").unwrap_or(1000) + storage::get_or(b"gov:apr", 1000) } /// The number of concrete validator approvals required for a proposal to pass. @@ -49,10 +49,10 @@ pub mod public { /// Proposal is by the `transactor` and will automatically count as an approval. Transactor must /// be a current validator. It is illegal to propose when there is already a proposal in effect. pub fn propose(validator: &AccountID, proposal: &Proposal) { - if Proposal::lookup(b"gov:pro").is_some() { + if storage::exists(b"gov:pro") { panic!("there may only be one proposal per era."); } - proposal.store(b"gov:pro"); + storage::put(b"gov:pro", proposal); approve(validator, staking::current_era()); } @@ -62,17 +62,17 @@ pub mod public { if era_index != staking::current_era() { panic!("approval vote applied on non-current era.") } - if Proposal::lookup(b"gov:pro").is_none() { + if !storage::exists(b"gov:pro") { panic!("there must be a proposal in order to approve."); } if session::validators().into_iter().position(|v| &v == validator).is_none() { panic!("transactor must be a validator to approve."); } let key = validator.to_keyed_vec(b"gov:app:"); - if bool::lookup(&key).is_some() { + if storage::exists(&key) { panic!("transactor may not approve a proposal twice in one era."); } - true.store(&key); + storage::put(&key, &true); } } @@ -84,7 +84,7 @@ pub mod privileged { /// validator. `1000` would require the approval of all validators; `667` would require two-thirds /// (or there abouts) of validators. pub fn set_approval_ppm_required(ppm: u32) { - ppm.store(b"gov:apr"); + storage::put(b"gov:apr", &ppm); } } @@ -94,11 +94,10 @@ pub mod internal { /// Current era is ending; we should finish up any proposals. pub fn end_of_an_era() { // tally up votes for the current proposal, if any. enact if there are sufficient approvals. - if let Some(proposal) = Proposal::lookup(b"gov:pro") { - kill(b"gov:pro"); + if let Some(proposal) = storage::take::(b"gov:pro") { let approvals_required = approvals_required(); let approved = session::validators().into_iter() - .filter_map(|v| bool::take(&v.to_keyed_vec(b"gov:app:"))) + .filter_map(|v| storage::take::(&v.to_keyed_vec(b"gov:app:"))) .take(approvals_required as usize) .count() as u32; if approved == approvals_required { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index c88aabbbe6..9322653d20 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -19,7 +19,7 @@ use runtime_std::prelude::*; use codec::KeyedVec; -use support::{kill, Storable, StorageVec}; +use support::{storage, StorageVec}; use primitives::{AccountID, SessionKey, BlockNumber}; use runtime::{system, staking, consensus}; @@ -30,7 +30,7 @@ pub fn validators() -> Vec { /// The number of blocks in each session. pub fn length() -> BlockNumber { - Storable::lookup_default(b"ses:len") + storage::get_or(b"ses:len", 0) } /// The number of validators currently. @@ -40,12 +40,12 @@ pub fn validator_count() -> usize { /// The current era index. pub fn current_index() -> BlockNumber { - Storable::lookup_default(b"ses:ind") + storage::get_or(b"ses:ind", 0) } /// The block number at which the era length last changed. pub fn last_length_change() -> BlockNumber { - Storable::lookup_default(b"ses:llc") + storage::get_or(b"ses:llc", 0) } pub mod public { @@ -55,7 +55,7 @@ pub mod public { /// session. pub fn set_key(validator: &AccountID, key: &SessionKey) { // set new value for next session - key.store(&validator.to_keyed_vec(b"ses:nxt:")); + storage::put(&validator.to_keyed_vec(b"ses:nxt:"), key); } } @@ -64,7 +64,7 @@ pub mod privileged { /// Set a new era length. Won't kick in until the next era change (at current length). pub fn set_length(new: BlockNumber) { - new.store(b"ses:nln"); + storage::put(b"ses:nln", &new); } } @@ -102,21 +102,20 @@ impl StorageVec for ValidatorStorageVec { /// Move onto next session: register the new authority set. fn rotate_session() { // Increment current session index. - (current_index() + 1).store(b"ses:ind"); + storage::put(b"ses:ind", &(current_index() + 1)); // Enact era length change. - if let Some(next_len) = u64::lookup(b"ses:nln") { - next_len.store(b"ses:len"); - system::block_number().store(b"ses:llc"); - kill(b"ses:nln"); + if let Some(next_len) = storage::get::(b"ses:nln") { + storage::put(b"ses:len", &next_len); + storage::put(b"ses:llc", &system::block_number()); + storage::kill(b"ses:nln"); } // Update any changes in session keys. validators().iter().enumerate().for_each(|(i, v)| { let k = v.to_keyed_vec(b"ses:nxt:"); - if let Some(n) = Storable::lookup(&k) { + if let Some(n) = storage::take(&k) { consensus::internal::set_authority(i as u32, &n); - kill(&k); } }); } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index b0e8a9ddaf..fbe1149f0a 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -19,7 +19,7 @@ use runtime_std::prelude::*; use runtime_std::cell::RefCell; use codec::KeyedVec; -use support::{Storable, StorageVec}; +use support::{storage, StorageVec}; use primitives::{BlockNumber, AccountID}; use runtime::{system, session, governance}; @@ -31,12 +31,12 @@ pub type Bondage = u64; /// The length of the bonding duration in eras. pub fn bonding_duration() -> BlockNumber { - Storable::lookup_default(b"sta:loc") + storage::get_default(b"sta:loc") } /// The length of a staking era in sessions. pub fn validator_count() -> usize { - u32::lookup_default(b"sta:vac") as usize + storage::get_default::(b"sta:vac") as usize } /// The length of a staking era in blocks. @@ -46,27 +46,27 @@ pub fn era_length() -> BlockNumber { /// The length of a staking era in sessions. pub fn sessions_per_era() -> BlockNumber { - Storable::lookup_default(b"sta:spe") + storage::get_default(b"sta:spe") } /// The current era index. pub fn current_era() -> BlockNumber { - Storable::lookup_default(b"sta:era") + storage::get_default(b"sta:era") } /// The block number at which the era length last changed. pub fn last_era_length_change() -> BlockNumber { - Storable::lookup_default(b"sta:lec") + storage::get_default(b"sta:lec") } /// The balance of a given account. pub fn balance(who: &AccountID) -> Balance { - Storable::lookup_default(&who.to_keyed_vec(b"sta:bal:")) + storage::get_default(&who.to_keyed_vec(b"sta:bal:")) } /// The liquidity-state of a given account. pub fn bondage(who: &AccountID) -> Bondage { - Storable::lookup_default(&who.to_keyed_vec(b"sta:bon:")) + storage::get_default(&who.to_keyed_vec(b"sta:bon:")) } // Each identity's stake may be in one of three bondage states, given by an integer: @@ -81,14 +81,14 @@ pub mod public { /// Transfer some unlocked staking balance to another staker. pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { let from_key = transactor.to_keyed_vec(b"sta:bal:"); - let from_balance = Balance::lookup_default(&from_key); + let from_balance = storage::get_default::(&from_key); assert!(from_balance >= value); let to_key = dest.to_keyed_vec(b"sta:bal:"); - let to_balance: Balance = Storable::lookup_default(&to_key); + let to_balance: Balance = storage::get_default(&to_key); assert!(bondage(transactor) <= bondage(dest)); assert!(to_balance + value > to_balance); // no overflow - (from_balance - value).store(&from_key); - (to_balance + value).store(&to_key); + storage::put(&from_key, &(from_balance - value)); + storage::put(&to_key, &(to_balance + value)); } /// Declare the desire to stake for the transactor. @@ -100,7 +100,7 @@ pub mod public { assert!(intentions.iter().find(|t| *t == transactor).is_none(), "Cannot stake if already staked."); intentions.push(transactor.clone()); IntentionStorageVec::set_items(&intentions); - u64::max_value().store(&transactor.to_keyed_vec(b"sta:bon:")); + storage::put(&transactor.to_keyed_vec(b"sta:bon:"), &u64::max_value()); } /// Retract the desire to stake for the transactor. @@ -114,7 +114,7 @@ pub mod public { panic!("Cannot unstake if not already staked."); } IntentionStorageVec::set_items(&intentions); - (current_era() + bonding_duration()).store(&transactor.to_keyed_vec(b"sta:bon:")); + storage::put(&transactor.to_keyed_vec(b"sta:bon:"), &(current_era() + bonding_duration())); } } @@ -123,17 +123,17 @@ pub mod privileged { /// Set the number of sessions in an era. pub fn set_sessions_per_era(new: BlockNumber) { - new.store(b"sta:nse"); + storage::put(b"sta:nse", &new); } /// The length of the bonding duration in eras. pub fn set_bonding_duration(new: BlockNumber) { - new.store(b"sta:loc"); + storage::put(b"sta:loc", &new); } /// The length of a staking era in sessions. pub fn set_validator_count(new: usize) { - (new as u32).store(b"sta:vac"); + storage::put(b"sta:vac", &(new as u32)); } } @@ -164,13 +164,13 @@ fn new_era() { governance::internal::end_of_an_era(); // Increment current era. - (current_era() + 1).store(b"sta:era"); + storage::put(b"sta:era", &(current_era() + 1)); // Enact era length change. - let next_spe: u64 = Storable::lookup_default(b"sta:nse"); + let next_spe: u64 = storage::get_default(b"sta:nse"); if next_spe > 0 && next_spe != sessions_per_era() { - next_spe.store(b"sta:spe"); - system::block_number().store(b"sta:lec"); + storage::put(b"sta:spe", &next_spe); + storage::put(b"sta:lec", &system::block_number()); } // evaluate desired staking amounts and nominations and optimise to find the best @@ -196,7 +196,7 @@ mod tests { use super::internal::*; use super::public::*; use super::privileged::*; - + use runtime_std::{with_externalities, twox_128}; use codec::{KeyedVec, Joiner}; use support::{one, two, TestExternalities, with_env}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 2327ffc3c4..b8610f0980 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -20,7 +20,7 @@ use runtime_std::prelude::*; use runtime_std::{mem, print}; use codec::KeyedVec; -use support::{Hashable, Storable, with_env}; +use support::{Hashable, storage, with_env}; use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder}; use runtime::{staking, session}; @@ -31,7 +31,7 @@ pub fn block_number() -> BlockNumber { /// Get the block hash of a given block (uses storage). pub fn block_hash(number: BlockNumber) -> Hash { - Storable::lookup_default(&number.to_keyed_vec(b"sys:old:")) + storage::get_default(&number.to_keyed_vec(b"sys:old:")) } pub mod privileged { @@ -39,7 +39,7 @@ pub mod privileged { /// Set the new code. pub fn set_code(new: &[u8]) { - new.store(b":code"); + storage::put_raw(b":code", new); } } @@ -77,7 +77,7 @@ pub mod internal { // store the header hash in storage. let header_hash_key = header.number.to_keyed_vec(b"sys:old:"); - header.blake2_256().store(&header_hash_key); + storage::put(&header_hash_key, &header.blake2_256()); // execute transactions block.transactions.iter().for_each(execute_transaction); @@ -102,11 +102,11 @@ pub mod internal { // check nonce let nonce_key = tx.signed.to_keyed_vec(b"sys:non:"); - let expected_nonce: TxOrder = Storable::lookup_default(&nonce_key); + let expected_nonce: TxOrder = storage::get_default(&nonce_key); assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); // increment nonce in storage - (expected_nonce + 1).store(&nonce_key); + storage::put(&nonce_key, &(expected_nonce + 1)); // decode parameters and dispatch tx.function.dispatch(&tx.signed, &tx.input_data); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 0f471f4a98..116b6b6bb5 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -16,14 +16,14 @@ //! Timestamp manager: just handles the current timestamp. -use support::Storable; +use support::storage; /// Representation of a time. pub type Timestamp = u64; /// Get the current time. pub fn get() -> Timestamp { - Storable::lookup_default(b"tim:val") + storage::get_default(b"tim:val") } pub mod public { @@ -31,7 +31,7 @@ pub mod public { /// Set the current time. pub fn set(now: Timestamp) { - now.store(b"tim:val") + storage::put(b"tim:val", &now); } } diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 854a8f9f01..6bc60880a0 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -17,7 +17,7 @@ //! Support code for the runtime. mod environment; -mod storable; +pub mod storage; mod hashable; #[cfg(feature = "with-std")] mod statichex; @@ -25,8 +25,8 @@ mod statichex; #[cfg(feature = "with-std")] mod testing; -pub use self::environment::{Environment, with_env}; -pub use self::storable::{StorageVec, Storable, kill}; +pub use self::environment::with_env; +pub use self::storage::StorageVec; pub use self::hashable::Hashable; #[cfg(feature = "with-std")] pub use self::statichex::{StaticHexConversion, StaticHexInto}; diff --git a/substrate/wasm-runtime/polkadot/src/support/storable.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs similarity index 50% rename from substrate/wasm-runtime/polkadot/src/support/storable.rs rename to substrate/wasm-runtime/polkadot/src/support/storage.rs index dc1a6fde2d..e21f41bfd4 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -20,60 +20,95 @@ use runtime_std::prelude::*; use runtime_std::{self, twox_128}; use codec::{Slicable, KeyedVec}; -/// Trait for a value which may be stored in the storage DB. -pub trait Storable { - /// Lookup the value in storage and deserialise, giving a default value if not found. - fn lookup_default(key: &[u8]) -> Self where Self: Sized + Default { - Self::lookup(key).unwrap_or_else(Default::default) - } - - /// Lookup `Some` value in storage and deserialise; `None` if it's not there. - fn lookup(_key: &[u8]) -> Option where Self: Sized { - unimplemented!() - } - - /// Retrives and returns the serialised value of a key from storage, removing it immediately. - fn take(key: &[u8]) -> Option where Self: Sized { - if let Some(value) = Self::lookup(key) { - kill(key); - Some(value) - } else { - None - } - } - - /// Place the value in storage under `key`. - fn store(&self, key: &[u8]); -} - // TODO: consider using blake256 to avoid possible preimage attack. -/// Remove `key` from storage. +/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. +pub fn get(key: &[u8]) -> Option { + Slicable::set_as_slice(&|out, offset| + runtime_std::read_storage(&twox_128(key)[..], out, offset) >= out.len() + ) +} + +/// Return the value of the item in storage under `key`, or the type's default if there is no +/// explicit entry. +pub fn get_default(key: &[u8]) -> T { + get(key).unwrap_or_else(Default::default) +} + +/// Return the value of the item in storage under `key`, or `default_value` if there is no +/// explicit entry. +pub fn get_or(key: &[u8], default_value: T) -> T { + get(key).unwrap_or(default_value) +} + +/// Return the value of the item in storage under `key`, or `default_value()` if there is no +/// explicit entry. +pub fn get_or_else T>(key: &[u8], default_value: F) -> T { + get(key).unwrap_or_else(default_value) +} + +/// Please `value` in storage under `key`. +pub fn put(key: &[u8], value: &T) { + value.as_slice_then(|slice| runtime_std::set_storage(&twox_128(key)[..], slice)); +} + +/// Please `value` in storage under `key`. +pub fn place(key: &[u8], value: T) { + value.as_slice_then(|slice| runtime_std::set_storage(&twox_128(key)[..], slice)); +} + +/// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. +pub fn take(key: &[u8]) -> Option { + let r = get(key); + if r.is_some() { + kill(key); + } + r +} + +/// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, +/// the default for its type. +pub fn take_default(key: &[u8]) -> T { + take(key).unwrap_or_else(Default::default) +} + +/// Return the value of the item in storage under `key`, or `default_value` if there is no +/// explicit entry. Ensure there is no explicit entry on return. +pub fn take_or(key: &[u8], default_value: T) -> T { + take(key).unwrap_or(default_value) +} + +/// Return the value of the item in storage under `key`, or `default_value()` if there is no +/// explicit entry. Ensure there is no explicit entry on return. +pub fn take_or_else T>(key: &[u8], default_value: F) -> T { + take(key).unwrap_or_else(default_value) +} + +/// Check to see if `key` has an explicit entry in storage. +pub fn exists(key: &[u8]) -> bool { + let mut x = [0u8; 1]; + runtime_std::read_storage(&twox_128(key)[..], &mut x[..], 0) == 1 +} + +/// Ensure `key` has no explicit entry in storage. pub fn kill(key: &[u8]) { runtime_std::set_storage(&twox_128(key)[..], b""); } -impl Storable for T { - fn lookup(key: &[u8]) -> Option { - Slicable::set_as_slice(&|out, offset| - runtime_std::read_storage(&twox_128(key)[..], out, offset) >= out.len() - ) - } - fn store(&self, key: &[u8]) { - self.as_slice_then(|slice| runtime_std::set_storage(&twox_128(key)[..], slice)); - } +/// Get a Vec of bytes from storage. +pub fn get_raw(key: &[u8]) -> Vec { + runtime_std::storage(&twox_128(key)[..]) } -impl Storable for [u8] { - fn store(&self, key: &[u8]) { - runtime_std::set_storage(&twox_128(key)[..], self) - } +/// Put a raw byte slice into storage. +pub fn put_raw(key: &[u8], value: &[u8]) { + runtime_std::set_storage(&twox_128(key)[..], value) } /// A trait to conveniently store a vector of storable data. // TODO: add iterator support pub trait StorageVec { - type Item: Default + Sized + Storable; + type Item: Default + Sized + Slicable; const PREFIX: &'static [u8]; /// Get the current set of items. @@ -88,20 +123,20 @@ pub trait StorageVec { } fn set_item(index: u32, item: &Self::Item) { - item.store(&index.to_keyed_vec(Self::PREFIX)); + put(&index.to_keyed_vec(Self::PREFIX), item); } fn item(index: u32) -> Self::Item { - Storable::lookup_default(&index.to_keyed_vec(Self::PREFIX)) + get_default(&index.to_keyed_vec(Self::PREFIX)) } fn set_count(count: u32) { (count..Self::count()).for_each(|i| Self::set_item(i, &Self::Item::default())); - count.store(&b"len".to_keyed_vec(Self::PREFIX)); + put(&b"len".to_keyed_vec(Self::PREFIX), &count); } fn count() -> u32 { - Storable::lookup_default(&b"len".to_keyed_vec(Self::PREFIX)) + get_default(&b"len".to_keyed_vec(Self::PREFIX)) } } @@ -118,14 +153,14 @@ mod tests { let mut t = TestExternalities { storage: HashMap::new(), }; with_externalities(&mut t, || { let x = 69u32; - x.store(b":test"); - let y = u32::lookup(b":test").unwrap(); + put(b":test", &x); + let y: u32 = get(b":test").unwrap(); assert_eq!(x, y); }); with_externalities(&mut t, || { let x = 69426942i64; - x.store(b":test"); - let y = i64::lookup(b":test").unwrap(); + put(b":test", &x); + let y: i64 = get(b":test").unwrap(); assert_eq!(x, y); }); } @@ -135,15 +170,15 @@ mod tests { let mut t = TestExternalities { storage: HashMap::new(), }; with_externalities(&mut t, || { let x = true; - x.store(b":test"); - let y = bool::lookup(b":test").unwrap(); + put(b":test", &x); + let y: bool = get(b":test").unwrap(); assert_eq!(x, y); }); with_externalities(&mut t, || { let x = false; - x.store(b":test"); - let y = bool::lookup(b":test").unwrap(); + put(b":test", &x); + let y: bool = get(b":test").unwrap(); assert_eq!(x, y); }); } @@ -155,7 +190,7 @@ mod tests { runtime_std::set_storage(&twox_128(b":test"), b"\x0b\0\0\0Hello world"); let x = b"Hello world".to_vec(); println!("Hex: {}", HexDisplay::from(&storage(&twox_128(b":test")))); - let y = >::lookup(b":test").unwrap(); + let y = get::>(b":test").unwrap(); assert_eq!(x, y); }); @@ -167,13 +202,13 @@ mod tests { let x = b"Hello world".to_vec(); with_externalities(&mut t, || { - x.store(b":test"); + put(b":test", &x); }); println!("Ext is {:?}", t); with_externalities(&mut t, || { println!("Hex: {}", HexDisplay::from(&storage(&twox_128(b":test")))); - let y = >::lookup(b":test").unwrap(); + let y: Vec = get(b":test").unwrap(); assert_eq!(x, y); }); } @@ -184,8 +219,8 @@ mod tests { let mut t = TestExternalities { storage: HashMap::new(), }; with_externalities(&mut t, || { let x = Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: b"Hello world".to_vec() }; - x.store(b":test"); - let y = Proposal::lookup(b":test").unwrap(); + put(b":test", &x); + let y: Proposal = get(b":test").unwrap(); assert_eq!(x, y); }); }