mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 22:21:07 +00:00
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 10064461570436465ed664 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 100644139cef13f90dbf3d M core/client/src/error.rs :100644 100644 2800c503 3298e66a M core/client/src/runtime_api.rs :100644 100644affa1c5c809b08bc M core/primitives/src/lib.rs :100644 1006442877dfa9d5547413 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 1006442e113ab6dcc01a6d M srml/metadata/Cargo.toml :100644 100644ea722a700809531aM 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:
Generated
+7
-13
@@ -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",
|
||||
]
|
||||
|
||||
@@ -32,7 +32,6 @@ members = [
|
||||
"core/primitives",
|
||||
"core/rpc",
|
||||
"core/rpc-servers",
|
||||
"core/sr-api",
|
||||
"core/sr-io",
|
||||
"core/sr-sandbox",
|
||||
"core/sr-std",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
+35
-47
@@ -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;
|
||||
@@ -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
@@ -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]
|
||||
|
||||
@@ -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::*;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
+40
-108
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>>> {
|
||||
|
||||
@@ -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,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>;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
@@ -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>;
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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<()>
|
||||
|
||||
@@ -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>,
|
||||
{
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
+779
-11
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
]
|
||||
|
||||
|
||||
BIN
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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,
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Generated
+770
-11
File diff suppressed because it is too large
Load Diff
@@ -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",
|
||||
|
||||
BIN
Binary file not shown.
@@ -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"
|
||||
]
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user