From 6413c3557e21cfdd5c25fa7485773799a8637eb2 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Mon, 29 Apr 2019 20:58:01 +0300 Subject: [PATCH 1/3] Pass parent hash to the validate_block function --- runtime/src/validate_block/implementation.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/runtime/src/validate_block/implementation.rs b/runtime/src/validate_block/implementation.rs index a7c725382..a1f21241f 100644 --- a/runtime/src/validate_block/implementation.rs +++ b/runtime/src/validate_block/implementation.rs @@ -23,6 +23,7 @@ use runtime_primitives::traits::{ use executive::ExecuteBlock; use substrate_trie::{MemoryDB, read_trie_value, delta_trie_root}; +use codec::Decode; use rstd::{slice, ptr, cmp, vec::Vec, boxed::Box, mem}; @@ -56,14 +57,14 @@ trait Storage { #[cfg(not(feature = "std"))] #[doc(hidden)] pub fn validate_block>( - mut block_data: &[u8], + mut arguments: &[u8], ) { - use codec::Decode; - - let block_data = crate::ParachainBlockData::::decode(&mut block_data) + let (parent_hash, block_data): (B::Hash, crate::ParachainBlockData::) = Decode::decode(&mut arguments) .expect("Could not decode parachain block."); // TODO: Add `PolkadotInherent`. let block = B::new(block_data.header, block_data.extrinsics); + assert!(parent_hash == *block.header().parent_hash(), "Invalid parent hash"); + let storage = WitnessStorage::::new( block_data.witness_data, block_data.witness_data_storage_root, From cd6fd5ea5313c639875b145ff2608ca5db96deba Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 30 Apr 2019 15:10:31 +0300 Subject: [PATCH 2/3] Fix tests --- runtime/src/validate_block/implementation.rs | 3 ++- runtime/src/validate_block/mod.rs | 12 ++++++------ runtime/src/validate_block/tests.rs | 17 +++++++++-------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/runtime/src/validate_block/implementation.rs b/runtime/src/validate_block/implementation.rs index a1f21241f..d61641926 100644 --- a/runtime/src/validate_block/implementation.rs +++ b/runtime/src/validate_block/implementation.rs @@ -23,7 +23,6 @@ use runtime_primitives::traits::{ use executive::ExecuteBlock; use substrate_trie::{MemoryDB, read_trie_value, delta_trie_root}; -use codec::Decode; use rstd::{slice, ptr, cmp, vec::Vec, boxed::Box, mem}; @@ -59,6 +58,8 @@ trait Storage { pub fn validate_block>( mut arguments: &[u8], ) { + use codec::Decode; + let (parent_hash, block_data): (B::Hash, crate::ParachainBlockData::) = Decode::decode(&mut arguments) .expect("Could not decode parachain block."); // TODO: Add `PolkadotInherent`. diff --git a/runtime/src/validate_block/mod.rs b/runtime/src/validate_block/mod.rs index c973a6798..99adf3a08 100644 --- a/runtime/src/validate_block/mod.rs +++ b/runtime/src/validate_block/mod.rs @@ -57,17 +57,17 @@ macro_rules! register_validate_block_impl { #[no_mangle] unsafe fn validate_block( - block_data: *const u8, - block_data_len: u64, + arguments: *const u8, + arguments_len: u64, ) { - let block_data = $crate::slice::from_raw_parts( - block_data, - block_data_len as usize, + let arguments = $crate::slice::from_raw_parts( + arguments, + arguments_len as usize, ); $crate::validate_block::implementation::validate_block::< $block, $block_executor - >(block_data); + >(arguments); } } }; diff --git a/runtime/src/validate_block/tests.rs b/runtime/src/validate_block/tests.rs index ef4c81b92..4d1d336a6 100644 --- a/runtime/src/validate_block/tests.rs +++ b/runtime/src/validate_block/tests.rs @@ -23,7 +23,8 @@ use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; use executor::{WasmExecutor, error::Result, wasmi::RuntimeValue::{I64, I32}}; use test_client::{ TestClientBuilder, TestClient, - runtime::{Block, Transfer}, TestClientBuilderExt, + runtime::{Block, Transfer, Hash}, TestClientBuilderExt, + client_ext::TestClient as _, }; use std::collections::HashMap; @@ -33,7 +34,7 @@ use codec::Encode; const WASM_CODE: &[u8] = include_bytes!("../../../test/runtime/wasm/target/wasm32-unknown-unknown/release/cumulus_test_runtime.compact.wasm"); -fn call_validate_block(block_data: ParachainBlockData) -> Result<()> { +fn call_validate_block(parent_hash: Hash, block_data: ParachainBlockData) -> Result<()> { let mut ext = TestExternalities::default(); WasmExecutor::new().call_with_custom_signature( &mut ext, @@ -41,13 +42,13 @@ fn call_validate_block(block_data: ParachainBlockData) -> Result<()> { &WASM_CODE, "validate_block", |alloc| { - let block_data = block_data.encode(); - let block_data_offset = alloc(&block_data)?; + let arguments = (parent_hash, block_data).encode(); + let arguments_offset = alloc(&arguments)?; Ok( vec![ - I32(block_data_offset as i32), - I64(block_data.len() as i64), + I32(arguments_offset as i32), + I64(arguments.len() as i64), ] ) }, @@ -131,7 +132,7 @@ fn validate_block_with_no_extrinsics() { witness_data, witness_data_storage_root ); - call_validate_block(block_data).expect("Calls `validate_block`"); + call_validate_block(client.genesis_hash(), block_data).expect("Calls `validate_block`"); } #[test] @@ -150,5 +151,5 @@ fn validate_block_with_extrinsics() { witness_data, witness_data_storage_root ); - call_validate_block(block_data).expect("Calls `validate_block`"); + call_validate_block(client.genesis_hash(), block_data).expect("Calls `validate_block`"); } \ No newline at end of file From 41f4460872303f23d106800aff4b92f0159d3558 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Fri, 3 May 2019 13:50:54 +0300 Subject: [PATCH 3/3] Add test --- runtime/src/validate_block/tests.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/runtime/src/validate_block/tests.rs b/runtime/src/validate_block/tests.rs index 4d1d336a6..8289d3388 100644 --- a/runtime/src/validate_block/tests.rs +++ b/runtime/src/validate_block/tests.rs @@ -152,4 +152,25 @@ fn validate_block_with_extrinsics() { witness_data_storage_root ); call_validate_block(client.genesis_hash(), block_data).expect("Calls `validate_block`"); -} \ No newline at end of file +} + +#[test] +#[should_panic] +fn validate_block_invalid_parent_hash() { + let client = create_test_client(); + let witness_data_storage_root = *client + .best_block_header() + .expect("Best block exists") + .state_root(); + let (block, witness_data) = build_block_with_proof(&client, Vec::new()); + let (mut header, extrinsics) = block.deconstruct(); + header.set_parent_hash(Hash::from_low_u64_be(1)); + + let block_data = ParachainBlockData::new( + header, + extrinsics, + witness_data, + witness_data_storage_root + ); + call_validate_block(client.genesis_hash(), block_data).expect("Calls `validate_block`"); +}