Skip to content

Commit

Permalink
Merge pull request #12 from paritytech/bkchr-validate_block_2
Browse files Browse the repository at this point in the history
Switch to `parachain::ValidationParams`
  • Loading branch information
bkchr authored Jun 21, 2019
2 parents 1f76160 + a36527e commit 6c5fddd
Show file tree
Hide file tree
Showing 17 changed files with 608 additions and 1,492 deletions.
955 changes: 430 additions & 525 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[workspace]
members = [
"consensus",
"runtime",
"test/runtime",
members = [
"consensus",
"runtime",
"test/runtime",
"test/client",
]
4 changes: 2 additions & 2 deletions consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,13 @@ impl<B, E, RA> PolkadotClient for Arc<Client<B, E, PBlock, RA>> where

fn head_updates(&self, para_id: ParaId) -> Self::HeadUpdates {
let parachain_key = parachain_key(para_id);
let stream = stream::once(self.storage_changes_notification_stream(Some(&[parachain_key.clone()])))
let stream = stream::once(self.storage_changes_notification_stream(Some(&[parachain_key.clone()]), None))
.map(|s| s.map_err(|()| panic!("unbounded receivers never yield errors; qed")))
.flatten();

let s = stream.filter_map(move |(hash, changes)| {
let head_data = changes.iter()
.filter_map(|(k, v)| if k == &parachain_key { Some(v) } else { None })
.filter_map(|(_, k, v)| if k == &parachain_key { Some(v) } else { None })
.next();

match head_data {
Expand Down
16 changes: 11 additions & 5 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,26 @@ authors = ["Parity Technologies <[email protected]>"]
edition = "2018"

[dependencies]
codec = { package = "parity-codec", version = "3.1", default-features = false, features = [ "derive" ] }
# Substrate dependencies
rstd = { package = "sr-std", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
runtime-primitives = { package = "sr-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
rio = { package = "sr-io", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
executive = { package = "srml-executive", git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }
substrate-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }

# Polkadot dependencies
parachain = { package = "polkadot-parachain", git = "https://github.com/paritytech/polkadot", default-features = false, branch = "bkchr-cumulus-branch" }

# Other deps
codec = { package = "parity-codec", version = "3.5.1", default-features = false, features = [ "derive" ] }
memory-db = { version = "0.12.2", default-features = false }
hash-db = { version = "0.12.2", default-features = false }
trie-db = { version = "0.12.2", default-features = false }
hashbrown = "0.1"
hashbrown = "0.5.0"

[dev-dependencies]
keyring = { package = "substrate-keyring", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
executor = { package = "substrate-executor", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
consensus-common = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
test-client = { package = "cumulus-test-client", path = "../test/client" }
Expand All @@ -36,10 +41,11 @@ std = [
"memory-db/std",
"hash-db/std",
"trie-db/std",
"test-client/std",
"substrate-trie/std",
"parachain/std",
]
wasm = [
no_std = [
"hashbrown/nightly",
"rio/wasm-nice-panic-message",
"parachain/wasm-api",
]
16 changes: 10 additions & 6 deletions runtime/src/validate_block/implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ use rstd::{slice, ptr, cmp, vec::Vec, boxed::Box, mem};

use hash_db::HashDB;

static mut STORAGE: Option<Box<Storage>> = None;
use parachain::ValidationParams;

static mut STORAGE: Option<Box<dyn Storage>> = 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.";
Expand All @@ -53,18 +55,20 @@ trait Storage {
}

/// Validate a given parachain block on a validator.
#[cfg(not(feature = "std"))]
#[doc(hidden)]
pub fn validate_block<B: BlockT, E: ExecuteBlock<B>>(
mut arguments: &[u8],
params: ValidationParams,
) {
use codec::Decode;

let (parent_hash, block_data): (B::Hash, crate::ParachainBlockData::<B>) = Decode::decode(&mut arguments)
.expect("Could not decode parachain block.");
let block_data = crate::ParachainBlockData::<B>::decode(&mut &params.block_data[..])
.expect("Invalid parachain block data");

let parent_head = B::Header::decode(&mut &params.parent_head[..]).expect("Invalid parent head");

// TODO: Add `PolkadotInherent`.
let block = B::new(block_data.header, block_data.extrinsics);
assert!(parent_hash == *block.header().parent_hash(), "Invalid parent hash");
assert!(parent_head.hash() == *block.header().parent_hash(), "Invalid parent hash");

let storage = WitnessStorage::<B>::new(
block_data.witness_data,
Expand Down
12 changes: 8 additions & 4 deletions runtime/src/validate_block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ mod tests;
#[doc(hidden)]
pub mod implementation;

#[cfg(not(feature = "std"))]
#[doc(hidden)]
pub use parachain;

/// Register the `validate_block` function that is used by parachains to validate blocks on a validator.
///
/// Does *nothing* when `std` feature is enabled.
Expand Down Expand Up @@ -58,16 +62,16 @@ macro_rules! register_validate_block_impl {
#[no_mangle]
unsafe fn validate_block(
arguments: *const u8,
arguments_len: u64,
arguments_len: usize,
) {
let arguments = $crate::slice::from_raw_parts(
let params = $crate::validate_block::parachain::wasm_api::load_params(
arguments,
arguments_len as usize,
arguments_len,
);

$crate::validate_block::implementation::validate_block::<
$block, $block_executor
>(arguments);
>(params);
}
}
};
Expand Down
65 changes: 28 additions & 37 deletions runtime/src/validate_block/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,36 @@ use crate::{ParachainBlockData, WitnessData};

use rio::TestExternalities;
use keyring::AccountKeyring;
use primitives::{storage::well_known_keys};
use runtime_primitives::{generic::BlockId, traits::{Block as BlockT, Header as HeaderT}};
use executor::{WasmExecutor, error::Result, wasmi::RuntimeValue::{I64, I32}};
use test_client::{TestClientBuilder, TestClient, LongestChain, runtime::{Block, Transfer, Hash}};
use executor::{WasmExecutor, error::Result, wasmi::RuntimeValue::I32};
use test_client::{
TestClientBuilder, TestClientBuilderExt, DefaultTestClientBuilderExt, Client, LongestChain,
runtime::{Block, Transfer, Hash, WASM_BINARY, Header}
};
use consensus_common::SelectChain;

use std::collections::HashMap;
use parachain::ValidationParams;

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(parent_hash: Hash, block_data: ParachainBlockData<Block>) -> Result<()> {
fn call_validate_block(parent_head: Header, block_data: ParachainBlockData<Block>) -> Result<()> {
let mut ext = TestExternalities::default();
WasmExecutor::new().call_with_custom_signature(
&mut ext,
1024,
&WASM_CODE,
&WASM_BINARY,
"validate_block",
|alloc| {
let arguments = (parent_hash, block_data).encode();
let arguments_offset = alloc(&arguments)?;
let params = ValidationParams {
block_data: block_data.encode(),
parent_head: parent_head.encode(),
ingress: Vec::new(),
}.encode();
let params_offset = alloc(&params)?;

Ok(
vec![
I32(arguments_offset as i32),
I64(arguments.len() as i64),
I32(params_offset as i32),
I32(params.len() as i32),
]
)
},
Expand Down Expand Up @@ -88,17 +90,12 @@ fn create_extrinsics() -> Vec<<Block as BlockT>::Extrinsic> {
]
}

fn create_test_client() -> (TestClient, LongestChain) {
let mut genesis_extension = HashMap::new();
genesis_extension.insert(well_known_keys::CODE.to_vec(), WASM_CODE.to_vec());

TestClientBuilder::new()
.set_genesis_extension(genesis_extension)
.build_with_longest_chain()
fn create_test_client() -> (Client, LongestChain) {
TestClientBuilder::new().build_with_longest_chain()
}

fn build_block_with_proof(
client: &TestClient,
client: &Client,
extrinsics: Vec<<Block as BlockT>::Extrinsic>,
) -> (Block, WitnessData) {
let block_id = BlockId::Hash(client.info().chain.best_hash);
Expand All @@ -119,10 +116,8 @@ fn build_block_with_proof(
#[test]
fn validate_block_with_no_extrinsics() {
let (client, longest_chain) = create_test_client();
let witness_data_storage_root = *longest_chain
.best_chain()
.expect("Best block exists")
.state_root();
let parent_head = longest_chain.best_chain().expect("Best block exists");
let witness_data_storage_root = *parent_head.state_root();
let (block, witness_data) = build_block_with_proof(&client, Vec::new());
let (header, extrinsics) = block.deconstruct();

Expand All @@ -132,16 +127,14 @@ fn validate_block_with_no_extrinsics() {
witness_data,
witness_data_storage_root
);
call_validate_block(client.info().chain.genesis_hash, block_data).expect("Calls `validate_block`");
call_validate_block(parent_head, block_data).expect("Calls `validate_block`");
}

#[test]
fn validate_block_with_extrinsics() {
let (client, longest_chain) = create_test_client();
let witness_data_storage_root = *longest_chain
.best_chain()
.expect("Best block exists")
.state_root();
let parent_head = longest_chain.best_chain().expect("Best block exists");
let witness_data_storage_root = *parent_head.state_root();
let (block, witness_data) = build_block_with_proof(&client, create_extrinsics());
let (header, extrinsics) = block.deconstruct();

Expand All @@ -151,17 +144,15 @@ fn validate_block_with_extrinsics() {
witness_data,
witness_data_storage_root
);
call_validate_block(client.info().chain.genesis_hash, block_data).expect("Calls `validate_block`");
call_validate_block(parent_head, block_data).expect("Calls `validate_block`");
}

#[test]
#[should_panic]
fn validate_block_invalid_parent_hash() {
let (client, longest_chain) = create_test_client();
let witness_data_storage_root = *longest_chain
.best_chain()
.expect("Best block exists")
.state_root();
let parent_head = longest_chain.best_chain().expect("Best block exists");
let witness_data_storage_root = *parent_head.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));
Expand All @@ -172,5 +163,5 @@ fn validate_block_invalid_parent_hash() {
witness_data,
witness_data_storage_root
);
call_validate_block(client.info().chain.genesis_hash, block_data).expect("Calls `validate_block`");
call_validate_block(parent_head, block_data).expect("Calls `validate_block`");
}
28 changes: 0 additions & 28 deletions scripts/build.sh

This file was deleted.

18 changes: 0 additions & 18 deletions scripts/common.sh

This file was deleted.

11 changes: 4 additions & 7 deletions test/client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ authors = ["Parity Technologies <[email protected]>"]
edition = "2018"

[dependencies]
substrate-test-client = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "bkchr-cumulus-branch" }

[features]
default = ["std"]
std = [
"substrate-test-client/std",
]
test-client = { package = "substrate-test-client", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
runtime = { package = "cumulus-test-runtime", path = "../runtime" }
runtime_primitives = { package = "sr-primitives", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
Loading

0 comments on commit 6c5fddd

Please sign in to comment.