mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 12:07:57 +00:00
Remove node-api (#804)
* Remove `node-api` from `node-consensus` and `node-transaction-pool` * Remove the `node-api` crate and its last usages * Remove left over file * Fixes compilation errors * Switch to `As` trait * Rename trait * Whitespace
This commit is contained in:
Generated
+1
-16
@@ -1586,18 +1586,6 @@ dependencies = [
|
|||||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "node-api"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"node-primitives 0.1.0",
|
|
||||||
"node-runtime 0.1.0",
|
|
||||||
"sr-primitives 0.1.0",
|
|
||||||
"substrate-client 0.1.0",
|
|
||||||
"substrate-keyring 0.1.0",
|
|
||||||
"substrate-primitives 0.1.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "node-cli"
|
name = "node-cli"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -1617,7 +1605,6 @@ dependencies = [
|
|||||||
"exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"node-api 0.1.0",
|
|
||||||
"node-primitives 0.1.0",
|
"node-primitives 0.1.0",
|
||||||
"node-runtime 0.1.0",
|
"node-runtime 0.1.0",
|
||||||
"node-transaction-pool 0.1.0",
|
"node-transaction-pool 0.1.0",
|
||||||
@@ -1625,6 +1612,7 @@ dependencies = [
|
|||||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rhododendron 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rhododendron 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sr-primitives 0.1.0",
|
"sr-primitives 0.1.0",
|
||||||
|
"srml-system 0.1.0",
|
||||||
"substrate-bft 0.1.0",
|
"substrate-bft 0.1.0",
|
||||||
"substrate-client 0.1.0",
|
"substrate-client 0.1.0",
|
||||||
"substrate-keyring 0.1.0",
|
"substrate-keyring 0.1.0",
|
||||||
@@ -1664,7 +1652,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"node-api 0.1.0",
|
|
||||||
"node-consensus 0.1.0",
|
"node-consensus 0.1.0",
|
||||||
"node-primitives 0.1.0",
|
"node-primitives 0.1.0",
|
||||||
"rhododendron 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rhododendron 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -1729,7 +1716,6 @@ dependencies = [
|
|||||||
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"node-api 0.1.0",
|
|
||||||
"node-consensus 0.1.0",
|
"node-consensus 0.1.0",
|
||||||
"node-executor 0.1.0",
|
"node-executor 0.1.0",
|
||||||
"node-network 0.1.0",
|
"node-network 0.1.0",
|
||||||
@@ -1753,7 +1739,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"node-api 0.1.0",
|
|
||||||
"node-primitives 0.1.0",
|
"node-primitives 0.1.0",
|
||||||
"node-runtime 0.1.0",
|
"node-runtime 0.1.0",
|
||||||
"parity-codec 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-codec 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ members = [
|
|||||||
"core/trie",
|
"core/trie",
|
||||||
"core/keystore",
|
"core/keystore",
|
||||||
"node/cli",
|
"node/cli",
|
||||||
"node/api",
|
|
||||||
"node/consensus",
|
"node/consensus",
|
||||||
"node/executor",
|
"node/executor",
|
||||||
"node/network",
|
"node/network",
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "node-api"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
node-runtime = { path = "../runtime" }
|
|
||||||
node-primitives = { path = "../primitives" }
|
|
||||||
substrate-client = { path = "../../core/client" }
|
|
||||||
substrate-primitives = { path = "../../core/primitives" }
|
|
||||||
sr-primitives = { path = "../../core/sr-primitives" }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
substrate-keyring = { path = "../../core/keyring" }
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Substrate.
|
|
||||||
|
|
||||||
// Substrate is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Substrate is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! Strongly typed API for Substrate runtime.
|
|
||||||
|
|
||||||
#![warn(missing_docs)]
|
|
||||||
#![warn(unused_extern_crates)]
|
|
||||||
|
|
||||||
extern crate node_primitives as primitives;
|
|
||||||
extern crate node_runtime as runtime;
|
|
||||||
extern crate substrate_client as client;
|
|
||||||
extern crate sr_primitives;
|
|
||||||
extern crate substrate_primitives;
|
|
||||||
|
|
||||||
pub use client::error::{Error, ErrorKind, Result};
|
|
||||||
use runtime::Address;
|
|
||||||
use client::backend::Backend;
|
|
||||||
use client::block_builder::BlockBuilder as ClientBlockBuilder;
|
|
||||||
use client::{Client, CallExecutor};
|
|
||||||
use primitives::{
|
|
||||||
AccountId, Block, BlockId, BlockNumber, Hash, Index, InherentData, SessionKey, Timestamp, UncheckedExtrinsic
|
|
||||||
};
|
|
||||||
use sr_primitives::{transaction_validity::TransactionValidity, traits::{CurrentHeight, BlockNumberToHash}};
|
|
||||||
use substrate_primitives::{Blake2Hasher};
|
|
||||||
|
|
||||||
/// Build new blocks.
|
|
||||||
pub trait BlockBuilder {
|
|
||||||
/// Push an extrinsic onto the block. Fails if the extrinsic is invalid.
|
|
||||||
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()>;
|
|
||||||
|
|
||||||
/// Bake the block with provided extrinsics.
|
|
||||||
fn bake(self) -> Result<Block>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait encapsulating the node API.
|
|
||||||
///
|
|
||||||
/// All calls should fail when the exact runtime is unknown.
|
|
||||||
pub trait Api: CurrentHeight<BlockNumber=BlockNumber> + BlockNumberToHash<BlockNumber=BlockNumber,Hash=Hash> {
|
|
||||||
/// The block builder for this API type.
|
|
||||||
type BlockBuilder: BlockBuilder;
|
|
||||||
|
|
||||||
/// Get session keys at a given block.
|
|
||||||
fn session_keys(&self, at: &BlockId) -> Result<Vec<SessionKey>>;
|
|
||||||
|
|
||||||
/// Get validators at a given block.
|
|
||||||
fn validators(&self, at: &BlockId) -> Result<Vec<AccountId>>;
|
|
||||||
|
|
||||||
/// Get the value of the randomness beacon at a given block.
|
|
||||||
fn random_seed(&self, at: &BlockId) -> Result<Hash>;
|
|
||||||
|
|
||||||
/// Get the timestamp registered at a block.
|
|
||||||
fn timestamp(&self, at: &BlockId) -> Result<Timestamp>;
|
|
||||||
|
|
||||||
// TODO: remove in favour of validate_transaction
|
|
||||||
|
|
||||||
/// Get the nonce (né index) of an account at a block.
|
|
||||||
fn index(&self, at: &BlockId, account: AccountId) -> Result<Index>;
|
|
||||||
|
|
||||||
/// Get the account id of an address at a block.
|
|
||||||
fn lookup(&self, at: &BlockId, address: Address) -> Result<Option<AccountId>>;
|
|
||||||
|
|
||||||
/// Validate a transaction and determine its dependencies.
|
|
||||||
fn validate_transaction(&self, at: &BlockId, transaction: UncheckedExtrinsic) -> Result<TransactionValidity>;
|
|
||||||
|
|
||||||
/// Evaluate a block. Returns true if the block is good, false if it is known to be bad,
|
|
||||||
/// and an error if we can't evaluate for some reason.
|
|
||||||
fn evaluate_block(&self, at: &BlockId, block: Block) -> Result<bool>;
|
|
||||||
|
|
||||||
/// Build a block on top of the given, with inherent extrinsics pre-pushed.
|
|
||||||
fn build_block(&self, at: &BlockId, inherent_data: InherentData) -> Result<Self::BlockBuilder>;
|
|
||||||
|
|
||||||
/// Attempt to produce the (encoded) inherent extrinsics for a block being built upon the given.
|
|
||||||
/// This may vary by runtime and will fail if a runtime doesn't follow the same API.
|
|
||||||
fn inherent_extrinsics(&self, at: &BlockId, inherent_data: InherentData) -> Result<Vec<UncheckedExtrinsic>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<B, E> BlockBuilder for ClientBlockBuilder<B, E, Block, Blake2Hasher>
|
|
||||||
where
|
|
||||||
B: Backend<Block, Blake2Hasher>,
|
|
||||||
E: CallExecutor<Block, Blake2Hasher> + Clone,
|
|
||||||
{
|
|
||||||
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
|
|
||||||
self.push(extrinsic).map_err(Into::into)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Bake the block with provided extrinsics.
|
|
||||||
fn bake(self) -> Result<Block> {
|
|
||||||
ClientBlockBuilder::bake(self).map_err(Into::into)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<B, E> Api for Client<B, E, Block>
|
|
||||||
where
|
|
||||||
B: Backend<Block, Blake2Hasher>,
|
|
||||||
E: CallExecutor<Block, Blake2Hasher> + Clone,
|
|
||||||
{
|
|
||||||
type BlockBuilder = ClientBlockBuilder<B, E, Block, Blake2Hasher>;
|
|
||||||
|
|
||||||
fn session_keys(&self, at: &BlockId) -> Result<Vec<SessionKey>> {
|
|
||||||
Ok(self.authorities_at(at)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validators(&self, at: &BlockId) -> Result<Vec<AccountId>> {
|
|
||||||
self.call_api_at(at, "validators", &())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn random_seed(&self, at: &BlockId) -> Result<Hash> {
|
|
||||||
self.call_api_at(at, "random_seed", &())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn timestamp(&self, at: &BlockId) -> Result<Timestamp> {
|
|
||||||
self.call_api_at(at, "timestamp", &())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn evaluate_block(&self, at: &BlockId, block: Block) -> Result<bool> {
|
|
||||||
let res: Result<()> = self.call_api_at(at, "execute_block", &block);
|
|
||||||
match res {
|
|
||||||
Ok(()) => Ok(true),
|
|
||||||
Err(err) => match err.kind() {
|
|
||||||
&client::error::ErrorKind::Execution(_) => Ok(false),
|
|
||||||
_ => Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn index(&self, at: &BlockId, account: AccountId) -> Result<Index> {
|
|
||||||
self.call_api_at(at, "account_nonce", &account)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lookup(&self, at: &BlockId, address: Address) -> Result<Option<AccountId>> {
|
|
||||||
self.call_api_at(at, "lookup_address", &address)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_transaction(&self, at: &BlockId, tx: UncheckedExtrinsic) -> Result<TransactionValidity> {
|
|
||||||
self.call_api_at(at, "validate_transaction", &tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_block(&self, at: &BlockId, inherent_data: InherentData) -> Result<Self::BlockBuilder> {
|
|
||||||
let runtime_version = self.runtime_version_at(at)?;
|
|
||||||
|
|
||||||
let mut block_builder = self.new_block_at(at)?;
|
|
||||||
if runtime_version.has_api(*b"inherent", 1) {
|
|
||||||
for inherent in self.inherent_extrinsics(at, inherent_data)? {
|
|
||||||
block_builder.push(inherent)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(block_builder)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inherent_extrinsics(&self, at: &BlockId, inherent_data: InherentData) -> Result<Vec<UncheckedExtrinsic>> {
|
|
||||||
self.call_api_at(at, "inherent_extrinsics", &inherent_data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -11,7 +11,6 @@ error-chain = "0.12"
|
|||||||
log = "0.3"
|
log = "0.3"
|
||||||
exit-future = "0.1"
|
exit-future = "0.1"
|
||||||
rhododendron = "0.3"
|
rhododendron = "0.3"
|
||||||
node-api = { path = "../api" }
|
|
||||||
node-primitives = { path = "../primitives" }
|
node-primitives = { path = "../primitives" }
|
||||||
node-runtime = { path = "../runtime" }
|
node-runtime = { path = "../runtime" }
|
||||||
node-transaction-pool = { path = "../transaction-pool" }
|
node-transaction-pool = { path = "../transaction-pool" }
|
||||||
@@ -20,6 +19,7 @@ parity-codec = { version = "2.0" }
|
|||||||
substrate-primitives = { path = "../../core/primitives" }
|
substrate-primitives = { path = "../../core/primitives" }
|
||||||
substrate-client = { path = "../../core/client" }
|
substrate-client = { path = "../../core/client" }
|
||||||
sr-primitives = { path = "../../core/sr-primitives" }
|
sr-primitives = { path = "../../core/sr-primitives" }
|
||||||
|
srml-system = { path = "../../srml/system" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
substrate-keyring = { path = "../../core/keyring" }
|
substrate-keyring = { path = "../../core/keyring" }
|
||||||
|
|||||||
@@ -17,10 +17,11 @@
|
|||||||
//! Errors that can occur during the consensus process.
|
//! Errors that can occur during the consensus process.
|
||||||
|
|
||||||
use primitives::AuthorityId;
|
use primitives::AuthorityId;
|
||||||
|
use client;
|
||||||
|
|
||||||
error_chain! {
|
error_chain! {
|
||||||
links {
|
links {
|
||||||
Api(::node_api::Error, ::node_api::ErrorKind);
|
Client(client::error::Error, client::error::ErrorKind);
|
||||||
Bft(::bft::Error, ::bft::ErrorKind);
|
Bft(::bft::Error, ::bft::ErrorKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,13 +20,11 @@ use super::MAX_TRANSACTIONS_SIZE;
|
|||||||
|
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use node_runtime::{Block as GenericBlock, CheckedBlock};
|
use node_runtime::{Block as GenericBlock, CheckedBlock};
|
||||||
use node_primitives::{Block, Hash, BlockNumber, Timestamp};
|
use node_primitives::{Hash, BlockNumber, Timestamp};
|
||||||
|
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As};
|
||||||
|
|
||||||
|
|
||||||
error_chain! {
|
error_chain! {
|
||||||
links {
|
|
||||||
Api(::node_api::Error, ::node_api::ErrorKind);
|
|
||||||
}
|
|
||||||
|
|
||||||
errors {
|
errors {
|
||||||
BadProposalFormat {
|
BadProposalFormat {
|
||||||
description("Proposal provided not a block."),
|
description("Proposal provided not a block."),
|
||||||
@@ -56,12 +54,16 @@ error_chain! {
|
|||||||
|
|
||||||
/// Attempt to evaluate a substrate block as a node block, returning error
|
/// Attempt to evaluate a substrate block as a node block, returning error
|
||||||
/// upon any initial validity checks failing.
|
/// upon any initial validity checks failing.
|
||||||
pub fn evaluate_initial(
|
pub fn evaluate_initial<Block: BlockT, Hash>(
|
||||||
proposal: &Block,
|
proposal: &Block,
|
||||||
now: Timestamp,
|
now: Timestamp,
|
||||||
parent_hash: &Hash,
|
parent_hash: &Hash,
|
||||||
parent_number: BlockNumber,
|
parent_number: <<Block as BlockT>::Header as HeaderT>::Number,
|
||||||
) -> Result<CheckedBlock> {
|
) -> Result<CheckedBlock>
|
||||||
|
where
|
||||||
|
Hash: PartialEq<<<GenericBlock as BlockT>::Header as HeaderT>::Hash>,
|
||||||
|
Hash: Into<self::Hash> + Clone,
|
||||||
|
{
|
||||||
const MAX_TIMESTAMP_DRIFT: Timestamp = 60;
|
const MAX_TIMESTAMP_DRIFT: Timestamp = 60;
|
||||||
|
|
||||||
let encoded = Encode::encode(proposal);
|
let encoded = Encode::encode(proposal);
|
||||||
@@ -77,12 +79,12 @@ pub fn evaluate_initial(
|
|||||||
bail!(ErrorKind::ProposalTooLarge(transactions_size))
|
bail!(ErrorKind::ProposalTooLarge(transactions_size))
|
||||||
}
|
}
|
||||||
|
|
||||||
if proposal.header.parent_hash != *parent_hash {
|
if *parent_hash != *proposal.header().parent_hash() {
|
||||||
bail!(ErrorKind::WrongParentHash(*parent_hash, proposal.header.parent_hash));
|
bail!(ErrorKind::WrongParentHash((*parent_hash).clone().into(), proposal.header.parent_hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
if proposal.header.number != parent_number + 1 {
|
if parent_number.as_() + 1 != *proposal.header().number() {
|
||||||
bail!(ErrorKind::WrongNumber(parent_number + 1, proposal.header.number));
|
bail!(ErrorKind::WrongNumber(parent_number.as_() + 1, proposal.header.number));
|
||||||
}
|
}
|
||||||
|
|
||||||
let block_timestamp = proposal.timestamp();
|
let block_timestamp = proposal.timestamp();
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
//! This service uses BFT consensus provided by the substrate.
|
//! This service uses BFT consensus provided by the substrate.
|
||||||
|
|
||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
extern crate node_api;
|
|
||||||
extern crate node_transaction_pool as transaction_pool;
|
extern crate node_transaction_pool as transaction_pool;
|
||||||
extern crate node_runtime;
|
extern crate node_runtime;
|
||||||
extern crate node_primitives;
|
extern crate node_primitives;
|
||||||
@@ -26,6 +25,7 @@ extern crate substrate_bft as bft;
|
|||||||
extern crate parity_codec as codec;
|
extern crate parity_codec as codec;
|
||||||
extern crate substrate_primitives as primitives;
|
extern crate substrate_primitives as primitives;
|
||||||
extern crate sr_primitives as runtime_primitives;
|
extern crate sr_primitives as runtime_primitives;
|
||||||
|
extern crate srml_system;
|
||||||
extern crate substrate_client as client;
|
extern crate substrate_client as client;
|
||||||
|
|
||||||
extern crate exit_future;
|
extern crate exit_future;
|
||||||
@@ -45,12 +45,15 @@ extern crate substrate_keyring;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{self, Duration, Instant};
|
use std::time::{self, Duration, Instant};
|
||||||
|
|
||||||
|
use client::{Client as SubstrateClient, CallExecutor};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use node_api::Api;
|
use node_primitives::{AccountId, Timestamp, SessionKey, InherentData};
|
||||||
use node_primitives::{AccountId, Hash, Block, BlockId, BlockNumber, Header, Timestamp, SessionKey};
|
use node_runtime::Runtime;
|
||||||
use runtime_primitives::generic::Era;
|
use primitives::{AuthorityId, ed25519, Blake2Hasher};
|
||||||
use primitives::{AuthorityId, ed25519};
|
use runtime_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, As};
|
||||||
use transaction_pool::TransactionPool;
|
use runtime_primitives::generic::{BlockId, Era};
|
||||||
|
use srml_system::Trait as SystemT;
|
||||||
|
use transaction_pool::{TransactionPool, Client as TPClient};
|
||||||
use tokio::runtime::TaskExecutor;
|
use tokio::runtime::TaskExecutor;
|
||||||
use tokio::timer::Delay;
|
use tokio::timer::Delay;
|
||||||
|
|
||||||
@@ -58,7 +61,7 @@ use futures::prelude::*;
|
|||||||
use futures::future;
|
use futures::future;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
pub use self::error::{ErrorKind, Error};
|
pub use self::error::{ErrorKind, Error, Result};
|
||||||
pub use self::offline_tracker::OfflineTracker;
|
pub use self::offline_tracker::OfflineTracker;
|
||||||
pub use service::Service;
|
pub use service::Service;
|
||||||
|
|
||||||
@@ -73,33 +76,133 @@ pub type SharedOfflineTracker = Arc<RwLock<OfflineTracker>>;
|
|||||||
// block size limit.
|
// block size limit.
|
||||||
const MAX_TRANSACTIONS_SIZE: usize = 4 * 1024 * 1024;
|
const MAX_TRANSACTIONS_SIZE: usize = 4 * 1024 * 1024;
|
||||||
|
|
||||||
|
/// Build new blocks.
|
||||||
|
pub trait BlockBuilder<Block: BlockT> {
|
||||||
|
/// Push an extrinsic onto the block. Fails if the extrinsic is invalid.
|
||||||
|
fn push_extrinsic(&mut self, extrinsic: <Block as BlockT>::Extrinsic) -> Result<()>;
|
||||||
|
|
||||||
|
/// Bake the block with provided extrinsics.
|
||||||
|
fn bake(self) -> Result<Block>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Local client abstraction for the consensus.
|
||||||
|
pub trait AuthoringApi: Send + Sync {
|
||||||
|
/// The block used for this API type.
|
||||||
|
type Block: BlockT;
|
||||||
|
/// The block builder for this API type.
|
||||||
|
type BlockBuilder: BlockBuilder<Self::Block>;
|
||||||
|
|
||||||
|
/// Get the value of the randomness beacon at a given block.
|
||||||
|
fn random_seed(&self, at: &BlockId<Self::Block>) -> Result<<Self::Block as BlockT>::Hash>;
|
||||||
|
|
||||||
|
/// Get validators at a given block.
|
||||||
|
fn validators(&self, at: &BlockId<Self::Block>) -> Result<Vec<AccountId>>;
|
||||||
|
|
||||||
|
/// Build a block on top of the given, with inherent extrinsics pre-pushed.
|
||||||
|
fn build_block(&self, at: &BlockId<Self::Block>, inherent_data: InherentData) -> Result<Self::BlockBuilder>;
|
||||||
|
|
||||||
|
/// Get the nonce (né index) of an account at a block.
|
||||||
|
fn index(&self, at: &BlockId<Self::Block>, account: AccountId) -> Result<u64>;
|
||||||
|
|
||||||
|
/// Attempt to produce the (encoded) inherent extrinsics for a block being built upon the given.
|
||||||
|
/// This may vary by runtime and will fail if a runtime doesn't follow the same API.
|
||||||
|
fn inherent_extrinsics(&self, at: &BlockId<Self::Block>, inherent_data: InherentData) -> Result<Vec<<Self::Block as BlockT>::Extrinsic>>;
|
||||||
|
|
||||||
|
/// Evaluate a block. Returns true if the block is good, false if it is known to be bad,
|
||||||
|
/// and an error if we can't evaluate for some reason.
|
||||||
|
fn evaluate_block(&self, at: &BlockId<Self::Block>, block: Self::Block) -> Result<bool>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, E, Block> BlockBuilder<Block> for client::block_builder::BlockBuilder<B, E, Block, Blake2Hasher> where
|
||||||
|
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
|
||||||
|
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
|
||||||
|
Block: BlockT
|
||||||
|
{
|
||||||
|
fn push_extrinsic(&mut self, extrinsic: <Block as BlockT>::Extrinsic) -> Result<()> {
|
||||||
|
client::block_builder::BlockBuilder::push(self, extrinsic).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bake(self) -> Result<Block> {
|
||||||
|
client::block_builder::BlockBuilder::bake(self).map_err(Into::into)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, E, Block> AuthoringApi for SubstrateClient<B, E, Block> where
|
||||||
|
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
|
||||||
|
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
|
||||||
|
Block: BlockT,
|
||||||
|
{
|
||||||
|
type Block = Block;
|
||||||
|
type BlockBuilder = client::block_builder::BlockBuilder<B, E, Block, Blake2Hasher>;
|
||||||
|
|
||||||
|
fn random_seed(&self, at: &BlockId<Block>) -> Result<<Self::Block as BlockT>::Hash> {
|
||||||
|
self.call_api_at(at, "random_seed", &()).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validators(&self, at: &BlockId<Block>) -> Result<Vec<AccountId>> {
|
||||||
|
self.call_api_at(at, "validators", &()).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_block(&self, at: &BlockId<Block>, inherent_data: InherentData) -> Result<Self::BlockBuilder> {
|
||||||
|
let runtime_version = self.runtime_version_at(at)?;
|
||||||
|
|
||||||
|
let mut block_builder = self.new_block_at(at)?;
|
||||||
|
if runtime_version.has_api(*b"inherent", 1) {
|
||||||
|
for inherent in self.inherent_extrinsics(at, inherent_data)? {
|
||||||
|
block_builder.push(inherent)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(block_builder)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index(&self, at: &BlockId<Block>, account: AccountId) -> Result<u64> {
|
||||||
|
self.call_api_at(at, "account_nonce", &account).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inherent_extrinsics(&self, at: &BlockId<Self::Block>, inherent_data: InherentData) -> Result<Vec<<Block as BlockT>::Extrinsic>> {
|
||||||
|
self.call_api_at(at, "inherent_extrinsics", &inherent_data).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn evaluate_block(&self, at: &BlockId<Self::Block>, block: Self::Block) -> Result<bool> {
|
||||||
|
let res: client::error::Result<()> = self.call_api_at(at, "execute_block", &block);
|
||||||
|
match res {
|
||||||
|
Ok(()) => Ok(true),
|
||||||
|
Err(err) => match err.kind() {
|
||||||
|
&client::error::ErrorKind::Execution(_) => Ok(false),
|
||||||
|
_ => Err(err.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A long-lived network which can create BFT message routing processes on demand.
|
/// A long-lived network which can create BFT message routing processes on demand.
|
||||||
pub trait Network {
|
pub trait Network {
|
||||||
|
/// The block used for this API type.
|
||||||
|
type Block: BlockT;
|
||||||
/// The input stream of BFT messages. Should never logically conclude.
|
/// The input stream of BFT messages. Should never logically conclude.
|
||||||
type Input: Stream<Item=bft::Communication<Block>,Error=Error>;
|
type Input: Stream<Item=bft::Communication<Self::Block>,Error=Error>;
|
||||||
/// The output sink of BFT messages. Messages sent here should eventually pass to all
|
/// The output sink of BFT messages. Messages sent here should eventually pass to all
|
||||||
/// current authorities.
|
/// current authorities.
|
||||||
type Output: Sink<SinkItem=bft::Communication<Block>,SinkError=Error>;
|
type Output: Sink<SinkItem=bft::Communication<Self::Block>,SinkError=Error>;
|
||||||
|
|
||||||
/// Instantiate input and output streams.
|
/// Instantiate input and output streams.
|
||||||
fn communication_for(
|
fn communication_for(
|
||||||
&self,
|
&self,
|
||||||
validators: &[SessionKey],
|
validators: &[SessionKey],
|
||||||
local_id: SessionKey,
|
local_id: SessionKey,
|
||||||
parent_hash: Hash,
|
parent_hash: <Self::Block as BlockT>::Hash,
|
||||||
task_executor: TaskExecutor
|
task_executor: TaskExecutor
|
||||||
) -> (Self::Input, Self::Output);
|
) -> (Self::Input, Self::Output);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Proposer factory.
|
/// Proposer factory.
|
||||||
pub struct ProposerFactory<N, P>
|
pub struct ProposerFactory<N, C> where
|
||||||
where
|
C: AuthoringApi + TPClient,
|
||||||
P: Api + Send + Sync + 'static
|
|
||||||
{
|
{
|
||||||
/// The client instance.
|
/// The client instance.
|
||||||
pub client: Arc<P>,
|
pub client: Arc<C>,
|
||||||
/// The transaction pool.
|
/// The transaction pool.
|
||||||
pub transaction_pool: Arc<TransactionPool<P>>,
|
pub transaction_pool: Arc<TransactionPool<C>>,
|
||||||
/// The backing network handle.
|
/// The backing network handle.
|
||||||
pub network: N,
|
pub network: N,
|
||||||
/// handle to remote task executor
|
/// handle to remote task executor
|
||||||
@@ -108,32 +211,31 @@ pub struct ProposerFactory<N, P>
|
|||||||
pub offline: SharedOfflineTracker,
|
pub offline: SharedOfflineTracker,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N, P> bft::Environment<Block> for ProposerFactory<N, P>
|
impl<N, C> bft::Environment<<C as AuthoringApi>::Block> for ProposerFactory<N, C> where
|
||||||
where
|
N: Network<Block=<C as AuthoringApi>::Block>,
|
||||||
N: Network,
|
C: AuthoringApi + TPClient<Block=<C as AuthoringApi>::Block>,
|
||||||
P: Api + Send + Sync + 'static,
|
<<C as AuthoringApi>::Block as BlockT>::Hash:
|
||||||
|
Into<<Runtime as SystemT>::Hash> + PartialEq<primitives::H256> + Into<primitives::H256>
|
||||||
{
|
{
|
||||||
type Proposer = Proposer<P>;
|
type Proposer = Proposer<C>;
|
||||||
type Input = N::Input;
|
type Input = N::Input;
|
||||||
type Output = N::Output;
|
type Output = N::Output;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn init(
|
fn init(
|
||||||
&self,
|
&self,
|
||||||
parent_header: &Header,
|
parent_header: &<<C as AuthoringApi>::Block as BlockT>::Header,
|
||||||
authorities: &[AuthorityId],
|
authorities: &[AuthorityId],
|
||||||
sign_with: Arc<ed25519::Pair>,
|
sign_with: Arc<ed25519::Pair>,
|
||||||
) -> Result<(Self::Proposer, Self::Input, Self::Output), Error> {
|
) -> Result<(Self::Proposer, Self::Input, Self::Output)> {
|
||||||
use runtime_primitives::traits::{Hash as HashT, BlakeTwo256};
|
|
||||||
|
|
||||||
// force delay in evaluation this long.
|
// force delay in evaluation this long.
|
||||||
const FORCE_DELAY: Timestamp = 5;
|
const FORCE_DELAY: Timestamp = 5;
|
||||||
|
|
||||||
let parent_hash = parent_header.hash().into();
|
let parent_hash = parent_header.hash();
|
||||||
|
|
||||||
let id = BlockId::hash(parent_hash);
|
let id = BlockId::hash(parent_hash);
|
||||||
let random_seed = self.client.random_seed(&id)?;
|
let random_seed = self.client.random_seed(&id)?;
|
||||||
let random_seed = BlakeTwo256::hash(&*random_seed);
|
let random_seed = <<<C as AuthoringApi>::Block as BlockT>::Header as HeaderT>::Hashing::hash(random_seed.as_ref());
|
||||||
|
|
||||||
let validators = self.client.validators(&id)?;
|
let validators = self.client.validators(&id)?;
|
||||||
self.offline.write().note_new_block(&validators[..]);
|
self.offline.write().note_new_block(&validators[..]);
|
||||||
@@ -154,7 +256,7 @@ impl<N, P> bft::Environment<Block> for ProposerFactory<N, P>
|
|||||||
local_key: sign_with,
|
local_key: sign_with,
|
||||||
parent_hash,
|
parent_hash,
|
||||||
parent_id: id,
|
parent_id: id,
|
||||||
parent_number: parent_header.number,
|
parent_number: *parent_header.number(),
|
||||||
random_seed,
|
random_seed,
|
||||||
transaction_pool: self.transaction_pool.clone(),
|
transaction_pool: self.transaction_pool.clone(),
|
||||||
offline: self.offline.clone(),
|
offline: self.offline.clone(),
|
||||||
@@ -167,43 +269,42 @@ impl<N, P> bft::Environment<Block> for ProposerFactory<N, P>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The proposer logic.
|
/// The proposer logic.
|
||||||
pub struct Proposer<C: Api + Send + Sync> {
|
pub struct Proposer<C: AuthoringApi + TPClient> {
|
||||||
client: Arc<C>,
|
client: Arc<C>,
|
||||||
start: Instant,
|
start: Instant,
|
||||||
local_key: Arc<ed25519::Pair>,
|
local_key: Arc<ed25519::Pair>,
|
||||||
parent_hash: Hash,
|
parent_hash: <<C as AuthoringApi>::Block as BlockT>::Hash,
|
||||||
parent_id: BlockId,
|
parent_id: BlockId<<C as AuthoringApi>::Block>,
|
||||||
parent_number: BlockNumber,
|
parent_number: <<<C as AuthoringApi>::Block as BlockT>::Header as HeaderT>::Number,
|
||||||
random_seed: Hash,
|
random_seed: <<C as AuthoringApi>::Block as BlockT>::Hash,
|
||||||
transaction_pool: Arc<TransactionPool<C>>,
|
transaction_pool: Arc<TransactionPool<C>>,
|
||||||
offline: SharedOfflineTracker,
|
offline: SharedOfflineTracker,
|
||||||
validators: Vec<AccountId>,
|
validators: Vec<AccountId>,
|
||||||
minimum_timestamp: u64,
|
minimum_timestamp: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Api + Send + Sync> Proposer<C> {
|
impl<C: AuthoringApi + TPClient> Proposer<C> {
|
||||||
fn primary_index(&self, round_number: usize, len: usize) -> usize {
|
fn primary_index(&self, round_number: usize, len: usize) -> usize {
|
||||||
use primitives::uint::U256;
|
use primitives::uint::U256;
|
||||||
|
|
||||||
let big_len = U256::from(len);
|
let big_len = U256::from(len);
|
||||||
let offset = U256::from_big_endian(&self.random_seed.0) % big_len;
|
let offset = U256::from_big_endian(self.random_seed.as_ref()) % big_len;
|
||||||
let offset = offset.low_u64() as usize + round_number;
|
let offset = offset.low_u64() as usize + round_number;
|
||||||
offset % len
|
offset % len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> bft::Proposer<Block> for Proposer<C>
|
impl<C> bft::Proposer<<C as AuthoringApi>::Block> for Proposer<C> where
|
||||||
where
|
C: AuthoringApi + TPClient<Block=<C as AuthoringApi>::Block>,
|
||||||
C: Api + Send + Sync,
|
<<C as AuthoringApi>::Block as BlockT>::Hash:
|
||||||
|
Into<<Runtime as SystemT>::Hash> + PartialEq<primitives::H256> + Into<primitives::H256>
|
||||||
{
|
{
|
||||||
type Create = Result<Block, Error>;
|
type Create = Result<<C as AuthoringApi>::Block>;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Evaluate = Box<Future<Item=bool, Error=Error>>;
|
type Evaluate = Box<Future<Item=bool, Error=Error>>;
|
||||||
|
|
||||||
fn propose(&self) -> Result<Block, Error> {
|
fn propose(&self) -> Result<<C as AuthoringApi>::Block> {
|
||||||
use node_api::BlockBuilder;
|
use runtime_primitives::traits::BlakeTwo256;
|
||||||
use runtime_primitives::traits::{Hash as HashT, BlakeTwo256};
|
|
||||||
use node_primitives::InherentData;
|
|
||||||
|
|
||||||
const MAX_VOTE_OFFLINE_SECONDS: Duration = Duration::from_secs(60);
|
const MAX_VOTE_OFFLINE_SECONDS: Duration = Duration::from_secs(60);
|
||||||
|
|
||||||
@@ -259,10 +360,10 @@ impl<C> bft::Proposer<Block> for Proposer<C>
|
|||||||
let block = block_builder.bake()?;
|
let block = block_builder.bake()?;
|
||||||
|
|
||||||
info!("Proposing block [number: {}; hash: {}; parent_hash: {}; extrinsics: [{}]]",
|
info!("Proposing block [number: {}; hash: {}; parent_hash: {}; extrinsics: [{}]]",
|
||||||
block.header.number,
|
block.header().number(),
|
||||||
Hash::from(block.header.hash()),
|
<<C as AuthoringApi>::Block as BlockT>::Hash::from(block.header().hash()),
|
||||||
block.header.parent_hash,
|
block.header().parent_hash(),
|
||||||
block.extrinsics.iter()
|
block.extrinsics().iter()
|
||||||
.map(|xt| format!("{}", BlakeTwo256::hash_of(xt)))
|
.map(|xt| format!("{}", BlakeTwo256::hash_of(xt)))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ")
|
.join(", ")
|
||||||
@@ -281,7 +382,7 @@ impl<C> bft::Proposer<Block> for Proposer<C>
|
|||||||
Ok(substrate_block)
|
Ok(substrate_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate(&self, unchecked_proposal: &Block) -> Self::Evaluate {
|
fn evaluate(&self, unchecked_proposal: &<C as AuthoringApi>::Block) -> Self::Evaluate {
|
||||||
debug!(target: "bft", "evaluating block on top of parent ({}, {:?})", self.parent_number, self.parent_hash);
|
debug!(target: "bft", "evaluating block on top of parent ({}, {:?})", self.parent_number, self.parent_hash);
|
||||||
|
|
||||||
let current_timestamp = current_timestamp();
|
let current_timestamp = current_timestamp();
|
||||||
@@ -359,10 +460,9 @@ impl<C> bft::Proposer<Block> for Proposer<C>
|
|||||||
proposer
|
proposer
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, bft::Misbehavior<Hash>)>) {
|
fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, bft::Misbehavior<<<C as AuthoringApi>::Block as BlockT>::Hash>)>) {
|
||||||
use rhododendron::Misbehavior as GenericMisbehavior;
|
use rhododendron::Misbehavior as GenericMisbehavior;
|
||||||
use runtime_primitives::bft::{MisbehaviorKind, MisbehaviorReport};
|
use runtime_primitives::bft::{MisbehaviorKind, MisbehaviorReport};
|
||||||
use node_primitives::UncheckedExtrinsic as GenericExtrinsic;
|
|
||||||
use node_runtime::{Call, UncheckedExtrinsic, ConsensusCall};
|
use node_runtime::{Call, UncheckedExtrinsic, ConsensusCall};
|
||||||
|
|
||||||
let local_id = self.local_key.public().0.into();
|
let local_id = self.local_key.public().0.into();
|
||||||
@@ -371,7 +471,7 @@ impl<C> bft::Proposer<Block> for Proposer<C>
|
|||||||
.filter(|tx| tx.verified.sender == local_id)
|
.filter(|tx| tx.verified.sender == local_id)
|
||||||
.last()
|
.last()
|
||||||
.map(|tx| Ok(tx.verified.index()))
|
.map(|tx| Ok(tx.verified.index()))
|
||||||
.unwrap_or_else(|| self.client.index(&self.parent_id, local_id))
|
.unwrap_or_else(|| AuthoringApi::index(self.client.as_ref(), &self.parent_id, local_id))
|
||||||
);
|
);
|
||||||
|
|
||||||
match cur_index {
|
match cur_index {
|
||||||
@@ -389,16 +489,16 @@ impl<C> bft::Proposer<Block> for Proposer<C>
|
|||||||
|
|
||||||
for (target, misbehavior) in misbehavior {
|
for (target, misbehavior) in misbehavior {
|
||||||
let report = MisbehaviorReport {
|
let report = MisbehaviorReport {
|
||||||
parent_hash: self.parent_hash,
|
parent_hash: self.parent_hash.into(),
|
||||||
parent_number: self.parent_number,
|
parent_number: self.parent_number.as_(),
|
||||||
target,
|
target,
|
||||||
misbehavior: match misbehavior {
|
misbehavior: match misbehavior {
|
||||||
GenericMisbehavior::ProposeOutOfTurn(_, _, _) => continue,
|
GenericMisbehavior::ProposeOutOfTurn(_, _, _) => continue,
|
||||||
GenericMisbehavior::DoublePropose(_, _, _) => continue,
|
GenericMisbehavior::DoublePropose(_, _, _) => continue,
|
||||||
GenericMisbehavior::DoublePrepare(round, (h1, s1), (h2, s2))
|
GenericMisbehavior::DoublePrepare(round, (h1, s1), (h2, s2))
|
||||||
=> MisbehaviorKind::BftDoublePrepare(round as u32, (h1, s1.signature), (h2, s2.signature)),
|
=> MisbehaviorKind::BftDoublePrepare(round as u32, (h1.into(), s1.signature), (h2.into(), s2.signature)),
|
||||||
GenericMisbehavior::DoubleCommit(round, (h1, s1), (h2, s2))
|
GenericMisbehavior::DoubleCommit(round, (h1, s1), (h2, s2))
|
||||||
=> MisbehaviorKind::BftDoubleCommit(round as u32, (h1, s1.signature), (h2, s2.signature)),
|
=> MisbehaviorKind::BftDoubleCommit(round as u32, (h1.into(), s1.signature), (h2.into(), s2.signature)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let payload = (next_index, Call::Consensus(ConsensusCall::report_misbehavior(report)), Era::immortal(), self.client.genesis_hash());
|
let payload = (next_index, Call::Consensus(ConsensusCall::report_misbehavior(report)), Era::immortal(), self.client.genesis_hash());
|
||||||
@@ -410,8 +510,9 @@ impl<C> bft::Proposer<Block> for Proposer<C>
|
|||||||
signature: Some((node_runtime::RawAddress::Id(local_id), signature, payload.0, Era::immortal())),
|
signature: Some((node_runtime::RawAddress::Id(local_id), signature, payload.0, Era::immortal())),
|
||||||
function: payload.1,
|
function: payload.1,
|
||||||
};
|
};
|
||||||
let uxt: GenericExtrinsic = Decode::decode(&mut extrinsic.encode().as_slice()).expect("Encoded extrinsic is valid");
|
let uxt: <<C as AuthoringApi>::Block as BlockT>::Extrinsic = Decode::decode(&mut extrinsic.encode().as_slice()).expect("Encoded extrinsic is valid");
|
||||||
self.transaction_pool.submit_one(&BlockId::hash(self.parent_hash), uxt)
|
let hash = BlockId::<<C as AuthoringApi>::Block>::hash(self.parent_hash);
|
||||||
|
self.transaction_pool.submit_one(&hash, uxt)
|
||||||
.expect("locally signed extrinsic is valid; qed");
|
.expect("locally signed extrinsic is valid; qed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,16 +26,16 @@ use bft::{self, BftService};
|
|||||||
use client::{BlockchainEvents, ChainHead, BlockBody};
|
use client::{BlockchainEvents, ChainHead, BlockBody};
|
||||||
use ed25519;
|
use ed25519;
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use node_api::Api;
|
use transaction_pool::{TransactionPool, Client as TPClient};
|
||||||
use node_primitives::{Block, Header};
|
use primitives;
|
||||||
use transaction_pool::TransactionPool;
|
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
||||||
|
|
||||||
use tokio::executor::current_thread::TaskExecutor as LocalThreadHandle;
|
use tokio::executor::current_thread::TaskExecutor as LocalThreadHandle;
|
||||||
use tokio::runtime::TaskExecutor as ThreadPoolHandle;
|
use tokio::runtime::TaskExecutor as ThreadPoolHandle;
|
||||||
use tokio::runtime::current_thread::Runtime as LocalRuntime;
|
use tokio::runtime::current_thread::Runtime as LocalRuntime;
|
||||||
use tokio::timer::Interval;
|
use tokio::timer::Interval;
|
||||||
|
|
||||||
use super::{Network, ProposerFactory};
|
use super::{Network, ProposerFactory, AuthoringApi};
|
||||||
use error;
|
use error;
|
||||||
|
|
||||||
const TIMER_DELAY_MS: u64 = 5000;
|
const TIMER_DELAY_MS: u64 = 5000;
|
||||||
@@ -43,15 +43,16 @@ const TIMER_INTERVAL_MS: u64 = 500;
|
|||||||
|
|
||||||
// spin up an instance of BFT agreement on the current thread's executor.
|
// spin up an instance of BFT agreement on the current thread's executor.
|
||||||
// panics if there is no current thread executor.
|
// panics if there is no current thread executor.
|
||||||
fn start_bft<F, C>(
|
fn start_bft<F, C, Block>(
|
||||||
header: Header,
|
header: <Block as BlockT>::Header,
|
||||||
bft_service: Arc<BftService<Block, F, C>>,
|
bft_service: Arc<BftService<Block, F, C>>,
|
||||||
) where
|
) where
|
||||||
F: bft::Environment<Block> + 'static,
|
F: bft::Environment<Block> + 'static,
|
||||||
C: bft::BlockImport<Block> + bft::Authorities<Block> + 'static,
|
C: bft::BlockImport<Block> + bft::Authorities<Block> + 'static,
|
||||||
F::Error: ::std::fmt::Debug,
|
F::Error: ::std::fmt::Debug,
|
||||||
<F::Proposer as bft::Proposer<Block>>::Error: ::std::fmt::Display + Into<error::Error>,
|
<F::Proposer as bft::Proposer<Block>>::Error: ::std::fmt::Display + Into<error::Error>,
|
||||||
<F as bft::Environment<Block>>::Error: ::std::fmt::Display
|
<F as bft::Environment<Block>>::Error: ::std::fmt::Display,
|
||||||
|
Block: BlockT,
|
||||||
{
|
{
|
||||||
let mut handle = LocalThreadHandle::current();
|
let mut handle = LocalThreadHandle::current();
|
||||||
match bft_service.build_upon(&header) {
|
match bft_service.build_upon(&header) {
|
||||||
@@ -80,10 +81,15 @@ impl Service {
|
|||||||
key: ed25519::Pair,
|
key: ed25519::Pair,
|
||||||
) -> Service
|
) -> Service
|
||||||
where
|
where
|
||||||
A: Api + Send + Sync + 'static,
|
A: AuthoringApi + TPClient<Block = <A as AuthoringApi>::Block> + 'static,
|
||||||
C: BlockchainEvents<Block> + ChainHead<Block> + BlockBody<Block>,
|
C: BlockchainEvents<<A as AuthoringApi>::Block>
|
||||||
C: bft::BlockImport<Block> + bft::Authorities<Block> + Send + Sync + 'static,
|
+ ChainHead<<A as AuthoringApi>::Block>
|
||||||
N: Network + Send + 'static,
|
+ BlockBody<<A as AuthoringApi>::Block>,
|
||||||
|
C: bft::BlockImport<<A as AuthoringApi>::Block>
|
||||||
|
+ bft::Authorities<<A as AuthoringApi>::Block> + Send + Sync + 'static,
|
||||||
|
primitives::H256: From<<<A as AuthoringApi>::Block as BlockT>::Hash>,
|
||||||
|
<<A as AuthoringApi>::Block as BlockT>::Hash: PartialEq<primitives::H256> + PartialEq,
|
||||||
|
N: Network<Block = <A as AuthoringApi>::Block> + Send + 'static,
|
||||||
{
|
{
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use super::OfflineTracker;
|
use super::OfflineTracker;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
|||||||
description = "Substrate node networking protocol"
|
description = "Substrate node networking protocol"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
node-api = { path = "../api" }
|
|
||||||
node-consensus = { path = "../consensus" }
|
node-consensus = { path = "../consensus" }
|
||||||
node-primitives = { path = "../primitives" }
|
node-primitives = { path = "../primitives" }
|
||||||
substrate-bft = { path = "../../core/bft" }
|
substrate-bft = { path = "../../core/bft" }
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ use bft;
|
|||||||
use substrate_primitives::ed25519;
|
use substrate_primitives::ed25519;
|
||||||
use substrate_network::{self as net, generic_message as msg};
|
use substrate_network::{self as net, generic_message as msg};
|
||||||
use substrate_network::consensus_gossip::ConsensusMessage;
|
use substrate_network::consensus_gossip::ConsensusMessage;
|
||||||
use node_api::Api;
|
use node_consensus::{AuthoringApi, Network};
|
||||||
use node_consensus::Network;
|
|
||||||
use node_primitives::{Block, Hash, SessionKey};
|
use node_primitives::{Block, Hash, SessionKey};
|
||||||
use rhododendron;
|
use rhododendron;
|
||||||
|
|
||||||
@@ -248,12 +247,13 @@ impl<P> Clone for ConsensusNetwork<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A long-lived network which can create parachain statement and BFT message routing processes on demand.
|
/// A long-lived network which can create parachain statement and BFT message routing processes on demand.
|
||||||
impl<P: Api + Send + Sync + 'static> Network for ConsensusNetwork<P> {
|
impl<P: AuthoringApi + Send + Sync + 'static> Network for ConsensusNetwork<P> {
|
||||||
/// The input stream of BFT messages. Should never logically conclude.
|
/// The input stream of BFT messages. Should never logically conclude.
|
||||||
type Input = InputAdapter;
|
type Input = InputAdapter;
|
||||||
/// The output sink of BFT messages. Messages sent here should eventually pass to all
|
/// The output sink of BFT messages. Messages sent here should eventually pass to all
|
||||||
/// current validators.
|
/// current validators.
|
||||||
type Output = BftSink<::node_consensus::Error>;
|
type Output = BftSink<::node_consensus::Error>;
|
||||||
|
type Block = Block;
|
||||||
|
|
||||||
/// Get input and output streams of BFT messages.
|
/// Get input and output streams of BFT messages.
|
||||||
fn communication_for(
|
fn communication_for(
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ extern crate substrate_bft as bft;
|
|||||||
extern crate substrate_network;
|
extern crate substrate_network;
|
||||||
extern crate substrate_primitives;
|
extern crate substrate_primitives;
|
||||||
|
|
||||||
extern crate node_api;
|
|
||||||
extern crate node_consensus;
|
extern crate node_consensus;
|
||||||
extern crate node_primitives;
|
extern crate node_primitives;
|
||||||
|
|
||||||
@@ -114,4 +113,3 @@ impl Specialization<Block> for Protocol {
|
|||||||
fn on_block_imported(&mut self, _ctx: &mut Context<Block>, _hash: Hash, _header: &Header) {
|
fn on_block_imported(&mut self, _ctx: &mut Context<Block>, _hash: Hash, _header: &Header) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ log = "0.3"
|
|||||||
slog = "^2"
|
slog = "^2"
|
||||||
tokio = "0.1.7"
|
tokio = "0.1.7"
|
||||||
hex-literal = "0.1"
|
hex-literal = "0.1"
|
||||||
node-api = { path = "../api" }
|
|
||||||
node-primitives = { path = "../primitives" }
|
node-primitives = { path = "../primitives" }
|
||||||
node-runtime = { path = "../runtime" }
|
node-runtime = { path = "../runtime" }
|
||||||
node-executor = { path = "../executor" }
|
node-executor = { path = "../executor" }
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
//! Substrate service. Specialized wrapper over substrate service.
|
//! Substrate service. Specialized wrapper over substrate service.
|
||||||
|
|
||||||
extern crate node_api;
|
|
||||||
extern crate node_primitives;
|
extern crate node_primitives;
|
||||||
extern crate node_runtime;
|
extern crate node_runtime;
|
||||||
extern crate node_executor;
|
extern crate node_executor;
|
||||||
@@ -41,11 +40,12 @@ pub mod chain_spec;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use transaction_pool::TransactionPool;
|
use transaction_pool::TransactionPool;
|
||||||
use node_api::Api;
|
|
||||||
use node_primitives::{Block, Hash};
|
use node_primitives::{Block, Hash};
|
||||||
use node_runtime::GenesisConfig;
|
use node_runtime::GenesisConfig;
|
||||||
use client::Client;
|
use client::Client;
|
||||||
|
use consensus::AuthoringApi;
|
||||||
use node_network::{Protocol as DemoProtocol, consensus::ConsensusNetwork};
|
use node_network::{Protocol as DemoProtocol, consensus::ConsensusNetwork};
|
||||||
|
use transaction_pool::Client as TPApi;
|
||||||
use tokio::runtime::TaskExecutor;
|
use tokio::runtime::TaskExecutor;
|
||||||
use service::FactoryFullConfiguration;
|
use service::FactoryFullConfiguration;
|
||||||
use primitives::{Blake2Hasher};
|
use primitives::{Blake2Hasher};
|
||||||
@@ -63,7 +63,7 @@ pub type NetworkService = network::Service<Block, <Factory as service::ServiceFa
|
|||||||
/// A collection of type to generalise specific components over full / light client.
|
/// A collection of type to generalise specific components over full / light client.
|
||||||
pub trait Components: service::Components {
|
pub trait Components: service::Components {
|
||||||
/// Demo API.
|
/// Demo API.
|
||||||
type Api: 'static + Api + Send + Sync;
|
type Api: 'static + AuthoringApi + TPApi + Send + Sync;
|
||||||
/// Client backend.
|
/// Client backend.
|
||||||
type Backend: 'static + client::backend::Backend<Block, Blake2Hasher>;
|
type Backend: 'static + client::backend::Backend<Block, Blake2Hasher>;
|
||||||
/// Client executor.
|
/// Client executor.
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
|||||||
log = "0.3.0"
|
log = "0.3.0"
|
||||||
error-chain = "0.12"
|
error-chain = "0.12"
|
||||||
parking_lot = "0.4"
|
parking_lot = "0.4"
|
||||||
node-api = { path = "../api" }
|
|
||||||
node-primitives = { path = "../primitives" }
|
node-primitives = { path = "../primitives" }
|
||||||
node-runtime = { path = "../runtime" }
|
node-runtime = { path = "../runtime" }
|
||||||
substrate-client = { path = "../../core/client" }
|
substrate-client = { path = "../../core/client" }
|
||||||
|
|||||||
@@ -15,14 +15,14 @@
|
|||||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use transaction_pool;
|
use transaction_pool;
|
||||||
use node_api;
|
|
||||||
use primitives::Hash;
|
use primitives::Hash;
|
||||||
use runtime::{Address, UncheckedExtrinsic};
|
use runtime::{Address, UncheckedExtrinsic};
|
||||||
|
use client;
|
||||||
|
|
||||||
error_chain! {
|
error_chain! {
|
||||||
links {
|
links {
|
||||||
|
Client(client::error::Error, client::error::ErrorKind);
|
||||||
Pool(transaction_pool::Error, transaction_pool::ErrorKind);
|
Pool(transaction_pool::Error, transaction_pool::ErrorKind);
|
||||||
Api(node_api::Error, node_api::ErrorKind);
|
|
||||||
}
|
}
|
||||||
errors {
|
errors {
|
||||||
/// Unexpected extrinsic format submitted
|
/// Unexpected extrinsic format submitted
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ extern crate substrate_primitives;
|
|||||||
extern crate sr_primitives;
|
extern crate sr_primitives;
|
||||||
extern crate node_runtime as runtime;
|
extern crate node_runtime as runtime;
|
||||||
extern crate node_primitives as primitives;
|
extern crate node_primitives as primitives;
|
||||||
extern crate node_api;
|
|
||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -42,11 +41,16 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
|
use client::{Client as SubstrateClient, CallExecutor};
|
||||||
use transaction_pool::{Readiness, scoring::{Change, Choice}, VerifiedFor, ExtrinsicFor};
|
use transaction_pool::{Readiness, scoring::{Change, Choice}, VerifiedFor, ExtrinsicFor};
|
||||||
use node_api::Api;
|
use primitives::{AccountId, Hash, Index};
|
||||||
use primitives::{AccountId, BlockId, Block, Hash, Index, BlockNumber};
|
|
||||||
use runtime::{Address, UncheckedExtrinsic};
|
use runtime::{Address, UncheckedExtrinsic};
|
||||||
use sr_primitives::traits::{Bounded, Checkable, Hash as HashT, BlakeTwo256, Lookup, CurrentHeight, BlockNumberToHash};
|
use substrate_primitives::{Blake2Hasher};
|
||||||
|
use sr_primitives::generic::BlockId;
|
||||||
|
use sr_primitives::traits::{
|
||||||
|
Bounded, Checkable, Block as BlockT, Hash as HashT, Header as HeaderT, BlakeTwo256, Lookup, CurrentHeight,
|
||||||
|
BlockNumberToHash
|
||||||
|
};
|
||||||
|
|
||||||
pub use transaction_pool::{Options, Status, LightStatus, VerifiedTransaction as VerifiedTransactionOps};
|
pub use transaction_pool::{Options, Status, LightStatus, VerifiedTransaction as VerifiedTransactionOps};
|
||||||
pub use error::{Error, ErrorKind, Result};
|
pub use error::{Error, ErrorKind, Result};
|
||||||
@@ -54,8 +58,38 @@ pub use error::{Error, ErrorKind, Result};
|
|||||||
/// Maximal size of a single encoded extrinsic.
|
/// Maximal size of a single encoded extrinsic.
|
||||||
const MAX_TRANSACTION_SIZE: usize = 4 * 1024 * 1024;
|
const MAX_TRANSACTION_SIZE: usize = 4 * 1024 * 1024;
|
||||||
|
|
||||||
|
/// Local client abstraction for the transaction-pool.
|
||||||
|
pub trait Client:
|
||||||
|
Send
|
||||||
|
+ Sync
|
||||||
|
+ CurrentHeight<BlockNumber=<<<Self as Client>::Block as BlockT>::Header as HeaderT>::Number>
|
||||||
|
+ BlockNumberToHash<BlockNumber=<<<Self as Client>::Block as BlockT>::Header as HeaderT>::Number, Hash=<<Self as Client>::Block as BlockT>::Hash> {
|
||||||
|
/// The block used for this API type.
|
||||||
|
type Block: BlockT;
|
||||||
|
/// Get the nonce (né index) of an account at a block.
|
||||||
|
fn index(&self, at: &BlockId<Self::Block>, account: AccountId) -> Result<u64>;
|
||||||
|
/// Get the account id of an address at a block.
|
||||||
|
fn lookup(&self, at: &BlockId<Self::Block>, address: Address) -> Result<Option<AccountId>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, E, Block> Client for SubstrateClient<B, E, Block> where
|
||||||
|
B: client::backend::Backend<Block, Blake2Hasher> + Send + Sync + 'static,
|
||||||
|
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone + 'static,
|
||||||
|
Block: BlockT,
|
||||||
|
{
|
||||||
|
type Block = Block;
|
||||||
|
|
||||||
|
fn index(&self, at: &BlockId<Block>, account: AccountId) -> Result<u64> {
|
||||||
|
self.call_api_at(at, "account_nonce", &account).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup(&self, at: &BlockId<Block>, address: Address) -> Result<Option<AccountId>> {
|
||||||
|
self.call_api_at(at, "lookup_address", &address).map_err(Into::into)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Type alias for the transaction pool.
|
/// Type alias for the transaction pool.
|
||||||
pub type TransactionPool<A> = transaction_pool::Pool<ChainApi<A>>;
|
pub type TransactionPool<C> = transaction_pool::Pool<ChainApi<C>>;
|
||||||
|
|
||||||
/// A verified transaction which should be includable and non-inherent.
|
/// A verified transaction which should be includable and non-inherent.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -104,15 +138,13 @@ impl transaction_pool::VerifiedTransaction for VerifiedTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The transaction pool logic.
|
/// The transaction pool logic.
|
||||||
pub struct ChainApi<A> {
|
pub struct ChainApi<C: Client> {
|
||||||
api: Arc<A>,
|
api: Arc<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A> ChainApi<A> where
|
impl<C: Client> ChainApi<C> {
|
||||||
A: Api,
|
|
||||||
{
|
|
||||||
/// Create a new instance.
|
/// Create a new instance.
|
||||||
pub fn new(api: Arc<A>) -> Self {
|
pub fn new(api: Arc<C>) -> Self {
|
||||||
ChainApi {
|
ChainApi {
|
||||||
api,
|
api,
|
||||||
}
|
}
|
||||||
@@ -123,20 +155,20 @@ impl<A> ChainApi<A> where
|
|||||||
///
|
///
|
||||||
/// This is due for removal when #721 lands
|
/// This is due for removal when #721 lands
|
||||||
pub struct LocalContext<'a, A: 'a>(&'a Arc<A>);
|
pub struct LocalContext<'a, A: 'a>(&'a Arc<A>);
|
||||||
impl<'a, A: 'a + Api> CurrentHeight for LocalContext<'a, A> {
|
impl<'a, C: 'a + Client> CurrentHeight for LocalContext<'a, C> {
|
||||||
type BlockNumber = BlockNumber;
|
type BlockNumber = <C as CurrentHeight>::BlockNumber;
|
||||||
fn current_height(&self) -> BlockNumber {
|
fn current_height(&self) -> Self::BlockNumber {
|
||||||
self.0.current_height()
|
self.0.current_height()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a, A: 'a + Api> BlockNumberToHash for LocalContext<'a, A> {
|
impl<'a, C: 'a + Client> BlockNumberToHash for LocalContext<'a, C> {
|
||||||
type BlockNumber = BlockNumber;
|
type BlockNumber = <C as BlockNumberToHash>::BlockNumber;
|
||||||
type Hash = Hash;
|
type Hash = <C as BlockNumberToHash>::Hash;
|
||||||
fn block_number_to_hash(&self, n: BlockNumber) -> Option<Hash> {
|
fn block_number_to_hash(&self, n: Self::BlockNumber) -> Option<Self::Hash> {
|
||||||
self.0.block_number_to_hash(n)
|
self.0.block_number_to_hash(n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a, A: 'a + Api> Lookup for LocalContext<'a, A> {
|
impl<'a, C: 'a + Client> Lookup for LocalContext<'a, C> {
|
||||||
type Source = Address;
|
type Source = Address;
|
||||||
type Target = AccountId;
|
type Target = AccountId;
|
||||||
fn lookup(&self, a: Address) -> ::std::result::Result<AccountId, &'static str> {
|
fn lookup(&self, a: Address) -> ::std::result::Result<AccountId, &'static str> {
|
||||||
@@ -144,10 +176,8 @@ impl<'a, A: 'a + Api> Lookup for LocalContext<'a, A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A> transaction_pool::ChainApi for ChainApi<A> where
|
impl<C: Client> transaction_pool::ChainApi for ChainApi<C> {
|
||||||
A: Api + Send + Sync,
|
type Block = C::Block;
|
||||||
{
|
|
||||||
type Block = Block;
|
|
||||||
type Hash = Hash;
|
type Hash = Hash;
|
||||||
type Sender = AccountId;
|
type Sender = AccountId;
|
||||||
type VEx = VerifiedTransaction;
|
type VEx = VerifiedTransaction;
|
||||||
@@ -156,7 +186,7 @@ impl<A> transaction_pool::ChainApi for ChainApi<A> where
|
|||||||
type Score = u64;
|
type Score = u64;
|
||||||
type Event = ();
|
type Event = ();
|
||||||
|
|
||||||
fn verify_transaction(&self, _at: &BlockId, xt: &ExtrinsicFor<Self>) -> Result<Self::VEx> {
|
fn verify_transaction(&self, _at: &BlockId<Self::Block>, xt: &ExtrinsicFor<Self>) -> Result<Self::VEx> {
|
||||||
let encoded = xt.encode();
|
let encoded = xt.encode();
|
||||||
let uxt = UncheckedExtrinsic::decode(&mut encoded.as_slice()).ok_or_else(|| ErrorKind::InvalidExtrinsicFormat)?;
|
let uxt = UncheckedExtrinsic::decode(&mut encoded.as_slice()).ok_or_else(|| ErrorKind::InvalidExtrinsicFormat)?;
|
||||||
if !uxt.is_signed() {
|
if !uxt.is_signed() {
|
||||||
@@ -191,7 +221,7 @@ impl<A> transaction_pool::ChainApi for ChainApi<A> where
|
|||||||
HashMap::default()
|
HashMap::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_ready(&self, at: &BlockId, known_nonces: &mut Self::Ready, xt: &VerifiedFor<Self>) -> Readiness {
|
fn is_ready(&self, at: &BlockId<Self::Block>, known_nonces: &mut Self::Ready, xt: &VerifiedFor<Self>) -> Readiness {
|
||||||
let sender = xt.verified.sender().clone();
|
let sender = xt.verified.sender().clone();
|
||||||
trace!(target: "transaction-pool", "Checking readiness of {} (from {})", xt.verified.hash, sender);
|
trace!(target: "transaction-pool", "Checking readiness of {} (from {})", xt.verified.hash, sender);
|
||||||
|
|
||||||
@@ -249,4 +279,3 @@ impl<A> transaction_pool::ChainApi for ChainApi<A> where
|
|||||||
Choice::RejectNew
|
Choice::RejectNew
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user