From 692770e03f15bf51465311978f3a543e122356ff Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 7 Feb 2018 18:44:00 +0100 Subject: [PATCH] Split up substrate-executor into polkadot-executor. --- substrate/Cargo.lock | 60 +++-- substrate/Cargo.toml | 1 + substrate/cli/Cargo.toml | 11 +- substrate/{client => cli}/src/genesis.rs | 8 +- substrate/cli/src/lib.rs | 26 +- substrate/client/Cargo.toml | 4 +- substrate/client/src/lib.rs | 9 +- substrate/executor/Cargo.toml | 3 - substrate/executor/src/lib.rs | 18 +- substrate/executor/src/native_executor.rs | 248 +---------------- substrate/executor/src/wasm_executor.rs | 56 +--- substrate/executor/src/wasm_utils.rs | 7 - substrate/network/Cargo.toml | 4 +- substrate/network/src/lib.rs | 2 +- substrate/polkadot-executor/Cargo.toml | 17 ++ substrate/polkadot-executor/src/lib.rs | 315 ++++++++++++++++++++++ substrate/rpc/Cargo.toml | 4 +- substrate/rpc/src/chain/tests.rs | 2 +- substrate/rpc/src/lib.rs | 4 +- substrate/rpc/src/state/tests.rs | 2 +- 20 files changed, 445 insertions(+), 356 deletions(-) rename substrate/{client => cli}/src/genesis.rs (94%) create mode 100644 substrate/polkadot-executor/Cargo.toml create mode 100644 substrate/polkadot-executor/src/lib.rs diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 8f333b159e..e58fd510ed 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -986,30 +986,20 @@ name = "polkadot-cli" version = "0.1.0" dependencies = [ "clap 2.29.4 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "polkadot-client 0.1.0", - "polkadot-rpc-servers 0.1.0", - "substrate-executor 0.1.0", - "substrate-primitives 0.1.0", -] - -[[package]] -name = "polkadot-client" -version = "0.1.0" -dependencies = [ "ed25519 0.1.0", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "native-runtime 0.1.0", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "polkadot-executor 0.1.0", "polkadot-primitives 0.1.0", + "polkadot-rpc-servers 0.1.0", + "substrate-client 0.1.0", "substrate-codec 0.1.0", "substrate-executor 0.1.0", "substrate-primitives 0.1.0", - "substrate-serializer 0.1.0", + "substrate-runtime-io 0.1.0", "substrate-state-machine 0.1.0", "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1023,6 +1013,22 @@ dependencies = [ "substrate-primitives 0.1.0", ] +[[package]] +name = "polkadot-executor" +version = "0.1.0" +dependencies = [ + "ed25519 0.1.0", + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "native-runtime 0.1.0", + "polkadot-primitives 0.1.0", + "substrate-codec 0.1.0", + "substrate-executor 0.1.0", + "substrate-primitives 0.1.0", + "substrate-runtime-io 0.1.0", + "substrate-state-machine 0.1.0", + "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "polkadot-network" version = "0.1.0" @@ -1036,7 +1042,6 @@ dependencies = [ "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "polkadot-client 0.1.0", "polkadot-primitives 0.1.0", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1044,6 +1049,7 @@ dependencies = [ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-client 0.1.0", "substrate-primitives 0.1.0", "substrate-serializer 0.1.0", "substrate-state-machine 0.1.0", @@ -1070,7 +1076,8 @@ dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)", "jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "polkadot-client 0.1.0", + "polkadot-executor 0.1.0", + "substrate-client 0.1.0", "substrate-executor 0.1.0", "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", @@ -1413,6 +1420,23 @@ name = "strsim" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "substrate-client" +version = "0.1.0" +dependencies = [ + "ed25519 0.1.0", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-codec 0.1.0", + "substrate-executor 0.1.0", + "substrate-primitives 0.1.0", + "substrate-serializer 0.1.0", + "substrate-state-machine 0.1.0", + "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-codec" version = "0.1.0" @@ -1430,9 +1454,7 @@ dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "native-runtime 0.1.0", "parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", - "polkadot-primitives 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index 4780426456..5d275c2caa 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -22,6 +22,7 @@ members = [ "rpc", "codec", "polkadot-primitives", + "polkadot-executor", "runtime-io", "runtime-std", "serializer", diff --git a/substrate/cli/Cargo.toml b/substrate/cli/Cargo.toml index 74299ec2eb..aa8989d2af 100644 --- a/substrate/cli/Cargo.toml +++ b/substrate/cli/Cargo.toml @@ -9,7 +9,16 @@ clap = { version = "2.27", features = ["yaml"] } env_logger = "0.4" error-chain = "0.11" log = "0.3" -polkadot-client = { path = "../client" } +hex-literal = "0.1" +ed25519 = { path = "../ed25519" } +triehash = { version = "0.1" } +substrate-client = { path = "../client" } +substrate-codec = { path = "../codec" } +substrate-runtime-io = { path = "../runtime-io" } +substrate-state-machine = { path = "../state-machine" } substrate-executor = { path = "../executor" } substrate-primitives = { path = "../primitives" } polkadot-rpc-servers = { path = "../rpc-servers" } +polkadot-primitives = { path = "../polkadot-primitives" } +polkadot-executor = { path = "../polkadot-executor" } +native-runtime = { path = "../native-runtime" } diff --git a/substrate/client/src/genesis.rs b/substrate/cli/src/genesis.rs similarity index 94% rename from substrate/client/src/genesis.rs rename to substrate/cli/src/genesis.rs index 788513ffa6..25c1744ab1 100644 --- a/substrate/client/src/genesis.rs +++ b/substrate/cli/src/genesis.rs @@ -1,18 +1,18 @@ // Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// This file is part of Substrate. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Polkadot is distributed in the hope that it will be useful, +// Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . +// along with Substrate. If not, see . //! Tool for creating the genesis block. diff --git a/substrate/cli/src/lib.rs b/substrate/cli/src/lib.rs index faad72526e..d18c40b013 100644 --- a/substrate/cli/src/lib.rs +++ b/substrate/cli/src/lib.rs @@ -19,11 +19,22 @@ #![warn(missing_docs)] extern crate env_logger; -extern crate polkadot_client as client; -extern crate substrate_executor as executor; +extern crate ed25519; +extern crate triehash; +extern crate substrate_codec as codec; +extern crate substrate_state_machine as state_machine; +extern crate substrate_client as client; +extern crate substrate_executor; extern crate substrate_primitives as primitives; +extern crate substrate_runtime_io as runtime_io; extern crate polkadot_rpc_servers as rpc; +extern crate polkadot_primitives; +extern crate polkadot_executor as executor; +extern crate native_runtime; +#[cfg(test)] +#[macro_use] +extern crate hex_literal; #[macro_use] extern crate clap; #[macro_use] @@ -31,6 +42,14 @@ extern crate error_chain; #[macro_use] extern crate log; +// TODO: move into own crate. +#[cfg(test)] +macro_rules! map { + ($( $name:expr => $value:expr ),*) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ) +} + pub mod error; /// Parse command line arguments and start the node. @@ -54,7 +73,7 @@ pub fn run(args: I) -> error::Result<()> where // Create client let executor = executor::executor(); - let client = client::new_in_mem(executor)?; + let client = client::new_in_mem(executor)?; // TODO: pass in genesis builder. let address = "127.0.0.1:9933".parse().unwrap(); let handler = rpc::rpc_handler(client); @@ -94,4 +113,3 @@ fn init_logger(pattern: &str) { builder.init().expect("Logger initialized only once."); } - diff --git a/substrate/client/Cargo.toml b/substrate/client/Cargo.toml index b5ee065dbb..ebe3adba77 100644 --- a/substrate/client/Cargo.toml +++ b/substrate/client/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "polkadot-client" +name = "substrate-client" version = "0.1.0" authors = ["Parity Technologies "] @@ -7,13 +7,11 @@ authors = ["Parity Technologies "] error-chain = "0.11" log = "0.3" parking_lot = "0.4" -polkadot-primitives = { path = "../polkadot-primitives", version = "0.1" } substrate-primitives = { path = "../primitives", version = "0.1" } substrate-state-machine = { path = "../state-machine", version = "0.1" } substrate-serializer = { path = "../serializer" } substrate-executor = { path = "../executor" } substrate-codec = { path = "../codec", version = "0.1" } -native-runtime = { path = "../native-runtime" } triehash = "0.1" hex-literal = "0.1" ed25519 = { path = "../ed25519", version = "0.1" } diff --git a/substrate/client/src/lib.rs b/substrate/client/src/lib.rs index f0d1fd1a63..3f29842c00 100644 --- a/substrate/client/src/lib.rs +++ b/substrate/client/src/lib.rs @@ -18,13 +18,11 @@ #![warn(missing_docs)] -extern crate polkadot_primitives; extern crate substrate_primitives as primitives; extern crate substrate_state_machine as state_machine; extern crate substrate_serializer as ser; extern crate substrate_codec as codec; extern crate substrate_executor; -extern crate native_runtime; extern crate ed25519; extern crate triehash; @@ -41,10 +39,6 @@ pub mod blockchain; pub mod backend; pub mod in_mem; -mod genesis; - -pub use genesis::construct_genesis_block; - pub use blockchain::Info as ChainInfo; pub use blockchain::BlockId; @@ -109,7 +103,6 @@ pub enum BlockStatus { Unknown, } - /// Create an instance of in-memory client. pub fn new_in_mem(executor: E) -> error::Result> where E: state_machine::CodeExecutor { Client::new(in_mem::Backend::new(), executor) @@ -124,7 +117,7 @@ impl Client where pub fn new(backend: B, executor: E) -> error::Result { if backend.blockchain().header(BlockId::Number(0))?.is_none() { trace!("Empty database, writing genesis block"); - // TODO: spec + // TODO: spec, coming in from new_in_mem's params. let genesis_header = block::Header { parent_hash: Default::default(), number: 0, diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index 8d2643d585..7a4a5c8af0 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -19,9 +19,6 @@ rustc-hex = "1.0.0" triehash = "0.1.0" hex-literal = "0.1.0" log = "0.3" -# TODO: Remove these and split out tests and a concrete executor. -native-runtime = { path = "../native-runtime" } -polkadot-primitives = { path = "../polkadot-primitives" } [dev-dependencies] assert_matches = "1.1" diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index 88c52c9389..44656fab5b 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -41,10 +41,6 @@ extern crate rustc_hex; extern crate triehash; #[macro_use] extern crate log; -// TODO: Remove and split out into polkadot-specific crate. -extern crate native_runtime; -extern crate polkadot_primitives; - #[cfg(test)] #[macro_use] extern crate hex_literal; @@ -55,14 +51,18 @@ extern crate error_chain; #[cfg(test)] extern crate assert_matches; +// TODO: move into own crate +macro_rules! map { + ($( $name:expr => $value:expr ),*) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ) +} + #[macro_use] mod wasm_utils; mod wasm_executor; mod native_executor; pub mod error; - -/// Creates new RustExecutor for contracts. -pub fn executor() -> native_executor::NativeExecutor { - native_executor::NativeExecutor -} +pub use wasm_executor::WasmExecutor; +pub use native_executor::{NativeExecutionDispatch, NativeExecutor}; diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index e4812be894..eef18be128 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -15,20 +15,26 @@ // along with Substrate. If not, see . use error::{Error, ErrorKind, Result}; -use native_runtime as runtime; use runtime_io; use state_machine::{Externalities, CodeExecutor}; use wasm_executor::WasmExecutor; use std::panic::catch_unwind; -pub struct NativeExecutor; +pub trait NativeExecutionDispatch { + fn native_equivalent() -> &'static [u8]; + fn dispatch(method: &str, data: &[u8]) -> Option>; +} -fn safe_call Vec>(f: F) -> Result> { +pub struct NativeExecutor { + pub _dummy: ::std::marker::PhantomData, +} + +fn safe_call Option>>(f: F) -> Result>> { catch_unwind(f).map_err(|_| ErrorKind::Runtime.into()) } -impl CodeExecutor for NativeExecutor { +impl CodeExecutor for NativeExecutor { type Error = Error; fn call( @@ -38,240 +44,12 @@ impl CodeExecutor for NativeExecutor { method: &str, data: &[u8], ) -> Result> { - // WARNING!!! This assumes that the runtime was built *before* the main project. Until we - // get a proper build script, this must be strictly adhered to or things will go wrong. - let native_equivalent = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); - if code == &native_equivalent[..] { - runtime_io::with_externalities(ext, || match method { - "execute_block" => safe_call(|| runtime::execute_block(data)), - "execute_transaction" => safe_call(|| runtime::execute_transaction(data)), - "finalise_block" => safe_call(|| runtime::finalise_block(data)), - _ => Err(ErrorKind::MethodNotFound(method.to_owned()).into()), - }) + if code == D::native_equivalent() { + runtime_io::with_externalities(ext, || safe_call(|| D::dispatch(method, data)))? + .ok_or(ErrorKind::MethodNotFound(method.to_owned()).into()) } else { // call into wasm. WasmExecutor.call(ext, code, method, data) } } } - -#[cfg(test)] -mod tests { - use super::*; - use codec::{KeyedVec, Slicable, Joiner}; - use native_runtime::support::{one, two, Hashable}; - use native_runtime::runtime::staking::balance; - use state_machine::TestExternalities; - use primitives::twox_128; - use polkadot_primitives::{Hash, Header, BlockNumber, Block, Digest, Transaction, - UncheckedTransaction, Function, AccountId}; - use ed25519::Pair; - - const BLOATY_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); - const COMPACT_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); - - fn tx() -> UncheckedTransaction { - let transaction = Transaction { - signed: one(), - nonce: 0, - function: Function::StakingTransfer(two(), 69), - }; - let signature = secret_for(&transaction.signed).unwrap() - .sign(&transaction.to_vec()); - - UncheckedTransaction { transaction, signature } - } - - #[test] - fn panic_execution_with_foreign_code_gives_error() { - let one = one(); - let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] - ], }; - - let r = NativeExecutor.call(&mut t, BLOATY_CODE, "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); - assert!(r.is_err()); - } - - #[test] - fn panic_execution_with_native_equivalent_code_gives_error() { - let one = one(); - let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] - ], }; - - let r = NativeExecutor.call(&mut t, COMPACT_CODE, "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); - assert!(r.is_err()); - } - - #[test] - fn successful_execution_with_native_equivalent_code_gives_ok() { - let one = one(); - let two = two(); - - let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ], }; - - let r = NativeExecutor.call(&mut t, COMPACT_CODE, "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); - assert!(r.is_ok()); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&one), 42); - assert_eq!(balance(&two), 69); - }); - } - - #[test] - fn successful_execution_with_foreign_code_gives_ok() { - let one = one(); - let two = two(); - - let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ], }; - - let r = NativeExecutor.call(&mut t, BLOATY_CODE, "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); - assert!(r.is_ok()); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&one), 42); - assert_eq!(balance(&two), 69); - }); - } - - fn new_test_ext() -> TestExternalities { - let one = one(); - let two = two(); - let three = [3u8; 32]; - - TestExternalities { storage: map![ - twox_128(&0u64.to_keyed_vec(b"sys:old:")).to_vec() => [69u8; 32].to_vec(), - twox_128(b"gov:apr").to_vec() => vec![].join(&667u32), - twox_128(b"ses:len").to_vec() => vec![].join(&2u64), - twox_128(b"ses:val:len").to_vec() => vec![].join(&3u32), - twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => one.to_vec(), - twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => two.to_vec(), - twox_128(&2u32.to_keyed_vec(b"ses:val:")).to_vec() => three.to_vec(), - twox_128(b"sta:wil:len").to_vec() => vec![].join(&3u32), - twox_128(&0u32.to_keyed_vec(b"sta:wil:")).to_vec() => one.to_vec(), - twox_128(&1u32.to_keyed_vec(b"sta:wil:")).to_vec() => two.to_vec(), - twox_128(&2u32.to_keyed_vec(b"sta:wil:")).to_vec() => three.to_vec(), - twox_128(b"sta:spe").to_vec() => vec![].join(&2u64), - twox_128(b"sta:vac").to_vec() => vec![].join(&3u64), - twox_128(b"sta:era").to_vec() => vec![].join(&0u64), - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ], } - } - - fn secret_for(who: &AccountId) -> Option { - match who { - x if *x == one() => Some(Pair::from_seed(b"12345678901234567890123456789012")), - x if *x == two() => Some("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into()), - _ => None, - } - } - - fn construct_block(number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec) -> (Vec, Hash) { - use triehash::ordered_trie_root; - - let transactions = txs.into_iter().map(|transaction| { - let signature = secret_for(&transaction.signed).unwrap() - .sign(&transaction.to_vec()); - - UncheckedTransaction { transaction, signature } - }).collect::>(); - - let transaction_root = ordered_trie_root(transactions.iter().map(Slicable::to_vec)).0.into(); - - let header = Header { - parent_hash, - number, - state_root, - transaction_root, - digest: Digest { logs: vec![], }, - }; - let hash = header.blake2_256(); - - (Block { header, transactions }.to_vec(), hash.into()) - } - - fn block1() -> (Vec, Hash) { - construct_block( - 1, - [69u8; 32].into(), - hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db").into(), - vec![Transaction { - signed: one(), - nonce: 0, - function: Function::StakingTransfer(two(), 69), - }] - ) - } - - fn block2() -> (Vec, Hash) { - construct_block( - 2, - block1().1, - hex!("1feb4d3a2e587079e6ce1685fa79994efd995e33cb289d39cded67aac1bb46a9").into(), - vec![ - Transaction { - signed: two(), - nonce: 0, - function: Function::StakingTransfer(one(), 5), - }, - Transaction { - signed: one(), - nonce: 1, - function: Function::StakingTransfer(two(), 15), - } - ] - ) - } - - #[test] - fn test_execution_works() { - let mut t = new_test_ext(); - println!("Testing Wasm..."); - let r = WasmExecutor.call(&mut t, COMPACT_CODE, "run_tests", &block2().0); - assert!(r.is_ok()); - } - - #[test] - fn full_native_block_import_works() { - let mut t = new_test_ext(); - - NativeExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&one()), 42); - assert_eq!(balance(&two()), 69); - }); - - NativeExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&one()), 32); - assert_eq!(balance(&two()), 79); - }); - } - - #[test] - fn full_wasm_block_import_works() { - let mut t = new_test_ext(); - - WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&one()), 42); - assert_eq!(balance(&two()), 69); - }); - - WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&one()), 32); - assert_eq!(balance(&two()), 79); - }); - } -} diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index e46991c2c3..5426aba447 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -289,34 +289,11 @@ mod tests { use super::*; use rustc_hex::FromHex; use codec::{KeyedVec, Slicable, Joiner}; - use native_runtime::support::{one, two}; - use native_runtime::runtime::staking::balance; use state_machine::TestExternalities; - use primitives::twox_128; - use polkadot_primitives::{Header, Transaction, UncheckedTransaction, Function, AccountId}; + use primitives::{twox_128, Header}; use runtime_io; use ed25519::Pair; - fn secret_for(who: &AccountId) -> Option { - match who { - x if *x == one() => Some(Pair::from_seed(b"12345678901234567890123456789012")), - x if *x == two() => Some("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into()), - _ => None, - } - } - - fn tx() -> UncheckedTransaction { - let transaction = Transaction { - signed: one(), - nonce: 0, - function: Function::StakingTransfer(two(), 69), - }; - let signature = secret_for(&transaction.signed).unwrap() - .sign(&transaction.to_vec()); - - UncheckedTransaction { transaction, signature } - } - #[test] fn returning_should_work() { let mut ext = TestExternalities::default(); @@ -422,35 +399,4 @@ mod tests { ordered_trie_root(vec![b"zero".to_vec(), b"one".to_vec(), b"two".to_vec()]).0.to_vec() ); } - - #[test] - fn panic_execution_gives_error() { - let one = one(); - let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] - ], }; - - let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); - let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); - assert!(r.is_err()); - } - - #[test] - fn successful_execution_gives_ok() { - let one = one(); - let two = two(); - - let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ], }; - - let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); - let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); - assert!(r.is_ok()); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(balance(&one), 42); - assert_eq!(balance(&two), 69); - }); - } } diff --git a/substrate/executor/src/wasm_utils.rs b/substrate/executor/src/wasm_utils.rs index 11fc404e2c..0e747b7fe3 100644 --- a/substrate/executor/src/wasm_utils.rs +++ b/substrate/executor/src/wasm_utils.rs @@ -198,10 +198,3 @@ impl AddModuleWithoutFullDependentInstance for interpreter::ProgramInstance $value:expr ),*) => ( - vec![ $( ( $name, $value ) ),* ].into_iter().collect() - ) -} diff --git a/substrate/network/Cargo.toml b/substrate/network/Cargo.toml index e1e8310d33..39e88c97db 100644 --- a/substrate/network/Cargo.toml +++ b/substrate/network/Cargo.toml @@ -11,8 +11,7 @@ authors = ["Parity Technologies "] ethcore-network = { git = "https://github.com/paritytech/parity.git" } ethcore-io = { git = "https://github.com/paritytech/parity.git" } substrate-primitives = { path = "../primitives" } -polkadot-primitives = { path = "../polkadot-primitives" } -polkadot-client = { path = "../client" } +substrate-client = { path = "../client" } substrate-state-machine = { path = "../state-machine" } substrate-serializer = { path = "../serializer" } log = "0.3" @@ -28,3 +27,4 @@ bitflags = "1.0" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" +polkadot-primitives = { path = "../polkadot-primitives" } diff --git a/substrate/network/src/lib.rs b/substrate/network/src/lib.rs index 6feabb0b46..bdd7b41ca6 100644 --- a/substrate/network/src/lib.rs +++ b/substrate/network/src/lib.rs @@ -35,7 +35,7 @@ extern crate serde_json; // TODO: remove these two; split off dependent logic into polkadot-network and rename this crate // to substrate-network. extern crate polkadot_primitives as polkadot_primitives; -extern crate polkadot_client as client; +extern crate substrate_client as client; #[macro_use] extern crate serde_derive; #[macro_use] extern crate log; #[macro_use] extern crate bitflags; diff --git a/substrate/polkadot-executor/Cargo.toml b/substrate/polkadot-executor/Cargo.toml new file mode 100644 index 0000000000..39ee892a56 --- /dev/null +++ b/substrate/polkadot-executor/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "polkadot-executor" +version = "0.1.0" +authors = ["Parity Technologies "] +description = "Polkadot node implementation in Rust." + +[dependencies] +hex-literal = "0.1" +ed25519 = { path = "../ed25519" } +triehash = { version = "0.1" } +substrate-codec = { path = "../codec" } +substrate-runtime-io = { path = "../runtime-io" } +substrate-state-machine = { path = "../state-machine" } +substrate-executor = { path = "../executor" } +substrate-primitives = { path = "../primitives" } +polkadot-primitives = { path = "../polkadot-primitives", version = "0.1" } +native-runtime = { path = "../native-runtime" } diff --git a/substrate/polkadot-executor/src/lib.rs b/substrate/polkadot-executor/src/lib.rs new file mode 100644 index 0000000000..567559adcf --- /dev/null +++ b/substrate/polkadot-executor/src/lib.rs @@ -0,0 +1,315 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +extern crate native_runtime; +extern crate substrate_executor; +extern crate substrate_codec as codec; +extern crate substrate_state_machine as state_machine; +extern crate substrate_runtime_io as runtime_io; +extern crate substrate_primitives as primitives; +extern crate polkadot_primitives as polkadot_primitives; +extern crate ed25519; +extern crate triehash; +#[macro_use] +extern crate hex_literal; + +use native_runtime as runtime; +use substrate_executor::{NativeExecutionDispatch, NativeExecutor}; + +pub struct LocalNativeExecutionDispatch; + +impl NativeExecutionDispatch for LocalNativeExecutionDispatch { + fn native_equivalent() -> &'static [u8] { + // WARNING!!! This assumes that the runtime was built *before* the main project. Until we + // get a proper build script, this must be strictly adhered to or things will go wrong. + include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm") + } + + fn dispatch(method: &str, data: &[u8]) -> Option> { + match method { + "execute_block" => Some(runtime::execute_block(data)), + "execute_transaction" => Some(runtime::execute_transaction(data)), + "finalise_block" => Some(runtime::finalise_block(data)), + _ => None, + } + } +} + +/// Creates new RustExecutor for contracts. +pub fn executor() -> NativeExecutor { + NativeExecutor{ _dummy: ::std::marker::PhantomData } +} + +#[cfg(test)] +mod tests { + use runtime_io; + use super::*; + use substrate_executor::WasmExecutor; + use codec::{KeyedVec, Slicable, Joiner}; + use native_runtime::support::{one, two, Hashable}; + use native_runtime::runtime::staking::balance; + use state_machine::{CodeExecutor, TestExternalities}; + use primitives::twox_128; + use polkadot_primitives::{Hash, Header, BlockNumber, Block, Digest, Transaction, + UncheckedTransaction, Function, AccountId}; + use ed25519::Pair; + + const BLOATY_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); + const COMPACT_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); + + // TODO: move into own crate. + macro_rules! map { + ($( $name:expr => $value:expr ),*) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ) + } + + fn tx() -> UncheckedTransaction { + let transaction = Transaction { + signed: one(), + nonce: 0, + function: Function::StakingTransfer(two(), 69), + }; + let signature = secret_for(&transaction.signed).unwrap() + .sign(&transaction.to_vec()); + + UncheckedTransaction { transaction, signature } + } + + #[test] + fn panic_execution_with_foreign_code_gives_error() { + let one = one(); + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let r = executor().call(&mut t, BLOATY_CODE, "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); + assert!(r.is_err()); + } + + #[test] + fn panic_execution_with_native_equivalent_code_gives_error() { + let one = one(); + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let r = executor().call(&mut t, COMPACT_CODE, "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); + assert!(r.is_err()); + } + + #[test] + fn successful_execution_with_native_equivalent_code_gives_ok() { + let one = one(); + let two = two(); + + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let r = executor().call(&mut t, COMPACT_CODE, "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); + assert!(r.is_ok()); + + runtime_io::with_externalities(&mut t, || { + assert_eq!(balance(&one), 42); + assert_eq!(balance(&two), 69); + }); + } + + #[test] + fn successful_execution_with_foreign_code_gives_ok() { + let one = one(); + let two = two(); + + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let r = executor().call(&mut t, BLOATY_CODE, "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); + assert!(r.is_ok()); + + runtime_io::with_externalities(&mut t, || { + assert_eq!(balance(&one), 42); + assert_eq!(balance(&two), 69); + }); + } + + fn new_test_ext() -> TestExternalities { + let one = one(); + let two = two(); + let three = [3u8; 32]; + + TestExternalities { storage: map![ + twox_128(&0u64.to_keyed_vec(b"sys:old:")).to_vec() => [69u8; 32].to_vec(), + twox_128(b"gov:apr").to_vec() => vec![].join(&667u32), + twox_128(b"ses:len").to_vec() => vec![].join(&2u64), + twox_128(b"ses:val:len").to_vec() => vec![].join(&3u32), + twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => one.to_vec(), + twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => two.to_vec(), + twox_128(&2u32.to_keyed_vec(b"ses:val:")).to_vec() => three.to_vec(), + twox_128(b"sta:wil:len").to_vec() => vec![].join(&3u32), + twox_128(&0u32.to_keyed_vec(b"sta:wil:")).to_vec() => one.to_vec(), + twox_128(&1u32.to_keyed_vec(b"sta:wil:")).to_vec() => two.to_vec(), + twox_128(&2u32.to_keyed_vec(b"sta:wil:")).to_vec() => three.to_vec(), + twox_128(b"sta:spe").to_vec() => vec![].join(&2u64), + twox_128(b"sta:vac").to_vec() => vec![].join(&3u64), + twox_128(b"sta:era").to_vec() => vec![].join(&0u64), + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], } + } + + fn secret_for(who: &AccountId) -> Option { + match who { + x if *x == one() => Some(Pair::from_seed(b"12345678901234567890123456789012")), + x if *x == two() => Some("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into()), + _ => None, + } + } + + fn construct_block(number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec) -> (Vec, Hash) { + use triehash::ordered_trie_root; + + let transactions = txs.into_iter().map(|transaction| { + let signature = secret_for(&transaction.signed).unwrap() + .sign(&transaction.to_vec()); + + UncheckedTransaction { transaction, signature } + }).collect::>(); + + let transaction_root = ordered_trie_root(transactions.iter().map(Slicable::to_vec)).0.into(); + + let header = Header { + parent_hash, + number, + state_root, + transaction_root, + digest: Digest { logs: vec![], }, + }; + let hash = header.blake2_256(); + + (Block { header, transactions }.to_vec(), hash.into()) + } + + fn block1() -> (Vec, Hash) { + construct_block( + 1, + [69u8; 32].into(), + hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db").into(), + vec![Transaction { + signed: one(), + nonce: 0, + function: Function::StakingTransfer(two(), 69), + }] + ) + } + + fn block2() -> (Vec, Hash) { + construct_block( + 2, + block1().1, + hex!("1feb4d3a2e587079e6ce1685fa79994efd995e33cb289d39cded67aac1bb46a9").into(), + vec![ + Transaction { + signed: two(), + nonce: 0, + function: Function::StakingTransfer(one(), 5), + }, + Transaction { + signed: one(), + nonce: 1, + function: Function::StakingTransfer(two(), 15), + } + ] + ) + } + + #[test] + fn test_execution_works() { + let mut t = new_test_ext(); + println!("Testing Wasm..."); + let r = WasmExecutor.call(&mut t, COMPACT_CODE, "run_tests", &block2().0); + assert!(r.is_ok()); + } + + #[test] + fn full_native_block_import_works() { + let mut t = new_test_ext(); + + executor().call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); + + runtime_io::with_externalities(&mut t, || { + assert_eq!(balance(&one()), 42); + assert_eq!(balance(&two()), 69); + }); + + executor().call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); + + runtime_io::with_externalities(&mut t, || { + assert_eq!(balance(&one()), 32); + assert_eq!(balance(&two()), 79); + }); + } + + #[test] + fn full_wasm_block_import_works() { + let mut t = new_test_ext(); + + WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); + + runtime_io::with_externalities(&mut t, || { + assert_eq!(balance(&one()), 42); + assert_eq!(balance(&two()), 69); + }); + + WasmExecutor.call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); + + runtime_io::with_externalities(&mut t, || { + assert_eq!(balance(&one()), 32); + assert_eq!(balance(&two()), 79); + }); + } + + #[test] + fn panic_execution_gives_error() { + let one = one(); + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); + let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); + assert!(r.is_err()); + } + + #[test] + fn successful_execution_gives_ok() { + let one = one(); + let two = two(); + + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); + let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &vec![].join(&Header::from_block_number(1u64)).join(&tx())); + assert!(r.is_ok()); + + runtime_io::with_externalities(&mut t, || { + assert_eq!(balance(&one), 42); + assert_eq!(balance(&two), 69); + }); + } +} diff --git a/substrate/rpc/Cargo.toml b/substrate/rpc/Cargo.toml index fdf9f7595b..be8fec54dd 100644 --- a/substrate/rpc/Cargo.toml +++ b/substrate/rpc/Cargo.toml @@ -7,9 +7,11 @@ authors = ["Parity Technologies "] error-chain = "0.11" jsonrpc-core = { git="https://github.com/paritytech/jsonrpc.git" } jsonrpc-macros = { git="https://github.com/paritytech/jsonrpc.git" } -polkadot-client = { path = "../client" } +substrate-client = { path = "../client" } substrate-primitives = { path = "../primitives" } substrate-state-machine = { path = "../state-machine" } +# TODO: Remove this and split out tests. +polkadot-executor = { path = "../polkadot-executor" } [dev-dependencies] assert_matches = "1.1" diff --git a/substrate/rpc/src/chain/tests.rs b/substrate/rpc/src/chain/tests.rs index ad629fd41f..952b20b35c 100644 --- a/substrate/rpc/src/chain/tests.rs +++ b/substrate/rpc/src/chain/tests.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use substrate_executor as executor; +use polkadot_executor as executor; use client; use super::*; diff --git a/substrate/rpc/src/lib.rs b/substrate/rpc/src/lib.rs index 68935fb00b..a1cce746b3 100644 --- a/substrate/rpc/src/lib.rs +++ b/substrate/rpc/src/lib.rs @@ -19,7 +19,7 @@ #![warn(missing_docs)] extern crate jsonrpc_core as rpc; -extern crate polkadot_client as client; +extern crate substrate_client as client; extern crate substrate_primitives as primitives; extern crate substrate_state_machine as state_machine; @@ -29,7 +29,7 @@ extern crate error_chain; extern crate jsonrpc_macros; #[cfg(test)] -extern crate substrate_executor; +extern crate polkadot_executor; #[cfg(test)] #[macro_use] extern crate assert_matches; diff --git a/substrate/rpc/src/state/tests.rs b/substrate/rpc/src/state/tests.rs index 8bc0d6ec5f..d15f42183e 100644 --- a/substrate/rpc/src/state/tests.rs +++ b/substrate/rpc/src/state/tests.rs @@ -15,7 +15,7 @@ // along with Polkadot. If not, see . use super::*; -use substrate_executor as executor; +use polkadot_executor as executor; use self::error::{Error, ErrorKind}; use client;