diff --git a/substrate/polkadot/executor/src/lib.rs b/substrate/polkadot/executor/src/lib.rs index a7cef0c3cb..f7ded05025 100644 --- a/substrate/polkadot/executor/src/lib.rs +++ b/substrate/polkadot/executor/src/lib.rs @@ -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) -> (Vec, 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())); diff --git a/substrate/polkadot/runtime/src/runtime/governance.rs b/substrate/polkadot/runtime/src/runtime/governance.rs index b8733b9776..9138a3eddf 100644 --- a/substrate/polkadot/runtime/src/runtime/governance.rs +++ b/substrate/polkadot/runtime/src/runtime/governance.rs @@ -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] diff --git a/substrate/polkadot/runtime/src/runtime/parachains.rs b/substrate/polkadot/runtime/src/runtime/parachains.rs index dd7485ddc8..1cd4151cf9 100644 --- a/substrate/polkadot/runtime/src/runtime/parachains.rs +++ b/substrate/polkadot/runtime/src/runtime/parachains.rs @@ -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] diff --git a/substrate/polkadot/runtime/src/runtime/session.rs b/substrate/polkadot/runtime/src/runtime/session.rs index a3a43d88cc..e9bf5f3765 100644 --- a/substrate/polkadot/runtime/src/runtime/session.rs +++ b/substrate/polkadot/runtime/src/runtime/session.rs @@ -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] diff --git a/substrate/polkadot/runtime/src/runtime/staking.rs b/substrate/polkadot/runtime/src/runtime/staking.rs index a66d43eeb9..0bb4372c6d 100644 --- a/substrate/polkadot/runtime/src/runtime/staking.rs +++ b/substrate/polkadot/runtime/src/runtime/staking.rs @@ -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); diff --git a/substrate/polkadot/runtime/src/runtime/system.rs b/substrate/polkadot/runtime/src/runtime/system.rs index 2f8f5c25c7..7d5e8835ed 100644 --- a/substrate/polkadot/runtime/src/runtime/system.rs +++ b/substrate/polkadot/runtime/src/runtime/system.rs @@ -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] diff --git a/substrate/polkadot/runtime/src/runtime/timestamp.rs b/substrate/polkadot/runtime/src/runtime/timestamp.rs index c64a511ad0..0b96f39bd4 100644 --- a/substrate/polkadot/runtime/src/runtime/timestamp.rs +++ b/substrate/polkadot/runtime/src/runtime/timestamp.rs @@ -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); diff --git a/substrate/polkadot/runtime/wasm/genesis.wasm b/substrate/polkadot/runtime/wasm/genesis.wasm index 91c7b47574..bc0cb89235 100644 Binary files a/substrate/polkadot/runtime/wasm/genesis.wasm and b/substrate/polkadot/runtime/wasm/genesis.wasm differ diff --git a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm index 84e52dbc50..bc0cb89235 100644 Binary files a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm and b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm differ diff --git a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm index a92614dcc2..0434b6b783 100644 Binary files a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm and b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm differ diff --git a/substrate/substrate/client/src/backend.rs b/substrate/substrate/client/src/backend.rs index 4421c82b37..7c445908f7 100644 --- a/substrate/substrate/client/src/backend.rs +++ b/substrate/substrate/client/src/backend.rs @@ -31,7 +31,7 @@ pub trait BlockImportOperation { /// Append block data to the transaction. fn set_block_data(&mut self, header: block::Header, body: Option, is_new_best: bool) -> error::Result<()>; /// Inject storage data into the database. - fn set_storage, Vec)>>(&mut self, iter: I) -> error::Result<()>; + fn set_storage, Option>)>>(&mut self, changes: I) -> error::Result<()>; /// Inject storage data into the database. fn reset_storage, Vec)>>(&mut self, iter: I) -> error::Result<()>; } diff --git a/substrate/substrate/client/src/client.rs b/substrate/substrate/client/src/client.rs index 3fff8bf2ee..ec4d8bf405 100644 --- a/substrate/substrate/client/src/client.rs +++ b/substrate/substrate/client/src/client.rs @@ -132,9 +132,10 @@ impl Client 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 { - 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 Client where /// Get the current set of authorities from storage. pub fn authorities_at(&self, id: &BlockId) -> error::Result> { 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() } diff --git a/substrate/substrate/client/src/error.rs b/substrate/substrate/client/src/error.rs index 1c97387e81..65380efe10 100644 --- a/substrate/substrate/client/src/error.rs +++ b/substrate/substrate/client/src/error.rs @@ -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) { + 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), } diff --git a/substrate/substrate/client/src/genesis.rs b/substrate/substrate/client/src/genesis.rs index fb3e228d03..5008609777 100644 --- a/substrate/substrate/client/src/genesis.rs +++ b/substrate/substrate/client/src/genesis.rs @@ -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( diff --git a/substrate/substrate/client/src/in_mem.rs b/substrate/substrate/client/src/in_mem.rs index 69afbb10b6..5d56ef5770 100644 --- a/substrate/substrate/client/src/in_mem.rs +++ b/substrate/substrate/client/src/in_mem.rs @@ -172,7 +172,7 @@ impl backend::BlockImportOperation for BlockImportOperation { Ok(()) } - fn set_storage, Vec)>>(&mut self, changes: I) -> error::Result<()> { + fn set_storage, Option>)>>(&mut self, changes: I) -> error::Result<()> { self.pending_state.commit(changes); Ok(()) } diff --git a/substrate/substrate/executor/src/wasm_executor.rs b/substrate/substrate/executor/src/wasm_executor.rs index 00bdb55865..4d525a5975 100644 --- a/substrate/substrate/executor/src/wasm_executor.rs +++ b/substrate/substrate/executor/src/wasm_executor.rs @@ -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 { "".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 { "".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 { "".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 { "".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] diff --git a/substrate/substrate/executor/wasm/src/lib.rs b/substrate/substrate/executor/wasm/src/lib.rs index 11401a39d7..013ecca1ed 100644 --- a/substrate/substrate/executor/wasm/src/lib.rs +++ b/substrate/substrate/executor/wasm/src/lib.rs @@ -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); diff --git a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 39b6f737ef..cbc81694c0 100644 Binary files a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm and b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm differ diff --git a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm index 7a21c42208..ab23e9b4f7 100644 Binary files a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm and b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm differ diff --git a/substrate/substrate/runtime-io/with_std.rs b/substrate/substrate/runtime-io/with_std.rs index 3c75935d64..5d785119c5 100644 --- a/substrate/substrate/runtime-io/with_std.rs +++ b/substrate/substrate/runtime-io/with_std.rs @@ -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| diff --git a/substrate/substrate/runtime-io/without_std.rs b/substrate/substrate/runtime-io/without_std.rs index cac6b6dff2..ad31020cc4 100644 --- a/substrate/substrate/runtime-io/without_std.rs +++ b/substrate/substrate/runtime-io/without_std.rs @@ -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 { +pub fn storage(key: &[u8]) -> Option> { 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 { 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), + } } } diff --git a/substrate/substrate/runtime-support/src/storage.rs b/substrate/substrate/runtime-support/src/storage.rs index 9896cb07c6..ac289a4988 100644 --- a/substrate/substrate/runtime-support/src/storage.rs +++ b/substrate/substrate/runtime-support/src/storage.rs @@ -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(key: &[u8]) -> Option { - 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>(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 { +pub fn get_raw(key: &[u8]) -> Option> { 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(key: &[u8]) -> Option { - 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 { + pub fn get_raw(key: &[u8]) -> Option> { 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::>(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 = get(b":test").unwrap(); assert_eq!(x, y); }); diff --git a/substrate/substrate/test-runtime/src/system.rs b/substrate/substrate/test-runtime/src/system.rs index 4c98e16003..a6de75760a 100644 --- a/substrate/substrate/test-runtime/src/system.rs +++ b/substrate/substrate/test-runtime/src/system.rs @@ -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 { diff --git a/substrate/substrate/test-runtime/wasm/genesis.wasm b/substrate/substrate/test-runtime/wasm/genesis.wasm index 3eca504735..7daba8a15c 100644 Binary files a/substrate/substrate/test-runtime/wasm/genesis.wasm and b/substrate/substrate/test-runtime/wasm/genesis.wasm differ diff --git a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index c8ac9359ef..7daba8a15c 100644 Binary files a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm index 3329885da9..f57ee8a775 100644 Binary files a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm and b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm differ