mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-15 13:51:11 +00:00
Remove all (non-dev) client references from frame, activate dependency enforcer (#4184)
* Move transaction pool to primitives * move backend, errors into primitives * remove unused client depencies * Move rpc-api into primitives * Move peerset back to client * Move rpc/api back to client, move palette/support/rpc into utils * move support-rpc into subfolder * move system-rpc into utils * move transaction-pool and -graph back into client * fix broken imports * Clean up test primitives * Make support test utils independent of frame * remove unnecessary node dependencies from service * Reactivate dependency script: - only enforce the now achieved status quo will remain - allow for primitives to depend on /client for now without failing - more discriptive error message so people understand, what it wants - minor fix to differentiative between ../client and /client (which may be a subfolder) - don't allow this to fail anylonger. * fix doc comment * 'Should not' rather than 'must not'. * Revert unwanted dependency changes * fix faulty import * fixup derive_more version * fix wrong import path
This commit is contained in:
committed by
GitHub
parent
b2aab98e69
commit
bd652793db
@@ -15,7 +15,6 @@ externalities = { package = "substrate-externalities", path = "../primitives/ext
|
||||
fnv = { version = "1.0.6" }
|
||||
futures = { version = "0.3.1", features = ["compat"] }
|
||||
hash-db = { version = "0.15.2" }
|
||||
header-metadata = { package = "substrate-header-metadata", path = "header-metadata" }
|
||||
hex-literal = { version = "0.2.1" }
|
||||
inherents = { package = "substrate-inherents", path = "../primitives/inherents" }
|
||||
keyring = { package = "substrate-keyring", path = "../primitives/keyring" }
|
||||
@@ -27,6 +26,7 @@ rstd = { package = "sr-std", path = "../primitives/sr-std" }
|
||||
runtime-version = { package = "sr-version", path = "../primitives/sr-version" }
|
||||
sr-api = { path = "../primitives/sr-api" }
|
||||
sr-primitives = { path = "../primitives/sr-primitives" }
|
||||
sp-blockchain = { path = "../primitives/blockchain" }
|
||||
state-machine = { package = "substrate-state-machine", path = "../primitives/state-machine" }
|
||||
substrate-telemetry = { path = "telemetry" }
|
||||
trie = { package = "substrate-trie", path = "../primitives/trie" }
|
||||
|
||||
@@ -14,7 +14,7 @@ externalities = { package = "substrate-externalities", path = "../../primitives/
|
||||
fnv = { version = "1.0.6" }
|
||||
futures = { version = "0.3.1" }
|
||||
hash-db = { version = "0.15.2", default-features = false }
|
||||
header-metadata = { package = "substrate-header-metadata", path = "../header-metadata" }
|
||||
sp-blockchain = { path = "../../primitives/blockchain" }
|
||||
hex-literal = { version = "0.2.1" }
|
||||
inherents = { package = "substrate-inherents", path = "../../primitives/inherents", default-features = false }
|
||||
keyring = { package = "substrate-keyring", path = "../../primitives/keyring" }
|
||||
|
||||
@@ -28,9 +28,9 @@ use crate::{
|
||||
blockchain::{
|
||||
Backend as BlockchainBackend, well_known_cache_keys
|
||||
},
|
||||
error,
|
||||
light::RemoteBlockchain,
|
||||
};
|
||||
use sp_blockchain;
|
||||
use consensus::BlockOrigin;
|
||||
use hash_db::Hasher;
|
||||
use parking_lot::RwLock;
|
||||
@@ -116,7 +116,7 @@ pub trait BlockImportOperation<Block, H> where
|
||||
/// Returns pending state.
|
||||
///
|
||||
/// Returns None for backends with locally-unavailable state data.
|
||||
fn state(&self) -> error::Result<Option<&Self::State>>;
|
||||
fn state(&self) -> sp_blockchain::Result<Option<&Self::State>>;
|
||||
|
||||
/// Append block data to the transaction.
|
||||
fn set_block_data(
|
||||
@@ -125,37 +125,37 @@ pub trait BlockImportOperation<Block, H> where
|
||||
body: Option<Vec<Block::Extrinsic>>,
|
||||
justification: Option<Justification>,
|
||||
state: NewBlockState,
|
||||
) -> error::Result<()>;
|
||||
) -> sp_blockchain::Result<()>;
|
||||
|
||||
/// Update cached data.
|
||||
fn update_cache(&mut self, cache: HashMap<well_known_cache_keys::Id, Vec<u8>>);
|
||||
|
||||
/// Inject storage data into the database.
|
||||
fn update_db_storage(&mut self, update: <Self::State as StateBackend<H>>::Transaction) -> error::Result<()>;
|
||||
fn update_db_storage(&mut self, update: <Self::State as StateBackend<H>>::Transaction) -> sp_blockchain::Result<()>;
|
||||
|
||||
/// Inject storage data into the database replacing any existing data.
|
||||
fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> error::Result<H::Out>;
|
||||
fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> sp_blockchain::Result<H::Out>;
|
||||
|
||||
/// Set storage changes.
|
||||
fn update_storage(
|
||||
&mut self,
|
||||
update: StorageCollection,
|
||||
child_update: ChildStorageCollection,
|
||||
) -> error::Result<()>;
|
||||
) -> sp_blockchain::Result<()>;
|
||||
|
||||
/// Inject changes trie data into the database.
|
||||
fn update_changes_trie(&mut self, update: ChangesTrieTransaction<H, NumberFor<Block>>) -> error::Result<()>;
|
||||
fn update_changes_trie(&mut self, update: ChangesTrieTransaction<H, NumberFor<Block>>) -> sp_blockchain::Result<()>;
|
||||
|
||||
/// Insert auxiliary keys.
|
||||
///
|
||||
/// Values are `None` if should be deleted.
|
||||
fn insert_aux<I>(&mut self, ops: I) -> error::Result<()>
|
||||
fn insert_aux<I>(&mut self, ops: I) -> sp_blockchain::Result<()>
|
||||
where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>;
|
||||
|
||||
/// Mark a block as finalized.
|
||||
fn mark_finalized(&mut self, id: BlockId<Block>, justification: Option<Justification>) -> error::Result<()>;
|
||||
fn mark_finalized(&mut self, id: BlockId<Block>, justification: Option<Justification>) -> sp_blockchain::Result<()>;
|
||||
/// Mark a block as new head. If both block import and set head are specified, set head overrides block import's best block rule.
|
||||
fn mark_head(&mut self, id: BlockId<Block>) -> error::Result<()>;
|
||||
fn mark_head(&mut self, id: BlockId<Block>) -> sp_blockchain::Result<()>;
|
||||
}
|
||||
|
||||
/// Finalize Facilities
|
||||
@@ -175,7 +175,7 @@ pub trait Finalizer<Block: BlockT, H: Hasher<Out=Block::Hash>, B: Backend<Block,
|
||||
id: BlockId<Block>,
|
||||
justification: Option<Justification>,
|
||||
notify: bool,
|
||||
) -> error::Result<()>;
|
||||
) -> sp_blockchain::Result<()>;
|
||||
|
||||
|
||||
/// Finalize a block.
|
||||
@@ -196,7 +196,7 @@ pub trait Finalizer<Block: BlockT, H: Hasher<Out=Block::Hash>, B: Backend<Block,
|
||||
id: BlockId<Block>,
|
||||
justification: Option<Justification>,
|
||||
notify: bool,
|
||||
) -> error::Result<()>;
|
||||
) -> sp_blockchain::Result<()>;
|
||||
|
||||
}
|
||||
|
||||
@@ -211,10 +211,10 @@ pub trait AuxStore {
|
||||
'c: 'a,
|
||||
I: IntoIterator<Item=&'a(&'c [u8], &'c [u8])>,
|
||||
D: IntoIterator<Item=&'a &'b [u8]>,
|
||||
>(&self, insert: I, delete: D) -> error::Result<()>;
|
||||
>(&self, insert: I, delete: D) -> sp_blockchain::Result<()>;
|
||||
|
||||
/// Query auxiliary data from key-value store.
|
||||
fn get_aux(&self, key: &[u8]) -> error::Result<Option<Vec<u8>>>;
|
||||
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>>;
|
||||
}
|
||||
|
||||
/// Client backend.
|
||||
@@ -245,18 +245,18 @@ pub trait Backend<Block, H>: AuxStore + Send + Sync where
|
||||
/// Begin a new block insertion transaction with given parent block id.
|
||||
///
|
||||
/// When constructing the genesis, this is called with all-zero hash.
|
||||
fn begin_operation(&self) -> error::Result<Self::BlockImportOperation>;
|
||||
fn begin_operation(&self) -> sp_blockchain::Result<Self::BlockImportOperation>;
|
||||
|
||||
/// Note an operation to contain state transition.
|
||||
fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId<Block>) -> error::Result<()>;
|
||||
fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId<Block>) -> sp_blockchain::Result<()>;
|
||||
|
||||
/// Commit block insertion.
|
||||
fn commit_operation(&self, transaction: Self::BlockImportOperation) -> error::Result<()>;
|
||||
fn commit_operation(&self, transaction: Self::BlockImportOperation) -> sp_blockchain::Result<()>;
|
||||
|
||||
/// Finalize block with given Id.
|
||||
///
|
||||
/// This should only be called if the parent of the given block has been finalized.
|
||||
fn finalize_block(&self, block: BlockId<Block>, justification: Option<Justification>) -> error::Result<()>;
|
||||
fn finalize_block(&self, block: BlockId<Block>, justification: Option<Justification>) -> sp_blockchain::Result<()>;
|
||||
|
||||
/// Returns reference to blockchain backend.
|
||||
fn blockchain(&self) -> &Self::Blockchain;
|
||||
@@ -276,17 +276,17 @@ pub trait Backend<Block, H>: AuxStore + Send + Sync where
|
||||
}
|
||||
|
||||
/// Returns state backend with post-state of given block.
|
||||
fn state_at(&self, block: BlockId<Block>) -> error::Result<Self::State>;
|
||||
fn state_at(&self, block: BlockId<Block>) -> sp_blockchain::Result<Self::State>;
|
||||
|
||||
/// Destroy state and save any useful data, such as cache.
|
||||
fn destroy_state(&self, _state: Self::State) -> error::Result<()> {
|
||||
fn destroy_state(&self, _state: Self::State) -> sp_blockchain::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Attempts to revert the chain by `n` blocks.
|
||||
///
|
||||
/// Returns the number of blocks that were successfully reverted.
|
||||
fn revert(&self, n: NumberFor<Block>) -> error::Result<NumberFor<Block>>;
|
||||
fn revert(&self, n: NumberFor<Block>) -> sp_blockchain::Result<NumberFor<Block>>;
|
||||
|
||||
/// Insert auxiliary data into key-value store.
|
||||
fn insert_aux<
|
||||
@@ -295,12 +295,12 @@ pub trait Backend<Block, H>: AuxStore + Send + Sync where
|
||||
'c: 'a,
|
||||
I: IntoIterator<Item=&'a(&'c [u8], &'c [u8])>,
|
||||
D: IntoIterator<Item=&'a &'b [u8]>,
|
||||
>(&self, insert: I, delete: D) -> error::Result<()>
|
||||
>(&self, insert: I, delete: D) -> sp_blockchain::Result<()>
|
||||
{
|
||||
AuxStore::insert_aux(self, insert, delete)
|
||||
}
|
||||
/// Query auxiliary data from key-value store.
|
||||
fn get_aux(&self, key: &[u8]) -> error::Result<Option<Vec<u8>>> {
|
||||
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
|
||||
AuxStore::get_aux(self, key)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,275 +0,0 @@
|
||||
// Copyright 2017-2019 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/>.
|
||||
|
||||
//! Substrate blockchain trait
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor};
|
||||
use sr_primitives::generic::BlockId;
|
||||
use sr_primitives::Justification;
|
||||
use log::warn;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
use header_metadata::HeaderMetadata;
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
|
||||
/// Blockchain database header backend. Does not perform any validation.
|
||||
pub trait HeaderBackend<Block: BlockT>: Send + Sync {
|
||||
/// Get block header. Returns `None` if block is not found.
|
||||
fn header(&self, id: BlockId<Block>) -> Result<Option<Block::Header>>;
|
||||
/// Get blockchain info.
|
||||
fn info(&self) -> Info<Block>;
|
||||
/// Get block status.
|
||||
fn status(&self, id: BlockId<Block>) -> Result<BlockStatus>;
|
||||
/// Get block number by hash. Returns `None` if the header is not in the chain.
|
||||
fn number(&self, hash: Block::Hash) -> Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>>;
|
||||
/// Get block hash by number. Returns `None` if the header is not in the chain.
|
||||
fn hash(&self, number: NumberFor<Block>) -> Result<Option<Block::Hash>>;
|
||||
|
||||
/// 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)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get block header. Returns `UnknownBlock` error if block is not found.
|
||||
fn expect_header(&self, id: BlockId<Block>) -> Result<Block::Header> {
|
||||
self.header(id)?.ok_or_else(|| Error::UnknownBlock(format!("{}", id)))
|
||||
}
|
||||
|
||||
/// Convert an arbitrary block ID into a block number. Returns `UnknownBlock` error if block is not found.
|
||||
fn expect_block_number_from_id(&self, id: &BlockId<Block>) -> Result<NumberFor<Block>> {
|
||||
self.block_number_from_id(id)
|
||||
.and_then(|n| n.ok_or_else(|| Error::UnknownBlock(format!("{}", id))))
|
||||
}
|
||||
|
||||
/// Convert an arbitrary block ID into a block hash. Returns `UnknownBlock` error if block is not found.
|
||||
fn expect_block_hash_from_id(&self, id: &BlockId<Block>) -> Result<Block::Hash> {
|
||||
self.block_hash_from_id(id)
|
||||
.and_then(|n| n.ok_or_else(|| Error::UnknownBlock(format!("{}", id))))
|
||||
}
|
||||
}
|
||||
|
||||
/// Blockchain database backend. Does not perform any validation.
|
||||
pub trait Backend<Block: BlockT>: HeaderBackend<Block> + HeaderMetadata<Block, Error=Error> {
|
||||
/// Get block body. Returns `None` if block is not found.
|
||||
fn body(&self, id: BlockId<Block>) -> Result<Option<Vec<<Block as BlockT>::Extrinsic>>>;
|
||||
/// Get block justification. Returns `None` if justification does not exist.
|
||||
fn justification(&self, id: BlockId<Block>) -> Result<Option<Justification>>;
|
||||
/// Get last finalized block hash.
|
||||
fn last_finalized(&self) -> Result<Block::Hash>;
|
||||
/// Returns data cache reference, if it is enabled on this backend.
|
||||
fn cache(&self) -> Option<Arc<dyn Cache<Block>>>;
|
||||
|
||||
/// Returns hashes of all blocks that are leaves of the block tree.
|
||||
/// in other words, that have no children, are chain heads.
|
||||
/// Results must be ordered best (longest, highest) chain first.
|
||||
fn leaves(&self) -> Result<Vec<Block::Hash>>;
|
||||
|
||||
/// Return hashes of all blocks that are children of the block with `parent_hash`.
|
||||
fn children(&self, parent_hash: Block::Hash) -> Result<Vec<Block::Hash>>;
|
||||
|
||||
/// Get the most recent block hash of the best (longest) chains
|
||||
/// that contain block with the given `target_hash`.
|
||||
///
|
||||
/// The search space is always limited to blocks which are in the finalized
|
||||
/// chain or descendents of it.
|
||||
///
|
||||
/// If `maybe_max_block_number` is `Some(max_block_number)`
|
||||
/// the search is limited to block `numbers <= max_block_number`.
|
||||
/// in other words as if there were no blocks greater `max_block_number`.
|
||||
/// Returns `Ok(None)` if `target_hash` is not found in search space.
|
||||
/// TODO: document time complexity of this, see [#1444](https://github.com/paritytech/substrate/issues/1444)
|
||||
fn best_containing(
|
||||
&self,
|
||||
target_hash: Block::Hash,
|
||||
maybe_max_number: Option<NumberFor<Block>>,
|
||||
import_lock: &RwLock<()>,
|
||||
) -> Result<Option<Block::Hash>> {
|
||||
let target_header = {
|
||||
match self.header(BlockId::Hash(target_hash))? {
|
||||
Some(x) => x,
|
||||
// target not in blockchain
|
||||
None => { return Ok(None); },
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(max_number) = maybe_max_number {
|
||||
// target outside search range
|
||||
if target_header.number() > &max_number {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
|
||||
let leaves = {
|
||||
// ensure no blocks are imported during this code block.
|
||||
// an import could trigger a reorg which could change the canonical chain.
|
||||
// we depend on the canonical chain staying the same during this code block.
|
||||
let _import_guard = import_lock.read();
|
||||
|
||||
let info = self.info();
|
||||
|
||||
// this can be `None` if the best chain is shorter than the target header.
|
||||
let maybe_canon_hash = self.hash(*target_header.number())?;
|
||||
|
||||
if maybe_canon_hash.as_ref() == Some(&target_hash) {
|
||||
// if a `max_number` is given we try to fetch the block at the
|
||||
// given depth, if it doesn't exist or `max_number` is not
|
||||
// provided, we continue to search from all leaves below.
|
||||
if let Some(max_number) = maybe_max_number {
|
||||
if let Some(header) = self.hash(max_number)? {
|
||||
return Ok(Some(header));
|
||||
}
|
||||
}
|
||||
} else if info.finalized_number >= *target_header.number() {
|
||||
// header is on a dead fork.
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
self.leaves()?
|
||||
};
|
||||
|
||||
// for each chain. longest chain first. shortest last
|
||||
for leaf_hash in leaves {
|
||||
// start at the leaf
|
||||
let mut current_hash = leaf_hash;
|
||||
|
||||
// if search is not restricted then the leaf is the best
|
||||
let mut best_hash = leaf_hash;
|
||||
|
||||
// go backwards entering the search space
|
||||
// waiting until we are <= max_number
|
||||
if let Some(max_number) = maybe_max_number {
|
||||
loop {
|
||||
let current_header = self.header(BlockId::Hash(current_hash.clone()))?
|
||||
.ok_or_else(|| Error::from(format!("failed to get header for hash {}", current_hash)))?;
|
||||
|
||||
if current_header.number() <= &max_number {
|
||||
best_hash = current_header.hash();
|
||||
break;
|
||||
}
|
||||
|
||||
current_hash = *current_header.parent_hash();
|
||||
}
|
||||
}
|
||||
|
||||
// go backwards through the chain (via parent links)
|
||||
loop {
|
||||
// until we find target
|
||||
if current_hash == target_hash {
|
||||
return Ok(Some(best_hash));
|
||||
}
|
||||
|
||||
let current_header = self.header(BlockId::Hash(current_hash.clone()))?
|
||||
.ok_or_else(|| Error::from(format!("failed to get header for hash {}", current_hash)))?;
|
||||
|
||||
// stop search in this chain once we go below the target's block number
|
||||
if current_header.number() < target_header.number() {
|
||||
break;
|
||||
}
|
||||
|
||||
current_hash = *current_header.parent_hash();
|
||||
}
|
||||
}
|
||||
|
||||
// header may be on a dead fork -- the only leaves that are considered are
|
||||
// those which can still be finalized.
|
||||
//
|
||||
// FIXME #1558 only issue this warning when not on a dead fork
|
||||
warn!(
|
||||
"Block {:?} exists in chain but not found when following all \
|
||||
leaves backwards. Number limit = {:?}",
|
||||
target_hash,
|
||||
maybe_max_number,
|
||||
);
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides access to the optional cache.
|
||||
pub trait ProvideCache<Block: BlockT> {
|
||||
/// Returns data cache reference, if it is enabled on this backend.
|
||||
fn cache(&self) -> Option<Arc<dyn Cache<Block>>>;
|
||||
}
|
||||
|
||||
/// Blockchain optional data cache.
|
||||
pub trait Cache<Block: BlockT>: Send + Sync {
|
||||
/// Initialize genesis value for the given cache.
|
||||
///
|
||||
/// The operation should be performed once before anything else is inserted in the cache.
|
||||
/// Otherwise cache may end up in inconsistent state.
|
||||
fn initialize(&self, key: &well_known_cache_keys::Id, value_at_genesis: Vec<u8>) -> Result<()>;
|
||||
/// Returns cached value by the given key.
|
||||
///
|
||||
/// Returned tuple is the range where value has been active and the value itself.
|
||||
fn get_at(
|
||||
&self,
|
||||
key: &well_known_cache_keys::Id,
|
||||
block: &BlockId<Block>,
|
||||
) -> Option<((NumberFor<Block>, Block::Hash), Option<(NumberFor<Block>, Block::Hash)>, Vec<u8>)>;
|
||||
}
|
||||
|
||||
/// Blockchain info
|
||||
#[derive(Debug)]
|
||||
pub struct Info<Block: BlockT> {
|
||||
/// Best block hash.
|
||||
pub best_hash: Block::Hash,
|
||||
/// Best block number.
|
||||
pub best_number: <<Block as BlockT>::Header as HeaderT>::Number,
|
||||
/// Genesis block hash.
|
||||
pub genesis_hash: Block::Hash,
|
||||
/// The head of the finalized chain.
|
||||
pub finalized_hash: Block::Hash,
|
||||
/// Last finalized block number.
|
||||
pub finalized_number: <<Block as BlockT>::Header as HeaderT>::Number,
|
||||
}
|
||||
|
||||
/// Block status.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum BlockStatus {
|
||||
/// Already in the blockchain.
|
||||
InChain,
|
||||
/// Not in the queue or the blockchain.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// A list of all well known keys in the blockchain cache.
|
||||
pub mod well_known_cache_keys {
|
||||
/// The type representing cache keys.
|
||||
pub type Id = consensus::import_queue::CacheKeyId;
|
||||
|
||||
/// A list of authorities.
|
||||
pub const AUTHORITIES: Id = *b"auth";
|
||||
|
||||
/// Current Epoch data.
|
||||
pub const EPOCH: Id = *b"epch";
|
||||
|
||||
/// Changes trie configuration.
|
||||
pub const CHANGES_TRIE_CONFIG: Id = *b"chtr";
|
||||
}
|
||||
@@ -31,7 +31,7 @@ use hash_db::Hasher;
|
||||
use primitives::{Blake2Hasher, NativeOrEncoded};
|
||||
|
||||
use sr_api::{ProofRecorder, InitializeBlock};
|
||||
use crate::error;
|
||||
use sp_blockchain;
|
||||
|
||||
/// Method call executor.
|
||||
pub trait CallExecutor<B, H>
|
||||
@@ -53,7 +53,7 @@ where
|
||||
call_data: &[u8],
|
||||
strategy: ExecutionStrategy,
|
||||
extensions: Option<Extensions>,
|
||||
) -> Result<Vec<u8>, error::Error>;
|
||||
) -> Result<Vec<u8>, sp_blockchain::Error>;
|
||||
|
||||
/// Execute a contextual call on top of state in a block of a given hash.
|
||||
///
|
||||
@@ -62,7 +62,7 @@ where
|
||||
/// of the execution context.
|
||||
fn contextual_call<
|
||||
'a,
|
||||
IB: Fn() -> error::Result<()>,
|
||||
IB: Fn() -> sp_blockchain::Result<()>,
|
||||
EM: Fn(
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
@@ -81,12 +81,12 @@ where
|
||||
native_call: Option<NC>,
|
||||
proof_recorder: &Option<ProofRecorder<B>>,
|
||||
extensions: Option<Extensions>,
|
||||
) -> error::Result<NativeOrEncoded<R>> where ExecutionManager<EM>: Clone;
|
||||
) -> sp_blockchain::Result<NativeOrEncoded<R>> where ExecutionManager<EM>: Clone;
|
||||
|
||||
/// Extract RuntimeVersion of given block
|
||||
///
|
||||
/// No changes are made.
|
||||
fn runtime_version(&self, id: &BlockId<B>) -> Result<RuntimeVersion, error::Error>;
|
||||
fn runtime_version(&self, id: &BlockId<B>) -> Result<RuntimeVersion, sp_blockchain::Error>;
|
||||
|
||||
/// Execute a call to a contract on top of given state.
|
||||
///
|
||||
@@ -113,7 +113,7 @@ where
|
||||
(S::Transaction, H::Out),
|
||||
Option<ChangesTrieTransaction<Blake2Hasher, NumberFor<B>>>
|
||||
),
|
||||
error::Error,
|
||||
sp_blockchain::Error,
|
||||
>;
|
||||
|
||||
/// Execute a call to a contract on top of given state, gathering execution proof.
|
||||
@@ -125,7 +125,7 @@ where
|
||||
overlay: &mut OverlayedChanges,
|
||||
method: &str,
|
||||
call_data: &[u8]
|
||||
) -> Result<(Vec<u8>, StorageProof), error::Error> {
|
||||
) -> Result<(Vec<u8>, StorageProof), sp_blockchain::Error> {
|
||||
let trie_state = state.as_trie_backend()
|
||||
.ok_or_else(||
|
||||
Box::new(state_machine::ExecutionError::UnableToGenerateProof)
|
||||
@@ -143,7 +143,7 @@ where
|
||||
overlay: &mut OverlayedChanges,
|
||||
method: &str,
|
||||
call_data: &[u8]
|
||||
) -> Result<(Vec<u8>, StorageProof), error::Error>;
|
||||
) -> Result<(Vec<u8>, StorageProof), sp_blockchain::Error>;
|
||||
|
||||
/// Get runtime version if supported.
|
||||
fn native_runtime_version(&self) -> Option<&NativeVersion>;
|
||||
|
||||
@@ -27,7 +27,7 @@ use consensus::BlockOrigin;
|
||||
|
||||
use crate::blockchain::Info;
|
||||
use crate::notifications::StorageEventStream;
|
||||
use crate::error;
|
||||
use sp_blockchain;
|
||||
|
||||
/// Type that implements `futures::Stream` of block import events.
|
||||
pub type ImportNotifications<Block> = mpsc::UnboundedReceiver<BlockImportNotification<Block>>;
|
||||
@@ -63,7 +63,7 @@ pub trait BlockchainEvents<Block: BlockT> {
|
||||
&self,
|
||||
filter_keys: Option<&[StorageKey]>,
|
||||
child_filter_keys: Option<&[(StorageKey, Option<Vec<StorageKey>>)]>,
|
||||
) -> error::Result<StorageEventStream<Block::Hash>>;
|
||||
) -> sp_blockchain::Result<StorageEventStream<Block::Hash>>;
|
||||
}
|
||||
|
||||
/// Fetch block body by ID.
|
||||
@@ -71,14 +71,14 @@ pub trait BlockBody<Block: BlockT> {
|
||||
/// Get block body by ID. Returns `None` if the body is not stored.
|
||||
fn block_body(&self,
|
||||
id: &BlockId<Block>
|
||||
) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>>;
|
||||
) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>>;
|
||||
}
|
||||
|
||||
/// Provide a list of potential uncle headers for a given block.
|
||||
pub trait ProvideUncles<Block: BlockT> {
|
||||
/// Gets the uncles of the block with `target_hash` going back `max_generation` ancestors.
|
||||
fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor<Block>)
|
||||
-> error::Result<Vec<Block::Header>>;
|
||||
-> sp_blockchain::Result<Vec<Block::Header>>;
|
||||
}
|
||||
|
||||
/// Client info
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
// Copyright 2017-2019 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/>.
|
||||
|
||||
//! Substrate client possible errors.
|
||||
|
||||
use std::{self, error, result};
|
||||
use state_machine;
|
||||
use sr_primitives::transaction_validity::TransactionValidityError;
|
||||
use consensus;
|
||||
use derive_more::{Display, From};
|
||||
|
||||
/// Client Result type alias
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
/// Substrate Client error
|
||||
#[derive(Debug, Display, From)]
|
||||
pub enum Error {
|
||||
/// Consensus Error
|
||||
#[display(fmt = "Consensus: {}", _0)]
|
||||
Consensus(consensus::Error),
|
||||
/// Backend error.
|
||||
#[display(fmt = "Backend error: {}", _0)]
|
||||
#[from(ignore)]
|
||||
Backend(String),
|
||||
/// Unknown block.
|
||||
#[display(fmt = "UnknownBlock: {}", _0)]
|
||||
#[from(ignore)]
|
||||
UnknownBlock(String),
|
||||
/// The `apply_extrinsic` is not valid due to the given `TransactionValidityError`.
|
||||
#[display(fmt = "Extrinsic is not valid: {:?}", _0)]
|
||||
ApplyExtrinsicFailed(TransactionValidityError),
|
||||
/// Execution error.
|
||||
#[display(fmt = "Execution: {}", _0)]
|
||||
Execution(Box<dyn state_machine::Error>),
|
||||
/// Blockchain error.
|
||||
#[display(fmt = "Blockchain: {}", _0)]
|
||||
Blockchain(Box<Error>),
|
||||
/// Invalid authorities set received from the runtime.
|
||||
#[display(fmt = "Current state of blockchain has invalid authorities set")]
|
||||
InvalidAuthoritiesSet,
|
||||
/// Could not get runtime version.
|
||||
#[display(fmt = "On-chain runtime does not specify version")]
|
||||
VersionInvalid,
|
||||
/// Genesis config is invalid.
|
||||
#[display(fmt = "Genesis config provided is invalid")]
|
||||
GenesisInvalid,
|
||||
/// Error decoding header justification.
|
||||
#[display(fmt = "error decoding justification for header")]
|
||||
JustificationDecode,
|
||||
/// Justification for header is correctly encoded, but invalid.
|
||||
#[display(fmt = "bad justification for header: {}", _0)]
|
||||
#[from(ignore)]
|
||||
BadJustification(String),
|
||||
/// Not available on light client.
|
||||
#[display(fmt = "This method is not currently available when running in light client mode")]
|
||||
NotAvailableOnLightClient,
|
||||
/// Invalid remote CHT-based proof.
|
||||
#[display(fmt = "Remote node has responded with invalid header proof")]
|
||||
InvalidCHTProof,
|
||||
/// Remote fetch has been cancelled.
|
||||
#[display(fmt = "Remote data fetch has been cancelled")]
|
||||
RemoteFetchCancelled,
|
||||
/// Remote fetch has been failed.
|
||||
#[display(fmt = "Remote data fetch has been failed")]
|
||||
RemoteFetchFailed,
|
||||
/// Error decoding call result.
|
||||
#[display(fmt = "Error decoding call result of {}: {}", _0, _1)]
|
||||
CallResultDecode(&'static str, codec::Error),
|
||||
/// Error converting a parameter between runtime and node.
|
||||
#[display(fmt = "Error converting `{}` between runtime and node", _0)]
|
||||
#[from(ignore)]
|
||||
RuntimeParamConversion(String),
|
||||
/// Changes tries are not supported.
|
||||
#[display(fmt = "Changes tries are not supported by the runtime")]
|
||||
ChangesTriesNotSupported,
|
||||
/// Key changes query has failed.
|
||||
#[display(fmt = "Failed to check changes proof: {}", _0)]
|
||||
#[from(ignore)]
|
||||
ChangesTrieAccessFailed(String),
|
||||
/// Last finalized block not parent of current.
|
||||
#[display(fmt = "Did not finalize blocks in sequential order.")]
|
||||
#[from(ignore)]
|
||||
NonSequentialFinalization(String),
|
||||
/// Safety violation: new best block not descendent of last finalized.
|
||||
#[display(fmt = "Potential long-range attack: block not in finalized chain.")]
|
||||
NotInFinalizedChain,
|
||||
/// Hash that is required for building CHT is missing.
|
||||
#[display(fmt = "Failed to get hash of block for building CHT")]
|
||||
MissingHashRequiredForCHT,
|
||||
/// Invalid calculated state root on block import.
|
||||
#[display(fmt = "Calculated state root does not match.")]
|
||||
InvalidStateRoot,
|
||||
/// A convenience variant for String
|
||||
#[display(fmt = "{}", _0)]
|
||||
#[from(ignore)]
|
||||
Msg(String),
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
Error::Consensus(e) => Some(e),
|
||||
Error::Blockchain(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Error {
|
||||
fn from(s: String) -> Self {
|
||||
Error::Msg(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Error {
|
||||
fn from(s: &'a str) -> Self {
|
||||
Error::Msg(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<block_builder::ApplyExtrinsicFailed> for Error {
|
||||
fn from(err: block_builder::ApplyExtrinsicFailed) -> Self {
|
||||
use block_builder::ApplyExtrinsicFailed;
|
||||
match err {
|
||||
ApplyExtrinsicFailed::Validity(tx_validity) => Self::ApplyExtrinsicFailed(tx_validity),
|
||||
ApplyExtrinsicFailed::Msg(msg) => Self::Msg(msg),
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Chain a blockchain error.
|
||||
pub fn from_blockchain(e: Box<Error>) -> Self {
|
||||
Error::Blockchain(e)
|
||||
}
|
||||
|
||||
/// Chain a state error.
|
||||
pub fn from_state(e: Box<dyn state_machine::Error>) -> Self {
|
||||
Error::Execution(e)
|
||||
}
|
||||
}
|
||||
@@ -18,20 +18,17 @@
|
||||
#![warn(missing_docs)]
|
||||
|
||||
pub mod backend;
|
||||
pub mod blockchain;
|
||||
pub mod call_executor;
|
||||
pub mod client;
|
||||
pub mod error;
|
||||
pub mod execution_extensions;
|
||||
pub mod light;
|
||||
pub mod notifications;
|
||||
|
||||
// TODO: avoid re-exports
|
||||
pub use sp_blockchain as blockchain;
|
||||
pub use backend::*;
|
||||
pub use blockchain::*;
|
||||
pub use notifications::*;
|
||||
pub use call_executor::*;
|
||||
pub use client::*;
|
||||
pub use error::*;
|
||||
pub use light::*;
|
||||
pub use notifications::*;
|
||||
|
||||
@@ -40,9 +37,7 @@ pub use state_machine::{StorageProof, ExecutionStrategy};
|
||||
|
||||
/// Utility methods for the client.
|
||||
pub mod utils {
|
||||
use super::HeaderBackend;
|
||||
use header_metadata::HeaderMetadata;
|
||||
use crate::error;
|
||||
use sp_blockchain::{HeaderBackend, HeaderMetadata, Error};
|
||||
use primitives::H256;
|
||||
use sr_primitives::traits::{Block as BlockT};
|
||||
use std::borrow::Borrow;
|
||||
@@ -56,8 +51,8 @@ pub mod utils {
|
||||
pub fn is_descendent_of<'a, Block: BlockT<Hash=H256>, T, H: Borrow<H256> + 'a>(
|
||||
client: &'a T,
|
||||
current: Option<(H, H)>,
|
||||
) -> impl Fn(&H256, &H256) -> Result<bool, error::Error> + 'a
|
||||
where T: HeaderBackend<Block> + HeaderMetadata<Block, Error=error::Error>,
|
||||
) -> impl Fn(&H256, &H256) -> Result<bool, Error> + 'a
|
||||
where T: HeaderBackend<Block> + HeaderMetadata<Block, Error=Error>,
|
||||
{
|
||||
move |base, hash| {
|
||||
if base == hash { return Ok(false); }
|
||||
@@ -76,7 +71,7 @@ pub mod utils {
|
||||
}
|
||||
}
|
||||
|
||||
let ancestor = header_metadata::lowest_common_ancestor(client, *hash, *base)?;
|
||||
let ancestor = sp_blockchain::lowest_common_ancestor(client, *hash, *base)?;
|
||||
|
||||
Ok(ancestor.hash == *base)
|
||||
}
|
||||
|
||||
@@ -28,16 +28,11 @@ use sr_primitives::{
|
||||
};
|
||||
use primitives::{ChangesTrieConfiguration};
|
||||
use state_machine::StorageProof;
|
||||
use header_metadata::HeaderMetadata;
|
||||
use crate::{
|
||||
backend::{
|
||||
AuxStore, NewBlockState,
|
||||
},
|
||||
blockchain::{
|
||||
well_known_cache_keys, HeaderBackend, Cache as BlockchainCache,
|
||||
},
|
||||
error::{ Error as ClientError, Result as ClientResult },
|
||||
use sp_blockchain::{
|
||||
HeaderMetadata, well_known_cache_keys, HeaderBackend, Cache as BlockchainCache,
|
||||
Error as ClientError, Result as ClientResult,
|
||||
};
|
||||
use crate::backend::{ AuxStore, NewBlockState };
|
||||
/// Remote call request.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct RemoteCallRequest<Header: HeaderT> {
|
||||
@@ -288,7 +283,7 @@ pub trait RemoteBlockchain<Block: BlockT>: Send + Sync {
|
||||
pub mod tests {
|
||||
use futures::future::Ready;
|
||||
use parking_lot::Mutex;
|
||||
use crate::error::Error as ClientError;
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use test_primitives::{Block, Header, Extrinsic};
|
||||
use super::*;
|
||||
|
||||
|
||||
@@ -21,12 +21,13 @@ libp2p = { version = "0.13.0", default-features = false, features = ["secp256k1"
|
||||
log = "0.4.8"
|
||||
network = { package = "substrate-network", path = "../network" }
|
||||
primitives = { package = "substrate-primitives", path = "../../primitives/core" }
|
||||
sp-blockchain = { path = "../../primitives/blockchain" }
|
||||
prost = "0.5.0"
|
||||
serde_json = "1.0.41"
|
||||
sr-primitives = { path = "../../primitives/sr-primitives" }
|
||||
|
||||
[dev-dependencies]
|
||||
parking_lot = "0.9.0"
|
||||
peerset = { package = "substrate-peerset", path = "../../primitives/peerset" }
|
||||
peerset = { package = "substrate-peerset", path = "../peerset" }
|
||||
test-client = { package = "substrate-test-runtime-client", path = "../../test/utils/runtime/client" }
|
||||
sr-api = { path = "../../primitives/sr-api" }
|
||||
|
||||
@@ -27,7 +27,7 @@ pub enum Error {
|
||||
/// Failed to hash the authority id to be used as a dht key.
|
||||
HashingAuthorityId(libp2p::core::multiaddr::multihash::EncodeError),
|
||||
/// Failed calling into the Substrate runtime.
|
||||
CallingRuntime(client_api::error::Error),
|
||||
CallingRuntime(sp_blockchain::Error),
|
||||
/// From the Dht we only get the hashed authority id. In order to retrieve the actual authority id and to ensure it
|
||||
/// is actually an authority, we match the hash against the hash of the authority id of all other authorities. This
|
||||
/// error is the result of the above failing.
|
||||
|
||||
@@ -117,7 +117,7 @@ where
|
||||
Block: BlockT + Unpin + 'static,
|
||||
Network: NetworkProvider,
|
||||
Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend<Block>,
|
||||
<Client as ProvideRuntimeApi>::Api: AuthorityDiscoveryApi<Block, Error = client_api::error::Error>,
|
||||
<Client as ProvideRuntimeApi>::Api: AuthorityDiscoveryApi<Block, Error = sp_blockchain::Error>,
|
||||
Self: Future<Output = ()>,
|
||||
{
|
||||
/// Return a new authority discovery.
|
||||
@@ -358,7 +358,7 @@ where
|
||||
Block: BlockT + Unpin + 'static,
|
||||
Network: NetworkProvider,
|
||||
Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend<Block>,
|
||||
<Client as ProvideRuntimeApi>::Api: AuthorityDiscoveryApi<Block, Error = client_api::error::Error>,
|
||||
<Client as ProvideRuntimeApi>::Api: AuthorityDiscoveryApi<Block, Error = sp_blockchain::Error>,
|
||||
{
|
||||
type Output = ();
|
||||
|
||||
@@ -500,7 +500,7 @@ mod tests {
|
||||
fn header(
|
||||
&self,
|
||||
_id: BlockId<Block>,
|
||||
) -> std::result::Result<Option<Block::Header>, client_api::error::Error> {
|
||||
) -> std::result::Result<Option<Block::Header>, sp_blockchain::Error> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
@@ -517,21 +517,21 @@ mod tests {
|
||||
fn status(
|
||||
&self,
|
||||
_id: BlockId<Block>,
|
||||
) -> std::result::Result<client_api::blockchain::BlockStatus, client_api::error::Error> {
|
||||
) -> std::result::Result<client_api::blockchain::BlockStatus, sp_blockchain::Error> {
|
||||
Ok(client_api::blockchain::BlockStatus::Unknown)
|
||||
}
|
||||
|
||||
fn number(
|
||||
&self,
|
||||
_hash: Block::Hash,
|
||||
) -> std::result::Result<Option<NumberFor<Block>>, client_api::error::Error> {
|
||||
) -> std::result::Result<Option<NumberFor<Block>>, sp_blockchain::Error> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn hash(
|
||||
&self,
|
||||
_number: NumberFor<Block>,
|
||||
) -> std::result::Result<Option<Block::Hash>, client_api::error::Error> {
|
||||
) -> std::result::Result<Option<Block::Hash>, sp_blockchain::Error> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
@@ -547,7 +547,7 @@ mod tests {
|
||||
_: ExecutionContext,
|
||||
_: Option<()>,
|
||||
_: Vec<u8>,
|
||||
) -> std::result::Result<NativeOrEncoded<RuntimeVersion>, client_api::error::Error> {
|
||||
) -> std::result::Result<NativeOrEncoded<RuntimeVersion>, sp_blockchain::Error> {
|
||||
unimplemented!("Not required for testing!")
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ mod tests {
|
||||
_: ExecutionContext,
|
||||
_: Option<(Block)>,
|
||||
_: Vec<u8>,
|
||||
) -> std::result::Result<NativeOrEncoded<()>, client_api::error::Error> {
|
||||
) -> std::result::Result<NativeOrEncoded<()>, sp_blockchain::Error> {
|
||||
unimplemented!("Not required for testing!")
|
||||
}
|
||||
|
||||
@@ -567,13 +567,13 @@ mod tests {
|
||||
_: ExecutionContext,
|
||||
_: Option<&<Block as BlockT>::Header>,
|
||||
_: Vec<u8>,
|
||||
) -> std::result::Result<NativeOrEncoded<()>, client_api::error::Error> {
|
||||
) -> std::result::Result<NativeOrEncoded<()>, sp_blockchain::Error> {
|
||||
unimplemented!("Not required for testing!")
|
||||
}
|
||||
}
|
||||
|
||||
impl ApiExt<Block> for RuntimeApi {
|
||||
type Error = client_api::error::Error;
|
||||
type Error = sp_blockchain::Error;
|
||||
|
||||
fn map_api_result<F: FnOnce(&Self) -> std::result::Result<R, E>, R, E>(
|
||||
&self,
|
||||
@@ -585,7 +585,7 @@ mod tests {
|
||||
fn runtime_version_at(
|
||||
&self,
|
||||
_: &BlockId<Block>,
|
||||
) -> std::result::Result<RuntimeVersion, client_api::error::Error> {
|
||||
) -> std::result::Result<RuntimeVersion, sp_blockchain::Error> {
|
||||
unimplemented!("Not required for testing!")
|
||||
}
|
||||
|
||||
@@ -605,7 +605,7 @@ mod tests {
|
||||
_: ExecutionContext,
|
||||
_: Option<()>,
|
||||
_: Vec<u8>,
|
||||
) -> std::result::Result<NativeOrEncoded<Vec<AuthorityId>>, client_api::error::Error> {
|
||||
) -> std::result::Result<NativeOrEncoded<Vec<AuthorityId>>, sp_blockchain::Error> {
|
||||
return Ok(NativeOrEncoded::Native(self.authorities.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,13 @@ futures = "0.3.1"
|
||||
codec = { package = "parity-scale-codec", version = "1.0.0" }
|
||||
sr-primitives = { path = "../../primitives/sr-primitives" }
|
||||
primitives = { package = "substrate-primitives", path = "../../primitives/core" }
|
||||
sp-blockchain = { path = "../../primitives/blockchain" }
|
||||
client = { package = "substrate-client", path = "../" }
|
||||
client-api = { package = "substrate-client-api", path = "../api" }
|
||||
consensus_common = { package = "substrate-consensus-common", path = "../../primitives/consensus/common" }
|
||||
inherents = { package = "substrate-inherents", path = "../../primitives/inherents" }
|
||||
substrate-telemetry = { path = "../telemetry" }
|
||||
transaction_pool = { package = "substrate-transaction-pool", path = "../transaction-pool" }
|
||||
transaction_pool = { package = "sc-transaction-pool", path = "../../client/transaction-pool" }
|
||||
block-builder = { package = "substrate-block-builder", path = "../block-builder" }
|
||||
tokio-executor = { version = "0.2.0-alpha.6", features = ["blocking"] }
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
// FIXME #1021 move this into substrate-consensus-common
|
||||
|
||||
use std::{time, sync::Arc};
|
||||
use client_api::{error, CallExecutor};
|
||||
use client_api::CallExecutor;
|
||||
use sp_blockchain;
|
||||
use client::Client as SubstrateClient;
|
||||
use codec::Decode;
|
||||
use consensus_common::{evaluation};
|
||||
@@ -53,13 +54,13 @@ where
|
||||
RA: Send + Sync + 'static,
|
||||
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi,
|
||||
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api:
|
||||
BlockBuilderApi<Block, Error = error::Error>,
|
||||
BlockBuilderApi<Block, Error = sp_blockchain::Error>,
|
||||
{
|
||||
pub fn init_with_now(
|
||||
&mut self,
|
||||
parent_header: &<Block as BlockT>::Header,
|
||||
now: Box<dyn Fn() -> time::Instant + Send + Sync>,
|
||||
) -> Result<Proposer<Block, SubstrateClient<B, E, Block, RA>, A>, error::Error> {
|
||||
) -> Result<Proposer<Block, SubstrateClient<B, E, Block, RA>, A>, sp_blockchain::Error> {
|
||||
let parent_hash = parent_header.hash();
|
||||
|
||||
let id = BlockId::hash(parent_hash);
|
||||
@@ -91,15 +92,15 @@ where
|
||||
RA: Send + Sync + 'static,
|
||||
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi,
|
||||
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api:
|
||||
BlockBuilderApi<Block, Error = error::Error>,
|
||||
BlockBuilderApi<Block, Error = sp_blockchain::Error>,
|
||||
{
|
||||
type Proposer = Proposer<Block, SubstrateClient<B, E, Block, RA>, A>;
|
||||
type Error = error::Error;
|
||||
type Error = sp_blockchain::Error;
|
||||
|
||||
fn init(
|
||||
&mut self,
|
||||
parent_header: &<Block as BlockT>::Header,
|
||||
) -> Result<Self::Proposer, error::Error> {
|
||||
) -> Result<Self::Proposer, sp_blockchain::Error> {
|
||||
self.init_with_now(parent_header, Box::new(time::Instant::now))
|
||||
}
|
||||
}
|
||||
@@ -129,10 +130,10 @@ where
|
||||
RA: Send + Sync + 'static,
|
||||
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi,
|
||||
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api:
|
||||
BlockBuilderApi<Block, Error = error::Error>,
|
||||
BlockBuilderApi<Block, Error = sp_blockchain::Error>,
|
||||
{
|
||||
type Create = tokio_executor::blocking::Blocking<Result<Block, error::Error>>;
|
||||
type Error = error::Error;
|
||||
type Create = tokio_executor::blocking::Blocking<Result<Block, sp_blockchain::Error>>;
|
||||
type Error = sp_blockchain::Error;
|
||||
|
||||
fn propose(
|
||||
&mut self,
|
||||
@@ -157,14 +158,14 @@ impl<Block, B, E, RA, A> ProposerInner<Block, SubstrateClient<B, E, Block, RA>,
|
||||
RA: Send + Sync + 'static,
|
||||
SubstrateClient<B, E, Block, RA>: ProvideRuntimeApi,
|
||||
<SubstrateClient<B, E, Block, RA> as ProvideRuntimeApi>::Api:
|
||||
BlockBuilderApi<Block, Error = error::Error>,
|
||||
BlockBuilderApi<Block, Error = sp_blockchain::Error>,
|
||||
{
|
||||
fn propose_with(
|
||||
&self,
|
||||
inherent_data: InherentData,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
deadline: time::Instant,
|
||||
) -> Result<Block, error::Error> {
|
||||
) -> Result<Block, sp_blockchain::Error> {
|
||||
/// If the block is full we will attempt to push at most
|
||||
/// this number of transactions before quitting for real.
|
||||
/// It allows us to increase block utilization.
|
||||
@@ -202,7 +203,8 @@ impl<Block, B, E, RA, A> ProposerInner<Block, SubstrateClient<B, E, Block, RA>,
|
||||
Ok(()) => {
|
||||
debug!("[{:?}] Pushed to the block.", pending.hash);
|
||||
}
|
||||
Err(error::Error::ApplyExtrinsicFailed(e)) if e.exhausted_resources() => {
|
||||
Err(sp_blockchain::Error::ApplyExtrinsicFailed(sp_blockchain::ApplyExtrinsicFailed::Validity(e)))
|
||||
if e.exhausted_resources() => {
|
||||
if is_first {
|
||||
debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending.hash);
|
||||
unqueue_invalid.push(pending.hash.clone());
|
||||
|
||||
@@ -7,6 +7,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
state-machine = { package = "substrate-state-machine", path = "../../primitives/state-machine" }
|
||||
sr-primitives = { path = "../../primitives/sr-primitives" }
|
||||
sp-blockchain = { path = "../../primitives/blockchain" }
|
||||
primitives = { package = "substrate-primitives", path = "../../primitives/core" }
|
||||
codec = { package = "parity-scale-codec", version = "1.0.6", features = ["derive"] }
|
||||
runtime_api = { package = "substrate-block-builder-runtime-api", path = "../../primitives/block-builder/runtime-api" }
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Substrate block builder
|
||||
//!
|
||||
//! This crate provides the [`BlockBuilder`] utility and the corresponding runtime api
|
||||
//! [`BlockBuilder`](api::BlockBuilder).
|
||||
//! [`BlockBuilder`](api::BlockBuilder).Error
|
||||
//!
|
||||
//! The block builder utility is used in the node as an abstraction over the runtime api to
|
||||
//! initialize a block, to push extrinsics and to finalize a block.
|
||||
@@ -31,42 +31,15 @@ use sr_primitives::{
|
||||
traits::{
|
||||
Header as HeaderT, Hash, Block as BlockT, HashFor, ProvideRuntimeApi, ApiRef, DigestFor,
|
||||
NumberFor, One,
|
||||
},
|
||||
transaction_validity::TransactionValidityError,
|
||||
}
|
||||
};
|
||||
|
||||
use sp_blockchain::{ApplyExtrinsicFailed, Error};
|
||||
use primitives::ExecutionContext;
|
||||
use state_machine::StorageProof;
|
||||
use sr_api::{Core, ApiExt, ApiErrorFor};
|
||||
|
||||
#[allow(deprecated)]
|
||||
use runtime_api::compatability_v3;
|
||||
|
||||
pub use runtime_api::BlockBuilder as BlockBuilderApi;
|
||||
|
||||
/// Error when the runtime failed to apply an extrinsic.
|
||||
pub enum ApplyExtrinsicFailed {
|
||||
/// The transaction cannot be included into the current block.
|
||||
///
|
||||
/// This doesn't necessary mean that the transaction itself is invalid, but it might be just
|
||||
/// unappliable onto the current block.
|
||||
Validity(TransactionValidityError),
|
||||
/// This is used for miscelanious errors that can be represented by string and not handleable.
|
||||
///
|
||||
/// This will become obsolete with complete migration to v4 APIs.
|
||||
Msg(String),
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl From<compatability_v3::ApplyError> for ApplyExtrinsicFailed {
|
||||
fn from(e: compatability_v3::ApplyError) -> Self {
|
||||
use self::compatability_v3::ApplyError::*;
|
||||
match e {
|
||||
Validity(tx_validity) => Self::Validity(tx_validity),
|
||||
e => Self::Msg(format!("Apply extrinsic failed: {:?}", e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Utility for building new (valid) blocks from a stream of extrinsics.
|
||||
pub struct BlockBuilder<'a, Block: BlockT, A: ProvideRuntimeApi> {
|
||||
@@ -81,7 +54,7 @@ where
|
||||
Block: BlockT,
|
||||
A: ProvideRuntimeApi + 'a,
|
||||
A::Api: BlockBuilderApi<Block>,
|
||||
ApiErrorFor<A, Block>: From<ApplyExtrinsicFailed>,
|
||||
ApiErrorFor<A, Block>: From<Error>,
|
||||
{
|
||||
/// Create a new instance of builder based on the given `parent_hash` and `parent_number`.
|
||||
///
|
||||
@@ -149,7 +122,7 @@ where
|
||||
extrinsics.push(xt);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(ApplyExtrinsicFailed::from(e))?,
|
||||
Err(e) => Err(ApplyExtrinsicFailed::from(e).into())?,
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -163,7 +136,7 @@ where
|
||||
extrinsics.push(xt);
|
||||
Ok(())
|
||||
}
|
||||
Err(tx_validity) => Err(ApplyExtrinsicFailed::Validity(tx_validity))?,
|
||||
Err(tx_validity) => Err(ApplyExtrinsicFailed::Validity(tx_validity).into())?,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ fdlimit = "0.1.1"
|
||||
serde_json = "1.0.41"
|
||||
panic-handler = { package = "substrate-panic-handler", path = "../../primitives/panic-handler" }
|
||||
client-api = { package = "substrate-client-api", path = "../api" }
|
||||
header-metadata = { package = "substrate-header-metadata", path = "../header-metadata" }
|
||||
sp-blockchain = { path = "../../primitives/blockchain" }
|
||||
network = { package = "substrate-network", path = "../network" }
|
||||
sr-primitives = { path = "../../primitives/sr-primitives" }
|
||||
primitives = { package = "substrate-primitives", path = "../../primitives/core" }
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
//! Initialization errors.
|
||||
|
||||
use client_api;
|
||||
|
||||
/// Result type alias for the CLI.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
@@ -31,7 +29,7 @@ pub enum Error {
|
||||
/// Service error
|
||||
Service(service::Error),
|
||||
/// Client error
|
||||
Client(client_api::error::Error),
|
||||
Client(sp_blockchain::Error),
|
||||
/// Input error
|
||||
#[from(ignore)]
|
||||
Input(String),
|
||||
|
||||
@@ -50,7 +50,7 @@ pub fn build(service: &impl AbstractService) -> impl futures::Future<Output = ()
|
||||
// detect and log reorganizations.
|
||||
if let Some((ref last_num, ref last_hash)) = last_best {
|
||||
if n.header.parent_hash() != last_hash && n.is_new_best {
|
||||
let maybe_ancestor = header_metadata::lowest_common_ancestor(
|
||||
let maybe_ancestor = sp_blockchain::lowest_common_ancestor(
|
||||
&*client,
|
||||
last_hash.clone(),
|
||||
n.hash,
|
||||
|
||||
@@ -22,6 +22,7 @@ keystore = { package = "substrate-keystore", path = "../../keystore" }
|
||||
log = "0.4.8"
|
||||
parking_lot = "0.9.0"
|
||||
primitives = { package = "substrate-primitives", path = "../../../primitives/core" }
|
||||
sp-blockchain = { path = "../../../primitives/blockchain" }
|
||||
runtime_io = { package = "sr-io", path = "../../../primitives/sr-io" }
|
||||
runtime_version = { package = "sr-version", path = "../../../primitives/sr-version" }
|
||||
slots = { package = "substrate-consensus-slots", path = "../slots" }
|
||||
|
||||
@@ -38,10 +38,12 @@ use consensus_common::{self, BlockImport, Environment, Proposer,
|
||||
use consensus_common::import_queue::{
|
||||
Verifier, BasicQueue, BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport,
|
||||
};
|
||||
use client_api::{ error::Result as CResult, backend::AuxStore };
|
||||
use client_api::backend::AuxStore;
|
||||
use client::{
|
||||
blockchain::ProvideCache, BlockOf,
|
||||
well_known_cache_keys::{self, Id as CacheKeyId},
|
||||
blockchain::ProvideCache, BlockOf
|
||||
};
|
||||
use sp_blockchain::{
|
||||
Result as CResult, well_known_cache_keys::{self, Id as CacheKeyId},
|
||||
};
|
||||
|
||||
use block_builder_api::BlockBuilder as BlockBuilderApi;
|
||||
@@ -55,6 +57,7 @@ use inherents::{InherentDataProviders, InherentData};
|
||||
use futures::prelude::*;
|
||||
use parking_lot::Mutex;
|
||||
use log::{debug, info, trace};
|
||||
use sp_blockchain;
|
||||
|
||||
use sp_timestamp::{
|
||||
TimestampInherentData, InherentType as TimestampInherent, InherentError as TIError
|
||||
@@ -95,7 +98,7 @@ impl SlotDuration {
|
||||
A: Codec,
|
||||
B: BlockT,
|
||||
C: AuxStore + ProvideRuntimeApi,
|
||||
C::Api: AuraApi<B, A, Error = client::error::Error>,
|
||||
C::Api: AuraApi<B, A, Error = sp_blockchain::Error>,
|
||||
{
|
||||
slots::SlotDuration::get_or_compute(client, |a, b| a.slot_duration(b)).map(Self)
|
||||
}
|
||||
@@ -340,7 +343,7 @@ enum Error<B: BlockT> {
|
||||
BadSignature(B::Hash),
|
||||
#[display(fmt = "Rejecting block too far in future")]
|
||||
TooFarInFuture,
|
||||
Client(client::error::Error),
|
||||
Client(sp_blockchain::Error),
|
||||
DataProvider(String),
|
||||
Runtime(String),
|
||||
}
|
||||
@@ -448,7 +451,7 @@ impl<C, P, T> AuraVerifier<C, P, T>
|
||||
inherent_data: InherentData,
|
||||
timestamp_now: u64,
|
||||
) -> Result<(), Error<B>>
|
||||
where C: ProvideRuntimeApi, C::Api: BlockBuilderApi<B, Error = client::error::Error>
|
||||
where C: ProvideRuntimeApi, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>
|
||||
{
|
||||
const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60;
|
||||
|
||||
@@ -495,7 +498,7 @@ impl<C, P, T> AuraVerifier<C, P, T>
|
||||
#[forbid(deprecated)]
|
||||
impl<B: BlockT, C, P, T> Verifier<B> for AuraVerifier<C, P, T> where
|
||||
C: ProvideRuntimeApi + Send + Sync + client_api::backend::AuxStore + ProvideCache<B> + BlockOf,
|
||||
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B, Error = client::error::Error>,
|
||||
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B, Error = sp_blockchain::Error>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P>,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + 'static,
|
||||
@@ -682,7 +685,7 @@ pub fn import_queue<B, C, P, T>(
|
||||
) -> Result<AuraImportQueue<B>, consensus_common::Error> where
|
||||
B: BlockT,
|
||||
C: 'static + ProvideRuntimeApi + BlockOf + ProvideCache<B> + Send + Sync + AuxStore,
|
||||
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B, Error = client::error::Error>,
|
||||
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B, Error = sp_blockchain::Error>,
|
||||
DigestItemFor<B>: CompatibleDigestItem<P>,
|
||||
P: Pair + Send + Sync + 'static,
|
||||
P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode,
|
||||
@@ -721,7 +724,7 @@ mod tests {
|
||||
use test_client;
|
||||
use aura_primitives::sr25519::AuthorityPair;
|
||||
|
||||
type Error = client::error::Error;
|
||||
type Error = sp_blockchain::Error;
|
||||
|
||||
type TestClient = client::Client<
|
||||
test_client::Backend,
|
||||
|
||||
@@ -23,7 +23,7 @@ client-api = { package = "substrate-client-api", path = "../../api" }
|
||||
client = { package = "substrate-client", path = "../../" }
|
||||
sr-api = { path = "../../../primitives/sr-api" }
|
||||
block-builder-api = { package = "substrate-block-builder-runtime-api", path = "../../../primitives/block-builder/runtime-api" }
|
||||
header-metadata = { package = "substrate-header-metadata", path = "../../header-metadata" }
|
||||
sp-blockchain = { path = "../../../primitives/blockchain" }
|
||||
consensus-common = { package = "substrate-consensus-common", path = "../../../primitives/consensus/common" }
|
||||
uncles = { package = "substrate-consensus-uncles", path = "../uncles" }
|
||||
slots = { package = "substrate-consensus-slots", path = "../slots" }
|
||||
|
||||
@@ -19,10 +19,8 @@
|
||||
use log::info;
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
use client_api::{
|
||||
backend::AuxStore,
|
||||
error::{Result as ClientResult, Error as ClientError},
|
||||
};
|
||||
use client_api::backend::AuxStore;
|
||||
use sp_blockchain::{Result as ClientResult, Error as ClientError};
|
||||
use sr_primitives::traits::Block as BlockT;
|
||||
use babe_primitives::BabeBlockWeight;
|
||||
|
||||
|
||||
@@ -25,12 +25,8 @@ use fork_tree::ForkTree;
|
||||
use parking_lot::{Mutex, MutexGuard};
|
||||
use sr_primitives::traits::{Block as BlockT, NumberFor, One, Zero};
|
||||
use codec::{Encode, Decode};
|
||||
use client_api::{
|
||||
error::Error as ClientError,
|
||||
utils::is_descendent_of,
|
||||
blockchain::HeaderBackend
|
||||
};
|
||||
use header_metadata::HeaderMetadata;
|
||||
use client_api::utils::is_descendent_of;
|
||||
use sp_blockchain::{HeaderMetadata, HeaderBackend, Error as ClientError};
|
||||
use primitives::H256;
|
||||
use std::ops::Add;
|
||||
|
||||
|
||||
@@ -90,8 +90,6 @@ use consensus_common::import_queue::{Verifier, BasicQueue, CacheKeyId};
|
||||
use client_api::{
|
||||
backend::{AuxStore, Backend},
|
||||
call_executor::CallExecutor,
|
||||
error::{Result as ClientResult, Error as ClientError},
|
||||
blockchain::{self, HeaderBackend, ProvideCache},
|
||||
BlockchainEvents, ProvideUncles,
|
||||
};
|
||||
use client::Client;
|
||||
@@ -103,7 +101,10 @@ use futures::prelude::*;
|
||||
use log::{warn, debug, info, trace};
|
||||
use slots::{SlotWorker, SlotData, SlotInfo, SlotCompatible};
|
||||
use epoch_changes::descendent_query;
|
||||
use header_metadata::HeaderMetadata;
|
||||
use sp_blockchain::{
|
||||
Result as ClientResult, Error as ClientError,
|
||||
HeaderBackend, ProvideCache, HeaderMetadata
|
||||
};
|
||||
use schnorrkel::SignatureError;
|
||||
|
||||
use sr_api::ApiExt;
|
||||
@@ -157,11 +158,11 @@ enum Error<B: BlockT> {
|
||||
#[display(fmt = "VRF verification failed: {:?}", _0)]
|
||||
VRFVerificationFailed(SignatureError),
|
||||
#[display(fmt = "Could not fetch parent header: {:?}", _0)]
|
||||
FetchParentHeader(client_api::error::Error),
|
||||
FetchParentHeader(sp_blockchain::Error),
|
||||
#[display(fmt = "Expected epoch change to happen at {:?}, s{}", _0, _1)]
|
||||
ExpectedEpochChange(B::Hash, u64),
|
||||
#[display(fmt = "Could not look up epoch: {:?}", _0)]
|
||||
CouldNotLookUpEpoch(Box<fork_tree::Error<client_api::error::Error>>),
|
||||
CouldNotLookUpEpoch(Box<fork_tree::Error<sp_blockchain::Error>>),
|
||||
#[display(fmt = "Block {} is not valid under any epoch.", _0)]
|
||||
BlockNotValid(B::Hash),
|
||||
#[display(fmt = "Unexpected epoch change")]
|
||||
@@ -170,9 +171,9 @@ enum Error<B: BlockT> {
|
||||
ParentBlockNoAssociatedWeight(B::Hash),
|
||||
#[display(fmt = "Checking inherents failed: {}", _0)]
|
||||
CheckInherents(String),
|
||||
Client(client_api::error::Error),
|
||||
Client(sp_blockchain::Error),
|
||||
Runtime(inherents::Error),
|
||||
ForkTree(Box<fork_tree::Error<client_api::error::Error>>),
|
||||
ForkTree(Box<fork_tree::Error<sp_blockchain::Error>>),
|
||||
}
|
||||
|
||||
impl<B: BlockT> std::convert::From<Error<B>> for String {
|
||||
@@ -206,7 +207,7 @@ impl Config {
|
||||
/// Either fetch the slot duration from disk or compute it from the genesis
|
||||
/// state.
|
||||
pub fn get_or_compute<B: BlockT, C>(client: &C) -> ClientResult<Self> where
|
||||
C: AuxStore + ProvideRuntimeApi, C::Api: BabeApi<B, Error = client_api::error::Error>,
|
||||
C: AuxStore + ProvideRuntimeApi, C::Api: BabeApi<B, Error = sp_blockchain::Error>,
|
||||
{
|
||||
trace!(target: "babe", "Getting slot duration");
|
||||
match slots::SlotDuration::get_or_compute(client, |a, b| a.configuration(b)).map(Self) {
|
||||
@@ -558,7 +559,7 @@ impl<B, E, Block: BlockT, RA, PRA> BabeVerifier<B, E, Block, RA, PRA> {
|
||||
block_id: BlockId<Block>,
|
||||
inherent_data: InherentData,
|
||||
) -> Result<(), Error<Block>>
|
||||
where PRA: ProvideRuntimeApi, PRA::Api: BlockBuilderApi<Block, Error = client_api::error::Error>
|
||||
where PRA: ProvideRuntimeApi, PRA::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error>
|
||||
{
|
||||
let inherent_res = self.api.runtime_api().check_inherents(
|
||||
&block_id,
|
||||
@@ -627,8 +628,8 @@ impl<B, E, Block, RA, PRA> Verifier<Block> for BabeVerifier<B, E, Block, RA, PRA
|
||||
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
|
||||
RA: Send + Sync,
|
||||
PRA: ProvideRuntimeApi + Send + Sync + AuxStore + ProvideCache<Block>,
|
||||
PRA::Api: BlockBuilderApi<Block, Error = client_api::error::Error>
|
||||
+ BabeApi<Block, Error = client_api::error::Error>,
|
||||
PRA::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error>
|
||||
+ BabeApi<Block, Error = sp_blockchain::Error>,
|
||||
{
|
||||
fn verify(
|
||||
&mut self,
|
||||
@@ -851,8 +852,8 @@ impl<B, E, Block, I, RA, PRA> BlockImport<Block> for BabeBlockImport<B, E, Block
|
||||
// early exit if block already in chain, otherwise the check for
|
||||
// epoch changes will error when trying to re-import an epoch change
|
||||
match self.client.status(BlockId::Hash(hash)) {
|
||||
Ok(blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain),
|
||||
Ok(blockchain::BlockStatus::Unknown) => {},
|
||||
Ok(sp_blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain),
|
||||
Ok(sp_blockchain::BlockStatus::Unknown) => {},
|
||||
Err(e) => return Err(ConsensusError::ClientImport(e.to_string())),
|
||||
}
|
||||
|
||||
@@ -907,7 +908,7 @@ impl<B, E, Block, I, RA, PRA> BlockImport<Block> for BabeBlockImport<B, E, Block
|
||||
slot_number,
|
||||
|slot| self.config.genesis_epoch(slot),
|
||||
)
|
||||
.map_err(|e: fork_tree::Error<client_api::error::Error>| ConsensusError::ChainLookup(
|
||||
.map_err(|e: fork_tree::Error<sp_blockchain::Error>| ConsensusError::ChainLookup(
|
||||
babe_err(Error::<Block>::CouldNotLookUpEpoch(Box::new(e))).into()
|
||||
))?
|
||||
.ok_or_else(|| ConsensusError::ClientImport(
|
||||
@@ -1146,7 +1147,7 @@ pub fn import_queue<B, E, Block: BlockT<Hash=H256>, I, RA, PRA>(
|
||||
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync + 'static,
|
||||
RA: Send + Sync + 'static,
|
||||
PRA: ProvideRuntimeApi + ProvideCache<Block> + Send + Sync + AuxStore + 'static,
|
||||
PRA::Api: BlockBuilderApi<Block> + BabeApi<Block> + ApiExt<Block, Error = client_api::error::Error>,
|
||||
PRA::Api: BlockBuilderApi<Block> + BabeApi<Block> + ApiExt<Block, Error = sp_blockchain::Error>,
|
||||
{
|
||||
register_babe_inherent_data_provider(&inherent_data_providers, babe_link.config.slot_duration)?;
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ use std::{time::Duration, cell::RefCell};
|
||||
|
||||
type Item = DigestItem<Hash>;
|
||||
|
||||
type Error = client::error::Error;
|
||||
type Error = sp_blockchain::Error;
|
||||
|
||||
type TestClient = client::Client<
|
||||
test_client::Backend,
|
||||
|
||||
@@ -8,6 +8,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] }
|
||||
primitives = { package = "substrate-primitives", path = "../../../primitives/core" }
|
||||
sp-blockchain = { path = "../../../primitives/blockchain" }
|
||||
sr-primitives = { path = "../../../primitives/sr-primitives" }
|
||||
client-api = { package = "substrate-client-api", path = "../../api" }
|
||||
block-builder-api = { package = "substrate-block-builder-runtime-api", path = "../../../primitives/block-builder/runtime-api" }
|
||||
|
||||
@@ -32,10 +32,8 @@
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::collections::HashMap;
|
||||
use client_api::{
|
||||
BlockOf, blockchain::{HeaderBackend, ProvideCache}, backend::AuxStore,
|
||||
well_known_cache_keys::Id as CacheKeyId,
|
||||
};
|
||||
use client_api::{BlockOf, backend::AuxStore};
|
||||
use sp_blockchain::{HeaderBackend, ProvideCache, well_known_cache_keys::Id as CacheKeyId};
|
||||
use block_builder_api::BlockBuilder as BlockBuilderApi;
|
||||
use sr_primitives::{Justification, RuntimeString};
|
||||
use sr_primitives::generic::{BlockId, Digest, DigestItem};
|
||||
@@ -66,7 +64,7 @@ pub enum Error<B: BlockT> {
|
||||
#[display(fmt = "Fetching best header failed using select chain: {:?}", _0)]
|
||||
BestHeaderSelectChain(ConsensusError),
|
||||
#[display(fmt = "Fetching best header failed: {:?}", _0)]
|
||||
BestHeader(client_api::error::Error),
|
||||
BestHeader(sp_blockchain::Error),
|
||||
#[display(fmt = "Best header does not exist")]
|
||||
NoBestHeader,
|
||||
#[display(fmt = "Block proposing error: {:?}", _0)]
|
||||
@@ -79,7 +77,7 @@ pub enum Error<B: BlockT> {
|
||||
CreateInherents(inherents::Error),
|
||||
#[display(fmt = "Checking inherents failed: {}", _0)]
|
||||
CheckInherents(String),
|
||||
Client(client_api::error::Error),
|
||||
Client(sp_blockchain::Error),
|
||||
Codec(codec::Error),
|
||||
Environment(String),
|
||||
Runtime(RuntimeString)
|
||||
@@ -211,7 +209,7 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
|
||||
inherent_data: InherentData,
|
||||
timestamp_now: u64,
|
||||
) -> Result<(), Error<B>> where
|
||||
C: ProvideRuntimeApi, C::Api: BlockBuilderApi<B, Error = client_api::error::Error>
|
||||
C: ProvideRuntimeApi, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>
|
||||
{
|
||||
const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60;
|
||||
|
||||
@@ -249,7 +247,7 @@ impl<B: BlockT<Hash=H256>, C, S, Algorithm> PowVerifier<B, C, S, Algorithm> {
|
||||
|
||||
impl<B: BlockT<Hash=H256>, C, S, Algorithm> Verifier<B> for PowVerifier<B, C, S, Algorithm> where
|
||||
C: ProvideRuntimeApi + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf,
|
||||
C::Api: BlockBuilderApi<B, Error = client_api::error::Error>,
|
||||
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>,
|
||||
S: SelectChain<B>,
|
||||
Algorithm: PowAlgorithm<B> + Send + Sync,
|
||||
{
|
||||
@@ -341,7 +339,7 @@ pub fn import_queue<B, C, S, Algorithm>(
|
||||
B: BlockT<Hash=H256>,
|
||||
C: ProvideRuntimeApi + HeaderBackend<B> + BlockOf + ProvideCache<B> + AuxStore,
|
||||
C: Send + Sync + AuxStore + 'static,
|
||||
C::Api: BlockBuilderApi<B, Error = client_api::error::Error>,
|
||||
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>,
|
||||
Algorithm: PowAlgorithm<B> + Send + Sync + 'static,
|
||||
S: SelectChain<B> + 'static,
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ build = "build.rs"
|
||||
codec = { package = "parity-scale-codec", version = "1.0.0" }
|
||||
client-api = { package = "substrate-client-api", path = "../../api" }
|
||||
primitives = { package = "substrate-primitives", path = "../../../primitives/core" }
|
||||
sp-blockchain = { path = "../../../primitives/blockchain" }
|
||||
sr-primitives = { path = "../../../primitives/sr-primitives" }
|
||||
substrate-telemetry = { path = "../../telemetry" }
|
||||
consensus_common = { package = "substrate-consensus-common", path = "../../../primitives/consensus/common" }
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use codec::{Encode, Decode};
|
||||
use client_api::backend::AuxStore;
|
||||
use client_api::error::{Result as ClientResult, Error as ClientError};
|
||||
use sp_blockchain::{Result as ClientResult, Error as ClientError};
|
||||
use sr_primitives::traits::Header;
|
||||
|
||||
const SLOT_HEADER_MAP_KEY: &[u8] = b"slot_header_map";
|
||||
|
||||
@@ -401,17 +401,17 @@ impl<T: Clone> SlotDuration<T> {
|
||||
///
|
||||
/// `slot_key` is marked as `'static`, as it should really be a
|
||||
/// compile-time constant.
|
||||
pub fn get_or_compute<B: BlockT, C, CB>(client: &C, cb: CB) -> client_api::error::Result<Self> where
|
||||
pub fn get_or_compute<B: BlockT, C, CB>(client: &C, cb: CB) -> sp_blockchain::Result<Self> where
|
||||
C: client_api::backend::AuxStore,
|
||||
C: ProvideRuntimeApi,
|
||||
CB: FnOnce(ApiRef<C::Api>, &BlockId<B>) -> client_api::error::Result<T>,
|
||||
CB: FnOnce(ApiRef<C::Api>, &BlockId<B>) -> sp_blockchain::Result<T>,
|
||||
T: SlotData + Encode + Decode + Debug,
|
||||
{
|
||||
match client.get_aux(T::SLOT_KEY)? {
|
||||
Some(v) => <T as codec::Decode>::decode(&mut &v[..])
|
||||
.map(SlotDuration)
|
||||
.map_err(|_| {
|
||||
client_api::error::Error::Backend({
|
||||
sp_blockchain::Error::Backend({
|
||||
error!(target: "slots", "slot duration kept in invalid format");
|
||||
"slot duration kept in invalid format".to_string()
|
||||
})
|
||||
|
||||
@@ -23,7 +23,7 @@ executor = { package = "substrate-executor", path = "../executor" }
|
||||
state_db = { package = "substrate-state-db", path = "../state-db" }
|
||||
trie = { package = "substrate-trie", path = "../../primitives/trie" }
|
||||
consensus_common = { package = "substrate-consensus-common", path = "../../primitives/consensus/common" }
|
||||
header_metadata = { package = "substrate-header-metadata", path = "../header-metadata" }
|
||||
sp-blockchain = { path = "../../primitives/blockchain" }
|
||||
|
||||
[dev-dependencies]
|
||||
substrate-keyring = { path = "../../primitives/keyring" }
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ use std::collections::{BTreeSet, BTreeMap};
|
||||
|
||||
use log::warn;
|
||||
|
||||
use client_api::error::{Error as ClientError, Result as ClientResult};
|
||||
use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
||||
use sr_primitives::traits::{
|
||||
Block as BlockT, NumberFor, Zero, Bounded, CheckedSub
|
||||
};
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
|
||||
//! List-cache storage entries.
|
||||
|
||||
use client_api::error::Result as ClientResult;
|
||||
use sp_blockchain::Result as ClientResult;
|
||||
use sr_primitives::traits::{Block as BlockT, NumberFor};
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ use std::sync::Arc;
|
||||
|
||||
use kvdb::{KeyValueDB, DBTransaction};
|
||||
|
||||
use client_api::error::{Error as ClientError, Result as ClientResult};
|
||||
use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
||||
use codec::{Encode, Decode};
|
||||
use sr_primitives::generic::BlockId;
|
||||
use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor};
|
||||
|
||||
Vendored
+2
-2
@@ -22,7 +22,7 @@ use parking_lot::RwLock;
|
||||
use kvdb::{KeyValueDB, DBTransaction};
|
||||
|
||||
use client_api::blockchain::{well_known_cache_keys::{self, Id as CacheKeyId}, Cache as BlockchainCache};
|
||||
use client_api::error::Result as ClientResult;
|
||||
use sp_blockchain::Result as ClientResult;
|
||||
use codec::{Encode, Decode};
|
||||
use sr_primitives::generic::BlockId;
|
||||
use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero};
|
||||
@@ -211,7 +211,7 @@ impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> {
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut insert_op = |name: CacheKeyId, value: Option<Vec<u8>>| -> Result<(), client_api::error::Error> {
|
||||
let mut insert_op = |name: CacheKeyId, value: Option<Vec<u8>>| -> Result<(), sp_blockchain::Error> {
|
||||
let cache = self.cache.get_cache(name);
|
||||
let op = cache.on_block_insert(
|
||||
&mut self::list_storage::DbStorageTransaction::new(
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use kvdb::{KeyValueDB, DBTransaction};
|
||||
use codec::{Encode, Decode};
|
||||
use client_api::error;
|
||||
use sp_blockchain;
|
||||
use std::hash::Hash;
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@ use std::hash::Hash;
|
||||
pub fn read_children<
|
||||
K: Eq + Hash + Clone + Encode + Decode,
|
||||
V: Eq + Hash + Clone + Encode + Decode,
|
||||
>(db: &dyn KeyValueDB, column: Option<u32>, prefix: &[u8], parent_hash: K) -> error::Result<Vec<V>> {
|
||||
>(db: &dyn KeyValueDB, column: Option<u32>, prefix: &[u8], parent_hash: K) -> sp_blockchain::Result<Vec<V>> {
|
||||
let mut buf = prefix.to_vec();
|
||||
parent_hash.using_encoded(|s| buf.extend(s));
|
||||
|
||||
let raw_val_opt = match db.get(column, &buf[..]) {
|
||||
Ok(raw_val_opt) => raw_val_opt,
|
||||
Err(_) => return Err(error::Error::Backend("Error reading value from database".into())),
|
||||
Err(_) => return Err(sp_blockchain::Error::Backend("Error reading value from database".into())),
|
||||
};
|
||||
|
||||
let raw_val = match raw_val_opt {
|
||||
@@ -42,7 +42,7 @@ pub fn read_children<
|
||||
|
||||
let children: Vec<V> = match Decode::decode(&mut &raw_val[..]) {
|
||||
Ok(children) => children,
|
||||
Err(_) => return Err(error::Error::Backend("Error decoding children".into())),
|
||||
Err(_) => return Err(sp_blockchain::Error::Backend("Error decoding children".into())),
|
||||
};
|
||||
|
||||
Ok(children)
|
||||
|
||||
@@ -39,12 +39,13 @@ use std::path::PathBuf;
|
||||
use std::io;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use client_api::ForkBlocks;
|
||||
use client_api::{execution_extensions::ExecutionExtensions, ForkBlocks};
|
||||
use client_api::backend::NewBlockState;
|
||||
use client_api::backend::{StorageCollection, ChildStorageCollection};
|
||||
use client_api::blockchain::{well_known_cache_keys, HeaderBackend};
|
||||
use client_api::error::{Result as ClientResult, Error as ClientError};
|
||||
use client_api::execution_extensions::ExecutionExtensions;
|
||||
use sp_blockchain::{
|
||||
Result as ClientResult, Error as ClientError,
|
||||
well_known_cache_keys, HeaderBackend,
|
||||
};
|
||||
use codec::{Decode, Encode};
|
||||
use hash_db::{Hasher, Prefix};
|
||||
use kvdb::{KeyValueDB, DBTransaction};
|
||||
@@ -67,7 +68,7 @@ use state_machine::{
|
||||
use crate::utils::{Meta, db_err, meta_keys, read_db, read_meta};
|
||||
use client::leaves::{LeafSet, FinalizationDisplaced};
|
||||
use state_db::StateDb;
|
||||
use header_metadata::{CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache};
|
||||
use sp_blockchain::{CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache};
|
||||
use crate::storage_cache::{CachingState, SharedCache, new_shared_cache};
|
||||
use log::{trace, debug, warn};
|
||||
pub use state_db::PruningMode;
|
||||
@@ -239,7 +240,7 @@ pub fn new_client<E, S, Block, RA>(
|
||||
>,
|
||||
Arc<Backend<Block>>,
|
||||
),
|
||||
client::error::Error,
|
||||
sp_blockchain::Error,
|
||||
>
|
||||
where
|
||||
Block: BlockT<Hash=H256>,
|
||||
@@ -381,7 +382,7 @@ impl<Block: BlockT> client::blockchain::Backend<Block> for BlockchainDb<Block> {
|
||||
match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? {
|
||||
Some(body) => match Decode::decode(&mut &body[..]) {
|
||||
Ok(body) => Ok(Some(body)),
|
||||
Err(err) => return Err(client::error::Error::Backend(
|
||||
Err(err) => return Err(sp_blockchain::Error::Backend(
|
||||
format!("Error decoding body: {}", err)
|
||||
)),
|
||||
}
|
||||
@@ -393,7 +394,7 @@ impl<Block: BlockT> client::blockchain::Backend<Block> for BlockchainDb<Block> {
|
||||
match read_db(&*self.db, columns::KEY_LOOKUP, columns::JUSTIFICATION, id)? {
|
||||
Some(justification) => match Decode::decode(&mut &justification[..]) {
|
||||
Ok(justification) => Ok(Some(justification)),
|
||||
Err(err) => return Err(client::error::Error::Backend(
|
||||
Err(err) => return Err(sp_blockchain::Error::Backend(
|
||||
format!("Error decoding justification: {}", err)
|
||||
)),
|
||||
}
|
||||
@@ -425,7 +426,7 @@ impl<Block: BlockT> client::blockchain::ProvideCache<Block> for BlockchainDb<Blo
|
||||
}
|
||||
|
||||
impl<Block: BlockT> HeaderMetadata<Block> for BlockchainDb<Block> {
|
||||
type Error = client::error::Error;
|
||||
type Error = sp_blockchain::Error;
|
||||
|
||||
fn header_metadata(&self, hash: Block::Hash) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
|
||||
self.header_metadata_cache.header_metadata(hash).or_else(|_| {
|
||||
@@ -517,12 +518,12 @@ impl<Block> client_api::backend::BlockImportOperation<Block, Blake2Hasher>
|
||||
) -> ClientResult<H256> {
|
||||
|
||||
if top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) {
|
||||
return Err(client::error::Error::GenesisInvalid.into());
|
||||
return Err(sp_blockchain::Error::GenesisInvalid.into());
|
||||
}
|
||||
|
||||
for child_key in children.keys() {
|
||||
if !well_known_keys::is_child_storage_key(&child_key) {
|
||||
return Err(client::error::Error::GenesisInvalid.into());
|
||||
return Err(sp_blockchain::Error::GenesisInvalid.into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -823,7 +824,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
|
||||
let is_archive_pruning = config.pruning.is_archive();
|
||||
let blockchain = BlockchainDb::new(db.clone())?;
|
||||
let meta = blockchain.meta.clone();
|
||||
let map_e = |e: state_db::Error<io::Error>| ::client::error::Error::from(format!("State database error: {:?}", e));
|
||||
let map_e = |e: state_db::Error<io::Error>| ::sp_blockchain::Error::from(format!("State database error: {:?}", e));
|
||||
let state_db: StateDb<_, _> = StateDb::new(config.pruning.clone(), &StateMetaDb(&*db)).map_err(map_e)?;
|
||||
let storage_db = StorageDb {
|
||||
db: db.clone(),
|
||||
@@ -948,7 +949,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
|
||||
|
||||
// cannot find tree route with empty DB.
|
||||
if meta.best_hash != Default::default() {
|
||||
let tree_route = header_metadata::tree_route(
|
||||
let tree_route = sp_blockchain::tree_route(
|
||||
&self.blockchain,
|
||||
meta.best_hash,
|
||||
route_to,
|
||||
@@ -963,7 +964,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
|
||||
(&r.number, &r.hash)
|
||||
);
|
||||
|
||||
return Err(::client::error::Error::NotInFinalizedChain.into());
|
||||
return Err(::sp_blockchain::Error::NotInFinalizedChain.into());
|
||||
}
|
||||
|
||||
retracted.push(r.hash.clone());
|
||||
@@ -1005,7 +1006,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
|
||||
) -> ClientResult<()> {
|
||||
let last_finalized = last_finalized.unwrap_or_else(|| self.blockchain.meta.read().finalized_hash);
|
||||
if *header.parent_hash() != last_finalized {
|
||||
return Err(::client::error::Error::NonSequentialFinalization(
|
||||
return Err(::sp_blockchain::Error::NonSequentialFinalization(
|
||||
format!("Last finalized {:?} not parent of {:?}", last_finalized, header.hash()),
|
||||
).into());
|
||||
}
|
||||
@@ -1068,7 +1069,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
|
||||
|
||||
trace!(target: "db", "Canonicalize block #{} ({:?})", new_canonical, hash);
|
||||
let commit = self.storage.state_db.canonicalize_block(&hash)
|
||||
.map_err(|e: state_db::Error<io::Error>| client::error::Error::from(format!("State database error: {:?}", e)))?;
|
||||
.map_err(|e: state_db::Error<io::Error>| sp_blockchain::Error::from(format!("State database error: {:?}", e)))?;
|
||||
apply_state_commit(transaction, commit);
|
||||
};
|
||||
|
||||
@@ -1152,7 +1153,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
|
||||
}
|
||||
let number_u64 = number.saturated_into::<u64>();
|
||||
let commit = self.storage.state_db.insert_block(&hash, number_u64, &pending_block.header.parent_hash(), changeset)
|
||||
.map_err(|e: state_db::Error<io::Error>| client::error::Error::from(format!("State database error: {:?}", e)))?;
|
||||
.map_err(|e: state_db::Error<io::Error>| sp_blockchain::Error::from(format!("State database error: {:?}", e)))?;
|
||||
apply_state_commit(&mut transaction, commit);
|
||||
|
||||
// Check if need to finalize. Genesis is always finalized instantly.
|
||||
@@ -1217,7 +1218,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
|
||||
meta_updates.push((hash, *number, true, false));
|
||||
Some((enacted, retracted))
|
||||
} else {
|
||||
return Err(client::error::Error::UnknownBlock(format!("Cannot set head {:?}", set_head)))
|
||||
return Err(sp_blockchain::Error::UnknownBlock(format!("Cannot set head {:?}", set_head)))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
@@ -1288,7 +1289,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
|
||||
transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key);
|
||||
|
||||
let commit = self.storage.state_db.canonicalize_block(&f_hash)
|
||||
.map_err(|e: state_db::Error<io::Error>| client::error::Error::from(format!("State database error: {:?}", e)))?;
|
||||
.map_err(|e: state_db::Error<io::Error>| sp_blockchain::Error::from(format!("State database error: {:?}", e)))?;
|
||||
apply_state_commit(transaction, commit);
|
||||
|
||||
let changes_trie_config = self.changes_trie_config(parent_hash)?;
|
||||
@@ -1451,12 +1452,12 @@ impl<Block> client_api::backend::Backend<Block, Blake2Hasher> for Backend<Block>
|
||||
Some(commit) => {
|
||||
apply_state_commit(&mut transaction, commit);
|
||||
let removed = self.blockchain.header(BlockId::Number(best))?.ok_or_else(
|
||||
|| client::error::Error::UnknownBlock(
|
||||
|| sp_blockchain::Error::UnknownBlock(
|
||||
format!("Error reverting to {}. Block hash not found.", best)))?;
|
||||
|
||||
best -= One::one(); // prev block
|
||||
let hash = self.blockchain.hash(best)?.ok_or_else(
|
||||
|| client::error::Error::UnknownBlock(
|
||||
|| sp_blockchain::Error::UnknownBlock(
|
||||
format!("Error reverting to {}. Block hash not found.", best)))?;
|
||||
let key = utils::number_and_hash_to_lookup_key(best.clone(), &hash)?;
|
||||
transaction.put(columns::META, meta_keys::BEST_BLOCK, &key);
|
||||
@@ -1500,7 +1501,7 @@ impl<Block> client_api::backend::Backend<Block, Blake2Hasher> for Backend<Block>
|
||||
Ok(Some(ref hdr)) => {
|
||||
let hash = hdr.hash();
|
||||
if !self.have_state_at(&hash, *hdr.number()) {
|
||||
return Err(client::error::Error::UnknownBlock(format!("State already discarded for {:?}", block)))
|
||||
return Err(sp_blockchain::Error::UnknownBlock(format!("State already discarded for {:?}", block)))
|
||||
}
|
||||
if let Ok(()) = self.storage.state_db.pin(&hash) {
|
||||
let root = H256::from_slice(hdr.state_root().as_ref());
|
||||
@@ -1508,10 +1509,10 @@ impl<Block> client_api::backend::Backend<Block, Blake2Hasher> for Backend<Block>
|
||||
let state = RefTrackingState::new(db_state, self.storage.clone(), Some(hash.clone()));
|
||||
Ok(CachingState::new(state, self.shared_cache.clone(), Some(hash)))
|
||||
} else {
|
||||
Err(client::error::Error::UnknownBlock(format!("State already discarded for {:?}", block)))
|
||||
Err(sp_blockchain::Error::UnknownBlock(format!("State already discarded for {:?}", block)))
|
||||
}
|
||||
},
|
||||
Ok(None) => Err(client::error::Error::UnknownBlock(format!("Unknown state for block {:?}", block))),
|
||||
Ok(None) => Err(sp_blockchain::Error::UnknownBlock(format!("Unknown state for block {:?}", block))),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
@@ -1561,7 +1562,7 @@ mod tests {
|
||||
use sr_primitives::testing::{Header, Block as RawBlock, ExtrinsicWrapper};
|
||||
use sr_primitives::traits::{Hash, BlakeTwo256};
|
||||
use state_machine::{TrieMut, TrieDBMut, ChangesTrieRootsStorage, ChangesTrieStorage};
|
||||
use header_metadata::{lowest_common_ancestor, tree_route};
|
||||
use sp_blockchain::{lowest_common_ancestor, tree_route};
|
||||
|
||||
use test_client;
|
||||
|
||||
|
||||
@@ -24,18 +24,20 @@ use kvdb::{KeyValueDB, DBTransaction};
|
||||
|
||||
use client_api::backend::{AuxStore, NewBlockState};
|
||||
use client::blockchain::{
|
||||
BlockStatus, Cache as BlockchainCache,
|
||||
HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo,
|
||||
well_known_cache_keys,
|
||||
BlockStatus, Cache as BlockchainCache,Info as BlockchainInfo,
|
||||
};
|
||||
use client::cht;
|
||||
use client::error::{Error as ClientError, Result as ClientResult};
|
||||
use sp_blockchain::{
|
||||
CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache,
|
||||
Error as ClientError, Result as ClientResult,
|
||||
HeaderBackend as BlockchainHeaderBackend,
|
||||
well_known_cache_keys,
|
||||
};
|
||||
use client::light::blockchain::Storage as LightBlockchainStorage;
|
||||
use codec::{Decode, Encode};
|
||||
use primitives::Blake2Hasher;
|
||||
use sr_primitives::generic::{DigestItem, BlockId};
|
||||
use sr_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One, NumberFor};
|
||||
use header_metadata::{CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache};
|
||||
use crate::cache::{DbCacheSync, DbCache, ComplexBlockId, EntryType as CacheEntryType};
|
||||
use crate::utils::{self, meta_keys, Meta, db_err, read_db, block_id_to_lookup_key, read_meta};
|
||||
use crate::DatabaseSettings;
|
||||
@@ -235,7 +237,7 @@ impl<Block: BlockT> LightStorage<Block> {
|
||||
// handle reorg.
|
||||
let meta = self.meta.read();
|
||||
if meta.best_hash != Default::default() {
|
||||
let tree_route = header_metadata::tree_route(self, meta.best_hash, route_to)?;
|
||||
let tree_route = sp_blockchain::tree_route(self, meta.best_hash, route_to)?;
|
||||
|
||||
// update block number to hash lookup entries.
|
||||
for retracted in tree_route.retracted() {
|
||||
@@ -282,7 +284,7 @@ impl<Block: BlockT> LightStorage<Block> {
|
||||
) -> ClientResult<()> {
|
||||
let meta = self.meta.read();
|
||||
if &meta.finalized_hash != header.parent_hash() {
|
||||
return Err(::client::error::Error::NonSequentialFinalization(
|
||||
return Err(::sp_blockchain::Error::NonSequentialFinalization(
|
||||
format!("Last finalized {:?} not parent of {:?}",
|
||||
meta.finalized_hash, hash),
|
||||
).into())
|
||||
@@ -560,7 +562,7 @@ pub(crate) mod tests {
|
||||
use client::cht;
|
||||
use sr_primitives::generic::DigestItem;
|
||||
use sr_primitives::testing::{H256 as Hash, Header, Block as RawBlock, ExtrinsicWrapper};
|
||||
use header_metadata::{lowest_common_ancestor, tree_route};
|
||||
use sp_blockchain::{lowest_common_ancestor, tree_route};
|
||||
use super::*;
|
||||
|
||||
type Block = RawBlock<ExtrinsicWrapper<u32>>;
|
||||
|
||||
@@ -25,7 +25,6 @@ use kvdb::{KeyValueDB, DBTransaction};
|
||||
use kvdb_rocksdb::{Database, DatabaseConfig};
|
||||
use log::debug;
|
||||
|
||||
use client;
|
||||
use codec::Decode;
|
||||
use trie::DBValue;
|
||||
use sr_primitives::generic::BlockId;
|
||||
@@ -82,9 +81,9 @@ pub type NumberIndexKey = [u8; 4];
|
||||
///
|
||||
/// In the current database schema, this kind of key is only used for
|
||||
/// lookups into an index, NOT for storing header data or others.
|
||||
pub fn number_index_key<N: TryInto<u32>>(n: N) -> client::error::Result<NumberIndexKey> {
|
||||
pub fn number_index_key<N: TryInto<u32>>(n: N) -> sp_blockchain::Result<NumberIndexKey> {
|
||||
let n = n.try_into().map_err(|_|
|
||||
client::error::Error::Backend("Block number cannot be converted to u32".into())
|
||||
sp_blockchain::Error::Backend("Block number cannot be converted to u32".into())
|
||||
)?;
|
||||
|
||||
Ok([
|
||||
@@ -100,7 +99,7 @@ pub fn number_index_key<N: TryInto<u32>>(n: N) -> client::error::Result<NumberIn
|
||||
pub fn number_and_hash_to_lookup_key<N, H>(
|
||||
number: N,
|
||||
hash: H,
|
||||
) -> client::error::Result<Vec<u8>> where
|
||||
) -> sp_blockchain::Result<Vec<u8>> where
|
||||
N: TryInto<u32>,
|
||||
H: AsRef<[u8]>,
|
||||
{
|
||||
@@ -111,11 +110,11 @@ pub fn number_and_hash_to_lookup_key<N, H>(
|
||||
|
||||
/// Convert block lookup key into block number.
|
||||
/// all block lookup keys start with the block number.
|
||||
pub fn lookup_key_to_number<N>(key: &[u8]) -> client::error::Result<N> where
|
||||
pub fn lookup_key_to_number<N>(key: &[u8]) -> sp_blockchain::Result<N> where
|
||||
N: From<u32>
|
||||
{
|
||||
if key.len() < 4 {
|
||||
return Err(client::error::Error::Backend("Invalid block key".into()));
|
||||
return Err(sp_blockchain::Error::Backend("Invalid block key".into()));
|
||||
}
|
||||
Ok((key[0] as u32) << 24
|
||||
| (key[1] as u32) << 16
|
||||
@@ -128,7 +127,7 @@ pub fn remove_number_to_key_mapping<N: TryInto<u32>>(
|
||||
transaction: &mut DBTransaction,
|
||||
key_lookup_col: Option<u32>,
|
||||
number: N,
|
||||
) -> client::error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
transaction.delete(key_lookup_col, number_index_key(number)?.as_ref());
|
||||
Ok(())
|
||||
}
|
||||
@@ -139,7 +138,7 @@ pub fn remove_key_mappings<N: TryInto<u32>, H: AsRef<[u8]>>(
|
||||
key_lookup_col: Option<u32>,
|
||||
number: N,
|
||||
hash: H,
|
||||
) -> client::error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
remove_number_to_key_mapping(transaction, key_lookup_col, number)?;
|
||||
transaction.delete(key_lookup_col, hash.as_ref());
|
||||
Ok(())
|
||||
@@ -152,7 +151,7 @@ pub fn insert_number_to_key_mapping<N: TryInto<u32> + Clone, H: AsRef<[u8]>>(
|
||||
key_lookup_col: Option<u32>,
|
||||
number: N,
|
||||
hash: H,
|
||||
) -> client::error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
transaction.put_vec(
|
||||
key_lookup_col,
|
||||
number_index_key(number.clone())?.as_ref(),
|
||||
@@ -167,7 +166,7 @@ pub fn insert_hash_to_key_mapping<N: TryInto<u32>, H: AsRef<[u8]> + Clone>(
|
||||
key_lookup_col: Option<u32>,
|
||||
number: N,
|
||||
hash: H,
|
||||
) -> client::error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
transaction.put_vec(
|
||||
key_lookup_col,
|
||||
hash.clone().as_ref(),
|
||||
@@ -183,7 +182,7 @@ pub fn block_id_to_lookup_key<Block>(
|
||||
db: &dyn KeyValueDB,
|
||||
key_lookup_col: Option<u32>,
|
||||
id: BlockId<Block>
|
||||
) -> Result<Option<Vec<u8>>, client::error::Error> where
|
||||
) -> Result<Option<Vec<u8>>, sp_blockchain::Error> where
|
||||
Block: BlockT,
|
||||
::sr_primitives::traits::NumberFor<Block>: UniqueSaturatedFrom<u64> + UniqueSaturatedInto<u64>,
|
||||
{
|
||||
@@ -199,8 +198,8 @@ pub fn block_id_to_lookup_key<Block>(
|
||||
}
|
||||
|
||||
/// Maps database error to client error
|
||||
pub fn db_err(err: io::Error) -> client::error::Error {
|
||||
client::error::Error::Backend(format!("{}", err))
|
||||
pub fn db_err(err: io::Error) -> sp_blockchain::Error {
|
||||
sp_blockchain::Error::Backend(format!("{}", err))
|
||||
}
|
||||
|
||||
/// Open RocksDB database.
|
||||
@@ -208,7 +207,7 @@ pub fn open_database(
|
||||
config: &DatabaseSettings,
|
||||
col_meta: Option<u32>,
|
||||
db_type: &str
|
||||
) -> client::error::Result<Arc<dyn KeyValueDB>> {
|
||||
) -> sp_blockchain::Result<Arc<dyn KeyValueDB>> {
|
||||
let db: Arc<dyn KeyValueDB> = match &config.source {
|
||||
#[cfg(feature = "kvdb-rocksdb")]
|
||||
DatabaseSettingsSrc::Path { path, cache_size } => {
|
||||
@@ -230,13 +229,13 @@ pub fn open_database(
|
||||
db_config.memory_budget = memory_budget;
|
||||
}
|
||||
let path = path.to_str()
|
||||
.ok_or_else(|| client::error::Error::Backend("Invalid database path".into()))?;
|
||||
.ok_or_else(|| sp_blockchain::Error::Backend("Invalid database path".into()))?;
|
||||
Arc::new(Database::open(&db_config, &path).map_err(db_err)?)
|
||||
},
|
||||
#[cfg(not(feature = "kvdb-rocksdb"))]
|
||||
DatabaseSettingsSrc::Path { .. } => {
|
||||
let msg = "Try to open RocksDB database with RocksDB disabled".into();
|
||||
return Err(client::error::Error::Backend(msg));
|
||||
return Err(sp_blockchain::Error::Backend(msg));
|
||||
},
|
||||
DatabaseSettingsSrc::Custom(db) => db.clone(),
|
||||
};
|
||||
@@ -245,7 +244,7 @@ pub fn open_database(
|
||||
match db.get(col_meta, meta_keys::TYPE).map_err(db_err)? {
|
||||
Some(stored_type) => {
|
||||
if db_type.as_bytes() != &*stored_type {
|
||||
return Err(client::error::Error::Backend(
|
||||
return Err(sp_blockchain::Error::Backend(
|
||||
format!("Unexpected database type. Expected: {}", db_type)).into());
|
||||
}
|
||||
},
|
||||
@@ -265,7 +264,7 @@ pub fn read_db<Block>(
|
||||
col_index: Option<u32>,
|
||||
col: Option<u32>,
|
||||
id: BlockId<Block>
|
||||
) -> client::error::Result<Option<DBValue>>
|
||||
) -> sp_blockchain::Result<Option<DBValue>>
|
||||
where
|
||||
Block: BlockT,
|
||||
{
|
||||
@@ -281,12 +280,12 @@ pub fn read_header<Block: BlockT>(
|
||||
col_index: Option<u32>,
|
||||
col: Option<u32>,
|
||||
id: BlockId<Block>,
|
||||
) -> client::error::Result<Option<Block::Header>> {
|
||||
) -> sp_blockchain::Result<Option<Block::Header>> {
|
||||
match read_db(db, col_index, col, id)? {
|
||||
Some(header) => match Block::Header::decode(&mut &header[..]) {
|
||||
Ok(header) => Ok(Some(header)),
|
||||
Err(_) => return Err(
|
||||
client::error::Error::Backend("Error decoding header".into())
|
||||
sp_blockchain::Error::Backend("Error decoding header".into())
|
||||
),
|
||||
}
|
||||
None => Ok(None),
|
||||
@@ -299,15 +298,15 @@ pub fn require_header<Block: BlockT>(
|
||||
col_index: Option<u32>,
|
||||
col: Option<u32>,
|
||||
id: BlockId<Block>,
|
||||
) -> client::error::Result<Block::Header> {
|
||||
) -> sp_blockchain::Result<Block::Header> {
|
||||
read_header(db, col_index, col, id)
|
||||
.and_then(|header| header.ok_or_else(|| client::error::Error::UnknownBlock(format!("{}", id))))
|
||||
.and_then(|header| header.ok_or_else(|| sp_blockchain::Error::UnknownBlock(format!("{}", id))))
|
||||
}
|
||||
|
||||
/// Read meta from the database.
|
||||
pub fn read_meta<Block>(db: &dyn KeyValueDB, col_meta: Option<u32>, col_header: Option<u32>) -> Result<
|
||||
Meta<<<Block as BlockT>::Header as HeaderT>::Number, Block::Hash>,
|
||||
client::error::Error,
|
||||
sp_blockchain::Error,
|
||||
>
|
||||
where
|
||||
Block: BlockT,
|
||||
@@ -315,7 +314,7 @@ pub fn read_meta<Block>(db: &dyn KeyValueDB, col_meta: Option<u32>, col_header:
|
||||
let genesis_hash: Block::Hash = match db.get(col_meta, meta_keys::GENESIS_HASH).map_err(db_err)? {
|
||||
Some(h) => match Decode::decode(&mut &h[..]) {
|
||||
Ok(h) => h,
|
||||
Err(err) => return Err(client::error::Error::Backend(
|
||||
Err(err) => return Err(sp_blockchain::Error::Backend(
|
||||
format!("Error decoding genesis hash: {}", err)
|
||||
)),
|
||||
},
|
||||
@@ -328,7 +327,7 @@ pub fn read_meta<Block>(db: &dyn KeyValueDB, col_meta: Option<u32>, col_header:
|
||||
}),
|
||||
};
|
||||
|
||||
let load_meta_block = |desc, key| -> Result<_, client::error::Error> {
|
||||
let load_meta_block = |desc, key| -> Result<_, sp_blockchain::Error> {
|
||||
if let Some(Some(header)) = db.get(col_meta, key).and_then(|id|
|
||||
match id {
|
||||
Some(id) => db.get(col_header, &id).map(|h| h.map(|b| Block::Header::decode(&mut &b[..]).ok())),
|
||||
|
||||
@@ -22,8 +22,8 @@ keystore = { package = "substrate-keystore", path = "../keystore" }
|
||||
serde_json = "1.0.41"
|
||||
client-api = { package = "substrate-client-api", path = "../api" }
|
||||
client = { package = "substrate-client", path = "../" }
|
||||
header-metadata = { package = "substrate-header-metadata", path = "../header-metadata" }
|
||||
inherents = { package = "substrate-inherents", path = "../../primitives/inherents" }
|
||||
sp-blockchain = { path = "../../primitives/blockchain" }
|
||||
network = { package = "substrate-network", path = "../network" }
|
||||
sp-finality-tracker = { path = "../../primitives/finality-tracker" }
|
||||
fg_primitives = { package = "substrate-finality-grandpa-primitives", path = "../../primitives/finality-grandpa" }
|
||||
|
||||
@@ -20,7 +20,7 @@ use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
use codec::{Encode, Decode};
|
||||
use client_api::backend::AuxStore;
|
||||
use client_api::error::{Result as ClientResult, Error as ClientError};
|
||||
use sp_blockchain::{Result as ClientResult, Error as ClientError};
|
||||
use fork_tree::ForkTree;
|
||||
use grandpa::round::State as RoundState;
|
||||
use sr_primitives::traits::{Block as BlockT, NumberFor};
|
||||
|
||||
@@ -47,11 +47,11 @@ impl<H: Copy + PartialEq, N: Copy + Ord> ConsensusChanges<H, N> {
|
||||
|
||||
/// Finalize all pending consensus changes that are finalized by given block.
|
||||
/// Returns true if there any changes were finalized.
|
||||
pub(crate) fn finalize<F: Fn(N) -> ::client_api::error::Result<Option<H>>>(
|
||||
pub(crate) fn finalize<F: Fn(N) -> ::sp_blockchain::Result<Option<H>>>(
|
||||
&mut self,
|
||||
block: (N, H),
|
||||
canonical_at_height: F,
|
||||
) -> ::client_api::error::Result<(bool, bool)> {
|
||||
) -> ::sp_blockchain::Result<(bool, bool)> {
|
||||
let (split_idx, has_finalized_changes) = self.pending_changes.iter()
|
||||
.enumerate()
|
||||
.take_while(|(_, &(at_height, _))| at_height <= block.0)
|
||||
|
||||
@@ -24,13 +24,13 @@ use codec::{Decode, Encode};
|
||||
use futures::prelude::*;
|
||||
use tokio_timer::Delay;
|
||||
use parking_lot::RwLock;
|
||||
use sp_blockchain::{HeaderBackend, Error as ClientError};
|
||||
|
||||
use client_api::{
|
||||
HeaderBackend, BlockchainEvents,
|
||||
BlockchainEvents,
|
||||
backend::{Backend},
|
||||
Finalizer,
|
||||
call_executor::CallExecutor,
|
||||
error::Error as ClientError,
|
||||
utils::is_descendent_of,
|
||||
};
|
||||
use client::{
|
||||
@@ -534,7 +534,7 @@ pub(crate) fn ancestry<B, Block: BlockT<Hash=H256>, E, RA>(
|
||||
{
|
||||
if base == block { return Err(GrandpaError::NotDescendent) }
|
||||
|
||||
let tree_route_res = header_metadata::tree_route(client, block, base);
|
||||
let tree_route_res = sp_blockchain::tree_route(client, block, base);
|
||||
|
||||
let tree_route = match tree_route_res {
|
||||
Ok(tree_route) => tree_route,
|
||||
|
||||
@@ -38,11 +38,10 @@ use std::iter;
|
||||
use std::sync::Arc;
|
||||
use log::{trace, warn};
|
||||
|
||||
use sp_blockchain::{Backend as BlockchainBackend, Error as ClientError, Result as ClientResult};
|
||||
use client_api::{
|
||||
backend::Backend, blockchain::Backend as BlockchainBackend, CallExecutor,
|
||||
error::{Error as ClientError, Result as ClientResult},
|
||||
backend::Backend, CallExecutor, StorageProof,
|
||||
light::{FetchChecker, RemoteReadRequest},
|
||||
StorageProof,
|
||||
};
|
||||
use client::Client;
|
||||
use codec::{Encode, Decode};
|
||||
@@ -259,7 +258,7 @@ pub(crate) fn prove_finality<Block: BlockT<Hash=H256>, B: BlockchainBackend<Bloc
|
||||
authorities_set_id: u64,
|
||||
begin: Block::Hash,
|
||||
end: Block::Hash,
|
||||
) -> ::client_api::error::Result<Option<Vec<u8>>>
|
||||
) -> ::sp_blockchain::Result<Option<Vec<u8>>>
|
||||
where
|
||||
J: ProvableJustification<Block::Header>,
|
||||
{
|
||||
|
||||
@@ -21,11 +21,8 @@ use codec::Encode;
|
||||
use futures::sync::mpsc;
|
||||
use parking_lot::RwLockWriteGuard;
|
||||
|
||||
use client_api::{
|
||||
backend::Backend, blockchain,
|
||||
CallExecutor, blockchain::HeaderBackend, well_known_cache_keys,
|
||||
utils::is_descendent_of,
|
||||
};
|
||||
use sp_blockchain::{HeaderBackend, BlockStatus, well_known_cache_keys};
|
||||
use client_api::{backend::Backend, CallExecutor, utils::is_descendent_of};
|
||||
use client::Client;
|
||||
use consensus_common::{
|
||||
BlockImport, Error as ConsensusError,
|
||||
@@ -403,8 +400,8 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, SC> BlockImport<Block>
|
||||
// early exit if block already in chain, otherwise the check for
|
||||
// authority changes will error when trying to re-import a change block
|
||||
match self.inner.status(BlockId::Hash(hash)) {
|
||||
Ok(blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain),
|
||||
Ok(blockchain::BlockStatus::Unknown) => {},
|
||||
Ok(BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain),
|
||||
Ok(BlockStatus::Unknown) => {},
|
||||
Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()),
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use client::Client;
|
||||
use client_api::{CallExecutor, backend::Backend, error::Error as ClientError};
|
||||
use client_api::{CallExecutor, backend::Backend};
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use codec::{Encode, Decode};
|
||||
use grandpa::voter_set::VoterSet;
|
||||
use grandpa::{Error as GrandpaError};
|
||||
|
||||
@@ -55,10 +55,8 @@
|
||||
use futures::prelude::*;
|
||||
use log::{debug, error, info};
|
||||
use futures::sync::mpsc;
|
||||
use client_api::{
|
||||
BlockchainEvents, CallExecutor, backend::Backend, error::Error as ClientError,
|
||||
ExecutionStrategy, HeaderBackend
|
||||
};
|
||||
use client_api::{BlockchainEvents, CallExecutor, backend::Backend, ExecutionStrategy};
|
||||
use sp_blockchain::{HeaderBackend, Error as ClientError};
|
||||
use client::Client;
|
||||
use codec::{Decode, Encode};
|
||||
use sr_primitives::generic::BlockId;
|
||||
@@ -546,7 +544,7 @@ pub struct GrandpaParams<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X> {
|
||||
/// block import worker that has already been instantiated with `block_import`.
|
||||
pub fn run_grandpa_voter<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X>(
|
||||
grandpa_params: GrandpaParams<B, E, Block, N, RA, SC, VR, X>,
|
||||
) -> client_api::error::Result<impl Future<Item=(),Error=()> + Send + 'static> where
|
||||
) -> sp_blockchain::Result<impl Future<Item=(),Error=()> + Send + 'static> where
|
||||
Block::Hash: Ord,
|
||||
B: Backend<Block, Blake2Hasher> + 'static,
|
||||
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
|
||||
@@ -880,7 +878,7 @@ where
|
||||
#[deprecated(since = "1.1.0", note = "Please switch to run_grandpa_voter.")]
|
||||
pub fn run_grandpa<B, E, Block: BlockT<Hash=H256>, N, RA, SC, VR, X>(
|
||||
grandpa_params: GrandpaParams<B, E, Block, N, RA, SC, VR, X>,
|
||||
) -> ::client_api::error::Result<impl Future<Item=(),Error=()> + Send + 'static> where
|
||||
) -> ::sp_blockchain::Result<impl Future<Item=(),Error=()> + Send + 'static> where
|
||||
Block::Hash: Ord,
|
||||
B: Backend<Block, Blake2Hasher> + 'static,
|
||||
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
|
||||
|
||||
@@ -19,13 +19,8 @@ use std::sync::Arc;
|
||||
use log::{info, trace, warn};
|
||||
use parking_lot::RwLock;
|
||||
use client::Client;
|
||||
use client_api::{
|
||||
CallExecutor,
|
||||
backend::{AuxStore, Backend, Finalizer},
|
||||
blockchain::HeaderBackend,
|
||||
error::Error as ClientError,
|
||||
well_known_cache_keys,
|
||||
};
|
||||
use client_api::{CallExecutor, backend::{AuxStore, Backend, Finalizer}};
|
||||
use sp_blockchain::{HeaderBackend, Error as ClientError, well_known_cache_keys};
|
||||
use codec::{Encode, Decode};
|
||||
use consensus_common::{
|
||||
import_queue::Verifier,
|
||||
|
||||
@@ -156,7 +156,7 @@ pub fn run_grandpa_observer<B, E, Block: BlockT<Hash=H256>, N, RA, SC>(
|
||||
link: LinkHalf<B, E, Block, RA, SC>,
|
||||
network: N,
|
||||
on_exit: impl Future<Item=(),Error=()> + Clone + Send + 'static,
|
||||
) -> ::client_api::error::Result<impl Future<Item=(),Error=()> + Send + 'static> where
|
||||
) -> ::sp_blockchain::Result<impl Future<Item=(),Error=()> + Send + 'static> where
|
||||
B: Backend<Block, Blake2Hasher> + 'static,
|
||||
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + 'static,
|
||||
N: Network<Block> + Send + Sync + 'static,
|
||||
|
||||
@@ -26,7 +26,7 @@ use futures03::{StreamExt as _, TryStreamExt as _};
|
||||
use tokio::runtime::current_thread;
|
||||
use keyring::Ed25519Keyring;
|
||||
use client::LongestChain;
|
||||
use client_api::error::Result;
|
||||
use sp_blockchain::Result;
|
||||
use sr_api::{Core, RuntimeVersion, ApiExt, StorageProof};
|
||||
use test_client::{self, runtime::BlockNumber};
|
||||
use consensus_common::{BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult};
|
||||
@@ -242,7 +242,7 @@ impl Core<Block> for RuntimeApi {
|
||||
}
|
||||
|
||||
impl ApiExt<Block> for RuntimeApi {
|
||||
type Error = client_api::error::Error;
|
||||
type Error = sp_blockchain::Error;
|
||||
|
||||
fn map_api_result<F: FnOnce(&Self) -> result::Result<R, E>, R, E>(
|
||||
&self,
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
[package]
|
||||
name = "substrate-header-metadata"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
lru = { version = "0.4.0" }
|
||||
parking_lot = { version = "0.9.0" }
|
||||
sr-primitives = { path = "../../primitives/sr-primitives" }
|
||||
@@ -1,281 +0,0 @@
|
||||
// Copyright 2019 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/>.
|
||||
|
||||
//! Implements tree backend, cached header metadata and algorithms
|
||||
//! to compute routes efficiently over the tree of headers.
|
||||
|
||||
use sr_primitives::traits::{Block as BlockT, NumberFor, Header};
|
||||
use parking_lot::RwLock;
|
||||
use lru::LruCache;
|
||||
|
||||
/// Set to the expected max difference between `best` and `finalized` blocks at sync.
|
||||
const LRU_CACHE_SIZE: usize = 5_000;
|
||||
|
||||
/// Get lowest common ancestor between two blocks in the tree.
|
||||
///
|
||||
/// This implementation is efficient because our trees have very few and
|
||||
/// small branches, and because of our current query pattern:
|
||||
/// lca(best, final), lca(best + 1, final), lca(best + 2, final), etc.
|
||||
/// The first call is O(h) but the others are O(1).
|
||||
pub fn lowest_common_ancestor<Block: BlockT, T: HeaderMetadata<Block>>(
|
||||
backend: &T,
|
||||
id_one: Block::Hash,
|
||||
id_two: Block::Hash,
|
||||
) -> Result<HashAndNumber<Block>, T::Error> {
|
||||
let mut header_one = backend.header_metadata(id_one)?;
|
||||
let mut header_two = backend.header_metadata(id_two)?;
|
||||
|
||||
let mut orig_header_one = header_one.clone();
|
||||
let mut orig_header_two = header_two.clone();
|
||||
|
||||
// We move through ancestor links as much as possible, since ancestor >= parent.
|
||||
|
||||
while header_one.number > header_two.number {
|
||||
let ancestor_one = backend.header_metadata(header_one.ancestor)?;
|
||||
|
||||
if ancestor_one.number >= header_two.number {
|
||||
header_one = ancestor_one;
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
while header_one.number < header_two.number {
|
||||
let ancestor_two = backend.header_metadata(header_two.ancestor)?;
|
||||
|
||||
if ancestor_two.number >= header_one.number {
|
||||
header_two = ancestor_two;
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Then we move the remaining path using parent links.
|
||||
|
||||
while header_one.hash != header_two.hash {
|
||||
if header_one.number > header_two.number {
|
||||
header_one = backend.header_metadata(header_one.parent)?;
|
||||
} else {
|
||||
header_two = backend.header_metadata(header_two.parent)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Update cached ancestor links.
|
||||
|
||||
if orig_header_one.number > header_one.number {
|
||||
orig_header_one.ancestor = header_one.hash;
|
||||
backend.insert_header_metadata(orig_header_one.hash, orig_header_one);
|
||||
}
|
||||
|
||||
if orig_header_two.number > header_one.number {
|
||||
orig_header_two.ancestor = header_one.hash;
|
||||
backend.insert_header_metadata(orig_header_two.hash, orig_header_two);
|
||||
}
|
||||
|
||||
Ok(HashAndNumber {
|
||||
hash: header_one.hash,
|
||||
number: header_one.number,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute a tree-route between two blocks. See tree-route docs for more details.
|
||||
pub fn tree_route<Block: BlockT, T: HeaderMetadata<Block>>(
|
||||
backend: &T,
|
||||
from: Block::Hash,
|
||||
to: Block::Hash,
|
||||
) -> Result<TreeRoute<Block>, T::Error> {
|
||||
let mut from = backend.header_metadata(from)?;
|
||||
let mut to = backend.header_metadata(to)?;
|
||||
|
||||
let mut from_branch = Vec::new();
|
||||
let mut to_branch = Vec::new();
|
||||
|
||||
while to.number > from.number {
|
||||
to_branch.push(HashAndNumber {
|
||||
number: to.number,
|
||||
hash: to.hash,
|
||||
});
|
||||
|
||||
to = backend.header_metadata(to.parent)?;
|
||||
}
|
||||
|
||||
while from.number > to.number {
|
||||
from_branch.push(HashAndNumber {
|
||||
number: from.number,
|
||||
hash: from.hash,
|
||||
});
|
||||
from = backend.header_metadata(from.parent)?;
|
||||
}
|
||||
|
||||
// numbers are equal now. walk backwards until the block is the same
|
||||
|
||||
while to.hash != from.hash {
|
||||
to_branch.push(HashAndNumber {
|
||||
number: to.number,
|
||||
hash: to.hash,
|
||||
});
|
||||
to = backend.header_metadata(to.parent)?;
|
||||
|
||||
from_branch.push(HashAndNumber {
|
||||
number: from.number,
|
||||
hash: from.hash,
|
||||
});
|
||||
from = backend.header_metadata(from.parent)?;
|
||||
}
|
||||
|
||||
// add the pivot block. and append the reversed to-branch (note that it's reverse order originals)
|
||||
let pivot = from_branch.len();
|
||||
from_branch.push(HashAndNumber {
|
||||
number: to.number,
|
||||
hash: to.hash,
|
||||
});
|
||||
from_branch.extend(to_branch.into_iter().rev());
|
||||
|
||||
Ok(TreeRoute {
|
||||
route: from_branch,
|
||||
pivot,
|
||||
})
|
||||
}
|
||||
|
||||
/// Hash and number of a block.
|
||||
#[derive(Debug)]
|
||||
pub struct HashAndNumber<Block: BlockT> {
|
||||
/// The number of the block.
|
||||
pub number: NumberFor<Block>,
|
||||
/// The hash of the block.
|
||||
pub hash: Block::Hash,
|
||||
}
|
||||
|
||||
/// A tree-route from one block to another in the chain.
|
||||
///
|
||||
/// All blocks prior to the pivot in the deque is the reverse-order unique ancestry
|
||||
/// of the first block, the block at the pivot index is the common ancestor,
|
||||
/// and all blocks after the pivot is the ancestry of the second block, in
|
||||
/// order.
|
||||
///
|
||||
/// The ancestry sets will include the given blocks, and thus the tree-route is
|
||||
/// never empty.
|
||||
///
|
||||
/// ```text
|
||||
/// Tree route from R1 to E2. Retracted is [R1, R2, R3], Common is C, enacted [E1, E2]
|
||||
/// <- R3 <- R2 <- R1
|
||||
/// /
|
||||
/// C
|
||||
/// \-> E1 -> E2
|
||||
/// ```
|
||||
///
|
||||
/// ```text
|
||||
/// Tree route from C to E2. Retracted empty. Common is C, enacted [E1, E2]
|
||||
/// C -> E1 -> E2
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct TreeRoute<Block: BlockT> {
|
||||
route: Vec<HashAndNumber<Block>>,
|
||||
pivot: usize,
|
||||
}
|
||||
|
||||
impl<Block: BlockT> TreeRoute<Block> {
|
||||
/// Get a slice of all retracted blocks in reverse order (towards common ancestor)
|
||||
pub fn retracted(&self) -> &[HashAndNumber<Block>] {
|
||||
&self.route[..self.pivot]
|
||||
}
|
||||
|
||||
/// Get the common ancestor block. This might be one of the two blocks of the
|
||||
/// route.
|
||||
pub fn common_block(&self) -> &HashAndNumber<Block> {
|
||||
self.route.get(self.pivot).expect("tree-routes are computed between blocks; \
|
||||
which are included in the route; \
|
||||
thus it is never empty; qed")
|
||||
}
|
||||
|
||||
/// Get a slice of enacted blocks (descendents of the common ancestor)
|
||||
pub fn enacted(&self) -> &[HashAndNumber<Block>] {
|
||||
&self.route[self.pivot + 1 ..]
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles header metadata: hash, number, parent hash, etc.
|
||||
pub trait HeaderMetadata<Block: BlockT> {
|
||||
/// Error used in case the header metadata is not found.
|
||||
type Error;
|
||||
|
||||
fn header_metadata(&self, hash: Block::Hash) -> Result<CachedHeaderMetadata<Block>, Self::Error>;
|
||||
fn insert_header_metadata(&self, hash: Block::Hash, header_metadata: CachedHeaderMetadata<Block>);
|
||||
fn remove_header_metadata(&self, hash: Block::Hash);
|
||||
}
|
||||
|
||||
/// Caches header metadata in an in-memory LRU cache.
|
||||
pub struct HeaderMetadataCache<Block: BlockT> {
|
||||
cache: RwLock<LruCache<Block::Hash, CachedHeaderMetadata<Block>>>,
|
||||
}
|
||||
|
||||
impl<Block: BlockT> HeaderMetadataCache<Block> {
|
||||
/// Creates a new LRU header metadata cache with `capacity`.
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
HeaderMetadataCache {
|
||||
cache: RwLock::new(LruCache::new(capacity)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT> Default for HeaderMetadataCache<Block> {
|
||||
fn default() -> Self {
|
||||
HeaderMetadataCache {
|
||||
cache: RwLock::new(LruCache::new(LRU_CACHE_SIZE)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT> HeaderMetadata<Block> for HeaderMetadataCache<Block> {
|
||||
type Error = String;
|
||||
|
||||
fn header_metadata(&self, hash: Block::Hash) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
|
||||
self.cache.write().get(&hash).cloned()
|
||||
.ok_or("header metadata not found in cache".to_owned())
|
||||
}
|
||||
|
||||
fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata<Block>) {
|
||||
self.cache.write().put(hash, metadata);
|
||||
}
|
||||
|
||||
fn remove_header_metadata(&self, hash: Block::Hash) {
|
||||
self.cache.write().pop(&hash);
|
||||
}
|
||||
}
|
||||
|
||||
/// Cached header metadata. Used to efficiently traverse the tree.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CachedHeaderMetadata<Block: BlockT> {
|
||||
/// Hash of the header.
|
||||
pub hash: Block::Hash,
|
||||
/// Block number.
|
||||
pub number: NumberFor<Block>,
|
||||
/// Hash of parent header.
|
||||
pub parent: Block::Hash,
|
||||
/// Hash of an ancestor header. Used to jump through the tree.
|
||||
ancestor: Block::Hash,
|
||||
}
|
||||
|
||||
impl<Block: BlockT> From<&Block::Header> for CachedHeaderMetadata<Block> {
|
||||
fn from(header: &Block::Header) -> Self {
|
||||
CachedHeaderMetadata {
|
||||
hash: header.hash().clone(),
|
||||
number: header.number().clone(),
|
||||
parent: header.parent_hash().clone(),
|
||||
ancestor: header.parent_hash().clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,13 +27,13 @@ fork-tree = { path = "../../utils/fork-tree" }
|
||||
consensus = { package = "substrate-consensus-common", path = "../../primitives/consensus/common" }
|
||||
client = { package = "substrate-client", path = "../" }
|
||||
client-api = { package = "substrate-client-api", path = "../api" }
|
||||
header_metadata = { package = "substrate-header-metadata", path = "../header-metadata" }
|
||||
sp-blockchain = { path = "../../primitives/blockchain" }
|
||||
sr-primitives = { path = "../../primitives/sr-primitives" }
|
||||
sr-arithmetic = { path = "../../primitives/sr-arithmetic" }
|
||||
primitives = { package = "substrate-primitives", path = "../../primitives/core" }
|
||||
block-builder = { package = "substrate-block-builder", path = "../block-builder" }
|
||||
codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] }
|
||||
peerset = { package = "substrate-peerset", path = "../../primitives/peerset" }
|
||||
peerset = { package = "substrate-peerset", path = "../peerset" }
|
||||
serde = { version = "1.0.101", features = ["derive"] }
|
||||
serde_json = "1.0.41"
|
||||
slog = { version = "2.5.2", features = ["nested-values"] }
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Blockchain access trait
|
||||
|
||||
use client::Client as SubstrateClient;
|
||||
use client_api::error::Error;
|
||||
use sp_blockchain::Error;
|
||||
use client_api::{ChangesProof, StorageProof, ClientInfo, CallExecutor};
|
||||
use consensus::{BlockImport, BlockStatus, Error as ConsensusError};
|
||||
use sr_primitives::traits::{Block as BlockT, Header as HeaderT};
|
||||
@@ -162,7 +162,7 @@ impl<B, E, Block, RA> Client<Block> for SubstrateClient<B, E, Block, RA> where
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let ancestor = header_metadata::lowest_common_ancestor(self, *block, *base)?;
|
||||
let ancestor = sp_blockchain::lowest_common_ancestor(self, *block, *base)?;
|
||||
|
||||
Ok(ancestor.hash == *base)
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
//! Substrate network possible errors.
|
||||
|
||||
use client_api;
|
||||
|
||||
use libp2p::{PeerId, Multiaddr};
|
||||
|
||||
use std::fmt;
|
||||
@@ -31,7 +29,7 @@ pub enum Error {
|
||||
/// Io error
|
||||
Io(std::io::Error),
|
||||
/// Client error
|
||||
Client(client_api::error::Error),
|
||||
Client(sp_blockchain::Error),
|
||||
/// The same bootnode (based on address) is registered with two different peer ids.
|
||||
#[display(
|
||||
fmt = "The same bootnode (`{}`) is registered with two different peer ids: `{}` and `{}`",
|
||||
|
||||
@@ -22,7 +22,7 @@ use std::sync::Arc;
|
||||
use futures::{prelude::*, sync::mpsc, sync::oneshot};
|
||||
use futures03::compat::{Compat01As03, Future01CompatExt as _};
|
||||
use parking_lot::Mutex;
|
||||
use client_api::error::Error as ClientError;
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use client_api::{Fetcher, FetchChecker, RemoteHeaderRequest,
|
||||
RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest,
|
||||
RemoteReadChildRequest, RemoteBodyRequest};
|
||||
|
||||
@@ -25,7 +25,7 @@ use std::time::{Instant, Duration};
|
||||
use log::{trace, info};
|
||||
use futures::sync::oneshot::{Sender as OneShotSender};
|
||||
use linked_hash_map::{Entry, LinkedHashMap};
|
||||
use client_api::error::Error as ClientError;
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use client_api::{FetchChecker, RemoteHeaderRequest,
|
||||
RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest, ChangesProof,
|
||||
RemoteReadChildRequest, RemoteBodyRequest, StorageProof};
|
||||
@@ -677,7 +677,7 @@ pub mod tests {
|
||||
use std::time::Instant;
|
||||
use futures::{Future, sync::oneshot};
|
||||
use sr_primitives::traits::{Block as BlockT, NumberFor, Header as HeaderT};
|
||||
use client_api::{error::{Error as ClientError, Result as ClientResult}};
|
||||
use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
||||
use client_api::{FetchChecker, RemoteHeaderRequest,
|
||||
ChangesProof, RemoteCallRequest, RemoteReadRequest,
|
||||
RemoteReadChildRequest, RemoteChangesRequest, RemoteBodyRequest};
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
//!
|
||||
|
||||
use blocks::BlockCollection;
|
||||
use client_api::{ClientInfo, error::Error as ClientError};
|
||||
use client_api::ClientInfo;
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use consensus::{BlockOrigin, BlockStatus,
|
||||
block_validation::{BlockAnnounceValidator, Validation},
|
||||
import_queue::{IncomingBlock, BlockImportResult, BlockImportError}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use client_api::error::Error as ClientError;
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use crate::protocol::sync::{PeerSync, PeerSyncState};
|
||||
use fork_tree::ForkTree;
|
||||
use libp2p::PeerId;
|
||||
@@ -283,7 +283,7 @@ impl<'a, B: BlockT> Matcher<'a, B> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::protocol::sync::PeerSync;
|
||||
use client_api::error::Error as ClientError;
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use quickcheck::{Arbitrary, Gen, QuickCheck, StdThreadGen};
|
||||
use rand::Rng;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
@@ -27,12 +27,13 @@ use std::sync::Arc;
|
||||
use crate::config::build_multiaddr;
|
||||
use log::trace;
|
||||
use crate::chain::FinalityProofProvider;
|
||||
use sp_blockchain::{
|
||||
Result as ClientResult, well_known_cache_keys::{self, Id as CacheKeyId},
|
||||
};
|
||||
use client_api::{
|
||||
ClientInfo, BlockchainEvents, BlockImportNotification,
|
||||
FinalityNotifications, ImportNotifications,
|
||||
FinalityNotification,
|
||||
error::Result as ClientResult,
|
||||
well_known_cache_keys::{self, Id as CacheKeyId},
|
||||
backend::{AuxStore, Backend, Finalizer}
|
||||
};
|
||||
use block_builder::BlockBuilder;
|
||||
|
||||
@@ -35,7 +35,7 @@ client-db = { package = "substrate-client-db", path = "../db/", default-features
|
||||
env_logger = "0.7.0"
|
||||
test-client = { package = "substrate-test-runtime-client", path = "../../test/utils/runtime/client" }
|
||||
tokio = "0.1.22"
|
||||
transaction_pool = { package = "substrate-transaction-pool", path = "../transaction-pool" }
|
||||
transaction_pool = { package = "sc-transaction-pool", path = "../../client/transaction-pool" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
description = "Connectivity manager based on reputation"
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "substrate-peerset"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
futures = "0.3.1"
|
||||
libp2p = { version = "0.13.0", default-features = false }
|
||||
log = "0.4.8"
|
||||
serde_json = "1.0.41"
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.7.2"
|
||||
@@ -0,0 +1,652 @@
|
||||
// Copyright 2018-2019 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/>.
|
||||
|
||||
//! Peer Set Manager (PSM). Contains the strategy for choosing which nodes the network should be
|
||||
//! connected to.
|
||||
|
||||
mod peersstate;
|
||||
|
||||
use std::{collections::{HashSet, HashMap}, collections::VecDeque, time::Instant};
|
||||
use futures::{prelude::*, channel::mpsc};
|
||||
use libp2p::PeerId;
|
||||
use log::{debug, error, trace};
|
||||
use serde_json::json;
|
||||
use std::{pin::Pin, task::Context, task::Poll};
|
||||
|
||||
/// We don't accept nodes whose reputation is under this value.
|
||||
const BANNED_THRESHOLD: i32 = 82 * (i32::min_value() / 100);
|
||||
/// Reputation change for a node when we get disconnected from it.
|
||||
const DISCONNECT_REPUTATION_CHANGE: i32 = -10;
|
||||
/// Reserved peers group ID
|
||||
const RESERVED_NODES: &'static str = "reserved";
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Action {
|
||||
AddReservedPeer(PeerId),
|
||||
RemoveReservedPeer(PeerId),
|
||||
SetReservedOnly(bool),
|
||||
ReportPeer(PeerId, i32),
|
||||
SetPriorityGroup(String, HashSet<PeerId>),
|
||||
AddToPriorityGroup(String, PeerId),
|
||||
RemoveFromPriorityGroup(String, PeerId),
|
||||
}
|
||||
|
||||
/// Shared handle to the peer set manager (PSM). Distributed around the code.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PeersetHandle {
|
||||
tx: mpsc::UnboundedSender<Action>,
|
||||
}
|
||||
|
||||
impl PeersetHandle {
|
||||
/// Adds a new reserved peer. The peerset will make an effort to always remain connected to
|
||||
/// this peer.
|
||||
///
|
||||
/// Has no effect if the node was already a reserved peer.
|
||||
///
|
||||
/// > **Note**: Keep in mind that the networking has to know an address for this node,
|
||||
/// > otherwise it will not be able to connect to it.
|
||||
pub fn add_reserved_peer(&self, peer_id: PeerId) {
|
||||
let _ = self.tx.unbounded_send(Action::AddReservedPeer(peer_id));
|
||||
}
|
||||
|
||||
/// Remove a previously-added reserved peer.
|
||||
///
|
||||
/// Has no effect if the node was not a reserved peer.
|
||||
pub fn remove_reserved_peer(&self, peer_id: PeerId) {
|
||||
let _ = self.tx.unbounded_send(Action::RemoveReservedPeer(peer_id));
|
||||
}
|
||||
|
||||
/// Sets whether or not the peerset only has connections .
|
||||
pub fn set_reserved_only(&self, reserved: bool) {
|
||||
let _ = self.tx.unbounded_send(Action::SetReservedOnly(reserved));
|
||||
}
|
||||
|
||||
/// Reports an adjustment to the reputation of the given peer.
|
||||
pub fn report_peer(&self, peer_id: PeerId, score_diff: i32) {
|
||||
let _ = self.tx.unbounded_send(Action::ReportPeer(peer_id, score_diff));
|
||||
}
|
||||
|
||||
/// Modify a priority group.
|
||||
pub fn set_priority_group(&self, group_id: String, peers: HashSet<PeerId>) {
|
||||
let _ = self.tx.unbounded_send(Action::SetPriorityGroup(group_id, peers));
|
||||
}
|
||||
|
||||
/// Add a peer to a priority group.
|
||||
pub fn add_to_priority_group(&self, group_id: String, peer_id: PeerId) {
|
||||
let _ = self.tx.unbounded_send(Action::AddToPriorityGroup(group_id, peer_id));
|
||||
}
|
||||
|
||||
/// Remove a peer from a priority group.
|
||||
pub fn remove_from_priority_group(&self, group_id: String, peer_id: PeerId) {
|
||||
let _ = self.tx.unbounded_send(Action::RemoveFromPriorityGroup(group_id, peer_id));
|
||||
}
|
||||
}
|
||||
|
||||
/// Message that can be sent by the peer set manager (PSM).
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Message {
|
||||
/// Request to open a connection to the given peer. From the point of view of the PSM, we are
|
||||
/// immediately connected.
|
||||
Connect(PeerId),
|
||||
|
||||
/// Drop the connection to the given peer, or cancel the connection attempt after a `Connect`.
|
||||
Drop(PeerId),
|
||||
|
||||
/// Equivalent to `Connect` for the peer corresponding to this incoming index.
|
||||
Accept(IncomingIndex),
|
||||
|
||||
/// Equivalent to `Drop` for the peer corresponding to this incoming index.
|
||||
Reject(IncomingIndex),
|
||||
}
|
||||
|
||||
/// Opaque identifier for an incoming connection. Allocated by the network.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct IncomingIndex(pub u64);
|
||||
|
||||
impl From<u64> for IncomingIndex {
|
||||
fn from(val: u64) -> IncomingIndex {
|
||||
IncomingIndex(val)
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration to pass when creating the peer set manager.
|
||||
#[derive(Debug)]
|
||||
pub struct PeersetConfig {
|
||||
/// Maximum number of ingoing links to peers.
|
||||
pub in_peers: u32,
|
||||
|
||||
/// Maximum number of outgoing links to peers.
|
||||
pub out_peers: u32,
|
||||
|
||||
/// List of bootstrap nodes to initialize the peer with.
|
||||
///
|
||||
/// > **Note**: Keep in mind that the networking has to know an address for these nodes,
|
||||
/// > otherwise it will not be able to connect to them.
|
||||
pub bootnodes: Vec<PeerId>,
|
||||
|
||||
/// If true, we only accept reserved nodes.
|
||||
pub reserved_only: bool,
|
||||
|
||||
/// List of nodes that we should always be connected to.
|
||||
///
|
||||
/// > **Note**: Keep in mind that the networking has to know an address for these nodes,
|
||||
/// > otherwise it will not be able to connect to them.
|
||||
pub reserved_nodes: Vec<PeerId>,
|
||||
}
|
||||
|
||||
/// Side of the peer set manager owned by the network. In other words, the "receiving" side.
|
||||
///
|
||||
/// Implements the `Stream` trait and can be polled for messages. The `Stream` never ends and never
|
||||
/// errors.
|
||||
#[derive(Debug)]
|
||||
pub struct Peerset {
|
||||
data: peersstate::PeersState,
|
||||
/// If true, we only accept reserved nodes.
|
||||
reserved_only: bool,
|
||||
/// Receiver for messages from the `PeersetHandle` and from `tx`.
|
||||
rx: mpsc::UnboundedReceiver<Action>,
|
||||
/// Sending side of `rx`.
|
||||
tx: mpsc::UnboundedSender<Action>,
|
||||
/// Queue of messages to be emitted when the `Peerset` is polled.
|
||||
message_queue: VecDeque<Message>,
|
||||
/// When the `Peerset` was created.
|
||||
created: Instant,
|
||||
/// Last time when we updated the reputations of connected nodes.
|
||||
latest_time_update: Instant,
|
||||
}
|
||||
|
||||
impl Peerset {
|
||||
/// Builds a new peerset from the given configuration.
|
||||
pub fn from_config(config: PeersetConfig) -> (Peerset, PeersetHandle) {
|
||||
let (tx, rx) = mpsc::unbounded();
|
||||
|
||||
let handle = PeersetHandle {
|
||||
tx: tx.clone(),
|
||||
};
|
||||
|
||||
let mut peerset = Peerset {
|
||||
data: peersstate::PeersState::new(config.in_peers, config.out_peers, config.reserved_only),
|
||||
tx,
|
||||
rx,
|
||||
reserved_only: config.reserved_only,
|
||||
message_queue: VecDeque::new(),
|
||||
created: Instant::now(),
|
||||
latest_time_update: Instant::now(),
|
||||
};
|
||||
|
||||
peerset.data.set_priority_group(RESERVED_NODES, config.reserved_nodes.into_iter().collect());
|
||||
for peer_id in config.bootnodes {
|
||||
if let peersstate::Peer::Unknown(entry) = peerset.data.peer(&peer_id) {
|
||||
entry.discover();
|
||||
} else {
|
||||
debug!(target: "peerset", "Duplicate bootnode in config: {:?}", peer_id);
|
||||
}
|
||||
}
|
||||
|
||||
peerset.alloc_slots();
|
||||
(peerset, handle)
|
||||
}
|
||||
|
||||
fn on_add_reserved_peer(&mut self, peer_id: PeerId) {
|
||||
let mut reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default();
|
||||
reserved.insert(peer_id);
|
||||
self.data.set_priority_group(RESERVED_NODES, reserved);
|
||||
self.alloc_slots();
|
||||
}
|
||||
|
||||
fn on_remove_reserved_peer(&mut self, peer_id: PeerId) {
|
||||
let mut reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default();
|
||||
reserved.remove(&peer_id);
|
||||
self.data.set_priority_group(RESERVED_NODES, reserved);
|
||||
match self.data.peer(&peer_id) {
|
||||
peersstate::Peer::Connected(peer) => {
|
||||
if self.reserved_only {
|
||||
peer.disconnect();
|
||||
self.message_queue.push_back(Message::Drop(peer_id));
|
||||
}
|
||||
}
|
||||
peersstate::Peer::NotConnected(_) => {},
|
||||
peersstate::Peer::Unknown(_) => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn on_set_reserved_only(&mut self, reserved_only: bool) {
|
||||
self.reserved_only = reserved_only;
|
||||
self.data.set_priority_only(reserved_only);
|
||||
|
||||
if self.reserved_only {
|
||||
// Disconnect non-reserved nodes.
|
||||
let reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default();
|
||||
for peer_id in self.data.connected_peers().cloned().collect::<Vec<_>>().into_iter() {
|
||||
let peer = self.data.peer(&peer_id).into_connected()
|
||||
.expect("We are enumerating connected peers, therefore the peer is connected; qed");
|
||||
if !reserved.contains(&peer_id) {
|
||||
peer.disconnect();
|
||||
self.message_queue.push_back(Message::Drop(peer_id));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.alloc_slots();
|
||||
}
|
||||
}
|
||||
|
||||
fn on_set_priority_group(&mut self, group_id: &str, peers: HashSet<PeerId>) {
|
||||
self.data.set_priority_group(group_id, peers);
|
||||
self.alloc_slots();
|
||||
}
|
||||
|
||||
fn on_add_to_priority_group(&mut self, group_id: &str, peer_id: PeerId) {
|
||||
self.data.add_to_priority_group(group_id, peer_id);
|
||||
self.alloc_slots();
|
||||
}
|
||||
|
||||
fn on_remove_from_priority_group(&mut self, group_id: &str, peer_id: PeerId) {
|
||||
self.data.remove_from_priority_group(group_id, &peer_id);
|
||||
self.alloc_slots();
|
||||
}
|
||||
|
||||
fn on_report_peer(&mut self, peer_id: PeerId, score_diff: i32) {
|
||||
// We want reputations to be up-to-date before adjusting them.
|
||||
self.update_time();
|
||||
|
||||
match self.data.peer(&peer_id) {
|
||||
peersstate::Peer::Connected(mut peer) => {
|
||||
peer.add_reputation(score_diff);
|
||||
if peer.reputation() < BANNED_THRESHOLD {
|
||||
peer.disconnect();
|
||||
self.message_queue.push_back(Message::Drop(peer_id));
|
||||
}
|
||||
},
|
||||
peersstate::Peer::NotConnected(mut peer) => peer.add_reputation(score_diff),
|
||||
peersstate::Peer::Unknown(peer) => peer.discover().add_reputation(score_diff),
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the value of `self.latest_time_update` and performs all the updates that happen
|
||||
/// over time, such as reputation increases for staying connected.
|
||||
fn update_time(&mut self) {
|
||||
// We basically do `(now - self.latest_update).as_secs()`, except that by the way we do it
|
||||
// we know that we're not going to miss seconds because of rounding to integers.
|
||||
let secs_diff = {
|
||||
let now = Instant::now();
|
||||
let elapsed_latest = self.latest_time_update - self.created;
|
||||
let elapsed_now = now - self.created;
|
||||
self.latest_time_update = now;
|
||||
elapsed_now.as_secs() - elapsed_latest.as_secs()
|
||||
};
|
||||
|
||||
// For each elapsed second, move the node reputation towards zero.
|
||||
// If we multiply each second the reputation by `k` (where `k` is between 0 and 1), it
|
||||
// takes `ln(0.5) / ln(k)` seconds to reduce the reputation by half. Use this formula to
|
||||
// empirically determine a value of `k` that looks correct.
|
||||
for _ in 0..secs_diff {
|
||||
for peer in self.data.peers().cloned().collect::<Vec<_>>() {
|
||||
// We use `k = 0.98`, so we divide by `50`. With that value, it takes 34.3 seconds
|
||||
// to reduce the reputation by half.
|
||||
fn reput_tick(reput: i32) -> i32 {
|
||||
let mut diff = reput / 50;
|
||||
if diff == 0 && reput < 0 {
|
||||
diff = -1;
|
||||
} else if diff == 0 && reput > 0 {
|
||||
diff = 1;
|
||||
}
|
||||
reput.saturating_sub(diff)
|
||||
}
|
||||
match self.data.peer(&peer) {
|
||||
peersstate::Peer::Connected(mut peer) =>
|
||||
peer.set_reputation(reput_tick(peer.reputation())),
|
||||
peersstate::Peer::NotConnected(mut peer) =>
|
||||
peer.set_reputation(reput_tick(peer.reputation())),
|
||||
peersstate::Peer::Unknown(_) => unreachable!("We iterate over known peers; qed")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to fill available out slots with nodes.
|
||||
fn alloc_slots(&mut self) {
|
||||
self.update_time();
|
||||
|
||||
// Try to grab the next node to attempt to connect to.
|
||||
while let Some(next) = {
|
||||
if self.reserved_only {
|
||||
self.data.priority_not_connected_peer_from_group(RESERVED_NODES)
|
||||
} else {
|
||||
self.data.priority_not_connected_peer()
|
||||
}
|
||||
} {
|
||||
match next.try_outgoing() {
|
||||
Ok(conn) => self.message_queue.push_back(Message::Connect(conn.into_peer_id())),
|
||||
Err(_) => break, // No more slots available.
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
if self.reserved_only {
|
||||
break
|
||||
}
|
||||
|
||||
// Try to grab the next node to attempt to connect to.
|
||||
let next = match self.data.highest_not_connected_peer() {
|
||||
Some(p) => p,
|
||||
None => break, // No known node to add.
|
||||
};
|
||||
|
||||
// Don't connect to nodes with an abysmal reputation.
|
||||
if next.reputation() < BANNED_THRESHOLD {
|
||||
break;
|
||||
}
|
||||
|
||||
match next.try_outgoing() {
|
||||
Ok(conn) => self.message_queue.push_back(Message::Connect(conn.into_peer_id())),
|
||||
Err(_) => break, // No more slots available.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicate that we received an incoming connection. Must be answered either with
|
||||
/// a corresponding `Accept` or `Reject`, except if we were already connected to this peer.
|
||||
///
|
||||
/// Note that this mechanism is orthogonal to `Connect`/`Drop`. Accepting an incoming
|
||||
/// connection implicitly means `Connect`, but incoming connections aren't cancelled by
|
||||
/// `dropped`.
|
||||
///
|
||||
// Implementation note: because of concurrency issues, it is possible that we push a `Connect`
|
||||
// message to the output channel with a `PeerId`, and that `incoming` gets called with the same
|
||||
// `PeerId` before that message has been read by the user. In this situation we must not answer.
|
||||
pub fn incoming(&mut self, peer_id: PeerId, index: IncomingIndex) {
|
||||
trace!(target: "peerset", "Incoming {:?}", peer_id);
|
||||
self.update_time();
|
||||
|
||||
let not_connected = match self.data.peer(&peer_id) {
|
||||
// If we're already connected, don't answer, as the docs mention.
|
||||
peersstate::Peer::Connected(_) => return,
|
||||
peersstate::Peer::NotConnected(entry) => entry,
|
||||
peersstate::Peer::Unknown(entry) => entry.discover(),
|
||||
};
|
||||
|
||||
if not_connected.reputation() < BANNED_THRESHOLD {
|
||||
self.message_queue.push_back(Message::Reject(index));
|
||||
return
|
||||
}
|
||||
|
||||
match not_connected.try_accept_incoming() {
|
||||
Ok(_) => self.message_queue.push_back(Message::Accept(index)),
|
||||
Err(_) => self.message_queue.push_back(Message::Reject(index)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicate that we dropped an active connection with a peer, or that we failed to connect.
|
||||
///
|
||||
/// Must only be called after the PSM has either generated a `Connect` message with this
|
||||
/// `PeerId`, or accepted an incoming connection with this `PeerId`.
|
||||
pub fn dropped(&mut self, peer_id: PeerId) {
|
||||
trace!(target: "peerset", "Dropping {:?}", peer_id);
|
||||
|
||||
// We want reputations to be up-to-date before adjusting them.
|
||||
self.update_time();
|
||||
|
||||
match self.data.peer(&peer_id) {
|
||||
peersstate::Peer::Connected(mut entry) => {
|
||||
// Decrease the node's reputation so that we don't try it again and again and again.
|
||||
entry.add_reputation(DISCONNECT_REPUTATION_CHANGE);
|
||||
entry.disconnect();
|
||||
}
|
||||
peersstate::Peer::NotConnected(_) | peersstate::Peer::Unknown(_) =>
|
||||
error!(target: "peerset", "Received dropped() for non-connected node"),
|
||||
}
|
||||
|
||||
self.alloc_slots();
|
||||
}
|
||||
|
||||
/// Adds discovered peer ids to the PSM.
|
||||
///
|
||||
/// > **Note**: There is no equivalent "expired" message, meaning that it is the responsibility
|
||||
/// > of the PSM to remove `PeerId`s that fail to dial too often.
|
||||
pub fn discovered<I: IntoIterator<Item = PeerId>>(&mut self, peer_ids: I) {
|
||||
let mut discovered_any = false;
|
||||
|
||||
for peer_id in peer_ids {
|
||||
if let peersstate::Peer::Unknown(entry) = self.data.peer(&peer_id) {
|
||||
entry.discover();
|
||||
discovered_any = true;
|
||||
}
|
||||
}
|
||||
|
||||
if discovered_any {
|
||||
self.alloc_slots();
|
||||
}
|
||||
}
|
||||
|
||||
/// Reports an adjustment to the reputation of the given peer.
|
||||
pub fn report_peer(&mut self, peer_id: PeerId, score_diff: i32) {
|
||||
// We don't immediately perform the adjustments in order to have state consistency. We
|
||||
// don't want the reporting here to take priority over messages sent using the
|
||||
// `PeersetHandle`.
|
||||
let _ = self.tx.unbounded_send(Action::ReportPeer(peer_id, score_diff));
|
||||
}
|
||||
|
||||
/// Produces a JSON object containing the state of the peerset manager, for debugging purposes.
|
||||
pub fn debug_info(&mut self) -> serde_json::Value {
|
||||
self.update_time();
|
||||
|
||||
json!({
|
||||
"nodes": self.data.peers().cloned().collect::<Vec<_>>().into_iter().map(|peer_id| {
|
||||
let state = match self.data.peer(&peer_id) {
|
||||
peersstate::Peer::Connected(entry) => json!({
|
||||
"connected": true,
|
||||
"reputation": entry.reputation()
|
||||
}),
|
||||
peersstate::Peer::NotConnected(entry) => json!({
|
||||
"connected": false,
|
||||
"reputation": entry.reputation()
|
||||
}),
|
||||
peersstate::Peer::Unknown(_) =>
|
||||
unreachable!("We iterate over the known peers; QED")
|
||||
};
|
||||
|
||||
(peer_id.to_base58(), state)
|
||||
}).collect::<HashMap<_, _>>(),
|
||||
"reserved_only": self.reserved_only,
|
||||
"message_queue": self.message_queue.len(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns priority group by id.
|
||||
pub fn get_priority_group(&self, group_id: &str) -> Option<HashSet<PeerId>> {
|
||||
self.data.get_priority_group(group_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for Peerset {
|
||||
type Item = Message;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
loop {
|
||||
if let Some(message) = self.message_queue.pop_front() {
|
||||
return Poll::Ready(Some(message));
|
||||
}
|
||||
|
||||
let action = match Stream::poll_next(Pin::new(&mut self.rx), cx) {
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(Some(event)) => event,
|
||||
Poll::Ready(None) => return Poll::Pending,
|
||||
};
|
||||
|
||||
match action {
|
||||
Action::AddReservedPeer(peer_id) =>
|
||||
self.on_add_reserved_peer(peer_id),
|
||||
Action::RemoveReservedPeer(peer_id) =>
|
||||
self.on_remove_reserved_peer(peer_id),
|
||||
Action::SetReservedOnly(reserved) =>
|
||||
self.on_set_reserved_only(reserved),
|
||||
Action::ReportPeer(peer_id, score_diff) =>
|
||||
self.on_report_peer(peer_id, score_diff),
|
||||
Action::SetPriorityGroup(group_id, peers) =>
|
||||
self.on_set_priority_group(&group_id, peers),
|
||||
Action::AddToPriorityGroup(group_id, peer_id) =>
|
||||
self.on_add_to_priority_group(&group_id, peer_id),
|
||||
Action::RemoveFromPriorityGroup(group_id, peer_id) =>
|
||||
self.on_remove_from_priority_group(&group_id, peer_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use libp2p::PeerId;
|
||||
use futures::prelude::*;
|
||||
use super::{PeersetConfig, Peerset, Message, IncomingIndex, BANNED_THRESHOLD};
|
||||
use std::{pin::Pin, task::Poll, thread, time::Duration};
|
||||
|
||||
fn assert_messages(mut peerset: Peerset, messages: Vec<Message>) -> Peerset {
|
||||
for expected_message in messages {
|
||||
let (message, p) = next_message(peerset).expect("expected message");
|
||||
assert_eq!(message, expected_message);
|
||||
peerset = p;
|
||||
}
|
||||
assert!(peerset.message_queue.is_empty(), peerset.message_queue);
|
||||
peerset
|
||||
}
|
||||
|
||||
fn next_message(mut peerset: Peerset) -> Result<(Message, Peerset), ()> {
|
||||
let next = futures::executor::block_on_stream(&mut peerset).next();
|
||||
let message = next.ok_or_else(|| ())?;
|
||||
Ok((message, peerset))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peerset_add_reserved_peer() {
|
||||
let bootnode = PeerId::random();
|
||||
let reserved_peer = PeerId::random();
|
||||
let reserved_peer2 = PeerId::random();
|
||||
let config = PeersetConfig {
|
||||
in_peers: 0,
|
||||
out_peers: 2,
|
||||
bootnodes: vec![bootnode],
|
||||
reserved_only: true,
|
||||
reserved_nodes: Vec::new(),
|
||||
};
|
||||
|
||||
let (peerset, handle) = Peerset::from_config(config);
|
||||
handle.add_reserved_peer(reserved_peer.clone());
|
||||
handle.add_reserved_peer(reserved_peer2.clone());
|
||||
|
||||
assert_messages(peerset, vec![
|
||||
Message::Connect(reserved_peer),
|
||||
Message::Connect(reserved_peer2)
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peerset_incoming() {
|
||||
let bootnode = PeerId::random();
|
||||
let incoming = PeerId::random();
|
||||
let incoming2 = PeerId::random();
|
||||
let incoming3 = PeerId::random();
|
||||
let ii = IncomingIndex(1);
|
||||
let ii2 = IncomingIndex(2);
|
||||
let ii3 = IncomingIndex(3);
|
||||
let ii4 = IncomingIndex(3);
|
||||
let config = PeersetConfig {
|
||||
in_peers: 2,
|
||||
out_peers: 1,
|
||||
bootnodes: vec![bootnode.clone()],
|
||||
reserved_only: false,
|
||||
reserved_nodes: Vec::new(),
|
||||
};
|
||||
|
||||
let (mut peerset, _handle) = Peerset::from_config(config);
|
||||
peerset.incoming(incoming.clone(), ii);
|
||||
peerset.incoming(incoming.clone(), ii4);
|
||||
peerset.incoming(incoming2.clone(), ii2);
|
||||
peerset.incoming(incoming3.clone(), ii3);
|
||||
|
||||
assert_messages(peerset, vec![
|
||||
Message::Connect(bootnode.clone()),
|
||||
Message::Accept(ii),
|
||||
Message::Accept(ii2),
|
||||
Message::Reject(ii3),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peerset_discovered() {
|
||||
let bootnode = PeerId::random();
|
||||
let discovered = PeerId::random();
|
||||
let discovered2 = PeerId::random();
|
||||
let config = PeersetConfig {
|
||||
in_peers: 0,
|
||||
out_peers: 2,
|
||||
bootnodes: vec![bootnode.clone()],
|
||||
reserved_only: false,
|
||||
reserved_nodes: vec![],
|
||||
};
|
||||
|
||||
let (mut peerset, _handle) = Peerset::from_config(config);
|
||||
peerset.discovered(Some(discovered.clone()));
|
||||
peerset.discovered(Some(discovered.clone()));
|
||||
peerset.discovered(Some(discovered2));
|
||||
|
||||
assert_messages(peerset, vec![
|
||||
Message::Connect(bootnode),
|
||||
Message::Connect(discovered),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peerset_banned() {
|
||||
let (mut peerset, handle) = Peerset::from_config(PeersetConfig {
|
||||
in_peers: 25,
|
||||
out_peers: 25,
|
||||
bootnodes: vec![],
|
||||
reserved_only: false,
|
||||
reserved_nodes: vec![],
|
||||
});
|
||||
|
||||
// We ban a node by setting its reputation under the threshold.
|
||||
let peer_id = PeerId::random();
|
||||
handle.report_peer(peer_id.clone(), BANNED_THRESHOLD - 1);
|
||||
|
||||
let fut = futures::future::poll_fn(move |cx| {
|
||||
// We need one polling for the message to be processed.
|
||||
assert_eq!(Stream::poll_next(Pin::new(&mut peerset), cx), Poll::Pending);
|
||||
|
||||
// Check that an incoming connection from that node gets refused.
|
||||
peerset.incoming(peer_id.clone(), IncomingIndex(1));
|
||||
if let Poll::Ready(msg) = Stream::poll_next(Pin::new(&mut peerset), cx) {
|
||||
assert_eq!(msg.unwrap(), Message::Reject(IncomingIndex(1)));
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
|
||||
// Wait a bit for the node's reputation to go above the threshold.
|
||||
thread::sleep(Duration::from_millis(1500));
|
||||
|
||||
// Try again. This time the node should be accepted.
|
||||
peerset.incoming(peer_id.clone(), IncomingIndex(2));
|
||||
while let Poll::Ready(msg) = Stream::poll_next(Pin::new(&mut peerset), cx) {
|
||||
assert_eq!(msg.unwrap(), Message::Accept(IncomingIndex(2)));
|
||||
}
|
||||
|
||||
Poll::Ready(())
|
||||
});
|
||||
|
||||
futures::executor::block_on(fut);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,720 @@
|
||||
// Copyright 2019 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/>.
|
||||
|
||||
//! Contains the state storage behind the peerset.
|
||||
|
||||
use libp2p::PeerId;
|
||||
use std::{borrow::Cow, collections::{HashSet, HashMap}};
|
||||
use log::warn;
|
||||
|
||||
/// State storage behind the peerset.
|
||||
///
|
||||
/// # Usage
|
||||
///
|
||||
/// This struct is nothing more but a data structure containing a list of nodes, where each node
|
||||
/// has a reputation and is either connected to us or not.
|
||||
///
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PeersState {
|
||||
/// List of nodes that we know about.
|
||||
///
|
||||
/// > **Note**: This list should really be ordered by decreasing reputation, so that we can
|
||||
/// easily select the best node to connect to. As a first draft, however, we don't
|
||||
/// sort, to make the logic easier.
|
||||
nodes: HashMap<PeerId, Node>,
|
||||
|
||||
/// Number of non-priority nodes for which the `ConnectionState` is `In`.
|
||||
num_in: u32,
|
||||
|
||||
/// Number of non-priority nodes for which the `ConnectionState` is `In`.
|
||||
num_out: u32,
|
||||
|
||||
/// Maximum allowed number of non-priority nodes for which the `ConnectionState` is `In`.
|
||||
max_in: u32,
|
||||
|
||||
/// Maximum allowed number of non-priority nodes for which the `ConnectionState` is `Out`.
|
||||
max_out: u32,
|
||||
|
||||
/// Priority groups. Each group is identified by a string ID and contains a set of peer IDs.
|
||||
priority_nodes: HashMap<String, HashSet<PeerId>>,
|
||||
|
||||
/// Only allow connections to/from peers in a priority group.
|
||||
priority_only: bool,
|
||||
}
|
||||
|
||||
/// State of a single node that we know about.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct Node {
|
||||
/// Whether we are connected to this node.
|
||||
connection_state: ConnectionState,
|
||||
|
||||
/// Reputation value of the node, between `i32::min_value` (we hate that node) and
|
||||
/// `i32::max_value` (we love that node).
|
||||
reputation: i32,
|
||||
}
|
||||
|
||||
impl Default for Node {
|
||||
fn default() -> Node {
|
||||
Node {
|
||||
connection_state: ConnectionState::NotConnected,
|
||||
reputation: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether we are connected to a node.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
enum ConnectionState {
|
||||
/// We are connected through an ingoing connection.
|
||||
In,
|
||||
/// We are connected through an outgoing connection.
|
||||
Out,
|
||||
/// We are not connected to this node.
|
||||
NotConnected,
|
||||
}
|
||||
|
||||
impl ConnectionState {
|
||||
/// Returns `true` for `In` and `Out`.
|
||||
fn is_connected(self) -> bool {
|
||||
match self {
|
||||
ConnectionState::In => true,
|
||||
ConnectionState::Out => true,
|
||||
ConnectionState::NotConnected => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PeersState {
|
||||
/// Builds a new empty `PeersState`.
|
||||
pub fn new(in_peers: u32, out_peers: u32, priority_only: bool) -> Self {
|
||||
PeersState {
|
||||
nodes: HashMap::new(),
|
||||
num_in: 0,
|
||||
num_out: 0,
|
||||
max_in: in_peers,
|
||||
max_out: out_peers,
|
||||
priority_nodes: HashMap::new(),
|
||||
priority_only,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an object that grants access to the state of a peer.
|
||||
pub fn peer<'a>(&'a mut self, peer_id: &'a PeerId) -> Peer<'a> {
|
||||
match self.nodes.get_mut(peer_id) {
|
||||
None => return Peer::Unknown(UnknownPeer {
|
||||
parent: self,
|
||||
peer_id: Cow::Borrowed(peer_id),
|
||||
}),
|
||||
Some(peer) => {
|
||||
if peer.connection_state.is_connected() {
|
||||
Peer::Connected(ConnectedPeer {
|
||||
state: self,
|
||||
peer_id: Cow::Borrowed(peer_id),
|
||||
})
|
||||
} else {
|
||||
Peer::NotConnected(NotConnectedPeer {
|
||||
state: self,
|
||||
peer_id: Cow::Borrowed(peer_id),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the list of all the peers we know of.
|
||||
// Note: this method could theoretically return a `Peer`, but implementing that
|
||||
// isn't simple.
|
||||
pub fn peers(&self) -> impl Iterator<Item = &PeerId> {
|
||||
self.nodes.keys()
|
||||
}
|
||||
|
||||
/// Returns the list of peers we are connected to.
|
||||
// Note: this method could theoretically return a `ConnectedPeer`, but implementing that
|
||||
// isn't simple.
|
||||
pub fn connected_peers(&self) -> impl Iterator<Item = &PeerId> {
|
||||
self.nodes.iter()
|
||||
.filter(|(_, p)| p.connection_state.is_connected())
|
||||
.map(|(p, _)| p)
|
||||
}
|
||||
|
||||
/// Returns the first priority peer that we are not connected to.
|
||||
///
|
||||
/// If multiple nodes are prioritized, which one is returned is unspecified.
|
||||
pub fn priority_not_connected_peer(&mut self) -> Option<NotConnectedPeer> {
|
||||
let id = self.priority_nodes.values()
|
||||
.flatten()
|
||||
.find(|id| self.nodes.get(id).map_or(false, |node| !node.connection_state.is_connected()))
|
||||
.cloned();
|
||||
id.map(move |id| NotConnectedPeer {
|
||||
state: self,
|
||||
peer_id: Cow::Owned(id),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the first priority peer that we are not connected to.
|
||||
///
|
||||
/// If multiple nodes are prioritized, which one is returned is unspecified.
|
||||
pub fn priority_not_connected_peer_from_group(&mut self, group_id: &str) -> Option<NotConnectedPeer> {
|
||||
let id = self.priority_nodes.get(group_id)
|
||||
.and_then(|group| group.iter()
|
||||
.find(|id| self.nodes.get(id).map_or(false, |node| !node.connection_state.is_connected()))
|
||||
.cloned());
|
||||
id.map(move |id| NotConnectedPeer {
|
||||
state: self,
|
||||
peer_id: Cow::Owned(id),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the peer with the highest reputation and that we are not connected to.
|
||||
///
|
||||
/// If multiple nodes have the same reputation, which one is returned is unspecified.
|
||||
pub fn highest_not_connected_peer(&mut self) -> Option<NotConnectedPeer> {
|
||||
let outcome = self.nodes
|
||||
.iter_mut()
|
||||
.filter(|(_, Node { connection_state, .. })| !connection_state.is_connected())
|
||||
.fold(None::<(&PeerId, &mut Node)>, |mut cur_node, to_try| {
|
||||
if let Some(cur_node) = cur_node.take() {
|
||||
if cur_node.1.reputation >= to_try.1.reputation {
|
||||
return Some(cur_node);
|
||||
}
|
||||
}
|
||||
Some(to_try)
|
||||
})
|
||||
.map(|(peer_id, _)| peer_id.clone());
|
||||
|
||||
if let Some(peer_id) = outcome {
|
||||
Some(NotConnectedPeer {
|
||||
state: self,
|
||||
peer_id: Cow::Owned(peer_id),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn disconnect(&mut self, peer_id: &PeerId) {
|
||||
let is_priority = self.is_priority(peer_id);
|
||||
if let Some(mut node) = self.nodes.get_mut(peer_id) {
|
||||
if !is_priority {
|
||||
match node.connection_state {
|
||||
ConnectionState::In => self.num_in -= 1,
|
||||
ConnectionState::Out => self.num_out -= 1,
|
||||
ConnectionState::NotConnected =>
|
||||
debug_assert!(false, "State inconsistency: disconnecting a disconnected node")
|
||||
}
|
||||
}
|
||||
node.connection_state = ConnectionState::NotConnected;
|
||||
} else {
|
||||
warn!(target: "peerset", "Attempting to disconnect unknown peer {}", peer_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the peer as connected with an outgoing connection.
|
||||
fn try_outgoing(&mut self, peer_id: &PeerId) -> bool {
|
||||
let is_priority = self.is_priority(peer_id);
|
||||
|
||||
// We are only accepting connections from priority nodes.
|
||||
if !is_priority && self.priority_only {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note that it is possible for num_out to be strictly superior to the max, in case we were
|
||||
// connected to reserved node then marked them as not reserved.
|
||||
if self.num_out >= self.max_out && !is_priority {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(mut peer) = self.nodes.get_mut(peer_id) {
|
||||
peer.connection_state = ConnectionState::Out;
|
||||
if !is_priority {
|
||||
self.num_out += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Tries to accept the peer as an incoming connection.
|
||||
///
|
||||
/// If there are enough slots available, switches the node to "connected" and returns `Ok`. If
|
||||
/// the slots are full, the node stays "not connected" and we return `Err`.
|
||||
///
|
||||
/// Note that reserved nodes don't count towards the number of slots.
|
||||
fn try_accept_incoming(&mut self, peer_id: &PeerId) -> bool {
|
||||
let is_priority = self.is_priority(peer_id);
|
||||
|
||||
// We are only accepting connections from priority nodes.
|
||||
if !is_priority && self.priority_only {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note that it is possible for num_in to be strictly superior to the max, in case we were
|
||||
// connected to reserved node then marked them as not reserved.
|
||||
if self.num_in >= self.max_in && !is_priority {
|
||||
return false;
|
||||
}
|
||||
if let Some(mut peer) = self.nodes.get_mut(peer_id) {
|
||||
peer.connection_state = ConnectionState::In;
|
||||
if !is_priority {
|
||||
self.num_in += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Sets priority group
|
||||
pub fn set_priority_group(&mut self, group_id: &str, peers: HashSet<PeerId>) {
|
||||
// update slot counters
|
||||
let all_other_groups: HashSet<_> = self.priority_nodes
|
||||
.iter()
|
||||
.filter(|(g, _)| *g != group_id)
|
||||
.flat_map(|(_, id)| id.clone())
|
||||
.collect();
|
||||
let existing_group = self.priority_nodes.remove(group_id).unwrap_or_default();
|
||||
for id in existing_group {
|
||||
// update slots for nodes that are no longer priority
|
||||
if !all_other_groups.contains(&id) {
|
||||
if let Some(peer) = self.nodes.get_mut(&id) {
|
||||
match peer.connection_state {
|
||||
ConnectionState::In => self.num_in += 1,
|
||||
ConnectionState::Out => self.num_out += 1,
|
||||
ConnectionState::NotConnected => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for id in &peers {
|
||||
// update slots for nodes that become priority
|
||||
if !all_other_groups.contains(&id) {
|
||||
let peer = self.nodes.entry(id.clone()).or_default();
|
||||
match peer.connection_state {
|
||||
ConnectionState::In => self.num_in -= 1,
|
||||
ConnectionState::Out => self.num_out -= 1,
|
||||
ConnectionState::NotConnected => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
self.priority_nodes.insert(group_id.into(), peers);
|
||||
}
|
||||
|
||||
/// Add a peer to a priority group.
|
||||
pub fn add_to_priority_group(&mut self, group_id: &str, peer_id: PeerId) {
|
||||
let mut peers = self.priority_nodes.get(group_id).cloned().unwrap_or_default();
|
||||
peers.insert(peer_id);
|
||||
self.set_priority_group(group_id, peers);
|
||||
}
|
||||
|
||||
/// Remove a peer from a priority group.
|
||||
pub fn remove_from_priority_group(&mut self, group_id: &str, peer_id: &PeerId) {
|
||||
let mut peers = self.priority_nodes.get(group_id).cloned().unwrap_or_default();
|
||||
peers.remove(&peer_id);
|
||||
self.set_priority_group(group_id, peers);
|
||||
}
|
||||
|
||||
/// Get priority group content.
|
||||
pub fn get_priority_group(&self, group_id: &str) -> Option<HashSet<PeerId>> {
|
||||
self.priority_nodes.get(group_id).cloned()
|
||||
}
|
||||
|
||||
/// Set whether to only allow connections to/from peers in a priority group.
|
||||
/// Calling this method does not affect any existing connection, e.g.
|
||||
/// enabling priority only will not disconnect from any non-priority peers
|
||||
/// we are already connected to, only future incoming/outgoing connection
|
||||
/// attempts will be affected.
|
||||
pub fn set_priority_only(&mut self, priority: bool) {
|
||||
self.priority_only = priority;
|
||||
}
|
||||
|
||||
/// Check that node is any priority group.
|
||||
fn is_priority(&self, peer_id: &PeerId) -> bool {
|
||||
self.priority_nodes.iter().any(|(_, group)| group.contains(peer_id))
|
||||
}
|
||||
|
||||
/// Returns the reputation value of the node.
|
||||
fn reputation(&self, peer_id: &PeerId) -> i32 {
|
||||
self.nodes.get(peer_id).map_or(0, |p| p.reputation)
|
||||
}
|
||||
|
||||
/// Sets the reputation of the peer.
|
||||
fn set_reputation(&mut self, peer_id: &PeerId, value: i32) {
|
||||
let node = self.nodes
|
||||
.entry(peer_id.clone())
|
||||
.or_default();
|
||||
node.reputation = value;
|
||||
}
|
||||
|
||||
/// Performs an arithmetic addition on the reputation score of that peer.
|
||||
///
|
||||
/// In case of overflow, the value will be capped.
|
||||
/// If the peer is unknown to us, we insert it and consider that it has a reputation of 0.
|
||||
fn add_reputation(&mut self, peer_id: &PeerId, modifier: i32) {
|
||||
let node = self.nodes
|
||||
.entry(peer_id.clone())
|
||||
.or_default();
|
||||
node.reputation = node.reputation.saturating_add(modifier);
|
||||
}
|
||||
}
|
||||
|
||||
/// Grants access to the state of a peer in the `PeersState`.
|
||||
pub enum Peer<'a> {
|
||||
/// We are connected to this node.
|
||||
Connected(ConnectedPeer<'a>),
|
||||
/// We are not connected to this node.
|
||||
NotConnected(NotConnectedPeer<'a>),
|
||||
/// We have never heard of this node.
|
||||
Unknown(UnknownPeer<'a>),
|
||||
}
|
||||
|
||||
impl<'a> Peer<'a> {
|
||||
/// If we are the `Connected` variant, returns the inner `ConnectedPeer`. Returns `None`
|
||||
/// otherwise.
|
||||
pub fn into_connected(self) -> Option<ConnectedPeer<'a>> {
|
||||
match self {
|
||||
Peer::Connected(peer) => Some(peer),
|
||||
Peer::NotConnected(_) => None,
|
||||
Peer::Unknown(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// If we are the `Unknown` variant, returns the inner `ConnectedPeer`. Returns `None`
|
||||
/// otherwise.
|
||||
#[cfg(test)] // Feel free to remove this if this function is needed outside of tests
|
||||
pub fn into_not_connected(self) -> Option<NotConnectedPeer<'a>> {
|
||||
match self {
|
||||
Peer::Connected(_) => None,
|
||||
Peer::NotConnected(peer) => Some(peer),
|
||||
Peer::Unknown(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// If we are the `Unknown` variant, returns the inner `ConnectedPeer`. Returns `None`
|
||||
/// otherwise.
|
||||
#[cfg(test)] // Feel free to remove this if this function is needed outside of tests
|
||||
pub fn into_unknown(self) -> Option<UnknownPeer<'a>> {
|
||||
match self {
|
||||
Peer::Connected(_) => None,
|
||||
Peer::NotConnected(_) => None,
|
||||
Peer::Unknown(peer) => Some(peer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A peer that is connected to us.
|
||||
pub struct ConnectedPeer<'a> {
|
||||
state: &'a mut PeersState,
|
||||
peer_id: Cow<'a, PeerId>,
|
||||
}
|
||||
|
||||
impl<'a> ConnectedPeer<'a> {
|
||||
/// Destroys this `ConnectedPeer` and returns the `PeerId` inside of it.
|
||||
pub fn into_peer_id(self) -> PeerId {
|
||||
self.peer_id.into_owned()
|
||||
}
|
||||
|
||||
/// Switches the peer to "not connected".
|
||||
pub fn disconnect(self) -> NotConnectedPeer<'a> {
|
||||
self.state.disconnect(&self.peer_id);
|
||||
NotConnectedPeer {
|
||||
state: self.state,
|
||||
peer_id: self.peer_id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the reputation value of the node.
|
||||
pub fn reputation(&self) -> i32 {
|
||||
self.state.reputation(&self.peer_id)
|
||||
}
|
||||
|
||||
/// Sets the reputation of the peer.
|
||||
pub fn set_reputation(&mut self, value: i32) {
|
||||
self.state.set_reputation(&self.peer_id, value)
|
||||
}
|
||||
|
||||
/// Performs an arithmetic addition on the reputation score of that peer.
|
||||
///
|
||||
/// In case of overflow, the value will be capped.
|
||||
pub fn add_reputation(&mut self, modifier: i32) {
|
||||
self.state.add_reputation(&self.peer_id, modifier)
|
||||
}
|
||||
}
|
||||
|
||||
/// A peer that is not connected to us.
|
||||
#[derive(Debug)]
|
||||
pub struct NotConnectedPeer<'a> {
|
||||
state: &'a mut PeersState,
|
||||
peer_id: Cow<'a, PeerId>,
|
||||
}
|
||||
|
||||
impl<'a> NotConnectedPeer<'a> {
|
||||
/// Destroys this `NotConnectedPeer` and returns the `PeerId` inside of it.
|
||||
#[cfg(test)] // Feel free to remove this if this function is needed outside of tests
|
||||
pub fn into_peer_id(self) -> PeerId {
|
||||
self.peer_id.into_owned()
|
||||
}
|
||||
|
||||
/// Tries to set the peer as connected as an outgoing connection.
|
||||
///
|
||||
/// If there are enough slots available, switches the node to "connected" and returns `Ok`. If
|
||||
/// the slots are full, the node stays "not connected" and we return `Err`.
|
||||
///
|
||||
/// Note that priority nodes don't count towards the number of slots.
|
||||
pub fn try_outgoing(self) -> Result<ConnectedPeer<'a>, NotConnectedPeer<'a>> {
|
||||
if self.state.try_outgoing(&self.peer_id) {
|
||||
Ok(ConnectedPeer {
|
||||
state: self.state,
|
||||
peer_id: self.peer_id,
|
||||
})
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to accept the peer as an incoming connection.
|
||||
///
|
||||
/// If there are enough slots available, switches the node to "connected" and returns `Ok`. If
|
||||
/// the slots are full, the node stays "not connected" and we return `Err`.
|
||||
///
|
||||
/// Note that priority nodes don't count towards the number of slots.
|
||||
pub fn try_accept_incoming(self) -> Result<ConnectedPeer<'a>, NotConnectedPeer<'a>> {
|
||||
if self.state.try_accept_incoming(&self.peer_id) {
|
||||
Ok(ConnectedPeer {
|
||||
state: self.state,
|
||||
peer_id: self.peer_id,
|
||||
})
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the reputation value of the node.
|
||||
pub fn reputation(&self) -> i32 {
|
||||
self.state.reputation(&self.peer_id)
|
||||
}
|
||||
|
||||
/// Sets the reputation of the peer.
|
||||
pub fn set_reputation(&mut self, value: i32) {
|
||||
self.state.set_reputation(&self.peer_id, value)
|
||||
}
|
||||
|
||||
/// Performs an arithmetic addition on the reputation score of that peer.
|
||||
///
|
||||
/// In case of overflow, the value will be capped.
|
||||
/// If the peer is unknown to us, we insert it and consider that it has a reputation of 0.
|
||||
pub fn add_reputation(&mut self, modifier: i32) {
|
||||
self.state.add_reputation(&self.peer_id, modifier)
|
||||
}
|
||||
}
|
||||
|
||||
/// A peer that we have never heard of.
|
||||
pub struct UnknownPeer<'a> {
|
||||
parent: &'a mut PeersState,
|
||||
peer_id: Cow<'a, PeerId>,
|
||||
}
|
||||
|
||||
impl<'a> UnknownPeer<'a> {
|
||||
/// Inserts the peer identity in our list.
|
||||
///
|
||||
/// The node starts with a reputation of 0. You can adjust these default
|
||||
/// values using the `NotConnectedPeer` that this method returns.
|
||||
pub fn discover(self) -> NotConnectedPeer<'a> {
|
||||
self.parent.nodes.insert(self.peer_id.clone().into_owned(), Node {
|
||||
connection_state: ConnectionState::NotConnected,
|
||||
reputation: 0,
|
||||
});
|
||||
|
||||
let state = self.parent;
|
||||
NotConnectedPeer {
|
||||
state,
|
||||
peer_id: self.peer_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{PeersState, Peer};
|
||||
use libp2p::PeerId;
|
||||
|
||||
#[test]
|
||||
fn full_slots_in() {
|
||||
let mut peers_state = PeersState::new(1, 1, false);
|
||||
let id1 = PeerId::random();
|
||||
let id2 = PeerId::random();
|
||||
|
||||
if let Peer::Unknown(e) = peers_state.peer(&id1) {
|
||||
assert!(e.discover().try_accept_incoming().is_ok());
|
||||
}
|
||||
|
||||
if let Peer::Unknown(e) = peers_state.peer(&id2) {
|
||||
assert!(e.discover().try_accept_incoming().is_err());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn priority_node_doesnt_use_slot() {
|
||||
let mut peers_state = PeersState::new(1, 1, false);
|
||||
let id1 = PeerId::random();
|
||||
let id2 = PeerId::random();
|
||||
|
||||
peers_state.set_priority_group("test", vec![id1.clone()].into_iter().collect());
|
||||
if let Peer::NotConnected(p) = peers_state.peer(&id1) {
|
||||
assert!(p.try_accept_incoming().is_ok());
|
||||
} else { panic!() }
|
||||
|
||||
if let Peer::Unknown(e) = peers_state.peer(&id2) {
|
||||
assert!(e.discover().try_accept_incoming().is_ok());
|
||||
} else { panic!() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disconnecting_frees_slot() {
|
||||
let mut peers_state = PeersState::new(1, 1, false);
|
||||
let id1 = PeerId::random();
|
||||
let id2 = PeerId::random();
|
||||
|
||||
assert!(peers_state.peer(&id1).into_unknown().unwrap().discover().try_accept_incoming().is_ok());
|
||||
assert!(peers_state.peer(&id2).into_unknown().unwrap().discover().try_accept_incoming().is_err());
|
||||
peers_state.peer(&id1).into_connected().unwrap().disconnect();
|
||||
assert!(peers_state.peer(&id2).into_not_connected().unwrap().try_accept_incoming().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn priority_not_connected_peer() {
|
||||
let mut peers_state = PeersState::new(25, 25, false);
|
||||
let id1 = PeerId::random();
|
||||
let id2 = PeerId::random();
|
||||
|
||||
assert!(peers_state.priority_not_connected_peer().is_none());
|
||||
peers_state.peer(&id1).into_unknown().unwrap().discover();
|
||||
peers_state.peer(&id2).into_unknown().unwrap().discover();
|
||||
|
||||
assert!(peers_state.priority_not_connected_peer().is_none());
|
||||
peers_state.set_priority_group("test", vec![id1.clone()].into_iter().collect());
|
||||
assert!(peers_state.priority_not_connected_peer().is_some());
|
||||
peers_state.set_priority_group("test", vec![id2.clone(), id2.clone()].into_iter().collect());
|
||||
assert!(peers_state.priority_not_connected_peer().is_some());
|
||||
peers_state.set_priority_group("test", vec![].into_iter().collect());
|
||||
assert!(peers_state.priority_not_connected_peer().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn highest_not_connected_peer() {
|
||||
let mut peers_state = PeersState::new(25, 25, false);
|
||||
let id1 = PeerId::random();
|
||||
let id2 = PeerId::random();
|
||||
|
||||
assert!(peers_state.highest_not_connected_peer().is_none());
|
||||
peers_state.peer(&id1).into_unknown().unwrap().discover().set_reputation(50);
|
||||
peers_state.peer(&id2).into_unknown().unwrap().discover().set_reputation(25);
|
||||
assert_eq!(peers_state.highest_not_connected_peer().map(|p| p.into_peer_id()), Some(id1.clone()));
|
||||
peers_state.peer(&id2).into_not_connected().unwrap().set_reputation(75);
|
||||
assert_eq!(peers_state.highest_not_connected_peer().map(|p| p.into_peer_id()), Some(id2.clone()));
|
||||
peers_state.peer(&id2).into_not_connected().unwrap().try_accept_incoming().unwrap();
|
||||
assert_eq!(peers_state.highest_not_connected_peer().map(|p| p.into_peer_id()), Some(id1.clone()));
|
||||
peers_state.peer(&id1).into_not_connected().unwrap().set_reputation(100);
|
||||
peers_state.peer(&id2).into_connected().unwrap().disconnect();
|
||||
assert_eq!(peers_state.highest_not_connected_peer().map(|p| p.into_peer_id()), Some(id1.clone()));
|
||||
peers_state.peer(&id1).into_not_connected().unwrap().set_reputation(-100);
|
||||
assert_eq!(peers_state.highest_not_connected_peer().map(|p| p.into_peer_id()), Some(id2.clone()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disconnect_priority_doesnt_panic() {
|
||||
let mut peers_state = PeersState::new(1, 1, false);
|
||||
let id = PeerId::random();
|
||||
peers_state.set_priority_group("test", vec![id.clone()].into_iter().collect());
|
||||
let peer = peers_state.peer(&id).into_not_connected().unwrap().try_outgoing().unwrap();
|
||||
peer.disconnect();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_priority_groups_slot_count() {
|
||||
let mut peers_state = PeersState::new(1, 1, false);
|
||||
let id = PeerId::random();
|
||||
|
||||
if let Peer::Unknown(p) = peers_state.peer(&id) {
|
||||
assert!(p.discover().try_accept_incoming().is_ok());
|
||||
} else { panic!() }
|
||||
|
||||
assert_eq!(peers_state.num_in, 1);
|
||||
peers_state.set_priority_group("test1", vec![id.clone()].into_iter().collect());
|
||||
assert_eq!(peers_state.num_in, 0);
|
||||
peers_state.set_priority_group("test2", vec![id.clone()].into_iter().collect());
|
||||
assert_eq!(peers_state.num_in, 0);
|
||||
peers_state.set_priority_group("test1", vec![].into_iter().collect());
|
||||
assert_eq!(peers_state.num_in, 0);
|
||||
peers_state.set_priority_group("test2", vec![].into_iter().collect());
|
||||
assert_eq!(peers_state.num_in, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn priority_only_mode_ignores_drops_unknown_nodes() {
|
||||
// test whether connection to/from given peer is allowed
|
||||
let test_connection = |peers_state: &mut PeersState, id| {
|
||||
if let Peer::Unknown(p) = peers_state.peer(id) {
|
||||
p.discover();
|
||||
}
|
||||
|
||||
let incoming = if let Peer::NotConnected(p) = peers_state.peer(id) {
|
||||
p.try_accept_incoming().is_ok()
|
||||
} else {
|
||||
panic!()
|
||||
};
|
||||
|
||||
if incoming {
|
||||
peers_state.peer(id).into_connected().map(|p| p.disconnect());
|
||||
}
|
||||
|
||||
let outgoing = if let Peer::NotConnected(p) = peers_state.peer(id) {
|
||||
p.try_outgoing().is_ok()
|
||||
} else {
|
||||
panic!()
|
||||
};
|
||||
|
||||
if outgoing {
|
||||
peers_state.peer(id).into_connected().map(|p| p.disconnect());
|
||||
}
|
||||
|
||||
incoming || outgoing
|
||||
};
|
||||
|
||||
let mut peers_state = PeersState::new(1, 1, true);
|
||||
let id = PeerId::random();
|
||||
|
||||
// this is an unknown peer and our peer state is set to only allow
|
||||
// priority peers so any connection attempt should be denied.
|
||||
assert!(!test_connection(&mut peers_state, &id));
|
||||
|
||||
// disabling priority only mode should allow the connection to go
|
||||
// through.
|
||||
peers_state.set_priority_only(false);
|
||||
assert!(test_connection(&mut peers_state, &id));
|
||||
|
||||
// re-enabling it we should again deny connections from the peer.
|
||||
peers_state.set_priority_only(true);
|
||||
assert!(!test_connection(&mut peers_state, &id));
|
||||
|
||||
// but if we add the peer to a priority group it should be accepted.
|
||||
peers_state.set_priority_group("TEST_GROUP", vec![id.clone()].into_iter().collect());
|
||||
assert!(test_connection(&mut peers_state, &id));
|
||||
|
||||
// and removing it will cause the connection to once again be denied.
|
||||
peers_state.remove_from_priority_group("TEST_GROUP", &id);
|
||||
assert!(!test_connection(&mut peers_state, &id));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright 2018-2019 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 futures::prelude::*;
|
||||
use libp2p::PeerId;
|
||||
use rand::distributions::{Distribution, Uniform, WeightedIndex};
|
||||
use rand::seq::IteratorRandom;
|
||||
use std::{collections::HashMap, collections::HashSet, iter, pin::Pin, task::Poll};
|
||||
use substrate_peerset::{IncomingIndex, Message, PeersetConfig, Peerset};
|
||||
|
||||
#[test]
|
||||
fn run() {
|
||||
for _ in 0..50 {
|
||||
test_once();
|
||||
}
|
||||
}
|
||||
|
||||
fn test_once() {
|
||||
// PRNG to use.
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
// Nodes that the peerset knows about.
|
||||
let mut known_nodes = HashSet::<PeerId>::new();
|
||||
// Nodes that we have reserved. Always a subset of `known_nodes`.
|
||||
let mut reserved_nodes = HashSet::<PeerId>::new();
|
||||
|
||||
let (mut peerset, peerset_handle) = Peerset::from_config(PeersetConfig {
|
||||
bootnodes: (0 .. Uniform::new_inclusive(0, 4).sample(&mut rng)).map(|_| {
|
||||
let id = PeerId::random();
|
||||
known_nodes.insert(id.clone());
|
||||
id
|
||||
}).collect(),
|
||||
reserved_nodes: (0 .. Uniform::new_inclusive(0, 2).sample(&mut rng)).map(|_| {
|
||||
let id = PeerId::random();
|
||||
known_nodes.insert(id.clone());
|
||||
reserved_nodes.insert(id.clone());
|
||||
id
|
||||
}).collect(),
|
||||
reserved_only: Uniform::new_inclusive(0, 10).sample(&mut rng) == 0,
|
||||
in_peers: Uniform::new_inclusive(0, 25).sample(&mut rng),
|
||||
out_peers: Uniform::new_inclusive(0, 25).sample(&mut rng),
|
||||
});
|
||||
|
||||
futures::executor::block_on(futures::future::poll_fn(move |cx| {
|
||||
// List of nodes the user of `peerset` assumes it's connected to. Always a subset of
|
||||
// `known_nodes`.
|
||||
let mut connected_nodes = HashSet::<PeerId>::new();
|
||||
// List of nodes the user of `peerset` called `incoming` with and that haven't been
|
||||
// accepted or rejected yet.
|
||||
let mut incoming_nodes = HashMap::<IncomingIndex, PeerId>::new();
|
||||
// Next id for incoming connections.
|
||||
let mut next_incoming_id = IncomingIndex(0);
|
||||
|
||||
// Perform a certain number of actions while checking that the state is consistent. If we
|
||||
// reach the end of the loop, the run has succeeded.
|
||||
for _ in 0 .. 2500 {
|
||||
// Each of these weights corresponds to an action that we may perform.
|
||||
let action_weights = [150, 90, 90, 30, 30, 1, 1, 4, 4];
|
||||
match WeightedIndex::new(&action_weights).unwrap().sample(&mut rng) {
|
||||
// If we generate 0, poll the peerset.
|
||||
0 => match Stream::poll_next(Pin::new(&mut peerset), cx) {
|
||||
Poll::Ready(Some(Message::Connect(id))) => {
|
||||
if let Some(id) = incoming_nodes.iter().find(|(_, v)| **v == id).map(|(&id, _)| id) {
|
||||
incoming_nodes.remove(&id);
|
||||
}
|
||||
assert!(connected_nodes.insert(id));
|
||||
}
|
||||
Poll::Ready(Some(Message::Drop(id))) => { connected_nodes.remove(&id); }
|
||||
Poll::Ready(Some(Message::Accept(n))) =>
|
||||
assert!(connected_nodes.insert(incoming_nodes.remove(&n).unwrap())),
|
||||
Poll::Ready(Some(Message::Reject(n))) =>
|
||||
assert!(!connected_nodes.contains(&incoming_nodes.remove(&n).unwrap())),
|
||||
Poll::Ready(None) => panic!(),
|
||||
Poll::Pending => {}
|
||||
}
|
||||
|
||||
// If we generate 1, discover a new node.
|
||||
1 => {
|
||||
let new_id = PeerId::random();
|
||||
known_nodes.insert(new_id.clone());
|
||||
peerset.discovered(iter::once(new_id));
|
||||
}
|
||||
|
||||
// If we generate 2, adjust a random reputation.
|
||||
2 => if let Some(id) = known_nodes.iter().choose(&mut rng) {
|
||||
let val = Uniform::new_inclusive(i32::min_value(), i32::max_value()).sample(&mut rng);
|
||||
peerset_handle.report_peer(id.clone(), val);
|
||||
}
|
||||
|
||||
// If we generate 3, disconnect from a random node.
|
||||
3 => if let Some(id) = connected_nodes.iter().choose(&mut rng).cloned() {
|
||||
connected_nodes.remove(&id);
|
||||
peerset.dropped(id);
|
||||
}
|
||||
|
||||
// If we generate 4, connect to a random node.
|
||||
4 => if let Some(id) = known_nodes.iter()
|
||||
.filter(|n| incoming_nodes.values().all(|m| m != *n) && !connected_nodes.contains(n))
|
||||
.choose(&mut rng) {
|
||||
peerset.incoming(id.clone(), next_incoming_id.clone());
|
||||
incoming_nodes.insert(next_incoming_id.clone(), id.clone());
|
||||
next_incoming_id.0 += 1;
|
||||
}
|
||||
|
||||
// 5 and 6 are the reserved-only mode.
|
||||
5 => peerset_handle.set_reserved_only(true),
|
||||
6 => peerset_handle.set_reserved_only(false),
|
||||
|
||||
// 7 and 8 are about switching a random node in or out of reserved mode.
|
||||
7 => if let Some(id) = known_nodes.iter().filter(|n| !reserved_nodes.contains(n)).choose(&mut rng) {
|
||||
peerset_handle.add_reserved_peer(id.clone());
|
||||
reserved_nodes.insert(id.clone());
|
||||
}
|
||||
8 => if let Some(id) = reserved_nodes.iter().choose(&mut rng).cloned() {
|
||||
reserved_nodes.remove(&id);
|
||||
peerset_handle.remove_reserved_peer(id);
|
||||
}
|
||||
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
Poll::Ready(())
|
||||
}));
|
||||
}
|
||||
@@ -5,7 +5,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
api = { package = "substrate-rpc-api", path = "./api" }
|
||||
api = { package = "sc-rpc-api", path = "./api" }
|
||||
client-api = { package = "substrate-client-api", path = "../api" }
|
||||
client = { package = "substrate-client", path = "../" }
|
||||
sr-api = { path = "../../primitives/sr-api" }
|
||||
@@ -23,7 +23,8 @@ rpc-primitives = { package = "substrate-rpc-primitives", path = "../../primitive
|
||||
state_machine = { package = "substrate-state-machine", path = "../../primitives/state-machine" }
|
||||
substrate-executor = { path = "../executor" }
|
||||
substrate-keystore = { path = "../keystore" }
|
||||
transaction_pool = { package = "substrate-transaction-pool", path = "../transaction-pool" }
|
||||
transaction_pool = { package = "sc-transaction-pool", path = "../../client/transaction-pool" }
|
||||
sp-blockchain = { path = "../../primitives/blockchain" }
|
||||
hash-db = { version = "0.15.2", default-features = false }
|
||||
parking_lot = { version = "0.9.0" }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "substrate-rpc-api"
|
||||
name = "sc-rpc-api"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
@@ -18,5 +18,5 @@ primitives = { package = "substrate-primitives", path = "../../../primitives/cor
|
||||
runtime_version = { package = "sr-version", path = "../../../primitives/sr-version" }
|
||||
serde = { version = "1.0.101", features = ["derive"] }
|
||||
serde_json = "1.0.41"
|
||||
txpool = { package = "substrate-transaction-graph", path = "../../transaction-pool/graph" }
|
||||
txpool = { package = "sc-transaction-graph", path = "../../../client/transaction-pool/graph" }
|
||||
rpc-primitives = { package = "substrate-rpc-primitives", path = "../../../primitives/rpc" }
|
||||
|
||||
@@ -24,7 +24,7 @@ use futures::future::{FutureExt, TryFutureExt};
|
||||
use log::warn;
|
||||
|
||||
use client::Client;
|
||||
use client_api::error::Error as ClientError;
|
||||
use sp_blockchain::Error as ClientError;
|
||||
|
||||
use rpc::futures::{
|
||||
Sink, Future,
|
||||
|
||||
@@ -288,6 +288,6 @@ fn subscribe_headers<B, E, Block, RA, F, G, S, ERR>(
|
||||
});
|
||||
}
|
||||
|
||||
fn client_err(err: client::error::Error) -> Error {
|
||||
fn client_err(err: sp_blockchain::Error) -> Error {
|
||||
Error::Client(Box::new(err))
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ pub fn new_full<B, E, Block: BlockT, RA>(
|
||||
RA: Send + Sync + 'static,
|
||||
Client<B, E, Block, RA>: ProvideRuntimeApi,
|
||||
<Client<B, E, Block, RA> as ProvideRuntimeApi>::Api:
|
||||
Metadata<Block, Error = client::error::Error>,
|
||||
Metadata<Block, Error = sp_blockchain::Error>,
|
||||
{
|
||||
State {
|
||||
backend: Box::new(self::state_full::FullState::new(client, subscriptions)),
|
||||
@@ -332,6 +332,6 @@ impl<B, E, Block, RA> StateApi<Block::Hash> for State<B, E, Block, RA>
|
||||
}
|
||||
}
|
||||
|
||||
fn client_err(err: client::error::Error) -> Error {
|
||||
fn client_err(err: sp_blockchain::Error) -> Error {
|
||||
Error::Client(Box::new(err))
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ use rpc::{
|
||||
};
|
||||
|
||||
use api::Subscriptions;
|
||||
use client_api::{backend::Backend, error::Result as ClientResult};
|
||||
use client_api::backend::Backend;
|
||||
use sp_blockchain::Result as ClientResult;
|
||||
use client::{
|
||||
Client, CallExecutor, BlockchainEvents,
|
||||
};
|
||||
@@ -232,7 +233,7 @@ impl<B, E, Block, RA> StateBackend<B, E, Block, RA> for FullState<B, E, Block, R
|
||||
RA: Send + Sync + 'static,
|
||||
Client<B, E, Block, RA>: ProvideRuntimeApi,
|
||||
<Client<B, E, Block, RA> as ProvideRuntimeApi>::Api:
|
||||
Metadata<Block, Error = client::error::Error>,
|
||||
Metadata<Block, Error = sp_blockchain::Error>,
|
||||
{
|
||||
fn call(
|
||||
&self,
|
||||
|
||||
@@ -40,9 +40,9 @@ use rpc::{
|
||||
|
||||
use api::Subscriptions;
|
||||
use client_api::backend::Backend;
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use client::{
|
||||
BlockchainEvents, Client, CallExecutor,
|
||||
error::Error as ClientError,
|
||||
BlockchainEvents, Client, CallExecutor,
|
||||
light::{
|
||||
blockchain::{future_header, RemoteBlockchain},
|
||||
fetcher::{Fetcher, RemoteCallRequest, RemoteReadRequest, RemoteReadChildRequest},
|
||||
|
||||
@@ -31,6 +31,7 @@ target_info = "0.1.0"
|
||||
keystore = { package = "substrate-keystore", path = "../keystore" }
|
||||
sr-io = { path = "../../primitives/sr-io" }
|
||||
sr-primitives = { path = "../../primitives/sr-primitives" }
|
||||
sp-blockchain = { path = "../../primitives/blockchain" }
|
||||
primitives = { package = "substrate-primitives", path = "../../primitives/core" }
|
||||
session = { package = "substrate-session", path = "../../primitives/session" }
|
||||
app-crypto = { package = "substrate-application-crypto", path = "../../primitives/application-crypto" }
|
||||
@@ -44,7 +45,7 @@ tx-pool-api = { package = "substrate-transaction-pool-runtime-api", path = "../.
|
||||
client_db = { package = "substrate-client-db", path = "../db" }
|
||||
codec = { package = "parity-scale-codec", version = "1.0.0" }
|
||||
substrate-executor = { path = "../executor" }
|
||||
transaction_pool = { package = "substrate-transaction-pool", path = "../transaction-pool" }
|
||||
transaction_pool = { package = "sc-transaction-pool", path = "../../client/transaction-pool" }
|
||||
rpc-servers = { package = "substrate-rpc-servers", path = "../rpc-servers" }
|
||||
rpc = { package = "substrate-rpc", path = "../rpc" }
|
||||
tel = { package = "substrate-telemetry", path = "../telemetry" }
|
||||
@@ -56,9 +57,6 @@ tracing = "0.1.10"
|
||||
|
||||
[dev-dependencies]
|
||||
substrate-test-runtime-client = { path = "../../test/utils/runtime/client" }
|
||||
node-executor = { path = "../../bin/node/executor" }
|
||||
node-primitives = { path = "../../bin/node/primitives" }
|
||||
node-runtime = { path = "../../bin/node/runtime" }
|
||||
babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../primitives/consensus/babe" }
|
||||
grandpa = { package = "substrate-finality-grandpa", path = "../finality-grandpa" }
|
||||
grandpa-primitives = { package = "substrate-finality-grandpa-primitives", path = "../../primitives/finality-grandpa" }
|
||||
|
||||
@@ -54,6 +54,7 @@ use std::{
|
||||
use sysinfo::{get_current_pid, ProcessExt, System, SystemExt};
|
||||
use tel::{telemetry, SUBSTRATE_INFO};
|
||||
use transaction_pool::txpool::{self, ChainApi, Pool as TransactionPool};
|
||||
use sp_blockchain;
|
||||
use grafana_data_source::{self, record_metrics};
|
||||
|
||||
/// Aggregator for the components required to build a service.
|
||||
@@ -765,7 +766,7 @@ ServiceBuilder<
|
||||
offchain::OffchainWorkerApi<TBl> +
|
||||
tx_pool_api::TaggedTransactionQueue<TBl> +
|
||||
session::SessionKeys<TBl> +
|
||||
sr_api::ApiExt<TBl, Error = client::error::Error>,
|
||||
sr_api::ApiExt<TBl, Error = sp_blockchain::Error>,
|
||||
TBl: BlockT<Hash = <Blake2Hasher as Hasher>::Out>,
|
||||
TRtApi: 'static + Send + Sync,
|
||||
TCfg: Default,
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
//! Errors that can occur during the service operation.
|
||||
|
||||
use client;
|
||||
use network;
|
||||
use keystore;
|
||||
use consensus_common;
|
||||
use sp_blockchain;
|
||||
|
||||
/// Service Result typedef.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
@@ -28,7 +28,7 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||
#[derive(Debug, derive_more::Display, derive_more::From)]
|
||||
pub enum Error {
|
||||
/// Client error.
|
||||
Client(client::error::Error),
|
||||
Client(sp_blockchain::Error),
|
||||
/// IO error.
|
||||
Io(std::io::Error),
|
||||
/// Consensus error.
|
||||
|
||||
@@ -31,9 +31,7 @@ use primitives::{
|
||||
traits::CodeExecutor,
|
||||
};
|
||||
use sr_api::{ProofRecorder, InitializeBlock};
|
||||
use client_api::{
|
||||
error, backend, call_executor::CallExecutor,
|
||||
};
|
||||
use client_api::{backend, call_executor::CallExecutor};
|
||||
|
||||
/// Call executor that executes methods locally, querying all required
|
||||
/// data from local backend.
|
||||
@@ -79,7 +77,7 @@ where
|
||||
call_data: &[u8],
|
||||
strategy: ExecutionStrategy,
|
||||
extensions: Option<Extensions>,
|
||||
) -> error::Result<Vec<u8>> {
|
||||
) -> sp_blockchain::Result<Vec<u8>> {
|
||||
let mut changes = OverlayedChanges::default();
|
||||
let state = self.backend.state_at(*id)?;
|
||||
let return_data = StateMachine::new(
|
||||
@@ -105,7 +103,7 @@ where
|
||||
|
||||
fn contextual_call<
|
||||
'a,
|
||||
IB: Fn() -> error::Result<()>,
|
||||
IB: Fn() -> sp_blockchain::Result<()>,
|
||||
EM: Fn(
|
||||
Result<NativeOrEncoded<R>, Self::Error>,
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
@@ -124,7 +122,7 @@ where
|
||||
native_call: Option<NC>,
|
||||
recorder: &Option<ProofRecorder<Block>>,
|
||||
extensions: Option<Extensions>,
|
||||
) -> Result<NativeOrEncoded<R>, error::Error> where ExecutionManager<EM>: Clone {
|
||||
) -> Result<NativeOrEncoded<R>, sp_blockchain::Error> where ExecutionManager<EM>: Clone {
|
||||
match initialize_block {
|
||||
InitializeBlock::Do(ref init_block)
|
||||
if init_block.borrow().as_ref().map(|id| id != at).unwrap_or(true) => {
|
||||
@@ -189,7 +187,7 @@ where
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn runtime_version(&self, id: &BlockId<Block>) -> error::Result<RuntimeVersion> {
|
||||
fn runtime_version(&self, id: &BlockId<Block>) -> sp_blockchain::Result<RuntimeVersion> {
|
||||
let mut overlay = OverlayedChanges::default();
|
||||
let state = self.backend.state_at(*id)?;
|
||||
|
||||
@@ -204,7 +202,7 @@ where
|
||||
let _lock = self.backend.get_import_lock().read();
|
||||
self.backend.destroy_state(state)?;
|
||||
}
|
||||
version.ok_or(error::Error::VersionInvalid.into())
|
||||
version.ok_or(sp_blockchain::Error::VersionInvalid.into())
|
||||
}
|
||||
|
||||
fn call_at_state<
|
||||
@@ -223,7 +221,7 @@ where
|
||||
manager: ExecutionManager<F>,
|
||||
native_call: Option<NC>,
|
||||
extensions: Option<Extensions>,
|
||||
) -> error::Result<(
|
||||
) -> sp_blockchain::Result<(
|
||||
NativeOrEncoded<R>,
|
||||
(S::Transaction, <Blake2Hasher as Hasher>::Out),
|
||||
Option<ChangesTrieTransaction<Blake2Hasher, NumberFor<Block>>>,
|
||||
@@ -255,7 +253,7 @@ where
|
||||
overlay: &mut OverlayedChanges,
|
||||
method: &str,
|
||||
call_data: &[u8]
|
||||
) -> Result<(Vec<u8>, StorageProof), error::Error> {
|
||||
) -> Result<(Vec<u8>, StorageProof), sp_blockchain::Error> {
|
||||
state_machine::prove_execution_on_trie_backend(
|
||||
trie_state,
|
||||
overlay,
|
||||
|
||||
@@ -33,7 +33,7 @@ use state_machine::backend::InMemory as InMemoryState;
|
||||
use state_machine::{MemoryDB, TrieBackend, Backend as StateBackend, StorageProof,
|
||||
prove_read_on_trie_backend, read_proof_check, read_proof_check_on_proving_backend};
|
||||
|
||||
use client_api::error::{Error as ClientError, Result as ClientResult};
|
||||
use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
||||
|
||||
/// The size of each CHT. This value is passed to every CHT-related function from
|
||||
/// production code. Other values are passed from tests.
|
||||
|
||||
@@ -52,7 +52,12 @@ use consensus::{
|
||||
ImportResult, BlockOrigin, ForkChoiceStrategy,
|
||||
SelectChain, self,
|
||||
};
|
||||
use header_metadata::{HeaderMetadata, CachedHeaderMetadata};
|
||||
use sp_blockchain::{self as blockchain,
|
||||
Backend as ChainBackend,
|
||||
HeaderBackend as ChainHeaderBackend, ProvideCache, Cache,
|
||||
well_known_cache_keys::Id as CacheKeyId,
|
||||
HeaderMetadata, CachedHeaderMetadata,
|
||||
};
|
||||
|
||||
use sr_api::{CallRuntimeAt, ConstructRuntimeApi, Core as CoreApi, ProofRecorder, InitializeBlock};
|
||||
use block_builder::BlockBuilderApi;
|
||||
@@ -62,11 +67,6 @@ pub use client_api::{
|
||||
self, BlockImportOperation, PrunableStateChangesTrieStorage,
|
||||
ClientImportOperation, Finalizer, ImportSummary, NewBlockState,
|
||||
},
|
||||
blockchain::{
|
||||
self, Backend as ChainBackend,
|
||||
HeaderBackend as ChainHeaderBackend, ProvideCache, Cache,
|
||||
well_known_cache_keys::Id as CacheKeyId,
|
||||
},
|
||||
client::{
|
||||
ImportNotifications, FinalityNotification, FinalityNotifications, BlockImportNotification,
|
||||
ClientInfo, BlockchainEvents, BlockBody, ProvideUncles, ForkBlocks,
|
||||
@@ -74,10 +74,9 @@ pub use client_api::{
|
||||
},
|
||||
execution_extensions::{ExecutionExtensions, ExecutionStrategies},
|
||||
notifications::{StorageNotifications, StorageEventStream},
|
||||
error::Error,
|
||||
error,
|
||||
CallExecutor,
|
||||
};
|
||||
use sp_blockchain::Error;
|
||||
|
||||
use crate::{
|
||||
call_executor::LocalCallExecutor,
|
||||
@@ -146,7 +145,7 @@ pub fn new_in_mem<E, Block, S, RA>(
|
||||
executor: E,
|
||||
genesis_storage: S,
|
||||
keystore: Option<primitives::traits::BareCryptoStorePtr>,
|
||||
) -> error::Result<Client<
|
||||
) -> sp_blockchain::Result<Client<
|
||||
in_mem::Backend<Block, Blake2Hasher>,
|
||||
LocalCallExecutor<in_mem::Backend<Block, Blake2Hasher>, E>,
|
||||
Block,
|
||||
@@ -166,7 +165,7 @@ pub fn new_with_backend<B, E, Block, S, RA>(
|
||||
executor: E,
|
||||
build_genesis_storage: S,
|
||||
keystore: Option<primitives::traits::BareCryptoStorePtr>,
|
||||
) -> error::Result<Client<B, LocalCallExecutor<B, E>, Block, RA>>
|
||||
) -> sp_blockchain::Result<Client<B, LocalCallExecutor<B, E>, Block, RA>>
|
||||
where
|
||||
E: CodeExecutor + RuntimeInfo,
|
||||
S: BuildStorage,
|
||||
@@ -198,7 +197,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
build_genesis_storage: S,
|
||||
fork_blocks: ForkBlocks<Block>,
|
||||
execution_extensions: ExecutionExtensions<Block>,
|
||||
) -> error::Result<Self> {
|
||||
) -> sp_blockchain::Result<Self> {
|
||||
if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() {
|
||||
let (genesis_storage, children_genesis_storage) = build_genesis_storage.build_storage()?;
|
||||
let mut op = backend.begin_operation()?;
|
||||
@@ -237,29 +236,29 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
}
|
||||
|
||||
/// Get a reference to the state at a given block.
|
||||
pub fn state_at(&self, block: &BlockId<Block>) -> error::Result<B::State> {
|
||||
pub fn state_at(&self, block: &BlockId<Block>) -> sp_blockchain::Result<B::State> {
|
||||
self.backend.state_at(*block)
|
||||
}
|
||||
|
||||
/// Given a `BlockId` and a key prefix, return the matching child storage keys in that block.
|
||||
pub fn storage_keys(&self, id: &BlockId<Block>, key_prefix: &StorageKey) -> error::Result<Vec<StorageKey>> {
|
||||
pub fn storage_keys(&self, id: &BlockId<Block>, key_prefix: &StorageKey) -> sp_blockchain::Result<Vec<StorageKey>> {
|
||||
let keys = self.state_at(id)?.keys(&key_prefix.0).into_iter().map(StorageKey).collect();
|
||||
Ok(keys)
|
||||
}
|
||||
|
||||
/// Given a `BlockId` and a key, return the value under the key in that block.
|
||||
pub fn storage(&self, id: &BlockId<Block>, key: &StorageKey) -> error::Result<Option<StorageData>> {
|
||||
pub fn storage(&self, id: &BlockId<Block>, key: &StorageKey) -> sp_blockchain::Result<Option<StorageData>> {
|
||||
Ok(self.state_at(id)?
|
||||
.storage(&key.0).map_err(|e| error::Error::from_state(Box::new(e)))?
|
||||
.storage(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
||||
.map(StorageData)
|
||||
)
|
||||
}
|
||||
|
||||
/// Given a `BlockId` and a key, return the value under the hash in that block.
|
||||
pub fn storage_hash(&self, id: &BlockId<Block>, key: &StorageKey)
|
||||
-> error::Result<Option<Block::Hash>> {
|
||||
-> sp_blockchain::Result<Option<Block::Hash>> {
|
||||
Ok(self.state_at(id)?
|
||||
.storage_hash(&key.0).map_err(|e| error::Error::from_state(Box::new(e)))?
|
||||
.storage_hash(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
||||
)
|
||||
}
|
||||
|
||||
@@ -269,7 +268,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
id: &BlockId<Block>,
|
||||
child_storage_key: &StorageKey,
|
||||
key_prefix: &StorageKey
|
||||
) -> error::Result<Vec<StorageKey>> {
|
||||
) -> sp_blockchain::Result<Vec<StorageKey>> {
|
||||
let keys = self.state_at(id)?
|
||||
.child_keys(&child_storage_key.0, &key_prefix.0)
|
||||
.into_iter()
|
||||
@@ -284,9 +283,9 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
id: &BlockId<Block>,
|
||||
child_storage_key: &StorageKey,
|
||||
key: &StorageKey
|
||||
) -> error::Result<Option<StorageData>> {
|
||||
) -> sp_blockchain::Result<Option<StorageData>> {
|
||||
Ok(self.state_at(id)?
|
||||
.child_storage(&child_storage_key.0, &key.0).map_err(|e| error::Error::from_state(Box::new(e)))?
|
||||
.child_storage(&child_storage_key.0, &key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
||||
.map(StorageData))
|
||||
}
|
||||
|
||||
@@ -296,21 +295,21 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
id: &BlockId<Block>,
|
||||
child_storage_key: &StorageKey,
|
||||
key: &StorageKey
|
||||
) -> error::Result<Option<Block::Hash>> {
|
||||
) -> sp_blockchain::Result<Option<Block::Hash>> {
|
||||
Ok(self.state_at(id)?
|
||||
.child_storage_hash(&child_storage_key.0, &key.0).map_err(|e| error::Error::from_state(Box::new(e)))?
|
||||
.child_storage_hash(&child_storage_key.0, &key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the code at a given block.
|
||||
pub fn code_at(&self, id: &BlockId<Block>) -> error::Result<Vec<u8>> {
|
||||
pub fn code_at(&self, id: &BlockId<Block>) -> sp_blockchain::Result<Vec<u8>> {
|
||||
Ok(self.storage(id, &StorageKey(well_known_keys::CODE.to_vec()))?
|
||||
.expect("None is returned if there's no value stored for the given key;\
|
||||
':code' key is always defined; qed").0)
|
||||
}
|
||||
|
||||
/// Get the RuntimeVersion at a given block.
|
||||
pub fn runtime_version_at(&self, id: &BlockId<Block>) -> error::Result<RuntimeVersion> {
|
||||
pub fn runtime_version_at(&self, id: &BlockId<Block>) -> sp_blockchain::Result<RuntimeVersion> {
|
||||
self.executor.runtime_version(id)
|
||||
}
|
||||
|
||||
@@ -320,7 +319,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
}
|
||||
|
||||
/// Reads storage value at a given block + key, returning read proof.
|
||||
pub fn read_proof<I>(&self, id: &BlockId<Block>, keys: I) -> error::Result<StorageProof> where
|
||||
pub fn read_proof<I>(&self, id: &BlockId<Block>, keys: I) -> sp_blockchain::Result<StorageProof> where
|
||||
I: IntoIterator,
|
||||
I::Item: AsRef<[u8]>,
|
||||
{
|
||||
@@ -336,7 +335,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
id: &BlockId<Block>,
|
||||
storage_key: &[u8],
|
||||
keys: I,
|
||||
) -> error::Result<StorageProof> where
|
||||
) -> sp_blockchain::Result<StorageProof> where
|
||||
I: IntoIterator,
|
||||
I::Item: AsRef<[u8]>,
|
||||
{
|
||||
@@ -353,21 +352,21 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
id: &BlockId<Block>,
|
||||
method: &str,
|
||||
call_data: &[u8]
|
||||
) -> error::Result<(Vec<u8>, StorageProof)> {
|
||||
) -> sp_blockchain::Result<(Vec<u8>, StorageProof)> {
|
||||
let state = self.state_at(id)?;
|
||||
let header = self.prepare_environment_block(id)?;
|
||||
prove_execution(state, header, &self.executor, method, call_data)
|
||||
}
|
||||
|
||||
/// Reads given header and generates CHT-based header proof.
|
||||
pub fn header_proof(&self, id: &BlockId<Block>) -> error::Result<(Block::Header, StorageProof)> {
|
||||
pub fn header_proof(&self, id: &BlockId<Block>) -> sp_blockchain::Result<(Block::Header, StorageProof)> {
|
||||
self.header_proof_with_cht_size(id, cht::size())
|
||||
}
|
||||
|
||||
/// Get block hash by number.
|
||||
pub fn block_hash(&self,
|
||||
block_number: <<Block as BlockT>::Header as HeaderT>::Number
|
||||
) -> error::Result<Option<Block::Hash>> {
|
||||
) -> sp_blockchain::Result<Option<Block::Hash>> {
|
||||
self.backend.blockchain().hash(block_number)
|
||||
}
|
||||
|
||||
@@ -376,8 +375,8 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
cht_size: NumberFor<Block>,
|
||||
) -> error::Result<(Block::Header, StorageProof)> {
|
||||
let proof_error = || error::Error::Backend(format!("Failed to generate header proof for {:?}", id));
|
||||
) -> sp_blockchain::Result<(Block::Header, StorageProof)> {
|
||||
let proof_error = || sp_blockchain::Error::Backend(format!("Failed to generate header proof for {:?}", id));
|
||||
let header = self.backend.blockchain().expect_header(*id)?;
|
||||
let block_num = *header.number();
|
||||
let cht_num = cht::block_to_cht_number(cht_size, block_num).ok_or_else(proof_error)?;
|
||||
@@ -401,14 +400,14 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
&self,
|
||||
first: NumberFor<Block>,
|
||||
last: BlockId<Block>,
|
||||
) -> error::Result<Option<(NumberFor<Block>, BlockId<Block>)>> {
|
||||
) -> sp_blockchain::Result<Option<(NumberFor<Block>, BlockId<Block>)>> {
|
||||
let (config, storage) = match self.require_changes_trie().ok() {
|
||||
Some((config, storage)) => (config, storage),
|
||||
None => return Ok(None),
|
||||
};
|
||||
let last_num = self.backend.blockchain().expect_block_number_from_id(&last)?;
|
||||
if first > last_num {
|
||||
return Err(error::Error::ChangesTrieAccessFailed("Invalid changes trie range".into()));
|
||||
return Err(sp_blockchain::Error::ChangesTrieAccessFailed("Invalid changes trie range".into()));
|
||||
}
|
||||
let finalized_number = self.backend.blockchain().info().finalized_number;
|
||||
let oldest = storage.oldest_changes_trie_block(&config, finalized_number);
|
||||
@@ -426,7 +425,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
last: BlockId<Block>,
|
||||
storage_key: Option<&StorageKey>,
|
||||
key: &StorageKey
|
||||
) -> error::Result<Vec<(NumberFor<Block>, u32)>> {
|
||||
) -> sp_blockchain::Result<Vec<(NumberFor<Block>, u32)>> {
|
||||
let (config, storage) = self.require_changes_trie()?;
|
||||
let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?;
|
||||
let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?;
|
||||
@@ -450,7 +449,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
storage_key.as_ref().map(|sk| sk.0.as_slice()),
|
||||
&key.0)
|
||||
.and_then(|r| r.map(|r| r.map(|(block, tx)| (block, tx))).collect::<Result<_, _>>())
|
||||
.map_err(|err| error::Error::ChangesTrieAccessFailed(err))
|
||||
.map_err(|err| sp_blockchain::Error::ChangesTrieAccessFailed(err))
|
||||
}
|
||||
|
||||
/// Get proof for computation of (block, extrinsic) pairs where key has been changed at given blocks range.
|
||||
@@ -467,7 +466,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
max: Block::Hash,
|
||||
storage_key: Option<&StorageKey>,
|
||||
key: &StorageKey,
|
||||
) -> error::Result<ChangesProof<Block::Header>> {
|
||||
) -> sp_blockchain::Result<ChangesProof<Block::Header>> {
|
||||
self.key_changes_proof_with_cht_size(
|
||||
first,
|
||||
last,
|
||||
@@ -489,7 +488,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
storage_key: Option<&StorageKey>,
|
||||
key: &StorageKey,
|
||||
cht_size: NumberFor<Block>,
|
||||
) -> error::Result<ChangesProof<Block::Header>> {
|
||||
) -> sp_blockchain::Result<ChangesProof<Block::Header>> {
|
||||
struct AccessedRootsRecorder<'a, Block: BlockT> {
|
||||
storage: &'a dyn ChangesTrieStorage<Blake2Hasher, NumberFor<Block>>,
|
||||
min: NumberFor<Block>,
|
||||
@@ -575,7 +574,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
storage_key.as_ref().map(|sk| sk.0.as_slice()),
|
||||
&key.0,
|
||||
)
|
||||
.map_err(|err| error::Error::from(error::Error::ChangesTrieAccessFailed(err)))?;
|
||||
.map_err(|err| sp_blockchain::Error::from(sp_blockchain::Error::ChangesTrieAccessFailed(err)))?;
|
||||
|
||||
// now gather proofs for all changes tries roots that were touched during key_changes_proof
|
||||
// execution AND are unknown (i.e. replaced with CHT) to the requester
|
||||
@@ -595,7 +594,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
&self,
|
||||
cht_size: NumberFor<Block>,
|
||||
blocks: I
|
||||
) -> error::Result<StorageProof> {
|
||||
) -> sp_blockchain::Result<StorageProof> {
|
||||
// most probably we have touched several changes tries that are parts of the single CHT
|
||||
// => GroupBy changes tries by CHT number and then gather proof for the whole group at once
|
||||
let mut proofs = Vec::new();
|
||||
@@ -615,7 +614,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
cht_size: NumberFor<Block>,
|
||||
cht_num: NumberFor<Block>,
|
||||
blocks: Vec<NumberFor<Block>>
|
||||
) -> error::Result<StorageProof> {
|
||||
) -> sp_blockchain::Result<StorageProof> {
|
||||
let cht_start = cht::start_number(cht_size, cht_num);
|
||||
let mut current_num = cht_start;
|
||||
let cht_range = ::std::iter::from_fn(|| {
|
||||
@@ -631,12 +630,12 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
}
|
||||
|
||||
/// Returns changes trie configuration and storage or an error if it is not supported.
|
||||
fn require_changes_trie(&self) -> error::Result<(ChangesTrieConfiguration, &B::ChangesTrieStorage)> {
|
||||
fn require_changes_trie(&self) -> sp_blockchain::Result<(ChangesTrieConfiguration, &B::ChangesTrieStorage)> {
|
||||
let config = self.changes_trie_config()?;
|
||||
let storage = self.backend.changes_trie_storage();
|
||||
match (config, storage) {
|
||||
(Some(config), Some(storage)) => Ok((config, storage)),
|
||||
_ => Err(error::Error::ChangesTriesNotSupported.into()),
|
||||
_ => Err(sp_blockchain::Error::ChangesTriesNotSupported.into()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,7 +643,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
pub fn new_block(
|
||||
&self,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
) -> error::Result<block_builder::BlockBuilder<Block, Self>> where
|
||||
) -> sp_blockchain::Result<block_builder::BlockBuilder<Block, Self>> where
|
||||
E: Clone + Send + Sync,
|
||||
RA: Send + Sync,
|
||||
Self: ProvideRuntimeApi,
|
||||
@@ -665,7 +664,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
&self,
|
||||
parent: &BlockId<Block>,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
) -> error::Result<block_builder::BlockBuilder<Block, Self>> where
|
||||
) -> sp_blockchain::Result<block_builder::BlockBuilder<Block, Self>> where
|
||||
E: Clone + Send + Sync,
|
||||
RA: Send + Sync,
|
||||
Self: ProvideRuntimeApi,
|
||||
@@ -689,7 +688,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
&self,
|
||||
parent: &BlockId<Block>,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
) -> error::Result<block_builder::BlockBuilder<Block, Self>> where
|
||||
) -> sp_blockchain::Result<block_builder::BlockBuilder<Block, Self>> where
|
||||
E: Clone + Send + Sync,
|
||||
RA: Send + Sync,
|
||||
Self: ProvideRuntimeApi,
|
||||
@@ -707,7 +706,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
/// Lock the import lock, and run operations inside.
|
||||
pub fn lock_import_and_run<R, Err, F>(&self, f: F) -> Result<R, Err> where
|
||||
F: FnOnce(&mut ClientImportOperation<Block, Blake2Hasher, B>) -> Result<R, Err>,
|
||||
Err: From<error::Error>,
|
||||
Err: From<sp_blockchain::Error>,
|
||||
{
|
||||
let inner = || {
|
||||
let _import_lock = self.backend.get_import_lock().write();
|
||||
@@ -744,7 +743,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
operation: &mut ClientImportOperation<Block, Blake2Hasher, B>,
|
||||
import_block: BlockImportParams<Block>,
|
||||
new_cache: HashMap<CacheKeyId, Vec<u8>>,
|
||||
) -> error::Result<ImportResult> where
|
||||
) -> sp_blockchain::Result<ImportResult> where
|
||||
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone,
|
||||
{
|
||||
let BlockImportParams {
|
||||
@@ -829,7 +828,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
aux: Vec<(Vec<u8>, Option<Vec<u8>>)>,
|
||||
fork_choice: ForkChoiceStrategy,
|
||||
enact_state: bool,
|
||||
) -> error::Result<ImportResult> where
|
||||
) -> sp_blockchain::Result<ImportResult> where
|
||||
E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone,
|
||||
{
|
||||
let parent_hash = import_headers.post().parent_hash().clone();
|
||||
@@ -843,7 +842,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
// the block is lower than our last finalized block so it must revert
|
||||
// finality, refusing import.
|
||||
if *import_headers.post().number() <= info.finalized_number {
|
||||
return Err(error::Error::NotInFinalizedChain);
|
||||
return Err(sp_blockchain::Error::NotInFinalizedChain);
|
||||
}
|
||||
|
||||
// this is a fairly arbitrary choice of where to draw the line on making notifications,
|
||||
@@ -902,7 +901,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
};
|
||||
|
||||
let retracted = if is_new_best {
|
||||
let route_from_best = header_metadata::tree_route(
|
||||
let route_from_best = sp_blockchain::tree_route(
|
||||
self.backend.blockchain(),
|
||||
info.best_hash,
|
||||
parent_hash,
|
||||
@@ -948,7 +947,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
origin: BlockOrigin,
|
||||
hash: Block::Hash,
|
||||
body: &[Block::Extrinsic],
|
||||
) -> error::Result<(
|
||||
) -> sp_blockchain::Result<(
|
||||
Option<StorageUpdate<B, Block>>,
|
||||
Option<Option<ChangesUpdate<Block>>>,
|
||||
Option<(
|
||||
@@ -1009,7 +1008,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
let (top, children) = overlay.into_committed();
|
||||
let children = children.map(|(sk, it)| (sk, it.collect())).collect();
|
||||
if import_headers.post().state_root() != &storage_update.1 {
|
||||
return Err(error::Error::InvalidStateRoot);
|
||||
return Err(sp_blockchain::Error::InvalidStateRoot);
|
||||
}
|
||||
|
||||
Ok((Some(storage_update.0), Some(changes_update), Some((top.collect(), children))))
|
||||
@@ -1025,7 +1024,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
justification: Option<Justification>,
|
||||
best_block: Block::Hash,
|
||||
notify: bool,
|
||||
) -> error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
// find tree route from last finalized to given block.
|
||||
let last_finalized = self.backend.blockchain().last_finalized()?;
|
||||
|
||||
@@ -1034,16 +1033,16 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let route_from_finalized = header_metadata::tree_route(self.backend.blockchain(), last_finalized, block)?;
|
||||
let route_from_finalized = sp_blockchain::tree_route(self.backend.blockchain(), last_finalized, block)?;
|
||||
|
||||
if let Some(retracted) = route_from_finalized.retracted().get(0) {
|
||||
warn!("Safety violation: attempted to revert finalized block {:?} which is not in the \
|
||||
same chain as last finalized {:?}", retracted, last_finalized);
|
||||
|
||||
return Err(error::Error::NotInFinalizedChain);
|
||||
return Err(sp_blockchain::Error::NotInFinalizedChain);
|
||||
}
|
||||
|
||||
let route_from_best = header_metadata::tree_route(self.backend.blockchain(), best_block, block)?;
|
||||
let route_from_best = sp_blockchain::tree_route(self.backend.blockchain(), best_block, block)?;
|
||||
|
||||
// if the block is not a direct ancestor of the current best chain,
|
||||
// then some other block is the common ancestor.
|
||||
@@ -1083,7 +1082,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
fn notify_finalized(
|
||||
&self,
|
||||
notify_finalized: Vec<Block::Hash>,
|
||||
) -> error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
let mut sinks = self.finality_notification_sinks.lock();
|
||||
|
||||
for finalized_hash in notify_finalized {
|
||||
@@ -1106,7 +1105,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn notify_imported(&self, notify_import: ImportSummary<Block>) -> error::Result<()> {
|
||||
fn notify_imported(&self, notify_import: ImportSummary<Block>) -> sp_blockchain::Result<()> {
|
||||
if let Some(storage_changes) = notify_import.storage_changes {
|
||||
// TODO [ToDr] How to handle re-orgs? Should we re-emit all storage changes?
|
||||
self.storage_notifications.lock()
|
||||
@@ -1133,7 +1132,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
|
||||
/// Attempts to revert the chain by `n` blocks. Returns the number of blocks that were
|
||||
/// successfully reverted.
|
||||
pub fn revert(&self, n: NumberFor<Block>) -> error::Result<NumberFor<Block>> {
|
||||
pub fn revert(&self, n: NumberFor<Block>) -> sp_blockchain::Result<NumberFor<Block>> {
|
||||
Ok(self.backend.revert(n)?)
|
||||
}
|
||||
|
||||
@@ -1147,7 +1146,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
}
|
||||
|
||||
/// Get block status.
|
||||
pub fn block_status(&self, id: &BlockId<Block>) -> error::Result<BlockStatus> {
|
||||
pub fn block_status(&self, id: &BlockId<Block>) -> sp_blockchain::Result<BlockStatus> {
|
||||
// this can probably be implemented more efficiently
|
||||
if let BlockId::Hash(ref h) = id {
|
||||
if self.importing_block.read().as_ref().map_or(false, |importing| h == importing) {
|
||||
@@ -1171,23 +1170,23 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
}
|
||||
|
||||
/// Get block header by id.
|
||||
pub fn header(&self, id: &BlockId<Block>) -> error::Result<Option<<Block as BlockT>::Header>> {
|
||||
pub fn header(&self, id: &BlockId<Block>) -> sp_blockchain::Result<Option<<Block as BlockT>::Header>> {
|
||||
self.backend.blockchain().header(*id)
|
||||
}
|
||||
|
||||
/// Get block body by id.
|
||||
pub fn body(&self, id: &BlockId<Block>) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
|
||||
pub fn body(&self, id: &BlockId<Block>) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
|
||||
self.backend.blockchain().body(*id)
|
||||
}
|
||||
|
||||
/// Get block justification set by id.
|
||||
pub fn justification(&self, id: &BlockId<Block>) -> error::Result<Option<Justification>> {
|
||||
pub fn justification(&self, id: &BlockId<Block>) -> sp_blockchain::Result<Option<Justification>> {
|
||||
self.backend.blockchain().justification(*id)
|
||||
}
|
||||
|
||||
/// Get full block by id.
|
||||
pub fn block(&self, id: &BlockId<Block>)
|
||||
-> error::Result<Option<SignedBlock<Block>>>
|
||||
-> sp_blockchain::Result<Option<SignedBlock<Block>>>
|
||||
{
|
||||
Ok(match (self.header(id)?, self.body(id)?, self.justification(id)?) {
|
||||
(Some(header), Some(extrinsics), justification) =>
|
||||
@@ -1197,8 +1196,8 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
}
|
||||
|
||||
/// Gets the uncles of the block with `target_hash` going back `max_generation` ancestors.
|
||||
pub fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor<Block>) -> error::Result<Vec<Block::Hash>> {
|
||||
let load_header = |id: Block::Hash| -> error::Result<Block::Header> {
|
||||
pub fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor<Block>) -> sp_blockchain::Result<Vec<Block::Hash>> {
|
||||
let load_header = |id: Block::Hash| -> sp_blockchain::Result<Block::Header> {
|
||||
match self.backend.blockchain().header(BlockId::Hash(id))? {
|
||||
Some(hdr) => Ok(hdr),
|
||||
None => Err(Error::UnknownBlock(format!("{:?}", id))),
|
||||
@@ -1230,12 +1229,12 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
fn changes_trie_config(&self) -> Result<Option<ChangesTrieConfiguration>, Error> {
|
||||
Ok(self.backend.state_at(BlockId::Number(self.backend.blockchain().info().best_number))?
|
||||
.storage(well_known_keys::CHANGES_TRIE_CONFIG)
|
||||
.map_err(|e| error::Error::from_state(Box::new(e)))?
|
||||
.map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
|
||||
.and_then(|c| Decode::decode(&mut &*c).ok()))
|
||||
}
|
||||
|
||||
/// Prepare in-memory header that is used in execution environment.
|
||||
fn prepare_environment_block(&self, parent: &BlockId<Block>) -> error::Result<Block::Header> {
|
||||
fn prepare_environment_block(&self, parent: &BlockId<Block>) -> sp_blockchain::Result<Block::Header> {
|
||||
let parent_header = self.backend.blockchain().expect_header(*parent)?;
|
||||
Ok(<<Block as BlockT>::Header as HeaderT>::new(
|
||||
self.backend.blockchain().expect_block_number_from_id(parent)? + One::one(),
|
||||
@@ -1252,7 +1251,7 @@ impl<B, E, Block, RA> HeaderMetadata<Block> for Client<B, E, Block, RA> where
|
||||
E: CallExecutor<Block, Blake2Hasher>,
|
||||
Block: BlockT<Hash=H256>,
|
||||
{
|
||||
type Error = error::Error;
|
||||
type Error = sp_blockchain::Error;
|
||||
|
||||
fn header_metadata(&self, hash: Block::Hash) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
|
||||
self.backend.blockchain().header_metadata(hash)
|
||||
@@ -1272,7 +1271,7 @@ impl<B, E, Block, RA> ProvideUncles<Block> for Client<B, E, Block, RA> where
|
||||
E: CallExecutor<Block, Blake2Hasher>,
|
||||
Block: BlockT<Hash=H256>,
|
||||
{
|
||||
fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor<Block>) -> error::Result<Vec<Block::Header>> {
|
||||
fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor<Block>) -> sp_blockchain::Result<Vec<Block::Header>> {
|
||||
Ok(Client::uncles(self, target_hash, max_generation)?
|
||||
.into_iter()
|
||||
.filter_map(|hash| Client::header(self, &BlockId::Hash(hash)).unwrap_or(None))
|
||||
@@ -1287,7 +1286,7 @@ impl<B, E, Block, RA> ChainHeaderBackend<Block> for Client<B, E, Block, RA> wher
|
||||
Block: BlockT<Hash=H256>,
|
||||
RA: Send + Sync,
|
||||
{
|
||||
fn header(&self, id: BlockId<Block>) -> error::Result<Option<Block::Header>> {
|
||||
fn header(&self, id: BlockId<Block>) -> sp_blockchain::Result<Option<Block::Header>> {
|
||||
self.backend.blockchain().header(id)
|
||||
}
|
||||
|
||||
@@ -1295,15 +1294,15 @@ impl<B, E, Block, RA> ChainHeaderBackend<Block> for Client<B, E, Block, RA> wher
|
||||
self.backend.blockchain().info()
|
||||
}
|
||||
|
||||
fn status(&self, id: BlockId<Block>) -> error::Result<blockchain::BlockStatus> {
|
||||
fn status(&self, id: BlockId<Block>) -> sp_blockchain::Result<blockchain::BlockStatus> {
|
||||
self.backend.blockchain().status(id)
|
||||
}
|
||||
|
||||
fn number(&self, hash: Block::Hash) -> error::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>> {
|
||||
fn number(&self, hash: Block::Hash) -> sp_blockchain::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>> {
|
||||
fn hash(&self, number: NumberFor<Block>) -> sp_blockchain::Result<Option<Block::Hash>> {
|
||||
self.backend.blockchain().hash(number)
|
||||
}
|
||||
}
|
||||
@@ -1316,11 +1315,11 @@ impl<B, E, Block, RA> sr_primitives::traits::BlockIdTo<Block> for Client<B, E, B
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
fn to_hash(&self, block_id: &BlockId<Block>) -> error::Result<Option<Block::Hash>> {
|
||||
fn to_hash(&self, block_id: &BlockId<Block>) -> sp_blockchain::Result<Option<Block::Hash>> {
|
||||
self.block_hash_from_id(block_id)
|
||||
}
|
||||
|
||||
fn to_number(&self, block_id: &BlockId<Block>) -> error::Result<Option<NumberFor<Block>>> {
|
||||
fn to_number(&self, block_id: &BlockId<Block>) -> sp_blockchain::Result<Option<NumberFor<Block>>> {
|
||||
self.block_number_from_id(block_id)
|
||||
}
|
||||
}
|
||||
@@ -1331,7 +1330,7 @@ impl<B, E, Block, RA> ChainHeaderBackend<Block> for &Client<B, E, Block, RA> whe
|
||||
Block: BlockT<Hash=H256>,
|
||||
RA: Send + Sync,
|
||||
{
|
||||
fn header(&self, id: BlockId<Block>) -> error::Result<Option<Block::Header>> {
|
||||
fn header(&self, id: BlockId<Block>) -> sp_blockchain::Result<Option<Block::Header>> {
|
||||
(**self).backend.blockchain().header(id)
|
||||
}
|
||||
|
||||
@@ -1339,15 +1338,15 @@ impl<B, E, Block, RA> ChainHeaderBackend<Block> for &Client<B, E, Block, RA> whe
|
||||
(**self).backend.blockchain().info()
|
||||
}
|
||||
|
||||
fn status(&self, id: BlockId<Block>) -> error::Result<blockchain::BlockStatus> {
|
||||
fn status(&self, id: BlockId<Block>) -> sp_blockchain::Result<blockchain::BlockStatus> {
|
||||
(**self).status(id)
|
||||
}
|
||||
|
||||
fn number(&self, hash: Block::Hash) -> error::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>> {
|
||||
fn number(&self, hash: Block::Hash) -> sp_blockchain::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>> {
|
||||
(**self).number(hash)
|
||||
}
|
||||
|
||||
fn hash(&self, number: NumberFor<Block>) -> error::Result<Option<Block::Hash>> {
|
||||
fn hash(&self, number: NumberFor<Block>) -> sp_blockchain::Result<Option<Block::Hash>> {
|
||||
(**self).hash(number)
|
||||
}
|
||||
}
|
||||
@@ -1397,7 +1396,7 @@ impl<B, E, Block, RA> CallRuntimeAt<Block> for Client<B, E, Block, RA> where
|
||||
native_call: Option<NC>,
|
||||
context: ExecutionContext,
|
||||
recorder: &Option<ProofRecorder<Block>>,
|
||||
) -> error::Result<NativeOrEncoded<R>> {
|
||||
) -> sp_blockchain::Result<NativeOrEncoded<R>> {
|
||||
let (manager, extensions) = self.execution_extensions.manager_and_extensions(at, context);
|
||||
self.executor.contextual_call::<_, fn(_,_) -> _,_,_>(
|
||||
|| core_api.initialize_block(at, &self.prepare_environment_block(at)?),
|
||||
@@ -1413,7 +1412,7 @@ impl<B, E, Block, RA> CallRuntimeAt<Block> for Client<B, E, Block, RA> where
|
||||
)
|
||||
}
|
||||
|
||||
fn runtime_version_at(&self, at: &BlockId<Block>) -> error::Result<RuntimeVersion> {
|
||||
fn runtime_version_at(&self, at: &BlockId<Block>) -> sp_blockchain::Result<RuntimeVersion> {
|
||||
self.runtime_version_at(at)
|
||||
}
|
||||
}
|
||||
@@ -1529,13 +1528,13 @@ impl<B, E, Block, RA> Finalizer<Block, Blake2Hasher, B> for Client<B, E, Block,
|
||||
id: BlockId<Block>,
|
||||
justification: Option<Justification>,
|
||||
notify: bool,
|
||||
) -> error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
let last_best = self.backend.blockchain().info().best_hash;
|
||||
let to_finalize_hash = self.backend.blockchain().expect_block_hash_from_id(&id)?;
|
||||
self.apply_finality_with_block_hash(operation, to_finalize_hash, justification, last_best, notify)
|
||||
}
|
||||
|
||||
fn finalize_block(&self, id: BlockId<Block>, justification: Option<Justification>, notify: bool) -> error::Result<()> {
|
||||
fn finalize_block(&self, id: BlockId<Block>, justification: Option<Justification>, notify: bool) -> sp_blockchain::Result<()> {
|
||||
self.lock_import_and_run(|operation| {
|
||||
self.apply_finality(operation, id, justification, notify)
|
||||
})
|
||||
@@ -1553,11 +1552,11 @@ impl<B, E, Block, RA> Finalizer<Block, Blake2Hasher, B> for &Client<B, E, Block,
|
||||
id: BlockId<Block>,
|
||||
justification: Option<Justification>,
|
||||
notify: bool,
|
||||
) -> error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
(**self).apply_finality(operation, id, justification, notify)
|
||||
}
|
||||
|
||||
fn finalize_block(&self, id: BlockId<Block>, justification: Option<Justification>, notify: bool) -> error::Result<()> {
|
||||
fn finalize_block(&self, id: BlockId<Block>, justification: Option<Justification>, notify: bool) -> sp_blockchain::Result<()> {
|
||||
(**self).finalize_block(id, justification, notify)
|
||||
}
|
||||
}
|
||||
@@ -1585,7 +1584,7 @@ where
|
||||
&self,
|
||||
filter_keys: Option<&[StorageKey]>,
|
||||
child_filter_keys: Option<&[(StorageKey, Option<Vec<StorageKey>>)]>,
|
||||
) -> error::Result<StorageEventStream<Block::Hash>> {
|
||||
) -> sp_blockchain::Result<StorageEventStream<Block::Hash>> {
|
||||
Ok(self.storage_notifications.lock().listen(filter_keys, child_filter_keys))
|
||||
}
|
||||
}
|
||||
@@ -1620,7 +1619,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn best_block_header(&self) -> error::Result<<Block as BlockT>::Header> {
|
||||
fn best_block_header(&self) -> sp_blockchain::Result<<Block as BlockT>::Header> {
|
||||
let info = self.backend.blockchain().info();
|
||||
let import_lock = self.backend.get_import_lock();
|
||||
let best_hash = self.backend.blockchain().best_containing(info.best_hash, None, import_lock)?
|
||||
@@ -1630,7 +1629,7 @@ where
|
||||
.expect("given block hash was fetched from block in db; qed"))
|
||||
}
|
||||
|
||||
fn leaves(&self) -> Result<Vec<<Block as BlockT>::Hash>, error::Error> {
|
||||
fn leaves(&self) -> Result<Vec<<Block as BlockT>::Hash>, sp_blockchain::Error> {
|
||||
self.backend.blockchain().leaves()
|
||||
}
|
||||
}
|
||||
@@ -1670,7 +1669,7 @@ impl<B, E, Block, RA> BlockBody<Block> for Client<B, E, Block, RA>
|
||||
E: CallExecutor<Block, Blake2Hasher>,
|
||||
Block: BlockT<Hash=H256>,
|
||||
{
|
||||
fn block_body(&self, id: &BlockId<Block>) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
|
||||
fn block_body(&self, id: &BlockId<Block>) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
|
||||
self.body(id)
|
||||
}
|
||||
}
|
||||
@@ -1688,7 +1687,7 @@ impl<B, E, Block, RA> backend::AuxStore for Client<B, E, Block, RA>
|
||||
'c: 'a,
|
||||
I: IntoIterator<Item=&'a(&'c [u8], &'c [u8])>,
|
||||
D: IntoIterator<Item=&'a &'b [u8]>,
|
||||
>(&self, insert: I, delete: D) -> error::Result<()> {
|
||||
>(&self, insert: I, delete: D) -> sp_blockchain::Result<()> {
|
||||
// Import is locked here because we may have other block import
|
||||
// operations that tries to set aux data. Note that for consensus
|
||||
// layer, one can always use atomic operations to make sure
|
||||
@@ -1698,7 +1697,7 @@ impl<B, E, Block, RA> backend::AuxStore for Client<B, E, Block, RA>
|
||||
})
|
||||
}
|
||||
/// Query auxiliary data from key-value store.
|
||||
fn get_aux(&self, key: &[u8]) -> error::Result<Option<Vec<u8>>> {
|
||||
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
|
||||
backend::AuxStore::get_aux(&*self.backend, key)
|
||||
}
|
||||
}
|
||||
@@ -1717,11 +1716,11 @@ impl<B, E, Block, RA> backend::AuxStore for &Client<B, E, Block, RA>
|
||||
'c: 'a,
|
||||
I: IntoIterator<Item=&'a(&'c [u8], &'c [u8])>,
|
||||
D: IntoIterator<Item=&'a &'b [u8]>,
|
||||
>(&self, insert: I, delete: D) -> error::Result<()> {
|
||||
>(&self, insert: I, delete: D) -> sp_blockchain::Result<()> {
|
||||
(**self).insert_aux(insert, delete)
|
||||
}
|
||||
|
||||
fn get_aux(&self, key: &[u8]) -> error::Result<Option<Vec<u8>>> {
|
||||
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
|
||||
(**self).get_aux(key)
|
||||
}
|
||||
}
|
||||
@@ -1731,7 +1730,7 @@ pub fn apply_aux<'a, 'b: 'a, 'c: 'a, B, Block, H, D, I>(
|
||||
operation: &mut ClientImportOperation<Block, H, B>,
|
||||
insert: I,
|
||||
delete: D
|
||||
) -> error::Result<()>
|
||||
) -> sp_blockchain::Result<()>
|
||||
where
|
||||
Block: BlockT,
|
||||
H: Hasher<Out=Block::Hash>,
|
||||
@@ -2702,7 +2701,7 @@ pub(crate) mod tests {
|
||||
|
||||
let import_err = client.import(BlockOrigin::Own, b3).err().unwrap();
|
||||
let expected_err = ConsensusError::ClientImport(
|
||||
error::Error::NotInFinalizedChain.to_string()
|
||||
sp_blockchain::Error::NotInFinalizedChain.to_string()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
@@ -2725,7 +2724,7 @@ pub(crate) mod tests {
|
||||
|
||||
let import_err = client.import(BlockOrigin::Own, c1).err().unwrap();
|
||||
let expected_err = ConsensusError::ClientImport(
|
||||
error::Error::NotInFinalizedChain.to_string()
|
||||
sp_blockchain::Error::NotInFinalizedChain.to_string()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
||||
@@ -30,10 +30,9 @@ use state_machine::backend::{Backend as StateBackend, InMemory};
|
||||
use state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId, ChangesTrieTransaction};
|
||||
use hash_db::{Hasher, Prefix};
|
||||
use trie::MemoryDB;
|
||||
use header_metadata::{CachedHeaderMetadata, HeaderMetadata};
|
||||
use sp_blockchain::{CachedHeaderMetadata, HeaderMetadata};
|
||||
|
||||
use client_api::{
|
||||
error,
|
||||
backend::{self, NewBlockState, StorageCollection, ChildStorageCollection},
|
||||
blockchain::{
|
||||
self, BlockStatus, HeaderBackend, well_known_cache_keys::Id as CacheKeyId
|
||||
@@ -158,7 +157,7 @@ impl<Block: BlockT> Blockchain<Block> {
|
||||
justification: Option<Justification>,
|
||||
body: Option<Vec<<Block as BlockT>::Extrinsic>>,
|
||||
new_state: NewBlockState,
|
||||
) -> client_api::error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
let number = header.number().clone();
|
||||
if new_state.is_best() {
|
||||
self.apply_head(&header)?;
|
||||
@@ -208,16 +207,16 @@ impl<Block: BlockT> Blockchain<Block> {
|
||||
}
|
||||
|
||||
/// Set an existing block as head.
|
||||
pub fn set_head(&self, id: BlockId<Block>) -> error::Result<()> {
|
||||
pub fn set_head(&self, id: BlockId<Block>) -> sp_blockchain::Result<()> {
|
||||
let header = match self.header(id)? {
|
||||
Some(h) => h,
|
||||
None => return Err(error::Error::UnknownBlock(format!("{}", id))),
|
||||
None => return Err(sp_blockchain::Error::UnknownBlock(format!("{}", id))),
|
||||
};
|
||||
|
||||
self.apply_head(&header)
|
||||
}
|
||||
|
||||
fn apply_head(&self, header: &<Block as BlockT>::Header) -> error::Result<()> {
|
||||
fn apply_head(&self, header: &<Block as BlockT>::Header) -> sp_blockchain::Result<()> {
|
||||
let hash = header.hash();
|
||||
let number = header.number();
|
||||
|
||||
@@ -228,7 +227,7 @@ impl<Block: BlockT> Blockchain<Block> {
|
||||
if &best_hash == header.parent_hash() {
|
||||
None
|
||||
} else {
|
||||
let route = header_metadata::tree_route(self, best_hash, *header.parent_hash())?;
|
||||
let route = sp_blockchain::tree_route(self, best_hash, *header.parent_hash())?;
|
||||
Some(route)
|
||||
}
|
||||
};
|
||||
@@ -255,10 +254,10 @@ impl<Block: BlockT> Blockchain<Block> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn finalize_header(&self, id: BlockId<Block>, justification: Option<Justification>) -> error::Result<()> {
|
||||
fn finalize_header(&self, id: BlockId<Block>, justification: Option<Justification>) -> sp_blockchain::Result<()> {
|
||||
let hash = match self.header(id)? {
|
||||
Some(h) => h.hash(),
|
||||
None => return Err(error::Error::UnknownBlock(format!("{}", id))),
|
||||
None => return Err(sp_blockchain::Error::UnknownBlock(format!("{}", id))),
|
||||
};
|
||||
|
||||
let mut storage = self.storage.write();
|
||||
@@ -290,7 +289,7 @@ impl<Block: BlockT> Blockchain<Block> {
|
||||
}
|
||||
|
||||
impl<Block: BlockT> HeaderBackend<Block> for Blockchain<Block> {
|
||||
fn header(&self, id: BlockId<Block>) -> error::Result<Option<<Block as BlockT>::Header>> {
|
||||
fn header(&self, id: BlockId<Block>) -> sp_blockchain::Result<Option<<Block as BlockT>::Header>> {
|
||||
Ok(self.id(id).and_then(|hash| {
|
||||
self.storage.read().blocks.get(&hash).map(|b| b.header().clone())
|
||||
}))
|
||||
@@ -307,28 +306,28 @@ impl<Block: BlockT> HeaderBackend<Block> for Blockchain<Block> {
|
||||
}
|
||||
}
|
||||
|
||||
fn status(&self, id: BlockId<Block>) -> error::Result<BlockStatus> {
|
||||
fn status(&self, id: BlockId<Block>) -> sp_blockchain::Result<BlockStatus> {
|
||||
match self.id(id).map_or(false, |hash| self.storage.read().blocks.contains_key(&hash)) {
|
||||
true => Ok(BlockStatus::InChain),
|
||||
false => Ok(BlockStatus::Unknown),
|
||||
}
|
||||
}
|
||||
|
||||
fn number(&self, hash: Block::Hash) -> error::Result<Option<NumberFor<Block>>> {
|
||||
fn number(&self, hash: Block::Hash) -> sp_blockchain::Result<Option<NumberFor<Block>>> {
|
||||
Ok(self.storage.read().blocks.get(&hash).map(|b| *b.header().number()))
|
||||
}
|
||||
|
||||
fn hash(&self, number: <<Block as BlockT>::Header as HeaderT>::Number) -> error::Result<Option<Block::Hash>> {
|
||||
fn hash(&self, number: <<Block as BlockT>::Header as HeaderT>::Number) -> sp_blockchain::Result<Option<Block::Hash>> {
|
||||
Ok(self.id(BlockId::Number(number)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT> HeaderMetadata<Block> for Blockchain<Block> {
|
||||
type Error = error::Error;
|
||||
type Error = sp_blockchain::Error;
|
||||
|
||||
fn header_metadata(&self, hash: Block::Hash) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
|
||||
self.header(BlockId::hash(hash))?.map(|header| CachedHeaderMetadata::from(&header))
|
||||
.ok_or(error::Error::UnknownBlock(format!("header not found: {}", hash)))
|
||||
.ok_or(sp_blockchain::Error::UnknownBlock(format!("header not found: {}", hash)))
|
||||
}
|
||||
|
||||
fn insert_header_metadata(&self, _hash: Block::Hash, _metadata: CachedHeaderMetadata<Block>) {
|
||||
@@ -340,20 +339,20 @@ impl<Block: BlockT> HeaderMetadata<Block> for Blockchain<Block> {
|
||||
}
|
||||
|
||||
impl<Block: BlockT> blockchain::Backend<Block> for Blockchain<Block> {
|
||||
fn body(&self, id: BlockId<Block>) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
|
||||
fn body(&self, id: BlockId<Block>) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
|
||||
Ok(self.id(id).and_then(|hash| {
|
||||
self.storage.read().blocks.get(&hash)
|
||||
.and_then(|b| b.extrinsics().map(|x| x.to_vec()))
|
||||
}))
|
||||
}
|
||||
|
||||
fn justification(&self, id: BlockId<Block>) -> error::Result<Option<Justification>> {
|
||||
fn justification(&self, id: BlockId<Block>) -> sp_blockchain::Result<Option<Justification>> {
|
||||
Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b|
|
||||
b.justification().map(|x| x.clone()))
|
||||
))
|
||||
}
|
||||
|
||||
fn last_finalized(&self) -> error::Result<Block::Hash> {
|
||||
fn last_finalized(&self) -> sp_blockchain::Result<Block::Hash> {
|
||||
Ok(self.storage.read().finalized_hash.clone())
|
||||
}
|
||||
|
||||
@@ -361,11 +360,11 @@ impl<Block: BlockT> blockchain::Backend<Block> for Blockchain<Block> {
|
||||
None
|
||||
}
|
||||
|
||||
fn leaves(&self) -> error::Result<Vec<Block::Hash>> {
|
||||
fn leaves(&self) -> sp_blockchain::Result<Vec<Block::Hash>> {
|
||||
Ok(self.storage.read().leaves.hashes())
|
||||
}
|
||||
|
||||
fn children(&self, _parent_hash: Block::Hash) -> error::Result<Vec<Block::Hash>> {
|
||||
fn children(&self, _parent_hash: Block::Hash) -> sp_blockchain::Result<Vec<Block::Hash>> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
@@ -383,7 +382,7 @@ impl<Block: BlockT> backend::AuxStore for Blockchain<Block> {
|
||||
'c: 'a,
|
||||
I: IntoIterator<Item=&'a(&'c [u8], &'c [u8])>,
|
||||
D: IntoIterator<Item=&'a &'b [u8]>,
|
||||
>(&self, insert: I, delete: D) -> error::Result<()> {
|
||||
>(&self, insert: I, delete: D) -> sp_blockchain::Result<()> {
|
||||
let mut storage = self.storage.write();
|
||||
for (k, v) in insert {
|
||||
storage.aux.insert(k.to_vec(), v.to_vec());
|
||||
@@ -394,7 +393,7 @@ impl<Block: BlockT> backend::AuxStore for Blockchain<Block> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_aux(&self, key: &[u8]) -> error::Result<Option<Vec<u8>>> {
|
||||
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
|
||||
Ok(self.storage.read().aux.get(key).cloned())
|
||||
}
|
||||
}
|
||||
@@ -409,7 +408,7 @@ impl<Block: BlockT> client_api::light::Storage<Block> for Blockchain<Block>
|
||||
_cache: HashMap<CacheKeyId, Vec<u8>>,
|
||||
state: NewBlockState,
|
||||
aux_ops: Vec<(Vec<u8>, Option<Vec<u8>>)>,
|
||||
) -> error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
let hash = header.hash();
|
||||
self.insert(hash, header, None, None, state)?;
|
||||
|
||||
@@ -417,15 +416,15 @@ impl<Block: BlockT> client_api::light::Storage<Block> for Blockchain<Block>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_head(&self, id: BlockId<Block>) -> error::Result<()> {
|
||||
fn set_head(&self, id: BlockId<Block>) -> sp_blockchain::Result<()> {
|
||||
Blockchain::set_head(self, id)
|
||||
}
|
||||
|
||||
fn last_finalized(&self) -> error::Result<Block::Hash> {
|
||||
fn last_finalized(&self) -> sp_blockchain::Result<Block::Hash> {
|
||||
Ok(self.storage.read().finalized_hash.clone())
|
||||
}
|
||||
|
||||
fn finalize_header(&self, id: BlockId<Block>) -> error::Result<()> {
|
||||
fn finalize_header(&self, id: BlockId<Block>) -> sp_blockchain::Result<()> {
|
||||
Blockchain::finalize_header(self, id, None)
|
||||
}
|
||||
|
||||
@@ -433,18 +432,18 @@ impl<Block: BlockT> client_api::light::Storage<Block> for Blockchain<Block>
|
||||
&self,
|
||||
_cht_size: NumberFor<Block>,
|
||||
block: NumberFor<Block>,
|
||||
) -> error::Result<Block::Hash> {
|
||||
) -> sp_blockchain::Result<Block::Hash> {
|
||||
self.storage.read().header_cht_roots.get(&block).cloned()
|
||||
.ok_or_else(|| error::Error::Backend(format!("Header CHT for block {} not exists", block)))
|
||||
.ok_or_else(|| sp_blockchain::Error::Backend(format!("Header CHT for block {} not exists", block)))
|
||||
}
|
||||
|
||||
fn changes_trie_cht_root(
|
||||
&self,
|
||||
_cht_size: NumberFor<Block>,
|
||||
block: NumberFor<Block>,
|
||||
) -> error::Result<Block::Hash> {
|
||||
) -> sp_blockchain::Result<Block::Hash> {
|
||||
self.storage.read().changes_trie_cht_roots.get(&block).cloned()
|
||||
.ok_or_else(|| error::Error::Backend(format!("Changes trie CHT for block {} not exists", block)))
|
||||
.ok_or_else(|| sp_blockchain::Error::Backend(format!("Changes trie CHT for block {} not exists", block)))
|
||||
}
|
||||
|
||||
fn cache(&self) -> Option<Arc<dyn blockchain::Cache<Block>>> {
|
||||
@@ -473,7 +472,7 @@ where
|
||||
{
|
||||
type State = InMemory<H>;
|
||||
|
||||
fn state(&self) -> error::Result<Option<&Self::State>> {
|
||||
fn state(&self) -> sp_blockchain::Result<Option<&Self::State>> {
|
||||
Ok(Some(&self.old_state))
|
||||
}
|
||||
|
||||
@@ -483,7 +482,7 @@ where
|
||||
body: Option<Vec<<Block as BlockT>::Extrinsic>>,
|
||||
justification: Option<Justification>,
|
||||
state: NewBlockState,
|
||||
) -> error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
assert!(self.pending_block.is_none(), "Only one block per operation is allowed");
|
||||
self.pending_block = Some(PendingBlock {
|
||||
block: StoredBlock::new(header, body, justification),
|
||||
@@ -496,17 +495,17 @@ where
|
||||
self.pending_cache = cache;
|
||||
}
|
||||
|
||||
fn update_db_storage(&mut self, update: <InMemory<H> as StateBackend<H>>::Transaction) -> error::Result<()> {
|
||||
fn update_db_storage(&mut self, update: <InMemory<H> as StateBackend<H>>::Transaction) -> sp_blockchain::Result<()> {
|
||||
self.new_state = Some(self.old_state.update(update));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_changes_trie(&mut self, update: ChangesTrieTransaction<H, NumberFor<Block>>) -> error::Result<()> {
|
||||
fn update_changes_trie(&mut self, update: ChangesTrieTransaction<H, NumberFor<Block>>) -> sp_blockchain::Result<()> {
|
||||
self.changes_trie_update = Some(update.0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> error::Result<H::Out> {
|
||||
fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> sp_blockchain::Result<H::Out> {
|
||||
check_genesis_storage(&top, &children)?;
|
||||
|
||||
let child_delta = children.into_iter()
|
||||
@@ -522,7 +521,7 @@ where
|
||||
Ok(root)
|
||||
}
|
||||
|
||||
fn insert_aux<I>(&mut self, ops: I) -> error::Result<()>
|
||||
fn insert_aux<I>(&mut self, ops: I) -> sp_blockchain::Result<()>
|
||||
where I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>
|
||||
{
|
||||
self.aux.append(&mut ops.into_iter().collect());
|
||||
@@ -533,16 +532,16 @@ where
|
||||
&mut self,
|
||||
_update: StorageCollection,
|
||||
_child_update: ChildStorageCollection,
|
||||
) -> error::Result<()> {
|
||||
) -> sp_blockchain::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mark_finalized(&mut self, block: BlockId<Block>, justification: Option<Justification>) -> error::Result<()> {
|
||||
fn mark_finalized(&mut self, block: BlockId<Block>, justification: Option<Justification>) -> sp_blockchain::Result<()> {
|
||||
self.finalized_blocks.push((block, justification));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mark_head(&mut self, block: BlockId<Block>) -> error::Result<()> {
|
||||
fn mark_head(&mut self, block: BlockId<Block>) -> sp_blockchain::Result<()> {
|
||||
assert!(self.pending_block.is_none(), "Only one set block per operation is allowed");
|
||||
self.set_head = Some(block);
|
||||
Ok(())
|
||||
@@ -594,11 +593,11 @@ where
|
||||
'c: 'a,
|
||||
I: IntoIterator<Item=&'a(&'c [u8], &'c [u8])>,
|
||||
D: IntoIterator<Item=&'a &'b [u8]>,
|
||||
>(&self, insert: I, delete: D) -> error::Result<()> {
|
||||
>(&self, insert: I, delete: D) -> sp_blockchain::Result<()> {
|
||||
self.blockchain.insert_aux(insert, delete)
|
||||
}
|
||||
|
||||
fn get_aux(&self, key: &[u8]) -> error::Result<Option<Vec<u8>>> {
|
||||
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
|
||||
self.blockchain.get_aux(key)
|
||||
}
|
||||
}
|
||||
@@ -615,7 +614,7 @@ where
|
||||
type ChangesTrieStorage = ChangesTrieStorage<Block, H>;
|
||||
type OffchainStorage = OffchainStorage;
|
||||
|
||||
fn begin_operation(&self) -> error::Result<Self::BlockImportOperation> {
|
||||
fn begin_operation(&self) -> sp_blockchain::Result<Self::BlockImportOperation> {
|
||||
let old_state = self.state_at(BlockId::Hash(Default::default()))?;
|
||||
Ok(BlockImportOperation {
|
||||
pending_block: None,
|
||||
@@ -629,12 +628,12 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId<Block>) -> error::Result<()> {
|
||||
fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId<Block>) -> sp_blockchain::Result<()> {
|
||||
operation.old_state = self.state_at(block)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn commit_operation(&self, operation: Self::BlockImportOperation) -> error::Result<()> {
|
||||
fn commit_operation(&self, operation: Self::BlockImportOperation) -> sp_blockchain::Result<()> {
|
||||
if !operation.finalized_blocks.is_empty() {
|
||||
for (block, justification) in operation.finalized_blocks {
|
||||
self.blockchain.finalize_header(block, justification)?;
|
||||
@@ -674,7 +673,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn finalize_block(&self, block: BlockId<Block>, justification: Option<Justification>) -> error::Result<()> {
|
||||
fn finalize_block(&self, block: BlockId<Block>, justification: Option<Justification>) -> sp_blockchain::Result<()> {
|
||||
self.blockchain.finalize_header(block, justification)
|
||||
}
|
||||
|
||||
@@ -694,7 +693,7 @@ where
|
||||
None
|
||||
}
|
||||
|
||||
fn state_at(&self, block: BlockId<Block>) -> error::Result<Self::State> {
|
||||
fn state_at(&self, block: BlockId<Block>) -> sp_blockchain::Result<Self::State> {
|
||||
match block {
|
||||
BlockId::Hash(h) if h == Default::default() => {
|
||||
return Ok(Self::State::default());
|
||||
@@ -704,11 +703,11 @@ where
|
||||
|
||||
match self.blockchain.id(block).and_then(|id| self.states.read().get(&id).cloned()) {
|
||||
Some(state) => Ok(state),
|
||||
None => Err(error::Error::UnknownBlock(format!("{}", block))),
|
||||
None => Err(sp_blockchain::Error::UnknownBlock(format!("{}", block))),
|
||||
}
|
||||
}
|
||||
|
||||
fn revert(&self, _n: NumberFor<Block>) -> error::Result<NumberFor<Block>> {
|
||||
fn revert(&self, _n: NumberFor<Block>) -> sp_blockchain::Result<NumberFor<Block>> {
|
||||
Ok(Zero::zero())
|
||||
}
|
||||
|
||||
@@ -797,13 +796,13 @@ impl<Block, H> state_machine::ChangesTrieStorage<H, NumberFor<Block>> for Change
|
||||
}
|
||||
|
||||
/// Check that genesis storage is valid.
|
||||
pub fn check_genesis_storage(top: &StorageOverlay, children: &ChildrenStorageOverlay) -> error::Result<()> {
|
||||
pub fn check_genesis_storage(top: &StorageOverlay, children: &ChildrenStorageOverlay) -> sp_blockchain::Result<()> {
|
||||
if top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) {
|
||||
return Err(error::Error::GenesisInvalid.into());
|
||||
return Err(sp_blockchain::Error::GenesisInvalid.into());
|
||||
}
|
||||
|
||||
if children.keys().any(|child_key| !well_known_keys::is_child_storage_key(&child_key)) {
|
||||
return Err(error::Error::GenesisInvalid.into());
|
||||
return Err(sp_blockchain::Error::GenesisInvalid.into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -21,7 +21,7 @@ use std::cmp::Reverse;
|
||||
use kvdb::{KeyValueDB, DBTransaction};
|
||||
use sr_primitives::traits::SimpleArithmetic;
|
||||
use codec::{Encode, Decode};
|
||||
use client_api::error;
|
||||
use sp_blockchain::{Error, Result};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct LeafSetItem<H, N> {
|
||||
@@ -77,7 +77,7 @@ impl<H, N> LeafSet<H, N> where
|
||||
}
|
||||
|
||||
/// Read the leaf list from the DB, using given prefix for keys.
|
||||
pub fn read_from_db(db: &dyn KeyValueDB, column: Option<u32>, prefix: &[u8]) -> error::Result<Self> {
|
||||
pub fn read_from_db(db: &dyn KeyValueDB, column: Option<u32>, prefix: &[u8]) -> Result<Self> {
|
||||
let mut storage = BTreeMap::new();
|
||||
|
||||
for (key, value) in db.iter_from_prefix(column, prefix) {
|
||||
@@ -85,11 +85,11 @@ impl<H, N> LeafSet<H, N> where
|
||||
let raw_hash = &mut &key[prefix.len()..];
|
||||
let hash = match Decode::decode(raw_hash) {
|
||||
Ok(hash) => hash,
|
||||
Err(_) => return Err(error::Error::Backend("Error decoding hash".into())),
|
||||
Err(_) => return Err(Error::Backend("Error decoding hash".into())),
|
||||
};
|
||||
let number = match Decode::decode(&mut &value[..]) {
|
||||
Ok(number) => number,
|
||||
Err(_) => return Err(error::Error::Backend("Error decoding number".into())),
|
||||
Err(_) => return Err(Error::Backend("Error decoding number".into())),
|
||||
};
|
||||
storage.entry(Reverse(number)).or_insert_with(Vec::new).push(hash);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,6 @@ mod call_executor;
|
||||
mod client;
|
||||
|
||||
pub use client_api::{
|
||||
error,
|
||||
blockchain,
|
||||
blockchain::well_known_cache_keys,
|
||||
blockchain::Info as ChainInfo,
|
||||
|
||||
@@ -26,6 +26,7 @@ use primitives::offchain::storage::InMemOffchainStorage;
|
||||
use sr_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay};
|
||||
use sr_primitives::traits::{Block as BlockT, NumberFor, Zero, Header};
|
||||
use crate::in_mem::{self, check_genesis_storage};
|
||||
use sp_blockchain::{ Error as ClientError, Result as ClientResult };
|
||||
use client_api::{
|
||||
backend::{
|
||||
AuxStore, Backend as ClientBackend, BlockImportOperation, RemoteBackend, NewBlockState,
|
||||
@@ -34,9 +35,6 @@ use client_api::{
|
||||
blockchain::{
|
||||
HeaderBackend as BlockchainHeaderBackend, well_known_cache_keys,
|
||||
},
|
||||
error::{
|
||||
Error as ClientError, Result as ClientResult
|
||||
},
|
||||
light::Storage as BlockchainStorage,
|
||||
};
|
||||
use crate::light::blockchain::Blockchain;
|
||||
|
||||
@@ -23,7 +23,10 @@ use std::sync::Arc;
|
||||
use sr_primitives::{Justification, generic::BlockId};
|
||||
use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero};
|
||||
|
||||
use header_metadata::{HeaderMetadata, CachedHeaderMetadata};
|
||||
use sp_blockchain::{
|
||||
HeaderMetadata, CachedHeaderMetadata,
|
||||
Error as ClientError, Result as ClientResult,
|
||||
};
|
||||
pub use client_api::{
|
||||
backend::{
|
||||
AuxStore, NewBlockState
|
||||
@@ -33,9 +36,6 @@ pub use client_api::{
|
||||
HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo, ProvideCache,
|
||||
well_known_cache_keys,
|
||||
},
|
||||
error::{
|
||||
Error as ClientError, Result as ClientResult
|
||||
},
|
||||
light::{
|
||||
RemoteBlockchain, LocalOrRemote, Storage
|
||||
}
|
||||
|
||||
@@ -38,9 +38,10 @@ use hash_db::Hasher;
|
||||
|
||||
use sr_api::{ProofRecorder, InitializeBlock};
|
||||
|
||||
use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
||||
|
||||
use client_api::{
|
||||
backend::RemoteBackend,
|
||||
error::{Error as ClientError, Result as ClientResult},
|
||||
light::RemoteCallRequest,
|
||||
call_executor::CallExecutor
|
||||
};
|
||||
@@ -450,7 +451,7 @@ mod tests {
|
||||
),
|
||||
);
|
||||
match execution_result {
|
||||
Err(client_api::error::Error::Execution(_)) => (),
|
||||
Err(sp_blockchain::Error::Execution(_)) => (),
|
||||
_ => panic!("Unexpected execution result: {:?}", execution_result),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,12 +33,10 @@ use state_machine::{
|
||||
read_child_proof_check,
|
||||
};
|
||||
pub use state_machine::StorageProof;
|
||||
use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
||||
|
||||
use crate::cht;
|
||||
pub use client_api::{
|
||||
error::{
|
||||
Error as ClientError, Result as ClientResult
|
||||
},
|
||||
light::{
|
||||
RemoteCallRequest, RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest,
|
||||
RemoteChangesRequest, ChangesProof, RemoteBodyRequest, Fetcher, FetchChecker,
|
||||
@@ -329,10 +327,8 @@ pub mod tests {
|
||||
use codec::Decode;
|
||||
use crate::client::tests::prepare_client_with_key_changes;
|
||||
use executor::{NativeExecutor, WasmExecutionMethod};
|
||||
use client_api::{
|
||||
backend::NewBlockState,
|
||||
error::Error as ClientError,
|
||||
};
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use client_api::backend::NewBlockState;
|
||||
use test_client::{
|
||||
self, ClientExt, blockchain::HeaderBackend, AccountKeyring,
|
||||
runtime::{self, Hash, Block, Header, Extrinsic}
|
||||
|
||||
@@ -27,11 +27,11 @@ use executor::RuntimeInfo;
|
||||
use primitives::{H256, Blake2Hasher, traits::CodeExecutor};
|
||||
use sr_primitives::BuildStorage;
|
||||
use sr_primitives::traits::Block as BlockT;
|
||||
use sp_blockchain::Result as ClientResult;
|
||||
|
||||
use crate::call_executor::LocalCallExecutor;
|
||||
use crate::client::Client;
|
||||
use client_api::{
|
||||
error::Result as ClientResult,
|
||||
light::Storage as BlockchainStorage,
|
||||
};
|
||||
use crate::light::backend::Backend;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "substrate-transaction-pool"
|
||||
name = "sc-transaction-pool"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
@@ -14,7 +14,7 @@ primitives = { package = "substrate-primitives", path = "../../primitives/core"
|
||||
sr-api = { path = "../../primitives/sr-api" }
|
||||
sr-primitives = { path = "../../primitives/sr-primitives" }
|
||||
tx-runtime-api = { package = "substrate-transaction-pool-runtime-api", path = "../../primitives/transaction-pool/runtime-api" }
|
||||
txpool = { package = "substrate-transaction-graph", path = "./graph" }
|
||||
txpool = { package = "sc-transaction-graph", path = "./graph" }
|
||||
|
||||
[dev-dependencies]
|
||||
keyring = { package = "substrate-keyring", path = "../../primitives/keyring" }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "substrate-transaction-graph"
|
||||
name = "sc-transaction-graph"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
|
||||
use futures::executor::block_on;
|
||||
use substrate_transaction_graph::*;
|
||||
use sc_transaction_graph::*;
|
||||
use sr_primitives::transaction_validity::{ValidTransaction, InvalidTransaction};
|
||||
use codec::Encode;
|
||||
use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId};
|
||||
|
||||
Reference in New Issue
Block a user