diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 3fa6b03464..dd7ed8daf3 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -27,35 +27,33 @@ pub use rstd::slice; #[macro_use] pub mod validate_block; -/// The type of the witness data. +/// The witness data type. type WitnessData = Vec>; /// The parachain block that is created on a collator and validated by a validator. #[derive(Encode, Decode)] -struct ParachainBlockData { +pub struct ParachainBlockData { + /// The header of the parachain block. + header: ::Header, + /// The extrinsics of the parachain block without the `PolkadotInherent`. extrinsics: Vec<::Extrinsic>, /// The data that is required to emulate the storage accesses executed by all extrinsics. witness_data: WitnessData, + witness_data_storage_root: ::Hash, } impl ParachainBlockData { - #[cfg(test)] - fn new( + pub fn new( + header: ::Header, extrinsics: Vec<::Extrinsic>, - witness_data: WitnessData + witness_data: WitnessData, + witness_data_storage_root: ::Hash, ) -> Self { Self { + header, extrinsics, witness_data, - } - } -} - -impl Default for ParachainBlockData { - fn default() -> Self { - Self { - extrinsics: Vec::default(), - witness_data: WitnessData::default(), + witness_data_storage_root, } } } \ No newline at end of file diff --git a/runtime/src/validate_block/implementation.rs b/runtime/src/validate_block/implementation.rs index 95ffa86c9c..05a4d74d5f 100644 --- a/runtime/src/validate_block/implementation.rs +++ b/runtime/src/validate_block/implementation.rs @@ -18,16 +18,22 @@ use crate::WitnessData; use runtime_primitives::traits::{ - Block as BlockT, Header as HeaderT, One, Hash as HashT + Block as BlockT, Header as HeaderT, Hash as HashT }; use executive::ExecuteBlock; -use substrate_trie::{MemoryDB, read_trie_value}; +use substrate_trie::{MemoryDB, read_trie_value, delta_trie_root}; use rstd::{slice, ptr, cmp, vec::Vec, boxed::Box, mem}; use hash_db::HashDB; +static mut STORAGE: Option> = None; +/// The message to use as expect message while accessing the `STORAGE`. +const STORAGE_SET_EXPECT: &str = + "`STORAGE` needs to be set before calling this function."; +const STORAGE_ROOT_LEN: usize = 32; + /// Extract the hashing algorithm type from the given block type. type HashingOf = <::Header as HeaderT>::Hashing; /// Extract the hash type from the given block type. @@ -43,30 +49,27 @@ trait StorageT { /// Remove key and value. fn remove(&mut self, key: &[u8]); -} -static mut STORAGE: Option> = None; -/// The message to use as expect message while accessing the `STORAGE`. -const STORAGE_SET_EXPECT: &str = - "`STORAGE` needs to be set before calling this function."; + /// Calculate the storage root. + fn storage_root(&mut self) -> [u8; STORAGE_ROOT_LEN]; +} /// Validate a given parachain block on a validator. #[cfg(not(feature = "std"))] #[doc(hidden)] pub fn validate_block>( - mut block: &[u8], - mut prev_head: &[u8] + mut block_data: &[u8], ) { use codec::Decode; - let block = crate::ParachainBlockData::::decode(&mut block) + let block_data = crate::ParachainBlockData::::decode(&mut block_data) .expect("Could not decode parachain block."); - let parent_header = <::Header as Decode>::decode(&mut prev_head) - .expect("Could not decode parent header."); + // TODO: Add `PolkadotInherent`. + let block = B::new(block_data.header, block_data.extrinsics); let storage = Storage::::new( - block.witness_data, - parent_header.state_root().clone() - ).expect("Create storage out of witness data."); + block_data.witness_data, + block_data.witness_data_storage_root, + ).expect("Witness data and storage root always match; qed"); let _guard = unsafe { STORAGE = Some(Box::new(storage)); @@ -77,11 +80,11 @@ pub fn validate_block>( rio::ext_set_storage.replace_implementation(ext_set_storage), rio::ext_exists_storage.replace_implementation(ext_exists_storage), rio::ext_clear_storage.replace_implementation(ext_clear_storage), + rio::ext_storage_root.replace_implementation(ext_storage_root), ) }; - let block_number = *parent_header.number() + One::one(); - //E::execute_extrinsics_without_checks(block_number, block.extrinsics); + E::execute_block(block); } /// The storage implementation used when validating a block. @@ -131,9 +134,25 @@ impl StorageT for Storage { fn remove(&mut self, key: &[u8]) { self.overlay.insert(key.to_vec(), None); } + + fn storage_root(&mut self) -> [u8; STORAGE_ROOT_LEN] { + let root = match delta_trie_root( + &mut self.witness_data, + self.storage_root.clone(), + self.overlay.drain() + ) { + Ok(root) => root, + Err(_) => return [0; STORAGE_ROOT_LEN], + }; + + assert!(root.as_ref().len() != STORAGE_ROOT_LEN); + let mut res = [0; STORAGE_ROOT_LEN]; + res.copy_from_slice(root.as_ref()); + res + } } -pub unsafe fn ext_get_allocated_storage( +unsafe fn ext_get_allocated_storage( key_data: *const u8, key_len: u32, written_out: *mut u32, @@ -153,7 +172,7 @@ pub unsafe fn ext_get_allocated_storage( } } -pub unsafe fn ext_set_storage( +unsafe fn ext_set_storage( key_data: *const u8, key_len: u32, value_data: *const u8, @@ -165,7 +184,7 @@ pub unsafe fn ext_set_storage( STORAGE.as_mut().expect(STORAGE_SET_EXPECT).insert(key, value); } -pub unsafe fn ext_get_storage_into( +unsafe fn ext_get_storage_into( key_data: *const u8, key_len: u32, value_data: *mut u8, @@ -188,7 +207,7 @@ pub unsafe fn ext_get_storage_into( } } -pub unsafe fn ext_exists_storage(key_data: *const u8, key_len: u32) -> u32 { +unsafe fn ext_exists_storage(key_data: *const u8, key_len: u32) -> u32 { let key = slice::from_raw_parts(key_data, key_len as usize); if STORAGE.as_mut().expect(STORAGE_SET_EXPECT).get(key).is_some() { @@ -198,8 +217,14 @@ pub unsafe fn ext_exists_storage(key_data: *const u8, key_len: u32) -> u32 { } } -pub unsafe fn ext_clear_storage(key_data: *const u8, key_len: u32) { +unsafe fn ext_clear_storage(key_data: *const u8, key_len: u32) { let key = slice::from_raw_parts(key_data, key_len as usize); STORAGE.as_mut().expect(STORAGE_SET_EXPECT).remove(key); +} + +unsafe fn ext_storage_root(result: *mut u8) { + let res = STORAGE.as_mut().expect(STORAGE_SET_EXPECT).storage_root(); + let result = slice::from_raw_parts_mut(result, STORAGE_ROOT_LEN); + result.copy_from_slice(&res); } \ No newline at end of file diff --git a/runtime/src/validate_block/mod.rs b/runtime/src/validate_block/mod.rs index f5230ba3aa..c973a6798e 100644 --- a/runtime/src/validate_block/mod.rs +++ b/runtime/src/validate_block/mod.rs @@ -56,11 +56,18 @@ macro_rules! register_validate_block_impl { use super::*; #[no_mangle] - unsafe fn validate_block(block: *const u8, block_len: u64, prev_head: *const u8, prev_head_len: u64) { - let block = $crate::slice::from_raw_parts(block, block_len as usize); - let prev_head = $crate::slice::from_raw_parts(prev_head, prev_head_len as usize); + unsafe fn validate_block( + block_data: *const u8, + block_data_len: u64, + ) { + let block_data = $crate::slice::from_raw_parts( + block_data, + block_data_len as usize, + ); - $crate::validate_block::implementation::validate_block::<$block, $block_executor>(block, prev_head); + $crate::validate_block::implementation::validate_block::< + $block, $block_executor + >(block_data); } } };