Skip to content
client.rs 91.6 KiB
Newer Older
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
Gav Wood's avatar
Gav Wood committed
// 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

use std::{
	marker::PhantomData, collections::{HashSet, BTreeMap, HashMap}, sync::Arc,
	panic::UnwindSafe, result, cell::RefCell, rc::Rc,
};
use log::{info, trace, warn};
use futures03::channel::mpsc;
use parking_lot::{Mutex, RwLock};
use codec::{Encode, Decode};
use hash_db::{Hasher, Prefix};
use primitives::{
	Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash, NeverNativeValue, ExecutionContext,
	NativeOrEncoded, storage::{StorageKey, StorageData, well_known_keys},
	offchain::{OffchainExt, self}, traits::CodeExecutor,
};
use substrate_telemetry::{telemetry, SUBSTRATE_INFO};
use sr_primitives::{
	Justification, BuildStorage,
	generic::{BlockId, SignedBlock, DigestItem},
	traits::{
		Block as BlockT, Header as HeaderT, Zero, NumberFor,
		ApiRef, ProvideRuntimeApi, SaturatedConversion, One, DigestFor,
	},
	DBValue, Backend as StateBackend, ChangesTrieAnchorBlockId, ExecutionStrategy, ExecutionManager,
	prove_read, prove_child_read, ChangesTrieRootsStorage, ChangesTrieStorage,
	ChangesTrieTransaction, ChangesTrieConfigurationRange, key_changes, key_changes_proof,
	OverlayedChanges, BackendTrustLevel, StorageProof, merge_storage_proofs,
Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
use executor::{RuntimeVersion, RuntimeInfo};
use consensus::{
	Error as ConsensusError, BlockStatus, BlockImportParams, BlockCheckParams,
	ImportResult, BlockOrigin, ForkChoiceStrategy,
	SelectChain, self,
};
use header_metadata::{HeaderMetadata, CachedHeaderMetadata};
use crate::{
	runtime_api::{
		CallRuntimeAt, ConstructRuntimeApi, Core as CoreApi, ProofRecorder,
		InitializeBlock,
	},
	backend::{
		self, BlockImportOperation, PrunableStateChangesTrieStorage,
		ClientImportOperation, Finalizer, ImportSummary,
	},
	blockchain::{
		self, Info as ChainInfo, Backend as ChainBackend,
		HeaderBackend as ChainHeaderBackend, ProvideCache, Cache,
		well_known_cache_keys::Id as CacheKeyId,
	},
	call_executor::{CallExecutor, LocalCallExecutor},
	notifications::{StorageNotifications, StorageEventStream},
	light::{call_executor::prove_execution, fetcher::ChangesProof},
	block_builder::{self, api::BlockBuilder as BlockBuilderAPI},
	error::Error,
	cht, error, in_mem, genesis
};
Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
/// Type that implements `futures::Stream` of block import events.
pub type ImportNotifications<Block> = mpsc::UnboundedReceiver<BlockImportNotification<Block>>;

/// A stream of block finality notifications.
pub type FinalityNotifications<Block> = mpsc::UnboundedReceiver<FinalityNotification<Block>>;
Gavin Wood's avatar
Gavin Wood committed
type StorageUpdate<B, Block> = <
	<
		<B as backend::Backend<Block, Blake2Hasher>>::BlockImportOperation
			as BlockImportOperation<Block, Blake2Hasher>
	>::State as state_machine::Backend<Blake2Hasher>>::Transaction;
type ChangesUpdate<Block> = ChangesTrieTransaction<Blake2Hasher, NumberFor<Block>>;
/// Expected hashes of blocks at given heights.
///
/// This may be used as chain spec extension to filter out known, unwanted forks.
pub type ForkBlocks<Block> = Option<HashMap<NumberFor<Block>, <Block as BlockT>::Hash>>;

/// Execution strategies settings.
#[derive(Debug, Clone)]
pub struct ExecutionStrategies {
	/// Execution strategy used when syncing.
	pub syncing: ExecutionStrategy,
	/// Execution strategy used when importing blocks.
	pub importing: ExecutionStrategy,
	/// Execution strategy used when constructing blocks.
	pub block_construction: ExecutionStrategy,
	/// Execution strategy used for offchain workers.
	pub offchain_worker: ExecutionStrategy,
	/// Execution strategy used in other cases.
	pub other: ExecutionStrategy,
}

impl Default for ExecutionStrategies {
	fn default() -> ExecutionStrategies {
		ExecutionStrategies {
			syncing: ExecutionStrategy::NativeElseWasm,
			importing: ExecutionStrategy::NativeElseWasm,
			block_construction: ExecutionStrategy::AlwaysWasm,
			offchain_worker: ExecutionStrategy::NativeWhenPossible,
			other: ExecutionStrategy::NativeElseWasm,
		}
	}
}

Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
/// Substrate Client
pub struct Client<B, E, Block, RA> where Block: BlockT {
Gav Wood's avatar
Gav Wood committed
	executor: E,
	storage_notifications: Mutex<StorageNotifications<Block>>,
Gav Wood's avatar
Gav Wood committed
	import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<BlockImportNotification<Block>>>>,
	finality_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<FinalityNotification<Block>>>>,
	// holds the block hash currently being imported. TODO: replace this with block queue
	importing_block: RwLock<Option<Block::Hash>>,
	fork_blocks: ForkBlocks<Block>,
	execution_strategies: ExecutionStrategies,
/// A source of blockchain events.
Gav Wood's avatar
Gav Wood committed
pub trait BlockchainEvents<Block: BlockT> {
	/// Get block import event stream. Not guaranteed to be fired for every
	/// imported block.
	fn import_notification_stream(&self) -> ImportNotifications<Block>;

	/// Get a stream of finality notifications. Not guaranteed to be fired for every
	/// finalized block.
	fn finality_notification_stream(&self) -> FinalityNotifications<Block>;

	/// Get storage changes event stream.
	///
	/// Passing `None` as `filter_keys` subscribes to all storage changes.
	fn storage_changes_notification_stream(
		&self,
		filter_keys: Option<&[StorageKey]>,
		child_filter_keys: Option<&[(StorageKey, Option<Vec<StorageKey>>)]>,
Gavin Wood's avatar
Gavin Wood committed
	) -> error::Result<StorageEventStream<Block::Hash>>;
/// Fetch block body by ID.
pub trait BlockBody<Block: BlockT> {
	/// Get block body by ID. Returns `None` if the body is not stored.
Gavin Wood's avatar
Gavin Wood committed
	fn block_body(&self,
		id: &BlockId<Block>
	) -> error::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>>;
}

Gav Wood's avatar
Gav Wood committed
/// Client info
#[derive(Debug)]
Gav Wood's avatar
Gav Wood committed
pub struct ClientInfo<Block: BlockT> {
Gav Wood's avatar
Gav Wood committed
	/// Best block hash.
Gav Wood's avatar
Gav Wood committed
	pub chain: ChainInfo<Block>,
	/// State Cache Size currently used by the backend
	pub used_state_cache_size: Option<usize>,
Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
/// Summary of an imported block
#[derive(Clone, Debug)]
Gav Wood's avatar
Gav Wood committed
pub struct BlockImportNotification<Block: BlockT> {
Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
	/// Imported block header hash.
Gav Wood's avatar
Gav Wood committed
	pub hash: Block::Hash,
Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
	/// Imported block origin.
	pub origin: BlockOrigin,
	/// Imported block header.
Gav Wood's avatar
Gav Wood committed
	pub header: Block::Header,
Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
	/// Is this the new best block.
	pub is_new_best: bool,
	/// List of retracted blocks ordered by block number.
	pub retracted: Vec<Block::Hash>,
/// Summary of a finalized block.
#[derive(Clone, Debug)]
pub struct FinalityNotification<Block: BlockT> {
	/// Imported block header hash.
	pub hash: Block::Hash,
Loading full blame...