// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see .
//! Strongly typed API for full Polkadot client.
use client::backend::LocalBackend;
use client::block_builder::BlockBuilder as ClientBlockBuilder;
use client::{Client, LocalCallExecutor};
use polkadot_executor::Executor as LocalDispatch;
use substrate_executor::NativeExecutor;
use state_machine;
use runtime::Address;
use runtime_primitives::traits::AuxLookup;
use primitives::{AccountId, Block, Header, BlockId, Hash, Index, SessionKey, Timestamp, UncheckedExtrinsic};
use primitives::parachain::{CandidateReceipt, DutyRoster, Id as ParaId};
use {BlockBuilder, PolkadotApi, LocalPolkadotApi, ErrorKind, Error, Result};
// set up the necessary scaffolding to execute a set of calls to the runtime.
// this creates a new block on top of the given ID and initialises it.
macro_rules! with_runtime {
($client: ident, $at: expr, $exec: expr) => {{
let parent = $at;
let header = Header {
parent_hash: $client.block_hash_from_id(&parent)?
.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(),
extrinsics_root: Default::default(),
digest: Default::default(),
};
$client.state_at(&parent).map_err(Error::from).and_then(|state| {
let mut changes = Default::default();
let mut ext = state_machine::Ext::new(&mut changes, &state);
::substrate_executor::with_native_environment(&mut ext, || {
::runtime::Executive::initialise_block(&header);
($exec)()
}).map_err(Into::into)
})
}}
}
impl> BlockBuilder for ClientBlockBuilder>, Block> {
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
self.push(extrinsic).map_err(Into::into)
}
/// Bake the block with provided extrinsics.
fn bake(self) -> Result {
ClientBlockBuilder::bake(self).map_err(Into::into)
}
}
impl> PolkadotApi for Client>, Block> {
type BlockBuilder = ClientBlockBuilder>, Block>;
fn session_keys(&self, at: &BlockId) -> Result> {
with_runtime!(self, at, ::runtime::Consensus::authorities)
}
fn validators(&self, at: &BlockId) -> Result> {
with_runtime!(self, at, ::runtime::Session::validators)
}
fn random_seed(&self, at: &BlockId) -> Result {
with_runtime!(self, at, ::runtime::System::random_seed)
}
fn duty_roster(&self, at: &BlockId) -> Result {
with_runtime!(self, at, ::runtime::Parachains::calculate_duty_roster)
}
fn timestamp(&self, at: &BlockId) -> Result {
with_runtime!(self, at, ::runtime::Timestamp::get)
}
fn evaluate_block(&self, at: &BlockId, block: Block) -> Result {
use substrate_executor::error::ErrorKind as ExecErrorKind;
use codec::{Decode, Encode};
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(runtime_block));
match res {
Ok(()) => Ok(true),
Err(err) => match err.kind() {
&ErrorKind::Executor(ExecErrorKind::Runtime) => Ok(false),
_ => Err(err)
}
}
}
fn index(&self, at: &BlockId, account: AccountId) -> Result {
with_runtime!(self, at, || ::runtime::System::account_nonce(account))
}
fn lookup(&self, at: &BlockId, address: Address) -> Result