Finish up the API transition.

This commit is contained in:
Gav
2018-02-14 11:40:39 +01:00
parent 11ec408061
commit 828973143b
26 changed files with 181 additions and 92 deletions
+14 -14
View File
@@ -73,9 +73,9 @@ mod tests {
#[test]
fn panic_execution_with_foreign_code_gives_error() {
let one = Keyring::One.to_raw_public();
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0]
], };
];
let r = Executor::new().call(&mut t, BLOATY_CODE, "execute_transaction", &vec![].and(&Header::from_block_number(1u64)).and(&tx()));
assert!(r.is_err());
@@ -84,9 +84,9 @@ mod tests {
#[test]
fn panic_execution_with_native_equivalent_code_gives_error() {
let one = Keyring::One.to_raw_public();
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0]
], };
];
let r = Executor::new().call(&mut t, COMPACT_CODE, "execute_transaction", &vec![].and(&Header::from_block_number(1u64)).and(&tx()));
assert!(r.is_err());
@@ -97,9 +97,9 @@ mod tests {
let one = Keyring::One.to_raw_public();
let two = Keyring::Two.to_raw_public();
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
], };
];
let r = Executor::new().call(&mut t, COMPACT_CODE, "execute_transaction", &vec![].and(&Header::from_block_number(1u64)).and(&tx()));
assert!(r.is_ok());
@@ -115,9 +115,9 @@ mod tests {
let one = Keyring::One.to_raw_public();
let two = Keyring::Two.to_raw_public();
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
], };
];
let r = Executor::new().call(&mut t, BLOATY_CODE, "execute_transaction", &vec![].and(&Header::from_block_number(1u64)).and(&tx()));
assert!(r.is_ok());
@@ -133,7 +133,7 @@ mod tests {
let two = Keyring::Two.to_raw_public();
let three = [3u8; 32];
TestExternalities { storage: map![
map![
twox_128(&0u64.to_keyed_vec(b"sys:old:")).to_vec() => [69u8; 32].encode(),
twox_128(b"gov:apr").to_vec() => vec![].and(&667u32),
twox_128(b"ses:len").to_vec() => vec![].and(&2u64),
@@ -149,7 +149,7 @@ mod tests {
twox_128(b"sta:vac").to_vec() => vec![].and(&3u64),
twox_128(b"sta:era").to_vec() => vec![].and(&0u64),
twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
], }
]
}
fn construct_block(number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec<Transaction>) -> (Vec<u8>, Hash) {
@@ -250,9 +250,9 @@ mod tests {
#[test]
fn panic_execution_gives_error() {
let one = Keyring::One.to_raw_public();
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0]
], };
];
let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm");
let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &vec![].and(&Header::from_block_number(1u64)).and(&tx()));
@@ -264,9 +264,9 @@ mod tests {
let one = Keyring::One.to_raw_public();
let two = Keyring::Two.to_raw_public();
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
], };
];
let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm");
let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &vec![].and(&Header::from_block_number(1u64)).and(&tx()));
@@ -157,7 +157,7 @@ mod tests {
let two = Keyring::Two.to_raw_public();
let three = [3u8; 32];
TestExternalities { storage: map![
map![
twox_128(APPROVALS_REQUIRED).to_vec() => vec![].and(&667u32),
twox_128(b"ses:len").to_vec() => vec![].and(&1u64),
twox_128(b"ses:val:len").to_vec() => vec![].and(&3u32),
@@ -171,7 +171,7 @@ mod tests {
twox_128(b"sta:spe").to_vec() => vec![].and(&1u64),
twox_128(b"sta:vac").to_vec() => vec![].and(&3u64),
twox_128(b"sta:era").to_vec() => vec![].and(&1u64)
], }
]
}
#[test]
@@ -83,10 +83,10 @@ mod tests {
use runtime::{consensus, session};
fn simple_setup() -> TestExternalities {
TestExternalities { storage: map![
map![
twox_128(b"ses:val:len").to_vec() => vec![].and(&8u32),
twox_128(b"par:cou").to_vec() => vec![].and(&2u32)
], }
]
}
#[test]
@@ -145,7 +145,7 @@ mod tests {
use runtime::{consensus, session};
fn simple_setup() -> TestExternalities {
TestExternalities { storage: map![
map![
twox_128(SESSION_LENGTH).to_vec() => vec![].and(&2u64),
// the validators (10, 20, ...)
twox_128(b"ses:val:len").to_vec() => vec![].and(&2u32),
@@ -155,7 +155,7 @@ mod tests {
b":auth:len".to_vec() => vec![].and(&2u32),
0u32.to_keyed_vec(b":auth:") => vec![11; 32],
1u32.to_keyed_vec(b":auth:") => vec![21; 32]
], }
]
}
#[test]
@@ -227,7 +227,7 @@ mod tests {
let three = [3u8; 32];
let four = [4u8; 32];
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(b"ses:len").to_vec() => vec![].and(&1u64),
twox_128(b"ses:val:len").to_vec() => vec![].and(&2u32),
twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => vec![10; 32],
@@ -239,7 +239,7 @@ mod tests {
twox_128(&two.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&20u64),
twox_128(&three.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&30u64),
twox_128(&four.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&40u64)
], };
];
with_externalities(&mut t, || {
assert_eq!(era_length(), 2u64);
@@ -296,10 +296,10 @@ mod tests {
#[test]
fn staking_eras_work() {
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(b"ses:len").to_vec() => vec![].and(&1u64),
twox_128(SESSIONS_PER_ERA).to_vec() => vec![].and(&2u64)
], };
];
with_externalities(&mut t, || {
assert_eq!(era_length(), 2u64);
assert_eq!(sessions_per_era(), 2u64);
@@ -363,9 +363,9 @@ mod tests {
let one = Keyring::One.to_raw_public();
let two = Keyring::Two.to_raw_public();
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&42u64)
], };
];
with_externalities(&mut t, || {
assert_eq!(balance(&one), 42);
@@ -378,9 +378,9 @@ mod tests {
let one = Keyring::One.to_raw_public();
let two = Keyring::Two.to_raw_public();
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&111u64)
], };
];
with_externalities(&mut t, || {
transfer(&one, &two, 69);
@@ -395,9 +395,9 @@ mod tests {
let one = Keyring::One.to_raw_public();
let two = Keyring::Two.to_raw_public();
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&111u64)
], };
];
with_externalities(&mut t, || {
stake(&one);
@@ -247,9 +247,9 @@ mod tests {
let one = Keyring::One.to_raw_public();
let two = Keyring::Two.to_raw_public();
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
], };
];
let tx = UncheckedTransaction {
transaction: Transaction {
@@ -272,7 +272,7 @@ mod tests {
let two = Keyring::Two.to_raw_public();
let three = [3u8; 32];
TestExternalities { storage: map![
map![
twox_128(&0u64.to_keyed_vec(b"sys:old:")).to_vec() => [69u8; 32].encode(),
twox_128(b"gov:apr").to_vec() => vec![].and(&667u32),
twox_128(b"ses:len").to_vec() => vec![].and(&2u64),
@@ -288,7 +288,7 @@ mod tests {
twox_128(b"sta:vac").to_vec() => vec![].and(&3u64),
twox_128(b"sta:era").to_vec() => vec![].and(&0u64),
twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
], }
]
}
#[test]
@@ -47,9 +47,9 @@ mod tests {
#[test]
fn timestamp_works() {
let mut t = TestExternalities { storage: map![
let mut t: TestExternalities = map![
twox_128(CURRENT_TIMESTAMP).to_vec() => vec![].and(&42u64)
], };
];
with_externalities(&mut t, || {
assert_eq!(get(), 42);
Binary file not shown.
+1 -1
View File
@@ -31,7 +31,7 @@ pub trait BlockImportOperation {
/// Append block data to the transaction.
fn set_block_data(&mut self, header: block::Header, body: Option<block::Body>, is_new_best: bool) -> error::Result<()>;
/// Inject storage data into the database.
fn set_storage<I: Iterator<Item=(Vec<u8>, Vec<u8>)>>(&mut self, iter: I) -> error::Result<()>;
fn set_storage<I: Iterator<Item=(Vec<u8>, Option<Vec<u8>>)>>(&mut self, changes: I) -> error::Result<()>;
/// Inject storage data into the database.
fn reset_storage<I: Iterator<Item=(Vec<u8>, Vec<u8>)>>(&mut self, iter: I) -> error::Result<()>;
}
+7 -5
View File
@@ -132,9 +132,10 @@ impl<B, E> Client<B, E> where
/// Return single storage entry of contract under given address in state in a block of given hash.
pub fn storage(&self, id: &BlockId, key: &StorageKey) -> error::Result<StorageData> {
Ok(self.state_at(id)?
.storage(&key.0)
.map(|x| StorageData(x.to_vec()))?)
Ok(StorageData(self.state_at(id)?
.storage(&key.0)?
.ok_or_else(|| error::ErrorKind::NoValueForKey(key.0.clone()))?
.to_vec()))
}
/// Get the code at a given block.
@@ -150,10 +151,11 @@ impl<B, E> Client<B, E> where
/// Get the current set of authorities from storage.
pub fn authorities_at(&self, id: &BlockId) -> error::Result<Vec<AuthorityId>> {
let state = self.state_at(id)?;
(0..u32::decode(&mut state.storage(b":auth:len")?).ok_or(error::ErrorKind::AuthLen)?)
(0..u32::decode(&mut state.storage(b":auth:len")?.ok_or(error::ErrorKind::AuthLenEmpty)?).ok_or(error::ErrorKind::AuthLenInvalid)?)
.map(|i| state.storage(&i.to_keyed_vec(b":auth:"))
.map_err(|_| error::ErrorKind::Backend)
.and_then(|mut s| AuthorityId::decode(&mut s).ok_or(error::ErrorKind::Auth(i)))
.and_then(|v| v.ok_or(error::ErrorKind::AuthEmpty(i)))
.and_then(|mut s| AuthorityId::decode(&mut s).ok_or(error::ErrorKind::AuthInvalid(i)))
.map_err(Into::into)
).collect()
}
+21 -2
View File
@@ -19,6 +19,7 @@
use std;
use state_machine;
use blockchain;
use primitives::hexdisplay::HexDisplay;
error_chain! {
errors {
@@ -46,14 +47,32 @@ error_chain! {
display("Blockchain: {}", e),
}
/// Attempt to read storage yet nothing set for that key.
NoValueForKey(key: Vec<u8>) {
description("storage doesn't contain key"),
display("Storage does not contain the key entry: {}", HexDisplay::from(key)),
}
/// Invalid state data.
AuthLen {
AuthLenEmpty {
description("authority count state error"),
display("Current state of blockchain has no authority count value"),
}
/// Invalid state data.
AuthEmpty(i: u32) {
description("authority value state error"),
display("Current state of blockchain has no authority value for index {}", i),
}
/// Invalid state data.
AuthLenInvalid {
description("authority count state error"),
display("Current state of blockchain has invalid authority count value"),
}
/// Invalid state data.
Auth(i: u32) {
AuthInvalid(i: u32) {
description("authority value state error"),
display("Current state of blockchain has invalid authority value for index {}", i),
}
+14 -1
View File
@@ -114,7 +114,7 @@ mod tests {
}
#[test]
fn construct_genesis_should_work() {
fn construct_genesis_should_work_with_native() {
let mut storage = GenesisConfig::new_simple(
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000
).genesis_map();
@@ -133,6 +133,19 @@ mod tests {
"execute_block",
&b1data
).unwrap();
}
#[test]
fn construct_genesis_should_work_with_wasm() {
let mut storage = GenesisConfig::new_simple(
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000
).genesis_map();
let block = construct_genesis_block(&storage);
let genesis_hash = block.header.blake2_256().into();
storage.extend(additional_storage_with_genesis(&block).into_iter());
let backend = InMemory::from(storage);
let (b1data, _b1hash) = block1(genesis_hash, &backend);
let mut overlay = OverlayedChanges::default();
let _ = execute(
+1 -1
View File
@@ -172,7 +172,7 @@ impl backend::BlockImportOperation for BlockImportOperation {
Ok(())
}
fn set_storage<I: Iterator<Item=(Vec<u8>, Vec<u8>)>>(&mut self, changes: I) -> error::Result<()> {
fn set_storage<I: Iterator<Item=(Vec<u8>, Option<Vec<u8>>)>>(&mut self, changes: I) -> error::Result<()> {
self.pending_state.commit(changes);
Ok(())
}
@@ -171,34 +171,53 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
}
this.ext.set_storage(key, value);
},
ext_clear_storage(key_data: *const u8, key_len: u32) => {
let key = this.memory.get(key_data, key_len as usize).map_err(|_| DummyUserError)?;
if let Some(preimage) = this.hash_lookup.get(&key) {
info!(target: "wasm-trace", "*** Clearing storage: %{} [k={}]", ascii_format(&preimage), HexDisplay::from(&key));
} else {
info!(target: "wasm-trace", "*** Clearing storage: {} [k={}]", ascii_format(&key), HexDisplay::from(&key));
}
this.ext.clear_storage(&key);
},
// return 0 and place u32::max_value() into written_out if no value exists for the key.
ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8 => {
let key = this.memory.get(key_data, key_len as usize).map_err(|_| DummyUserError)?;
let value = this.ext.storage(&key).map_err(|_| DummyUserError)?;
let maybe_value = this.ext.storage(&key);
if let Some(preimage) = this.hash_lookup.get(&key) {
info!(target: "wasm-trace", " Getting storage: %{} == {} [k={}]", ascii_format(&preimage), HexDisplay::from(&value), HexDisplay::from(&key));
info!(target: "wasm-trace", " Getting storage: %{} == {} [k={}]", ascii_format(&preimage), if let Some(ref b) = maybe_value { format!("{}", HexDisplay::from(b)) } else { "<empty>".to_owned() }, HexDisplay::from(&key));
} else {
info!(target: "wasm-trace", " Getting storage: {} == {} [k={}]", ascii_format(&key), HexDisplay::from(&value), HexDisplay::from(&key));
info!(target: "wasm-trace", " Getting storage: {} == {} [k={}]", ascii_format(&key), if let Some(ref b) = maybe_value { format!("{}", HexDisplay::from(b)) } else { "<empty>".to_owned() }, HexDisplay::from(&key));
}
let offset = this.heap.allocate(value.len() as u32) as u32;
this.memory.set(offset, &value).map_err(|_| DummyUserError)?;
this.memory.write_primitive(written_out, value.len() as u32)?;
offset
if let Some(value) = maybe_value {
let offset = this.heap.allocate(value.len() as u32) as u32;
this.memory.set(offset, &value).map_err(|_| DummyUserError)?;
this.memory.write_primitive(written_out, value.len() as u32)?;
offset
} else {
this.memory.write_primitive(written_out, u32::max_value())?;
0
}
},
// return u32::max_value() if no value exists for the key.
ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32 => {
let key = this.memory.get(key_data, key_len as usize).map_err(|_| DummyUserError)?;
let value = this.ext.storage(&key).map_err(|_| DummyUserError)?;
let maybe_value = this.ext.storage(&key);
if let Some(preimage) = this.hash_lookup.get(&key) {
info!(target: "wasm-trace", " Getting storage: %{} == {} [k={}]", ascii_format(&preimage), HexDisplay::from(&value), HexDisplay::from(&key));
info!(target: "wasm-trace", " Getting storage: %{} == {} [k={}]", ascii_format(&preimage), if let Some(ref b) = maybe_value { format!("{}", HexDisplay::from(b)) } else { "<empty>".to_owned() }, HexDisplay::from(&key));
} else {
info!(target: "wasm-trace", " Getting storage: {} == {} [k={}]", ascii_format(&key), HexDisplay::from(&value), HexDisplay::from(&key));
info!(target: "wasm-trace", " Getting storage: {} == {} [k={}]", ascii_format(&key), if let Some(ref b) = maybe_value { format!("{}", HexDisplay::from(b)) } else { "<empty>".to_owned() }, HexDisplay::from(&key));
}
if let Some(value) = maybe_value {
let value = &value[value_offset as usize..];
let written = ::std::cmp::min(value_len as usize, value.len());
this.memory.set(value_data, &value[..written]).map_err(|_| DummyUserError)?;
written as u32
} else {
u32::max_value()
}
let value = &value[value_offset as usize..];
let written = ::std::cmp::min(value_len as usize, value.len());
this.memory.set(value_data, &value[..written]).map_err(|_| DummyUserError)?;
written as u32
},
ext_storage_root(result: *mut u8) => {
let r = this.ext.storage_root();
@@ -369,7 +388,7 @@ mod tests {
b"foo".to_vec() => b"bar".to_vec(),
b"baz".to_vec() => b"bar".to_vec()
];
assert_eq!(expected, ext.storage);
assert_eq!(expected, ext);
}
#[test]
+1 -1
View File
@@ -19,7 +19,7 @@ impl_stubs!(
set_storage(b"input", input);
print("storage");
let foo = storage(b"foo");
let foo = storage(b"foo").unwrap();
print("set_storage");
set_storage(b"baz", &foo);
+8 -1
View File
@@ -52,13 +52,20 @@ pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Op
})).expect("read_storage cannot be called outside of an Externalities-provided environment.")
}
/// Set the storage to some particular key.
/// Set the storage of some particular key to Some value.
pub fn set_storage(key: &[u8], value: &[u8]) {
ext::with(|ext|
ext.set_storage(key.to_vec(), value.to_vec())
);
}
/// Clear the storage of some particular key.
pub fn clear_storage(key: &[u8]) {
ext::with(|ext|
ext.clear_storage(key)
);
}
/// The current relay chain identifier.
pub fn chain_id() -> u64 {
ext::with(|ext|
+22 -5
View File
@@ -43,6 +43,7 @@ extern "C" {
fn ext_print_hex(data: *const u8, len: u32);
fn ext_print_num(value: u64);
fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32);
fn ext_clear_storage(key_data: *const u8, key_len: u32);
fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8;
fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32;
fn ext_storage_root(result: *mut u8);
@@ -55,11 +56,15 @@ extern "C" {
}
/// Get `key` from storage and return a `Vec`, empty if there's a problem.
pub fn storage(key: &[u8]) -> Vec<u8> {
pub fn storage(key: &[u8]) -> Option<Vec<u8>> {
let mut length: u32 = 0;
unsafe {
let ptr = ext_get_allocated_storage(key.as_ptr(), key.len() as u32, &mut length);
Vec::from_raw_parts(ptr, length as usize, length as usize)
if length == u32::max_value() {
None
} else {
Some(Vec::from_raw_parts(ptr, length as usize, length as usize))
}
}
}
@@ -73,15 +78,27 @@ pub fn set_storage(key: &[u8], value: &[u8]) {
}
}
/// Set the storage to some particular key.
pub fn clear_storage(key: &[u8]) {
unsafe {
ext_clear_storage(
key.as_ptr(), key.len() as u32
);
}
}
/// Get `key` from storage, placing the value into `value_out` (as much as possible) and return
/// the number of bytes that the key in storage was beyond the offset.
pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> usize {
pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option<usize> {
unsafe {
ext_get_storage_into(
match ext_get_storage_into(
key.as_ptr(), key.len() as u32,
value_out.as_mut_ptr(), value_out.len() as u32,
value_offset as u32
) as usize
) {
none if none == u32::max_value() => None,
length => Some(length as usize),
}
}
}
@@ -24,8 +24,9 @@ use codec::{Slicable, KeyedVec};
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
pub fn get<T: Slicable + Sized>(key: &[u8]) -> Option<T> {
let raw = runtime_io::storage(&twox_128(key)[..]);
Slicable::decode(&mut &raw[..])
let maybe_raw = runtime_io::storage(&twox_128(key)[..]);
maybe_raw.map(|raw| Slicable::decode(&mut &raw[..])
.expect("storage should contain a decodable value if there is some entry"))
}
/// Return the value of the item in storage under `key`, or the type's default if there is no
@@ -85,17 +86,17 @@ pub fn take_or_else<T: Slicable + Sized, F: FnOnce() -> T>(key: &[u8], default_v
/// Check to see if `key` has an explicit entry in storage.
pub fn exists(key: &[u8]) -> bool {
let mut x = [0u8; 1];
runtime_io::read_storage(&twox_128(key)[..], &mut x[..], 0) >= 1
let mut x = [0u8; 0];
runtime_io::read_storage(&twox_128(key)[..], &mut x[..], 0).is_some()
}
/// Ensure `key` has no explicit entry in storage.
pub fn kill(key: &[u8]) {
runtime_io::set_storage(&twox_128(key)[..], b"");
runtime_io::clear_storage(&twox_128(key)[..]);
}
/// Get a Vec of bytes from storage.
pub fn get_raw(key: &[u8]) -> Vec<u8> {
pub fn get_raw(key: &[u8]) -> Option<Vec<u8>> {
runtime_io::storage(&twox_128(key)[..])
}
@@ -127,12 +128,18 @@ pub trait StorageVec {
}
}
fn clear_item(index: u32) {
if index < Self::count() {
kill(&index.to_keyed_vec(Self::PREFIX));
}
}
fn item(index: u32) -> Self::Item {
get_or_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..Self::count()).for_each(Self::clear_item);
put(&b"len".to_keyed_vec(Self::PREFIX), &count);
}
@@ -146,8 +153,9 @@ pub mod unhashed {
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
pub fn get<T: Slicable + Sized>(key: &[u8]) -> Option<T> {
let raw = runtime_io::storage(key);
T::decode(&mut &raw[..])
let maybe_raw = runtime_io::storage(key);
maybe_raw.map(|raw| Slicable::decode(&mut &raw[..])
.expect("storage should contain a decodable value if there is some entry"))
}
/// Return the value of the item in storage under `key`, or the type's default if there is no
@@ -207,17 +215,16 @@ pub mod unhashed {
/// Check to see if `key` has an explicit entry in storage.
pub fn exists(key: &[u8]) -> bool {
let mut x = [0u8; 1];
runtime_io::read_storage(key, &mut x[..], 0) >= 1
runtime_io::read_storage(key, &mut [0;0][..], 0).is_some()
}
/// Ensure `key` has no explicit entry in storage.
pub fn kill(key: &[u8]) {
runtime_io::set_storage(key, b"");
runtime_io::clear_storage(key);
}
/// Get a Vec of bytes from storage.
pub fn get_raw(key: &[u8]) -> Vec<u8> {
pub fn get_raw(key: &[u8]) -> Option<Vec<u8>> {
runtime_io::storage(key)
}
@@ -249,12 +256,18 @@ pub mod unhashed {
}
}
fn clear_item(index: u32) {
if index < Self::count() {
kill(&index.to_keyed_vec(Self::PREFIX));
}
}
fn item(index: u32) -> Self::Item {
get_or_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..Self::count()).for_each(Self::clear_item);
put(&b"len".to_keyed_vec(Self::PREFIX), &count);
}
@@ -267,13 +280,12 @@ pub mod unhashed {
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
use primitives::hexdisplay::HexDisplay;
use runtime_io::{storage, twox_128, TestExternalities, with_externalities};
#[test]
fn integers_can_be_stored() {
let mut t = TestExternalities { storage: HashMap::new(), };
let mut t = TestExternalities::new();
with_externalities(&mut t, || {
let x = 69u32;
put(b":test", &x);
@@ -290,7 +302,7 @@ mod tests {
#[test]
fn bools_can_be_stored() {
let mut t = TestExternalities { storage: HashMap::new(), };
let mut t = TestExternalities::new();
with_externalities(&mut t, || {
let x = true;
put(b":test", &x);
@@ -308,11 +320,11 @@ mod tests {
#[test]
fn vecs_can_be_retrieved() {
let mut t = TestExternalities { storage: HashMap::new(), };
let mut t = TestExternalities::new();
with_externalities(&mut t, || {
runtime_io::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"))));
println!("Hex: {}", HexDisplay::from(&storage(&twox_128(b":test")).unwrap()));
let y = get::<Vec<u8>>(b":test").unwrap();
assert_eq!(x, y);
@@ -321,7 +333,7 @@ mod tests {
#[test]
fn vecs_can_be_stored() {
let mut t = TestExternalities { storage: HashMap::new(), };
let mut t = TestExternalities::new();
let x = b"Hello world".to_vec();
with_externalities(&mut t, || {
@@ -330,7 +342,7 @@ mod tests {
println!("Ext is {:?}", t);
with_externalities(&mut t, || {
println!("Hex: {}", HexDisplay::from(&storage(&twox_128(b":test"))));
println!("Hex: {}", HexDisplay::from(&storage(&twox_128(b":test")).unwrap()));
let y: Vec<u8> = get(b":test").unwrap();
assert_eq!(x, y);
});
@@ -136,14 +136,14 @@ mod tests {
use ::{Header, Digest, Transaction, UncheckedTransaction};
fn new_test_ext() -> TestExternalities {
TestExternalities { storage: map![
map![
twox_128(b"latest").to_vec() => vec![69u8; 32],
twox_128(b":auth:len").to_vec() => vec![].and(&3u32),
twox_128(&0u32.to_keyed_vec(b":auth:")).to_vec() => Keyring::Alice.to_raw_public().to_vec(),
twox_128(&1u32.to_keyed_vec(b":auth:")).to_vec() => Keyring::Bob.to_raw_public().to_vec(),
twox_128(&2u32.to_keyed_vec(b":auth:")).to_vec() => Keyring::Charlie.to_raw_public().to_vec(),
twox_128(&Keyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
], }
]
}
fn construct_signed_tx(tx: Transaction) -> UncheckedTransaction {
Binary file not shown.