Multiple storage root support (#902)

* Implement a non generic version of child delta trie

* Use delta_trie_root in state_machine

* Expand InMemory backend to support multi-storage

* Create Consolidate trait

* Fix all crate compile and remove unused OverlayedChanges::drain

* Implement child storage root support and overlay changes

* Add child storage reader

* Add child storage writer

* Implement child storage cleaning

* Fix light backend compile

* Add all required ext functions for wasm executor

* Add ext def to io

* Add all io functions

* Fix nostd compile

* Add simple test

* Remove unnecessary vec copy in child_storage_root_transaction

* Use values_mut/for_each to make it shorter

* Use extend to shorter a for loop

* Move record_all_keys to trie so it's easier to generic them later

* space -> tab

* Remove to_owned in debug format

* Clean out all to_owned

* Break debug_trace to multiple lines

* Remove 0..

* UserError copy/paste typo

* Replace Vec::from_raw_parts by slice::from_raw_parts

* Use iter::empty()

* Wrap some long lines

* Wrap a missing line

* Remove unnecessary map

https://github.com/paritytech/substrate/pull/856#discussion_r226222663

* Call ext_free after from_raw_parts

* Fix tests in other crates
This commit is contained in:
Wei Tang
2018-10-19 00:54:02 +08:00
committed by Gav Wood
parent 849506daa5
commit 2604474880
18 changed files with 1000 additions and 111 deletions
+98 -1
View File
@@ -54,16 +54,24 @@ pub extern fn oom(_: ::core::alloc::Layout) -> ! {
}
extern "C" {
fn ext_free(addr: *mut u8);
fn ext_print_utf8(utf8_data: *const u8, utf8_len: u32);
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_set_child_storage(storage_key_data: *const u8, storage_key_len: u32, 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_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32);
fn ext_exists_storage(key_data: *const u8, key_len: u32) -> u32;
fn ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32;
fn ext_clear_prefix(prefix_data: *const u8, prefix_len: u32);
fn ext_kill_child_storage(storage_key_data: *const u8, storage_key_len: u32);
fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8;
fn ext_get_allocated_child_storage(storage_key_data: *const u8, storage_key_len: u32, 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_get_child_storage_into(storage_key_data: *const u8, storage_key_len: u32, 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);
fn ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8;
fn ext_storage_changes_root(block: u64, result: *mut u8) -> u32;
fn ext_blake2_256_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8);
fn ext_chain_id() -> u64;
@@ -104,7 +112,24 @@ pub fn storage(key: &[u8]) -> Option<Vec<u8>> {
if length == u32::max_value() {
None
} else {
Some(Vec::from_raw_parts(ptr, length as usize, length as usize))
let ret = slice::from_raw_parts(ptr, length as usize).to_vec();
ext_free(ptr);
Some(ret)
}
}
}
/// Get `key` from child storage and return a `Vec`, empty if there's a problem.
pub fn child_storage(storage_key: &[u8], key: &[u8]) -> Option<Vec<u8>> {
let mut length: u32 = 0;
unsafe {
let ptr = ext_get_allocated_child_storage(storage_key.as_ptr(), storage_key.len() as u32, key.as_ptr(), key.len() as u32, &mut length);
if length == u32::max_value() {
None
} else {
let ret = slice::from_raw_parts(ptr, length as usize).to_vec();
ext_free(ptr);
Some(ret)
}
}
}
@@ -119,6 +144,17 @@ pub fn set_storage(key: &[u8], value: &[u8]) {
}
}
/// Set the child storage of some particular key to Some value.
pub fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) {
unsafe {
ext_set_child_storage(
storage_key.as_ptr(), key.len() as u32,
key.as_ptr(), key.len() as u32,
value.as_ptr(), value.len() as u32
);
}
}
/// Clear the storage of some particular key.
pub fn clear_storage(key: &[u8]) {
unsafe {
@@ -128,6 +164,16 @@ pub fn clear_storage(key: &[u8]) {
}
}
/// Clear the storage of some particular key.
pub fn clear_child_storage(storage_key: &[u8], key: &[u8]) {
unsafe {
ext_clear_child_storage(
storage_key.as_ptr(), storage_key.len() as u32,
key.as_ptr(), key.len() as u32
);
}
}
/// Determine whether a particular key exists in storage.
pub fn exists_storage(key: &[u8]) -> bool {
unsafe {
@@ -137,6 +183,16 @@ pub fn exists_storage(key: &[u8]) -> bool {
}
}
/// Determine whether a particular key exists in storage.
pub fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool {
unsafe {
ext_exists_child_storage(
storage_key.as_ptr(), storage_key.len() as u32,
key.as_ptr(), key.len() as u32
) != 0
}
}
/// Clear the storage entries key of which starts with the given prefix.
pub fn clear_prefix(prefix: &[u8]) {
unsafe {
@@ -147,6 +203,16 @@ pub fn clear_prefix(prefix: &[u8]) {
}
}
/// Clear an entire child storage.
pub fn kill_child_storage(storage_key: &[u8]) {
unsafe {
ext_kill_child_storage(
storage_key.as_ptr(),
storage_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) -> Option<usize> {
@@ -162,6 +228,22 @@ pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Op
}
}
/// Get `key` from child 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_child_storage(storage_key: &[u8], key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option<usize> {
unsafe {
match ext_get_child_storage_into(
storage_key.as_ptr(), storage_key.len() as u32,
key.as_ptr(), key.len() as u32,
value_out.as_mut_ptr(), value_out.len() as u32,
value_offset as u32
) {
none if none == u32::max_value() => None,
length => Some(length as usize),
}
}
}
/// The current storage's root.
pub fn storage_root() -> [u8; 32] {
let mut result: [u8; 32] = Default::default();
@@ -171,6 +253,21 @@ pub fn storage_root() -> [u8; 32] {
result
}
/// "Commit" all existing operations and compute the resultant child storage root.
pub fn child_storage_root(storage_key: &[u8]) -> Option<Vec<u8>> {
let mut length: u32 = 0;
unsafe {
let ptr = ext_child_storage_root(storage_key.as_ptr(), storage_key.len() as u32, &mut length);
if length == u32::max_value() {
None
} else {
let ret = slice::from_raw_parts(ptr, length as usize).to_vec();
ext_free(ptr);
Some(ret)
}
}
}
/// The current storage' changes root.
pub fn storage_changes_root(block: u64) -> Option<[u8; 32]> {
let mut result: [u8; 32] = Default::default();