Implement runtime api client side directly in the runtime (#1094)

* Move `initialise_block` into `Core` trait as it is crucial calling the API functions

* Switch to first version of new runtime API implementation

* Fixes bug in tests

* Reenable asserts

* Directly use the `TestAPI` in the tests

* Start improving the api traits

:100644 100644 898aadc7 49217199 M	Cargo.lock
:100644 100644 61570436 465ed664 M	core/client/src/backend.rs
:100644 100644 5d0c886b 64d710fd M	core/client/src/block_builder.rs
:100644 100644 c447855e 5ecbe474 M	core/client/src/client.rs
:100644 100644 139cef13 f90dbf3d M	core/client/src/error.rs
:100644 100644 2800c503 3298e66a M	core/client/src/runtime_api.rs
:100644 100644 affa1c5c 809b08bc M	core/primitives/src/lib.rs
:100644 100644 2877dfa9 d5547413 M	core/sr-api/Cargo.toml
:100644 100644 9a49784d 6a625a03 M	core/sr-api/src/lib.rs
:100644 100644 7c28e1c7 a1a444a9 M	core/sr-primitives/src/traits.rs
:100644 100644 2e113ab6 dcc01a6d M	srml/metadata/Cargo.toml
:100644 100644 ea722a70 0809531a M	srml/metadata/src/lib.rs

* Refactoring

* Move `sr-api` into client and more refactoring

* Fixes tests

* Some documentation and cleanup

* Fixes compilation after rebase

* More refactoring and more documentation

* Makes `substrate-client` compilable on `wasm`

On `wasm` it basically just exports the runtime api stuff.

* Fixes grumbles

* Updates wasm files after rebasing the master

* Remove TODO comment

* Remove whitespaces

* Fixes after rebasing master

* Another rebase, another fix commit
This commit is contained in:
Bastian Köcher
2018-11-13 13:33:28 +01:00
committed by Gav Wood
parent 6e3c56c135
commit 9063d1acae
51 changed files with 2993 additions and 777 deletions
+7 -13
View File
@@ -1786,7 +1786,6 @@ dependencies = [
"safe-mix 1.0.0 (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)",
"sr-api 0.1.0",
"sr-primitives 0.1.0",
"sr-std 0.1.0",
"sr-version 0.1.0",
@@ -1803,6 +1802,7 @@ dependencies = [
"srml-timestamp 0.1.0",
"srml-treasury 0.1.0",
"srml-upgrade-key 0.1.0",
"substrate-client 0.1.0",
"substrate-keyring 0.1.0",
"substrate-primitives 0.1.0",
]
@@ -2566,16 +2566,6 @@ dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "sr-api"
version = "0.1.0"
dependencies = [
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 0.1.0",
"sr-std 0.1.0",
"sr-version 0.1.0",
]
[[package]]
name = "sr-io"
version = "0.1.0"
@@ -2789,6 +2779,8 @@ dependencies = [
"parity-codec-derive 2.1.0 (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)",
"sr-std 0.1.0",
"substrate-primitives 0.1.0",
]
[[package]]
@@ -3060,8 +3052,9 @@ 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 0.1.0",
"sr-primitives 0.1.0",
"sr-std 0.1.0",
"sr-version 0.1.0",
"substrate-consensus-common 0.1.0",
"substrate-executor 0.1.0",
"substrate-keyring 0.1.0",
@@ -3455,6 +3448,7 @@ dependencies = [
"substrate-executor 0.1.0",
"substrate-keyring 0.1.0",
"substrate-primitives 0.1.0",
"substrate-state-machine 0.1.0",
"substrate-test-runtime 0.1.0",
]
@@ -3468,12 +3462,12 @@ dependencies = [
"parity-codec-derive 2.1.0 (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)",
"sr-api 0.1.0",
"sr-io 0.1.0",
"sr-primitives 0.1.0",
"sr-std 0.1.0",
"sr-version 0.1.0",
"srml-support 0.1.0",
"substrate-client 0.1.0",
"substrate-keyring 0.1.0",
"substrate-primitives 0.1.0",
]
-1
View File
@@ -32,7 +32,6 @@ members = [
"core/primitives",
"core/rpc",
"core/rpc-servers",
"core/sr-api",
"core/sr-io",
"core/sr-sandbox",
"core/sr-std",
+2 -4
View File
@@ -30,9 +30,8 @@ use runtime_primitives::traits::{Header, As};
const TIMER_INTERVAL_MS: u64 = 5000;
/// Spawn informant on the event loop
pub fn start<C>(service: &Service<C>, exit: ::exit_future::Exit, handle: TaskExecutor)
where
C: Components,
pub fn start<C>(service: &Service<C>, exit: ::exit_future::Exit, handle: TaskExecutor) where
C: Components,
{
let interval = Interval::new(Instant::now(), Duration::from_millis(TIMER_INTERVAL_MS));
@@ -121,4 +120,3 @@ fn speed(best_number: u64, last_number: Option<u64>) -> String {
format!(" {:4.1} bps", speed / 10.0)
}
}
+48 -20
View File
@@ -4,27 +4,55 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
error-chain = "0.12"
fnv = "1.0"
log = "0.4"
parking_lot = "0.4"
hex-literal = "0.1"
futures = "0.1.17"
slog = "^2"
heapsize = "0.4"
substrate-consensus-common = { path = "../consensus/common" }
parity-codec = "2.1"
substrate-executor = { path = "../executor" }
substrate-primitives = { path = "../primitives" }
sr-primitives = { path = "../sr-primitives" }
sr-api = { path = "../sr-api" }
substrate-state-machine = { path = "../state-machine" }
substrate-keyring = { path = "../keyring" }
substrate-trie = { path = "../trie" }
substrate-telemetry = { path = "../telemetry" }
hash-db = { git = "https://github.com/paritytech/trie" }
kvdb = "0.1"
error-chain = { version = "0.12", optional = true }
fnv = { version = "1.0", optional = true }
log = { version = "0.4", optional = true }
parking_lot = { version = "0.4", optional = true }
hex-literal = { version = "0.1", optional = true }
futures = { version = "0.1.17", optional = true }
slog = { version = "^2", optional = true }
heapsize = { version = "0.4", optional = true }
substrate-consensus-common = { path = "../consensus/common", optional = true }
substrate-executor = { path = "../executor", optional = true }
substrate-state-machine = { path = "../state-machine", optional = true }
substrate-keyring = { path = "../keyring", optional = true }
substrate-trie = { path = "../trie", optional = true }
substrate-telemetry = { path = "../telemetry", optional = true }
hash-db = { git = "https://github.com/paritytech/trie", optional = true }
kvdb = { version = "0.1", optional = true }
parity-codec = { version = "2.1", default-features = false }
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 }
[dev-dependencies]
substrate-test-client = { path = "../test-client" }
kvdb-memorydb = "0.1"
[features]
default = ["std"]
std = [
"parity-codec/std",
"substrate-consensus-common",
"substrate-primitives/std",
"parking_lot",
"error-chain",
"fnv",
"log",
"hex-literal",
"futures",
"slog",
"heapsize",
"substrate-executor",
"sr-primitives/std",
"sr-version/std",
"sr-std/std",
"substrate-state-machine",
"substrate-keyring",
"substrate-trie",
"substrate-telemetry",
"hash-db",
"kvdb"
]
+6 -6
View File
@@ -94,17 +94,17 @@ pub struct DatabaseSettings {
}
/// Create an instance of db-backed client.
pub fn new_client<E, S, Block>(
pub fn new_client<E, S, Block, RA>(
settings: DatabaseSettings,
executor: E,
genesis_storage: S,
block_execution_strategy: ExecutionStrategy,
api_execution_strategy: ExecutionStrategy,
) -> Result<client::Client<Backend<Block>, client::LocalCallExecutor<Backend<Block>, E>, Block>, client::error::Error>
where
Block: BlockT<Hash=H256>,
E: CodeExecutor<Blake2Hasher> + RuntimeInfo,
S: BuildStorage,
) -> Result<client::Client<Backend<Block>, client::LocalCallExecutor<Backend<Block>, E>, Block, RA>, client::error::Error>
where
Block: BlockT<Hash=H256>,
E: CodeExecutor<Blake2Hasher> + RuntimeInfo,
S: BuildStorage,
{
let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?);
let executor = client::LocalCallExecutor::new(backend.clone(), executor);
+2 -5
View File
@@ -47,8 +47,7 @@ impl NewBlockState {
}
/// Block insertion operation. Keeps hold if the inserted block state and data.
pub trait BlockImportOperation<Block, H>
where
pub trait BlockImportOperation<Block, H> where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
{
@@ -85,11 +84,9 @@ where
///
/// The same applies for live `BlockImportOperation`s: while an import operation building on a parent `P`
/// is alive, the state for `P` should not be pruned.
pub trait Backend<Block, H>: Send + Sync
where
pub trait Backend<Block, H>: Send + Sync where
Block: BlockT,
H: Hasher<Out=Block::Hash>,
{
/// Associated block insertion operation type.
type BlockImportOperation: BlockImportOperation<Block, H>;
@@ -0,0 +1,40 @@
// 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 <http://www.gnu.org/licenses/>.
//! The runtime api for building blocks.
use runtime_primitives::{traits::Block as BlockT, ApplyResult};
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<Block: BlockT> {
/// The runtime api for building blocks./// Apply the given extrinsics.
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyResult;
/// Finish the current block.
fn finalise_block() -> <Block as BlockT>::Header;
/// Generate inherent extrinsics.
fn inherent_extrinsics<InherentExtrinsic, UncheckedExtrinsic>(
inherent: InherentExtrinsic
) -> Vec<UncheckedExtrinsic>;
/// Check that the inherents are valid.
fn check_inherents<InherentData, Error>(
block: Block, data: InherentData
) -> Result<(), Error>;
/// Generate a random seed.
fn random_seed() -> <Block as BlockT>::Hash;
}
}
@@ -14,60 +14,48 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Utility struct to build a block.
use super::api::BlockBuilder as BlockBuilderApi;
use std::vec::Vec;
use std::marker::PhantomData;
use codec::Encode;
use state_machine;
use runtime_primitives::traits::{Header as HeaderT, Hash, Block as BlockT, One, HashFor};
use blockchain::HeaderBackend;
use runtime_primitives::traits::{
Header as HeaderT, Hash, Block as BlockT, One, HashFor, ProvideRuntimeApi, ApiRef
};
use primitives::H256;
use runtime_primitives::generic::BlockId;
use runtime_api::BlockBuilder as BlockBuilderAPI;
use {backend, error, Client, CallExecutor};
use runtime_api::Core;
use error;
use runtime_primitives::ApplyOutcome;
use primitives::{Blake2Hasher, H256};
use hash_db::Hasher;
/// Utility for building new (valid) blocks from a stream of extrinsics.
pub struct BlockBuilder<'a, B, E, Block, H>
where
B: backend::Backend<Block, H> + 'a,
E: CallExecutor<Block, H> + Clone + 'a,
Block: BlockT,
H: Hasher<Out=Block::Hash>,
H::Out: Ord,
{
pub struct BlockBuilder<'a, Block, A: ProvideRuntimeApi> where Block: BlockT {
header: <Block as BlockT>::Header,
extrinsics: Vec<<Block as BlockT>::Extrinsic>,
client: &'a Client<B, E, Block>,
api: ApiRef<'a, A::Api>,
block_id: BlockId<Block>,
changes: state_machine::OverlayedChanges,
_marker: PhantomData<H>,
}
impl<'a, B, E, Block> BlockBuilder<'a, B, E, Block, Blake2Hasher>
impl<'a, Block, A> BlockBuilder<'a, Block, A>
where
B: backend::Backend<Block, Blake2Hasher> + 'a,
E: CallExecutor<Block, Blake2Hasher> + Clone + 'a,
Block: BlockT<Hash=H256>,
A: ProvideRuntimeApi + HeaderBackend<Block> + 'a,
A::Api: BlockBuilderApi<Block>,
{
/// Create a new instance of builder from the given client, building on the latest block.
pub fn new(client: &'a Client<B, E, Block>) -> error::Result<Self> {
client.info().and_then(|i| Self::at_block(&BlockId::Hash(i.chain.best_hash), client))
pub fn new(api: &'a A) -> error::Result<Self> {
api.info().and_then(|i| Self::at_block(&BlockId::Hash(i.best_hash), api))
}
/// Create a new instance of builder from the given client using a particular block's ID to
/// build upon.
pub fn at_block(block_id: &BlockId<Block>, client: &'a Client<B, E, Block>) -> error::Result<Self> {
let number = client.block_number_from_id(block_id)?
pub fn at_block(block_id: &BlockId<Block>, api: &'a A) -> error::Result<Self> {
let number = api.block_number_from_id(block_id)?
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", block_id)))?
+ One::one();
let parent_hash = client.block_hash_from_id(block_id)?
let parent_hash = api.block_hash_from_id(block_id)?
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", block_id)))?;
let mut changes = Default::default();
let header = <<Block as BlockT>::Header as HeaderT>::new(
number,
Default::default(),
@@ -76,16 +64,14 @@ where
Default::default()
);
client.initialise_block(block_id, &mut changes, &header)?;
changes.commit_prospective();
let api = api.runtime_api();
api.initialise_block(block_id, &header)?;
Ok(BlockBuilder {
header,
extrinsics: Vec::new(),
client,
api,
block_id: *block_id,
changes,
_marker: Default::default(),
})
}
@@ -93,30 +79,32 @@ where
/// can be validly executed (by executing it); if it is invalid, it'll be returned along with
/// the error. Otherwise, it will return a mutable reference to self (in order to chain).
pub fn push(&mut self, xt: <Block as BlockT>::Extrinsic) -> error::Result<()> {
match self.client.apply_extrinsic(&self.block_id, &mut self.changes, &xt) {
Ok(result) => {
match result {
fn impl_push<'a, T, Block: BlockT>(
api: &mut ApiRef<'a, T>,
block_id: &BlockId<Block>,
xt: Block::Extrinsic,
extrinsics: &mut Vec<Block::Extrinsic>
) -> error::Result<()> where T: BlockBuilderApi<Block> {
api.map_api_result(|api| {
match api.apply_extrinsic(block_id, &xt)? {
Ok(ApplyOutcome::Success) | Ok(ApplyOutcome::Fail) => {
self.extrinsics.push(xt);
self.changes.commit_prospective();
extrinsics.push(xt);
Ok(())
}
Err(e) => {
self.changes.discard_prospective();
Err(error::ErrorKind::ApplyExtrinsicFailed(e).into())
}
}
}
Err(e) => {
self.changes.discard_prospective();
Err(e)
}
})
}
//FIXME: Please NLL, help me!
impl_push(&mut self.api, &self.block_id, xt, &mut self.extrinsics)
}
/// Consume the builder to return a valid `Block` containing all pushed extrinsics.
pub fn bake(mut self) -> error::Result<Block> {
self.header = self.client.finalise_block(&self.block_id, &mut self.changes)?;
self.header = self.api.finalise_block(&self.block_id)?;
debug_assert_eq!(
self.header.extrinsics_root().clone(),
@@ -0,0 +1,23 @@
// 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 <http://www.gnu.org/licenses/>.
//! Utility struct to build a block.
#[cfg(feature = "std")]
mod block_builder;
#[cfg(feature = "std")]
pub use self::block_builder::*;
pub mod api;
+16
View File
@@ -40,6 +40,22 @@ pub trait HeaderBackend<Block: BlockT>: Send + Sync {
fn expect_header(&self, id: BlockId<Block>) -> Result<Block::Header> {
self.header(id)?.ok_or_else(|| ErrorKind::UnknownBlock(format!("{}", id)).into())
}
/// Convert an arbitrary block ID into a block hash.
fn block_hash_from_id(&self, id: &BlockId<Block>) -> Result<Option<Block::Hash>> {
match *id {
BlockId::Hash(h) => Ok(Some(h)),
BlockId::Number(n) => self.hash(n),
}
}
/// Convert an arbitrary block ID into a block hash.
fn block_number_from_id(&self, id: &BlockId<Block>) -> Result<Option<NumberFor<Block>>> {
match *id {
BlockId::Hash(_) => Ok(self.header(*id)?.map(|h| h.number().clone())),
BlockId::Number(n) => Ok(Some(n)),
}
}
}
/// Blockchain database backend. Does not perform any validation.
+204 -232
View File
@@ -16,8 +16,8 @@
//! Substrate Client
use std::sync::Arc;
use error::{Error, ErrorKind};
use std::{marker::PhantomData, sync::Arc};
use error::Error;
use futures::sync::mpsc;
use parking_lot::{Mutex, RwLock};
use primitives::AuthorityId;
@@ -27,25 +27,29 @@ use runtime_primitives::{
transaction_validity::{TransactionValidity, TransactionTag},
};
use consensus::{ImportBlock, ImportResult, BlockOrigin};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash};
use runtime_primitives::{ApplyResult, BuildStorage};
use runtime_api as api;
use runtime_primitives::traits::{
Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash,
ApiRef, ProvideRuntimeApi
};
use runtime_primitives::BuildStorage;
use runtime_api::{Core as CoreAPI, CallApiAt, TaggedTransactionQueue, ConstructRuntimeApi};
use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash};
use primitives::storage::{StorageKey, StorageData};
use primitives::storage::well_known_keys;
use codec::{Encode, Decode};
use codec::Decode;
use state_machine::{
Backend as StateBackend, CodeExecutor,
ExecutionStrategy, ExecutionManager, ChangesTrieAnchorBlockId,
prove_read, key_changes, key_changes_proof, OverlayedChanges
Backend as StateBackend, CodeExecutor, ChangesTrieAnchorBlockId,
ExecutionStrategy, ExecutionManager, prove_read,
key_changes, key_changes_proof, OverlayedChanges
};
use codec::Encode;
use backend::{self, BlockImportOperation};
use blockchain::{self, Info as ChainInfo, Backend as ChainBackend, HeaderBackend as ChainHeaderBackend};
use call_executor::{CallExecutor, LocalCallExecutor};
use executor::{RuntimeVersion, RuntimeInfo};
use notifications::{StorageNotifications, StorageEventStream};
use {cht, error, in_mem, block_builder, genesis, consensus};
use {cht, error, in_mem, block_builder::{self, api::BlockBuilder as BlockBuilderAPI}, genesis, consensus};
/// Type that implements `futures::Stream` of block import events.
pub type ImportNotifications<Block> = mpsc::UnboundedReceiver<BlockImportNotification<Block>>;
@@ -54,7 +58,7 @@ pub type ImportNotifications<Block> = mpsc::UnboundedReceiver<BlockImportNotific
pub type FinalityNotifications<Block> = mpsc::UnboundedReceiver<FinalityNotification<Block>>;
/// Substrate Client
pub struct Client<B, E, Block> where Block: BlockT {
pub struct Client<B, E, Block, RA> where Block: BlockT {
backend: Arc<B>,
executor: E,
storage_notifications: Mutex<StorageNotifications<Block>>,
@@ -65,6 +69,7 @@ pub struct Client<B, E, Block> where Block: BlockT {
block_execution_strategy: ExecutionStrategy,
api_execution_strategy: ExecutionStrategy,
changes_trie_config: Option<ChangesTrieConfiguration>,
_phantom: PhantomData<RA>,
}
/// A source of blockchain events.
@@ -180,36 +185,36 @@ impl<H> PrePostHeader<H> {
}
/// Create an instance of in-memory client.
pub fn new_in_mem<E, Block, S>(
pub fn new_in_mem<E, Block, S, RA>(
executor: E,
genesis_storage: S,
) -> error::Result<Client<in_mem::Backend<Block, Blake2Hasher>, LocalCallExecutor<in_mem::Backend<Block, Blake2Hasher>, E>, Block>>
where
E: CodeExecutor<Blake2Hasher> + RuntimeInfo,
S: BuildStorage,
Block: BlockT<Hash=H256>,
) -> error::Result<Client<in_mem::Backend<Block, Blake2Hasher>, LocalCallExecutor<in_mem::Backend<Block, Blake2Hasher>, E>, Block, RA>>
where
E: CodeExecutor<Blake2Hasher> + RuntimeInfo,
S: BuildStorage,
Block: BlockT<Hash=H256>,
{
new_with_backend(Arc::new(in_mem::Backend::new()), executor, genesis_storage)
}
/// Create a client with the explicitely provided backend.
/// This is useful for testing backend implementations.
pub fn new_with_backend<B, E, Block, S>(
pub fn new_with_backend<B, E, Block, S, RA>(
backend: Arc<B>,
executor: E,
build_genesis_storage: S,
) -> error::Result<Client<B, LocalCallExecutor<B, E>, Block>>
where
E: CodeExecutor<Blake2Hasher> + RuntimeInfo,
S: BuildStorage,
Block: BlockT<Hash=H256>,
B: backend::LocalBackend<Block, Blake2Hasher>
) -> error::Result<Client<B, LocalCallExecutor<B, E>, Block, RA>>
where
E: CodeExecutor<Blake2Hasher> + RuntimeInfo,
S: BuildStorage,
Block: BlockT<Hash=H256>,
B: backend::LocalBackend<Block, Blake2Hasher>
{
let call_executor = LocalCallExecutor::new(backend.clone(), executor);
Client::new(backend, call_executor, build_genesis_storage, ExecutionStrategy::NativeWhenPossible, ExecutionStrategy::NativeWhenPossible)
}
impl<B, E, Block> Client<B, E, Block> where
impl<B, E, Block, RA> Client<B, E, Block, RA> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT<Hash=H256>,
@@ -255,6 +260,7 @@ impl<B, E, Block> Client<B, E, Block> where
block_execution_strategy,
api_execution_strategy,
changes_trie_config,
_phantom: Default::default(),
})
}
@@ -323,6 +329,36 @@ impl<B, E, Block> Client<B, E, Block> where
self.header_proof_with_cht_size(id, cht::SIZE)
}
pub(crate) fn call_at_state(
&self,
at: &BlockId<Block>,
function: &'static str,
args: Vec<u8>,
changes: &mut OverlayedChanges
) -> error::Result<Vec<u8>> {
let state = self.state_at(at)?;
let execution_manager = || match self.api_execution_strategy {
ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible,
ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm,
ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| {
warn!("Consensus error between wasm and native runtime execution at block {:?}", at);
warn!(" Function {:?}", function);
warn!(" Native result {:?}", native_result);
warn!(" Wasm result {:?}", wasm_result);
wasm_result
}),
};
self.executor.call_at_state(&state, changes, function, &args, execution_manager())
.map(|res| res.0)
}
/// Get block hash by number.
pub fn block_hash(&self, block_number: <<Block as BlockT>::Header as HeaderT>::Number) -> error::Result<Option<Block::Hash>> {
self.backend.blockchain().hash(block_number)
}
/// Reads given header and generates CHT-based header proof for CHT of given size.
pub fn header_proof_with_cht_size(&self, id: &BlockId<Block>, cht_size: u64) -> error::Result<(Block::Header, Vec<Vec<u8>>)> {
let proof_error = || error::ErrorKind::Backend(format!("Failed to generate header proof for {:?}", id));
@@ -402,88 +438,41 @@ impl<B, E, Block> Client<B, E, Block> where
}
/// Create a new block, built on the head of the chain.
pub fn new_block(&self) -> error::Result<block_builder::BlockBuilder<B, E, Block, Blake2Hasher>>
where E: Clone
pub fn new_block(
&self
) -> error::Result<block_builder::BlockBuilder<Block, Self>> where
E: Clone + Send + Sync,
RA: BlockBuilderAPI<Block>
{
block_builder::BlockBuilder::new(self)
}
/// Create a new block, built on top of `parent`.
pub fn new_block_at(&self, parent: &BlockId<Block>) -> error::Result<block_builder::BlockBuilder<B, E, Block, Blake2Hasher>>
where E: Clone
pub fn new_block_at(
&self, parent: &BlockId<Block>
) -> error::Result<block_builder::BlockBuilder<Block, Self>> where
E: Clone + Send + Sync,
RA: BlockBuilderAPI<Block>
{
block_builder::BlockBuilder::at_block(parent, &self)
}
/// Set up the native execution environment to call into a native runtime code.
pub fn call_api<A, R>(&self, function: &'static str, args: &A) -> error::Result<R>
where A: Encode, R: Decode
{
self.call_api_at(&BlockId::Number(self.info()?.chain.best_number), function, args)
}
/// Call a runtime function at given block.
pub fn call_api_at<A, R>(&self, at: &BlockId<Block>, function: &'static str, args: &A) -> error::Result<R>
where A: Encode, R: Decode
{
let parent = at;
let header = <<Block as BlockT>::Header as HeaderT>::new(
self.block_number_from_id(&parent)?
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{:?}", parent)))? + As::sa(1),
Default::default(),
Default::default(),
self.block_hash_from_id(&parent)?
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{:?}", parent)))?,
Default::default()
);
let mut overlay = Default::default();
self.call_at_state(at, "initialise_block", &header, &mut overlay)?;
self.call_at_state(at, function, args, &mut overlay)
}
fn call_at_state<A: Encode, R: Decode>(
&self,
at: &BlockId<Block>,
function: &'static str,
args: &A,
changes: &mut OverlayedChanges
) -> error::Result<R> {
let state = self.state_at(at)?;
let execution_manager = || match self.api_execution_strategy {
ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible,
ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm,
ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| {
warn!("Consensus error between wasm and native runtime execution at block {:?}", at);
warn!(" Function {:?}", function);
warn!(" Native result {:?}", native_result);
warn!(" Wasm result {:?}", wasm_result);
wasm_result
}),
};
self.executor.call_at_state(
&state,
changes,
function,
&args.encode(),
execution_manager()
).and_then(|res|
R::decode(&mut &res.0[..])
.ok_or_else(|| Error::from(ErrorKind::CallResultDecode(function)))
)
}
// TODO [ToDr] Optimize and re-use tags from the pool.
fn transaction_tags(&self, at: Block::Hash, body: &Option<Vec<Block::Extrinsic>>) -> error::Result<Vec<TransactionTag>> {
fn transaction_tags(
&self,
at: Block::Hash,
body: &Option<Vec<Block::Extrinsic>>
) -> error::Result<Vec<TransactionTag>> where
RA: TaggedTransactionQueue<Block>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone,
{
let id = BlockId::Hash(at);
Ok(match body {
None => vec![],
Some(ref extrinsics) => {
let mut tags = vec![];
for tx in extrinsics {
let tx = api::TaggedTransactionQueue::validate_transaction(self, &id, &tx)?;
let tx = self.runtime_api().validate_transaction(&id, &tx)?;
match tx {
TransactionValidity::Valid { mut provides, .. } => {
tags.append(&mut provides);
@@ -508,7 +497,10 @@ impl<B, E, Block> Client<B, E, Block> where
body: Option<Vec<Block::Extrinsic>>,
authorities: Option<Vec<AuthorityId>>,
finalized: bool,
) -> error::Result<ImportResult> {
) -> error::Result<ImportResult> where
RA: TaggedTransactionQueue<Block>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone,
{
let parent_hash = import_headers.post().parent_hash().clone();
match self.backend.blockchain().status(BlockId::Hash(hash))? {
blockchain::BlockStatus::InChain => return Ok(ImportResult::AlreadyInChain),
@@ -737,30 +729,9 @@ impl<B, E, Block> Client<B, E, Block> where
}
}
/// Get block hash by number.
pub fn block_hash(&self, block_number: <<Block as BlockT>::Header as HeaderT>::Number) -> error::Result<Option<Block::Hash>> {
self.backend.blockchain().hash(block_number)
}
/// Convert an arbitrary block ID into a block hash.
pub fn block_hash_from_id(&self, id: &BlockId<Block>) -> error::Result<Option<Block::Hash>> {
match *id {
BlockId::Hash(h) => Ok(Some(h)),
BlockId::Number(n) => self.block_hash(n),
}
}
/// Convert an arbitrary block ID into a block hash.
pub fn block_number_from_id(&self, id: &BlockId<Block>) -> error::Result<Option<NumberFor<Block>>> {
match *id {
BlockId::Hash(_) => Ok(self.header(id)?.map(|h| h.number().clone())),
BlockId::Number(n) => Ok(Some(n)),
}
}
/// Convert an arbitrary block ID into a block hash, returning error if the block is unknown.
fn require_block_number_from_id(&self, id: &BlockId<Block>) -> error::Result<NumberFor<Block>> {
self.block_number_from_id(id)
self.backend.blockchain().block_number_from_id(id)
.and_then(|n| n.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", id)).into()))
}
@@ -896,11 +867,87 @@ impl<B, E, Block> Client<B, E, Block> where
}
}
impl<B, E, Block> consensus::BlockImport<Block> for Client<B, E, Block> where
impl<B, E, Block, RA> ChainHeaderBackend<Block> for Client<B, E, Block, RA> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
Block: BlockT<Hash=H256>,
RA: Send + Sync
{
fn header(&self, id: BlockId<Block>) -> error::Result<Option<Block::Header>> {
self.backend.blockchain().header(id)
}
fn info(&self) -> error::Result<blockchain::Info<Block>> {
self.backend.blockchain().info()
}
fn status(&self, id: BlockId<Block>) -> error::Result<blockchain::BlockStatus> {
self.backend.blockchain().status(id)
}
fn number(&self, hash: Block::Hash) -> error::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>> {
self.backend.blockchain().number(hash)
}
fn hash(&self, number: NumberFor<Block>) -> error::Result<Option<Block::Hash>> {
self.backend.blockchain().hash(number)
}
}
impl<B, E, Block, RA> ProvideRuntimeApi for Client<B, E, Block, RA> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync,
Block: BlockT<Hash=H256>,
RA: CoreAPI<Block>
{
type Api = RA;
fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> {
Self::Api::construct_runtime_api(self)
}
}
impl<B, E, Block, RA> CallApiAt<Block> for Client<B, E, Block, RA> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync,
Block: BlockT<Hash=H256>,
RA: CoreAPI<Block>
{
fn call_api_at(
&self,
at: &BlockId<Block>,
function: &'static str,
args: Vec<u8>,
changes: &mut OverlayedChanges,
initialised_block: &mut Option<BlockId<Block>>,
) -> error::Result<Vec<u8>> {
//TODO: Find a better way to prevent double block initialization
if function != "initialise_block" && initialised_block.map(|id| id != *at).unwrap_or(true) {
let parent = at;
let header = <<Block as BlockT>::Header as HeaderT>::new(
self.block_number_from_id(parent)?
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{:?}", parent)))?
+ As::sa(1),
Default::default(),
Default::default(),
self.block_hash_from_id(&parent)?
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{:?}", parent)))?,
Default::default()
);
self.call_at_state(at, "initialise_block", header.encode(), changes)?;
*initialised_block = Some(*at);
}
self.call_at_state(at, function, args, changes)
}
}
impl<B, E, Block, RA> consensus::BlockImport<Block> for Client<B, E, Block, RA> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync,
Block: BlockT<Hash=H256>,
RA: TaggedTransactionQueue<Block>
{
type Error = Error;
@@ -963,7 +1010,7 @@ impl<B, E, Block> consensus::BlockImport<Block> for Client<B, E, Block> where
}
}
impl<B, E, Block> consensus::Authorities<Block> for Client<B, E, Block> where
impl<B, E, Block, RA> consensus::Authorities<Block> for Client<B, E, Block, RA> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone,
Block: BlockT<Hash=H256>,
@@ -974,7 +1021,7 @@ impl<B, E, Block> consensus::Authorities<Block> for Client<B, E, Block> where
}
}
impl<B, E, Block> CurrentHeight for Client<B, E, Block> where
impl<B, E, Block, RA> CurrentHeight for Client<B, E, Block, RA> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone,
Block: BlockT<Hash=H256>,
@@ -985,7 +1032,7 @@ impl<B, E, Block> CurrentHeight for Client<B, E, Block> where
}
}
impl<B, E, Block> BlockNumberToHash for Client<B, E, Block> where
impl<B, E, Block, RA> BlockNumberToHash for Client<B, E, Block, RA> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone,
Block: BlockT<Hash=H256>,
@@ -998,7 +1045,7 @@ impl<B, E, Block> BlockNumberToHash for Client<B, E, Block> where
}
impl<B, E, Block> BlockchainEvents<Block> for Client<B, E, Block>
impl<B, E, Block, RA> BlockchainEvents<Block> for Client<B, E, Block, RA>
where
E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT<Hash=H256>,
@@ -1022,7 +1069,7 @@ where
}
}
impl<B, E, Block> ChainHead<Block> for Client<B, E, Block>
impl<B, E, Block, RA> ChainHead<Block> for Client<B, E, Block, RA>
where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
@@ -1033,116 +1080,17 @@ where
}
}
impl<B, E, Block> BlockBody<Block> for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT<Hash=H256>,
impl<B, E, Block, RA> BlockBody<Block> for Client<B, E, Block, RA>
where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT<Hash=H256>,
{
fn block_body(&self, id: &BlockId<Block>) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
self.body(id)
}
}
impl<B, E, Block> api::Core<Block, AuthorityId> for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT<Hash=H256>,
{
type Error = Error;
fn version(&self, at: &BlockId<Block>) -> Result<RuntimeVersion, Self::Error> {
self.call_api_at(at, "version", &())
}
fn authorities(&self, at: &BlockId<Block>) -> Result<Vec<AuthorityId>, Self::Error> {
self.authorities_at(at)
}
fn execute_block(&self, at: &BlockId<Block>, block: &Block) -> Result<(), Self::Error> {
self.call_api_at(at, "execute_block", &(block))
}
}
impl<B, E, Block> api::Metadata<Block, Vec<u8>> for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT<Hash=H256>,
{
type Error = Error;
fn metadata(&self, at: &BlockId<Block>) -> Result<Vec<u8>, Self::Error> {
self.executor.call(at, "metadata",&[]).map(|v| v.return_data)
}
}
impl<B, E, Block> api::BlockBuilder<Block> for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT<Hash=H256>,
{
type Error = Error;
type OverlayedChanges = OverlayedChanges;
fn initialise_block(
&self,
at: &BlockId<Block>,
changes: &mut OverlayedChanges,
header: &<Block as BlockT>::Header
) -> Result<(), Self::Error> {
self.call_at_state(at, "initialise_block", header, changes)
}
fn apply_extrinsic(
&self,
at: &BlockId<Block>,
changes: &mut OverlayedChanges,
extrinsic: &<Block as BlockT>::Extrinsic
) -> Result<ApplyResult, Self::Error> {
self.call_at_state(at, "apply_extrinsic", extrinsic, changes)
}
fn finalise_block(
&self,
at: &BlockId<Block>,
changes: &mut OverlayedChanges
) -> Result<<Block as BlockT>::Header, Self::Error> {
self.call_at_state(at, "finalise_block", &(), changes)
}
fn inherent_extrinsics<InherentExtrinsic: Encode + Decode, UncheckedExtrinsic: Encode + Decode>(
&self, at: &BlockId<Block>, inherent: &InherentExtrinsic
) -> Result<Vec<UncheckedExtrinsic>, Self::Error> {
self.call_api_at(at, "inherent_extrinsics", &(inherent))
}
fn check_inherents<InherentData: Encode + Decode, InherentError: Encode + Decode>(
&self,
at: &BlockId<Block>,
block: &Block,
data: &InherentData
) -> Result<Result<(), InherentError>, Self::Error> {
self.call_api_at(at, "check_inherents", &(block, data))
}
fn random_seed(&self, at: &BlockId<Block>) -> Result<<Block as BlockT>::Hash, Self::Error> {
self.call_api_at(at, "random_seed", &())
}
}
impl<B, E, Block> api::TaggedTransactionQueue<Block> for Client<B, E, Block> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
Block: BlockT<Hash=H256>,
{
type Error = Error;
fn validate_transaction<TransactionValidity: Encode + Decode>(
&self, at: &BlockId<Block>, tx: &<Block as BlockT>::Extrinsic
) -> Result<TransactionValidity, Self::Error> {
self.call_api_at(at, "validate_transaction", &(tx))
}
}
#[cfg(test)]
pub(crate) mod tests {
use std::collections::HashMap;
@@ -1155,14 +1103,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};
use test_client::runtime::{self, Block, Transfer, ClientWithApi, 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::Backend, test_client::Executor, Block>,
test_client::client::Client<test_client::Backend, test_client::Executor, Block, ClientWithApi>,
Vec<H256>,
Vec<(u64, u64, Vec<u8>, Vec<(u64, u32)>)>,
) {
@@ -1234,8 +1182,20 @@ pub(crate) mod tests {
fn client_initialises_from_genesis_ok() {
let client = test_client::new();
assert_eq!(client.call_api::<_, u64>("balance_of", &Keyring::Alice.to_raw_public()).unwrap(), 1000);
assert_eq!(client.call_api::<_, u64>("balance_of", &Keyring::Ferdie.to_raw_public()).unwrap(), 0);
assert_eq!(
client.runtime_api().balance_of(
&BlockId::Number(client.info().unwrap().chain.best_number),
&Keyring::Alice.to_raw_public()
).unwrap(),
1000
);
assert_eq!(
client.runtime_api().balance_of(
&BlockId::Number(client.info().unwrap().chain.best_number),
&Keyring::Ferdie.to_raw_public()
).unwrap(),
0
);
}
#[test]
@@ -1278,8 +1238,20 @@ pub(crate) mod tests {
assert_eq!(client.info().unwrap().chain.best_number, 1);
assert!(client.state_at(&BlockId::Number(1)).unwrap() != client.state_at(&BlockId::Number(0)).unwrap());
assert_eq!(client.call_api::<_, u64>("balance_of", &Keyring::Alice.to_raw_public()).unwrap(), 958);
assert_eq!(client.call_api::<_, u64>("balance_of", &Keyring::Ferdie.to_raw_public()).unwrap(), 42);
assert_eq!(
client.runtime_api().balance_of(
&BlockId::Number(client.info().unwrap().chain.best_number),
&Keyring::Alice.to_raw_public()
).unwrap(),
958
);
assert_eq!(
client.runtime_api().balance_of(
&BlockId::Number(client.info().unwrap().chain.best_number),
&Keyring::Ferdie.to_raw_public()
).unwrap(),
42
);
}
#[test]
+56 -15
View File
@@ -16,60 +16,101 @@
//! Substrate Client and associated logic.
#![cfg_attr(not(feature = "std"), no_std)]
#![warn(missing_docs)]
#![recursion_limit="128"]
#[cfg(feature = "std")]
extern crate substrate_trie as trie;
extern crate parity_codec as codec;
extern crate substrate_primitives as primitives;
extern crate sr_primitives as runtime_primitives;
#[cfg(feature = "std")]
extern crate substrate_state_machine as state_machine;
#[cfg(feature = "std")]
extern crate substrate_consensus_common as consensus;
#[cfg(test)] extern crate substrate_keyring as keyring;
#[cfg(test)] extern crate substrate_test_client as test_client;
#[macro_use] extern crate substrate_telemetry;
#[macro_use] extern crate slog; // needed until we can reexport `slog_info` from `substrate_telemetry`
extern crate sr_version as runtime_version;
extern crate sr_std as rstd;
#[cfg(test)]
extern crate substrate_keyring as keyring;
#[cfg(test)]
extern crate substrate_test_client as test_client;
#[cfg(feature = "std")]
#[macro_use]
extern crate substrate_telemetry;
#[cfg(feature = "std")]
#[macro_use]
extern crate slog; // needed until we can reexport `slog_info` from `substrate_telemetry`
#[cfg(feature = "std")]
extern crate fnv;
#[cfg(feature = "std")]
extern crate futures;
#[cfg(feature = "std")]
extern crate parking_lot;
#[cfg(feature = "std")]
extern crate hash_db;
#[cfg(feature = "std")]
extern crate heapsize;
#[cfg(feature = "std")]
extern crate kvdb;
extern crate sr_api;
#[macro_use] extern crate error_chain;
#[macro_use] extern crate log;
#[cfg_attr(test, macro_use)] extern crate substrate_executor as executor;
#[cfg(test)] #[macro_use] extern crate hex_literal;
#[cfg(test)] extern crate kvdb_memorydb;
#[cfg(feature = "std")]
#[macro_use]
extern crate error_chain;
#[cfg(feature = "std")]
#[macro_use]
extern crate log;
#[cfg(feature = "std")]
#[cfg_attr(test, macro_use)]
extern crate substrate_executor as executor;
#[cfg(test)]
#[macro_use]
extern crate hex_literal;
#[cfg(feature = "std")]
#[cfg(test)]
extern crate kvdb_memorydb;
#[macro_use]
pub mod runtime_api;
#[cfg(feature = "std")]
pub mod error;
#[cfg(feature = "std")]
pub mod blockchain;
#[cfg(feature = "std")]
pub mod backend;
#[cfg(feature = "std")]
pub mod cht;
#[cfg(feature = "std")]
pub mod in_mem;
#[cfg(feature = "std")]
pub mod genesis;
pub mod block_builder;
#[cfg(feature = "std")]
pub mod light;
#[cfg(feature = "std")]
mod leaves;
#[cfg(feature = "std")]
mod call_executor;
#[cfg(feature = "std")]
mod client;
#[cfg(feature = "std")]
mod notifications;
#[cfg(feature = "std")]
pub use blockchain::Info as ChainInfo;
#[cfg(feature = "std")]
pub use call_executor::{CallResult, CallExecutor, LocalCallExecutor};
#[cfg(feature = "std")]
pub use client::{
new_with_backend,
new_in_mem,
BlockBody, BlockStatus, ImportNotifications, FinalityNotifications, BlockchainEvents,
Client, ClientInfo, ChainHead,
};
#[cfg(feature = "std")]
pub use notifications::{StorageEventStream, StorageChangeSet};
#[cfg(feature = "std")]
pub use state_machine::ExecutionStrategy;
#[cfg(feature = "std")]
pub use leaves::LeafSet;
/// Traits for interfacing with the runtime from the client.
pub mod runtime_api {
pub use sr_api::*;
}
+2 -2
View File
@@ -48,11 +48,11 @@ pub fn new_light_backend<B: BlockT, S: BlockchainStorage<B>, F: Fetcher<B>>(bloc
}
/// Create an instance of light client.
pub fn new_light<B, S, F, GS>(
pub fn new_light<B, S, F, GS, RA>(
backend: Arc<Backend<S, F>>,
fetcher: Arc<F>,
genesis_storage: GS,
) -> ClientResult<Client<Backend<S, F>, RemoteCallExecutor<Blockchain<S, F>, F, Blake2Hasher>, B>>
) -> ClientResult<Client<Backend<S, F>, RemoteCallExecutor<Blockchain<S, F>, F, Blake2Hasher>, B, RA>>
where
B: BlockT<Hash=H256>,
S: BlockchainStorage<B>,
@@ -0,0 +1,62 @@
// 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 <http://www.gnu.org/licenses/>.
#[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<Block: BlockT>: 'static + Send + Sync + ConstructRuntimeApi<Block> + ApiExt {
/// Returns the version of the runtime.
fn version(&self, at: &BlockId<Block>) -> Result<RuntimeVersion>;
/// Returns the authorities.
fn authorities(&self, at: &BlockId<Block>) -> Result<Vec<AuthorityId>>;
/// Execute the given block.
fn execute_block(&self, at: &BlockId<Block>, block: &Block) -> Result<()>;
/// Initialise a block with the given header.
fn initialise_block(
&self,
at: &BlockId<Block>,
header: &<Block as BlockT>::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<Block: BlockT> {
/// Returns the version of the runtime.
fn version() -> RuntimeVersion;
/// Returns the authorities.
fn authorities() -> Vec<AuthorityId>;
/// Execute the given block.
fn execute_block(block: Block);
/// Initialise a block with the given header.
fn initialise_block(header: <Block as BlockT>::Header);
}
}
@@ -14,31 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! API's for interfacing with the runtime via native/wasm.
#![cfg_attr(not(feature = "std"), no_std)]
extern crate sr_std as rstd;
extern crate sr_primitives as primitives;
#[doc(hidden)]
pub extern crate parity_codec as codec;
extern crate sr_version as runtime_version;
#[doc(hidden)]
pub use primitives::{traits::Block as BlockT, generic::BlockId, transaction_validity::TransactionValidity, ApplyResult};
use runtime_version::{ApiId, RuntimeVersion};
use rstd::vec::Vec;
#[doc(hidden)]
pub use rstd::slice;
#[doc(hidden)]
pub use codec::{Encode, Decode};
//! Macros for declaring and implementing the runtime APIs.
/// Declare the given API traits.
///
/// # Example:
///
/// ```nocompile
/// decl_apis!{
/// decl_runtime_apis!{
/// pub trait Test<Event> ExtraClientSide<ClientArg> {
/// fn test<AccountId>(event: Event) -> AccountId;
///
@@ -66,11 +49,11 @@ pub use codec::{Encode, Decode};
/// }
/// ```
///
/// The declarations generated in the `runtime` module will be used by `impl_apis!` for implementing
/// 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_apis {
macro_rules! decl_runtime_apis {
(
$(
$( #[$attr:meta] )*
@@ -89,7 +72,7 @@ macro_rules! decl_apis {
)*
) => {
$(
decl_apis!(
decl_runtime_apis!(
@ADD_BLOCK_GENERIC
$( #[$attr] )*
pub trait $name $(< $( $generic_param $( : $generic_bound )* ),* >)* {
@@ -107,7 +90,7 @@ macro_rules! decl_apis {
$( $( $generic_param $( : $generic_bound )* ),* )*
);
)*
decl_apis! {
decl_runtime_apis! {
@GENERATE_RUNTIME_TRAITS
$(
$( #[$attr] )*
@@ -136,7 +119,7 @@ macro_rules! decl_apis {
Block: BlockT
$(, $generic_param_rest:ident $( : $generic_bound_rest:ident )* )*
) => {
decl_apis!(
decl_runtime_apis!(
@ADD_BLOCK_GENERIC
$( #[$attr] )*
pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* {
@@ -149,7 +132,7 @@ macro_rules! decl_apis {
)*
};
Found;
$( $generic_param_parsed $( : $generic_bound_parsed )* , )* Block: $crate::BlockT;
$( $generic_param_parsed $( : $generic_bound_parsed )* , )* Block: $crate::runtime_api::BlockT;
$( $generic_param_rest $( : $generic_bound_rest )* ),*
);
};
@@ -169,7 +152,7 @@ macro_rules! decl_apis {
$generic_param:ident $( : $generic_bound:ident )*
$(, $generic_param_rest:ident $( : $generic_bound_rest:ident )* )*
) => {
decl_apis!(
decl_runtime_apis!(
@ADD_BLOCK_GENERIC
$( #[$attr] )*
pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* {
@@ -200,7 +183,7 @@ macro_rules! decl_apis {
Found;
$( $generic_param_parsed:ident $( : $generic_bound_parsed:path )* ),*;
) => {
decl_apis!(
decl_runtime_apis!(
@GENERATE_RETURN_TYPES
$( #[$attr] )*
pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* {
@@ -231,7 +214,7 @@ macro_rules! decl_apis {
;
$( $generic_param_parsed:ident $( : $generic_bound_parsed:ident )* ),*;
) => {
decl_apis!(
decl_runtime_apis!(
@GENERATE_RETURN_TYPES
$( #[$attr] )*
pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* {
@@ -244,7 +227,7 @@ macro_rules! decl_apis {
)*
};
// We need to add the required generic Block parameter
Block: $crate::BlockT $(, $generic_param_parsed $( : $generic_bound_parsed )* )*;
Block: $crate::runtime_api::BlockT $(, $generic_param_parsed $( : $generic_bound_parsed )* )*;
{};
$( $( $return_ty )*; )*
);
@@ -265,7 +248,7 @@ macro_rules! decl_apis {
$return_ty_current:ty;
$( $( $return_ty_rest:ty )*; )*
) => {
decl_apis!(
decl_runtime_apis!(
@GENERATE_RETURN_TYPES
$( #[$attr] )*
pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* {
@@ -278,7 +261,7 @@ macro_rules! decl_apis {
)*
};
$( $generic_param_parsed $( : $generic_bound_parsed )* ),*;
{ $( $result_return_ty; )* Result<$return_ty_current, Self::Error>; };
{ $( $result_return_ty; )* $crate::error::Result<$return_ty_current>; };
$( $( $return_ty_rest )*; )*
);
};
@@ -298,7 +281,7 @@ macro_rules! decl_apis {
;
$( $( $return_ty_rest:ty )*; )*
) => {
decl_apis!(
decl_runtime_apis!(
@GENERATE_RETURN_TYPES
$( #[$attr] )*
pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* {
@@ -311,7 +294,7 @@ macro_rules! decl_apis {
)*
};
$( $generic_param_parsed $( : $generic_bound_parsed )* ),*;
{ $( $result_return_ty; )* Result<(), Self::Error>; };
{ $( $result_return_ty; )* $crate::error::Result<()>; };
$( $( $return_ty_rest )*; )*
);
};
@@ -329,7 +312,7 @@ macro_rules! decl_apis {
$( $generic_param_parsed:ident $( : $generic_bound_parsed:path )* ),*;
{ $( $result_return_ty:ty; )* };
) => {
decl_apis!(
decl_runtime_apis!(
@GENERATE_CLIENT_TRAITS
$( #[$attr] )*
pub trait $name $(< $( $generic_param_orig $( : $generic_bound_orig )* ),* >)* {
@@ -360,15 +343,14 @@ macro_rules! decl_apis {
{ $( $result_return_ty:ty; )* };
) => {
$( #[$attr] )*
pub trait $name < $( $generic_param_parsed $( : $generic_bound_parsed )* ),* > {
/// The Error type returned by this API.
type Error;
#[cfg(feature = "std")]
pub trait $name < $( $generic_param_parsed $( : $generic_bound_parsed )* ),* > : $crate::runtime_api::Core<Block> {
$( type $client_generic_param $( : $client_generic_bound )*; )*
$(
$( #[$fn_attr] )*
fn $fn_name $( < $( $fn_generic: $crate::Encode + $crate::Decode ),* > )* (
&self, at: &$crate::BlockId<Block> $(, $param_name: $param_type )*
fn $fn_name $( < $( $fn_generic: $crate::runtime_api::Encode + $crate::runtime_api::Decode ),* > )* (
&self, at: &$crate::runtime_api::BlockId<Block> $(, $param_name: $param_type )*
) -> $result_return_ty;
)*
}
@@ -386,7 +368,7 @@ macro_rules! decl_apis {
};
)*
) => {
decl_apis! {
decl_runtime_apis! {
@GENERATE_RUNTIME_TRAITS_WITH_JOINED_GENERICS
$(
$( #[$attr] )*
@@ -427,57 +409,8 @@ macro_rules! decl_apis {
};
}
/// The ApiIds for the various standard runtime APIs.
pub mod id {
use super::ApiId;
/// ApiId for the BlockBuilder trait.
pub const BLOCK_BUILDER: ApiId = *b"blkbuild";
/// ApiId for the TaggedTransactionQueue trait.
pub const TAGGED_TRANSACTION_QUEUE: ApiId = *b"validatx";
/// ApiId for the Metadata trait.
pub const METADATA: ApiId = *b"metadata";
}
decl_apis! {
/// The `Core` api trait that is mandantory for each runtime.
pub trait Core<Block: BlockT, AuthorityId> {
fn version() -> RuntimeVersion;
fn authorities() -> Vec<AuthorityId>;
fn execute_block(block: Block);
}
/// The `Metadata` api trait that returns metadata for the runtime.
pub trait Metadata<Data> {
fn metadata() -> Data;
}
/// The `TaggedTransactionQueue` api trait for interfering with the new transaction queue.
pub trait TaggedTransactionQueue<Block: BlockT> {
fn validate_transaction<TransactionValidity>(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity;
}
/// The `BlockBuilder` api trait that provides required functions for building a block for a runtime.
pub trait BlockBuilder<Block: BlockT> ExtraClientSide <OverlayedChanges> {
/// Initialise a block with the given header.
fn initialise_block(header: <Block as BlockT>::Header) ExtraClientSide(changes: &mut Self::OverlayedChanges);
/// Apply the given extrinsics.
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) ExtraClientSide(changes: &mut Self::OverlayedChanges) -> ApplyResult;
/// Finish the current block.
fn finalise_block() ExtraClientSide(changes: &mut Self::OverlayedChanges) -> <Block as BlockT>::Header;
/// Generate inherent extrinsics.
fn inherent_extrinsics<InherentExtrinsic, UncheckedExtrinsic>(inherent: InherentExtrinsic) -> Vec<UncheckedExtrinsic>;
/// Check that the inherents are valid.
fn check_inherents<InherentData, Error>(block: Block, data: InherentData) -> Result<(), Error>;
/// Generate a random seed.
fn random_seed() -> <Block as BlockT>::Hash;
}
}
/// Implement the given API's for the given runtime.
/// All desired API's need to be implemented in one `impl_apis!` call.
/// 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.
@@ -486,18 +419,17 @@ decl_apis! {
///
/// ```nocompile
/// #[macro_use]
/// extern crate sr_api as runtime_api;
/// extern crate substrate_client as client;
///
/// use runtime_api::runtime::{Core, TaggedTransactionQueue};
/// use client::runtime_api::runtime::{Core, TaggedTransactionQueue};
///
/// impl_apis! {
/// impl Core<Block, AccountId> for Runtime {
/// fn version() -> RuntimeVersion { 1 }
/// fn authorities() -> Vec<AuthorityId> { vec![1] }
/// impl_runtime_apis! {
/// impl Core<Block> for Runtime {
/// fn version() -> RuntimeVersion { unimplemented!() }
/// fn authorities() -> Vec<AuthorityId> { unimplemented!() }
/// fn execute_block(block: Block) {
/// //comment
/// let block = call_arbitrary_code(block);
/// execute(block);
/// unimplemented!()
/// }
/// }
///
@@ -511,7 +443,7 @@ decl_apis! {
/// fn main() {}
/// ```
#[macro_export]
macro_rules! impl_apis {
macro_rules! impl_runtime_apis {
(
impl $trait_name:ident $( < $( $generic:ident ),* > )* for $runtime:ident {
$(
@@ -529,7 +461,7 @@ macro_rules! impl_apis {
}
)*
}
impl_apis! {
impl_runtime_apis! {
$runtime;
$( $fn_name ( $( $arg_name: $arg_ty ),* ); )*;
$( $rest )*
@@ -554,7 +486,7 @@ macro_rules! impl_apis {
}
)*
}
impl_apis! {
impl_runtime_apis! {
$runtime;
$( $fn_name_parsed ( $( $arg_name_parsed: $arg_ty_parsed ),* ); )*
$( $fn_name ( $( $arg_name: $arg_ty ),* ); )*;
@@ -573,7 +505,7 @@ macro_rules! impl_apis {
match method {
$(
stringify!($fn_name) => {
Some({impl_apis! {
Some({impl_runtime_apis! {
@GENERATE_IMPL_CALL
$runtime;
$fn_name;
@@ -594,11 +526,11 @@ macro_rules! impl_apis {
&[0u8; 0]
} else {
unsafe {
$crate::slice::from_raw_parts(input_data, input_len)
$crate::runtime_api::slice::from_raw_parts(input_data, input_len)
}
};
let output = { impl_apis! {
let output = { impl_runtime_apis! {
@GENERATE_IMPL_CALL
$runtime;
$fn_name;
@@ -622,13 +554,13 @@ macro_rules! impl_apis {
$arg_name:ident : $arg_ty:ty;
$input:ident;
) => {
let $arg_name : $arg_ty = match $crate::codec::Decode::decode(&mut $input) {
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::$fn_name($arg_name);
$crate::codec::Encode::encode(&output)
$crate::runtime_api::Encode::encode(&output)
};
(@GENERATE_IMPL_CALL
$runtime:ident;
@@ -636,12 +568,12 @@ macro_rules! impl_apis {
$( $arg_name:ident : $arg_ty:ty ),*;
$input:ident;
) => {
let ( $( $arg_name ),* ) : ($( $arg_ty ),*) = match $crate::codec::Decode::decode(&mut $input) {
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::$fn_name($( $arg_name ),*);
$crate::codec::Encode::encode(&output)
$crate::runtime_api::Encode::encode(&output)
};
}
@@ -0,0 +1,99 @@
// 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 <http://www.gnu.org/licenses/>.
//! All the functionality required for declaring and implementing runtime api's.
//! Core api's are also declared here.
#[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;
use runtime_version::ApiId;
#[doc(hidden)]
pub use rstd::slice;
#[cfg(feature = "std")]
use rstd::result;
#[doc(hidden)]
pub use codec::{Encode, Decode};
#[cfg(feature = "std")]
use error;
mod core;
#[macro_use]
mod macros;
mod traits;
/// Something that can be constructed to a runtime api.
#[cfg(feature = "std")]
pub trait ConstructRuntimeApi<Block: BlockT>: Sized {
/// Construct an instance of the runtime api.
fn construct_runtime_api<'a, T: CallApiAt<Block>>(call: &'a T) -> ApiRef<'a, Self>;
}
/// An extension for the `RuntimeApi`.
#[cfg(feature = "std")]
pub trait ApiExt {
/// The given closure will be called with api instance. Inside the closure any api call is
/// allowed. After doing the api call, the closure is allowed to map the `Result` to a
/// different `Result` type. This can be important, as the internal data structure that keeps
/// track of modifications to the storage, discards changes when the `Result` is an `Err`.
/// On `Ok`, the structure commits the changes to an internal buffer.
fn map_api_result<F: FnOnce(&Self) -> result::Result<R, E>, R, E>(
&self,
map_call: F
) -> result::Result<R, E>;
}
/// Something that can call the runtime api at a given block.
#[cfg(feature = "std")]
pub trait CallApiAt<Block: BlockT> {
/// Calls the given api function with the given encoded arguments at the given block
/// and returns the encoded result.
fn call_api_at(
&self,
at: &BlockId<Block>,
function: &'static str,
args: Vec<u8>,
changes: &mut OverlayedChanges,
initialised_block: &mut Option<BlockId<Block>>,
) -> error::Result<Vec<u8>>;
}
/// The ApiIds for the various standard runtime APIs.
pub mod id {
use super::ApiId;
/// ApiId for the BlockBuilder trait.
pub const BLOCK_BUILDER: ApiId = *b"blkbuild";
/// ApiId for the TaggedTransactionQueue trait.
pub const TAGGED_TRANSACTION_QUEUE: ApiId = *b"validatx";
/// ApiId for the Metadata trait.
pub const METADATA: ApiId = *b"metadata";
}
pub use self::core::*;
pub use self::traits::*;
/// The runtime apis that should be implemented for the `Runtime`.
pub mod runtime {
pub use super::core::runtime::Core;
pub use super::traits::runtime::*;
}
@@ -0,0 +1,35 @@
// 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 <http://www.gnu.org/licenses/>.
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<Block: BlockT> {
/// Validate the given transaction.
fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity;
}
}
+2 -17
View File
@@ -130,22 +130,7 @@ pub trait CompatibleDigestItem: Sized {
fn as_aura_seal(&self) -> Option<(u64, &ed25519::Signature)>;
}
impl CompatibleDigestItem for generic::DigestItem<primitives::H256, u64> {
/// Construct a digest item which is a slot number and a signature on the
/// hash.
fn aura_seal(slot_number: u64, signature: ed25519::Signature) -> Self {
generic::DigestItem::Seal(slot_number, signature)
}
/// If this item is an Aura seal, return the slot number and signature.
fn as_aura_seal(&self) -> Option<(u64, &ed25519::Signature)> {
match self {
generic::DigestItem::Seal(slot, ref sign) => Some((*slot, sign)),
_ => None
}
}
}
impl CompatibleDigestItem for generic::DigestItem<primitives::H256, primitives::AuthorityId> {
impl<Hash, AuthorityId> CompatibleDigestItem for generic::DigestItem<Hash, AuthorityId> {
/// Construct a digest item which is a slot number and a signature on the
/// hash.
fn aura_seal(slot_number: u64, signature: ed25519::Signature) -> Self {
@@ -429,7 +414,7 @@ mod tests {
type Error = client::error::Error;
type TestClient = client::Client<test_client::Backend, test_client::Executor, TestBlock>;
type TestClient = client::Client<test_client::Backend, test_client::Executor, TestBlock, test_client::runtime::ClientWithApi>;
struct DummyFactory(Arc<TestClient>);
struct DummyProposer(u64, Arc<TestClient>);
+12 -10
View File
@@ -41,7 +41,7 @@ extern crate substrate_keyring as keyring;
use futures::prelude::*;
use futures::stream::Fuse;
use futures::sync::mpsc;
use client::{Client, ImportNotifications, backend::Backend, CallExecutor};
use client::{Client, ImportNotifications, backend::Backend, CallExecutor, blockchain::HeaderBackend};
use codec::{Encode, Decode};
use runtime_primitives::traits::{As, NumberFor, Block as BlockT, Header as HeaderT};
use runtime_primitives::generic::BlockId;
@@ -121,9 +121,10 @@ pub trait BlockStatus<Block: BlockT> {
fn block_number(&self, hash: Block::Hash) -> Result<Option<u32>, Error>;
}
impl<B, E, Block: BlockT<Hash=H256>> BlockStatus<Block> for Arc<Client<B, E, Block>> where
impl<B, E, Block: BlockT<Hash=H256>, RA> BlockStatus<Block> for Arc<Client<B, E, Block, RA>> where
B: Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync,
RA: Send + Sync,
NumberFor<Block>: As<u32>,
{
fn block_number(&self, hash: Block::Hash) -> Result<Option<u32>, Error> {
@@ -376,14 +377,14 @@ fn outgoing_messages<Block: BlockT, N: Network>(
}
/// The environment we run GRANDPA in.
pub struct Environment<B, E, Block: BlockT, N: Network> {
inner: Arc<Client<B, E, Block>>,
pub struct Environment<B, E, Block: BlockT, N: Network, RA> {
inner: Arc<Client<B, E, Block, RA>>,
voters: HashMap<AuthorityId, usize>,
config: Config,
network: N,
}
impl<Block: BlockT<Hash=H256>, B, E, N> grandpa::Chain<Block::Hash> for Environment<B, E, Block, N> where
impl<Block: BlockT<Hash=H256>, B, E, N, RA> grandpa::Chain<Block::Hash> for Environment<B, E, Block, N, RA> where
Block: 'static,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static,
@@ -434,12 +435,13 @@ impl<Block: BlockT<Hash=H256>, B, E, N> grandpa::Chain<Block::Hash> for Environm
}
}
impl<B, E, Block: BlockT<Hash=H256>, N> voter::Environment<Block::Hash> for Environment<B, E, Block, N> where
impl<B, E, Block: BlockT<Hash=H256>, N, RA> voter::Environment<Block::Hash> for Environment<B, E, Block, N, RA> where
Block: 'static,
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Send + Sync,
N: Network + 'static,
N::In: 'static,
RA: 'static + Send + Sync,
NumberFor<Block>: As<u32>,
{
type Timer = Box<Future<Item = (), Error = Self::Error>>;
@@ -543,9 +545,9 @@ impl<B, E, Block: BlockT<Hash=H256>, N> voter::Environment<Block::Hash> for Envi
}
/// Run a GRANDPA voter as a task. The returned future should be executed in a tokio runtime.
pub fn run_grandpa<B, E, Block: BlockT<Hash=H256>, N>(
pub fn run_grandpa<B, E: Send + Sync, Block: BlockT<Hash=H256>, N, RA: Send + Sync + 'static>(
config: Config,
client: Arc<Client<B, E, Block>>,
client: Arc<Client<B, E, Block, RA>>,
voters: HashMap<AuthorityId, usize>,
network: N,
) -> Result<impl Future<Item=(),Error=()>,client::error::Error> where
+13 -12
View File
@@ -68,52 +68,53 @@ pub trait Client<Block: BlockT>: Send + Sync {
) -> Result<(NumberFor<Block>, Vec<Vec<u8>>), Error>;
}
impl<B, E, Block> Client<Block> for SubstrateClient<B, E, Block> where
impl<B, E, Block, RA> Client<Block> for SubstrateClient<B, E, Block, RA> where
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
Self: BlockImport<Block, Error=Error>,
Block: BlockT<Hash=H256>,
RA: Send + Sync
{
fn import(&self, block: ImportBlock<Block>, new_authorities: Option<Vec<AuthorityId>>)
-> Result<ImportResult, Error>
{
(self as &SubstrateClient<B, E, Block>).import_block(block, new_authorities)
(self as &SubstrateClient<B, E, Block, RA>).import_block(block, new_authorities)
}
fn info(&self) -> Result<ClientInfo<Block>, Error> {
(self as &SubstrateClient<B, E, Block>).info()
(self as &SubstrateClient<B, E, Block, RA>).info()
}
fn block_status(&self, id: &BlockId<Block>) -> Result<BlockStatus, Error> {
(self as &SubstrateClient<B, E, Block>).block_status(id)
(self as &SubstrateClient<B, E, Block, RA>).block_status(id)
}
fn block_hash(&self, block_number: <Block::Header as HeaderT>::Number) -> Result<Option<Block::Hash>, Error> {
(self as &SubstrateClient<B, E, Block>).block_hash(block_number)
(self as &SubstrateClient<B, E, Block, RA>).block_hash(block_number)
}
fn header(&self, id: &BlockId<Block>) -> Result<Option<Block::Header>, Error> {
(self as &SubstrateClient<B, E, Block>).header(id)
(self as &SubstrateClient<B, E, Block, RA>).header(id)
}
fn body(&self, id: &BlockId<Block>) -> Result<Option<Vec<Block::Extrinsic>>, Error> {
(self as &SubstrateClient<B, E, Block>).body(id)
(self as &SubstrateClient<B, E, Block, RA>).body(id)
}
fn justification(&self, id: &BlockId<Block>) -> Result<Option<Justification>, Error> {
(self as &SubstrateClient<B, E, Block>).justification(id)
(self as &SubstrateClient<B, E, Block, RA>).justification(id)
}
fn header_proof(&self, block_number: <Block::Header as HeaderT>::Number) -> Result<(Block::Header, Vec<Vec<u8>>), Error> {
(self as &SubstrateClient<B, E, Block>).header_proof(&BlockId::Number(block_number))
(self as &SubstrateClient<B, E, Block, RA>).header_proof(&BlockId::Number(block_number))
}
fn read_proof(&self, block: &Block::Hash, key: &[u8]) -> Result<Vec<Vec<u8>>, Error> {
(self as &SubstrateClient<B, E, Block>).read_proof(&BlockId::Hash(block.clone()), key)
(self as &SubstrateClient<B, E, Block, RA>).read_proof(&BlockId::Hash(block.clone()), key)
}
fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec<u8>, Vec<Vec<u8>>), Error> {
(self as &SubstrateClient<B, E, Block>).execution_proof(&BlockId::Hash(block.clone()), method, data)
(self as &SubstrateClient<B, E, Block, RA>).execution_proof(&BlockId::Hash(block.clone()), method, data)
}
fn key_changes_proof(
@@ -123,6 +124,6 @@ impl<B, E, Block> Client<Block> for SubstrateClient<B, E, Block> where
max: Block::Hash,
key: &[u8]
) -> Result<(NumberFor<Block>, Vec<Vec<u8>>), Error> {
(self as &SubstrateClient<B, E, Block>).key_changes_proof(first, last, max, key)
(self as &SubstrateClient<B, E, Block, RA>).key_changes_proof(first, last, max, key)
}
}
+1 -1
View File
@@ -677,7 +677,7 @@ pub mod tests {
fn restart(&mut self) { self.restarts += 1; }
}
fn prepare_good_block() -> (client::Client<test_client::Backend, test_client::Executor, Block>, Hash, u64, BlockData<Block>) {
fn prepare_good_block() -> (client::Client<test_client::Backend, test_client::Executor, Block, test_client::runtime::ClientWithApi>, Hash, u64, BlockData<Block>) {
let client = test_client::new();
let block = client.new_block().unwrap().bake().unwrap();
client.justify_and_import(BlockOrigin::File, block).unwrap();
+4 -5
View File
@@ -28,7 +28,6 @@ use client::block_builder::BlockBuilder;
use runtime_primitives::generic::BlockId;
use io::SyncIo;
use protocol::{Context, Protocol, ProtocolContext};
use primitives::{Blake2Hasher};
use config::ProtocolConfig;
use service::TransactionPool;
use network_libp2p::{NodeIndex, PeerId, Severity};
@@ -137,7 +136,7 @@ pub struct TestPacket {
recipient: NodeIndex,
}
pub type PeersClient = client::Client<test_client::Backend, test_client::Executor, Block>;
pub type PeersClient = client::Client<test_client::Backend, test_client::Executor, Block, test_client::runtime::ClientWithApi>;
pub struct Peer<V: Verifier<Block>> {
client: Arc<PeersClient>,
@@ -230,7 +229,7 @@ impl<V: 'static + Verifier<Block>> Peer<V> {
/// Add blocks to the peer -- edit the block before adding
pub fn generate_blocks<F>(&self, count: usize, origin: BlockOrigin, mut edit_block: F)
where F: FnMut(&mut BlockBuilder<test_client::Backend, test_client::Executor, Block, Blake2Hasher>)
where F: FnMut(&mut BlockBuilder<Block, PeersClient>)
{
for _ in 0 .. count {
let mut builder = self.client.new_block().unwrap();
@@ -305,7 +304,7 @@ pub trait TestNetFactory: Sized {
fn mut_peers<F: Fn(&mut Vec<Arc<Peer<Self::Verifier>>>)>(&mut self, closure: F );
fn started(&self) -> bool;
fn set_started(&mut self, now: bool);
fn set_started(&mut self, now: bool);
fn default_config() -> ProtocolConfig {
ProtocolConfig::default()
@@ -468,7 +467,7 @@ impl TestNetFactory for TestNet {
started: false
}
}
fn make_verifier(&self, _client: Arc<PeersClient>, _config: &ProtocolConfig)
-> Arc<Self::Verifier>
{
+23
View File
@@ -129,7 +129,30 @@ impl From<Vec<u8>> for Bytes {
fn from(s: Vec<u8>) -> Self { Bytes(s) }
}
impl From<OpaqueMetadata> for Bytes {
fn from(s: OpaqueMetadata) -> Self { Bytes(s.0) }
}
impl Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &[u8] { &self.0[..] }
}
/// Stores the encoded `RuntimeMetadata` for the native side as opaque type.
#[derive(Encode, Decode)]
pub struct OpaqueMetadata(Vec<u8>);
impl OpaqueMetadata {
/// Creates a new instance with the given metadata blob.
pub fn new(metadata: Vec<u8>) -> Self {
OpaqueMetadata(metadata)
}
}
impl rstd::ops::Deref for OpaqueMetadata {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
+6 -9
View File
@@ -71,23 +71,19 @@ build_rpc_trait! {
}
/// Authoring API
pub struct Author<B, E, P> where
P: PoolChainApi + Sync + Send + 'static,
{
pub struct Author<B, E, P, RA> where P: PoolChainApi + Sync + Send + 'static {
/// Substrate client
client: Arc<Client<B, E, <P as PoolChainApi>::Block>>,
client: Arc<Client<B, E, <P as PoolChainApi>::Block, RA>>,
/// Extrinsic pool
pool: Arc<Pool<P>>,
/// Subscriptions manager
subscriptions: Subscriptions,
}
impl<B, E, P> Author<B, E, P> where
P: PoolChainApi + Sync + Send + 'static,
{
impl<B, E, P, RA> Author<B, E, P, RA> where P: PoolChainApi + Sync + Send + 'static {
/// Create new instance of Authoring API.
pub fn new(
client: Arc<Client<B, E, <P as PoolChainApi>::Block>>,
client: Arc<Client<B, E, <P as PoolChainApi>::Block, RA>>,
pool: Arc<Pool<P>>,
subscriptions: Subscriptions,
) -> Self {
@@ -99,12 +95,13 @@ impl<B, E, P> Author<B, E, P> where
}
}
impl<B, E, P> AuthorApi<ExHash<P>, BlockHash<P>> for Author<B, E, P> where
impl<B, E, P, RA> AuthorApi<ExHash<P>, BlockHash<P>> for Author<B, E, P, RA> where
B: client::backend::Backend<<P as PoolChainApi>::Block, Blake2Hasher> + Send + Sync + 'static,
E: client::CallExecutor<<P as PoolChainApi>::Block, Blake2Hasher> + Send + Sync + 'static,
P: PoolChainApi + Sync + Send + 'static,
P::Block: traits::Block<Hash=H256>,
P::Error: 'static,
RA: Send + Sync + 'static
{
type Metadata = ::metadata::Metadata;
+8 -6
View File
@@ -97,16 +97,16 @@ build_rpc_trait! {
}
/// Chain API with subscriptions support.
pub struct Chain<B, E, Block: BlockT> {
pub struct Chain<B, E, Block: BlockT, RA> {
/// Substrate client.
client: Arc<Client<B, E, Block>>,
client: Arc<Client<B, E, Block, RA>>,
/// Current subscriptions.
subscriptions: Subscriptions,
}
impl<B, E, Block: BlockT> Chain<B, E, Block> {
impl<B, E, Block: BlockT, RA> Chain<B, E, Block, RA> {
/// Create new Chain API RPC handler.
pub fn new(client: Arc<Client<B, E, Block>>, subscriptions: Subscriptions) -> Self {
pub fn new(client: Arc<Client<B, E, Block, RA>>, subscriptions: Subscriptions) -> Self {
Self {
client,
subscriptions,
@@ -114,10 +114,11 @@ impl<B, E, Block: BlockT> Chain<B, E, Block> {
}
}
impl<B, E, Block> Chain<B, E, Block> where
impl<B, E, Block, RA> Chain<B, E, Block, RA> where
Block: BlockT<Hash=H256> + 'static,
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: client::CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
RA: Send + Sync + 'static
{
fn unwrap_or_best(&self, hash: Trailing<Block::Hash>) -> Result<Block::Hash> {
Ok(match hash.into() {
@@ -163,10 +164,11 @@ impl<B, E, Block> Chain<B, E, Block> where
}
}
impl<B, E, Block> ChainApi<Block::Hash, Block::Header, NumberFor<Block>, SignedBlock<Block>> for Chain<B, E, Block> where
impl<B, E, Block, RA> ChainApi<Block::Hash, Block::Header, NumberFor<Block>, SignedBlock<Block>> for Chain<B, E, Block, RA> where
Block: BlockT<Hash=H256> + 'static,
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: client::CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
RA: Send + Sync + 'static
{
type Metadata = ::metadata::Metadata;
+10 -9
View File
@@ -32,7 +32,7 @@ use primitives::{Blake2Hasher, Bytes};
use rpc::Result as RpcResult;
use rpc::futures::{stream, Future, Sink, Stream};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Block as BlockT, Header};
use runtime_primitives::traits::{Block as BlockT, Header, ProvideRuntimeApi};
use subscriptions::Subscriptions;
@@ -87,16 +87,16 @@ build_rpc_trait! {
}
/// State API with subscriptions support.
pub struct State<B, E, Block: BlockT> {
pub struct State<B, E, Block: BlockT, RA> {
/// Substrate client.
client: Arc<Client<B, E, Block>>,
client: Arc<Client<B, E, Block, RA>>,
/// Current subscriptions.
subscriptions: Subscriptions,
}
impl<B, E, Block: BlockT> State<B, E, Block> {
impl<B, E, Block: BlockT, RA> State<B, E, Block, RA> {
/// Create new State API RPC handler.
pub fn new(client: Arc<Client<B, E, Block>>, subscriptions: Subscriptions) -> Self {
pub fn new(client: Arc<Client<B, E, Block, RA>>, subscriptions: Subscriptions) -> Self {
Self {
client,
subscriptions,
@@ -104,7 +104,7 @@ impl<B, E, Block: BlockT> State<B, E, Block> {
}
}
impl<B, E, Block> State<B, E, Block> where
impl<B, E, Block, RA> State<B, E, Block, RA> where
Block: BlockT<Hash=H256>,
B: client::backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
@@ -114,10 +114,11 @@ impl<B, E, Block> State<B, E, Block> where
}
}
impl<B, E, Block> StateApi<Block::Hash> for State<B, E, Block> where
impl<B, E, Block, RA> StateApi<Block::Hash> for State<B, E, Block, RA> where
Block: BlockT<Hash=H256> + 'static,
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static + Clone,
RA: Metadata<Block>
{
type Metadata = ::metadata::Metadata;
@@ -151,7 +152,7 @@ impl<B, E, Block> StateApi<Block::Hash> for State<B, E, Block> where
fn metadata(&self, block: Trailing<Block::Hash>) -> Result<Bytes> {
let block = self.unwrap_or_best(block)?;
self.client.metadata(&BlockId::Hash(block)).map(Bytes).map_err(Into::into)
self.client.runtime_api().metadata(&BlockId::Hash(block)).map(Into::into).map_err(Into::into)
}
fn query_storage(&self, keys: Vec<StorageKey>, from: Block::Hash, to: Trailing<Block::Hash>) -> Result<Vec<StorageChangeSet<Block::Hash>>> {
+186 -22
View File
@@ -16,21 +16,20 @@
//! Substrate service components.
use std::sync::Arc;
use std::marker::PhantomData;
use std::ops::Deref;
use std::{sync::Arc, net::SocketAddr, marker::PhantomData, ops::Deref};
use serde::{Serialize, de::DeserializeOwned};
use tokio::runtime::TaskExecutor;
use chain_spec::ChainSpec;
use chain_spec::{ChainSpec, Properties};
use client_db;
use client::{self, Client};
use {error, Service};
use client::{self, Client, runtime_api::{TaggedTransactionQueue, Metadata}};
use {error, Service, RpcConfig, maybe_start_server, TransactionPoolAdapter};
use network::{self, OnDemand, import_queue::ImportQueue};
use substrate_executor::{NativeExecutor, NativeExecutionDispatch};
use transaction_pool::txpool::{self, Options as TransactionPoolOptions, Pool as TransactionPool};
use runtime_primitives::{traits::Block as BlockT, traits::Header as HeaderT, BuildStorage};
use runtime_primitives::{traits::Block as BlockT, traits::Header as HeaderT, BuildStorage, generic::SignedBlock};
use config::Configuration;
use primitives::{H256, Blake2Hasher};
use primitives::{Blake2Hasher, H256};
use rpc;
// Type aliases.
// These exist mainly to avoid typing `<F as Factory>::Foo` all over the code.
@@ -70,10 +69,10 @@ pub type LightExecutor<F> = client::light::call_executor::RemoteCallExecutor<
>;
/// Full client type for a factory.
pub type FullClient<F> = Client<FullBackend<F>, FullExecutor<F>, <F as ServiceFactory>::Block>;
pub type FullClient<F> = Client<FullBackend<F>, FullExecutor<F>, <F as ServiceFactory>::Block, <F as ServiceFactory>::RuntimeApi>;
/// Light client type for a factory.
pub type LightClient<F> = Client<LightBackend<F>, LightExecutor<F>, <F as ServiceFactory>::Block>;
pub type LightClient<F> = Client<LightBackend<F>, LightExecutor<F>, <F as ServiceFactory>::Block, <F as ServiceFactory>::RuntimeApi>;
/// `ChainSpec` specialization for a factory.
pub type FactoryChainSpec<F> = ChainSpec<<F as ServiceFactory>::Genesis>;
@@ -97,7 +96,8 @@ pub type FactoryFullConfiguration<F> = Configuration<<F as ServiceFactory>::Conf
pub type ComponentClient<C> = Client<
<C as Components>::Backend,
<C as Components>::Executor,
FactoryBlock<<C as Components>::Factory>
FactoryBlock<<C as Components>::Factory>,
<C as Components>::RuntimeApi,
>;
/// Block type for `Components`
@@ -116,10 +116,114 @@ pub type PoolApi<C> = <C as Components>::TransactionPoolApi;
pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {}
impl<T: Serialize + DeserializeOwned + BuildStorage> RuntimeGenesis for T {}
/// Something that can start the RPC service.
pub trait StartRPC<C: Components> {
fn start_rpc(
client: Arc<Client<C::Backend, C::Executor, ComponentBlock<C>, C::RuntimeApi>>,
chain_name: String,
impl_name: &'static str,
impl_version: &'static str,
rpc_http: Option<SocketAddr>,
rpc_ws: Option<SocketAddr>,
properties: Properties,
task_executor: TaskExecutor,
transaction_pool: Arc<TransactionPool<C::TransactionPoolApi>>,
) -> Result<(Option<rpc::HttpServer>, Option<rpc::WsServer>), error::Error>;
}
impl<T: Components> StartRPC<Self> for T where
T::RuntimeApi: Metadata<ComponentBlock<T>>,
for<'de> SignedBlock<ComponentBlock<T>>: ::serde::Deserialize<'de>,
{
fn start_rpc(
client: Arc<Client<T::Backend, T::Executor, ComponentBlock<T>, T::RuntimeApi>>,
chain_name: String,
impl_name: &'static str,
impl_version: &'static str,
rpc_http: Option<SocketAddr>,
rpc_ws: Option<SocketAddr>,
properties: Properties,
task_executor: TaskExecutor,
transaction_pool: Arc<TransactionPool<T::TransactionPoolApi>>,
) -> Result<(Option<rpc::HttpServer>, Option<rpc::WsServer>), error::Error> {
let rpc_config = RpcConfig { properties, chain_name, impl_name, impl_version };
let handler = || {
let client = client.clone();
let subscriptions = rpc::apis::Subscriptions::new(task_executor.clone());
let chain = rpc::apis::chain::Chain::new(client.clone(), subscriptions.clone());
let state = rpc::apis::state::State::new(client.clone(), subscriptions.clone());
let author = rpc::apis::author::Author::new(
client.clone(), transaction_pool.clone(), subscriptions
);
rpc::rpc_handler::<ComponentBlock<T>, ComponentExHash<T>, _, _, _, _>(
state,
chain,
author,
rpc_config.clone(),
)
};
Ok((
maybe_start_server(rpc_http, |address| rpc::start_http(address, handler()))?,
maybe_start_server(rpc_ws, |address| rpc::start_ws(address, handler()))?,
))
}
}
/// Something that can create an instance of `network::Params`.
pub trait CreateNetworkParams<C: Components> {
fn create_network_params<S>(
client: Arc<Client<C::Backend, C::Executor, ComponentBlock<C>, C::RuntimeApi>>,
roles: network::Roles,
network_config: network::NetworkConfiguration,
on_demand: Option<Arc<OnDemand<FactoryBlock<C::Factory>, NetworkService<C::Factory>>>>,
transaction_pool_adapter: TransactionPoolAdapter<C>,
specialization: S,
) -> network::Params<ComponentBlock<C>, S, ComponentExHash<C>>;
}
impl<T: Components> CreateNetworkParams<Self> for T where
T::RuntimeApi: TaggedTransactionQueue<ComponentBlock<T>>
{
fn create_network_params<S>(
client: Arc<Client<T::Backend, T::Executor, ComponentBlock<T>, T::RuntimeApi>>,
roles: network::Roles,
network_config: network::NetworkConfiguration,
on_demand: Option<Arc<OnDemand<FactoryBlock<T::Factory>, NetworkService<T::Factory>>>>,
transaction_pool_adapter: TransactionPoolAdapter<T>,
specialization: S,
) -> network::Params<ComponentBlock<T>, S, ComponentExHash<T>> {
network::Params {
config: network::ProtocolConfig { roles },
network_config,
chain: client,
on_demand: on_demand.map(|d| d as Arc<network::OnDemandService<ComponentBlock<T>>>),
transaction_pool: Arc::new(transaction_pool_adapter),
specialization,
}
}
}
/// The super trait that combines all required traits a `Service` needs to implement.
pub trait ServiceTrait<C: Components>:
Deref<Target = Service<C>>
+ Send
+ Sync
+ 'static
+ StartRPC<C>
+ CreateNetworkParams<C>
{}
impl<C: Components, T> ServiceTrait<C> for T where
T: Deref<Target = Service<C>> + Send + Sync + 'static + StartRPC<C> + CreateNetworkParams<C>
{}
/// A collection of types and methods to build a service on top of the substrate service.
pub trait ServiceFactory: 'static + Sized {
/// Block type.
type Block: BlockT<Hash=H256>;
/// The type that implements the runtime API.
type RuntimeApi: Send + Sync;
/// Network protocol extensions.
type NetworkProtocol: network::specialization::Specialization<Self::Block>;
/// Chain runtime.
@@ -133,9 +237,9 @@ pub trait ServiceFactory: 'static + Sized {
/// Other configuration for service members.
type Configuration: Default;
/// Extended full service type.
type FullService: Deref<Target = Service<FullComponents<Self>>> + Send + Sync + 'static;
type FullService: ServiceTrait<FullComponents<Self>>;
/// Extended light service type.
type LightService: Deref<Target = Service<LightComponents<Self>>> + Send + Sync + 'static;
type LightService: ServiceTrait<LightComponents<Self>>;
/// ImportQueue for full client
type FullImportQueue: network::import_queue::ImportQueue<Self::Block> + 'static;
/// ImportQueue for light clients
@@ -192,7 +296,7 @@ pub trait ServiceFactory: 'static + Sized {
}
/// A collection of types and function to generalise over full / light client type.
pub trait Components: 'static {
pub trait Components: Sized + 'static {
/// Associated service factory.
type Factory: ServiceFactory;
/// Client backend.
@@ -204,6 +308,12 @@ pub trait Components: 'static {
Hash = <<Self::Factory as ServiceFactory>::Block as BlockT>::Hash,
Block = FactoryBlock<Self::Factory>
>;
/// The type that implements the runtime API.
type RuntimeApi: Send + Sync;
/// A type that can start the RPC.
type RPC: StartRPC<Self>;
/// A type that can create the network params.
type CreateNetworkParams: CreateNetworkParams<Self>;
/// Our Import Queue
type ImportQueue: ImportQueue<FactoryBlock<Self::Factory>> + 'static;
@@ -212,11 +322,13 @@ pub trait Components: 'static {
fn build_client(
config: &FactoryFullConfiguration<Self::Factory>,
executor: CodeExecutor<Self::Factory>,
)
-> Result<(
) -> Result<
(
Arc<ComponentClient<Self>>,
Option<Arc<OnDemand<FactoryBlock<Self::Factory>, NetworkService<Self::Factory>>>>
), error::Error>;
),
error::Error
>;
/// Create extrinsic pool.
fn build_transaction_pool(config: TransactionPoolOptions, client: Arc<ComponentClient<Self>>)
@@ -232,6 +344,29 @@ pub trait Components: 'static {
/// A struct that implement `Components` for the full client.
pub struct FullComponents<Factory: ServiceFactory> {
_factory: PhantomData<Factory>,
service: Service<FullComponents<Factory>>,
}
impl<Factory: ServiceFactory> FullComponents<Factory> {
pub fn new(
config: FactoryFullConfiguration<Factory>,
task_executor: TaskExecutor
) -> Result<Self, error::Error> {
Ok(
Self {
_factory: Default::default(),
service: Service::new(config, task_executor)?,
}
)
}
}
impl<Factory: ServiceFactory> Deref for FullComponents<Factory> {
type Target = Service<Self>;
fn deref(&self) -> &Self::Target {
&self.service
}
}
impl<Factory: ServiceFactory> Components for FullComponents<Factory> {
@@ -240,6 +375,9 @@ impl<Factory: ServiceFactory> Components for FullComponents<Factory> {
type Backend = FullBackend<Factory>;
type TransactionPoolApi = <Factory as ServiceFactory>::FullTransactionPoolApi;
type ImportQueue = Factory::FullImportQueue;
type RuntimeApi = Factory::RuntimeApi;
type RPC = Factory::FullService;
type CreateNetworkParams = Factory::FullService;
fn build_client(
config: &FactoryFullConfiguration<Factory>,
@@ -281,6 +419,29 @@ impl<Factory: ServiceFactory> Components for FullComponents<Factory> {
/// A struct that implement `Components` for the light client.
pub struct LightComponents<Factory: ServiceFactory> {
_factory: PhantomData<Factory>,
service: Service<LightComponents<Factory>>,
}
impl<Factory: ServiceFactory> LightComponents<Factory> {
pub fn new(
config: FactoryFullConfiguration<Factory>,
task_executor: TaskExecutor
) -> Result<Self, error::Error> {
Ok(
Self {
_factory: Default::default(),
service: Service::new(config, task_executor)?,
}
)
}
}
impl<Factory: ServiceFactory> Deref for LightComponents<Factory> {
type Target = Service<Self>;
fn deref(&self) -> &Self::Target {
&self.service
}
}
impl<Factory: ServiceFactory> Components for LightComponents<Factory> {
@@ -289,16 +450,19 @@ impl<Factory: ServiceFactory> Components for LightComponents<Factory> {
type Backend = LightBackend<Factory>;
type TransactionPoolApi = <Factory as ServiceFactory>::LightTransactionPoolApi;
type ImportQueue = <Factory as ServiceFactory>::LightImportQueue;
type RuntimeApi = Factory::RuntimeApi;
type RPC = Factory::LightService;
type CreateNetworkParams = Factory::LightService;
fn build_client(
config: &FactoryFullConfiguration<Factory>,
executor: CodeExecutor<Self::Factory>,
)
-> Result<(
Arc<ComponentClient<Self>>,
Option<Arc<OnDemand<FactoryBlock<Self::Factory>,
NetworkService<Self::Factory>>>>
), error::Error>
-> Result<
(
Arc<ComponentClient<Self>>,
Option<Arc<OnDemand<FactoryBlock<Self::Factory>, NetworkService<Self::Factory>>>>
), error::Error>
{
let db_settings = client_db::DatabaseSettings {
cache_size: None,
+23 -24
View File
@@ -23,11 +23,11 @@ use std::time::{self, Duration, Instant};
use std;
use client::{self, error, Client as SubstrateClient, CallExecutor};
use client::runtime_api::{Core, BlockBuilder as BlockBuilderAPI, id::BLOCK_BUILDER};
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 primitives::{H256, AuthorityId, ed25519, Blake2Hasher};
use runtime_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT};
use runtime_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi};
use runtime_primitives::generic::BlockId;
use transaction_pool::txpool::{self, Pool as TransactionPool};
@@ -47,11 +47,8 @@ pub trait BlockBuilder<Block: BlockT> {
}
/// Local client abstraction for the consensus.
pub trait AuthoringApi:
Send
+ Sync
+ BlockBuilderAPI<<Self as AuthoringApi>::Block, Error=<Self as AuthoringApi>::Error>
+ Core<<Self as AuthoringApi>::Block, AuthorityId, Error=<Self as AuthoringApi>::Error>
pub trait AuthoringApi: Send + Sync + ProvideRuntimeApi where
<Self as ProvideRuntimeApi>::Api: Core<Self::Block>
{
/// The block used for this API type.
type Block: BlockT;
@@ -67,20 +64,22 @@ pub trait AuthoringApi:
) -> Result<Self::Block, error::Error>;
}
impl<'a, B, E, Block> BlockBuilder<Block> for client::block_builder::BlockBuilder<'a, B, E, Block, Blake2Hasher> where
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
impl<'a, B, E, Block, RA> BlockBuilder<Block> for client::block_builder::BlockBuilder<'a, Block, SubstrateClient<B, E, Block, RA>> where
B: client::backend::Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT<Hash=H256>,
RA: BlockBuilderApi<Block>,
{
fn push_extrinsic(&mut self, extrinsic: <Block as BlockT>::Extrinsic) -> Result<(), error::Error> {
client::block_builder::BlockBuilder::push(self, extrinsic).map_err(Into::into)
}
}
impl<'a, B, E, Block> AuthoringApi for SubstrateClient<B, E, Block> where
impl<B, E, Block, RA> AuthoringApi for SubstrateClient<B, E, Block, RA> where
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
Block: BlockT<Hash=H256>,
RA: BlockBuilderApi<Block>,
{
type Block = Block;
type Error = client::error::Error;
@@ -95,7 +94,7 @@ impl<'a, B, E, Block> AuthoringApi for SubstrateClient<B, E, Block> where
let mut block_builder = self.new_block_at(at)?;
if runtime_version.has_api(BLOCK_BUILDER, 1) {
self.inherent_extrinsics(at, &inherent_data)?
self.runtime_api().inherent_extrinsics(at, &inherent_data)?
.into_iter().try_for_each(|i| block_builder.push(i))?;
}
@@ -106,10 +105,7 @@ impl<'a, B, E, Block> AuthoringApi for SubstrateClient<B, E, Block> where
}
/// Proposer factory.
pub struct ProposerFactory<C, A> where
C: AuthoringApi,
A: txpool::ChainApi,
{
pub struct ProposerFactory<C, A> where A: txpool::ChainApi {
/// The client instance.
pub client: Arc<C>,
/// The transaction pool.
@@ -122,10 +118,11 @@ pub struct ProposerFactory<C, A> where
impl<C, A> consensus_common::Environment<<C as AuthoringApi>::Block> for ProposerFactory<C, A> where
C: AuthoringApi,
<C as ProvideRuntimeApi>::Api: BlockBuilderApi<<C as AuthoringApi>::Block>,
A: txpool::ChainApi<Block=<C as AuthoringApi>::Block>,
client::error::Error: From<<C as AuthoringApi>::Error>
{
type Proposer = Proposer<C, A>;
type Proposer = Proposer<<C as AuthoringApi>::Block, C, A>;
type Error = error::Error;
fn init(
@@ -138,7 +135,7 @@ impl<C, A> consensus_common::Environment<<C as AuthoringApi>::Block> for Propose
let id = BlockId::hash(parent_hash);
let authorities: Vec<AuthorityId> = self.client.authorities(&id)?;
let authorities: Vec<AuthorityId> = self.client.runtime_api().authorities(&id)?;
self.offline.write().note_new_block(&authorities[..]);
info!("Starting consensus session on top of parent {:?}", parent_hash);
@@ -161,21 +158,23 @@ impl<C, A> consensus_common::Environment<<C as AuthoringApi>::Block> for Propose
}
/// The proposer logic.
pub struct Proposer<C: AuthoringApi, A: txpool::ChainApi> {
pub struct Proposer<Block: BlockT, C, A: txpool::ChainApi> {
client: Arc<C>,
start: Instant,
parent_hash: <<C as AuthoringApi>::Block as BlockT>::Hash,
parent_id: BlockId<<C as AuthoringApi>::Block>,
parent_number: <<<C as AuthoringApi>::Block as BlockT>::Header as HeaderT>::Number,
parent_hash: <Block as BlockT>::Hash,
parent_id: BlockId<Block>,
parent_number: <<Block as BlockT>::Header as HeaderT>::Number,
transaction_pool: Arc<TransactionPool<A>>,
offline: SharedOfflineTracker,
authorities: Vec<AuthorityId>,
minimum_timestamp: u64,
}
impl<C, A> consensus_common::Proposer<<C as AuthoringApi>::Block> for Proposer<C, A> where
C: AuthoringApi,
A: txpool::ChainApi<Block=<C as AuthoringApi>::Block>,
impl<Block, C, A> consensus_common::Proposer<<C as AuthoringApi>::Block> for Proposer<Block, C, A> where
Block: BlockT,
C: AuthoringApi<Block=Block>,
<C as ProvideRuntimeApi>::Api: BlockBuilderApi<Block>,
A: txpool::ChainApi<Block=Block>,
client::error::Error: From<<C as AuthoringApi>::Error>
{
type Create = Result<<C as AuthoringApi>::Block, error::Error>;
+20 -79
View File
@@ -67,7 +67,7 @@ use parking_lot::{Mutex, RwLock};
use keystore::Store as Keystore;
use client::BlockchainEvents;
use runtime_primitives::traits::{Header, As};
use runtime_primitives::generic::{BlockId, SignedBlock};
use runtime_primitives::generic::BlockId;
use exit_future::Signal;
#[doc(hidden)]
pub use tokio::runtime::TaskExecutor;
@@ -87,8 +87,11 @@ pub use components::{ServiceFactory, FullBackend, FullExecutor, LightBackend,
ComponentBlock, FullClient, LightClient, FullComponents, LightComponents,
CodeExecutor, NetworkService, FactoryChainSpec, FactoryBlock,
FactoryFullConfiguration, RuntimeGenesis, FactoryGenesis,
ComponentExHash, ComponentExtrinsic, FactoryExtrinsic,
ComponentExHash, ComponentExtrinsic, FactoryExtrinsic
};
use components::{StartRPC, CreateNetworkParams};
#[doc(hidden)]
pub use network::OnDemand;
const DEFAULT_PROTOCOL_ID: &'static str = "sup";
@@ -122,7 +125,7 @@ impl<Components> Service<Components>
where
Components: components::Components,
<Components as components::Components>::Executor: std::clone::Clone,
for<'de> SignedBlock<ComponentBlock<Components>>: ::serde::Deserialize<'de>,
// <Components as components::Components>::RuntimeApi: client::runtime_api::BlockBuilder<<<Components as components::Components>::Factory as ServiceFactory>::Block, Error=client::error::Error, OverlayedChanges=client::runtime_api::OverlayedChanges> + Sync + Send + client::runtime_api::Core<<<Components as components::Components>::Factory as components::ServiceFactory>::Block, primitives::AuthorityId, Error=client::error::Error, OverlayedChanges=client::runtime_api::OverlayedChanges> + client::runtime_api::ConstructRuntimeApi<Block=<<Components as components::Components>::Factory as ServiceFactory>::Block> + client::runtime_api::Metadata<<<Components as components::Components>::Factory as components::ServiceFactory>::Block, Vec<u8>, Error=client::error::Error> + client::runtime_api::TaggedTransactionQueue<<<Components as components::Components>::Factory as components::ServiceFactory>::Block, Error=client::error::Error>,
{
/// Creates a new service.
pub fn new(
@@ -173,17 +176,10 @@ impl<Components> Service<Components>
client: client.clone(),
};
let network_params = network::Params {
config: network::ProtocolConfig {
roles: config.roles,
},
network_config: config.network,
chain: client.clone(),
on_demand: on_demand.clone()
.map(|d| d as Arc<network::OnDemandService<ComponentBlock<Components>>>),
transaction_pool: Arc::new(transaction_pool_adapter),
specialization: network_protocol,
};
let network_params = Components::CreateNetworkParams::create_network_params(
client.clone(), config.roles, config.network, on_demand.clone(),
transaction_pool_adapter, network_protocol
);
let mut protocol_id = network::ProtocolId::default();
let protocol_id_full = config.chain_spec.protocol_id().unwrap_or(DEFAULT_PROTOCOL_ID).as_bytes();
@@ -232,33 +228,13 @@ impl<Components> Service<Components>
task_executor.spawn(events);
}
// RPC
let rpc_config = RpcConfig {
chain_name: config.chain_spec.name().to_string(),
properties: config.chain_spec.properties().clone(),
impl_name: config.impl_name,
impl_version: config.impl_version,
};
let (rpc_http, rpc_ws) = {
let handler = || {
let client = client.clone();
let subscriptions = rpc::apis::Subscriptions::new(task_executor.clone());
let chain = rpc::apis::chain::Chain::new(client.clone(), subscriptions.clone());
let state = rpc::apis::state::State::new(client.clone(), subscriptions.clone());
let author = rpc::apis::author::Author::new(client.clone(), transaction_pool.clone(), subscriptions.clone());
rpc::rpc_handler::<ComponentBlock<Components>, ComponentExHash<Components>, _, _, _, _>(
state,
chain,
author,
rpc_config.clone(),
)
};
(
maybe_start_server(config.rpc_http, |address| rpc::start_http(address, handler()))?,
maybe_start_server(config.rpc_ws, |address| rpc::start_ws(address, handler()))?,
)
};
// RPC
let (rpc_http, rpc_ws) = Components::RPC::start_rpc(
client.clone(), config.chain_spec.name().to_string(), config.impl_name,
config.impl_version, config.rpc_http, config.rpc_ws, config.chain_spec.properties(),
task_executor.clone(), transaction_pool.clone()
)?;
let proposer = Arc::new(ProposerFactory {
client: client.clone(),
@@ -309,9 +285,7 @@ impl<Components> Service<Components>
}
}
impl<Components> Service<Components> where
Components: components::Components,
{
impl<Components> Service<Components> where Components: components::Components {
/// Get shared client instance.
pub fn client(&self) -> Arc<ComponentClient<Components>> {
self.client.clone()
@@ -420,7 +394,7 @@ impl<C: Components> TransactionPoolAdapter<C> {
}
}
impl<C: Components> network::TransactionPool<ComponentExHash<C>, ComponentBlock<C>> for TransactionPoolAdapter<C> {
impl<C: Components> network::TransactionPool<ComponentExHash<C>, ComponentBlock<C>> for TransactionPoolAdapter<C> where <C as components::Components>::RuntimeApi: Send + Sync{
fn transactions(&self) -> Vec<(ComponentExHash<C>, ComponentExtrinsic<C>)> {
self.pool.ready()
.map(|t| {
@@ -468,41 +442,6 @@ impl<C: Components> network::TransactionPool<ComponentExHash<C>, ComponentBlock<
}
}
/// Creates a simple `Service` implementation.
/// This `Service` just holds an instance to a `service::Service` and implements `Deref`.
/// It also provides a `new` function that takes a `config` and a `TaskExecutor`.
#[macro_export]
macro_rules! construct_simple_service {
(
$name: ident
) => {
pub struct $name<C: $crate::Components> {
inner: $crate::Arc<$crate::Service<C>>,
}
impl<C: $crate::Components> $name<C> {
fn new(
config: FactoryFullConfiguration<C::Factory>,
executor: $crate::TaskExecutor
) -> $crate::Result<Self, $crate::Error> {
Ok(
Self {
inner: $crate::Arc::new($crate::Service::new(config, executor)?)
}
)
}
}
impl<C: $crate::Components> $crate::Deref for $name<C> {
type Target = $crate::Service<C>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
}
}
/// Constructs a service factory with the given name that implements the `ServiceFactory` trait.
/// The required parameters are required to be given in the exact order. Some parameters are followed
/// by `{}` blocks. These blocks are required and used to initialize the given parameter.
@@ -544,6 +483,7 @@ macro_rules! construct_service_factory {
$(#[$attr:meta])*
struct $name:ident {
Block = $block:ty,
RuntimeApi = $runtime_api:ty,
NetworkProtocol = $protocol:ty { $( $protocol_init:tt )* },
RuntimeDispatch = $dispatch:ty,
FullTransactionPoolApi = $full_transaction:ty { $( $full_transaction_init:tt )* },
@@ -564,6 +504,7 @@ macro_rules! construct_service_factory {
#[allow(unused_variables)]
impl $crate::ServiceFactory for $name {
type Block = $block;
type RuntimeApi = $runtime_api;
type NetworkProtocol = $protocol;
type RuntimeDispatch = $dispatch;
type FullTransactionPoolApi = $full_transaction;
+9 -1
View File
@@ -179,7 +179,10 @@ impl<F: ServiceFactory> TestNet<F> {
}
}
pub fn connectivity<F: ServiceFactory>(spec: FactoryChainSpec<F>) {
pub fn connectivity<F: ServiceFactory>(spec: FactoryChainSpec<F>) where
<F as ServiceFactory>::RuntimeApi:
client::block_builder::api::BlockBuilder<<F as service::ServiceFactory>::Block>
{
const NUM_NODES: u32 = 10;
{
let temp = TempDir::new("substrate-connectivity-test").expect("Error creating test dir");
@@ -219,6 +222,9 @@ where
F: ServiceFactory,
B: Fn(&F::FullService) -> ImportBlock<F::Block>,
E: Fn(&F::FullService) -> FactoryExtrinsic<F>,
<F as ServiceFactory>::RuntimeApi:
client::block_builder::api::BlockBuilder<<F as service::ServiceFactory>::Block> +
client::runtime_api::TaggedTransactionQueue<<F as service::ServiceFactory>::Block>
{
const NUM_NODES: u32 = 10;
const NUM_BLOCKS: usize = 512;
@@ -255,6 +261,8 @@ where
pub fn consensus<F>(spec: FactoryChainSpec<F>, authorities: Vec<String>)
where
F: ServiceFactory,
<F as ServiceFactory>::RuntimeApi:
client::block_builder::api::BlockBuilder<<F as service::ServiceFactory>::Block>
{
const NUM_NODES: u32 = 20;
const NUM_BLOCKS: u64 = 200;
-19
View File
@@ -1,19 +0,0 @@
[package]
name = "sr-api"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
parity-codec = { version = "2.1", default-features = false }
sr-std = { path = "../sr-std", default-features = false }
sr-primitives = { path = "../sr-primitives", default-features = false }
sr-version = { path = "../sr-version", default-features = false }
[features]
default = ["std"]
std = [
"sr-std/std",
"parity-codec/std",
"sr-primitives/std",
"sr-version/std",
]
+34 -2
View File
@@ -27,8 +27,10 @@ use codec::{Codec, Encode, HasCompact};
pub use integer_sqrt::IntegerSquareRoot;
pub use num_traits::{Zero, One, Bounded};
pub use num_traits::ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
use rstd::ops::{Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign,
RemAssign, Shl, Shr};
use rstd::ops::{
Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign,
RemAssign, Shl, Shr
};
/// A lazy value.
pub trait Lazy<T: ?Sized> {
@@ -597,3 +599,33 @@ pub trait ProvideInherent {
block: &Block, data: Self::Inherent, extract_function: &F
) -> Result<(), Self::Error>;
}
/// Auxiliary wrapper that holds an api instance and binds it to the given lifetime.
pub struct ApiRef<'a, T>(T, rstd::marker::PhantomData<&'a ()>);
impl<'a, T> From<T> for ApiRef<'a, T> {
fn from(api: T) -> Self {
ApiRef(api, Default::default())
}
}
impl<'a, T> rstd::ops::Deref for ApiRef<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
/// Something that provides a runtime api.
pub trait ProvideRuntimeApi {
/// The concrete type that provides the api.
type Api;
/// Returns the runtime api.
/// The returned instance will keep track of modifications to the storage. Any successful
/// call to an api function, will `commit` its changes to an internal buffer. Otherwise,
/// the modifications will be `discarded`. The modifications will not be applied to the
/// storage, even on a `commit`.
fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api>;
}
+1 -1
View File
@@ -10,6 +10,6 @@ substrate-executor = { path = "../executor" }
substrate-consensus-common = { path = "../consensus/common" }
substrate-keyring = { path = "../../core/keyring" }
substrate-primitives = { path = "../primitives" }
substrate-state-machine = { path = "../state-machine" }
substrate-test-runtime = { path = "../test-runtime" }
sr-primitives = { path = "../sr-primitives" }
@@ -20,8 +20,8 @@ use codec;
use client;
use keyring;
use runtime;
use primitives::{Blake2Hasher};
use runtime_primitives::traits::ProvideRuntimeApi;
use client::block_builder::api::BlockBuilder;
/// Extension trait for test block builder.
pub trait BlockBuilderExt {
@@ -29,10 +29,9 @@ pub trait BlockBuilderExt {
fn push_transfer(&mut self, transfer: runtime::Transfer) -> Result<(), client::error::Error>;
}
impl<'a, B, E> BlockBuilderExt for client::block_builder::BlockBuilder<'a, B, E, runtime::Block, Blake2Hasher>
where
B: client::backend::Backend<runtime::Block, Blake2Hasher>,
E: client::CallExecutor<runtime::Block, Blake2Hasher> + Clone,
impl<'a, A> BlockBuilderExt for client::block_builder::BlockBuilder<'a, runtime::Block, A> where
A: ProvideRuntimeApi + client::blockchain::HeaderBackend<runtime::Block> + 'a,
A::Api: BlockBuilder<runtime::Block>
{
fn push_transfer(&mut self, transfer: runtime::Transfer) -> Result<(), client::error::Error> {
self.push(sign_tx(transfer))
+2 -2
View File
@@ -35,11 +35,11 @@ pub trait TestClient: Sized {
fn genesis_hash(&self) -> runtime::Hash;
}
impl<B, E> TestClient for Client<B, E, runtime::Block>
impl<B, E, RA> TestClient for Client<B, E, runtime::Block, RA>
where
B: client::backend::Backend<runtime::Block, Blake2Hasher>,
E: client::CallExecutor<runtime::Block, Blake2Hasher>,
Self: BlockImport<runtime::Block, Error=client::error::Error>
Self: BlockImport<runtime::Block, Error=client::error::Error>,
{
fn justify_and_import(&self, origin: BlockOrigin, block: runtime::Block)
-> client::error::Result<()>
+4 -3
View File
@@ -27,6 +27,7 @@ pub extern crate substrate_client as client;
pub extern crate substrate_keyring as keyring;
pub extern crate substrate_test_runtime as runtime;
pub extern crate substrate_consensus_common as consensus;
extern crate substrate_state_machine as state_machine;
pub mod client_ext;
pub mod trait_tests;
@@ -65,12 +66,12 @@ pub type Executor = client::LocalCallExecutor<
>;
/// Creates new client instance used for tests.
pub fn new() -> client::Client<Backend, Executor, runtime::Block> {
pub fn new() -> client::Client<Backend, Executor, runtime::Block, runtime::ClientWithApi> {
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<Backend, Executor, runtime::Block> {
pub fn new_with_changes_trie() -> client::Client<Backend, Executor, runtime::Block, runtime::ClientWithApi> {
new_with_backend(Arc::new(Backend::new()), true)
}
@@ -79,7 +80,7 @@ pub fn new_with_changes_trie() -> client::Client<Backend, Executor, runtime::Blo
pub fn new_with_backend<B>(
backend: Arc<B>,
support_changes_trie: bool
) -> client::Client<B, client::LocalCallExecutor<B, executor::NativeExecutor<LocalExecutor>>, runtime::Block>
) -> client::Client<B, client::LocalCallExecutor<B, executor::NativeExecutor<LocalExecutor>>, runtime::Block, runtime::ClientWithApi>
where
B: backend::LocalBackend<runtime::Block, Blake2Hasher>,
{
+2 -2
View File
@@ -11,8 +11,8 @@ serde_derive = { version = "1.0", optional = true }
parity-codec = { version = "2.1", default-features = false }
parity-codec-derive = { version = "2.1", default-features = false }
substrate-keyring = { path = "../keyring", optional = true }
substrate-client = { path = "../client", optional = true }
substrate-primitives = { path = "../primitives", default-features = false }
sr-api = { path = "../sr-api", default-features = false }
sr-std = { path = "../sr-std", default-features = false }
sr-io = { path = "../sr-io", default-features = false }
sr-primitives = { path = "../sr-primitives", default-features = false }
@@ -26,9 +26,9 @@ std = [
"hex-literal",
"serde",
"serde_derive",
"substrate-client",
"substrate-keyring",
"parity-codec/std",
"sr-api/std",
"sr-std/std",
"sr-io/std",
"srml-support/std",
+172 -12
View File
@@ -22,12 +22,13 @@ extern crate sr_std as rstd;
extern crate parity_codec as codec;
extern crate sr_primitives as runtime_primitives;
#[macro_use]
extern crate substrate_client as client;
#[macro_use]
extern crate srml_support as runtime_support;
#[macro_use]
extern crate parity_codec_derive;
#[macro_use]
extern crate sr_api as runtime_api;
extern crate sr_io as runtime_io;
#[macro_use]
extern crate sr_version as runtime_version;
@@ -47,12 +48,20 @@ pub mod system;
use rstd::prelude::*;
use codec::{Encode, Decode};
use runtime_api::runtime::*;
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 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;
@@ -152,8 +161,8 @@ pub fn changes_trie_config() -> primitives::ChangesTrieConfiguration {
}
}
mod test_api {
decl_apis! {
pub mod test_api {
decl_runtime_apis! {
pub trait TestAPI {
fn balance_of<AccountId>(id: AccountId) -> u64;
}
@@ -162,10 +171,161 @@ mod test_api {
use test_api::runtime::TestAPI;
#[cfg(feature = "std")]
pub struct ClientWithApi {
call: ::std::ptr::NonNull<client::runtime_api::CallApiAt<Block>>,
commit_on_success: ::std::cell::RefCell<bool>,
initialised_block: ::std::cell::RefCell<Option<BlockId<Block>>>,
changes: ::std::cell::RefCell<client::runtime_api::OverlayedChanges>,
}
#[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<F: FnOnce(&Self) -> Result<R, E>, R, E>(&self, map_call: F) -> Result<R, E> {
*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<Block> for ClientWithApi {
fn construct_runtime_api<'a, T: client::runtime_api::CallApiAt<Block>>(call: &'a T) -> ApiRef<'a, Self> {
ClientWithApi {
call: unsafe {
::std::ptr::NonNull::new_unchecked(
::std::mem::transmute(
call as &client::runtime_api::CallApiAt<Block>
)
)
},
commit_on_success: true.into(),
initialised_block: None.into(),
changes: Default::default(),
}.into()
}
}
#[cfg(feature = "std")]
impl ClientWithApi {
fn call_api_at<A: Encode, R: Decode>(
&self,
at: &BlockId<Block>,
function: &'static str,
args: &A
) -> client::error::Result<R> {
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<R, E>(&self, res: &Result<R, E>) {
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")]
impl client::runtime_api::Core<Block> for ClientWithApi {
fn version(&self, at: &BlockId<Block>) -> Result<RuntimeVersion, client::error::Error> {
self.call_api_at(at, "version", &())
}
fn authorities(&self, at: &BlockId<Block>) -> Result<Vec<AuthorityId>, client::error::Error> {
self.call_api_at(at, "authorities", &())
}
fn execute_block(&self, at: &BlockId<Block>, block: &Block) -> Result<(), client::error::Error> {
self.call_api_at(at, "execute_block", block)
}
fn initialise_block(&self, at: &BlockId<Block>, header: &<Block as BlockT>::Header) -> Result<(), client::error::Error> {
self.call_api_at(at, "initialise_block", header)
}
}
#[cfg(feature = "std")]
impl client::block_builder::api::BlockBuilder<Block> for ClientWithApi {
fn apply_extrinsic(&self, at: &BlockId<Block>, extrinsic: &<Block as BlockT>::Extrinsic) -> Result<ApplyResult, client::error::Error> {
self.call_api_at(at, "apply_extrinsic", extrinsic)
}
fn finalise_block(&self, at: &BlockId<Block>) -> Result<<Block as BlockT>::Header, client::error::Error> {
self.call_api_at(at, "finalise_block", &())
}
fn inherent_extrinsics<Inherent: Decode + Encode, Unchecked: Decode + Encode>(
&self, at: &BlockId<Block>, inherent: &Inherent
) -> Result<Vec<Unchecked>, client::error::Error> {
self.call_api_at(at, "inherent_extrinsics", inherent)
}
fn check_inherents<Inherent: Decode + Encode, Error: Decode + Encode>(&self, at: &BlockId<Block>, block: &Block, inherent: &Inherent) -> Result<Result<(), Error>, client::error::Error> {
self.call_api_at(at, "check_inherents", &(block, inherent))
}
fn random_seed(&self, at: &BlockId<Block>) -> Result<<Block as BlockT>::Hash, client::error::Error> {
self.call_api_at(at, "random_seed", &())
}
}
#[cfg(feature = "std")]
impl client::runtime_api::TaggedTransactionQueue<Block> for ClientWithApi {
fn validate_transaction(
&self,
at: &BlockId<Block>,
utx: &<Block as BlockT>::Extrinsic
) -> Result<TransactionValidity, client::error::Error> {
self.call_api_at(at, "validate_transaction", utx)
}
}
#[cfg(feature = "std")]
impl client::runtime_api::Metadata<Block> for ClientWithApi {
fn metadata(&self, at: &BlockId<Block>) -> Result<OpaqueMetadata, client::error::Error> {
self.call_api_at(at, "metadata", &())
}
}
#[cfg(feature = "std")]
impl test_api::TestAPI<Block> for ClientWithApi {
fn balance_of<AccountId: Encode + Decode>(&self, at: &BlockId<Block>, id: &AccountId) -> Result<u64, client::error::Error> {
self.call_api_at(at, "balance_of", id)
}
}
struct Runtime;
impl_apis! {
impl Core<Block, AuthorityId> for Runtime {
impl_runtime_apis! {
impl Core<Block> for Runtime {
fn version() -> RuntimeVersion {
version()
}
@@ -177,19 +337,19 @@ impl_apis! {
fn execute_block(block: Block) {
system::execute_block(block)
}
fn initialise_block(header: <Block as BlockT>::Header) {
system::initialise_block(header)
}
}
impl TaggedTransactionQueue<Block, TransactionValidity> for Runtime {
impl TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(utx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
system::validate_transaction(utx)
}
}
impl BlockBuilder<Block, u32, u32, u32, u32> for Runtime {
fn initialise_block(header: <Block as BlockT>::Header) {
system::initialise_block(header)
}
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyResult {
system::execute_transaction(extrinsic)
}
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -9,7 +9,7 @@ hex-literal = { version = "0.1.0", optional = true }
parity-codec = { version = "2.1", default-features = false }
parity-codec-derive = { version = "2.1", default-features = false }
substrate-primitives = { path = "../../primitives", default-features = false }
sr-api = { path = "../../sr-api", default-features = false }
substrate-client = { path = "../../client", default-features = false }
sr-std = { path = "../../sr-std", default-features = false }
sr-io = { path = "../../sr-io", default-features = false }
sr-version = { path = "../../sr-version", default-features = false }
@@ -22,12 +22,12 @@ std = [
"log",
"hex-literal",
"parity-codec/std",
"sr-api/std",
"sr-std/std",
"sr-io/std",
"srml-support/std",
"sr-version/std",
"substrate-primitives/std",
"substrate-client/std",
"sr-primitives/std"
]
+14 -9
View File
@@ -18,8 +18,9 @@
use std::{
sync::Arc,
marker::PhantomData,
};
use client::{self, runtime_api::TaggedTransactionQueue};
use client::{runtime_api::TaggedTransactionQueue, blockchain::HeaderBackend};
use parity_codec::Encode;
use txpool;
use substrate_primitives::{
@@ -36,30 +37,34 @@ use sr_primitives::{
use error;
/// The transaction pool logic
pub struct ChainApi<B, E, Block: traits::Block> {
client: Arc<client::Client<B, E, Block>>,
pub struct ChainApi<T, Block> {
client: Arc<T>,
_marker: PhantomData<Block>,
}
impl<B, E, Block: traits::Block> ChainApi<B, E, Block> {
impl<T, Block> ChainApi<T, Block> where
Block: traits::Block,
T: traits::ProvideRuntimeApi + HeaderBackend<Block> {
/// Create new transaction pool logic.
pub fn new(client: Arc<client::Client<B, E, Block>>) -> Self {
pub fn new(client: Arc<T>) -> Self {
ChainApi {
client,
_marker: Default::default()
}
}
}
impl<B, E, Block> txpool::ChainApi for ChainApi<B, E, Block> where
impl<T, Block> txpool::ChainApi for ChainApi<T, Block> where
Block: traits::Block<Hash=H256>,
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
E: client::CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
T: traits::ProvideRuntimeApi + HeaderBackend<Block>,
T::Api: TaggedTransactionQueue<Block>
{
type Block = Block;
type Hash = H256;
type Error = error::Error;
fn validate_transaction(&self, at: &BlockId<Self::Block>, uxt: &txpool::ExtrinsicFor<Self>) -> error::Result<TransactionValidity> {
Ok(self.client.validate_transaction(at, uxt)?)
Ok(self.client.runtime_api().validate_transaction(at, uxt)?)
}
// TODO [toDr] Use proper lbock number type
+5 -2
View File
@@ -33,6 +33,7 @@ extern crate substrate_transaction_pool as transaction_pool;
#[macro_use]
extern crate substrate_network as network;
extern crate substrate_consensus_aura as consensus;
extern crate substrate_client as client;
extern crate node_primitives;
#[macro_use]
extern crate substrate_service;
@@ -49,6 +50,7 @@ mod service;
use tokio::runtime::Runtime;
pub use cli::{VersionInfo, IntoExit};
use substrate_service::{ServiceFactory, Roles as ServiceRoles};
use std::ops::Deref;
/// The chain specification option.
#[derive(Clone, Debug)]
@@ -118,12 +120,13 @@ pub fn run<I, T, E>(args: I, exit: E, version: cli::VersionInfo) -> error::Resul
Ok(())
}
fn run_until_exit<C, E>(
fn run_until_exit<T, C, E>(
runtime: &mut Runtime,
service: service::Service<C>,
service: T,
e: E,
) -> error::Result<()>
where
T: Deref<Target=substrate_service::Service<C>>,
C: substrate_service::Components,
E: IntoExit,
{
+15 -13
View File
@@ -20,8 +20,8 @@
use std::sync::Arc;
use transaction_pool::{self, txpool::{Pool as TransactionPool}};
use node_runtime::{GenesisConfig, ClientWithApi};
use node_primitives::Block;
use node_runtime::GenesisConfig;
use substrate_service::{
FactoryFullConfiguration, LightComponents, FullComponents, FullBackend,
FullClient, LightClient, LightBackend, FullExecutor, LightExecutor,
@@ -29,6 +29,7 @@ use substrate_service::{
};
use node_executor;
use consensus::{import_queue, start_aura, Config as AuraConfig, AuraImportQueue};
use client;
const AURA_SLOT_DURATION: u64 = 6;
@@ -37,23 +38,22 @@ construct_simple_protocol! {
pub struct NodeProtocol where Block = Block { }
}
construct_simple_service!(Service);
construct_service_factory! {
struct Factory {
Block = Block,
RuntimeApi = ClientWithApi,
NetworkProtocol = NodeProtocol { |config| Ok(NodeProtocol::new()) },
RuntimeDispatch = node_executor::Executor,
FullTransactionPoolApi = transaction_pool::ChainApi<FullBackend<Self>, FullExecutor<Self>, Block>
FullTransactionPoolApi = transaction_pool::ChainApi<client::Client<FullBackend<Self>, FullExecutor<Self>, Block, ClientWithApi>, Block>
{ |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) },
LightTransactionPoolApi = transaction_pool::ChainApi<LightBackend<Self>, LightExecutor<Self>, Block>
LightTransactionPoolApi = transaction_pool::ChainApi<client::Client<LightBackend<Self>, LightExecutor<Self>, Block, ClientWithApi>, Block>
{ |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) },
Genesis = GenesisConfig,
Configuration = (),
FullService = Service<FullComponents<Self>>
FullService = FullComponents<Self>
{ |config: FactoryFullConfiguration<Self>, executor: TaskExecutor| {
let is_auth = config.roles == Roles::AUTHORITY;
Service::<FullComponents<Factory>>::new(config, executor.clone()).map(move |service|{
FullComponents::<Factory>::new(config, executor.clone()).map(move |service|{
if is_auth {
if let Ok(Some(Ok(key))) = service.keystore().contents()
.map(|keys| keys.get(0).map(|k| service.keystore().load(k, "")))
@@ -77,18 +77,20 @@ construct_service_factory! {
})
}
},
LightService = Service<LightComponents<Self>>
{ |config, executor| Service::<LightComponents<Factory>>::new(config, executor) },
LightService = LightComponents<Self>
{ |config, executor| <LightComponents<Factory>>::new(config, executor) },
FullImportQueue = AuraImportQueue<Self::Block, FullClient<Self>>
{ |config, client| Ok(import_queue(AuraConfig {
local_key: None,
slot_duration: 5
}, client)) },
LightImportQueue = AuraImportQueue<Self::Block, LightClient<Self>>
{ |config, client| Ok(import_queue(AuraConfig {
local_key: None,
slot_duration: 5
}, client)) },
{ |config, client| Ok(
import_queue(AuraConfig {
local_key: None,
slot_duration: 5
}, client))
},
}
}
+3 -3
View File
@@ -11,10 +11,10 @@ serde_derive = { version = "1.0", optional = true }
safe-mix = { version = "1.0", default-features = false }
parity-codec = "2.1"
parity-codec-derive = "2.1"
sr-api = { path = "../../core/sr-api", default-features = false }
sr-std = { path = "../../core/sr-std" }
srml-support = { path = "../../srml/support" }
substrate-primitives = { path = "../../core/primitives" }
substrate-client = { path = "../../core/client", optional = true }
substrate-keyring = { path = "../../core/keyring" }
srml-balances = { path = "../../srml/balances" }
srml-consensus = { path = "../../srml/consensus" }
@@ -37,7 +37,6 @@ default = ["std"]
std = [
"parity-codec/std",
"substrate-primitives/std",
"sr-api/std",
"sr-std/std",
"srml-support/std",
"srml-balances/std",
@@ -57,5 +56,6 @@ std = [
"node-primitives/std",
"serde_derive",
"serde/std",
"safe-mix/std"
"safe-mix/std",
"substrate-client",
]
+175 -16
View File
@@ -20,9 +20,6 @@
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit="256"]
#[macro_use]
extern crate sr_api as runtime_api;
#[macro_use]
extern crate srml_support;
@@ -35,9 +32,14 @@ extern crate serde_derive;
extern crate substrate_primitives;
#[macro_use]
extern crate substrate_client as client;
#[macro_use]
extern crate parity_codec_derive;
extern crate parity_codec as codec;
extern crate sr_std as rstd;
extern crate srml_balances as balances;
extern crate srml_consensus as consensus;
@@ -55,23 +57,33 @@ 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
AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, SessionKey, Signature
};
use runtime_api::{runtime::*, 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 runtime_primitives::transaction_validity::TransactionValidity;
use runtime_primitives::generic;
use runtime_primitives::traits::{Convert, BlakeTwo256, Block as BlockT};
#[cfg(feature = "std")]
use runtime_primitives::traits::ApiRef;
#[cfg(feature = "std")]
use substrate_primitives::AuthorityId;
use version::RuntimeVersion;
use council::{motions as council_motions, voting as council_voting};
#[cfg(feature = "std")]
use council::seats as council_seats;
#[cfg(any(feature = "std", test))]
use version::NativeVersion;
use substrate_primitives::OpaqueMetadata;
#[cfg(any(feature = "std", test))]
pub use runtime_primitives::BuildStorage;
@@ -236,8 +248,155 @@ pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Index, Call>;
/// Executive: handles dispatch to the various modules.
pub type Executive = executive::Executive<Runtime, Block, balances::ChainContext<Runtime>, Balances, AllModules>;
impl_apis! {
impl Core<Block, SessionKey> for Runtime {
#[cfg(feature = "std")]
pub struct ClientWithApi {
call: ::std::ptr::NonNull<client::runtime_api::CallApiAt<GBlock>>,
commit_on_success: ::std::cell::RefCell<bool>,
initialised_block: ::std::cell::RefCell<Option<GBlockId>>,
changes: ::std::cell::RefCell<client::runtime_api::OverlayedChanges>,
}
#[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<F: FnOnce(&Self) -> Result<R, E>, R, E>(&self, map_call: F) -> Result<R, E> {
*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<GBlock> for ClientWithApi {
fn construct_runtime_api<'a, T: client::runtime_api::CallApiAt<GBlock>>(call: &'a T) -> ApiRef<'a, Self> {
ClientWithApi {
call: unsafe {
::std::ptr::NonNull::new_unchecked(
::std::mem::transmute(
call as &client::runtime_api::CallApiAt<GBlock>
)
)
},
commit_on_success: true.into(),
initialised_block: None.into(),
changes: Default::default(),
}.into()
}
}
#[cfg(feature = "std")]
impl ClientWithApi {
fn call_api_at<A: Encode, R: Decode>(
&self,
at: &GBlockId,
function: &'static str,
args: &A
) -> client::error::Result<R> {
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<R, E>(&self, res: &Result<R, E>) {
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<GBlock>;
#[cfg(feature = "std")]
impl client::runtime_api::Core<GBlock> for ClientWithApi {
fn version(&self, at: &GBlockId) -> Result<RuntimeVersion, client::error::Error> {
self.call_api_at(at, "version", &())
}
fn authorities(&self, at: &GBlockId) -> Result<Vec<AuthorityId>, 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: &<GBlock as BlockT>::Header) -> Result<(), client::error::Error> {
self.call_api_at(at, "initialise_block", header)
}
}
#[cfg(feature = "std")]
impl client::block_builder::api::BlockBuilder<GBlock> for ClientWithApi {
fn apply_extrinsic(&self, at: &GBlockId, extrinsic: &<GBlock as BlockT>::Extrinsic) -> Result<ApplyResult, client::error::Error> {
self.call_api_at(at, "apply_extrinsic", extrinsic)
}
fn finalise_block(&self, at: &GBlockId) -> Result<<GBlock as BlockT>::Header, client::error::Error> {
self.call_api_at(at, "finalise_block", &())
}
fn inherent_extrinsics<Inherent: Decode + Encode, Unchecked: Decode + Encode>(
&self, at: &GBlockId, inherent: &Inherent
) -> Result<Vec<Unchecked>, client::error::Error> {
self.call_api_at(at, "inherent_extrinsics", inherent)
}
fn check_inherents<Inherent: Decode + Encode, Error: Decode + Encode>(&self, at: &GBlockId, block: &GBlock, inherent: &Inherent) -> Result<Result<(), Error>, client::error::Error> {
self.call_api_at(at, "check_inherents", &(block, inherent))
}
fn random_seed(&self, at: &GBlockId) -> Result<<GBlock as BlockT>::Hash, client::error::Error> {
self.call_api_at(at, "random_seed", &())
}
}
#[cfg(feature = "std")]
impl client::runtime_api::TaggedTransactionQueue<GBlock> for ClientWithApi {
fn validate_transaction(
&self,
at: &GBlockId,
utx: &<GBlock as BlockT>::Extrinsic
) -> Result<TransactionValidity, client::error::Error> {
self.call_api_at(at, "validate_transaction", utx)
}
}
#[cfg(feature = "std")]
impl client::runtime_api::Metadata<GBlock> for ClientWithApi {
fn metadata(&self, at: &GBlockId) -> Result<OpaqueMetadata, client::error::Error> {
self.call_api_at(at, "metadata", &())
}
}
impl_runtime_apis! {
impl Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
@@ -249,19 +408,19 @@ impl_apis! {
fn execute_block(block: Block) {
Executive::execute_block(block)
}
fn initialise_block(header: <Block as BlockT>::Header) {
Executive::initialise_block(&header)
}
}
impl Metadata<RuntimeMetadata> for Runtime {
fn metadata() -> RuntimeMetadata {
Runtime::metadata()
impl Metadata for Runtime {
fn metadata() -> OpaqueMetadata {
Runtime::metadata().into()
}
}
impl BlockBuilder<Block, InherentData, UncheckedExtrinsic, InherentData, InherentError> for Runtime {
fn initialise_block(header: <Block as BlockT>::Header) {
Executive::initialise_block(&header)
}
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyResult {
Executive::apply_extrinsic(extrinsic)
}
@@ -283,7 +442,7 @@ impl_apis! {
}
}
impl TaggedTransactionQueue<Block, TransactionValidity> for Runtime {
impl TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
Executive::validate_transaction(tx)
}
+770 -11
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -8,11 +8,11 @@ crate-type = ["cdylib"]
[dependencies]
integer-sqrt = { version = "0.1.2" }
safe-mix = { version = "1.0", default-features = false}
safe-mix = { version = "1.0", default-features = false }
parity-codec-derive = { version = "2.1" }
parity-codec = { version = "2.1", default-features = false }
substrate-primitives = { path = "../../../core/primitives", default-features = false }
sr-api = { path = "../../../core/sr-api", default-features = false }
substrate-client = { path = "../../../core/client", default-features = false }
sr-std = { path = "../../../core/sr-std", default-features = false }
srml-support = { path = "../../../srml/support", default-features = false }
srml-balances = { path = "../../../srml/balances", default-features = false }
@@ -37,7 +37,7 @@ std = [
"safe-mix/std",
"parity-codec/std",
"substrate-primitives/std",
"sr-api/std",
"substrate-client/std",
"sr-std/std",
"srml-support/std",
"srml-balances/std",
+4
View File
@@ -8,12 +8,16 @@ parity-codec = { version = "2.1", default-features = false }
parity-codec-derive = { version = "2.1", default-features = false }
serde = { version = "1.0", optional = true }
serde_derive = { version = "1.0", optional = true }
sr-std = { path = "../../core/sr-std", default-features = false }
substrate-primitives = { path = "../../core/primitives", default-features = false }
[features]
default = ["std"]
std = [
"parity-codec/std",
"parity-codec-derive/std",
"sr-std/std",
"substrate-primitives/std",
"serde",
"serde_derive"
]
+9 -12
View File
@@ -21,14 +21,12 @@
//! codec-encoded metadata.
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[macro_use]
extern crate parity_codec_derive;
extern crate parity_codec as codec;
extern crate sr_std as rstd;
extern crate substrate_primitives as primitives;
#[cfg(feature = "std")]
extern crate serde;
@@ -36,17 +34,10 @@ extern crate serde;
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "std")]
pub mod alloc {
pub use std::vec;
}
use codec::{Encode, Output};
#[cfg(feature = "std")]
use codec::{Decode, Input};
// Make Vec available on `std` and `no_std`
use alloc::vec::Vec;
use rstd::vec::Vec;
#[cfg(feature = "std")]
type StringBuf = String;
@@ -294,3 +285,9 @@ pub struct RuntimeMetadata {
pub modules: DecodeDifferentArray<RuntimeModuleMetadata>,
pub outer_dispatch: OuterDispatchMetadata,
}
impl Into<primitives::OpaqueMetadata> for RuntimeMetadata {
fn into(self) -> primitives::OpaqueMetadata {
primitives::OpaqueMetadata::new(self.encode())
}
}