Commit 521e3a23 authored by Gav Wood's avatar Gav Wood Committed by asynchronous rob
Browse files

Make substrate generic (#169)

* Some initial work on RPC and client

* Rephrase as params

* More work on traitifying substrate.

* Traitify in_mem.rs

* traitify client.rs

* Make new primitives (mainly traits) build again.

* Many (superficial) build fixes throughout.

* Fix remaining build issues up to bft interface.

* Make bft primitives be generic.

* Switch out MisBehaviorReport for generic version.

* Merge Hashing into Header.

* Update runtime for new generics (with Hashing).

* Update demo runtime.

* Make runtime compile.

* Build fixes for runtime

* Remove old modules.

* port substrate-bft to use generic substrate types

* port client

* port substrate-test-runtime

* mostly port test-runtime to get compiling for std

* Ensure `AccountId` has a `Default`.

* Fix type deps.

* finish porting

* initialize test_runtime from genesis correctly

* remove commented code

* maybe unsigned signatures

* runtimes compile

* port over most of network

* serialization for generic types

* fix comment

* remove some unnecessary trait bounds

* network compiles

* tests compile for sync

* fix deserialization

* temporarily remove deserialize derives

* workarounds for serde issues for deriving deserialization

* get demo-runtime compiling on std

* port extrinsic-pool

* primitives reshuffling

* get network compiling again

* remove debugging file

* runtime tests now passing

* port client-db

* start to port over substrate-rpc

* mostly port over PolkadotApi

* test_runtime follows normal conventions

* substrate runtime tests pass

* deal with inherent extrinsics correctly in polkadot-api

* port transaction-pool

* port polkadot-consensus

* port substrate-rpc

* everything compiles

* tests compile

* fix grumbles

* test-runtime uses its own transfer type

* switch to master branch of jsonrpc

* fix network tests and some warnings

* all tests pass locally

* [ci-skip] add another comment about issue

* remove some curlies
parent f62fb4bf
...@@ -17,20 +17,20 @@ ...@@ -17,20 +17,20 @@
//! Strongly typed API for full Polkadot client. //! Strongly typed API for full Polkadot client.
use client::backend::{Backend, LocalBackend}; use client::backend::{Backend, LocalBackend};
use client::{self, Client, LocalCallExecutor}; use client::block_builder::BlockBuilder as ClientBlockBuilder;
use client::{Client, LocalCallExecutor};
use polkadot_executor::Executor as LocalDispatch; use polkadot_executor::Executor as LocalDispatch;
use substrate_executor::{NativeExecutionDispatch, NativeExecutor}; use substrate_executor::{NativeExecutionDispatch, NativeExecutor};
use state_machine::{self, OverlayedChanges}; use state_machine;
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp}; use primitives::{AccountId, Block, Header, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId}; use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
use runtime::{self, Block, Header, UncheckedExtrinsic, Extrinsic, Call, TimestampCall, ParachainsCall};
use {CheckedBlockId, BlockBuilder, PolkadotApi, LocalPolkadotApi, ErrorKind, Error, Result}; use {CheckedBlockId, BlockBuilder, PolkadotApi, LocalPolkadotApi, ErrorKind, Error, Result};
/// A checked block ID used for the substrate-client implementation of CheckedBlockId; /// A checked block ID used for the substrate-client implementation of CheckedBlockId;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct CheckedId(pub BlockId); pub struct CheckedId(pub(crate) BlockId);
impl CheckedBlockId for CheckedId { impl CheckedBlockId for CheckedId {
fn block_id(&self) -> &BlockId { fn block_id(&self) -> &BlockId {
...@@ -44,14 +44,16 @@ macro_rules! with_runtime { ...@@ -44,14 +44,16 @@ macro_rules! with_runtime {
($client: ident, $at: expr, $exec: expr) => {{ ($client: ident, $at: expr, $exec: expr) => {{
let parent = $at.block_id(); let parent = $at.block_id();
let header = Header { let header = Header {
parent_hash: $client.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?, parent_hash: $client.block_hash_from_id(&parent)?
number: $client.block_number_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))? + 1, .ok_or_else(|| ErrorKind::UnknownBlock(format!("{:?}", parent)))?,
number: $client.block_number_from_id(&parent)?
.ok_or_else(|| ErrorKind::UnknownBlock(format!("{:?}", parent)))? + 1,
state_root: Default::default(), state_root: Default::default(),
extrinsics_root: Default::default(), extrinsics_root: Default::default(),
digest: Default::default(), digest: Default::default(),
}; };
$client.state_at(parent).map_err(Error::from).and_then(|state| { $client.state_at(&parent).map_err(Error::from).and_then(|state| {
let mut changes = Default::default(); let mut changes = Default::default();
let mut ext = state_machine::Ext::new(&mut changes, &state); let mut ext = state_machine::Ext::new(&mut changes, &state);
...@@ -63,105 +65,28 @@ macro_rules! with_runtime { ...@@ -63,105 +65,28 @@ macro_rules! with_runtime {
}} }}
} }
/// A polkadot block builder. impl<B: LocalBackend<Block>> BlockBuilder for ClientBlockBuilder<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
#[derive(Debug, Clone)] where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
pub struct ClientBlockBuilder<S> {
parent: BlockId,
changes: OverlayedChanges,
state: S,
header: Header,
timestamp: Timestamp,
extrinsics: Vec<UncheckedExtrinsic>,
}
impl<S: state_machine::Backend> ClientBlockBuilder<S>
where S::Error: Into<client::error::Error>
{
// initialises a block, ready to allow extrinsics to be applied.
fn initialise_block(&mut self) -> Result<()> {
let result = {
let mut ext = state_machine::Ext::new(&mut self.changes, &self.state);
let h = self.header.clone();
::substrate_executor::with_native_environment(
&mut ext,
|| runtime::Executive::initialise_block(&h),
).map_err(Into::into)
};
match result {
Ok(_) => {
self.changes.commit_prospective();
Ok(())
}
Err(e) => {
self.changes.discard_prospective();
Err(e)
}
}
}
// executes a extrinsic, inherent or otherwise, without appending to the list.
fn apply_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
let result = {
let mut ext = state_machine::Ext::new(&mut self.changes, &self.state);
::substrate_executor::with_native_environment(
&mut ext,
move || runtime::Executive::apply_extrinsic(extrinsic),
).map_err(Into::into)
};
match result {
Ok(_) => {
self.changes.commit_prospective();
Ok(())
}
Err(e) => {
self.changes.discard_prospective();
Err(e)
}
}
}
}
impl<S: state_machine::Backend> BlockBuilder for ClientBlockBuilder<S>
where S::Error: Into<client::error::Error>
{ {
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> { fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
// Check that this is not an "inherent" extrinsic. self.push(extrinsic).map_err(Into::into)
if extrinsic.signature == Default::default() {
bail!(ErrorKind::PushedInherentTransaction(extrinsic));
} else {
self.apply_extrinsic(extrinsic.clone())?;
self.extrinsics.push(extrinsic);
Ok(())
}
} }
fn bake(mut self) -> Block { /// Bake the block with provided extrinsics.
let mut ext = state_machine::Ext::new(&mut self.changes, &self.state); fn bake(self) -> Result<Block> {
ClientBlockBuilder::bake(self).map_err(Into::into)
let final_header = ::substrate_executor::with_native_environment(
&mut ext,
move || runtime::Executive::finalise_block()
).expect("all inherent extrinsics pushed; all other extrinsics executed correctly; qed");
Block {
header: final_header,
extrinsics: self.extrinsics,
}
} }
} }
impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>> impl<B: LocalBackend<Block>> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error> where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
{ {
type CheckedBlockId = CheckedId; type CheckedBlockId = CheckedId;
type BlockBuilder = ClientBlockBuilder<B::State>; type BlockBuilder = ClientBlockBuilder<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>;
fn check_id(&self, id: BlockId) -> Result<CheckedId> { fn check_id(&self, id: BlockId) -> Result<CheckedId> {
// bail if the code is not the same as the natively linked. // bail if the code is not the same as the natively linked.
if self.code_at(&id)? != LocalDispatch::native_equivalent() { if self.code_at(&id.into())? != LocalDispatch::native_equivalent() {
bail!("This node is out of date. Block authoring may not work correctly. Bailing.") bail!("This node is out of date. Block authoring may not work correctly. Bailing.")
} }
...@@ -190,8 +115,16 @@ impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecu ...@@ -190,8 +115,16 @@ impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecu
fn evaluate_block(&self, at: &CheckedId, block: Block) -> Result<bool> { fn evaluate_block(&self, at: &CheckedId, block: Block) -> Result<bool> {
use substrate_executor::error::ErrorKind as ExecErrorKind; use substrate_executor::error::ErrorKind as ExecErrorKind;
use codec::Slicable;
use runtime::Block as RuntimeBlock;
let encoded = block.encode();
let runtime_block = match RuntimeBlock::decode(&mut &encoded[..]) {
Some(x) => x,
None => return Ok(false),
};
let res = with_runtime!(self, at, || ::runtime::Executive::execute_block(block)); let res = with_runtime!(self, at, || ::runtime::Executive::execute_block(runtime_block));
match res { match res {
Ok(()) => Ok(true), Ok(()) => Ok(true),
Err(err) => match err.kind() { Err(err) => match err.kind() {
...@@ -217,85 +150,65 @@ impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecu ...@@ -217,85 +150,65 @@ impl<B: LocalBackend> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecu
with_runtime!(self, at, || ::runtime::Parachains::parachain_head(parachain)) with_runtime!(self, at, || ::runtime::Parachains::parachain_head(parachain))
} }
fn build_block(&self, parent: &CheckedId, timestamp: Timestamp, parachains: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> { fn build_block(&self, at: &CheckedId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder> {
let parent = parent.block_id(); let mut block_builder = self.new_block_at(at.block_id())?;
let header = Header { for inherent in self.inherent_extrinsics(at, timestamp, new_heads)? {
parent_hash: self.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?, block_builder.push(inherent)?;
number: self.block_number_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))? + 1, }
state_root: Default::default(),
extrinsics_root: Default::default(),
digest: Default::default(),
};
let extrinsics = vec![
UncheckedExtrinsic {
extrinsic: Extrinsic {
signed: Default::default(),
index: Default::default(),
function: Call::Timestamp(TimestampCall::set(timestamp)),
},
signature: Default::default(),
},
UncheckedExtrinsic {
extrinsic: Extrinsic {
signed: Default::default(),
index: Default::default(),
function: Call::Parachains(ParachainsCall::set_heads(parachains)),
},
signature: Default::default(),
}
];
let mut builder = ClientBlockBuilder {
parent: *parent,
changes: OverlayedChanges::default(),
state: self.state_at(parent)?,
header,
timestamp,
extrinsics: extrinsics.clone(),
};
builder.initialise_block()?; Ok(block_builder)
}
for inherent in extrinsics { fn inherent_extrinsics(&self, at: &Self::CheckedBlockId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Vec<UncheckedExtrinsic>> {
builder.apply_extrinsic(inherent)?; use codec::Slicable;
}
Ok(builder) with_runtime!(self, at, || {
let extrinsics = ::runtime::inherent_extrinsics(timestamp, new_heads);
extrinsics.into_iter()
.map(|x| x.encode()) // get encoded representation
.map(|x| Slicable::decode(&mut &x[..])) // get byte-vec equivalent to extrinsic
.map(|x| x.expect("UncheckedExtrinsic has encoded representation equivalent to Vec<u8>; qed"))
.collect()
})
} }
} }
impl<B: LocalBackend> LocalPolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>> impl<B: LocalBackend<Block>> LocalPolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
where ::client::error::Error: From<<<B as Backend>::State as state_machine::backend::Backend>::Error> where ::client::error::Error: From<<<B as Backend<Block>>::State as state_machine::backend::Backend>::Error>
{} {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use keyring::Keyring; use keyring::Keyring;
use codec::Slicable;
use client::{self, LocalCallExecutor}; use client::{self, LocalCallExecutor};
use client::in_mem::Backend as InMemory; use client::in_mem::Backend as InMemory;
use substrate_executor::NativeExecutionDispatch; use substrate_executor::NativeExecutionDispatch;
use substrate_primitives::{self, Header};
use runtime::{GenesisConfig, ConsensusConfig, SessionConfig, BuildExternalities}; use runtime::{GenesisConfig, ConsensusConfig, SessionConfig, BuildExternalities};
fn validators() -> Vec<AccountId> { fn validators() -> Vec<AccountId> {
vec![
Keyring::One.to_raw_public().into(),
Keyring::Two.to_raw_public().into(),
]
}
fn session_keys() -> Vec<SessionKey> {
vec![ vec![
Keyring::One.to_raw_public(), Keyring::One.to_raw_public(),
Keyring::Two.to_raw_public(), Keyring::Two.to_raw_public(),
] ]
} }
fn client() -> Client<InMemory, LocalCallExecutor<InMemory, NativeExecutor<LocalDispatch>>> { fn client() -> Client<InMemory<Block>, LocalCallExecutor<InMemory<Block>, NativeExecutor<LocalDispatch>>, Block> {
struct GenesisBuilder; struct GenesisBuilder;
impl client::GenesisBuilder for GenesisBuilder { impl client::GenesisBuilder<Block> for GenesisBuilder {
fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) { fn build(self) -> (Header, Vec<(Vec<u8>, Vec<u8>)>) {
let genesis_config = GenesisConfig { let genesis_config = GenesisConfig {
consensus: Some(ConsensusConfig { consensus: Some(ConsensusConfig {
code: LocalDispatch::native_equivalent().to_vec(), code: LocalDispatch::native_equivalent().to_vec(),
authorities: validators(), authorities: session_keys(),
}), }),
system: None, system: None,
session: Some(SessionConfig { session: Some(SessionConfig {
...@@ -309,8 +222,8 @@ mod tests { ...@@ -309,8 +222,8 @@ mod tests {
}; };
let storage = genesis_config.build_externalities(); let storage = genesis_config.build_externalities();
let block = ::client::genesis::construct_genesis_block(&storage); let block = ::client::genesis::construct_genesis_block::<Block>(&storage);
(substrate_primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect()) (block.header, storage.into_iter().collect())
} }
} }
...@@ -320,18 +233,36 @@ mod tests { ...@@ -320,18 +233,36 @@ mod tests {
#[test] #[test]
fn gets_session_and_validator_keys() { fn gets_session_and_validator_keys() {
let client = client(); let client = client();
let id = client.check_id(BlockId::Number(0)).unwrap(); let id = client.check_id(BlockId::number(0)).unwrap();
assert_eq!(client.session_keys(&id).unwrap(), validators()); assert_eq!(client.session_keys(&id).unwrap(), session_keys());
assert_eq!(client.validators(&id).unwrap(), validators()); assert_eq!(client.validators(&id).unwrap(), validators());
} }
#[test] #[test]
fn build_block() { fn build_block_implicit_succeeds() {
let client = client(); let client = client();
let id = client.check_id(BlockId::Number(0)).unwrap(); let id = client.check_id(BlockId::number(0)).unwrap();
let block_builder = client.build_block(&id, 1_000_000, Vec::new()).unwrap(); let block_builder = client.build_block(&id, 1_000_000, Vec::new()).unwrap();
let block = block_builder.bake(); let block = block_builder.bake().unwrap();
assert_eq!(block.header.number, 1);
assert!(block.header.extrinsics_root != Default::default());
}
#[test]
fn build_block_with_inherent_succeeds() {
let client = client();
let id = client.check_id(BlockId::number(0)).unwrap();
let inherent = client.inherent_extrinsics(&id, 1_000_000, Vec::new()).unwrap();
let mut block_builder = client.new_block_at(id.block_id()).unwrap();
for extrinsic in inherent {
block_builder.push(extrinsic).unwrap();
}
let block = block_builder.bake().unwrap();
assert_eq!(block.header.number, 1); assert_eq!(block.header.number, 1);
assert!(block.header.extrinsics_root != Default::default()); assert!(block.header.extrinsics_root != Default::default());
...@@ -339,14 +270,14 @@ mod tests { ...@@ -339,14 +270,14 @@ mod tests {
#[test] #[test]
fn fails_to_check_id_for_unknown_block() { fn fails_to_check_id_for_unknown_block() {
assert!(client().check_id(BlockId::Number(100)).is_err()); assert!(client().check_id(BlockId::number(100)).is_err());
} }
#[test] #[test]
fn gets_random_seed_with_genesis() { fn gets_random_seed_with_genesis() {
let client = client(); let client = client();
let id = client.check_id(BlockId::Number(0)).unwrap(); let id = client.check_id(BlockId::number(0)).unwrap();
assert!(client.random_seed(&id).is_ok()); assert!(client.random_seed(&id).is_ok());
} }
} }
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
//! runtime. //! runtime.
extern crate polkadot_executor; extern crate polkadot_executor;
extern crate polkadot_runtime as runtime;
extern crate polkadot_primitives as primitives; extern crate polkadot_primitives as primitives;
extern crate polkadot_runtime as runtime;
extern crate substrate_codec as codec; extern crate substrate_codec as codec;
extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_io as runtime_io;
extern crate substrate_client as client; extern crate substrate_client as client;
...@@ -37,9 +37,8 @@ extern crate substrate_keyring as keyring; ...@@ -37,9 +37,8 @@ extern crate substrate_keyring as keyring;
pub mod full; pub mod full;
pub mod light; pub mod light;
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp}; use primitives::{AccountId, Block, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId}; use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
use runtime::{Block, UncheckedExtrinsic};
error_chain! { error_chain! {
errors { errors {
...@@ -49,19 +48,9 @@ error_chain! { ...@@ -49,19 +48,9 @@ error_chain! {
display("Unknown runtime code") display("Unknown runtime code")
} }
/// Unknown block ID. /// Unknown block ID.
UnknownBlock(b: BlockId) { UnknownBlock(b: String) {
description("Unknown block") description("Unknown block")
display("Unknown block") display("Unknown block {}", b)
}
/// Attempted to push an inherent extrinsic manually.
PushedInherentTransaction(xt: UncheckedExtrinsic) {
description("Attempted to push an inherent extrinsic to a block."),
display("Pushed inherent extrinsic to a block: {:?}", xt),
}
/// Badly-formed extrinsic.
BadlyFormedTransaction(xt: UncheckedExtrinsic) {
description("Attempted to push a badly-formed extrinsic to a block."),
display("Pushed badly-formed extrinsic to a block: {:?}", xt),
} }
/// Some other error. /// Some other error.
// TODO: allow to be specified as associated type of PolkadotApi // TODO: allow to be specified as associated type of PolkadotApi
...@@ -85,28 +74,28 @@ impl From<client::error::Error> for Error { ...@@ -85,28 +74,28 @@ impl From<client::error::Error> for Error {
} }
} }
/// A builder for blocks.
pub trait BlockBuilder: Sized {
/// Push a non-inherent extrinsic.
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()>;
/// Finalise the block.
fn bake(self) -> Block;
}
/// A checked block identifier. /// A checked block identifier.
pub trait CheckedBlockId: Clone + 'static { pub trait CheckedBlockId: Clone + 'static {
/// Yield the underlying block ID. /// Yield the underlying block ID.
fn block_id(&self) -> &BlockId; fn block_id(&self) -> &BlockId;
} }
/// Build new blocks.
pub trait BlockBuilder {
/// Push an extrinsic onto the block. Fails if the extrinsic is invalid.
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()>;
/// Bake the block with provided extrinsics.
fn bake(self) -> Result<Block>;
}
/// Trait encapsulating the Polkadot API. /// Trait encapsulating the Polkadot API.
/// ///
/// All calls should fail when the exact runtime is unknown. /// All calls should fail when the exact runtime is unknown.
pub trait PolkadotApi { pub trait PolkadotApi {
/// A checked block ID. Used to avoid redundancy of code check. /// A checked block ID. Used to avoid redundancy of code check.
type CheckedBlockId: CheckedBlockId; type CheckedBlockId: CheckedBlockId;
/// The type used to build blocks. /// The block builder for this API type.
type BlockBuilder: BlockBuilder; type BlockBuilder: BlockBuilder;
/// Check whether requests at the given block ID can be served. /// Check whether requests at the given block ID can be served.
...@@ -146,8 +135,12 @@ pub trait PolkadotApi { ...@@ -146,8 +135,12 @@ pub trait PolkadotApi {
/// and an error if we can't evaluate for some reason. /// and an error if we can't evaluate for some reason.
fn evaluate_block(&self, at: &Self::CheckedBlockId, block: Block) -> Result<bool>; fn evaluate_block(&self, at: &Self::CheckedBlockId, block: Block) -> Result<bool>;
/// Create a block builder on top of the parent block. /// Build a block on top of the given, with inherent extrinsics pre-pushed.
fn build_block(&self, parent: &Self::CheckedBlockId, timestamp: Timestamp, parachains: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder>; fn build_block(&self, at: &Self::CheckedBlockId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Self::BlockBuilder>;
/// Attempt to produce the (encoded) inherent extrinsics for a block being built upon the given.
/// This may vary by runtime and will fail if a runtime doesn't follow the same API.
fn inherent_extrinsics(&self, at: &Self::CheckedBlockId, timestamp: Timestamp, new_heads: Vec<CandidateReceipt>) -> Result<Vec<UncheckedExtrinsic>>;
} }
/// Mark for all Polkadot API implementations, that are making use of state data, stored locally. /// Mark for all Polkadot API implementations, that are making use of state data, stored locally.
......
...@@ -21,20 +21,30 @@ use client::backend::{Backend, RemoteBackend}; ...@@ -21,20 +21,30 @@ use client::backend::{Backend, RemoteBackend};
use client::{Client, CallExecutor}; use client::{Client, CallExecutor};
use codec::Slicable; use codec::Slicable;
use state_machine; use state_machine;
use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp}; use primitives::{AccountId, Block, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId}; use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
use runtime::{Block, UncheckedExtrinsic};
use full::CheckedId; use full::CheckedId;
use {PolkadotApi, RemotePolkadotApi, BlockBuilder, CheckedBlockId, Result, ErrorKind}; use {PolkadotApi, BlockBuilder, RemotePolkadotApi, CheckedBlockId, Result, ErrorKind};
/// Remote polkadot API implementation. /// Light block builder. TODO: make this work (efficiently)
pub struct RemotePolkadotApiWrapper<B: Backend, E: CallExecutor>(pub Arc<Client<B, E>>); #[derive(Clone, Copy)]
/// Block builder for light client.
pub struct LightBlockBuilder; pub struct LightBlockBuilder;
impl<B: Backend, E: CallExecutor> PolkadotApi for RemotePolkadotApiWrapper<B, E> impl BlockBuilder for LightBlockBuilder {