Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 9 additions & 6 deletions substrate/client/src/block_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ use runtime_primitives::generic::BlockId;
use {backend, error, Client, CallExecutor};
use runtime_primitives::{ApplyResult, ApplyOutcome};
use patricia_trie::NodeCodec;
use primitives::{KeccakHasher, RlpCodec};
use hashdb::Hasher;
use rlp::Encodable;
use heapsize::HeapSizeOf;

/// Utility for building new (valid) blocks from a stream of extrinsics.
pub struct BlockBuilder<B, E, Block, H, C>
Expand All @@ -45,20 +45,23 @@ where
changes: state_machine::OverlayedChanges,
}

impl<B, E, Block> BlockBuilder<B, E, Block, KeccakHasher, RlpCodec>
impl<B, E, Block, H, C> BlockBuilder<B, E, Block, H, C>
where
B: backend::Backend<Block, KeccakHasher, RlpCodec>,
E: CallExecutor<Block, KeccakHasher, RlpCodec> + Clone,
B: backend::Backend<Block, H, C>,
E: CallExecutor<Block, H, C> + Clone,
Block: BlockT,
H: Hasher,
H::Out: Ord + Encodable + HeapSizeOf,
C: NodeCodec<H>
{
/// Create a new instance of builder from the given client, building on the latest block.
pub fn new(client: &Client<B, E, Block>) -> error::Result<Self> {
pub fn new(client: &Client<B, E, Block, H, C>) -> error::Result<Self> {
client.info().and_then(|i| Self::at_block(&BlockId::Hash(i.chain.best_hash), client))
}

/// Create a new instance of builder from the given client using a particular block's ID to
/// build upon.
pub fn at_block(block_id: &BlockId<Block>, client: &Client<B, E, Block>) -> error::Result<Self> {
pub fn at_block(block_id: &BlockId<Block>, client: &Client<B, E, Block, H, C>) -> error::Result<Self> {
let number = client.block_number_from_id(block_id)?
.ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", block_id)))?
+ One::one();
Expand Down
30 changes: 19 additions & 11 deletions substrate/client/src/call_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ use state_machine::{self, OverlayedChanges, Ext,
use runtime_io::Externalities;
use executor::{RuntimeVersion, RuntimeInfo};
use patricia_trie::NodeCodec;
use primitives::{KeccakHasher, RlpCodec};
use hashdb::Hasher;
use rlp::Encodable;
use std::marker::PhantomData;
use heapsize::HeapSizeOf;

use backend;
use error;
Expand Down Expand Up @@ -94,32 +95,39 @@ where

/// Call executor that executes methods locally, querying all required
/// data from local backend.
pub struct LocalCallExecutor<B, E> {
pub struct LocalCallExecutor<B, E, H, C> {
backend: Arc<B>,
executor: E,
_hasher: PhantomData<H>,
_codec: PhantomData<C>,
}

impl<B, E> LocalCallExecutor<B, E> {
impl<B, E, H, C> LocalCallExecutor<B, E, H, C> {
/// Creates new instance of local call executor.
pub fn new(backend: Arc<B>, executor: E) -> Self {
LocalCallExecutor { backend, executor }
LocalCallExecutor { backend, executor, _hasher: PhantomData, _codec: PhantomData }
}
}

impl<B, E> Clone for LocalCallExecutor<B, E> where E: Clone {
impl<B, E, H, C> Clone for LocalCallExecutor<B, E, H, C> where E: Clone {
fn clone(&self) -> Self {
LocalCallExecutor {
backend: self.backend.clone(),
executor: self.executor.clone(),
_hasher: PhantomData,
_codec: PhantomData,
}
}
}

impl<B, E, Block> CallExecutor<Block, KeccakHasher, RlpCodec> for LocalCallExecutor<B, E>
impl<B, E, Block, H, C> CallExecutor<Block, H, C> for LocalCallExecutor<B, E, H, C>
where
B: backend::LocalBackend<Block, KeccakHasher, RlpCodec>,
E: CodeExecutor<KeccakHasher> + RuntimeInfo,
B: backend::LocalBackend<Block, H, C>,
E: CodeExecutor<H> + RuntimeInfo<H>,
Block: BlockT,
H: Hasher,
H::Out: Ord + Encodable + HeapSizeOf,
C: NodeCodec<H>
{
type Error = E::Error;

Expand Down Expand Up @@ -151,7 +159,7 @@ where
}

fn call_at_state<
S: state_machine::Backend<KeccakHasher, RlpCodec>,
S: state_machine::Backend<H, C>,
F: FnOnce(Result<Vec<u8>, Self::Error>, Result<Vec<u8>, Self::Error>) -> Result<Vec<u8>, Self::Error>,
>(&self,
state: &S,
Expand All @@ -170,7 +178,7 @@ where
).map_err(Into::into)
}

fn prove_at_state<S: state_machine::Backend<KeccakHasher, RlpCodec>>(&self,
fn prove_at_state<S: state_machine::Backend<H, C>>(&self,
state: S,
changes: &mut OverlayedChanges,
method: &str,
Expand All @@ -188,6 +196,6 @@ where
}

fn native_runtime_version(&self) -> Option<RuntimeVersion> {
<E as RuntimeInfo>::NATIVE_VERSION
<E as RuntimeInfo<H>>::NATIVE_VERSION
}
}
94 changes: 64 additions & 30 deletions substrate/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ use primitives::AuthorityId;
use runtime_primitives::{bft::Justification, generic::{BlockId, SignedBlock, Block as RuntimeBlock}};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One, As, NumberFor};
use runtime_primitives::BuildStorage;
use primitives::{KeccakHasher, RlpCodec};
use hashdb::Hasher;
use heapsize::HeapSizeOf;
use patricia_trie::NodeCodec;
use rlp::Encodable;
use primitives::storage::{StorageKey, StorageData};
use codec::Decode;
use state_machine::{
Expand All @@ -37,19 +40,22 @@ use call_executor::{CallExecutor, LocalCallExecutor};
use executor::{RuntimeVersion, RuntimeInfo};
use notifications::{StorageNotifications, StorageEventStream};
use {error, in_mem, block_builder, runtime_io, bft, genesis};
use std::marker::PhantomData;

/// Type that implements `futures::Stream` of block import events.
pub type BlockchainEventStream<Block> = mpsc::UnboundedReceiver<BlockImportNotification<Block>>;

/// Substrate Client
pub struct Client<B, E, Block> where Block: BlockT {
pub struct Client<B, E, Block, H, C> where Block: BlockT {
backend: Arc<B>,
executor: E,
storage_notifications: Mutex<StorageNotifications<Block>>,
import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<BlockImportNotification<Block>>>>,
import_lock: Mutex<()>,
importing_block: RwLock<Option<Block::Hash>>, // holds the block hash currently being imported. TODO: replace this with block queue
execution_strategy: ExecutionStrategy,
_hasher: PhantomData<H>, // TODO: feels like these shouldn't be necesseary
_codec: PhantomData<C>,
}

/// A source of blockchain evenets.
Expand Down Expand Up @@ -161,24 +167,35 @@ impl<Block: BlockT> JustifiedHeader<Block> {
}

/// Create an instance of in-memory client.
pub fn new_in_mem<E, Block, S>(
pub fn new_in_mem<E, Block, S, H, C>(
executor: E,
genesis_storage: S,
) -> error::Result<Client<in_mem::Backend<Block, KeccakHasher, RlpCodec>, LocalCallExecutor<in_mem::Backend<Block, KeccakHasher, RlpCodec>, E>, Block>>
) -> error::Result<Client<
in_mem::Backend<Block, H, C>,
LocalCallExecutor<in_mem::Backend<Block, H, C>, E, H, C>,
Block,
H,
C>>
where
E: CodeExecutor<KeccakHasher> + RuntimeInfo,
E: CodeExecutor<H> + RuntimeInfo<H>,
S: BuildStorage,
Block: BlockT,
H: Hasher,
H::Out: Ord + Encodable + HeapSizeOf,
C: NodeCodec<H> + Send + Sync,
{
let backend = Arc::new(in_mem::Backend::new());
let executor = LocalCallExecutor::new(backend.clone(), executor);
Client::new(backend, executor, genesis_storage, ExecutionStrategy::NativeWhenPossible)
}

impl<B, E, Block> Client<B, E, Block> where
B: backend::Backend<Block, KeccakHasher, RlpCodec>,
E: CallExecutor<Block, KeccakHasher, RlpCodec>,
impl<B, E, Block, H, C> Client<B, E, Block, H, C> where
B: backend::Backend<Block, H, C>,
E: CallExecutor<Block, H, C>,
Block: BlockT,
H: Hasher,
H::Out: Ord + Encodable + HeapSizeOf,
C: NodeCodec<H>,
{
/// Creates new Substrate Client with given blockchain and code executor.
pub fn new<S: BuildStorage>(
Expand All @@ -204,6 +221,8 @@ impl<B, E, Block> Client<B, E, Block> where
import_lock: Default::default(),
importing_block: Default::default(),
execution_strategy,
_hasher: PhantomData,
_codec: PhantomData,
})
}

Expand Down Expand Up @@ -285,14 +304,14 @@ impl<B, E, Block> Client<B, E, Block> where
}

/// Create a new block, built on the head of the chain.
pub fn new_block(&self) -> error::Result<block_builder::BlockBuilder<B, E, Block, KeccakHasher, RlpCodec>>
pub fn new_block(&self) -> error::Result<block_builder::BlockBuilder<B, E, Block, H, C>>
where E: Clone
{
block_builder::BlockBuilder::new(self)
}

/// Create a new block, built on top of `parent`.
pub fn new_block_at(&self, parent: &BlockId<Block>) -> error::Result<block_builder::BlockBuilder<B, E, Block, KeccakHasher, RlpCodec>>
pub fn new_block_at(&self, parent: &BlockId<Block>) -> error::Result<block_builder::BlockBuilder<B, E, Block, H, C>>
where E: Clone
{
block_builder::BlockBuilder::at_block(parent, &self)
Expand Down Expand Up @@ -507,11 +526,14 @@ impl<B, E, Block> Client<B, E, Block> where
}
}

impl<B, E, Block> bft::BlockImport<Block> for Client<B, E, Block>
where
B: backend::Backend<Block, KeccakHasher, RlpCodec>,
E: CallExecutor<Block, KeccakHasher, RlpCodec>,
Block: BlockT,
impl<B, E, Block, H, C> bft::BlockImport<Block> for Client<B, E, Block, H, C>
where
H: Hasher,
H::Out: Ord + Encodable + HeapSizeOf,
C: NodeCodec<H>,
B: backend::Backend<Block, H, C>,
E: CallExecutor<Block, H, C>,
Block: BlockT,
{
fn import_block(
&self,
Expand All @@ -530,11 +552,14 @@ impl<B, E, Block> bft::BlockImport<Block> for Client<B, E, Block>
}
}

impl<B, E, Block> bft::Authorities<Block> for Client<B, E, Block>
where
B: backend::Backend<Block, KeccakHasher, RlpCodec>,
E: CallExecutor<Block, KeccakHasher, RlpCodec>,
Block: BlockT,
impl<B, E, Block, H, C> bft::Authorities<Block> for Client<B, E, Block, H, C>
where
H: Hasher,
H::Out: Ord + Encodable + HeapSizeOf,
C: NodeCodec<H>,
B: backend::Backend<Block, H, C>,
E: CallExecutor<Block, H, C>,
Block: BlockT,
{
fn authorities(&self, at: &BlockId<Block>) -> Result<Vec<AuthorityId>, bft::Error> {
let on_chain_version: Result<_, bft::Error> = self.runtime_version_at(at)
Expand All @@ -553,9 +578,12 @@ impl<B, E, Block> bft::Authorities<Block> for Client<B, E, Block>
}
}

impl<B, E, Block> BlockchainEvents<Block> for Client<B, E, Block>
impl<B, E, Block, H, C> BlockchainEvents<Block> for Client<B, E, Block, H, C>
where
E: CallExecutor<Block, KeccakHasher, RlpCodec>,
H: Hasher,
H::Out: Ord + Encodable + HeapSizeOf,
C: NodeCodec<H>,
E: CallExecutor<Block, H, C>,
Block: BlockT,
{
/// Get block import event stream.
Expand All @@ -571,22 +599,28 @@ where
}
}

impl<B, E, Block> ChainHead<Block> for Client<B, E, Block>
impl<B, E, Block, H, C> ChainHead<Block> for Client<B, E, Block, H, C>
where
B: backend::Backend<Block, KeccakHasher, RlpCodec>,
E: CallExecutor<Block, KeccakHasher, RlpCodec>,
H: Hasher,
H::Out: Ord + Encodable + HeapSizeOf,
C: NodeCodec<H>,
B: backend::Backend<Block, H, C>,
E: CallExecutor<Block, H, C>,
Block: BlockT,
{
fn best_block_header(&self) -> error::Result<<Block as BlockT>::Header> {
Client::best_block_header(self)
}
}

impl<B, E, Block> BlockBody<Block> for Client<B, E, Block>
where
B: backend::Backend<Block, KeccakHasher, RlpCodec>,
E: CallExecutor<Block, KeccakHasher, RlpCodec>,
Block: BlockT,
impl<B, E, Block, H, C> BlockBody<Block> for Client<B, E, Block, H, C>
where
H: Hasher,
H::Out: Ord + Encodable + HeapSizeOf,
C: NodeCodec<H>,
B: backend::Backend<Block, H, C>,
E: CallExecutor<Block, H, C>,
Block: BlockT,
{
fn block_body(&self, id: &BlockId<Block>) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
self.body(id)
Expand Down
27 changes: 16 additions & 11 deletions substrate/client/src/light/call_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use primitives::H256;
use patricia_trie::NodeCodec;
use hashdb::Hasher;
use rlp::Encodable;
use primitives::{KeccakHasher, RlpCodec};

use blockchain::Backend as ChainBackend;
use call_executor::{CallExecutor, CallResult};
Expand All @@ -37,26 +36,32 @@ use light::fetcher::{Fetcher, RemoteCallRequest};
use executor::RuntimeVersion;
use codec::Decode;
use heapsize::HeapSizeOf;
use std::marker::PhantomData;

/// Call executor that executes methods on remote node, querying execution proof
/// and checking proof by re-executing locally.
pub struct RemoteCallExecutor<B, F> {
pub struct RemoteCallExecutor<B, F, H, C> {
blockchain: Arc<B>,
fetcher: Arc<F>,
_hasher: PhantomData<H>,
_codec: PhantomData<C>,
}

impl<B, F> RemoteCallExecutor<B, F> {
impl<B, F, H, C> RemoteCallExecutor<B, F, H, C> {
/// Creates new instance of remote call executor.
pub fn new(blockchain: Arc<B>, fetcher: Arc<F>) -> Self {
RemoteCallExecutor { blockchain, fetcher }
RemoteCallExecutor { blockchain, fetcher, _hasher: PhantomData, _codec: PhantomData }
}
}

impl<B, F, Block> CallExecutor<Block, KeccakHasher, RlpCodec> for RemoteCallExecutor<B, F>
where
Block: BlockT,
B: ChainBackend<Block>,
F: Fetcher<Block>,
impl<B, F, Block, H, C> CallExecutor<Block, H, C> for RemoteCallExecutor<B, F, H, C>
where
Block: BlockT,
B: ChainBackend<Block>,
F: Fetcher<Block>,
H: Hasher,
H::Out: Ord + Encodable,
C: NodeCodec<H>
{
type Error = ClientError;

Expand All @@ -83,7 +88,7 @@ impl<B, F, Block> CallExecutor<Block, KeccakHasher, RlpCodec> for RemoteCallExec
}

fn call_at_state<
S: StateBackend<KeccakHasher, RlpCodec>,
S: StateBackend<H, C>,
FF: FnOnce(Result<Vec<u8>, Self::Error>, Result<Vec<u8>, Self::Error>) -> Result<Vec<u8>, Self::Error>
>(&self,
_state: &S,
Expand All @@ -95,7 +100,7 @@ impl<B, F, Block> CallExecutor<Block, KeccakHasher, RlpCodec> for RemoteCallExec
Err(ClientErrorKind::NotAvailableOnLightClient.into())
}

fn prove_at_state<S: StateBackend<KeccakHasher, RlpCodec>>(
fn prove_at_state<S: StateBackend<H, C>>(
&self,
_state: S,
_changes: &mut OverlayedChanges,
Expand Down
Loading