Check storage_key for validity (#2316)

* Intro `ChildStorageKey` for checked child keys

* Get rid of Into in Externalities trait

* Use Cow in ChildStorageKey

* Fix tests for state-machine.

* Clean

* child_storage_root always return a value

* Don't return Option from Ext::child_storage_root

* Return 42 in child_storage_root

* Return CHILD_STORAGE_KEY_PREFIX from trie id gen

* Bump spec and impl version.

* Require `:default:` in `is_child_trie_key_valid`

* Add `default:` prefix.

* Introduce `into_owned` for `ChildStorageKey`.

* Add documentation.

* Fix state-machine tests

* Remove outdated TODO

I check out with Emeric and he is ok with that

* child_storage_root is infailable

* Nit

* Move assert after check.

* Apply suggestions from @DemiMarie-parity

Co-Authored-By: pepyakin <s.pepyakin@gmail.com>

* Formatting nit in core/executor/src/wasm_executor.rs

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* Formatting nits from @thiolliere
This commit is contained in:
Sergei Pepyakin
2019-04-23 18:14:45 +02:00
committed by GitHub
parent 648dcc2728
commit 517746bd62
12 changed files with 286 additions and 123 deletions
+49 -19
View File
@@ -25,7 +25,7 @@ use wasmi::{
};
use wasmi::RuntimeValue::{I32, I64, self};
use wasmi::memory_units::{Pages};
use state_machine::Externalities;
use state_machine::{Externalities, ChildStorageKey};
use crate::error::{Error, ErrorKind, Result};
use crate::wasm_utils::UserError;
use primitives::{blake2_256, twox_128, twox_256, ed25519, sr25519, Pair};
@@ -174,6 +174,10 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
HexDisplay::from(&key)
);
}
let storage_key = ChildStorageKey::from_vec(storage_key)
.ok_or_else(||
UserError("ext_set_child_storage: child storage key is invalid")
)?;
this.ext.set_child_storage(storage_key, key, value);
Ok(())
},
@@ -189,8 +193,13 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage))
} else {
format!(" {}", ::primitives::hexdisplay::ascii_format(&key))
}, HexDisplay::from(&key));
this.ext.clear_child_storage(&storage_key, &key);
}, HexDisplay::from(&key)
);
let storage_key = ChildStorageKey::from_vec(storage_key)
.ok_or_else(||
UserError("ext_clear_child_storage: child storage key is not valid")
)?;
this.ext.clear_child_storage(storage_key, &key);
Ok(())
},
ext_clear_storage(key_data: *const u8, key_len: u32) => {
@@ -214,7 +223,11 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
storage_key_len as usize
).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_exists_child_storage"))?;
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_exists_child_storage"))?;
Ok(if this.ext.exists_child_storage(&storage_key, &key) { 1 } else { 0 })
let storage_key = ChildStorageKey::from_vec(storage_key)
.ok_or_else(||
UserError("ext_exists_child_storage: child storage key is not valid")
)?;
Ok(if this.ext.exists_child_storage(storage_key, &key) { 1 } else { 0 })
},
ext_clear_prefix(prefix_data: *const u8, prefix_len: u32) => {
let prefix = this.memory.get(prefix_data, prefix_len as usize).map_err(|_| UserError("Invalid attempt to determine prefix in ext_clear_prefix"))?;
@@ -226,7 +239,11 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
storage_key_data,
storage_key_len as usize
).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_kill_child_storage"))?;
this.ext.kill_child_storage(&storage_key);
let storage_key = ChildStorageKey::from_vec(storage_key)
.ok_or_else(||
UserError("ext_exists_child_storage: child storage key is not valid")
)?;
this.ext.kill_child_storage(storage_key);
Ok(())
},
// return 0 and place u32::max_value() into written_out if no value exists for the key.
@@ -273,7 +290,14 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
key_data,
key_len as usize
).map_err(|_| UserError("Invalid attempt to determine key in ext_get_allocated_child_storage"))?;
let maybe_value = this.ext.child_storage(&storage_key, &key);
let maybe_value = {
let storage_key = ChildStorageKey::from_slice(&storage_key)
.ok_or_else(||
UserError("ext_get_allocated_child_storage: child storage key is not valid")
)?;
this.ext.child_storage(storage_key, &key)
};
debug_trace!(target: "wasm-trace", "*** Getting child storage: {} -> {} == {} [k={}]",
::primitives::hexdisplay::ascii_format(&storage_key),
@@ -339,7 +363,14 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
key_data,
key_len as usize
).map_err(|_| UserError("Invalid attempt to get key in ext_get_child_storage_into"))?;
let maybe_value = this.ext.child_storage(&storage_key, &key);
let maybe_value = {
let storage_key = ChildStorageKey::from_slice(&*storage_key)
.ok_or_else(||
UserError("ext_get_child_storage_into: child storage key is not valid")
)?;
this.ext.child_storage(storage_key, &key)
};
debug_trace!(target: "wasm-trace", "*** Getting storage: {} -> {} == {} [k={}]",
::primitives::hexdisplay::ascii_format(&storage_key),
if let Some(_preimage) = this.hash_lookup.get(&key) {
@@ -371,18 +402,17 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
},
ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8 => {
let storage_key = this.memory.get(storage_key_data, storage_key_len as usize).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_child_storage_root"))?;
let r = this.ext.child_storage_root(&storage_key);
if let Some(value) = r {
let offset = this.heap.allocate(value.len() as u32)? as u32;
this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_child_storage_root"))?;
this.memory.write_primitive(written_out, value.len() as u32)
.map_err(|_| UserError("Invalid attempt to write written_out in ext_child_storage_root"))?;
Ok(offset)
} else {
this.memory.write_primitive(written_out, u32::max_value())
.map_err(|_| UserError("Invalid attempt to write failed written_out in ext_child_storage_root"))?;
Ok(0)
}
let storage_key = ChildStorageKey::from_slice(&*storage_key)
.ok_or_else(||
UserError("ext_child_storage_root: child storage key is not valid")
)?;
let value = this.ext.child_storage_root(storage_key);
let offset = this.heap.allocate(value.len() as u32)? as u32;
this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_child_storage_root"))?;
this.memory.write_primitive(written_out, value.len() as u32)
.map_err(|_| UserError("Invalid attempt to write written_out in ext_child_storage_root"))?;
Ok(offset)
},
ext_storage_changes_root(parent_hash_data: *const u8, parent_hash_len: u32, parent_number: u64, result: *mut u8) -> u32 => {
let mut parent_hash = H256::default();