mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 21:11:07 +00:00
Refactor the runtime API to use traits. (#878)
* Add missing `As` imports. * Adds new API traits that will be used by the client and runtime * Switch consensus to new API's * Switches transaction-pool to new API's * Move runtime api stuff into its own crate * Adds `impl_apis!` macro for implementing the new API traits * Make `metadata` return directly a blob * Runtime replace `impl_stubs!` with `impl_apis!` * Switches to none feature based approach for declaring the different API traits * Fixes compilation error * Fixes errors * Make the `decl_apis!` trait usable from the outside * Make the `test-client` use the new API traits * Remove last `impl_stubs!` bits and move some of them into wasm executor for tests * A little bit more documentation
This commit is contained in:
@@ -46,6 +46,7 @@ use std::sync::Arc;
|
||||
use std::time::{self, Duration, Instant};
|
||||
|
||||
use client::{Client as SubstrateClient, CallExecutor};
|
||||
use client::runtime_api::{BlockBuilder as BlockBuilderAPI, Core, Miscellaneous, OldTxQueue};
|
||||
use codec::{Decode, Encode};
|
||||
use node_primitives::{AccountId, Timestamp, SessionKey, InherentData};
|
||||
use node_runtime::Runtime;
|
||||
@@ -86,31 +87,23 @@ pub trait BlockBuilder<Block: BlockT> {
|
||||
}
|
||||
|
||||
/// Local client abstraction for the consensus.
|
||||
pub trait AuthoringApi: Send + Sync {
|
||||
pub trait AuthoringApi:
|
||||
Send
|
||||
+ Sync
|
||||
+ BlockBuilderAPI<<Self as AuthoringApi>::Block, Error=<Self as AuthoringApi>::Error>
|
||||
+ Core<<Self as AuthoringApi>::Block, AuthorityId, Error=<Self as AuthoringApi>::Error>
|
||||
+ Miscellaneous<<Self as AuthoringApi>::Block, Error=<Self as AuthoringApi>::Error>
|
||||
+ OldTxQueue<<Self as AuthoringApi>::Block, Error=<Self as AuthoringApi>::Error>
|
||||
{
|
||||
/// The block used for this API type.
|
||||
type Block: BlockT;
|
||||
/// The block builder for this API type.
|
||||
type BlockBuilder: BlockBuilder<Self::Block>;
|
||||
|
||||
/// Get the value of the randomness beacon at a given block.
|
||||
fn random_seed(&self, at: &BlockId<Self::Block>) -> Result<<Self::Block as BlockT>::Hash>;
|
||||
|
||||
/// Get validators at a given block.
|
||||
fn validators(&self, at: &BlockId<Self::Block>) -> Result<Vec<AccountId>>;
|
||||
/// The error used by this API type.
|
||||
type Error;
|
||||
|
||||
/// Build a block on top of the given, with inherent extrinsics pre-pushed.
|
||||
fn build_block(&self, at: &BlockId<Self::Block>, inherent_data: InherentData) -> Result<Self::BlockBuilder>;
|
||||
|
||||
/// Get the nonce (né index) of an account at a block.
|
||||
fn index(&self, at: &BlockId<Self::Block>, account: AccountId) -> Result<u64>;
|
||||
|
||||
/// 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: &BlockId<Self::Block>, inherent_data: InherentData) -> Result<Vec<<Self::Block as BlockT>::Extrinsic>>;
|
||||
|
||||
/// Evaluate a block. Returns true if the block is good, false if it is known to be bad,
|
||||
/// and an error if we can't evaluate for some reason.
|
||||
fn evaluate_block(&self, at: &BlockId<Self::Block>, block: Self::Block) -> Result<bool>;
|
||||
}
|
||||
|
||||
impl<B, E, Block> BlockBuilder<Block> for client::block_builder::BlockBuilder<B, E, Block, Blake2Hasher> where
|
||||
@@ -134,14 +127,7 @@ impl<B, E, Block> AuthoringApi for SubstrateClient<B, E, Block> where
|
||||
{
|
||||
type Block = Block;
|
||||
type BlockBuilder = client::block_builder::BlockBuilder<B, E, Block, Blake2Hasher>;
|
||||
|
||||
fn random_seed(&self, at: &BlockId<Block>) -> Result<<Self::Block as BlockT>::Hash> {
|
||||
self.call_api_at(at, "random_seed", &()).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn validators(&self, at: &BlockId<Block>) -> Result<Vec<AccountId>> {
|
||||
self.call_api_at(at, "validators", &()).map_err(Into::into)
|
||||
}
|
||||
type Error = client::error::Error;
|
||||
|
||||
fn build_block(&self, at: &BlockId<Block>, inherent_data: InherentData) -> Result<Self::BlockBuilder> {
|
||||
let runtime_version = self.runtime_version_at(at)?;
|
||||
@@ -152,27 +138,9 @@ impl<B, E, Block> AuthoringApi for SubstrateClient<B, E, Block> where
|
||||
block_builder.push(inherent)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(block_builder)
|
||||
}
|
||||
|
||||
fn index(&self, at: &BlockId<Block>, account: AccountId) -> Result<u64> {
|
||||
self.call_api_at(at, "account_nonce", &account).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn inherent_extrinsics(&self, at: &BlockId<Self::Block>, inherent_data: InherentData) -> Result<Vec<<Block as BlockT>::Extrinsic>> {
|
||||
self.call_api_at(at, "inherent_extrinsics", &inherent_data).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn evaluate_block(&self, at: &BlockId<Self::Block>, block: Self::Block) -> Result<bool> {
|
||||
let res: client::error::Result<()> = self.call_api_at(at, "execute_block", &block);
|
||||
match res {
|
||||
Ok(()) => Ok(true),
|
||||
Err(err) => match err.kind() {
|
||||
&client::error::ErrorKind::Execution(_) => Ok(false),
|
||||
_ => Err(err.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A long-lived network which can create BFT message routing processes on demand.
|
||||
@@ -217,7 +185,8 @@ impl<N, C> bft::Environment<<C as AuthoringApi>::Block> for ProposerFactory<N, C
|
||||
N: Network<Block=<C as AuthoringApi>::Block>,
|
||||
C: AuthoringApi + TPClient<Block=<C as AuthoringApi>::Block>,
|
||||
<<C as AuthoringApi>::Block as BlockT>::Hash:
|
||||
Into<<Runtime as SystemT>::Hash> + PartialEq<primitives::H256> + Into<primitives::H256>
|
||||
Into<<Runtime as SystemT>::Hash> + PartialEq<primitives::H256> + Into<primitives::H256>,
|
||||
Error: From<<C as AuthoringApi>::Error>
|
||||
{
|
||||
type Proposer = Proposer<C>;
|
||||
type Input = N::Input;
|
||||
@@ -297,7 +266,8 @@ impl<C: AuthoringApi + TPClient> Proposer<C> {
|
||||
impl<C> bft::Proposer<<C as AuthoringApi>::Block> for Proposer<C> where
|
||||
C: AuthoringApi + TPClient<Block=<C as AuthoringApi>::Block>,
|
||||
<<C as AuthoringApi>::Block as BlockT>::Hash:
|
||||
Into<<Runtime as SystemT>::Hash> + PartialEq<primitives::H256> + Into<primitives::H256>
|
||||
Into<<Runtime as SystemT>::Hash> + PartialEq<primitives::H256> + Into<primitives::H256>,
|
||||
error::Error: From<<C as AuthoringApi>::Error>
|
||||
{
|
||||
type Create = Result<<C as AuthoringApi>::Block>;
|
||||
type Error = Error;
|
||||
@@ -419,7 +389,7 @@ impl<C> bft::Proposer<<C as AuthoringApi>::Block> for Proposer<C> where
|
||||
|
||||
match timestamp_delay {
|
||||
Some(duration) => future::Either::A(
|
||||
Delay::new(duration).map_err(|e| Error::from(ErrorKind::Timer(e)))
|
||||
Delay::new(duration).map_err(|e| ErrorKind::Timer(e).into())
|
||||
),
|
||||
None => future::Either::B(future::ok(())),
|
||||
}
|
||||
@@ -434,9 +404,13 @@ impl<C> bft::Proposer<<C as AuthoringApi>::Block> for Proposer<C> where
|
||||
|
||||
// evaluate whether the block is actually valid.
|
||||
// TODO: is it better to delay this until the delays are finished?
|
||||
let evaluated = self.client
|
||||
.evaluate_block(&self.parent_id, unchecked_proposal.clone())
|
||||
.map_err(Into::into);
|
||||
let evaluated = match self.client.execute_block(&self.parent_id, unchecked_proposal.clone()).map_err(Error::from) {
|
||||
Ok(()) => Ok(true),
|
||||
Err(err) => match err.kind() {
|
||||
error::ErrorKind::Client(client::error::ErrorKind::Execution(_)) => Ok(false),
|
||||
_ => Err(err)
|
||||
}
|
||||
};
|
||||
|
||||
let future = future::result(evaluated).and_then(move |good| {
|
||||
let end_result = future::ok(good);
|
||||
@@ -471,7 +445,8 @@ impl<C> bft::Proposer<<C as AuthoringApi>::Block> for Proposer<C> where
|
||||
.filter(|tx| tx.verified.sender == local_id)
|
||||
.last()
|
||||
.map(|tx| Ok(tx.verified.index()))
|
||||
.unwrap_or_else(|| AuthoringApi::index(self.client.as_ref(), &self.parent_id, local_id))
|
||||
.unwrap_or_else(|| self.client.account_nonce(&self.parent_id, local_id))
|
||||
.map_err(Error::from)
|
||||
);
|
||||
|
||||
match cur_index {
|
||||
|
||||
@@ -83,6 +83,7 @@ impl Service {
|
||||
) -> Service
|
||||
where
|
||||
A: AuthoringApi + TPClient<Block = <A as AuthoringApi>::Block> + 'static,
|
||||
error::Error: From<<A as AuthoringApi>::Error>,
|
||||
C: BlockchainEvents<<A as AuthoringApi>::Block>
|
||||
+ ChainHead<<A as AuthoringApi>::Block>
|
||||
+ BlockBody<<A as AuthoringApi>::Block>,
|
||||
|
||||
Reference in New Issue
Block a user