From 2c65ad6c7b89708c62bed6b10f8173d4cb0b0093 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 9 Oct 2018 10:58:29 +0200 Subject: [PATCH] Refactor the runtime API to use traits. (#878) * Add missing `As` imports. * Adds new API traits that will be used by the client and runtime * Switch consensus to new API's * Switches transaction-pool to new API's * Move runtime api stuff into its own crate * Adds `impl_apis!` macro for implementing the new API traits * Make `metadata` return directly a blob * Runtime replace `impl_stubs!` with `impl_apis!` * Switches to none feature based approach for declaring the different API traits * Fixes compilation error * Fixes errors * Make the `decl_apis!` trait usable from the outside * Make the `test-client` use the new API traits * Remove last `impl_stubs!` bits and move some of them into wasm executor for tests * A little bit more documentation --- substrate/Cargo.lock | 62 ++- substrate/Cargo.toml | 1 + substrate/core/client/Cargo.toml | 1 + substrate/core/client/src/client.rs | 124 ++++- substrate/core/client/src/error.rs | 5 + substrate/core/client/src/lib.rs | 6 + substrate/core/executor/wasm/src/lib.rs | 59 +- substrate/core/sr-api/Cargo.toml | 19 + substrate/core/sr-api/src/lib.rs | 589 ++++++++++++++++++++ substrate/core/sr-io/with_std.rs | 28 - substrate/core/sr-io/without_std.rs | 57 -- substrate/core/sr-primitives/Cargo.toml | 3 + substrate/core/sr-primitives/src/lib.rs | 1 + substrate/core/test-runtime/Cargo.toml | 2 + substrate/core/test-runtime/src/lib.rs | 71 ++- substrate/core/test-runtime/wasm/Cargo.lock | 18 +- substrate/core/test-runtime/wasm/Cargo.toml | 2 + substrate/node/consensus/src/lib.rs | 79 +-- substrate/node/consensus/src/service.rs | 1 + substrate/node/runtime/Cargo.toml | 4 +- substrate/node/runtime/src/lib.rs | 116 ++-- substrate/node/runtime/wasm/Cargo.lock | 20 +- substrate/node/runtime/wasm/Cargo.toml | 2 + substrate/node/transaction-pool/src/lib.rs | 21 +- substrate/srml/support/src/metadata.rs | 23 +- 25 files changed, 1058 insertions(+), 256 deletions(-) create mode 100644 substrate/core/sr-api/Cargo.toml create mode 100644 substrate/core/sr-api/src/lib.rs diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 9bd2d282c4..af8eaf1512 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -1659,7 +1659,7 @@ name = "node-primitives" version = "0.1.0" dependencies = [ "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1676,11 +1676,12 @@ dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 0.1.0", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-api 0.1.0", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1856,7 +1857,7 @@ dependencies = [ [[package]] name = "parity-codec-derive" -version = "2.0.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2472,6 +2473,16 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sr-api" +version = "0.1.0" +dependencies = [ + "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "sr-version 0.1.0", +] + [[package]] name = "sr-io" version = "0.1.0" @@ -2494,12 +2505,13 @@ dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", + "sr-version 0.1.0", "substrate-primitives 0.1.0", ] @@ -2528,7 +2540,7 @@ name = "sr-version" version = "0.1.0" dependencies = [ "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", @@ -2540,7 +2552,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2559,7 +2571,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -2576,7 +2588,7 @@ version = "0.1.0" dependencies = [ "assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", "pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2598,7 +2610,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2619,7 +2631,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2639,7 +2651,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -2657,7 +2669,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -2675,7 +2687,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2695,7 +2707,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2719,7 +2731,7 @@ dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "mashup 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2735,7 +2747,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2769,7 +2781,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -2889,6 +2901,7 @@ dependencies = [ "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-api 0.1.0", "sr-primitives 0.1.0", "substrate-bft 0.1.0", "substrate-executor 0.1.0", @@ -2910,7 +2923,7 @@ dependencies = [ "kvdb-rocksdb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", @@ -2994,7 +3007,7 @@ name = "substrate-metadata" version = "0.1.0" dependencies = [ "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3023,7 +3036,7 @@ dependencies = [ "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3074,7 +3087,7 @@ dependencies = [ "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3187,7 +3200,7 @@ dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] @@ -3244,9 +3257,10 @@ dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-api 0.1.0", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -4260,7 +4274,7 @@ dependencies = [ "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5168b4cf41f3835e4bc6ffb32f51bc9365dc50cb351904595b3931d917fd0c" "checksum parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "63c4b16ee2b7d6aace13b09bb0d16ade6b90ef19b7ca1c6cec9b8d08b9f59ecb" -"checksum parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c1ab5c320ceee2509bd4255e659c705e5af4f75ddb6301481ec4c529531903ba" +"checksum parity-codec-derive 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "693976dd8dd73d0c06ea8f339046903684e9d6a66e915ec0186b7baad43e7945" "checksum parity-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1117f6574377d21309bfa1f7d69ff734120685d92b02c3f362b122585758840" "checksum parity-rocksdb 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd55d2d6d6000ec99f021cf52c9acc7d2a402e14f95ced4c5de230696fabe00b" "checksum parity-rocksdb-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ae07d4bfb2759541957c19f471996b807fc09ef3a5bdce14409b57f038de49f" diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index bd1a9a8746..937e7f8065 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -31,6 +31,7 @@ members = [ "core/primitives", "core/rpc", "core/rpc-servers", + "core/sr-api", "core/sr-io", "core/sr-sandbox", "core/sr-std", diff --git a/substrate/core/client/Cargo.toml b/substrate/core/client/Cargo.toml index 318ce5faf5..3d8bf2badc 100644 --- a/substrate/core/client/Cargo.toml +++ b/substrate/core/client/Cargo.toml @@ -17,6 +17,7 @@ parity-codec = "2.0" substrate-executor = { path = "../executor" } substrate-primitives = { path = "../primitives" } sr-primitives = { path = "../sr-primitives" } +sr-api = { path = "../sr-api" } substrate-state-machine = { path = "../state-machine" } substrate-keyring = { path = "../keyring" } substrate-trie = { path = "../trie" } diff --git a/substrate/core/client/src/client.rs b/substrate/core/client/src/client.rs index 989cfcadc8..902152061e 100644 --- a/substrate/core/client/src/client.rs +++ b/substrate/core/client/src/client.rs @@ -17,12 +17,14 @@ //! Substrate Client use std::sync::Arc; +use error::Error; use futures::sync::mpsc; use parking_lot::{Mutex, RwLock}; use primitives::AuthorityId; use runtime_primitives::{bft::Justification, generic::{BlockId, SignedBlock, Block as RuntimeBlock}}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash}; -use runtime_primitives::BuildStorage; +use runtime_primitives::{ApplyResult, BuildStorage}; +use runtime_api as api; use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration}; use primitives::storage::{StorageKey, StorageData}; use primitives::storage::well_known_keys; @@ -1043,6 +1045,126 @@ impl BlockBody for Client } } +impl api::Core for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Error = Error; + + fn version(&self, at: &BlockId) -> Result { + self.call_api_at(at, "version", &()) + } + + fn authorities(&self, at: &BlockId) -> Result, Self::Error> { + bft::Authorities::authorities(self, at).map_err(Into::into) + } + + fn execute_block(&self, at: &BlockId, block: Block) -> Result<(), Self::Error> { + self.call_api_at(at, "execute_block", &(block)) + } +} + +impl api::Metadata for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Error = Error; + + fn metadata(&self, at: &BlockId) -> Result, Self::Error> { + self.call_api_at(at, "metadata", &()) + } +} + +impl api::BlockBuilder for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Error = Error; + + fn initialise_block(&self, at: &BlockId, header: ::Header) -> Result<(), Self::Error> { + self.call_api_at(at, "initialise_block", &(header)) + } + + fn apply_extrinsic(&self, at: &BlockId, extrinsic: ::Extrinsic) -> Result { + self.call_api_at(at, "apply_extrinsic", &(extrinsic)) + } + + fn finalise_block(&self, at: &BlockId) -> Result<::Header, Self::Error> { + self.call_api_at(at, "finalise_block", &()) + } + + fn inherent_extrinsics( + &self, at: &BlockId, inherent: InherentExtrinsic + ) -> Result, Self::Error> { + self.call_api_at(at, "inherent_extrinsics", &(inherent)) + } + + fn random_seed(&self, at: &BlockId) -> Result<::Hash, Self::Error> { + self.call_api_at(at, "random_seed", &()) + } +} + +impl api::OldTxQueue for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Error = Error; + + fn account_nonce( + &self, at: &BlockId, account: AccountId + ) -> Result { + self.call_api_at(at, "account_nonce", &(account)) + } + + fn lookup_address( + &self, at: &BlockId, address: Address + ) -> Result, Self::Error> { + self.call_api_at(at, "lookup_address", &(address)) + } +} + +impl api::NewTxQueue for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Error = Error; + + fn validate_transaction( + &self, at: &BlockId, tx: ::Extrinsic + ) -> Result { + self.call_api_at(at, "validate_transaction", &(tx)) + } +} + +impl api::Miscellaneous for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Error = Error; + + fn validator_count(&self, at: &BlockId) -> Result { + self.call_api_at(at, "validator_count", &()) + } + + fn validators( + &self, at: &BlockId + ) -> Result, Self::Error> { + self.call_api_at(at, "validators", &()) + } + + fn timestamp( + &self, at: &BlockId + ) -> Result { + self.call_api_at(at, "timestamp", &()) + } +} + #[cfg(test)] pub(crate) mod tests { use std::collections::HashMap; diff --git a/substrate/core/client/src/error.rs b/substrate/core/client/src/error.rs index 88c7fe5ce6..a207eeb1b6 100644 --- a/substrate/core/client/src/error.rs +++ b/substrate/core/client/src/error.rs @@ -19,8 +19,13 @@ use std; use state_machine; use runtime_primitives::ApplyError; +use bft; error_chain! { + links { + BFT(bft::error::Error, bft::error::ErrorKind) #[doc="BFT error"]; + } + errors { /// Backend error. Backend(s: String) { diff --git a/substrate/core/client/src/lib.rs b/substrate/core/client/src/lib.rs index 3a79892b97..0463f2a464 100644 --- a/substrate/core/client/src/lib.rs +++ b/substrate/core/client/src/lib.rs @@ -36,6 +36,7 @@ extern crate parking_lot; extern crate hash_db; extern crate heapsize; extern crate kvdb; +extern crate sr_api; #[macro_use] extern crate error_chain; #[macro_use] extern crate log; @@ -67,3 +68,8 @@ pub use client::{ pub use notifications::{StorageEventStream, StorageChangeSet}; pub use state_machine::ExecutionStrategy; pub use leaves::LeafSet; + +/// Traits for interfacing with the runtime from the client. +pub mod runtime_api { + pub use sr_api::*; +} diff --git a/substrate/core/executor/wasm/src/lib.rs b/substrate/core/executor/wasm/src/lib.rs index fc4a1aa6ca..1c4ec640e7 100644 --- a/substrate/core/executor/wasm/src/lib.rs +++ b/substrate/core/executor/wasm/src/lib.rs @@ -4,8 +4,8 @@ #![feature(alloc)] extern crate alloc; use alloc::vec::Vec; +use alloc::slice; -#[macro_use] extern crate sr_io as runtime_io; extern crate sr_sandbox as sandbox; extern crate substrate_primitives; @@ -15,8 +15,37 @@ use runtime_io::{ twox_128, twox_256, ed25519_verify, enumerated_trie_root }; +macro_rules! impl_stubs { + ( $( $new_name:ident $($nodecode:ident)* => $invoke:expr ),* ) => { + $( + impl_stubs!(@METHOD $new_name $($nodecode)* => $invoke); + )* + }; + ( @METHOD $new_name:ident => $invoke:expr ) => { + #[no_mangle] + pub fn $new_name(input_data: *mut u8, input_len: usize) -> u64 { + let input: &[u8] = if input_len == 0 { + &[0u8; 0] + } else { + unsafe { + slice::from_raw_parts(input_data, input_len) + } + }; + + let output: Vec = $invoke(input); + let res = output.as_ptr() as u64 + ((output.len() as u64) << 32); + + // Leak the output vector to avoid it being freed. + // This is fine in a WASM context since the heap + // will be discarded after the call. + ::core::mem::forget(output); + res + } + }; +} + impl_stubs!( - test_data_in NO_DECODE => |input| { + test_data_in => |input| { print("set_storage"); set_storage(b"input", input); @@ -29,22 +58,22 @@ impl_stubs!( print("finished!"); b"all ok!".to_vec() }, - test_clear_prefix NO_DECODE => |input| { + test_clear_prefix => |input| { clear_prefix(input); b"all ok!".to_vec() }, - test_empty_return NO_DECODE => |_| Vec::new(), - test_panic NO_DECODE => |_| panic!("test panic"), - test_conditional_panic NO_DECODE => |input: &[u8]| { + test_empty_return => |_| Vec::new(), + test_panic => |_| panic!("test panic"), + test_conditional_panic => |input: &[u8]| { if input.len() > 0 { panic!("test panic") } input.to_vec() }, - test_blake2_256 NO_DECODE => |input| blake2_256(input).to_vec(), - test_twox_256 NO_DECODE => |input| twox_256(input).to_vec(), - test_twox_128 NO_DECODE => |input| twox_128(input).to_vec(), - test_ed25519_verify NO_DECODE => |input: &[u8]| { + test_blake2_256 => |input| blake2_256(input).to_vec(), + test_twox_256 => |input| twox_256(input).to_vec(), + test_twox_128 => |input| twox_128(input).to_vec(), + test_ed25519_verify => |input: &[u8]| { let mut pubkey = [0; 32]; let mut sig = [0; 64]; @@ -54,14 +83,14 @@ impl_stubs!( let msg = b"all ok!"; [ed25519_verify(&sig, &msg[..], &pubkey) as u8].to_vec() }, - test_enumerated_trie_root NO_DECODE => |_| { + test_enumerated_trie_root => |_| { enumerated_trie_root::(&[&b"zero"[..], &b"one"[..], &b"two"[..]]).to_vec() }, - test_sandbox NO_DECODE => |code: &[u8]| { + test_sandbox => |code: &[u8]| { let ok = execute_sandboxed(code, &[]).is_ok(); [ok as u8].to_vec() }, - test_sandbox_args NO_DECODE => |code: &[u8]| { + test_sandbox_args => |code: &[u8]| { let ok = execute_sandboxed( code, &[ @@ -71,7 +100,7 @@ impl_stubs!( ).is_ok(); [ok as u8].to_vec() }, - test_sandbox_return_val NO_DECODE => |code: &[u8]| { + test_sandbox_return_val => |code: &[u8]| { let result = execute_sandboxed( code, &[ @@ -81,7 +110,7 @@ impl_stubs!( let ok = if let Ok(sandbox::ReturnValue::Value(sandbox::TypedValue::I32(0x1337))) = result { true } else { false }; [ok as u8].to_vec() }, - test_sandbox_instantiate NO_DECODE => |code: &[u8]| { + test_sandbox_instantiate => |code: &[u8]| { let env_builder = sandbox::EnvironmentDefinitionBuilder::new(); let code = match sandbox::Instance::new(code, &env_builder, &mut ()) { Ok(_) => 0, diff --git a/substrate/core/sr-api/Cargo.toml b/substrate/core/sr-api/Cargo.toml new file mode 100644 index 0000000000..193d225683 --- /dev/null +++ b/substrate/core/sr-api/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "sr-api" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +parity-codec = { version = "2.0", default-features = false } +sr-std = { path = "../sr-std", default-features = false } +sr-primitives = { path = "../sr-primitives", default-features = false } +sr-version = { path = "../sr-version", default-features = false } + +[features] +default = ["std"] +std = [ + "sr-std/std", + "parity-codec/std", + "sr-primitives/std", + "sr-version/std", +] diff --git a/substrate/core/sr-api/src/lib.rs b/substrate/core/sr-api/src/lib.rs new file mode 100644 index 0000000000..c342241966 --- /dev/null +++ b/substrate/core/sr-api/src/lib.rs @@ -0,0 +1,589 @@ +// Copyright 2018 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 . + +//! API's for interfacing with the runtime via native/wasm. + +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate sr_std as rstd; +extern crate sr_primitives as primitives; +#[doc(hidden)] +pub extern crate parity_codec as codec; +extern crate sr_version as runtime_version; + +#[doc(hidden)] +pub use primitives::{ApplyResult, traits::Block as BlockT, generic::BlockId}; +use runtime_version::RuntimeVersion; +use rstd::vec::Vec; +#[doc(hidden)] +pub use rstd::slice; +#[doc(hidden)] +pub use codec::{Encode, Decode}; + +/// Declare the given API traits. +/// +/// # Example: +/// +/// ```nocompile +/// decl_apis!{ +/// pub trait Test { +/// fn test(event: Event) -> AccountId; +/// } +/// } +/// ``` +/// +/// Will result in the following declaration: +/// +/// ```nocompile +/// mod runtime { +/// pub trait Test { +/// fn test(event: Event) -> AccountId; +/// } +/// } +/// +/// pub trait Test { +/// type Error; +/// fn test(&self, at: &BlockId, event: Event) -> Result; +/// } +/// ``` +/// +/// The declarations generated in the `runtime` module will be used by `impl_apis!` for implementing +/// the traits for a runtime. The other declarations should be used for implementing the interface +/// in the client. +#[macro_export] +macro_rules! decl_apis { + ( + $( + $( #[$attr:meta] )* + pub trait $name:ident $(< $( $generic_param:ident $( : $generic_bound:ident )* ),* >)* { + $( + fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( + $( $param_name:ident : $param_type:ty )* + ) $( -> $return_ty:ty)*; + )* + } + )* + ) => { + $( + decl_apis!( + @ADD_BLOCK_GENERIC + $( #[$attr] )* + pub trait $name $(< $( $generic_param $( : $generic_bound )* ),* >)* { + $( + fn $fn_name $( < $( $fn_generic ),* > )* ($( $param_name : $param_type )* ) $( -> $return_ty )*; + )* + }; + ; + ; + $( $( $generic_param $( : $generic_bound )* ),* )* + ); + )* + decl_apis! { + @GENERATE_RUNTIME_TRAITS + $( + $( #[$attr] )* + pub trait $name $(< $( $generic_param $( : $generic_bound )* ),* >)* { + $( + fn $fn_name $( < $( $fn_generic ),* > )* ($( $param_name : $param_type )* ) $( -> $return_ty )*; + )* + }; + )* + } + }; + (@ADD_BLOCK_GENERIC + $( #[$attr:meta] )* + pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { + $( + fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( + $( $param_name:ident : $param_type:ty )* + ) $( -> $return_ty:ty)*; + )* + }; + ; + $( $generic_param_parsed:ident $( : $generic_bound_parsed:ident )* ),*; + Block: BlockT + $(, $generic_param_rest:ident $( : $generic_bound_rest:ident )* )* + ) => { + decl_apis!( + @ADD_BLOCK_GENERIC + $( #[$attr] )* + pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { + $( + fn $fn_name $( < $( $fn_generic ),* > )* ( + $( $param_name : $param_type )* + ) $( -> $return_ty )*; + )* + }; + Found; + $( $generic_param_parsed $( : $generic_bound_parsed )* , )* Block: $crate::BlockT; + $( $generic_param_rest $( : $generic_bound_rest )* ),* + ); + }; + (@ADD_BLOCK_GENERIC + $( #[$attr:meta] )* + pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { + $( + fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( + $( $param_name:ident : $param_type:ty )* + ) $( -> $return_ty:ty )*; + )* + }; + $( $block_found:ident )*; + $( $generic_param_parsed:ident $( : $generic_bound_parsed:path )* ),*; + $generic_param:ident $( : $generic_bound:ident )* + $(, $generic_param_rest:ident $( : $generic_bound_rest:ident )* )* + ) => { + decl_apis!( + @ADD_BLOCK_GENERIC + $( #[$attr] )* + pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { + $( + fn $fn_name $( < $( $fn_generic ),* > )* ( + $( $param_name : $param_type )* + ) $( -> $return_ty )*; + )* + }; + $( $block_found )*; + $( $generic_param_parsed $( : $generic_bound_parsed )* , )* $generic_param $( : $generic_bound )*; + $( $generic_param_rest $( : $generic_bound_rest )* ),* + ); + }; + (@ADD_BLOCK_GENERIC + $( #[$attr:meta] )* + pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { + $( + fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( + $( $param_name:ident : $param_type:ty )* + ) $( -> $return_ty:ty )*; + )* + }; + Found; + $( $generic_param_parsed:ident $( : $generic_bound_parsed:path )* ),*; + ) => { + decl_apis!( + @GENERATE_FNS + $( #[$attr] )* + pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { + $( + fn $fn_name $( < $( $fn_generic ),* > )* ( + $( $param_name : $param_type )* + ) $( -> $return_ty )*; + )* + }; + $( $generic_param_parsed $( : $generic_bound_parsed )* ),*; + {}; + $( $( $return_ty )*; )* + ); + }; + (@ADD_BLOCK_GENERIC + $( #[$attr:meta] )* + pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { + $( + fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( + $( $param_name:ident : $param_type:ty )* + ) $( -> $return_ty:ty )*; + )* + }; + ; + $( $generic_param_parsed:ident $( : $generic_bound_parsed:ident )* ),*; + ) => { + decl_apis!( + @GENERATE_FNS + $( #[$attr] )* + pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { + $( + fn $fn_name $( < $( $fn_generic ),* > )* ( + $( $param_name : $param_type )* + ) $( -> $return_ty )*; + )* + }; + // We need to add the required generic Block parameter + Block: $crate::BlockT $(, $generic_param_parsed $( : $generic_bound_parsed )* )*; + {}; + $( $( $return_ty )*; )* + ); + }; + (@GENERATE_FNS + $( #[$attr:meta] )* + pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { + $( + fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( + $( $param_name:ident : $param_type:ty )* + ) $( -> $return_ty:ty)*; + )* + }; + $( $generic_param_parsed:ident $( : $generic_bound_parsed:path )* ),*; + { $( $result_return_ty:ty; )* }; + $return_ty_current:ty; + $( $( $return_ty_rest:ty )*; )* + ) => { + decl_apis!( + @GENERATE_FNS + $( #[$attr] )* + pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { + $( + fn $fn_name $( < $( $fn_generic ),* > )* ( + $( $param_name : $param_type )* + ) $( -> $return_ty )*; + )* + }; + $( $generic_param_parsed $( : $generic_bound_parsed )* ),*; + { $( $result_return_ty; )* Result<$return_ty_current, Self::Error>; }; + $( $( $return_ty_rest )*; )* + ); + }; + (@GENERATE_FNS + $( #[$attr:meta] )* + pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { + $( + fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( + $( $param_name:ident : $param_type:ty )* + ) $( -> $return_ty:ty)*; + )* + }; + $( $generic_param_parsed:ident $( : $generic_bound_parsed:path )* ),*; + { $( $result_return_ty:ty; )* }; + ; + $( $( $return_ty_rest:ty )*; )* + ) => { + decl_apis!( + @GENERATE_FNS + $( #[$attr] )* + pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { + $( + fn $fn_name $( < $( $fn_generic ),* > )* ( + $( $param_name : $param_type )* + ) $( -> $return_ty )*; + )* + }; + $( $generic_param_parsed $( : $generic_bound_parsed )* ),*; + { $( $result_return_ty; )* Result<(), Self::Error>; }; + $( $( $return_ty_rest )*; )* + ); + }; + (@GENERATE_FNS + $( #[$attr:meta] )* + pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { + $( + fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( + $( $param_name:ident : $param_type:ty )* + ) $( -> $return_ty:ty)*; + )* + }; + $( $generic_param_parsed:ident $( : $generic_bound_parsed:path )* ),*; + { $( $result_return_ty:ty; )* }; + ) => { + decl_apis!( + @GENERATE_CLIENT_TRAITS + $( #[$attr] )* + pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { + $( + fn $fn_name $( < $( $fn_generic ),* > )* ( + $( $param_name : $param_type )* + ) $( -> $return_ty )*; + )* + }; + $( $generic_param_parsed $( : $generic_bound_parsed )* ),*; + { $( $result_return_ty; )* }; + $( $( $generic_param_orig $( : $generic_bound_orig )*, )* )* $( $( $( $fn_generic, )* )* )*; + ); + }; + (@GENERATE_CLIENT_TRAITS + $( #[$attr:meta] )* + pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { + $( + fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( + $( $param_name:ident : $param_type:ty )* + ) $( -> $return_ty:ty)*; + )* + }; + $( $generic_param_parsed:ident $( : $generic_bound_parsed:path )* ),*; + { $( $result_return_ty:ty; )* }; + $( $generic_param_joined:ident $( : $generic_bound_joined:ident )*, )*; + ) => { + $( #[$attr] )* + pub trait $name < $( $generic_param_parsed $( : $generic_bound_parsed )* ),* > { + type Error; + + $( + fn $fn_name $( < $( $fn_generic: $crate::Encode + $crate::Decode ),* > )* ( + &self, at: &$crate::BlockId $(, $param_name: $param_type )* + ) -> $result_return_ty; + )* + } + }; + (@GENERATE_RUNTIME_TRAITS + $( + $( #[$attr:meta] )* + pub trait $name:ident $(< $( $generic_param:ident $( : $generic_bound:ident )* ),* >)* { + $( + fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( + $( $param_name:ident : $param_type:ty )* + ) $( -> $return_ty:ty)*; + )* + }; + )* + ) => { + decl_apis! { + @GENERATE_RUNTIME_TRAITS_WITH_JOINED_GENERICS + $( + $( #[$attr] )* + pub trait $name < $( $( $generic_param $( : $generic_bound )*, )* )* $( $( $( $fn_generic, )* )* )* > { + $( + fn $fn_name ($( $param_name: $param_type ),*) $( -> $return_ty )*; + )* + } + )* + } + }; + (@GENERATE_RUNTIME_TRAITS_WITH_JOINED_GENERICS + $( + $( #[$attr:meta] )* + pub trait $name:ident < $( $generic_param:ident $( : $generic_bound:ident )*, )* > { + $( + fn $fn_name:ident($( $param_name:ident : $param_type:ty )*) $( -> $return_ty:ty)*; + )* + } + )* + ) => { + pub mod runtime { + use super::*; + + $( + $( #[$attr] )* + pub trait $name < $( $generic_param $( : $generic_bound )* ),* > { + $( + fn $fn_name ($( $param_name: $param_type ),*) $( -> $return_ty )*; + )* + } + )* + } + }; +} + +decl_apis! { + /// The `Core` api trait that is mandantory for each runtime. + pub trait Core { + fn version() -> RuntimeVersion; + fn authorities() -> Vec; + fn execute_block(block: Block); + } + + /// The `Metadata` api trait that returns metadata for the runtime. + pub trait Metadata { + fn metadata() -> Vec; + } + + /// The `BlockBuilder` api trait that provides required functions for building a block for a runtime. + pub trait BlockBuilder { + fn initialise_block(header: ::Header); + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult; + fn finalise_block() -> ::Header; + fn inherent_extrinsics(inherent: InherentExtrinsic) -> Vec; + fn random_seed() -> ::Hash; + } + + /// The `OldTxQueue` api trait for interfering with the old transaction queue. + pub trait OldTxQueue { + fn account_nonce(account: AccountId) -> Index; + fn lookup_address(address: Address) -> Option; + } + + /// The `NewTxQueue` api trait for interfering with the new transaction queue. + pub trait NewTxQueue { + fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity; + } + + /// The `Miscellaneous` api trait for getting miscellaneous information from the runtime. + pub trait Miscellaneous { + fn validator_count() -> u32; + fn validators() -> Vec; + fn timestamp() -> Moment; + } +} + +/// Implement the given API's for the given runtime. +/// All desired API's need to be implemented in one `impl_apis!` call. +/// Besides generating the implementation for the runtime, there will be also generated an +/// auxiliary module named `api` that contains function for inferring with the API in native/wasm. +/// It is important to use the traits from the `runtime` module with this macro. +/// +/// # Example: +/// +/// ```nocompile +/// #[macro_use] +/// extern crate sr_api as runtime_api; +/// +/// use runtime_api::runtime::{Core, OldTxQueue}; +/// +/// impl_apis! { +/// impl Core for Runtime { +/// fn version() -> RuntimeVersion { 1 } +/// fn authorities() -> Vec { vec![1] } +/// fn execute_block(block: Block) { +/// //comment +/// let block = call_arbitrary_code(block); +/// execute(block); +/// } +/// } +/// +/// impl OldTxQueue for Runtime { +/// fn account_nonce(account: AccountId) -> Index { +/// 0 +/// } +/// fn lookup_address(address: Address) -> Option { +/// None +/// } +/// } +/// } +/// +/// fn main() {} +/// ``` +#[macro_export] +macro_rules! impl_apis { + ( + impl $trait_name:ident $( < $( $generic:ident ),* > )* for $runtime:ident { + $( + fn $fn_name:ident ( $( $arg_name:ident : $arg_ty:ty ),* ) $( -> $return_ty:ty )* { + $( $impl:tt )* + } + )* + } + $( $rest:tt )* + ) => { + impl $trait_name $( < $( $generic ),* > )* for $runtime { + $( + fn $fn_name ( $( $arg_name : $arg_ty ),* ) $( -> $return_ty )* { + $( $impl )* + } + )* + } + impl_apis! { + $runtime; + $( $fn_name ( $( $arg_name: $arg_ty ),* ); )*; + $( $rest )* + } + }; + ( + $runtime:ident; + $( $fn_name_parsed:ident ( $( $arg_name_parsed:ident : $arg_ty_parsed:ty ),* ); )*; + impl $trait_name:ident $( < $( $generic:ident ),* > )* for $runtime_ignore:ident { + $( + fn $fn_name:ident ( $( $arg_name:ident : $arg_ty:ty ),* ) $( -> $return_ty:ty )* { + $( $impl:tt )* + } + )* + } + $( $rest:tt )* + ) => { + impl $trait_name $( < $( $generic ),* > )* for $runtime { + $( + fn $fn_name ( $( $arg_name : $arg_ty ),* ) $( -> $return_ty )* { + $( $impl )* + } + )* + } + impl_apis! { + $runtime; + $( $fn_name_parsed ( $( $arg_name_parsed: $arg_ty_parsed )* ); )* + $( $fn_name ( $( $arg_name: $arg_ty ),* ); )*; + $( $rest )* + } + }; + ( + $runtime:ident; + $( $fn_name:ident ( $( $arg_name:ident : $arg_ty:ty ),* ); )*; + ) => { + pub mod api { + use super::*; + + #[cfg(feature = "std")] + pub fn dispatch(method: &str, mut data: &[u8]) -> Option> { + match method { + $( + stringify!($fn_name) => { + Some({impl_apis! { + @GENERATE_IMPL_CALL + $runtime; + $fn_name; + $( $arg_name : $arg_ty ),*; + data; + }}) + } + )* + _ => None, + } + } + + $( + #[cfg(not(feature = "std"))] + #[no_mangle] + pub fn $fn_name(input_data: *mut u8, input_len: usize) -> u64 { + let mut input = if input_len == 0 { + &[0u8; 0] + } else { + unsafe { + $crate::slice::from_raw_parts(input_data, input_len) + } + }; + + let output = { impl_apis! { + @GENERATE_IMPL_CALL + $runtime; + $fn_name; + $( $arg_name : $arg_ty ),*; + input; + }}; + let res = output.as_ptr() as u64 + ((output.len() as u64) << 32); + + // Leak the output vector to avoid it being freed. + // This is fine in a WASM context since the heap + // will be discarded after the call. + ::core::mem::forget(output); + res + } + )* + } + }; + (@GENERATE_IMPL_CALL + $runtime:ident; + $fn_name:ident; + $arg_name:ident : $arg_ty:ty; + $input:ident; + ) => { + let $arg_name : $arg_ty = match $crate::codec::Decode::decode(&mut $input) { + Some(input) => input, + None => panic!("Bad input data provided to {}", stringify!($fn_name)), + }; + + let output = $runtime::$fn_name($arg_name); + $crate::codec::Encode::encode(&output) + }; + (@GENERATE_IMPL_CALL + $runtime:ident; + $fn_name:ident; + $( $arg_name:ident : $arg_ty:ty ),*; + $input:ident; + ) => { + let ( $( $arg_name ),* ) : ($( $arg_ty ),*) = match $crate::codec::Decode::decode(&mut $input) { + Some(input) => input, + None => panic!("Bad input data provided to {}", stringify!($fn_name)), + }; + + let output = $runtime::$fn_name($( $arg_name ),*); + $crate::codec::Encode::encode(&output) + }; +} diff --git a/substrate/core/sr-io/with_std.rs b/substrate/core/sr-io/with_std.rs index 5744010968..11c79370fb 100644 --- a/substrate/core/sr-io/with_std.rs +++ b/substrate/core/sr-io/with_std.rs @@ -181,34 +181,6 @@ pub fn print(value: T) { value.print(); } -#[macro_export] -macro_rules! impl_stubs { - ( $( $new_name:ident $($nodecode:ident)* => $invoke: expr ),*) => { - /// Dispatch logic for the native runtime. - pub fn dispatch(method: &str, data: &[u8]) -> Option> { - match method { - $( - stringify!($new_name) => { impl_stubs!(@METHOD data $new_name $($nodecode)* => $invoke) } - )* - _ => None, - } - } - }; - (@METHOD $data: ident $new_name: ident NO_DECODE => $invoke:expr) => { - Some($invoke($data)) - }; - (@METHOD $data: ident $new_name: ident => $invoke:expr) => {{ - let mut data = $data; - let input = match $crate::codec::Decode::decode(&mut data) { - Some(input) => input, - None => panic!("Bad input data provided to {}", stringify!($new_name)), - }; - - let output = $invoke(input); - Some($crate::codec::Encode::encode(&output)) - }} -} - #[cfg(test)] mod std_tests { use super::*; diff --git a/substrate/core/sr-io/without_std.rs b/substrate/core/sr-io/without_std.rs index d7c5519973..77476aae4e 100644 --- a/substrate/core/sr-io/without_std.rs +++ b/substrate/core/sr-io/without_std.rs @@ -285,60 +285,3 @@ impl Printable for u64 { pub fn print(value: T) { value.print(); } - -#[macro_export] -macro_rules! impl_stubs { - ( $( $new_name:ident $($nodecode:ident)* => $invoke:expr ),* ) => { - $( - impl_stubs!(@METHOD $new_name $($nodecode)* => $invoke); - )* - }; - ( @METHOD $new_name:ident NO_DECODE => $invoke:expr ) => { - #[no_mangle] - pub fn $new_name(input_data: *mut u8, input_len: usize) -> u64 { - let input: &[u8] = if input_len == 0 { - &[0u8; 0] - } else { - unsafe { - $crate::slice::from_raw_parts(input_data, input_len) - } - }; - - let output: $crate::rstd::vec::Vec = $invoke(input); - let res = output.as_ptr() as u64 + ((output.len() as u64) << 32); - - // Leak the output vector to avoid it being freed. - // This is fine in a WASM context since the heap - // will be discarded after the call. - ::core::mem::forget(output); - res - } - }; - ( @METHOD $new_name:ident => $invoke:expr ) => { - #[no_mangle] - pub fn $new_name(input_data: *mut u8, input_len: usize) -> u64 { - let mut input = if input_len == 0 { - &[0u8; 0] - } else { - unsafe { - $crate::slice::from_raw_parts(input_data, input_len) - } - }; - - let input = match $crate::codec::Decode::decode(&mut input) { - Some(input) => input, - None => panic!("Bad input data provided to {}", stringify!($name)), - }; - - let output = ($invoke)(input); - let output = $crate::codec::Encode::encode(&output); - let res = output.as_ptr() as u64 + ((output.len() as u64) << 32); - - // Leak the output vector to avoid it being freed. - // This is fine in a WASM context since the heap - // will be discarded after the call. - ::core::mem::forget(output); - res - } - } -} diff --git a/substrate/core/sr-primitives/Cargo.toml b/substrate/core/sr-primitives/Cargo.toml index 1e614e4668..561552795b 100644 --- a/substrate/core/sr-primitives/Cargo.toml +++ b/substrate/core/sr-primitives/Cargo.toml @@ -13,6 +13,7 @@ parity-codec-derive = { version = "2.0", default-features = false } substrate-primitives = { path = "../primitives", default-features = false } sr-std = { path = "../sr-std", default-features = false } sr-io = { path = "../sr-io", default-features = false } +sr-version = { path = "../sr-version", default-features = false } log = {version = "0.4", optional = true } [dev-dependencies] @@ -27,6 +28,8 @@ std = [ "log", "sr-std/std", "sr-io/std", + "sr-version/std", "parity-codec/std", "substrate-primitives/std", ] +api-for-runtime = [] diff --git a/substrate/core/sr-primitives/src/lib.rs b/substrate/core/sr-primitives/src/lib.rs index c51b92b4d6..84b9a4cd98 100644 --- a/substrate/core/sr-primitives/src/lib.rs +++ b/substrate/core/sr-primitives/src/lib.rs @@ -37,6 +37,7 @@ extern crate num_traits; extern crate integer_sqrt; extern crate sr_std as rstd; extern crate sr_io as runtime_io; +extern crate sr_version as runtime_version; #[doc(hidden)] pub extern crate parity_codec as codec; extern crate substrate_primitives; diff --git a/substrate/core/test-runtime/Cargo.toml b/substrate/core/test-runtime/Cargo.toml index d2c087f569..e8c857c75a 100644 --- a/substrate/core/test-runtime/Cargo.toml +++ b/substrate/core/test-runtime/Cargo.toml @@ -12,6 +12,7 @@ parity-codec = { version = "2.0", default-features = false } parity-codec-derive = { version = "2.0", default-features = false } substrate-keyring = { path = "../keyring", optional = true } substrate-primitives = { path = "../primitives", default-features = false } +sr-api = { path = "../sr-api", default-features = false } sr-std = { path = "../sr-std", default-features = false } sr-io = { path = "../sr-io", default-features = false } sr-primitives = { path = "../sr-primitives", default-features = false } @@ -27,6 +28,7 @@ std = [ "serde_derive", "substrate-keyring", "parity-codec/std", + "sr-api/std", "sr-std/std", "sr-io/std", "srml-support/std", diff --git a/substrate/core/test-runtime/src/lib.rs b/substrate/core/test-runtime/src/lib.rs index 9d9d75ca21..4cd75ae027 100644 --- a/substrate/core/test-runtime/src/lib.rs +++ b/substrate/core/test-runtime/src/lib.rs @@ -33,6 +33,7 @@ extern crate srml_support as runtime_support; #[macro_use] extern crate parity_codec_derive; #[macro_use] +extern crate sr_api as runtime_api; extern crate sr_io as runtime_io; #[macro_use] extern crate sr_version as runtime_version; @@ -52,10 +53,12 @@ pub mod system; use rstd::prelude::*; use codec::{Encode, Decode}; -use runtime_primitives::traits::{BlindCheckable, BlakeTwo256}; -use runtime_primitives::Ed25519Signature; +use runtime_api::runtime::*; +use runtime_primitives::traits::{BlindCheckable, BlakeTwo256, Block as BlockT}; +use runtime_primitives::{ApplyResult, Ed25519Signature}; use runtime_version::RuntimeVersion; pub use primitives::hash::H256; +use primitives::AuthorityId; #[cfg(any(feature = "std", test))] use runtime_version::NativeVersion; @@ -149,15 +152,57 @@ pub fn changes_trie_config() -> primitives::ChangesTrieConfiguration { } } -pub mod api { - use system; - impl_stubs!( - version => |()| super::version(), - authorities => |()| system::authorities(), - initialise_block => |header| system::initialise_block(header), - execute_block => |block| system::execute_block(block), - apply_extrinsic => |utx| system::execute_transaction(utx), - finalise_block => |()| system::finalise_block(), - balance_of => |a| system::balance_of(a) - ); +mod test_api { + decl_apis! { + pub trait TestAPI { + fn balance_of(id: AccountId) -> u64; + } + } +} +use test_api::runtime::TestAPI; + +struct Runtime; + +impl_apis! { + impl Core for Runtime { + fn version() -> RuntimeVersion { + version() + } + + fn authorities() -> Vec { + system::authorities() + } + + fn execute_block(block: Block) { + system::execute_block(block) + } + } + + impl BlockBuilder for Runtime { + fn initialise_block(header: ::Header) { + system::initialise_block(header) + } + + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { + system::execute_transaction(extrinsic) + } + + fn finalise_block() -> ::Header { + system::finalise_block() + } + + fn inherent_extrinsics(_data: u32) -> Vec { + unimplemented!() + } + + fn random_seed() -> ::Hash { + unimplemented!() + } + } + + impl TestAPI for Runtime { + fn balance_of(id: AccountId) -> u64 { + system::balance_of(id) + } + } } diff --git a/substrate/core/test-runtime/wasm/Cargo.lock b/substrate/core/test-runtime/wasm/Cargo.lock index 5813733d30..4e7e3a93e1 100644 --- a/substrate/core/test-runtime/wasm/Cargo.lock +++ b/substrate/core/test-runtime/wasm/Cargo.lock @@ -464,6 +464,16 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sr-api" +version = "0.1.0" +dependencies = [ + "parity-codec 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "sr-version 0.1.0", +] + [[package]] name = "sr-io" version = "0.1.0" @@ -491,6 +501,7 @@ dependencies = [ "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", + "sr-version 0.1.0", "substrate-primitives 0.1.0", ] @@ -564,7 +575,7 @@ dependencies = [ "twox-hash 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -591,6 +602,7 @@ dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-api 0.1.0", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -697,7 +709,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasmi" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -801,7 +813,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasmi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "522fe3fdd44a56f25cd5ddcd8ccdb1cf2e982ceb28fcb00f41d8a018ae5245a8" +"checksum wasmi 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d184c4b7081f30316f74f8d73c197314dcb56ea7af9323522b42a2fa9cb19453" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/substrate/core/test-runtime/wasm/Cargo.toml b/substrate/core/test-runtime/wasm/Cargo.toml index c3f0042278..ef2486c0ed 100644 --- a/substrate/core/test-runtime/wasm/Cargo.toml +++ b/substrate/core/test-runtime/wasm/Cargo.toml @@ -9,6 +9,7 @@ hex-literal = { version = "0.1.0", optional = true } parity-codec = { version = "2.0", default-features = false } parity-codec-derive = { version = "2.0", default-features = false } substrate-primitives = { path = "../../primitives", default-features = false } +sr-api = { path = "../../sr-api", default-features = false } sr-std = { path = "../../sr-std", default-features = false } sr-io = { path = "../../sr-io", default-features = false } sr-version = { path = "../../sr-version", default-features = false } @@ -21,6 +22,7 @@ std = [ "log", "hex-literal", "parity-codec/std", + "sr-api/std", "sr-std/std", "sr-io/std", "srml-support/std", diff --git a/substrate/node/consensus/src/lib.rs b/substrate/node/consensus/src/lib.rs index 7f0af2e064..58b715164c 100644 --- a/substrate/node/consensus/src/lib.rs +++ b/substrate/node/consensus/src/lib.rs @@ -46,6 +46,7 @@ use std::sync::Arc; use std::time::{self, Duration, Instant}; use client::{Client as SubstrateClient, CallExecutor}; +use client::runtime_api::{BlockBuilder as BlockBuilderAPI, Core, Miscellaneous, OldTxQueue}; use codec::{Decode, Encode}; use node_primitives::{AccountId, Timestamp, SessionKey, InherentData}; use node_runtime::Runtime; @@ -86,31 +87,23 @@ pub trait BlockBuilder { } /// Local client abstraction for the consensus. -pub trait AuthoringApi: Send + Sync { +pub trait AuthoringApi: + Send + + Sync + + BlockBuilderAPI<::Block, Error=::Error> + + Core<::Block, AuthorityId, Error=::Error> + + Miscellaneous<::Block, Error=::Error> + + OldTxQueue<::Block, Error=::Error> +{ /// The block used for this API type. type Block: BlockT; /// The block builder for this API type. type BlockBuilder: BlockBuilder; - - /// Get the value of the randomness beacon at a given block. - fn random_seed(&self, at: &BlockId) -> Result<::Hash>; - - /// Get validators at a given block. - fn validators(&self, at: &BlockId) -> Result>; + /// The error used by this API type. + type Error; /// Build a block on top of the given, with inherent extrinsics pre-pushed. fn build_block(&self, at: &BlockId, inherent_data: InherentData) -> Result; - - /// Get the nonce (né index) of an account at a block. - fn index(&self, at: &BlockId, account: AccountId) -> Result; - - /// Attempt to produce the (encoded) inherent extrinsics for a block being built upon the given. - /// This may vary by runtime and will fail if a runtime doesn't follow the same API. - fn inherent_extrinsics(&self, at: &BlockId, inherent_data: InherentData) -> Result::Extrinsic>>; - - /// Evaluate a block. Returns true if the block is good, false if it is known to be bad, - /// and an error if we can't evaluate for some reason. - fn evaluate_block(&self, at: &BlockId, block: Self::Block) -> Result; } impl BlockBuilder for client::block_builder::BlockBuilder where @@ -134,14 +127,7 @@ impl AuthoringApi for SubstrateClient where { type Block = Block; type BlockBuilder = client::block_builder::BlockBuilder; - - fn random_seed(&self, at: &BlockId) -> Result<::Hash> { - self.call_api_at(at, "random_seed", &()).map_err(Into::into) - } - - fn validators(&self, at: &BlockId) -> Result> { - self.call_api_at(at, "validators", &()).map_err(Into::into) - } + type Error = client::error::Error; fn build_block(&self, at: &BlockId, inherent_data: InherentData) -> Result { let runtime_version = self.runtime_version_at(at)?; @@ -152,27 +138,9 @@ impl AuthoringApi for SubstrateClient where block_builder.push(inherent)?; } } + Ok(block_builder) } - - fn index(&self, at: &BlockId, account: AccountId) -> Result { - self.call_api_at(at, "account_nonce", &account).map_err(Into::into) - } - - fn inherent_extrinsics(&self, at: &BlockId, inherent_data: InherentData) -> Result::Extrinsic>> { - self.call_api_at(at, "inherent_extrinsics", &inherent_data).map_err(Into::into) - } - - fn evaluate_block(&self, at: &BlockId, block: Self::Block) -> Result { - let res: client::error::Result<()> = self.call_api_at(at, "execute_block", &block); - match res { - Ok(()) => Ok(true), - Err(err) => match err.kind() { - &client::error::ErrorKind::Execution(_) => Ok(false), - _ => Err(err.into()) - } - } - } } /// A long-lived network which can create BFT message routing processes on demand. @@ -217,7 +185,8 @@ impl bft::Environment<::Block> for ProposerFactory::Block>, C: AuthoringApi + TPClient::Block>, <::Block as BlockT>::Hash: - Into<::Hash> + PartialEq + Into + Into<::Hash> + PartialEq + Into, + Error: From<::Error> { type Proposer = Proposer; type Input = N::Input; @@ -297,7 +266,8 @@ impl Proposer { impl bft::Proposer<::Block> for Proposer where C: AuthoringApi + TPClient::Block>, <::Block as BlockT>::Hash: - Into<::Hash> + PartialEq + Into + Into<::Hash> + PartialEq + Into, + error::Error: From<::Error> { type Create = Result<::Block>; type Error = Error; @@ -419,7 +389,7 @@ impl bft::Proposer<::Block> for Proposer where match timestamp_delay { Some(duration) => future::Either::A( - Delay::new(duration).map_err(|e| Error::from(ErrorKind::Timer(e))) + Delay::new(duration).map_err(|e| ErrorKind::Timer(e).into()) ), None => future::Either::B(future::ok(())), } @@ -434,9 +404,13 @@ impl bft::Proposer<::Block> for Proposer where // evaluate whether the block is actually valid. // TODO: is it better to delay this until the delays are finished? - let evaluated = self.client - .evaluate_block(&self.parent_id, unchecked_proposal.clone()) - .map_err(Into::into); + let evaluated = match self.client.execute_block(&self.parent_id, unchecked_proposal.clone()).map_err(Error::from) { + Ok(()) => Ok(true), + Err(err) => match err.kind() { + error::ErrorKind::Client(client::error::ErrorKind::Execution(_)) => Ok(false), + _ => Err(err) + } + }; let future = future::result(evaluated).and_then(move |good| { let end_result = future::ok(good); @@ -471,7 +445,8 @@ impl bft::Proposer<::Block> for Proposer where .filter(|tx| tx.verified.sender == local_id) .last() .map(|tx| Ok(tx.verified.index())) - .unwrap_or_else(|| AuthoringApi::index(self.client.as_ref(), &self.parent_id, local_id)) + .unwrap_or_else(|| self.client.account_nonce(&self.parent_id, local_id)) + .map_err(Error::from) ); match cur_index { diff --git a/substrate/node/consensus/src/service.rs b/substrate/node/consensus/src/service.rs index 3174165259..f8198161df 100644 --- a/substrate/node/consensus/src/service.rs +++ b/substrate/node/consensus/src/service.rs @@ -83,6 +83,7 @@ impl Service { ) -> Service where A: AuthoringApi + TPClient::Block> + 'static, + error::Error: From<::Error>, C: BlockchainEvents<::Block> + ChainHead<::Block> + BlockBody<::Block>, diff --git a/substrate/node/runtime/Cargo.toml b/substrate/node/runtime/Cargo.toml index e4e690ec3e..d610a02948 100644 --- a/substrate/node/runtime/Cargo.toml +++ b/substrate/node/runtime/Cargo.toml @@ -8,9 +8,10 @@ rustc-hex = "1.0" hex-literal = "0.1.0" serde = { version = "1.0", default-features = false } serde_derive = { version = "1.0", optional = true } -safe-mix = { version = "1.0", default-features = false} +safe-mix = { version = "1.0", default-features = false } parity-codec = "2.0" parity-codec-derive = "2.0" +sr-api = { path = "../../core/sr-api", default-features = false } sr-std = { path = "../../core/sr-std" } sr-io = { path = "../../core/sr-io" } srml-support = { path = "../../srml/support" } @@ -36,6 +37,7 @@ default = ["std"] std = [ "parity-codec/std", "substrate-primitives/std", + "sr-api/std", "sr-std/std", "sr-io/std", "srml-support/std", diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index a50889dcee..4f89366d33 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -20,9 +20,11 @@ // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit="256"] -#[macro_use] extern crate sr_io as runtime_io; +#[macro_use] +extern crate sr_api as runtime_api; + #[macro_use] extern crate srml_support; @@ -61,8 +63,11 @@ mod checked_block; use rstd::prelude::*; use substrate_primitives::u32_trait::{_2, _4}; use node_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, SessionKey, Signature, InherentData}; +use runtime_api::runtime::*; +use runtime_primitives::ApplyResult; +use runtime_primitives::transaction_validity::TransactionValidity; use runtime_primitives::generic; -use runtime_primitives::traits::{Convert, BlakeTwo256, DigestItem}; +use runtime_primitives::traits::{Convert, BlakeTwo256, DigestItem, Block as BlockT}; use version::{RuntimeVersion, ApiId}; use council::{motions as council_motions, voting as council_voting}; #[cfg(feature = "std")] @@ -243,37 +248,86 @@ pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = executive::Executive, Balances, AllModules>; -pub mod api { - impl_stubs!( - version => |()| super::VERSION, - metadata => |()| super::Runtime::metadata(), - authorities => |()| super::Consensus::authorities(), - initialise_block => |header| super::Executive::initialise_block(&header), - apply_extrinsic => |extrinsic| super::Executive::apply_extrinsic(extrinsic), - execute_block => |block| super::Executive::execute_block(block), - finalise_block => |()| super::Executive::finalise_block(), - inherent_extrinsics => |inherent| super::inherent_extrinsics(inherent), - validator_count => |()| super::Session::validator_count(), - validators => |()| super::Session::validators(), - timestamp => |()| super::Timestamp::get(), - random_seed => |()| super::System::random_seed(), - account_nonce => |account| super::System::account_nonce(&account), - lookup_address => |address| super::Balances::lookup_address(address), - validate_transaction => |tx| super::Executive::validate_transaction(tx) - ); -} +impl_apis! { + impl Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } -/// Produces the list of inherent extrinsics. -fn inherent_extrinsics(data: InherentData) -> Vec { - let mut inherent = vec![generic::UncheckedMortalExtrinsic::new_unsigned( - Call::Timestamp(TimestampCall::set(data.timestamp)) - )]; + fn authorities() -> Vec { + Consensus::authorities() + } - if !data.offline_indices.is_empty() { - inherent.push(generic::UncheckedMortalExtrinsic::new_unsigned( - Call::Consensus(ConsensusCall::note_offline(data.offline_indices)) - )); + fn execute_block(block: Block) { + Executive::execute_block(block) + } } - inherent + impl Metadata for Runtime { + fn metadata() -> Vec { + Runtime::metadata() + } + } + + impl BlockBuilder for Runtime { + fn initialise_block(header: ::Header) { + Executive::initialise_block(&header) + } + + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalise_block() -> ::Header { + Executive::finalise_block() + } + + fn inherent_extrinsics(data: InherentData) -> Vec { + let mut inherent = vec![generic::UncheckedMortalExtrinsic::new_unsigned( + Call::Timestamp(TimestampCall::set(data.timestamp)) + )]; + + if !data.offline_indices.is_empty() { + inherent.push(generic::UncheckedMortalExtrinsic::new_unsigned( + Call::Consensus(ConsensusCall::note_offline(data.offline_indices)) + )); + } + + inherent + } + + fn random_seed() -> ::Hash { + System::random_seed() + } + } + + impl OldTxQueue for Runtime { + fn account_nonce(account: AccountId) -> Index { + System::account_nonce(&account) + } + + fn lookup_address(address: Address) -> Option { + Balances::lookup_address(address) + } + } + + impl NewTxQueue for Runtime { + fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { + Executive::validate_transaction(tx) + } + } + + impl Miscellaneous for Runtime { + fn validator_count() -> u32 { + Session::validator_count() + } + + fn validators() -> Vec { + Session::validators() + } + + fn timestamp() -> u64 { + Timestamp::get() + } + } } diff --git a/substrate/node/runtime/wasm/Cargo.lock b/substrate/node/runtime/wasm/Cargo.lock index 4f73895efe..50a6088c69 100644 --- a/substrate/node/runtime/wasm/Cargo.lock +++ b/substrate/node/runtime/wasm/Cargo.lock @@ -268,6 +268,7 @@ dependencies = [ "parity-codec 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-api 0.1.0", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -523,6 +524,16 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sr-api" +version = "0.1.0" +dependencies = [ + "parity-codec 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "sr-version 0.1.0", +] + [[package]] name = "sr-io" version = "0.1.0" @@ -550,6 +561,7 @@ dependencies = [ "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", + "sr-version 0.1.0", "substrate-primitives 0.1.0", ] @@ -561,7 +573,7 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", - "wasmi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -851,7 +863,7 @@ dependencies = [ "twox-hash 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -968,7 +980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasmi" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1074,7 +1086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasmi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "522fe3fdd44a56f25cd5ddcd8ccdb1cf2e982ceb28fcb00f41d8a018ae5245a8" +"checksum wasmi 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d184c4b7081f30316f74f8d73c197314dcb56ea7af9323522b42a2fa9cb19453" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/substrate/node/runtime/wasm/Cargo.toml b/substrate/node/runtime/wasm/Cargo.toml index e102fb908f..4dfa3d3ba3 100644 --- a/substrate/node/runtime/wasm/Cargo.toml +++ b/substrate/node/runtime/wasm/Cargo.toml @@ -12,6 +12,7 @@ safe-mix = { version = "1.0", default-features = false} parity-codec-derive = { version = "2.0" } parity-codec = { version = "2.0", default-features = false } substrate-primitives = { path = "../../../core/primitives", default-features = false } +sr-api = { path = "../../../core/sr-api", default-features = false } sr-std = { path = "../../../core/sr-std", default-features = false } sr-io = { path = "../../../core/sr-io", default-features = false } srml-support = { path = "../../../srml/support", default-features = false } @@ -36,6 +37,7 @@ std = [ "safe-mix/std", "parity-codec/std", "substrate-primitives/std", + "sr-api/std", "sr-std/std", "sr-io/std", "srml-support/std", diff --git a/substrate/node/transaction-pool/src/lib.rs b/substrate/node/transaction-pool/src/lib.rs index bd6f79dc2f..e71c7d357b 100644 --- a/substrate/node/transaction-pool/src/lib.rs +++ b/substrate/node/transaction-pool/src/lib.rs @@ -41,6 +41,7 @@ use std::{ use codec::{Decode, Encode}; use client::{Client as SubstrateClient, CallExecutor}; +use client::runtime_api::OldTxQueue; use transaction_pool::{Readiness, scoring::{Change, Choice}, VerifiedFor, ExtrinsicFor}; use primitives::{AccountId, Hash, Index}; use runtime::{Address, UncheckedExtrinsic}; @@ -62,13 +63,11 @@ pub trait Client: Send + Sync + CurrentHeight::Block as BlockT>::Header as HeaderT>::Number> - + BlockNumberToHash::Block as BlockT>::Header as HeaderT>::Number, Hash=<::Block as BlockT>::Hash> { + + BlockNumberToHash::Block as BlockT>::Header as HeaderT>::Number, Hash=<::Block as BlockT>::Hash> + + OldTxQueue<::Block> +{ /// The block used for this API type. type Block: BlockT; - /// Get the nonce (né index) of an account at a block. - fn index(&self, at: &BlockId, account: AccountId) -> Result; - /// Get the account id of an address at a block. - fn lookup(&self, at: &BlockId, address: Address) -> Result>; } impl Client for SubstrateClient where @@ -77,14 +76,6 @@ impl Client for SubstrateClient where Block: BlockT, { type Block = Block; - - fn index(&self, at: &BlockId, account: AccountId) -> Result { - self.call_api_at(at, "account_nonce", &account).map_err(Into::into) - } - - fn lookup(&self, at: &BlockId, address: Address) -> Result> { - self.call_api_at(at, "lookup_address", &address).map_err(Into::into) - } } /// Type alias for the transaction pool. @@ -171,7 +162,7 @@ impl<'a, C: 'a + Client> Lookup for LocalContext<'a, C> { type Source = Address; type Target = AccountId; fn lookup(&self, a: Address) -> ::std::result::Result { - self.0.lookup(&BlockId::number(self.current_height()), a).unwrap_or(None).ok_or("error with lookup") + self.0.lookup_address(&BlockId::number(self.current_height()), a).unwrap_or(None).ok_or("error with lookup") } } @@ -232,7 +223,7 @@ impl transaction_pool::ChainApi for ChainApi { // transaction-pool trait. let api = &self.api; let next_index = known_nonces.entry(sender) - .or_insert_with(|| api.index(at, sender).ok().unwrap_or_else(Bounded::max_value)); + .or_insert_with(|| api.account_nonce(at, sender).ok().unwrap_or_else(Bounded::max_value)); trace!(target: "transaction-pool", "Next index for sender is {}; xt index is {}", next_index, xt.verified.index); diff --git a/substrate/srml/support/src/metadata.rs b/substrate/srml/support/src/metadata.rs index a2ac7ee5e9..a3095851a6 100644 --- a/substrate/srml/support/src/metadata.rs +++ b/substrate/srml/support/src/metadata.rs @@ -33,12 +33,14 @@ macro_rules! impl_runtime_metadata { $( $rest:tt )* ) => { impl $runtime { - pub fn metadata() -> $crate::metadata::RuntimeMetadata { - $crate::metadata::RuntimeMetadata { - outer_event: Self::outer_event_metadata(), - modules: __runtime_modules_to_metadata!($runtime;; $( $rest )*), - outer_dispatch: Self::outer_dispatch_metadata(), - } + pub fn metadata() -> Vec { + $crate::codec::Encode::encode( + &$crate::metadata::RuntimeMetadata { + outer_event: Self::outer_event_metadata(), + modules: __runtime_modules_to_metadata!($runtime;; $( $rest )*), + outer_dispatch: Self::outer_dispatch_metadata(), + } + ) } } } @@ -103,7 +105,7 @@ mod tests { StorageFunctionModifier, StorageFunctionType, FunctionMetadata, StorageMetadata, StorageFunctionMetadata, OuterDispatchMetadata, OuterDispatchCall }; - use codec::{Decode, Encode}; + use codec::Decode; mod system { pub trait Trait { @@ -344,12 +346,9 @@ mod tests { #[test] fn runtime_metadata() { - let metadata = TestRuntime::metadata(); - assert_eq!(EXPECTED_METADATA, metadata); - - let metadata_encoded = metadata.encode(); + let metadata_encoded = TestRuntime::metadata(); let metadata_decoded = RuntimeMetadata::decode(&mut &metadata_encoded[..]); - assert_eq!(metadata, metadata_decoded.unwrap()); + assert_eq!(EXPECTED_METADATA, metadata_decoded.unwrap()); } }