Skip to content
client.rs 57.5 KiB
Newer Older
// Copyright 2017-2018 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::sync::Arc;
use error::{Error, ErrorKind};
Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
use futures::sync::mpsc;
use parking_lot::{Mutex, RwLock};
Gav Wood's avatar
Gav Wood committed
use primitives::AuthorityId;
use runtime_primitives::{
	generic::{BlockId, SignedBlock, Block as RuntimeBlock},
	transaction_validity::{TransactionValidity, TransactionTag},
};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash};
use runtime_primitives::{ApplyResult, BuildStorage};
use runtime_api as api;
use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration};
Gav Wood's avatar
Gav Wood committed
use primitives::storage::{StorageKey, StorageData};
use primitives::storage::well_known_keys;
use codec::{Encode, Decode};
Gav Wood's avatar
Gav Wood committed
	Backend as StateBackend, CodeExecutor,
	ExecutionStrategy, ExecutionManager, prove_read,
	key_changes, key_changes_proof, OverlayedChanges
Gav Wood's avatar
Gav Wood committed

use backend::{self, BlockImportOperation};
use blockchain::{self, Info as ChainInfo, Backend as ChainBackend, HeaderBackend as ChainHeaderBackend};
use call_executor::{CallExecutor, LocalCallExecutor};
Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
use executor::{RuntimeVersion, RuntimeInfo};
use notifications::{StorageNotifications, StorageEventStream};
use {cht, error, in_mem, block_builder, 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>>;
Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
/// Substrate Client
Gav Wood's avatar
Gav Wood committed
pub struct Client<B, E, Block> 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>>>>,
	import_lock: Mutex<()>,
Gav Wood's avatar
Gav Wood committed
	importing_block: RwLock<Option<Block::Hash>>, // holds the block hash currently being imported. TODO: replace this with block queue
	block_execution_strategy: ExecutionStrategy,
	api_execution_strategy: ExecutionStrategy,
	changes_trie_config: Option<ChangesTrieConfiguration>,
/// 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]>) -> error::Result<StorageEventStream<Block::Hash>>;
/// Chain head information.
Gav Wood's avatar
Gav Wood committed
pub trait ChainHead<Block: BlockT> {
	/// Get best block header.
Gav Wood's avatar
Gav Wood committed
	fn best_block_header(&self) -> Result<<Block as BlockT>::Header, error::Error>;
/// Fetch block body by ID.
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>>>;
}

Gav Wood's avatar
Gav Wood committed
/// Client info
// TODO: split queue info from chain info and amalgamate into single struct.
#[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>,
Gav Wood's avatar
Gav Wood committed
	/// Best block number in the queue.
Gav Wood's avatar
Gav Wood committed
	pub best_queued_number: Option<<<Block as BlockT>::Header as HeaderT>::Number>,
Gav Wood's avatar
Gav Wood committed
	/// Best queued block hash.
Gav Wood's avatar
Gav Wood committed
	pub best_queued_hash: Option<Block::Hash>,
Gav Wood's avatar
Gav Wood committed
}

/// Block import result.
#[derive(Debug)]
pub enum ImportResult {
	/// Added to the import queue.
	Queued,
	/// Already in the import queue.
	AlreadyQueued,
	/// Already in the blockchain.
	AlreadyInChain,
	/// Block or parent is known to be bad.
	KnownBad,
	/// Block parent is not in the chain.
	UnknownParent,
}

/// Block status.
#[derive(Debug, PartialEq, Eq)]
pub enum BlockStatus {
	/// Added to the import queue.
	Queued,
	/// Already in the blockchain.
	InChain,
	/// Block or parent is known to be bad.
	KnownBad,
	/// Not in the queue or the blockchain.
	Unknown,
}

Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
/// Block data origin.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
Arkadiy Paronyan's avatar
Arkadiy Paronyan committed
pub enum BlockOrigin {
	/// Genesis block built into the client.
	Genesis,
	/// Block is part of the initial sync with the network.
	NetworkInitialSync,
	/// Block was broadcasted on the network.
	NetworkBroadcast,
	/// Block that was received from the network and validated in the consensus process.
	ConsensusBroadcast,
	/// Block that was collated by this node.
	Own,
	/// Block was imported from a file.
	File,
}

/// Data required to import a Block
pub struct ImportBlock<Block: BlockT> {
	/// Origin of the Block
	pub origin: BlockOrigin,
	/// Header
	pub header: Block::Header,
	/// Justification provided for this block from the outside
	pub external_justification: Justification,
	/// Internal Justification for the block
	pub internal_justification: Vec<u8>, // Block::Digest::DigestItem?
	/// Block's body
	pub body: Option<Vec<Block::Extrinsic>>,
	/// Is this block finalized already?
	/// `true` implies instant finality.
	pub finalized: bool,
	/// Auxiliary consensus data produced by the block.
	/// Contains a list of key-value pairs. If values are `None`, the keys
	/// will be deleted.
	pub auxiliary: Vec<(Vec<u8>, Option<Vec<u8>>)>,
}

impl<Block: BlockT> ImportBlock<Block> {
	/// Deconstruct the justified header into parts.
	pub fn into_inner(self)
		-> (
			BlockOrigin,
			<Block as BlockT>::Header,
			Justification,
			Justification,
			Option<Vec<<Block as BlockT>::Extrinsic>>,
			bool,
			Vec<(Vec<u8>, Option<Vec<u8>>)>,
		) {
		(
			self.origin,
			self.header,
			self.external_justification,
			self.internal_justification,
			self.body,
			self.finalized,
			self.auxiliary,
		)
	}
}



Loading full blame...