Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ad8ecaa
Implement a non generic version of child delta trie
sorpaas Oct 11, 2018
b4ae088
Use delta_trie_root in state_machine
sorpaas Oct 11, 2018
134ad78
Expand InMemory backend to support multi-storage
sorpaas Oct 12, 2018
48040c7
Create Consolidate trait
sorpaas Oct 12, 2018
307406f
Fix all crate compile and remove unused OverlayedChanges::drain
sorpaas Oct 12, 2018
252befb
Implement child storage root support and overlay changes
sorpaas Oct 12, 2018
bc88cd5
Add child storage reader
sorpaas Oct 12, 2018
74c2c1e
Add child storage writer
sorpaas Oct 12, 2018
925cace
Implement child storage cleaning
sorpaas Oct 12, 2018
f257e4c
Fix light backend compile
sorpaas Oct 12, 2018
7664f74
Add all required ext functions for wasm executor
sorpaas Oct 12, 2018
ceb03a2
Add ext def to io
sorpaas Oct 12, 2018
073f8a3
Add all io functions
sorpaas Oct 12, 2018
7b061ae
Fix nostd compile
sorpaas Oct 12, 2018
00e757b
Add simple test
sorpaas Oct 12, 2018
a450d4f
Remove unnecessary vec copy in child_storage_root_transaction
sorpaas Oct 15, 2018
8791a4c
Use values_mut/for_each to make it shorter
sorpaas Oct 15, 2018
8708012
Use extend to shorter a for loop
sorpaas Oct 15, 2018
44c22d3
Merge branch 'master' of https://github.com/paritytech/substrate into…
sorpaas Oct 18, 2018
5c8cc89
Move record_all_keys to trie so it's easier to generic them later
sorpaas Oct 18, 2018
e4ec3a5
space -> tab
sorpaas Oct 18, 2018
2cb62ba
Remove to_owned in debug format
sorpaas Oct 18, 2018
33afc57
Clean out all to_owned
sorpaas Oct 18, 2018
4d3ee4f
Break debug_trace to multiple lines
sorpaas Oct 18, 2018
7a2981c
Remove 0..
sorpaas Oct 18, 2018
577e32e
UserError copy/paste typo
sorpaas Oct 18, 2018
81685c4
Replace Vec::from_raw_parts by slice::from_raw_parts
sorpaas Oct 18, 2018
d132d05
Use iter::empty()
sorpaas Oct 18, 2018
b76e574
Wrap some long lines
sorpaas Oct 18, 2018
ac697ce
Wrap a missing line
sorpaas Oct 18, 2018
29c20a6
Remove unnecessary map
sorpaas Oct 18, 2018
b73f25c
Call ext_free after from_raw_parts
sorpaas Oct 18, 2018
69d1840
Fix tests in other crates
sorpaas Oct 18, 2018
d28f3c0
Merge branch 'master' of https://github.com/paritytech/substrate into…
sorpaas Oct 18, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/client/src/cht.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pub fn build_proof<Header, Hasher, I>(
{
let transaction = build_pairs::<Header, I>(cht_size, cht_num, hashes)?
.into_iter()
.map(|(k, v)| (k, Some(v)))
.map(|(k, v)| (None, k, Some(v)))
.collect::<Vec<_>>();
let storage = InMemoryState::<Hasher>::default().update(transaction);
let (value, proof) = prove_read(storage, &encode_cht_key(block_num)).ok()?;
Expand Down Expand Up @@ -205,7 +205,7 @@ pub fn decode_cht_value(value: &[u8]) -> Option<H256> {
32 => Some(H256::from_slice(&value[0..32])),
_ => None,
}

}

#[cfg(test)]
Expand Down
21 changes: 19 additions & 2 deletions core/client/src/light/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ impl<Block, S, F, H> StateBackend<H> for OnDemandState<Block, S, F>
S: BlockchainStorage<Block>,
F: Fetcher<Block>,
H: Hasher,

{
type Error = ClientError;
type Transaction = ();
Expand All @@ -227,15 +227,32 @@ impl<Block, S, F, H> StateBackend<H> for OnDemandState<Block, S, F>
.into_future().wait()
}

fn child_storage(&self, _storage_key: &[u8], _key: &[u8]) -> ClientResult<Option<Vec<u8>>> {
Err(ClientErrorKind::NotAvailableOnLightClient.into())
}

fn for_keys_with_prefix<A: FnMut(&[u8])>(&self, _prefix: &[u8], _action: A) {
// whole state is not available on light node
}

fn for_keys_in_child_storage<A: FnMut(&[u8])>(&self, _storage_key: &[u8], _action: A) {
// whole state is not available on light node
}

fn storage_root<I>(&self, _delta: I) -> (H::Out, Self::Transaction)
where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)> {
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>
{
(H::Out::default(), ())
}

fn child_storage_root<I>(&self, _key: &[u8], _delta: I) -> (Vec<u8>, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>
{
(H::Out::default().as_ref().to_vec(), ())
}

fn pairs(&self) -> Vec<(Vec<u8>, Vec<u8>)> {
// whole state is not available on light node
Vec::new()
Expand Down
162 changes: 155 additions & 7 deletions core/executor/src/wasm_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,46 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
this.ext.set_storage(key, value);
Ok(())
},
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) => {
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_set_child_storage"))?;
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_set_child_storage"))?;
let value = this.memory.get(value_data, value_len as usize).map_err(|_| UserError("Invalid attempt to determine value in ext_set_child_storage"))?;
if let Some(_preimage) = this.hash_lookup.get(&key) {
debug_trace!(
target: "wasm-trace", "*** Setting child storage: {} -> %{} -> {} [k={}]",
::primitives::hexdisplay::ascii_format(&storage_key),
::primitives::hexdisplay::ascii_format(&_preimage),
HexDisplay::from(&value),
HexDisplay::from(&key)
);
} else {
debug_trace!(
target: "wasm-trace", "*** Setting child storage: {} -> {} -> {} [k={}]",
::primitives::hexdisplay::ascii_format(&storage_key),
::primitives::hexdisplay::ascii_format(&key),
HexDisplay::from(&value),
HexDisplay::from(&key)
);
}
this.ext.set_child_storage(storage_key, key, value);
Ok(())
},
ext_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) => {
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_clear_child_storage"))?;
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_clear_child_storage"))?;
debug_trace!(target: "wasm-trace", "*** Clearing child storage: {} -> {} [k={}]",
::primitives::hexdisplay::ascii_format(&storage_key),
if let Some(_preimage) = this.hash_lookup.get(&key) {
format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage))
} else {
format!(" {}", ::primitives::hexdisplay::ascii_format(&key))
}, HexDisplay::from(&key));
this.ext.clear_child_storage(&storage_key, &key);
Ok(())
},
ext_clear_storage(key_data: *const u8, key_len: u32) => {
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_clear_storage"))?;
debug_trace!(target: "wasm-trace", "*** Clearing storage: {} [k={}]",
Expand All @@ -196,14 +236,33 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_exists_storage"))?;
Ok(if this.ext.exists_storage(&key) { 1 } else { 0 })
},
ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32 => {
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_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 })
},
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"))?;
this.ext.clear_prefix(&prefix);
Ok(())
},
ext_kill_child_storage(storage_key_data: *const u8, storage_key_len: u32) => {
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_kill_child_storage"))?;
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.
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(|_| UserError("Invalid attempt to determine key in ext_get_allocated_storage"))?;
let key = this.memory.get(
key_data,
key_len as usize
).map_err(|_| UserError("Invalid attempt to determine key in ext_get_allocated_storage"))?;
let maybe_value = this.ext.storage(&key);

debug_trace!(target: "wasm-trace", "*** Getting storage: {} == {} [k={}]",
Expand All @@ -213,9 +272,9 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
format!(" {}", ::primitives::hexdisplay::ascii_format(&key))
},
if let Some(ref b) = maybe_value {
format!("{}", HexDisplay::from(b))
&format!("{}", HexDisplay::from(b))
} else {
"<empty>".to_owned()
"<empty>"
},
HexDisplay::from(&key)
);
Expand All @@ -232,6 +291,45 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
Ok(0)
}
},
// return 0 and place u32::max_value() into written_out if no value exists for the key.
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 => {
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_get_allocated_child_storage"))?;
let key = this.memory.get(
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);

debug_trace!(target: "wasm-trace", "*** Getting child storage: {} -> {} == {} [k={}]",
::primitives::hexdisplay::ascii_format(&storage_key),
if let Some(_preimage) = this.hash_lookup.get(&key) {
format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage))
} else {
format!(" {}", ::primitives::hexdisplay::ascii_format(&key))
},
if let Some(ref b) = maybe_value {
&format!("{}", HexDisplay::from(b))
} else {
"<empty>"
},
HexDisplay::from(&key)
);

if let Some(value) = maybe_value {
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_get_allocated_child_storage"))?;
this.memory.write_primitive(written_out, value.len() as u32)
.map_err(|_| UserError("Invalid attempt to write written_out in ext_get_allocated_child_storage"))?;
Ok(offset)
} else {
this.memory.write_primitive(written_out, u32::max_value())
.map_err(|_| UserError("Invalid attempt to write failed written_out in ext_get_allocated_child_storage"))?;
Ok(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(|_| UserError("Invalid attempt to get key in ext_get_storage_into"))?;
Expand All @@ -243,9 +341,9 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
format!(" {}", ::primitives::hexdisplay::ascii_format(&key))
},
if let Some(ref b) = maybe_value {
format!("{}", HexDisplay::from(b))
&format!("{}", HexDisplay::from(b))
} else {
"<empty>".to_owned()
"<empty>"
},
HexDisplay::from(&key)
);
Expand All @@ -259,11 +357,61 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
Ok(u32::max_value())
}
},
// return u32::max_value() if no value exists for the key.
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 => {
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_get_child_storage_into"))?;
let key = this.memory.get(
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);
debug_trace!(target: "wasm-trace", "*** Getting storage: {} -> {} == {} [k={}]",
::primitives::hexdisplay::ascii_format(&storage_key),
if let Some(_preimage) = this.hash_lookup.get(&key) {
format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage))
} else {
format!(" {}", ::primitives::hexdisplay::ascii_format(&key))
},
if let Some(ref b) = maybe_value {
&format!("{}", HexDisplay::from(b))
} else {
"<empty>"
},
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(|_| UserError("Invalid attempt to set value in ext_get_child_storage_into"))?;
Ok(written as u32)
} else {
Ok(u32::max_value())
}
},
ext_storage_root(result: *mut u8) => {
let r = this.ext.storage_root();
this.memory.set(result, r.as_ref()).map_err(|_| UserError("Invalid attempt to set memory in ext_storage_root"))?;
Ok(())
},
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)
}
},
ext_storage_changes_root(block: u64, result: *mut u8) -> u32 => {
let r = this.ext.storage_changes_root(block);
if let Some(ref r) = r {
Expand Down Expand Up @@ -300,9 +448,9 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
let hashed_key = twox_128(&key);
debug_trace!(target: "xxhash", "XXhash: {} -> {}",
if let Ok(_skey) = ::std::str::from_utf8(&key) {
_skey.to_owned()
_skey
} else {
format!("{}", HexDisplay::from(&key))
&format!("{}", HexDisplay::from(&key))
},
HexDisplay::from(&hashed_key)
);
Expand Down
9 changes: 9 additions & 0 deletions core/primitives/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,13 @@ pub mod well_known_keys {

/// Changes trie configuration is stored under this key.
pub const CHANGES_TRIE_CONFIG: &'static [u8] = b":changes_trie";

/// Prefix of child storage keys.
pub const CHILD_STORAGE_KEY_PREFIX: &'static [u8] = b":child_storage:";

/// Whether a key is a child storage key.
pub fn is_child_storage_key(key: &[u8]) -> bool {
key.starts_with(CHILD_STORAGE_KEY_PREFIX)
}

}
Loading