diff --git a/Cargo.lock b/Cargo.lock index b9d4696b20506..e3a7322537923 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -651,7 +651,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2521,7 +2521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2642,6 +2642,21 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sr-api-macros" +version = "0.1.0" +dependencies = [ + "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "substrate-client 0.1.0", + "substrate-primitives 0.1.0", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sr-io" version = "0.1.0" @@ -3039,7 +3054,7 @@ dependencies = [ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3054,7 +3069,7 @@ dependencies = [ "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3097,7 +3112,7 @@ dependencies = [ "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3167,6 +3182,7 @@ dependencies = [ "parity-codec 2.1.5 (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.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-api-macros 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", @@ -3687,7 +3703,7 @@ dependencies = [ [[package]] name = "syn" -version = "0.15.20" +version = "0.15.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3702,7 +3718,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4715,7 +4731,7 @@ dependencies = [ "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)" = "8886c8d2774e853fcd7d9d2131f6e40ba46c9c0e358e4d57178452abd6859bb0" +"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum sysinfo 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "11c5f6e8a7a7146f26ffed9a5ff8bab2706f1ac8a413a415e1d211b819d5c24d" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" diff --git a/Cargo.toml b/Cargo.toml index 98c433f60566b..30a3e92325c7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,7 @@ members = [ "core/serializer", "core/service", "core/service/test", - "core/state-db", + "core/sr-api-macros", "core/state-machine", "core/test-runtime", "core/telemetry", diff --git a/core/client/Cargo.toml b/core/client/Cargo.toml index 1ecf284dc191c..9d960cb1a37aa 100644 --- a/core/client/Cargo.toml +++ b/core/client/Cargo.toml @@ -26,6 +26,7 @@ substrate-primitives = { path = "../primitives", default-features = false } sr-primitives = { path = "../sr-primitives", default-features = false } sr-version = { path = "../sr-version", default-features = false } sr-std = { path = "../sr-std", default-features = false } +sr-api-macros = { path = "../sr-api-macros" } [dev-dependencies] substrate-test-client = { path = "../test-client" } diff --git a/core/client/src/block_builder/api.rs b/core/client/src/block_builder/api.rs index 67a66373aa302..3b8ceb630531f 100644 --- a/core/client/src/block_builder/api.rs +++ b/core/client/src/block_builder/api.rs @@ -16,24 +16,20 @@ //! The runtime api for building blocks. -use runtime_primitives::{traits::Block as BlockT, ApplyResult}; +use runtime_primitives::{traits::Block as BlockT, ApplyResult, InherentData, CheckInherentError}; use rstd::vec::Vec; decl_runtime_apis! { /// The `BlockBuilder` api trait that provides required functions for building a block for a runtime. - pub trait BlockBuilder { + pub trait BlockBuilder { /// Apply the given extrinsics. fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult; /// Finish the current block. fn finalise_block() -> ::Header; /// Generate inherent extrinsics. - fn inherent_extrinsics( - inherent: InherentExtrinsic - ) -> Vec; + fn inherent_extrinsics(inherent: InherentData) -> Vec<::Extrinsic>; /// Check that the inherents are valid. - fn check_inherents( - block: Block, data: InherentData - ) -> Result<(), Error>; + fn check_inherents(block: Block, data: InherentData) -> Result<(), CheckInherentError>; /// Generate a random seed. fn random_seed() -> ::Hash; } diff --git a/core/client/src/client.rs b/core/client/src/client.rs index 92a4688845464..205827b6d4455 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -1221,14 +1221,14 @@ pub(crate) mod tests { use consensus::BlockOrigin; use test_client::client::backend::Backend as TestBackend; use test_client::BlockBuilderExt; - use test_client::runtime::{self, Block, Transfer, ClientWithApi, test_api::TestAPI}; + use test_client::runtime::{self, Block, Transfer, RuntimeApi, test_api::TestAPI}; /// Returns tuple, consisting of: /// 1) test client pre-filled with blocks changing balances; /// 2) roots of changes tries for these blocks /// 3) test cases in form (begin, end, key, vec![(block, extrinsic)]) that are required to pass pub fn prepare_client_with_key_changes() -> ( - test_client::client::Client, + test_client::client::Client, Vec, Vec<(u64, u64, Vec, Vec<(u64, u32)>)>, ) { @@ -1303,14 +1303,14 @@ pub(crate) mod tests { assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - &Keyring::Alice.to_raw_public() + &Keyring::Alice.to_raw_public().into() ).unwrap(), 1000 ); assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - &Keyring::Ferdie.to_raw_public() + &Keyring::Ferdie.to_raw_public().into() ).unwrap(), 0 ); @@ -1359,14 +1359,14 @@ pub(crate) mod tests { assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - &Keyring::Alice.to_raw_public() + &Keyring::Alice.to_raw_public().into() ).unwrap(), 958 ); assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - &Keyring::Ferdie.to_raw_public() + &Keyring::Ferdie.to_raw_public().into() ).unwrap(), 42 ); diff --git a/core/client/src/lib.rs b/core/client/src/lib.rs index a73671ca4760c..fb07c130b25ff 100644 --- a/core/client/src/lib.rs +++ b/core/client/src/lib.rs @@ -31,6 +31,8 @@ extern crate substrate_state_machine as state_machine; extern crate substrate_consensus_common as consensus; extern crate sr_version as runtime_version; extern crate sr_std as rstd; +#[macro_use] +extern crate sr_api_macros; #[cfg(test)] extern crate substrate_keyring as keyring; #[cfg(test)] @@ -114,3 +116,6 @@ pub use notifications::{StorageEventStream, StorageChangeSet}; pub use state_machine::ExecutionStrategy; #[cfg(feature = "std")] pub use leaves::LeafSet; + +#[doc(inline)] +pub use sr_api_macros::{decl_runtime_apis, impl_runtime_apis}; diff --git a/core/client/src/runtime_api/mod.rs b/core/client/src/runtime_api.rs similarity index 74% rename from core/client/src/runtime_api/mod.rs rename to core/client/src/runtime_api.rs index acf4db705c902..2e5c5e38cad39 100644 --- a/core/client/src/runtime_api/mod.rs +++ b/core/client/src/runtime_api.rs @@ -14,17 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! All the functionality required for declaring and implementing runtime api's. -//! Core api's are also declared here. +//! All the functionality required for declaring and implementing runtime apis. #[doc(hidden)] #[cfg(feature = "std")] pub use state_machine::OverlayedChanges; #[doc(hidden)] -pub use runtime_primitives::{traits::Block as BlockT, generic::BlockId}; -#[cfg(feature = "std")] -use runtime_primitives::traits::ApiRef; -pub use runtime_version::ApiId; +pub use runtime_primitives::{ + traits::{Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, ApiRef}, generic::BlockId, + transaction_validity::TransactionValidity +}; +pub use runtime_version::{ApiId, RuntimeVersion}; #[doc(hidden)] pub use rstd::slice; #[cfg(feature = "std")] @@ -32,12 +32,9 @@ use rstd::result; pub use codec::{Encode, Decode}; #[cfg(feature = "std")] use error; -pub use runtime_version::RuntimeVersion; +use rstd::vec::Vec; +use primitives::{AuthorityId, OpaqueMetadata}; -mod core; -#[macro_use] -mod macros; -mod traits; /// Something that can be constructed to a runtime api. #[cfg(feature = "std")] @@ -113,11 +110,29 @@ pub mod id { pub const METADATA: ApiId = *b"metadata"; } -pub use self::core::*; -pub use self::traits::*; +decl_runtime_apis! { + /// The `Core` api trait that is mandantory for each runtime. + #[core_trait] + pub trait Core { + /// Returns the version of the runtime. + fn version() -> RuntimeVersion; + /// Returns the authorities. + fn authorities() -> Vec; + /// Execute the given block. + fn execute_block(block: Block); + /// Initialise a block with the given header. + fn initialise_block(header: ::Header); + } -/// The runtime apis that should be implemented for the `Runtime`. -pub mod runtime { - pub use super::core::runtime::Core; - pub use super::traits::runtime::*; + /// The `Metadata` api trait that returns metadata for the runtime. + pub trait Metadata { + /// Returns the metadata of a runtime. + fn metadata() -> OpaqueMetadata; + } + + /// The `TaggedTransactionQueue` api trait for interfering with the new transaction queue. + pub trait TaggedTransactionQueue { + /// Validate the given transaction. + fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity; + } } diff --git a/core/client/src/runtime_api/core.rs b/core/client/src/runtime_api/core.rs deleted file mode 100644 index 20798422b7fad..0000000000000 --- a/core/client/src/runtime_api/core.rs +++ /dev/null @@ -1,62 +0,0 @@ -// 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 . - -#[cfg(feature = "std")] -use super::{ConstructRuntimeApi, ApiExt}; -use runtime_version::RuntimeVersion; -use runtime_primitives::traits::Block as BlockT; -#[cfg(feature = "std")] -use runtime_primitives::generic::BlockId; -use primitives::AuthorityId; -#[cfg(feature = "std")] -use error::Result; -use rstd::vec::Vec; - -/// The `Core` api trait that is mandantory for each runtime. -/// This is the side that should be implemented for the `RuntimeApi` that is used by the `Client`. -/// Any modifications at one of these two traits, needs to be done on the other one as well. -#[cfg(feature = "std")] -pub trait Core: 'static + Send + Sync + ConstructRuntimeApi + ApiExt { - /// Returns the version of the runtime. - fn version(&self, at: &BlockId) -> Result; - /// Returns the authorities. - fn authorities(&self, at: &BlockId) -> Result>; - /// Execute the given block. - fn execute_block(&self, at: &BlockId, block: &Block) -> Result<()>; - /// Initialise a block with the given header. - fn initialise_block( - &self, - at: &BlockId, - header: &::Header - ) -> Result<()>; -} - -pub mod runtime { - use super::*; - - /// The `Core` api trait that is mandantory for each runtime. - /// This is the side that should be implemented for the `Runtime`. - pub trait Core { - /// Returns the version of the runtime. - fn version() -> RuntimeVersion; - /// Returns the authorities. - fn authorities() -> Vec; - /// Execute the given block. - fn execute_block(block: Block); - /// Initialise a block with the given header. - fn initialise_block(header: ::Header); - } -} diff --git a/core/client/src/runtime_api/macros.rs b/core/client/src/runtime_api/macros.rs deleted file mode 100644 index 1721fbd416a39..0000000000000 --- a/core/client/src/runtime_api/macros.rs +++ /dev/null @@ -1,650 +0,0 @@ -// 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 . - -//! Macros for declaring and implementing the runtime APIs. - -// these are part of the public API, so need to be re-exported -pub use runtime_version::{ApiId, RuntimeVersion}; - -/// Declare the given API traits. -/// -/// # Example: -/// -/// ```nocompile -/// decl_runtime_apis!{ -/// pub trait Test ExtraClientSide { -/// fn test(event: Event) -> AccountId; -/// -/// /// A function that will have the extra parameter `param` on the client side, -/// /// the runtime does not have any parameter. -/// fn testWithExtraParams() ExtraClientSide(param: &Self::ClientArg); -/// } -/// } -/// ``` -/// -/// Will result in the following declaration: -/// -/// ```nocompile -/// mod runtime { -/// pub trait Test { -/// fn test(event: Event) -> AccountId; -/// } -/// } -/// -/// pub trait Test { -/// type Error; -/// type ClientArg; -/// fn test(&self, at: &BlockId, event: Event) -> Result; -/// fn testWithExtraParams(&self, at: &BlockId, param: &Client) -> Result; -/// } -/// ``` -/// -/// The declarations generated in the `runtime` module will be used by `impl_runtime_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_runtime_apis { - ( - $( - $( #[$attr:meta] )* - pub trait $name:ident $(< $( $generic_param:ident $( : $generic_bound:ident )* ),* >)* - $( ExtraClientSide < $( $client_generic_param:ident $( : $client_generic_bound:ident )* ),+ > )* - { - $( - $( #[$fn_attr:meta] )* - fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( - $( $param_name:ident : $param_type:ty ),* - ) - $( ExtraClientSide ( $( $client_param_name:ident : $client_param_type:ty ),+ ) )* - $( -> $return_ty:ty)*; - )* - } - )* - ) => { - $( - decl_runtime_apis!( - @ADD_BLOCK_GENERIC - $( #[$attr] )* - pub trait $name $(< $( $generic_param $( : $generic_bound )* ),* >)* { - $( $( type $client_generic_param $( : $client_generic_bound )*; )* )* - $( - $( #[$fn_attr] )* - fn $fn_name $( < $( $fn_generic ),* > )* ( - $( $( $client_param_name: $client_param_type, )* )* - $( $param_name : &$param_type, )* - ) $( -> $return_ty )*; - )* - }; - ; - ; - $( $( $generic_param $( : $generic_bound )* ),* )* - ); - )* - decl_runtime_apis! { - @GENERATE_RUNTIME_TRAITS - $( - $( #[$attr] )* - pub trait $name $(< $( $generic_param $( : $generic_bound )* ),* >)* { - $( - $( #[$fn_attr] )* - 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 )* ),* >)* { - $( type $client_generic_param:ident $( : $client_generic_bound:ident )*; )* - $( - $( #[$fn_attr:meta] )* - 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_runtime_apis!( - @ADD_BLOCK_GENERIC - $( #[$attr] )* - pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { - $( type $client_generic_param $( : $client_generic_bound )*; )* - $( - $( #[$fn_attr] )* - fn $fn_name $( < $( $fn_generic ),* > )* ( - $( $param_name : $param_type, )* - ) $( -> $return_ty )*; - )* - }; - Found; - $( $generic_param_parsed $( : $generic_bound_parsed )* , )* Block: $crate::runtime_api::BlockT; - $( $generic_param_rest $( : $generic_bound_rest )* ),* - ); - }; - (@ADD_BLOCK_GENERIC - $( #[$attr:meta] )* - pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { - $( type $client_generic_param:ident $( : $client_generic_bound:ident )*; )* - $( - $( #[$fn_attr:meta] )* - 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_runtime_apis!( - @ADD_BLOCK_GENERIC - $( #[$attr] )* - pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { - $( type $client_generic_param $( : $client_generic_bound )*; )* - $( - $( #[$fn_attr] )* - 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 )* ),* >)* { - $( type $client_generic_param:ident $( : $client_generic_bound:ident )*; )* - $( - $( #[$fn_attr:meta] )* - 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_runtime_apis!( - @GENERATE_RETURN_TYPES - $( #[$attr] )* - pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { - $( type $client_generic_param $( : $client_generic_bound )*; )* - $( - $( #[$fn_attr] )* - 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 )* ),* >)* { - $( type $client_generic_param:ident $( : $client_generic_bound:ident )*; )* - $( - $( #[$fn_attr:meta] )* - 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_runtime_apis!( - @GENERATE_RETURN_TYPES - $( #[$attr] )* - pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { - $( type $client_generic_param $( : $client_generic_bound )*; )* - $( - $( #[$fn_attr] )* - fn $fn_name $( < $( $fn_generic ),* > )* ( - $( $param_name : $param_type, )* - ) $( -> $return_ty )*; - )* - }; - // We need to add the required generic Block parameter - Block: $crate::runtime_api::BlockT $(, $generic_param_parsed $( : $generic_bound_parsed )* )*; - {}; - $( $( $return_ty )*; )* - ); - }; - (@GENERATE_RETURN_TYPES - $( #[$attr:meta] )* - pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { - $( type $client_generic_param:ident $( : $client_generic_bound:ident )*; )* - $( - $( #[$fn_attr:meta] )* - 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_runtime_apis!( - @GENERATE_RETURN_TYPES - $( #[$attr] )* - pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { - $( type $client_generic_param $( : $client_generic_bound )*; )* - $( - $( #[$fn_attr] )* - fn $fn_name $( < $( $fn_generic ),* > )* ( - $( $param_name : $param_type, )* - ) $( -> $return_ty )*; - )* - }; - $( $generic_param_parsed $( : $generic_bound_parsed )* ),*; - { $( $result_return_ty; )* $crate::error::Result<$return_ty_current>; }; - $( $( $return_ty_rest )*; )* - ); - }; - (@GENERATE_RETURN_TYPES - $( #[$attr:meta] )* - pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { - $( type $client_generic_param:ident $( : $client_generic_bound:ident )*; )* - $( - $( #[$fn_attr:meta] )* - 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_runtime_apis!( - @GENERATE_RETURN_TYPES - $( #[$attr] )* - pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { - $( type $client_generic_param $( : $client_generic_bound )*; )* - $( - $( #[$fn_attr] )* - fn $fn_name $( < $( $fn_generic ),* > )* ( - $( $param_name : $param_type, )* - ) $( -> $return_ty )*; - )* - }; - $( $generic_param_parsed $( : $generic_bound_parsed )* ),*; - { $( $result_return_ty; )* $crate::error::Result<()>; }; - $( $( $return_ty_rest )*; )* - ); - }; - (@GENERATE_RETURN_TYPES - $( #[$attr:meta] )* - pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { - $( type $client_generic_param:ident $( : $client_generic_bound:ident )*; )* - $( - $( #[$fn_attr:meta] )* - 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_runtime_apis!( - @GENERATE_CLIENT_TRAITS - $( #[$attr] )* - pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* { - $( type $client_generic_param $( : $client_generic_bound )*; )* - $( - $( #[$fn_attr] )* - fn $fn_name $( < $( $fn_generic ),* > )* ( - $( $param_name : $param_type, )* - ) $( -> $return_ty )*; - )* - }; - $( $generic_param_parsed $( : $generic_bound_parsed )* ),*; - { $( $result_return_ty; )* }; - ); - }; - (@GENERATE_CLIENT_TRAITS - $( #[$attr:meta] )* - pub trait $name:ident $(< $( $generic_param_orig:ident $( : $generic_bound_orig:ident )* ),* >)* { - $( type $client_generic_param:ident $( : $client_generic_bound:ident )*; )* - $( - $( #[$fn_attr:meta] )* - 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; )* }; - ) => { - $( #[$attr] )* - #[cfg(feature = "std")] - pub trait $name < $( $generic_param_parsed $( : $generic_bound_parsed )* ),* > : $crate::runtime_api::Core { - $( type $client_generic_param $( : $client_generic_bound )*; )* - - $( - $( #[$fn_attr] )* - fn $fn_name $( < $( $fn_generic: $crate::runtime_api::Encode + $crate::runtime_api::Decode ),* > )* ( - &self, at: &$crate::runtime_api::BlockId $(, $param_name: $param_type )* - ) -> $result_return_ty; - )* - } - }; - (@GENERATE_RUNTIME_TRAITS - $( - $( #[$attr:meta] )* - pub trait $name:ident $(< $( $generic_param:ident $( : $generic_bound:ident )* ),* >)* { - $( - $( #[$fn_attr:meta] )* - fn $fn_name:ident $( < $( $fn_generic:ident ),* > )* ( - $( $param_name:ident : $param_type:ty )* - ) $( -> $return_ty:ty)*; - )* - }; - )* - ) => { - decl_runtime_apis! { - @GENERATE_RUNTIME_TRAITS_WITH_JOINED_GENERICS - $( - $( #[$attr] )* - pub trait $name < $( $( $generic_param $( : $generic_bound )*, )* )* $( $( $( $fn_generic, )* )* )* > { - $( - $( #[$fn_attr] )* - 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_attr:meta] )* - fn $fn_name:ident($( $param_name:ident : $param_type:ty ),*) $( -> $return_ty:ty)*; - )* - } - )* - ) => { - /// The API traits to implement on the runtime side. - pub mod runtime { - use super::*; - - $( - $( #[$attr] )* - pub trait $name < $( $generic_param $( : $generic_bound )* ),* > { - $( - $( #[$fn_attr] )* - fn $fn_name ($( $param_name: $param_type ),*) $( -> $return_ty )*; - )* - } - )* - } - }; -} - -/// Implement the given API's for the given runtime. -/// All desired API's need to be implemented in one `impl_runtime_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 substrate_client as client; -/// -/// use client::runtime_api::runtime::{Core, TaggedTransactionQueue}; -/// -/// impl_runtime_apis! { -/// impl Core for Runtime { -/// fn version() -> RuntimeVersion { unimplemented!() } -/// fn authorities() -> Vec { unimplemented!() } -/// fn execute_block(block: Block) { -/// //comment -/// unimplemented!() -/// } -/// } -/// -/// impl TaggedTransactionQueue for Runtime { -/// fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { -/// unimplemented!() -/// } -/// } -/// } -/// -/// fn main() {} -/// ``` -#[macro_export] -macro_rules! impl_runtime_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_runtime_apis! { - @EXTEND_FUNCTIONS - $runtime; - ; - $trait_name; - $( $( $generic ),* )*; - { $( $fn_name ( $( $arg_name: $arg_ty ),* ); )* } - $( $rest )* - } - }; - ( - $runtime:ident; - $( $trait_name_parsed:ident $( < $( $parsed_generic: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_runtime_apis! { - @EXTEND_FUNCTIONS - $runtime; - $( - $trait_name_parsed $( < $( $parsed_generic ),* > )* - ::$fn_name_parsed ( $( $arg_name_parsed: $arg_ty_parsed ),* ); - )*; - $trait_name; - $( $( $generic ),* )*; - { $( $fn_name ( $( $arg_name: $arg_ty ),* ); )* } - $( $rest )* - } - }; - (@EXTEND_FUNCTIONS - $runtime:ident; - $( $trait_name_parsed:ident $( < $( $parsed_generic:ident ),* > )*::$fn_name_parsed:ident ( - $( $arg_name_parsed:ident : $arg_ty_parsed:ty ),* ); - )*; - $trait_name:ident; - $( $generic:ident ),*; - { - $fn_name_extend:ident ( $( $arg_name_extend:ident : $arg_ty_extend:ty ),* ); - $( $extend_rest:tt )* - } - $( $rest:tt )* - ) => { - impl_runtime_apis! { - @EXTEND_FUNCTIONS - $runtime; - $( - $trait_name_parsed $( < $( $parsed_generic ),* > )* - ::$fn_name_parsed ( $( $arg_name_parsed: $arg_ty_parsed ),* ); - )* - $trait_name < $( $generic ),* > - ::$fn_name_extend ( $( $arg_name_extend: $arg_ty_extend ),* );; - $trait_name; - $( $generic ),*; - { - $( $extend_rest )* - } - $( $rest )* - } - }; - (@EXTEND_FUNCTIONS - $runtime:ident; - $( $trait_name_parsed:ident $( < $( $parsed_generic:ident ),* > )*::$fn_name_parsed:ident ( - $( $arg_name_parsed:ident : $arg_ty_parsed:ty ),* ); - )*; - $trait_name:ident; - $( $generic:ident ),*; - {} - $( $rest:tt )* - ) => { - impl_runtime_apis! { - $runtime; - $( - $trait_name_parsed $( < $( $parsed_generic ),* > )* - ::$fn_name_parsed ( $( $arg_name_parsed: $arg_ty_parsed ),* ); - )*; - $( $rest )* - } - }; - ( - $runtime:ident; - $( - $trait_name:ident $( < $( $generic: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_runtime_apis! { - @GENERATE_IMPL_CALL - $runtime; - $trait_name $( < $( $generic ),* > )*; - $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::runtime_api::slice::from_raw_parts(input_data, input_len) - } - }; - - let output = { impl_runtime_apis! { - @GENERATE_IMPL_CALL - $runtime; - $trait_name $( < $( $generic ),* > )*; - $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; - $trait_name:ident $( < $( $generic:ident ),* > )*; - $fn_name:ident; - $arg_name:ident : $arg_ty:ty; - $input:ident; - ) => { - let $arg_name : $arg_ty = match $crate::runtime_api::Decode::decode(&mut $input) { - Some(input) => input, - None => panic!("Bad input data provided to {}", stringify!($fn_name)), - }; - - let output = <$runtime as $trait_name $( < $( $generic ),* > )*>::$fn_name($arg_name); - $crate::runtime_api::Encode::encode(&output) - }; - (@GENERATE_IMPL_CALL - $runtime:ident; - $trait_name:ident $( < $( $generic:ident ),* > )*; - $fn_name:ident; - $( $arg_name:ident : $arg_ty:ty ),*; - $input:ident; - ) => { - let ( $( $arg_name ),* ) : ($( $arg_ty ),*) = match $crate::runtime_api::Decode::decode(&mut $input) { - Some(input) => input, - None => panic!("Bad input data provided to {}", stringify!($fn_name)), - }; - - let output = <$runtime as $trait_name $( < $( $generic ),* > )*>::$fn_name($( $arg_name ),*); - $crate::runtime_api::Encode::encode(&output) - }; -} diff --git a/core/client/src/runtime_api/traits.rs b/core/client/src/runtime_api/traits.rs deleted file mode 100644 index 4d237a09ef522..0000000000000 --- a/core/client/src/runtime_api/traits.rs +++ /dev/null @@ -1,35 +0,0 @@ -// 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 . - -use primitives::OpaqueMetadata; -use runtime_primitives::{ - traits::{Block as BlockT}, - transaction_validity::TransactionValidity -}; - -decl_runtime_apis! { - /// The `Metadata` api trait that returns metadata for the runtime. - pub trait Metadata { - /// Returns the metadata of a runtime. - fn metadata() -> OpaqueMetadata; - } - - /// The `TaggedTransactionQueue` api trait for interfering with the new transaction queue. - pub trait TaggedTransactionQueue { - /// Validate the given transaction. - fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity; - } -} diff --git a/core/consensus/aura/src/lib.rs b/core/consensus/aura/src/lib.rs index 0313f7af3ca08..a871861d18e14 100644 --- a/core/consensus/aura/src/lib.rs +++ b/core/consensus/aura/src/lib.rs @@ -440,7 +440,7 @@ mod tests { type Error = client::error::Error; - type TestClient = client::Client; + type TestClient = client::Client; struct DummyFactory(Arc); struct DummyProposer(u64, Arc); diff --git a/core/consensus/common/src/lib.rs b/core/consensus/common/src/lib.rs index 4758a4abfe49c..227131914cc37 100644 --- a/core/consensus/common/src/lib.rs +++ b/core/consensus/common/src/lib.rs @@ -86,25 +86,6 @@ pub trait Proposer { fn propose(&self) -> Self::Create; } -/// Inherent data to include in a block. -#[derive(Encode, Decode)] -pub struct InherentData { - /// Current timestamp. - pub timestamp: u64, - /// Indices of offline validators. - pub offline_indices: Vec, -} - -impl InherentData { - /// Create a new `InherentData` instance. - pub fn new(timestamp: u64, offline_indices: Vec) -> Self { - Self { - timestamp, - offline_indices - } - } -} - /// An oracle for when major synchronization work is being undertaken. /// /// Generally, consensus authoring work isn't undertaken while well behind diff --git a/core/finality-grandpa/primitives/src/lib.rs b/core/finality-grandpa/primitives/src/lib.rs index 49405745338d5..df224fa9d4ad1 100644 --- a/core/finality-grandpa/primitives/src/lib.rs +++ b/core/finality-grandpa/primitives/src/lib.rs @@ -35,7 +35,7 @@ extern crate substrate_client as client; extern crate sr_std as rstd; use substrate_primitives::AuthorityId; -use sr_primitives::traits::{Block as BlockT, DigestFor, NumberFor}; +use sr_primitives::traits::{DigestFor, NumberFor}; use rstd::vec::Vec; /// A scheduled change of authority set. @@ -79,7 +79,7 @@ decl_runtime_apis! { /// applied in the runtime after those N blocks have passed. /// /// The consensus protocol will coordinate the handoff externally. - pub trait GrandpaApi { + pub trait GrandpaApi { /// Check a digest for pending changes. /// Return `None` if there are no pending changes. /// diff --git a/core/finality-grandpa/src/tests.rs b/core/finality-grandpa/src/tests.rs index c8ba80098dc62..1dfe8d69e8ddc 100644 --- a/core/finality-grandpa/src/tests.rs +++ b/core/finality-grandpa/src/tests.rs @@ -43,7 +43,7 @@ type PeerData = test_client::Backend, test_client::Executor, Block, - test_client::runtime::ClientWithApi, + test_client::runtime::RuntimeApi, > > >; diff --git a/core/network/src/import_queue.rs b/core/network/src/import_queue.rs index cb7bf86e697c0..c6bb0c51bc1d9 100644 --- a/core/network/src/import_queue.rs +++ b/core/network/src/import_queue.rs @@ -699,7 +699,7 @@ pub mod tests { } } - fn prepare_good_block() -> (client::Client, Hash, u64, BlockData) { + fn prepare_good_block() -> (client::Client, Hash, u64, BlockData) { let client = test_client::new(); let block = client.new_block().unwrap().bake().unwrap(); client.justify_and_import(BlockOrigin::File, block).unwrap(); diff --git a/core/network/src/test/mod.rs b/core/network/src/test/mod.rs index 374e825bc8b70..603aaa9572d93 100644 --- a/core/network/src/test/mod.rs +++ b/core/network/src/test/mod.rs @@ -129,7 +129,7 @@ pub struct TestPacket { recipient: NodeIndex, } -pub type PeersClient = client::Client; +pub type PeersClient = client::Client; pub struct Peer, D> { client: Arc, diff --git a/core/service/src/consensus.rs b/core/service/src/consensus.rs index 338c1680cf28e..240ba7dc498a7 100644 --- a/core/service/src/consensus.rs +++ b/core/service/src/consensus.rs @@ -25,10 +25,11 @@ use std; use client::{self, error, Client as SubstrateClient, CallExecutor}; use client::{block_builder::api::BlockBuilder as BlockBuilderApi, runtime_api::{id::BLOCK_BUILDER, Core}}; use codec::{Decode, Encode}; -use consensus_common::{self, InherentData, evaluation, offline_tracker::OfflineTracker}; +use consensus_common::{self, evaluation, offline_tracker::OfflineTracker}; use primitives::{H256, AuthorityId, ed25519, Blake2Hasher}; use runtime_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi}; use runtime_primitives::generic::BlockId; +use runtime_primitives::InherentData; use transaction_pool::txpool::{self, Pool as TransactionPool}; use parking_lot::RwLock; @@ -200,10 +201,7 @@ impl consensus_common::Proposer<::Block> for Pro ) } - let inherent_data = InherentData { - timestamp, - offline_indices, - }; + let inherent_data = InherentData::new(timestamp, offline_indices); let block = self.client.build_block( &self.parent_id, diff --git a/core/sr-api-macros/Cargo.toml b/core/sr-api-macros/Cargo.toml new file mode 100644 index 0000000000000..05172e5bf8222 --- /dev/null +++ b/core/sr-api-macros/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "sr-api-macros" +version = "0.1.0" +authors = ["Parity Technologies "] + +[lib] +proc-macro = true + +[dependencies] +quote = "0.6" +syn = { version = "0.15", features = [ "full", "fold", "extra-traits", "visit" ] } +proc-macro2 = "0.4" + +[dev-dependencies] +substrate-client = { path = "../client" } +sr-primitives = { path = "../sr-primitives" } +substrate-primitives = { path = "../primitives" } +parity-codec = "2.1" +parity-codec-derive = "2.1" +serde = "1.0" diff --git a/core/sr-api-macros/src/compile_fail_tests.rs b/core/sr-api-macros/src/compile_fail_tests.rs new file mode 100644 index 0000000000000..14d77d003ccec --- /dev/null +++ b/core/sr-api-macros/src/compile_fail_tests.rs @@ -0,0 +1,408 @@ +// 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 . + +//! Compile fail tests. + +mod declaring_own_block { + /*! + ```compile_fail + #[macro_use] + extern crate substrate_client; + extern crate sr_primitives as runtime_primitives; + + use runtime_primitives::traits::Block as BlockT; + + decl_runtime_apis! { + pub trait Api { + fn test(); + } + } + + fn main() {} + ``` + */ +} + +mod declaring_own_block_with_different_name { + /*! + ```compile_fail + #[macro_use] + extern crate substrate_client; + extern crate sr_primitives as runtime_primitives; + + use runtime_primitives::traits::Block as BlockT; + + decl_runtime_apis! { + pub trait Api { + fn test(); + } + } + + fn main() {} + ``` + */ +} + +mod adding_self_parameter { + /*! + ```compile_fail + #[macro_use] + extern crate substrate_client; + extern crate sr_primitives as runtime_primitives; + + decl_runtime_apis! { + pub trait Api { + fn test(&self); + } + } + + fn main() {} + ``` + */ +} + +mod adding_at_parameter { + /*! + ```compile_fail + #[macro_use] + extern crate substrate_client; + extern crate sr_primitives as runtime_primitives; + + decl_runtime_apis! { + pub trait Api { + fn test(at: u64); + } + } + + fn main() {} + ``` + */ +} + +mod adding_parameter_with_type_reference { + /*! + ```compile_fail + #[macro_use] + extern crate substrate_client; + extern crate sr_primitives as runtime_primitives; + + decl_runtime_apis! { + pub trait Api { + fn test(data: &u64); + } + } + + fn main() {} + ``` + */ +} + +mod missing_block_generic_parameter { + /*! + ```compile_fail + #[macro_use] + extern crate substrate_client; + extern crate sr_primitives as runtime_primitives; + extern crate substrate_primitives as primitives; + #[macro_use] + extern crate parity_codec_derive; + extern crate serde; + extern crate core; + + use primitives::hash::H256; + use runtime_primitives::traits::{BlakeTwo256, GetNodeBlockType, Extrinsic as ExtrinsicT}; + + // All the stuff we need to declare our `Block` + pub type BlockNumber = u64; + pub type DigestItem = runtime_primitives::generic::DigestItem; + pub type Digest = runtime_primitives::generic::Digest; + #[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] + pub struct Extrinsic {} + + impl serde::Serialize for Extrinsic { + fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { + unimplemented!() + } + } + impl ExtrinsicT for Extrinsic { + fn is_signed(&self) -> Option { + unimplemented!() + } + } + pub type Header = runtime_primitives::generic::Header; + pub type Block = runtime_primitives::generic::Block; + + /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` + /// trait are done by the `construct_runtime!` macro in a real runtime. + struct Runtime {} + impl GetNodeBlockType for Runtime { + type NodeBlock = Block; + } + + decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + } + } + + impl_runtime_apis! { + impl self::Api for Runtime { + fn test(data: u64) { + unimplemented!() + } + } + } + + fn main() {} + ``` + */ +} + +mod missing_path_for_trait { + /*! + ```compile_fail + #[macro_use] + extern crate substrate_client; + extern crate sr_primitives as runtime_primitives; + extern crate substrate_primitives as primitives; + #[macro_use] + extern crate parity_codec_derive; + extern crate serde; + extern crate core; + + use primitives::hash::H256; + use runtime_primitives::traits::{BlakeTwo256, GetNodeBlockType, Extrinsic as ExtrinsicT}; + + // All the stuff we need to declare our `Block` + pub type BlockNumber = u64; + pub type DigestItem = runtime_primitives::generic::DigestItem; + pub type Digest = runtime_primitives::generic::Digest; + #[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] + pub struct Extrinsic {} + impl serde::Serialize for Extrinsic + { + fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { + unimplemented!() + } + } + impl ExtrinsicT for Extrinsic { + fn is_signed(&self) -> Option { + unimplemented!() + } + } + pub type Header = runtime_primitives::generic::Header; + pub type Block = runtime_primitives::generic::Block; + + /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` + /// trait are done by the `construct_runtime!` macro in a real runtime. + struct Runtime {} + impl GetNodeBlockType for Runtime { + type NodeBlock = Block; + } + + decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + } + } + + impl_runtime_apis! { + impl Api for Runtime { + fn test(data: u64) { + unimplemented!() + } + } + } + + fn main() {} + ``` + */ +} + +mod empty_impl_runtime_apis_call { + /*! + ```compile_fail + #[macro_use] + extern crate substrate_client; + extern crate sr_primitives as runtime_primitives; + extern crate substrate_primitives as primitives; + #[macro_use] + extern crate parity_codec_derive; + extern crate serde; + extern crate core; + + use primitives::hash::H256; + use runtime_primitives::traits::{BlakeTwo256, GetNodeBlockType, Extrinsic as ExtrinsicT}; + + // All the stuff we need to declare our `Block` + pub type BlockNumber = u64; + pub type DigestItem = runtime_primitives::generic::DigestItem; + pub type Digest = runtime_primitives::generic::Digest; + #[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] + pub struct Extrinsic {} + impl serde::Serialize for Extrinsic + { + fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { + unimplemented!() + } + } + impl ExtrinsicT for Extrinsic { + fn is_signed(&self) -> Option { + unimplemented!() + } + } + pub type Header = runtime_primitives::generic::Header; + pub type Block = runtime_primitives::generic::Block; + + /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` + /// trait are done by the `construct_runtime!` macro in a real runtime. + struct Runtime {} + impl GetNodeBlockType for Runtime { + type NodeBlock = Block; + } + + decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + } + } + + impl_runtime_apis! {} + + fn main() {} + ``` + */ +} + +mod type_reference_in_impl_runtime_apis_call { + /*! + ```compile_fail + #[macro_use] + extern crate substrate_client; + extern crate sr_primitives as runtime_primitives; + extern crate substrate_primitives as primitives; + #[macro_use] + extern crate parity_codec_derive; + extern crate serde; + extern crate core; + + use primitives::hash::H256; + use runtime_primitives::traits::{BlakeTwo256, GetNodeBlockType, Extrinsic as ExtrinsicT}; + + // All the stuff we need to declare our `Block` + pub type BlockNumber = u64; + pub type DigestItem = runtime_primitives::generic::DigestItem; + pub type Digest = runtime_primitives::generic::Digest; + #[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] + pub struct Extrinsic {} + impl serde::Serialize for Extrinsic + { + fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { + unimplemented!() + } + } + impl ExtrinsicT for Extrinsic { + fn is_signed(&self) -> Option { + unimplemented!() + } + } + pub type Header = runtime_primitives::generic::Header; + pub type Block = runtime_primitives::generic::Block; + + /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` + /// trait are done by the `construct_runtime!` macro in a real runtime. + struct Runtime {} + impl GetNodeBlockType for Runtime { + type NodeBlock = Block; + } + + decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + } + } + + impl_runtime_apis! { + impl self::Api for Runtime { + fn test(data: &u64) { + unimplemented!() + } + } + } + + fn main() {} + ``` + */ +} + +mod impl_incorrect_method_signature { + /*! + ```compile_fail + #[macro_use] + extern crate substrate_client; + extern crate sr_primitives as runtime_primitives; + extern crate substrate_primitives as primitives; + #[macro_use] + extern crate parity_codec_derive; + extern crate serde; + extern crate core; + + use primitives::hash::H256; + use runtime_primitives::traits::{BlakeTwo256, GetNodeBlockType, Extrinsic as ExtrinsicT}; + + // All the stuff we need to declare our `Block` + pub type BlockNumber = u64; + pub type DigestItem = runtime_primitives::generic::DigestItem; + pub type Digest = runtime_primitives::generic::Digest; + #[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] + pub struct Extrinsic {} + impl serde::Serialize for Extrinsic + { + fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { + unimplemented!() + } + } + impl ExtrinsicT for Extrinsic { + fn is_signed(&self) -> Option { + unimplemented!() + } + } + pub type Header = runtime_primitives::generic::Header; + pub type Block = runtime_primitives::generic::Block; + + /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` + /// trait are done by the `construct_runtime!` macro in a real runtime. + struct Runtime {} + impl GetNodeBlockType for Runtime { + type NodeBlock = Block; + } + + decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + } + } + + impl_runtime_apis! { + impl self::Api for Runtime { + fn test(data: String) {} + } + } + + fn main() {} + ``` + */ +} diff --git a/core/sr-api-macros/src/decl_runtime_apis.rs b/core/sr-api-macros/src/decl_runtime_apis.rs new file mode 100644 index 0000000000000..1f723519e1af7 --- /dev/null +++ b/core/sr-api-macros/src/decl_runtime_apis.rs @@ -0,0 +1,278 @@ +// 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 . + +use utils::{ + generate_crate_access, generate_hidden_includes, generate_runtime_mod_name_for_trait, + fold_fn_decl_for_client_side +}; + +use proc_macro; +use proc_macro2::TokenStream; + +use quote::quote; + +use syn::{ + spanned::Spanned, parse_macro_input, parse::{Parse, ParseStream, Result, Error}, + fold::{self, Fold}, FnDecl, parse_quote, ItemTrait, Generics, GenericParam, Attribute, + visit::{Visit, self}, FnArg, Pat, TraitBound, Type +}; + +/// Unique identifier used to make the hidden includes unique for this macro. +const HIDDEN_INCLUDES_ID: &str = "DECL_RUNTIME_APIS"; + +/// The structure used for parsing the runtime api declarations. +struct RuntimeApiDecls { + decls: Vec, +} + +impl Parse for RuntimeApiDecls { + fn parse(input: ParseStream) -> Result { + let mut decls = Vec::new(); + + while !input.is_empty() { + decls.push(ItemTrait::parse(input)?); + } + + Ok(Self { decls }) + } +} + +/// Extend the given generics with `Block: BlockT` as first generic parameter. +fn extend_generics_with_block(generics: &mut Generics) { + let c = generate_crate_access(HIDDEN_INCLUDES_ID); + + generics.lt_token = Some(parse_quote!(<)); + generics.params.insert(0, parse_quote!( Block: #c::runtime_api::BlockT )); + generics.gt_token = Some(parse_quote!(>)); +} + +// Check if `core_trait` attribute is present and remove it. Returns if the attribute was found. +fn remove_core_trait_attribute(attrs: &mut Vec) -> bool { + let mut found = false; + attrs.retain(|v| { + let res = v.path.is_ident("core_trait"); + found |= res; + !res + }); + found +} + +/// Generate the decleration of the trait for the runtime. +fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream { + let mut result = Vec::new(); + + for decl in decls { + let mut decl = decl.clone(); + extend_generics_with_block(&mut decl.generics); + let mod_name = generate_runtime_mod_name_for_trait(&decl.ident); + remove_core_trait_attribute(&mut decl.attrs); + + result.push(quote!( + #[doc(hidden)] + pub mod #mod_name { + use super::*; + + #decl + } + )); + } + + quote!( #( #result )* ) +} + +/// Modify the given runtime api declaration to be usable on the client side. +struct ToClientSideDecl<'a> { + block_id: &'a TokenStream, + crate_: &'a TokenStream, +} + +impl<'a> Fold for ToClientSideDecl<'a> { + fn fold_fn_decl(&mut self, input: FnDecl) -> FnDecl { + let input = fold_fn_decl_for_client_side( + input, + &self.block_id, + &self.crate_ + ); + + fold::fold_fn_decl(self, input) + } + + fn fold_item_trait(&mut self, mut input: ItemTrait) -> ItemTrait { + extend_generics_with_block(&mut input.generics); + + // Check if this is the `Core` runtime api trait. + let is_core_trait = remove_core_trait_attribute(&mut input.attrs); + + if is_core_trait { + // Add all the supertraits we want to have for `Core`. + let crate_ = &self.crate_; + input.supertraits = parse_quote!( + 'static + + Send + + Sync + + #crate_::runtime_api::ConstructRuntimeApi + + #crate_::runtime_api::ApiExt + ); + } else { + // Add the `Core` runtime api as super trait. + let crate_ = &self.crate_; + input.supertraits.push(parse_quote!( #crate_::runtime_api::Core )); + } + + // The client side trait is only required when compiling with the feature `std` or `test`. + input.attrs.push(parse_quote!( #[cfg(any(feature = "std", test))] )); + + fold::fold_item_trait(self, input) + } +} + +/// Generate the decleration of the trait for the client side. +fn generate_client_side_decls(decls: &[ItemTrait]) -> TokenStream { + let mut result = Vec::new(); + + for decl in decls { + let mut decl = decl.clone(); + + let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); + let block_id = quote!( #crate_::runtime_api::BlockId ); + let mut to_client_side = ToClientSideDecl { crate_: &crate_, block_id: &block_id }; + + result.push(to_client_side.fold_item_trait(decl)); + } + + quote!( #( #result )* ) +} + +/// Checks that a trait declaration is in the format we expect. +struct CheckTraitDecl { + errors: Vec, +} + +impl<'ast> Visit<'ast> for CheckTraitDecl { + fn visit_fn_arg(&mut self, input: &'ast FnArg) { + match input { + FnArg::Captured(ref arg) => { + match arg.pat { + Pat::Ident(ref pat) if pat.ident == "at" => { + self.errors.push( + Error::new( + pat.span(), + "`decl_runtime_apis!` adds automatically a parameter \ + `at: &BlockId`. Please rename/remove your parameter." + ) + ) + }, + _ => {} + } + + match arg.ty { + Type::Reference(ref reference) => { + self.errors.push( + Error::new( + reference.span(), + "Do not use type references as arguments. The client side \ + declaration will take all arguments as reference automatically." + ) + ) + }, + _ => {}, + } + }, + FnArg::SelfRef(_) | FnArg::SelfValue(_) => { + self.errors.push(Error::new(input.span(), "Self values are not supported.")) + } + _ => { + self.errors.push( + Error::new( + input.span(), + "Only function arguments in the form `pat: type` are supported." + ) + ) + } + } + + visit::visit_fn_arg(self, input); + } + + fn visit_generic_param(&mut self, input: &'ast GenericParam) { + match input { + GenericParam::Type(ty) if &ty.ident == "Block" => { + self.errors.push( + Error::new( + input.span(), + "`Block: BlockT` generic parameter will be added automatically by the \ + `decl_runtime_apis!` macro!" + ) + ) + }, + _ => {} + } + + visit::visit_generic_param(self, input); + } + + fn visit_trait_bound(&mut self, input: &'ast TraitBound) { + if let Some(last_ident) = input.path.segments.last().map(|v| &v.value().ident) { + if last_ident == "BlockT" || last_ident == "Block" { + self.errors.push( + Error::new( + input.span(), + "`Block: BlockT` generic parameter will be added automatically by the \ + `decl_runtime_apis!` macro! If you try to use a different trait than the \ + substrate `Block` trait, please rename it locally." + ) + ) + } + } + + visit::visit_trait_bound(self, input) + } +} + +/// Check that the trait declarations are in the format we expect. +fn check_trait_decls(decls: &[ItemTrait]) -> Option { + let mut checker = CheckTraitDecl { errors: Vec::new() }; + decls.iter().for_each(|decl| visit::visit_item_trait(&mut checker, &decl)); + + if checker.errors.is_empty() { + None + } else { + let errors = checker.errors.into_iter().map(|e| e.to_compile_error()); + Some(quote!( #( #errors )* )) + } +} + +/// The implementation of the `decl_runtime_apis!` macro. +pub fn decl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + // Parse all trait declarations + let RuntimeApiDecls { decls: api_decls } = parse_macro_input!(input as RuntimeApiDecls); + + if let Some(errors) = check_trait_decls(&api_decls) { + return errors.into(); + } + + let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID); + let runtime_decls = generate_runtime_decls(&api_decls); + let client_side_decls = generate_client_side_decls(&api_decls); + + quote!( + #hidden_includes + + #runtime_decls + + #client_side_decls + ).into() +} diff --git a/core/sr-api-macros/src/impl_runtime_apis.rs b/core/sr-api-macros/src/impl_runtime_apis.rs new file mode 100644 index 0000000000000..6817366def6ea --- /dev/null +++ b/core/sr-api-macros/src/impl_runtime_apis.rs @@ -0,0 +1,528 @@ +// 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 . + +use utils::{ + unwrap_or_error, generate_crate_access, generate_hidden_includes, + generate_runtime_mod_name_for_trait, fold_fn_decl_for_client_side +}; + +use proc_macro; +use proc_macro2::{Span, TokenStream}; + +use quote::quote; + +use syn::{ + spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, MethodSig, FnArg, Path, + ImplItem, parse::{Parse, ParseStream, Result, Error}, PathArguments, GenericArgument, TypePath, + fold::{self, Fold}, FnDecl, parse_quote, Pat +}; + +use std::iter; + +/// Unique identifier used to make the hidden includes unique for this macro. +const HIDDEN_INCLUDES_ID: &str = "IMPL_RUNTIME_APIS"; + +/// The structure used for parsing the runtime api implementations. +struct RuntimeApiImpls { + impls: Vec, +} + +impl Parse for RuntimeApiImpls { + fn parse(input: ParseStream) -> Result { + let mut impls = Vec::new(); + + while !input.is_empty() { + impls.push(ItemImpl::parse(input)?); + } + + Ok(Self { impls }) + } +} + +/// Generates the call to the implementation of the requested function. +/// The generated code includes decoding of the input arguments and encoding of the output. +fn generate_impl_call( + signature: &MethodSig, + runtime: &Type, + input: &Ident, + impl_trait: &Path +) -> Result { + let mut pnames = Vec::new(); + let mut ptypes = Vec::new(); + let mut generated_pattern_counter = 0; + for input in signature.decl.inputs.iter() { + match input { + FnArg::Captured(arg) => { + match &arg.ty { + Type::Reference(_) => { + return Err( + Error::new( + arg.ty.span(), + "No type references are allowed in the api traits!" + ) + ) + }, + _ => {}, + } + + pnames.push( + generate_unique_pattern(arg.pat.clone(), &mut generated_pattern_counter) + ); + ptypes.push(&arg.ty); + }, + _ => { + return Err( + Error::new( + input.span(), + "Only function arguments with the following \ + pattern are accepted: `name: type`!" + ) + ) + } + } + } + + let c = generate_crate_access(HIDDEN_INCLUDES_ID); + let c_iter = iter::repeat(&c); + let fn_name = &signature.ident; + let fn_name_str = iter::repeat(fn_name.to_string()); + let input = iter::repeat(input); + let pnames2 = pnames.clone(); + + Ok( + quote!( + #( + let #pnames : #ptypes = match #c_iter::runtime_api::Decode::decode(&mut #input) { + Some(input) => input, + None => panic!("Bad input data provided to {}", #fn_name_str), + }; + )* + + let output = <#runtime as #impl_trait>::#fn_name(#( #pnames2 ),*); + #c::runtime_api::Encode::encode(&output) + ).into() + ) +} + +/// Extract the trait that is implemented in the given `ItemImpl`. +fn extract_impl_trait<'a>(impl_: &'a ItemImpl) -> Result<&'a Path> { + impl_.trait_.as_ref().map(|v| &v.1).ok_or_else( + || Error::new(impl_.span(), "Only implementation of traits are supported!") + ).and_then(|p| { + if p.segments.len() > 1 { + Ok(p) + } else { + Err( + Error::new( + p.span(), + "The implemented trait has to be referenced with a path, \ + e.g. `impl client::Core for Runtime`." + ) + ) + } + }) +} + +/// Extracts the runtime block identifier. +fn extract_runtime_block_ident(trait_: &Path) -> Result<&TypePath> { + let span = trait_.span(); + let segment = trait_ + .segments + .last() + .ok_or_else( + || Error::new(span, "Empty path not supported") + )?; + let generics = segment.value(); + + match &generics.arguments { + PathArguments::AngleBracketed(ref args) => { + args.args.first().and_then(|v| match v.value() { + GenericArgument::Type(Type::Path(block)) => Some(block), + _ => None + }).ok_or_else(|| Error::new(args.span(), "Missing `Block` generic parameter.")) + }, + PathArguments::None => { + let span = trait_.segments.last().as_ref().unwrap().value().span(); + Err(Error::new(span, "Missing `Block` generic parameter.")) + }, + PathArguments::Parenthesized(_) => { + Err(Error::new(generics.arguments.span(), "Unexpected parentheses in path!")) + } + } +} + +/// Generate all the implementation calls for the given functions. +fn generate_impl_calls(impls: &[ItemImpl], input: &Ident) -> Result> { + let mut impl_calls = Vec::new(); + + for impl_ in impls { + let impl_trait = extend_with_runtime_decl_path(extract_impl_trait(impl_)?.clone()); + + for item in &impl_.items { + match item { + ImplItem::Method(method) => { + let impl_call = generate_impl_call( + &method.sig, + &impl_.self_ty, + input, + &impl_trait + )?; + + impl_calls.push((method.sig.ident.clone(), impl_call)); + }, + _ => {}, + } + } + } + + Ok(impl_calls) +} + +/// Generate the dispatch function that is used in native to call into the runtime. +fn generate_dispatch_function(impls: &[ItemImpl]) -> Result { + let data = Ident::new("data", Span::call_site()); + let impl_calls = generate_impl_calls(impls, &data)?.into_iter().map(|(fn_name, impl_)| { + let fn_name = fn_name.to_string(); + quote!( #fn_name => Some({ #impl_ }), ) + }); + + Ok(quote!( + #[cfg(feature = "std")] + pub fn dispatch(method: &str, mut #data: &[u8]) -> Option> { + match method { + #( #impl_calls )* + _ => None, + } + } + ).into()) +} + +/// Generate the interface functions that are used to call into the runtime in wasm. +fn generate_wasm_interface(impls: &[ItemImpl]) -> Result { + let input = Ident::new("input", Span::call_site()); + let c = generate_crate_access(HIDDEN_INCLUDES_ID); + let impl_calls = generate_impl_calls(impls, &input)?.into_iter().map(|(fn_name, impl_)| { + quote!( + #[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 { + #c::runtime_api::slice::from_raw_parts(input_data, input_len) + } + }; + + let output = { #impl_ }; + 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 + } + ) + }); + + Ok(quote!( #( #impl_calls )* )) +} + +fn generate_block_and_block_id_ty( + runtime: &Type, + trait_: &'static str, + assoc_type: &'static str, +) -> (TokenStream, TokenStream) { + let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); + let trait_ = Ident::new(trait_, Span::call_site()); + let assoc_type = Ident::new(assoc_type, Span::call_site()); + + let block = quote!( <#runtime as #crate_::runtime_api::#trait_>::#assoc_type ); + let block_id = quote!( #crate_::runtime_api::BlockId<#block> ); + + (block, block_id) +} + +fn generate_node_block_and_block_id_ty(runtime: &Type) -> (TokenStream, TokenStream) { + generate_block_and_block_id_ty(runtime, "GetNodeBlockType", "NodeBlock") +} + +fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result { + let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); + let runtime = &impls.get(0).ok_or_else(|| + Error::new(Span::call_site(), "No api implementation given!") + )?.self_ty; + let (block, block_id) = generate_node_block_and_block_id_ty(runtime); + + Ok(quote!( + /// Implements all runtime apis for the client side. + #[cfg(any(feature = "std", test))] + pub struct RuntimeApi { + call: ::std::ptr::NonNull<#crate_::runtime_api::CallApiAt<#block>>, + commit_on_success: ::std::cell::RefCell, + initialised_block: ::std::cell::RefCell>, + changes: ::std::cell::RefCell<#crate_::runtime_api::OverlayedChanges>, + } + + // `RuntimeApi` itself is not threadsafe. However, an instance is only available in a + // `ApiRef` object and `ApiRef` also has an associated lifetime. This lifetimes makes it + // impossible to move `RuntimeApi` into another thread. + #[cfg(any(feature = "std", test))] + unsafe impl Send for RuntimeApi {} + #[cfg(any(feature = "std", test))] + unsafe impl Sync for RuntimeApi {} + + #[cfg(any(feature = "std", test))] + impl #crate_::runtime_api::ApiExt for RuntimeApi { + fn map_api_result ::std::result::Result, R, E>( + &self, + map_call: F + ) -> ::std::result::Result { + *self.commit_on_success.borrow_mut() = false; + let res = map_call(self); + *self.commit_on_success.borrow_mut() = true; + + self.commit_on_ok(&res); + + res + } + } + + #[cfg(any(feature = "std", test))] + impl #crate_::runtime_api::ConstructRuntimeApi<#block> for RuntimeApi { + fn construct_runtime_api<'a, T: #crate_::runtime_api::CallApiAt<#block>>( + call: &'a T + ) -> #crate_::runtime_api::ApiRef<'a, Self> { + RuntimeApi { + call: unsafe { + ::std::ptr::NonNull::new_unchecked( + call as &#crate_::runtime_api::CallApiAt<#block> as *const _ as *mut _ + ) + }, + commit_on_success: true.into(), + initialised_block: None.into(), + changes: Default::default(), + }.into() + } + } + + #[cfg(any(feature = "std", test))] + impl RuntimeApi { + fn call_api_at( + &self, + at: &#block_id, + function: &'static str, + args: &A + ) -> #crate_::error::Result { + let res = unsafe { + self.call.as_ref().call_api_at( + at, + function, + args.encode(), + &mut *self.changes.borrow_mut(), + &mut *self.initialised_block.borrow_mut() + ).and_then(|r| + R::decode(&mut &r[..]) + .ok_or_else(|| + #crate_::error::ErrorKind::CallResultDecode(function).into() + ) + ) + }; + + self.commit_on_ok(&res); + res + } + + fn commit_on_ok(&self, res: &::std::result::Result) { + if *self.commit_on_success.borrow() { + if res.is_err() { + self.changes.borrow_mut().discard_prospective(); + } else { + self.changes.borrow_mut().commit_prospective(); + } + } + } + } + )) +} + +/// Extend the given trait path with module that contains the declaration of the trait for the +/// runtime. +fn extend_with_runtime_decl_path(mut trait_: Path) -> Path { + let runtime = { + let trait_name = &trait_ + .segments + .last() + .as_ref() + .expect("Trait path should always contain at least one item; qed") + .value() + .ident; + + generate_runtime_mod_name_for_trait(trait_name) + }; + + let pos = trait_.segments.len() - 1; + trait_.segments.insert(pos, runtime.clone().into()); + trait_ +} + +/// Generates the implementations of the apis for the runtime. +fn generate_api_impl_for_runtime(impls: &[ItemImpl]) -> Result { + let mut impls_prepared = Vec::new(); + + // We put `runtime` before each trait to get the trait that is intended for the runtime and + // we put the `RuntimeBlock` as first argument for the trait generics. + for impl_ in impls.iter() { + let mut impl_ = impl_.clone(); + let trait_ = extract_impl_trait(&impl_)?.clone(); + let trait_ = extend_with_runtime_decl_path(trait_); + + impl_.trait_.as_mut().unwrap().1 = trait_; + impls_prepared.push(impl_); + } + + Ok(quote!( #( #impls_prepared )* )) +} + +/// Generate an unique pattern based on the given counter, if the given pattern is a `_`. +fn generate_unique_pattern(pat: Pat, counter: &mut u32) -> Pat { + match pat { + Pat::Wild(_) => { + let generated_name = Ident::new( + &format!("impl_runtime_api_generated_name_{}", counter), + pat.span() + ); + *counter += 1; + + parse_quote!( #generated_name ) + }, + _ => pat, + } +} + +/// Auxilariy data structure that is used to convert `impl Api for Runtime` to +/// `impl Api for RuntimeApi`. +/// This requires us to replace the runtime `Block` with the node `Block`, +/// `impl Api for Runtime` with `impl Api for RuntimeApi` and replace the method implementations +/// with code that calls into the runtime. +struct ApiRuntimeImplToApiRuntimeApiImpl<'a> { + node_block: &'a TokenStream, + runtime_block: &'a TypePath, + node_block_id: &'a TokenStream, +} + +impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { + fn fold_type_path(&mut self, input: TypePath) -> TypePath { + let new_ty_path = if input == *self.runtime_block { + let node_block = self.node_block; + parse_quote!( #node_block ) + } else { + input + }; + + fold::fold_type_path(self, new_ty_path) + } + + fn fold_fn_decl(&mut self, input: FnDecl) -> FnDecl { + let input = fold_fn_decl_for_client_side( + input, + &self.node_block_id, + &generate_crate_access(HIDDEN_INCLUDES_ID) + ); + + fold::fold_fn_decl(self, input) + } + + fn fold_impl_item_method(&mut self, mut input: syn::ImplItemMethod) -> syn::ImplItemMethod { + { + let mut generated_name_counter = 0; + let arg_names = input.sig.decl.inputs.iter_mut().filter_map(|i| match i { + FnArg::Captured(ref mut arg) => Some(&mut arg.pat), + _ => None, + }).map(|p| { + *p = generate_unique_pattern(p.clone(), &mut generated_name_counter); + p + }); + let name = input.sig.ident.to_string(); + + // Generate the new method implementation that calls into the runime. + input.block = parse_quote!( { self.call_api_at(at, #name, &( #( #arg_names ),* )) } ); + } + + fold::fold_impl_item_method(self, input) + } + + fn fold_item_impl(&mut self, mut input: ItemImpl) -> ItemImpl { + // Implement the trait for the `RuntimeApi` + input.self_ty = Box::new(parse_quote!( RuntimeApi )); + + // The implementation for the `RuntimeApi` is only required when compiling with the feature + // `std` or `test`. + input.attrs.push(parse_quote!( #[cfg(any(feature = "std", test))] )); + + fold::fold_item_impl(self, input) + } +} + +fn generate_api_impl_for_runtime_api(impls: &[ItemImpl]) -> Result { + let mut result = Vec::with_capacity(impls.len()); + + for impl_ in impls { + let runtime_block = extract_runtime_block_ident(extract_impl_trait(&impl_)?)?; + let (node_block, node_block_id) = generate_node_block_and_block_id_ty(&impl_.self_ty); + + let mut visitor = ApiRuntimeImplToApiRuntimeApiImpl { + runtime_block, + node_block: &node_block, + node_block_id: &node_block_id, + }; + + result.push(visitor.fold_item_impl(impl_.clone())); + } + + Ok(quote!( #( #result )* )) +} + +/// The implementation of the `impl_runtime_apis!` macro. +pub fn impl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + // Parse all impl blocks + let RuntimeApiImpls { impls: api_impls } = parse_macro_input!(input as RuntimeApiImpls); + let dispatch_impl = unwrap_or_error(generate_dispatch_function(&api_impls)); + let wasm_interface = unwrap_or_error(generate_wasm_interface(&api_impls)); + let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID); + let base_runtime_api = unwrap_or_error(generate_runtime_api_base_structures(&api_impls)); + let api_impls_for_runtime = unwrap_or_error(generate_api_impl_for_runtime(&api_impls)); + let api_impls_for_runtime_api = unwrap_or_error(generate_api_impl_for_runtime_api(&api_impls)); + + quote!( + #hidden_includes + + #base_runtime_api + + #api_impls_for_runtime + + #api_impls_for_runtime_api + + pub mod api { + use super::*; + + #dispatch_impl + + #wasm_interface + } + ).into() +} diff --git a/core/sr-api-macros/src/lib.rs b/core/sr-api-macros/src/lib.rs new file mode 100644 index 0000000000000..371cbbef6f273 --- /dev/null +++ b/core/sr-api-macros/src/lib.rs @@ -0,0 +1,164 @@ +// 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 . + +//! Macros for declaring and implementing runtime apis. + +#![recursion_limit = "128"] +extern crate proc_macro; +extern crate proc_macro2; +extern crate quote; +extern crate syn; + +use proc_macro::TokenStream; + +mod impl_runtime_apis; +mod decl_runtime_apis; +mod utils; +mod compile_fail_tests; + +/// Tags given trait implementations as runtime apis. +/// +/// All traits given to this macro, need to be declared with the `decl_runtime_apis!` macro. +/// The implementation of the trait should follow the declaration given to the `decl_runtime_apis!` +/// macro, besides the `Block` type that is required as first generic parameter for each runtime +/// api trait. When implementing a runtime api trait, it is required that the trait is referenced +/// by a path, e.g. `impl my_trait::MyTrait for Runtime`. The macro will use this path to access +/// the declaration of the trait for the runtime side. +/// +/// The macro also generates the implementation of the apis for the client side by generating the +/// `RuntimeApi` type. The `RuntimeApi` is hidden behind a `feature` called `std`. +/// +/// # Example +/// +/// ```rust +/// #[macro_use] +/// extern crate substrate_client; +/// # extern crate sr_primitives as runtime_primitives; +/// # extern crate substrate_primitives as primitives; +/// # #[macro_use] +/// # extern crate parity_codec_derive; +/// # extern crate serde; +/// # extern crate core; +/// # +/// # use primitives::hash::H256; +/// # use runtime_primitives::traits::{BlakeTwo256, GetNodeBlockType, Extrinsic as ExtrinsicT}; +/// # +/// # // All the stuff we need to declare our `Block` +/// # pub type BlockNumber = u64; +/// # pub type DigestItem = runtime_primitives::generic::DigestItem; +/// # pub type Digest = runtime_primitives::generic::Digest; +/// # #[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] +/// # pub struct Extrinsic {} +/// # +/// # impl serde::Serialize for Extrinsic { +/// # fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { +/// # unimplemented!() +/// # } +/// # } +/// # impl ExtrinsicT for Extrinsic { +/// # fn is_signed(&self) -> Option { +/// # unimplemented!() +/// # } +/// # } +/// # pub type Header = runtime_primitives::generic::Header; +/// # pub type Block = runtime_primitives::generic::Block; +/// # +/// # /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` +/// # /// trait are done by the `construct_runtime!` macro in a real runtime. +/// # struct Runtime {} +/// # impl GetNodeBlockType for Runtime { +/// # type NodeBlock = Block; +/// # } +/// # +/// # decl_runtime_apis! { +/// # /// Declare the api trait. +/// # pub trait Balance { +/// # /// Get the balance. +/// # fn get_balance() -> u64; +/// # /// Set the balance. +/// # fn set_balance(val: u64); +/// # } +/// # pub trait BlockBuilder { +/// # fn build_block() -> Block; +/// # } +/// # } +/// +/// /// All runtime api implementations need to be done in one call of the macro! +/// impl_runtime_apis! { +/// impl self::Balance for Runtime { +/// fn get_balance() -> u64 { +/// 1 +/// } +/// fn set_balance(_bal: u64) { +/// // Store the balance +/// } +/// } +/// +/// impl self::BlockBuilder for Runtime { +/// fn build_block() -> Block { +/// unimplemented!("Please implement me!") +/// } +/// } +/// } +/// +/// # fn main() {} +/// ``` +#[proc_macro] +pub fn impl_runtime_apis(input: TokenStream) -> TokenStream { + impl_runtime_apis::impl_runtime_apis_impl(input) +} + +/// Declares given traits as runtime apis. +/// +/// The macro will create two declarations, one for using on the client side and one for using +/// on the runtime side. The declaration for the runtime side is hidden in its own module. +/// The client side declaration gets two extra parameters per function, +/// `&self` and `at: &BlockId`. The runtime side declaration will match the given trait +/// declaration. Besides one exception, the macro adds an extra generic parameter `Block: BlockT` +/// to the client side and the runtime side. This generic parameter is usable by the user. +/// +/// For implementing these macros you should use the `impl_runtime_apis!` macro. +/// +/// # Example +/// +/// ```rust +/// #[macro_use] +/// extern crate substrate_client; +/// +/// decl_runtime_apis! { +/// /// Declare the api trait. +/// pub trait Balance { +/// /// Get the balance. +/// fn get_balance() -> u64; +/// /// Set the balance. +/// fn set_balance(val: u64); +/// } +/// +/// /// You can declare multiple api traits in one macro call. +/// /// In one module you can call the macro at maximum one time. +/// pub trait BlockBuilder { +/// /// The macro adds an explicit `Block: BlockT` generic parameter for you. +/// /// You can use this generic parameter as you would defined it manually. +/// fn build_block() -> Block; +/// } +/// } +/// +/// # fn main() {} +/// ``` +#[proc_macro] +pub fn decl_runtime_apis(input: TokenStream) -> TokenStream { + decl_runtime_apis::decl_runtime_apis_impl(input) +} diff --git a/core/sr-api-macros/src/utils.rs b/core/sr-api-macros/src/utils.rs new file mode 100644 index 0000000000000..4c80adf16b4d2 --- /dev/null +++ b/core/sr-api-macros/src/utils.rs @@ -0,0 +1,97 @@ +// 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 . + +use proc_macro2::{TokenStream, Span}; +use syn::{Result, Ident, FnDecl, parse_quote, Type, FnArg}; +use quote::quote; +use std::env; + +/// Unwrap the given result, if it is an error, `compile_error!` will be generated. +pub fn unwrap_or_error(res: Result) -> TokenStream { + res.unwrap_or_else(|e| e.to_compile_error()) +} + +fn generate_hidden_includes_mod_name(unique_id: &'static str) -> Ident { + Ident::new(&format!("sr_api_hidden_includes_{}", unique_id), Span::call_site()) +} + +/// Generates the hidden includes that are required to make the macro independent from its scope. +pub fn generate_hidden_includes(unique_id: &'static str) -> TokenStream { + if env::var("CARGO_PKG_NAME").unwrap() == "substrate-client" { + TokenStream::new() + } else { + let mod_name = generate_hidden_includes_mod_name(unique_id); + quote!( + #[doc(hidden)] + mod #mod_name { + pub extern crate substrate_client as sr_api_client; + } + ) + }.into() +} + +/// Generates the access to the `subtrate_client` crate. +pub fn generate_crate_access(unique_id: &'static str) -> TokenStream { + if env::var("CARGO_PKG_NAME").unwrap() == "substrate-client" { + quote!( crate ) + } else { + let mod_name = generate_hidden_includes_mod_name(unique_id); + quote!( self::#mod_name::sr_api_client ) + }.into() +} + +/// Generates the name of the module that contains the trait declaration for the runtime. +pub fn generate_runtime_mod_name_for_trait(trait_: &Ident) -> Ident { + Ident::new(&format!("runtime_decl_for_{}", trait_.to_string()), Span::call_site()) +} + +/// Fold the given `FnDecl` to make it usable on the client side. +pub fn fold_fn_decl_for_client_side( + mut input: FnDecl, + block_id: &TokenStream, + crate_: &TokenStream +) -> FnDecl { + // Add `&` to all parameter types. + input.inputs + .iter_mut() + .filter_map(|i| match i { + FnArg::Captured(ref mut arg) => Some(&mut arg.ty), + _ => None, + }) + .filter_map(|i| match i { + Type::Reference(_) => None, + r => Some(r), + }) + .for_each(|i| *i = parse_quote!( &#i )); + + // Add `&self, at:& BlockId` as parameters to each function at the beginning. + input.inputs.insert(0, parse_quote!( at: &#block_id )); + input.inputs.insert(0, parse_quote!( &self )); + + // Wrap the output in a `Result` + input.output = { + let generate_result = |ty: &Type| { + parse_quote!( -> ::std::result::Result<#ty, #crate_::error::Error> ) + }; + + match &input.output { + syn::ReturnType::Default => generate_result(&parse_quote!( () )), + syn::ReturnType::Type(_, ref ty) => generate_result(&ty), + } + }; + + input +} diff --git a/core/sr-api-macros/tests/decl_and_impl.rs b/core/sr-api-macros/tests/decl_and_impl.rs new file mode 100644 index 0000000000000..97dc2f9189029 --- /dev/null +++ b/core/sr-api-macros/tests/decl_and_impl.rs @@ -0,0 +1,93 @@ +#[macro_use] +extern crate substrate_client; +extern crate sr_primitives as runtime_primitives; +extern crate substrate_primitives as primitives; +#[macro_use] +extern crate parity_codec_derive; +extern crate serde; +extern crate core; + +use primitives::hash::H256; +use runtime_primitives::traits::{ + BlakeTwo256, GetNodeBlockType, Extrinsic as ExtrinsicT, Block as BlockT +}; +use runtime_primitives::generic::BlockId; +use substrate_client::runtime_api; +use primitives::AuthorityId; +use substrate_client::error::Result; + +// All the stuff we need to declare our `Block` +pub type BlockNumber = u64; +pub type DigestItem = runtime_primitives::generic::DigestItem; +pub type Digest = runtime_primitives::generic::Digest; +#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] +pub struct Extrinsic {} + +impl serde::Serialize for Extrinsic { + fn serialize( + &self, + _: S + ) -> ::std::result::Result where S: ::serde::Serializer { + unimplemented!() + } +} +impl ExtrinsicT for Extrinsic { + fn is_signed(&self) -> Option { + unimplemented!() + } +} +pub type Header = runtime_primitives::generic::Header; +pub type Block = runtime_primitives::generic::Block; + +/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` +/// trait are done by the `construct_runtime!` macro in a real runtime. +pub struct Runtime {} +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} + +decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + fn something_with_block(block: Block) -> Block; + fn function_with_two_args(data: u64, block: Block); + } +} + +impl_runtime_apis! { + impl self::Api for Runtime { + fn test(_: u64) { + unimplemented!() + } + + fn something_with_block(_: Block) -> Block { + unimplemented!() + } + + fn function_with_two_args(_: u64, _: Block) { + unimplemented!() + } + } + + impl runtime_api::Core for Runtime { + fn version() -> runtime_api::RuntimeVersion { + unimplemented!() + } + fn authorities() -> Vec { + unimplemented!() + } + fn execute_block(_: Block) { + unimplemented!() + } + fn initialise_block(_: ::Header) { + unimplemented!() + } + } +} + +#[test] +fn test_client_side_function_signature() { + let _test: fn(&RuntimeApi, &BlockId, &u64) -> Result<()> = RuntimeApi::test; + let _something_with_block: fn(&RuntimeApi, &BlockId, &Block) -> Result = + RuntimeApi::something_with_block; +} diff --git a/core/sr-primitives/src/generic/era.rs b/core/sr-primitives/src/generic/era.rs index 71ee8fa145431..bccee778be203 100644 --- a/core/sr-primitives/src/generic/era.rs +++ b/core/sr-primitives/src/generic/era.rs @@ -61,7 +61,7 @@ impl Era { Era::Mortal(period, quantized_phase) } - /// Create an "immortal" transaction. + /// Create an "immortal" transaction. pub fn immortal() -> Self { Era::Immortal } @@ -75,7 +75,7 @@ impl Era { } /// Get the block number of the start of the era whose properties this object - /// describes that `current` belongs to. + /// describes that `current` belongs to. pub fn birth(self, current: u64) -> u64 { match self { Era::Immortal => 0, @@ -189,10 +189,10 @@ mod tests { assert_ne!(e.birth(10), 6); assert_ne!(e.birth(5), 6); } - + #[test] fn current_less_than_phase() { // should not panic Era::mortal(4, 3).birth(1); } -} \ No newline at end of file +} diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 9ad97cf28c28c..86c93ab3d772f 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -462,6 +462,35 @@ macro_rules! impl_outer_log { }; } +//TODO: https://github.com/paritytech/substrate/issues/1022 +/// Inherent data to include in a block. +#[derive(Encode, Decode)] +pub struct InherentData { + /// Current timestamp. + pub timestamp: u64, + /// Indices of offline validators. + pub consensus: Vec, +} + +impl InherentData { + /// Create a new `InherentData` instance. + pub fn new(timestamp: u64, consensus: Vec) -> Self { + Self { + timestamp, + consensus, + } + } +} + +//TODO: https://github.com/paritytech/substrate/issues/1022 +/// Error type used while checking inherents. +#[derive(Encode)] +#[cfg_attr(feature = "std", derive(Decode))] +pub enum CheckInherentError { + TimestampInFuture(u64), + Other(RuntimeString), +} + #[cfg(test)] mod tests { use substrate_primitives::hash::H256; diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 85ce07ff4b9ab..0d33d7859f870 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -582,8 +582,6 @@ pub trait DigestItem: Codec + Member + MaybeSerializeDebugButNotDeserialize { pub trait ProvideInherent { /// The inherent that is provided. type Inherent: Encode + MaybeDecode; - /// The error used by this trait. - type Error: Encode + MaybeDecode; /// The call for setting the inherent. type Call: Encode + MaybeDecode; @@ -597,7 +595,7 @@ pub trait ProvideInherent { /// Check that the given inherent is valid. fn check_inherent Option<&Self::Call>>( block: &Block, data: Self::Inherent, extract_function: &F - ) -> Result<(), Self::Error>; + ) -> Result<(), super::CheckInherentError>; } /// Auxiliary wrapper that holds an api instance and binds it to the given lifetime. @@ -629,3 +627,15 @@ pub trait ProvideRuntimeApi { /// storage, even on a `commit`. fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api>; } + +/// A marker trait for something that knows the type of the runtime block. +pub trait GetRuntimeBlockType { + /// The `RuntimeBlock` type. + type RuntimeBlock: self::Block; +} + +/// A marker trait for something that knows the type of the node block. +pub trait GetNodeBlockType { + /// The `NodeBlock` type. + type NodeBlock: self::Block; +} diff --git a/core/test-client/src/lib.rs b/core/test-client/src/lib.rs index ce504bd0851ae..66b057350a217 100644 --- a/core/test-client/src/lib.rs +++ b/core/test-client/src/lib.rs @@ -66,12 +66,12 @@ pub type Executor = client::LocalCallExecutor< >; /// Creates new client instance used for tests. -pub fn new() -> client::Client { +pub fn new() -> client::Client { new_with_backend(Arc::new(Backend::new()), false) } /// Creates new test client instance that suports changes trie creation. -pub fn new_with_changes_trie() -> client::Client { +pub fn new_with_changes_trie() -> client::Client { new_with_backend(Arc::new(Backend::new()), true) } @@ -80,7 +80,7 @@ pub fn new_with_changes_trie() -> client::Client( backend: Arc, support_changes_trie: bool -) -> client::Client>, runtime::Block, runtime::ClientWithApi> +) -> client::Client>, runtime::Block, runtime::RuntimeApi> where B: backend::LocalBackend, { diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index 65d122b498c4a..50a0134e90bd7 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -50,19 +50,17 @@ pub mod system; use rstd::prelude::*; use codec::{Encode, Decode}; -use client::{runtime_api::runtime::*, block_builder::api::runtime::*}; -#[cfg(feature = "std")] -use client::runtime_api::ApiExt; -use runtime_primitives::traits::{BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT}; -#[cfg(feature = "std")] -use runtime_primitives::traits::ApiRef; -use runtime_primitives::{ApplyResult, Ed25519Signature, transaction_validity::TransactionValidity}; -#[cfg(feature = "std")] -use runtime_primitives::generic::BlockId; +use client::{runtime_api as client_api, block_builder::api as block_builder_api}; +use runtime_primitives::{ + ApplyResult, Ed25519Signature, transaction_validity::TransactionValidity, + traits::{ + BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, + GetNodeBlockType, GetRuntimeBlockType + }, InherentData, CheckInherentError +}; use runtime_version::RuntimeVersion; pub use primitives::hash::H256; use primitives::AuthorityId; -#[cfg(feature = "std")] use primitives::OpaqueMetadata; #[cfg(any(feature = "std", test))] use runtime_version::NativeVersion; @@ -172,170 +170,27 @@ pub fn changes_trie_config() -> primitives::ChangesTrieConfiguration { } pub mod test_api { + use super::AccountId; + decl_runtime_apis! { pub trait TestAPI { - fn balance_of(id: AccountId) -> u64; - } - } -} - -use test_api::runtime::TestAPI; - -#[cfg(feature = "std")] -pub struct ClientWithApi { - call: ::std::ptr::NonNull>, - commit_on_success: ::std::cell::RefCell, - initialised_block: ::std::cell::RefCell>>, - changes: ::std::cell::RefCell, -} - -#[cfg(feature = "std")] -unsafe impl Send for ClientWithApi {} -#[cfg(feature = "std")] -unsafe impl Sync for ClientWithApi {} - -#[cfg(feature = "std")] -impl ApiExt for ClientWithApi { - fn map_api_result Result, R, E>(&self, map_call: F) -> Result { - *self.commit_on_success.borrow_mut() = false; - let res = map_call(self); - *self.commit_on_success.borrow_mut() = true; - - self.commit_on_ok(&res); - - res - } -} - -#[cfg(feature = "std")] -impl client::runtime_api::ConstructRuntimeApi for ClientWithApi { - fn construct_runtime_api<'a, T: client::runtime_api::CallApiAt>(call: &'a T) -> ApiRef<'a, Self> { - ClientWithApi { - call: unsafe { - ::std::ptr::NonNull::new_unchecked( - ::std::mem::transmute( - call as &client::runtime_api::CallApiAt - ) - ) - }, - commit_on_success: true.into(), - initialised_block: None.into(), - changes: Default::default(), - }.into() - } -} - -#[cfg(feature = "std")] -impl ClientWithApi { - fn call_api_at( - &self, - at: &BlockId, - function: &'static str, - args: &A - ) -> client::error::Result { - let res = unsafe { - self.call.as_ref().call_api_at( - at, - function, - args.encode(), - &mut *self.changes.borrow_mut(), - &mut *self.initialised_block.borrow_mut() - ).and_then(|r| - R::decode(&mut &r[..]) - .ok_or_else(|| - client::error::ErrorKind::CallResultDecode(function).into() - ) - ) - }; - - self.commit_on_ok(&res); - res - } - - fn commit_on_ok(&self, res: &Result) { - if *self.commit_on_success.borrow() { - if res.is_err() { - self.changes.borrow_mut().discard_prospective(); - } else { - self.changes.borrow_mut().commit_prospective(); - } + fn balance_of(id: AccountId) -> u64; } } } -#[cfg(feature = "std")] -impl client::runtime_api::Core for ClientWithApi { - fn version(&self, at: &BlockId) -> Result { - self.call_api_at(at, "version", &()) - } - - fn authorities(&self, at: &BlockId) -> Result, client::error::Error> { - self.call_api_at(at, "authorities", &()) - } - - fn execute_block(&self, at: &BlockId, block: &Block) -> Result<(), client::error::Error> { - self.call_api_at(at, "execute_block", block) - } - - fn initialise_block(&self, at: &BlockId, header: &::Header) -> Result<(), client::error::Error> { - self.call_api_at(at, "initialise_block", header) - } -} - -#[cfg(feature = "std")] -impl client::block_builder::api::BlockBuilder for ClientWithApi { - 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, client::error::Error> { - self.call_api_at(at, "finalise_block", &()) - } - - fn inherent_extrinsics( - &self, at: &BlockId, inherent: &Inherent - ) -> Result, client::error::Error> { - self.call_api_at(at, "inherent_extrinsics", inherent) - } - - fn check_inherents(&self, at: &BlockId, block: &Block, inherent: &Inherent) -> Result, client::error::Error> { - self.call_api_at(at, "check_inherents", &(block, inherent)) - } - - fn random_seed(&self, at: &BlockId) -> Result<::Hash, client::error::Error> { - self.call_api_at(at, "random_seed", &()) - } -} - -#[cfg(feature = "std")] -impl client::runtime_api::TaggedTransactionQueue for ClientWithApi { - fn validate_transaction( - &self, - at: &BlockId, - utx: &::Extrinsic - ) -> Result { - self.call_api_at(at, "validate_transaction", utx) - } -} +pub struct Runtime; -#[cfg(feature = "std")] -impl client::runtime_api::Metadata for ClientWithApi { - fn metadata(&self, at: &BlockId) -> Result { - self.call_api_at(at, "metadata", &()) - } +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; } -#[cfg(feature = "std")] -impl test_api::TestAPI for ClientWithApi { - fn balance_of(&self, at: &BlockId, id: &AccountId) -> Result { - self.call_api_at(at, "balance_of", id) - } +impl GetRuntimeBlockType for Runtime { + type RuntimeBlock = Block; } -struct Runtime; - impl_runtime_apis! { - impl Core for Runtime { + impl client_api::Core for Runtime { fn version() -> RuntimeVersion { version() } @@ -353,13 +208,19 @@ impl_runtime_apis! { } } - impl TaggedTransactionQueue for Runtime { + impl client_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + unimplemented!() + } + } + + impl client_api::TaggedTransactionQueue for Runtime { fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { system::validate_transaction(utx) } } - impl BlockBuilder for Runtime { + impl block_builder_api::BlockBuilder for Runtime { fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { system::execute_transaction(extrinsic) } @@ -368,11 +229,11 @@ impl_runtime_apis! { system::finalise_block() } - fn inherent_extrinsics(_data: u32) -> Vec { + fn inherent_extrinsics(_data: InherentData) -> Vec<::Extrinsic> { unimplemented!() } - fn check_inherents(_block: Block, _data: u32) -> Result<(), u32> { + fn check_inherents(_block: Block, _data: InherentData) -> Result<(), CheckInherentError> { unimplemented!() } @@ -381,7 +242,7 @@ impl_runtime_apis! { } } - impl TestAPI for Runtime { + impl self::test_api::TestAPI for Runtime { fn balance_of(id: AccountId) -> u64 { system::balance_of(id) } diff --git a/core/test-runtime/wasm/Cargo.lock b/core/test-runtime/wasm/Cargo.lock index c268f0c4007e7..ddba821e1f895 100644 --- a/core/test-runtime/wasm/Cargo.lock +++ b/core/test-runtime/wasm/Cargo.lock @@ -768,7 +768,7 @@ 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)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -835,6 +835,15 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sr-api-macros" +version = "0.1.0" +dependencies = [ + "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sr-io" version = "0.1.0" @@ -936,6 +945,7 @@ dependencies = [ "parity-codec 2.1.5 (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.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-api-macros 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", @@ -1095,7 +1105,7 @@ dependencies = [ [[package]] name = "syn" -version = "0.15.6" +version = "0.15.22" 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)", @@ -1550,7 +1560,7 @@ dependencies = [ "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.6 (registry+https://github.com/rust-lang/crates.io-index)" = "854b08a640fc8f54728fb95321e3ec485b365a97fe47609797c671addd1dde69" +"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" diff --git a/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 1e1603db25f1a..46d88c5cbc813 100644 Binary files a/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index 6035677f85057..59b4c3f5bfb6c 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use transaction_pool::{self, txpool::{Pool as TransactionPool}}; -use node_runtime::{GenesisConfig, ClientWithApi}; +use node_runtime::{GenesisConfig, RuntimeApi}; use node_primitives::Block; use substrate_service::{ FactoryFullConfiguration, LightComponents, FullComponents, FullBackend, @@ -68,12 +68,12 @@ impl Default for NodeConfig where F: substrate_service::ServiceFactory { construct_service_factory! { struct Factory { Block = Block, - RuntimeApi = ClientWithApi, + RuntimeApi = RuntimeApi, NetworkProtocol = NodeProtocol { |config| Ok(NodeProtocol::new()) }, RuntimeDispatch = node_executor::Executor, - FullTransactionPoolApi = transaction_pool::ChainApi, FullExecutor, Block, ClientWithApi>, Block> + FullTransactionPoolApi = transaction_pool::ChainApi, FullExecutor, Block, RuntimeApi>, Block> { |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) }, - LightTransactionPoolApi = transaction_pool::ChainApi, LightExecutor, Block, ClientWithApi>, Block> + LightTransactionPoolApi = transaction_pool::ChainApi, LightExecutor, Block, RuntimeApi>, Block> { |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) }, Genesis = GenesisConfig, Configuration = NodeConfig, @@ -125,7 +125,7 @@ construct_service_factory! { { |config, executor| >::new(config, executor) }, FullImportQueue = AuraImportQueue, NothingExtra> { |config: &mut FactoryFullConfiguration , client: Arc>| { - let (block_import, link_half) = grandpa::block_import::<_, _, _, ClientWithApi, FullClient>(client.clone(), client)?; + let (block_import, link_half) = grandpa::block_import::<_, _, _, RuntimeApi, FullClient>(client.clone(), client)?; let block_import = Arc::new(block_import); config.custom.grandpa_import_setup = Some((block_import.clone(), link_half)); diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index f3d1672642c26..c0b344e0525c9 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -58,27 +58,21 @@ extern crate srml_upgrade_key as upgrade_key; extern crate sr_version as version; extern crate node_primitives; -#[cfg(feature = "std")] -use codec::{Encode, Decode}; use rstd::prelude::*; use substrate_primitives::u32_trait::{_2, _4}; use node_primitives::{ AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, SessionKey, Signature }; -use grandpa::fg_primitives::{runtime::GrandpaApi, ScheduledChange, id::*}; -#[cfg(feature = "std")] -use node_primitives::Block as GBlock; -use client::{block_builder::api::runtime::*, runtime_api::{runtime::*, id::*}}; -#[cfg(feature = "std")] -use client::runtime_api::ApiExt; -use runtime_primitives::ApplyResult; +use grandpa::fg_primitives::{self, ScheduledChange, id::*}; +use client::{ + block_builder::api as block_builder_api, runtime_api::{self as client_api, id::*} +}; +use runtime_primitives::{ApplyResult, CheckInherentError}; use runtime_primitives::transaction_validity::TransactionValidity; use runtime_primitives::generic; -use runtime_primitives::traits::{Convert, BlakeTwo256, Block as BlockT, DigestFor, NumberFor}; -#[cfg(feature = "std")] -use runtime_primitives::traits::ApiRef; -#[cfg(feature = "std")] -use substrate_primitives::AuthorityId; +use runtime_primitives::traits::{ + Convert, BlakeTwo256, Block as BlockT, DigestFor, NumberFor, ProvideInherent +}; use version::RuntimeVersion; use council::{motions as council_motions, voting as council_voting}; #[cfg(feature = "std")] @@ -219,7 +213,7 @@ impl grandpa::Trait for Runtime { construct_runtime!( pub enum Runtime with Log(InternalLog: DigestItem) where Block = Block, - UncheckedExtrinsic = UncheckedExtrinsic + NodeBlock = node_primitives::Block { System: system::{default, Log(ChangesTrieRoot)}, Timestamp: timestamp::{Module, Call, Storage, Config, Inherent}, @@ -241,6 +235,7 @@ construct_runtime!( /// The address format for describing accounts. pub use balances::address::Address as RawAddress; + /// The address format for describing accounts. pub type Address = balances::Address; /// Block header type as expected by this runtime. @@ -258,168 +253,8 @@ pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = executive::Executive, Balances, AllModules>; -#[cfg(feature = "std")] -pub struct ClientWithApi { - call: ::std::ptr::NonNull>, - commit_on_success: ::std::cell::RefCell, - initialised_block: ::std::cell::RefCell>, - changes: ::std::cell::RefCell, -} - -#[cfg(feature = "std")] -unsafe impl Send for ClientWithApi {} -#[cfg(feature = "std")] -unsafe impl Sync for ClientWithApi {} - -#[cfg(feature = "std")] -impl ApiExt for ClientWithApi { - fn map_api_result Result, R, E>(&self, map_call: F) -> Result { - *self.commit_on_success.borrow_mut() = false; - let res = map_call(self); - *self.commit_on_success.borrow_mut() = true; - - self.commit_on_ok(&res); - - res - } -} - -#[cfg(feature = "std")] -impl client::runtime_api::ConstructRuntimeApi for ClientWithApi { - fn construct_runtime_api<'a, T: client::runtime_api::CallApiAt>(call: &'a T) -> ApiRef<'a, Self> { - ClientWithApi { - call: unsafe { - ::std::ptr::NonNull::new_unchecked( - ::std::mem::transmute( - call as &client::runtime_api::CallApiAt - ) - ) - }, - commit_on_success: true.into(), - initialised_block: None.into(), - changes: Default::default(), - }.into() - } -} - -#[cfg(feature = "std")] -impl ClientWithApi { - fn call_api_at( - &self, - at: &GBlockId, - function: &'static str, - args: &A - ) -> client::error::Result { - let res = unsafe { - self.call.as_ref().call_api_at( - at, - function, - args.encode(), - &mut *self.changes.borrow_mut(), - &mut *self.initialised_block.borrow_mut() - ).and_then(|r| - R::decode(&mut &r[..]) - .ok_or_else(|| - client::error::ErrorKind::CallResultDecode(function).into() - ) - ) - }; - - self.commit_on_ok(&res); - res - } - - fn commit_on_ok(&self, res: &Result) { - if *self.commit_on_success.borrow() { - if res.is_err() { - self.changes.borrow_mut().discard_prospective(); - } else { - self.changes.borrow_mut().commit_prospective(); - } - } - } -} - -#[cfg(feature = "std")] -type GBlockId = generic::BlockId; - -#[cfg(feature = "std")] -impl client::runtime_api::Core for ClientWithApi { - fn version(&self, at: &GBlockId) -> Result { - self.call_api_at(at, "version", &()) - } - - fn authorities(&self, at: &GBlockId) -> Result, client::error::Error> { - self.call_api_at(at, "authorities", &()) - } - - fn execute_block(&self, at: &GBlockId, block: &GBlock) -> Result<(), client::error::Error> { - self.call_api_at(at, "execute_block", block) - } - - fn initialise_block(&self, at: &GBlockId, header: &::Header) -> Result<(), client::error::Error> { - self.call_api_at(at, "initialise_block", header) - } -} - -#[cfg(feature = "std")] -impl client::block_builder::api::BlockBuilder for ClientWithApi { - fn apply_extrinsic(&self, at: &GBlockId, extrinsic: &::Extrinsic) -> Result { - self.call_api_at(at, "apply_extrinsic", extrinsic) - } - - fn finalise_block(&self, at: &GBlockId) -> Result<::Header, client::error::Error> { - self.call_api_at(at, "finalise_block", &()) - } - - fn inherent_extrinsics( - &self, at: &GBlockId, inherent: &Inherent - ) -> Result, client::error::Error> { - self.call_api_at(at, "inherent_extrinsics", inherent) - } - - fn check_inherents(&self, at: &GBlockId, block: &GBlock, inherent: &Inherent) -> Result, client::error::Error> { - self.call_api_at(at, "check_inherents", &(block, inherent)) - } - - fn random_seed(&self, at: &GBlockId) -> Result<::Hash, client::error::Error> { - self.call_api_at(at, "random_seed", &()) - } -} - -#[cfg(feature = "std")] -impl client::runtime_api::TaggedTransactionQueue for ClientWithApi { - fn validate_transaction( - &self, - at: &GBlockId, - utx: &::Extrinsic - ) -> Result { - self.call_api_at(at, "validate_transaction", utx) - } -} - -#[cfg(feature = "std")] -impl client::runtime_api::Metadata for ClientWithApi { - fn metadata(&self, at: &GBlockId) -> Result { - self.call_api_at(at, "metadata", &()) - } -} - -#[cfg(feature = "std")] -impl substrate_finality_grandpa_primitives::GrandpaApi for ClientWithApi { - fn grandpa_pending_change(&self, at: &GBlockId, digest: &DigestFor) - -> Result>>, client::error::Error> { - self.call_api_at(at, "grandpa_pending_change", digest) - } - - fn grandpa_authorities(&self, at: &GBlockId) - -> Result, client::error::Error> { - self.call_api_at(at, "grandpa_authorities", &()) - } -} - impl_runtime_apis! { - impl Core for Runtime { + impl client_api::Core for Runtime { fn version() -> RuntimeVersion { VERSION } @@ -437,13 +272,13 @@ impl_runtime_apis! { } } - impl Metadata for Runtime { + impl client_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { Runtime::metadata().into() } } - impl BlockBuilder for Runtime { + impl block_builder_api::BlockBuilder for Runtime { fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { Executive::apply_extrinsic(extrinsic) } @@ -452,12 +287,27 @@ impl_runtime_apis! { Executive::finalise_block() } - fn inherent_extrinsics(data: InherentData) -> Vec { - data.create_inherent_extrinsics() + fn inherent_extrinsics(data: runtime_primitives::InherentData) -> Vec<::Extrinsic> { + let mut inherent = Vec::new(); + + inherent.extend( + Timestamp::create_inherent_extrinsics(data.timestamp) + .into_iter() + .map(|v| (v.0, UncheckedExtrinsic::new_unsigned(Call::Timestamp(v.1)))) + ); + + inherent.extend( + Consensus::create_inherent_extrinsics(data.consensus) + .into_iter() + .map(|v| (v.0, UncheckedExtrinsic::new_unsigned(Call::Consensus(v.1)))) + ); + + inherent.as_mut_slice().sort_unstable_by_key(|v| v.0); + inherent.into_iter().map(|v| v.1).collect() } - fn check_inherents(block: Block, data: InherentData) -> Result<(), InherentError> { - data.check_inherents(block) + fn check_inherents(block: Block, data: runtime_primitives::InherentData) -> Result<(), CheckInherentError> { + InherentData::check_inherents(data, block) } fn random_seed() -> ::Hash { @@ -465,13 +315,13 @@ impl_runtime_apis! { } } - impl TaggedTransactionQueue for Runtime { + impl client_api::TaggedTransactionQueue for Runtime { fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { Executive::validate_transaction(tx) } } - impl GrandpaApi for Runtime { + impl fg_primitives::GrandpaApi for Runtime { fn grandpa_pending_change(digest: DigestFor) -> Option>> { diff --git a/node/runtime/wasm/Cargo.lock b/node/runtime/wasm/Cargo.lock index 83b4a4cc4a6d2..55354c02e9837 100644 --- a/node/runtime/wasm/Cargo.lock +++ b/node/runtime/wasm/Cargo.lock @@ -829,7 +829,7 @@ 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)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -896,6 +896,15 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sr-api-macros" +version = "0.1.0" +dependencies = [ + "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sr-io" version = "0.1.0" @@ -1240,6 +1249,7 @@ dependencies = [ "parity-codec 2.1.5 (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.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-api-macros 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", @@ -1394,7 +1404,7 @@ dependencies = [ [[package]] name = "syn" -version = "0.15.6" +version = "0.15.22" 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)", @@ -1851,7 +1861,7 @@ dependencies = [ "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.6 (registry+https://github.com/rust-lang/crates.io-index)" = "854b08a640fc8f54728fb95321e3ec485b365a97fe47609797c671addd1dde69" +"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" diff --git a/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm b/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm index 56a3e347cea88..a12cd6a07e1ef 100644 Binary files a/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm and b/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm differ diff --git a/srml/consensus/src/lib.rs b/srml/consensus/src/lib.rs index b39977a476b6c..6a30327d81342 100644 --- a/srml/consensus/src/lib.rs +++ b/srml/consensus/src/lib.rs @@ -44,7 +44,7 @@ use runtime_support::{storage, Parameter}; use runtime_support::dispatch::Result; use runtime_support::storage::StorageValue; use runtime_support::storage::unhashed::StorageVec; -use primitives::RuntimeString; +use primitives::CheckInherentError; use primitives::traits::{ MaybeSerializeDebug, Member, ProvideInherent, Block as BlockT }; @@ -249,7 +249,6 @@ impl Module { impl ProvideInherent for Module { type Inherent = Vec; type Call = Call; - type Error = RuntimeString; fn create_inherent_extrinsics(data: Self::Inherent) -> Vec<(u32, Self::Call)> { vec![(T::NOTE_OFFLINE_POSITION, Call::note_offline(data))] @@ -257,7 +256,7 @@ impl ProvideInherent for Module { fn check_inherent Option<&Self::Call>>( block: &Block, data: Self::Inherent, extract_function: &F - ) -> result::Result<(), Self::Error> { + ) -> result::Result<(), CheckInherentError> { let noted_offline = block .extrinsics().get(T::NOTE_OFFLINE_POSITION as usize) .and_then(|xt| match extract_function(&xt) { @@ -267,7 +266,7 @@ impl ProvideInherent for Module { noted_offline.iter().try_for_each(|n| if !data.contains(n) { - Err("Online node marked offline".into()) + Err(CheckInherentError::Other("Online node marked offline".into())) } else { Ok(()) } diff --git a/srml/support/src/inherent.rs b/srml/support/src/inherent.rs index f87a41806a93a..8be51f4224b6b 100644 --- a/srml/support/src/inherent.rs +++ b/srml/support/src/inherent.rs @@ -17,7 +17,9 @@ #[doc(hidden)] pub use rstd::{result::Result, vec::Vec}; #[doc(hidden)] -pub use runtime_primitives::traits::ProvideInherent; +pub use runtime_primitives::{ + traits::{ProvideInherent, Block as BlockT}, CheckInherentError, InherentData +}; /// Implement the outer inherent. @@ -39,50 +41,43 @@ pub use runtime_primitives::traits::ProvideInherent; macro_rules! impl_outer_inherent { ( $(#[$attr:meta])* - pub struct $name:ident where Block = $block:ident, UncheckedExtrinsic = $unchecked:ident { - $( $module:ident: $module_ty:ident $(export Error as $error_name:ident)*, )* + pub struct $name:ident where Block = $block:ident { + $( $module:ident: $module_ty:ident, )* } ) => { impl_outer_inherent!( $( #[$attr] )* - pub struct $name where Block = $block, UncheckedExtrinsic = $unchecked, Error = InherentError, Call = Call { - $( $module: $module_ty $(export Error as $error_name)*, )* + pub struct $name where Block = $block, Call = Call { + $( $module: $module_ty, )* } ); }; ( $(#[$attr:meta])* - pub struct $name:ident where Block = $block:ident, UncheckedExtrinsic = $unchecked:ident, Error = $error:ident { - $( $module:ident: $module_ty:ident $(export Error as $error_name:ident)*, )* + pub struct $name:ident where Block = $block:ident { + $( $module:ident: $module_ty:ident, )* } ) => { impl_outer_inherent!( $( #[$attr] )* - pub struct $name where Block = $block, UncheckedExtrinsic = $unchecked, Error = $error, Call = Call { - $( $module: $module_ty $(export Error as $error_name)*, )* + pub struct $name where Block = $block, Call = Call { + $( $module: $module_ty, )* } ); }; ( $(#[$attr:meta])* - pub struct $name:ident where Block = $block:ident, UncheckedExtrinsic = $unchecked:ident, Error = $error:ident, Call = $call:ident { - $( $module:ident: $module_ty:ident $(export Error as $error_name:ident)*, )* + pub struct $name:ident where Block = $block:ident, Call = $call:ident { + $( $module:ident: $module_ty:ident, )* } ) => { $( #[$attr] )* - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Encode, Decode)] /// Inherent data to include in a block. pub struct $name { $( $module: <$module_ty as $crate::inherent::ProvideInherent>::Inherent, )* } - $( - $( - pub type $error_name =<$module_ty as $crate::inherent::ProvideInherent>::Error; - )* - )* - impl $name { /// Create a new instance. pub fn new( $( $module: <$module_ty as $crate::inherent::ProvideInherent>::Inherent ),* ) -> Self { @@ -91,38 +86,19 @@ macro_rules! impl_outer_inherent { } } - fn create_inherent_extrinsics(self) -> Vec<$unchecked> { - let mut inherent = $crate::inherent::Vec::new(); - - $( - inherent.extend( - <$module_ty as $crate::inherent::ProvideInherent>::create_inherent_extrinsics(self.$module) - .into_iter() - .map(|v| (v.0, $unchecked::new_unsigned($call::$module_ty(v.1)))) - ); - )* - - inherent.as_mut_slice().sort_unstable_by_key(|v| v.0); - inherent.into_iter().map(|v| v.1).collect() - } - - fn check_inherents(self, block: $block) -> $crate::inherent::Result<(), $error> { + fn check_inherents( + data: $crate::inherent::InherentData, + block: $block + ) -> $crate::inherent::Result<(), $crate::inherent::CheckInherentError> { $( <$module_ty as $crate::inherent::ProvideInherent>::check_inherent( - &block, self.$module, &|xt| match xt.function { + &block, data.$module, &|xt| match xt.function { Call::$module_ty(ref data) => Some(data), _ => None, - }).map_err($error::$module_ty)?; + })?; )* Ok(()) } } - - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Encode)] - #[cfg_attr(feature = "std", derive(Decode))] - pub enum $error { - $( $module_ty(<$module_ty as $crate::inherent::ProvideInherent>::Error), )* - } }; } diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index 20cf57ca71d85..adccf997ebbb0 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -122,4 +122,5 @@ pub enum Void {} pub use mashup::*; #[cfg(feature = "std")] +#[doc(hidden)] pub use serde_derive::*; diff --git a/srml/support/src/runtime.rs b/srml/support/src/runtime.rs index 86eaaf1b04d2e..0376179e38b32 100644 --- a/srml/support/src/runtime.rs +++ b/srml/support/src/runtime.rs @@ -20,7 +20,10 @@ /// /// ```nocompile /// construct_runtime!( -/// pub enum Runtime with Log(interalIdent: DigestItem) { +/// pub enum Runtime with Log(interalIdent: DigestItem) where +/// Block = Block, +/// NodeBlock = runtime::Block +/// { /// System: system, /// Test: test::{default, Log(Test)}, /// Test2: test_with_long_module::{Module}, @@ -48,7 +51,9 @@ macro_rules! construct_runtime { ( pub enum $runtime:ident with Log ($log_internal:ident: DigestItem<$( $log_genarg:ty ),+>) - where Block = $block:ident, UncheckedExtrinsic = $unchecked:ident + where + Block = $block:ident, + NodeBlock = $node_block:ty { $( $rest:tt )* } @@ -56,7 +61,7 @@ macro_rules! construct_runtime { construct_runtime!( $runtime; $block; - $unchecked; + $node_block; $log_internal < $( $log_genarg ),* >; ; $( $rest )* @@ -65,7 +70,7 @@ macro_rules! construct_runtime { ( $runtime:ident; $block:ident; - $unchecked:ident; + $node_block:ty; $log_internal:ident <$( $log_genarg:ty ),+>; $( $expanded_name:ident: $expanded_module:ident::{ @@ -92,7 +97,7 @@ macro_rules! construct_runtime { construct_runtime!( $runtime; $block; - $unchecked; + $node_block; $log_internal < $( $log_genarg ),* >; $( $expanded_name: $expanded_module::{ @@ -119,7 +124,7 @@ macro_rules! construct_runtime { ( $runtime:ident; $block:ident; - $unchecked:ident; + $node_block:ty; $log_internal:ident <$( $log_genarg:ty ),+>; $( $expanded_name:ident: $expanded_module:ident::{ @@ -153,7 +158,7 @@ macro_rules! construct_runtime { construct_runtime!( $runtime; $block; - $unchecked; + $node_block; $log_internal < $( $log_genarg ),* >; $( $expanded_name: $expanded_module::{ @@ -186,7 +191,7 @@ macro_rules! construct_runtime { ( $runtime:ident; $block:ident; - $unchecked:ident; + $node_block:ty; $log_internal:ident <$( $log_genarg:ty ),+>; $( $expanded_name:ident: $expanded_module:ident::{ @@ -219,7 +224,7 @@ macro_rules! construct_runtime { construct_runtime!( $runtime; $block; - $unchecked; + $node_block; $log_internal < $( $log_genarg ),* >; $( $expanded_name: $expanded_module::{ @@ -251,7 +256,7 @@ macro_rules! construct_runtime { ( $runtime:ident; $block:ident; - $unchecked:ident; + $node_block:ty; $log_internal:ident <$( $log_genarg:ty ),+>; $( $name:ident: $module:ident::{ @@ -273,6 +278,12 @@ macro_rules! construct_runtime { #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] pub struct $runtime; + impl $crate::runtime_primitives::traits::GetNodeBlockType for $runtime { + type NodeBlock = $node_block; + } + impl $crate::runtime_primitives::traits::GetRuntimeBlockType for $runtime { + type RuntimeBlock = $block; + } __decl_outer_event!( $runtime; $( @@ -326,7 +337,6 @@ macro_rules! construct_runtime { __decl_outer_inherent!( $runtime; $block; - $unchecked; ; $( $name: $module::{ $( $modules $( <$modules_generic> )* ),* } @@ -1052,7 +1062,6 @@ macro_rules! __decl_outer_inherent { ( $runtime:ident; $block:ident; - $unchecked:ident; $( $parsed_modules:ident :: $parsed_name:ident ),*; $name:ident: $module:ident::{ Inherent $(, $modules:ident $( <$modules_generic:ident> )* )* @@ -1064,7 +1073,6 @@ macro_rules! __decl_outer_inherent { __decl_outer_inherent!( $runtime; $block; - $unchecked; $( $parsed_modules :: $parsed_name, )* $module::$name; $( $rest_name: $rest_module::{ @@ -1076,7 +1084,6 @@ macro_rules! __decl_outer_inherent { ( $runtime:ident; $block:ident; - $unchecked:ident; $( $parsed_modules:ident :: $parsed_name:ident ),*; $name:ident: $module:ident::{ $ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )* @@ -1088,7 +1095,6 @@ macro_rules! __decl_outer_inherent { __decl_outer_inherent!( $runtime; $block; - $unchecked; $( $parsed_modules :: $parsed_name ),*; $name: $module::{ $( $modules $( <$modules_generic> )* ),* } $( @@ -1101,7 +1107,6 @@ macro_rules! __decl_outer_inherent { ( $runtime:ident; $block:ident; - $unchecked:ident; $( $parsed_modules:ident :: $parsed_name:ident ),*; $name:ident: $module:ident::{} $(, $rest_name:ident : $rest_module:ident::{ @@ -1111,7 +1116,6 @@ macro_rules! __decl_outer_inherent { __decl_outer_inherent!( $runtime; $block; - $unchecked; $( $parsed_modules :: $parsed_name ),*; $( $rest_name: $rest_module::{ @@ -1123,15 +1127,14 @@ macro_rules! __decl_outer_inherent { ( $runtime:ident; $block:ident; - $unchecked:ident; $( $parsed_modules:ident :: $parsed_name:ident ),*; ; ) => { substrate_generate_ident_name! { impl_outer_inherent!( - pub struct InherentData where Block = $block, UncheckedExtrinsic = $unchecked { + pub struct InherentData where Block = $block { $( - $parsed_modules: $parsed_name export Error as "inherent-error-ident" $parsed_name, + $parsed_modules: $parsed_name, )* } ); diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index db1e2934db3a7..422fd1faad738 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -52,7 +52,7 @@ extern crate parity_codec_derive; use codec::HasCompact; use runtime_support::{StorageValue, Parameter}; use runtime_support::dispatch::Result; -use runtime_primitives::RuntimeString; +use runtime_primitives::CheckInherentError; use runtime_primitives::traits::{ As, SimpleArithmetic, Zero, ProvideInherent, Block as BlockT, Extrinsic }; @@ -131,17 +131,9 @@ impl Module { } } -#[derive(Encode)] -#[cfg_attr(feature = "std", derive(Decode))] -pub enum InherentError { - Other(RuntimeString), - TimestampInFuture(u64), -} - impl ProvideInherent for Module { type Inherent = T::Moment; type Call = Call; - type Error = InherentError; fn create_inherent_extrinsics(data: Self::Inherent) -> Vec<(u32, Self::Call)> { vec![(T::TIMESTAMP_SET_POSITION, Call::set(data.into()))] @@ -149,19 +141,19 @@ impl ProvideInherent for Module { fn check_inherent Option<&Self::Call>>( block: &Block, data: Self::Inherent, extract_function: &F - ) -> result::Result<(), Self::Error> { + ) -> result::Result<(), CheckInherentError> { const MAX_TIMESTAMP_DRIFT: u64 = 60; let xt = block.extrinsics().get(T::TIMESTAMP_SET_POSITION as usize) - .ok_or_else(|| InherentError::Other("No valid timestamp inherent in block".into()))?; + .ok_or_else(|| CheckInherentError::Other("No valid timestamp inherent in block".into()))?; let t = match (xt.is_signed(), extract_function(&xt)) { (Some(false), Some(Call::set(ref t))) => t.clone(), - _ => return Err(InherentError::Other("No valid timestamp inherent in block".into())), + _ => return Err(CheckInherentError::Other("No valid timestamp inherent in block".into())), }.into().as_(); if t > data.as_() + MAX_TIMESTAMP_DRIFT { - Err(InherentError::TimestampInFuture(t)) + Err(CheckInherentError::TimestampInFuture(t)) } else { Ok(()) }