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
+23 -30
View File
@@ -20,10 +20,10 @@ use std::{error, fmt, cmp::Ord};
use log::warn;
use crate::backend::{Backend, Consolidate};
use crate::changes_trie::{AnchorBlockId, Storage as ChangesTrieStorage, compute_changes_trie_root};
use crate::{Externalities, OverlayedChanges, OffchainExt};
use crate::{Externalities, OverlayedChanges, OffchainExt, ChildStorageKey};
use hash_db::Hasher;
use primitives::storage::well_known_keys::is_child_storage_key;
use trie::{MemoryDB, TrieDBMut, TrieMut, default_child_trie_root, is_child_trie_key_valid};
use trie::{MemoryDB, TrieDBMut, TrieMut, default_child_trie_root};
use heapsize::HeapSizeOf;
const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime";
@@ -214,10 +214,10 @@ where
self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL)
}
fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Option<Vec<u8>> {
fn child_storage(&self, storage_key: ChildStorageKey<H>, key: &[u8]) -> Option<Vec<u8>> {
let _guard = panic_handler::AbortGuard::new(true);
self.overlay.child_storage(storage_key, key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(||
self.backend.child_storage(storage_key, key).expect(EXT_NOT_ALLOWED_TO_FAIL))
self.overlay.child_storage(storage_key.as_ref(), key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(||
self.backend.child_storage(storage_key.as_ref(), key).expect(EXT_NOT_ALLOWED_TO_FAIL))
}
fn exists_storage(&self, key: &[u8]) -> bool {
@@ -228,11 +228,12 @@ where
}
}
fn exists_child_storage(&self, storage_key: &[u8], key: &[u8]) -> bool {
fn exists_child_storage(&self, storage_key: ChildStorageKey<H>, key: &[u8]) -> bool {
let _guard = panic_handler::AbortGuard::new(true);
match self.overlay.child_storage(storage_key, key) {
match self.overlay.child_storage(storage_key.as_ref(), key) {
Some(x) => x.is_some(),
_ => self.backend.exists_child_storage(storage_key, key).expect(EXT_NOT_ALLOWED_TO_FAIL),
_ => self.backend.exists_child_storage(storage_key.as_ref(), key).expect(EXT_NOT_ALLOWED_TO_FAIL),
}
}
@@ -247,28 +248,20 @@ where
self.overlay.set_storage(key, value);
}
fn place_child_storage(&mut self, storage_key: Vec<u8>, key: Vec<u8>, value: Option<Vec<u8>>) -> bool {
fn place_child_storage(&mut self, storage_key: ChildStorageKey<H>, key: Vec<u8>, value: Option<Vec<u8>>) {
let _guard = panic_handler::AbortGuard::new(true);
if !is_child_storage_key(&storage_key) || !is_child_trie_key_valid::<H>(&storage_key) {
return false;
}
self.mark_dirty();
self.overlay.set_child_storage(storage_key, key, value);
true
self.overlay.set_child_storage(storage_key.into_owned(), key, value);
}
fn kill_child_storage(&mut self, storage_key: &[u8]) {
fn kill_child_storage(&mut self, storage_key: ChildStorageKey<H>) {
let _guard = panic_handler::AbortGuard::new(true);
if !is_child_storage_key(storage_key) || !is_child_trie_key_valid::<H>(storage_key) {
return;
}
self.mark_dirty();
self.overlay.clear_child_storage(storage_key);
self.backend.for_keys_in_child_storage(storage_key, |key| {
self.overlay.set_child_storage(storage_key.to_vec(), key.to_vec(), None);
self.overlay.clear_child_storage(storage_key.as_ref());
self.backend.for_keys_in_child_storage(storage_key.as_ref(), |key| {
self.overlay.set_child_storage(storage_key.as_ref().to_vec(), key.to_vec(), None);
});
}
@@ -315,17 +308,17 @@ where
root
}
fn child_storage_root(&mut self, storage_key: &[u8]) -> Option<Vec<u8>> {
fn child_storage_root(&mut self, storage_key: ChildStorageKey<H>) -> Vec<u8> {
let _guard = panic_handler::AbortGuard::new(true);
if !is_child_storage_key(storage_key) || !is_child_trie_key_valid::<H>(storage_key) {
return None;
}
if self.storage_transaction.is_some() {
return Some(self.storage(storage_key).unwrap_or(default_child_trie_root::<H>(storage_key)));
self
.storage(storage_key.as_ref())
.unwrap_or(
default_child_trie_root::<H>(storage_key.as_ref())
)
} else {
self.child_storage_root_transaction(storage_key.as_ref()).0
}
Some(self.child_storage_root_transaction(storage_key).0)
}
fn storage_changes_root(&mut self, parent: H::Out, parent_num: u64) -> Option<H::Out> {