mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 15:27:57 +00:00
polkadot-service: Make native runtime configurable (#3189)
* polkadot-service: Make native runtime configurable
This pull requests adds support for configuring the native runtimes used
by polkadot-service. While this whole pr doesn't change that much for
polkadot, besides not having the light-node enabled for the default
polkadot binary. However, downstream projects (parachains) will have a
much better compile time. In cumulus for example the `cargo test --all
--release` is about 4m faster to compile.
* Fixes
* Fix
* Enable rococo-native
* Fix light client
* 🤦
* Fixes
This commit is contained in:
@@ -0,0 +1,530 @@
|
||||
// Copyright 2017-2020 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Polkadot Client
|
||||
//!
|
||||
//! Provides the [`AbstractClient`] trait that is a super trait that combines all the traits the client implements.
|
||||
//! There is also the [`Client`] enum that combines all the different clients into one common structure.
|
||||
|
||||
use std::sync::Arc;
|
||||
use beefy_primitives::ecdsa::AuthorityId as BeefyId;
|
||||
use sp_api::{ProvideRuntimeApi, CallApiAt, NumberFor};
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use sp_runtime::{
|
||||
Justifications, generic::{BlockId, SignedBlock}, traits::{Block as BlockT, BlakeTwo256},
|
||||
};
|
||||
use sc_client_api::{Backend as BackendT, BlockchainEvents, KeyIterator, AuxStore, UsageProvider};
|
||||
use sp_storage::{StorageData, StorageKey, ChildInfo, PrefixedStorageKey};
|
||||
use polkadot_primitives::v1::{Block, ParachainHost, AccountId, Nonce, Balance, Header, BlockNumber, Hash};
|
||||
use sp_consensus::BlockStatus;
|
||||
use sc_executor::native_executor_instance;
|
||||
|
||||
pub type FullBackend = sc_service::TFullBackend<Block>;
|
||||
|
||||
pub type FullClient<RuntimeApi, Executor> = sc_service::TFullClient<Block, RuntimeApi, Executor>;
|
||||
|
||||
native_executor_instance!(
|
||||
pub PolkadotExecutor,
|
||||
polkadot_runtime::api::dispatch,
|
||||
polkadot_runtime::native_version,
|
||||
frame_benchmarking::benchmarking::HostFunctions,
|
||||
);
|
||||
|
||||
#[cfg(feature = "kusama")]
|
||||
native_executor_instance!(
|
||||
pub KusamaExecutor,
|
||||
kusama_runtime::api::dispatch,
|
||||
kusama_runtime::native_version,
|
||||
frame_benchmarking::benchmarking::HostFunctions,
|
||||
);
|
||||
|
||||
#[cfg(feature = "westend")]
|
||||
native_executor_instance!(
|
||||
pub WestendExecutor,
|
||||
westend_runtime::api::dispatch,
|
||||
westend_runtime::native_version,
|
||||
frame_benchmarking::benchmarking::HostFunctions,
|
||||
);
|
||||
|
||||
#[cfg(feature = "rococo")]
|
||||
native_executor_instance!(
|
||||
pub RococoExecutor,
|
||||
rococo_runtime::api::dispatch,
|
||||
rococo_runtime::native_version,
|
||||
frame_benchmarking::benchmarking::HostFunctions,
|
||||
);
|
||||
|
||||
/// A set of APIs that polkadot-like runtimes must implement.
|
||||
pub trait RuntimeApiCollection:
|
||||
sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
|
||||
+ sp_api::ApiExt<Block>
|
||||
+ sp_consensus_babe::BabeApi<Block>
|
||||
+ sp_finality_grandpa::GrandpaApi<Block>
|
||||
+ ParachainHost<Block>
|
||||
+ sp_block_builder::BlockBuilder<Block>
|
||||
+ frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce>
|
||||
+ pallet_mmr_primitives::MmrApi<Block, <Block as BlockT>::Hash>
|
||||
+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
|
||||
+ sp_api::Metadata<Block>
|
||||
+ sp_offchain::OffchainWorkerApi<Block>
|
||||
+ sp_session::SessionKeys<Block>
|
||||
+ sp_authority_discovery::AuthorityDiscoveryApi<Block>
|
||||
+ beefy_primitives::BeefyApi<Block, BeefyId>
|
||||
where
|
||||
<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
|
||||
{}
|
||||
|
||||
impl<Api> RuntimeApiCollection for Api
|
||||
where
|
||||
Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
|
||||
+ sp_api::ApiExt<Block>
|
||||
+ sp_consensus_babe::BabeApi<Block>
|
||||
+ sp_finality_grandpa::GrandpaApi<Block>
|
||||
+ ParachainHost<Block>
|
||||
+ sp_block_builder::BlockBuilder<Block>
|
||||
+ frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce>
|
||||
+ pallet_mmr_primitives::MmrApi<Block, <Block as BlockT>::Hash>
|
||||
+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
|
||||
+ sp_api::Metadata<Block>
|
||||
+ sp_offchain::OffchainWorkerApi<Block>
|
||||
+ sp_session::SessionKeys<Block>
|
||||
+ sp_authority_discovery::AuthorityDiscoveryApi<Block>
|
||||
+ beefy_primitives::BeefyApi<Block, BeefyId>,
|
||||
<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
|
||||
{}
|
||||
|
||||
/// Trait that abstracts over all available client implementations.
|
||||
///
|
||||
/// For a concrete type there exists [`Client`].
|
||||
pub trait AbstractClient<Block, Backend>:
|
||||
BlockchainEvents<Block> + Sized + Send + Sync
|
||||
+ ProvideRuntimeApi<Block>
|
||||
+ HeaderBackend<Block>
|
||||
+ CallApiAt<
|
||||
Block,
|
||||
StateBackend = Backend::State
|
||||
>
|
||||
+ AuxStore
|
||||
+ UsageProvider<Block>
|
||||
where
|
||||
Block: BlockT,
|
||||
Backend: BackendT<Block>,
|
||||
Backend::State: sp_api::StateBackend<BlakeTwo256>,
|
||||
Self::Api: RuntimeApiCollection<StateBackend = Backend::State>,
|
||||
{}
|
||||
|
||||
impl<Block, Backend, Client> AbstractClient<Block, Backend> for Client
|
||||
where
|
||||
Block: BlockT,
|
||||
Backend: BackendT<Block>,
|
||||
Backend::State: sp_api::StateBackend<BlakeTwo256>,
|
||||
Client: BlockchainEvents<Block>
|
||||
+ ProvideRuntimeApi<Block>
|
||||
+ HeaderBackend<Block>
|
||||
+ AuxStore
|
||||
+ UsageProvider<Block>
|
||||
+ Sized
|
||||
+ Send
|
||||
+ Sync
|
||||
+ CallApiAt<
|
||||
Block,
|
||||
StateBackend = Backend::State
|
||||
>,
|
||||
Client::Api: RuntimeApiCollection<StateBackend = Backend::State>,
|
||||
{}
|
||||
|
||||
/// Execute something with the client instance.
|
||||
///
|
||||
/// As there exist multiple chains inside Polkadot, like Polkadot itself, Kusama, Westend etc,
|
||||
/// there can exist different kinds of client types. As these client types differ in the generics
|
||||
/// that are being used, we can not easily return them from a function. For returning them from a
|
||||
/// function there exists [`Client`]. However, the problem on how to use this client instance still
|
||||
/// exists. This trait "solves" it in a dirty way. It requires a type to implement this trait and
|
||||
/// than the [`execute_with_client`](ExecuteWithClient::execute_with_client) function can be called
|
||||
/// with any possible client instance.
|
||||
///
|
||||
/// In a perfect world, we could make a closure work in this way.
|
||||
pub trait ExecuteWithClient {
|
||||
/// The return type when calling this instance.
|
||||
type Output;
|
||||
|
||||
/// Execute whatever should be executed with the given client instance.
|
||||
fn execute_with_client<Client, Api, Backend>(self, client: Arc<Client>) -> Self::Output
|
||||
where
|
||||
<Api as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
|
||||
Backend: sc_client_api::Backend<Block> + 'static,
|
||||
Backend::State: sp_api::StateBackend<BlakeTwo256>,
|
||||
Api: crate::RuntimeApiCollection<StateBackend = Backend::State>,
|
||||
Client: AbstractClient<Block, Backend, Api = Api> + 'static;
|
||||
}
|
||||
|
||||
/// A handle to a Polkadot client instance.
|
||||
///
|
||||
/// The Polkadot service supports multiple different runtimes (Westend, Polkadot itself, etc). As each runtime has a
|
||||
/// specialized client, we need to hide them behind a trait. This is this trait.
|
||||
///
|
||||
/// When wanting to work with the inner client, you need to use `execute_with`.
|
||||
///
|
||||
/// See [`ExecuteWithClient`](trait.ExecuteWithClient.html) for more information.
|
||||
pub trait ClientHandle {
|
||||
/// Execute the given something with the client.
|
||||
fn execute_with<T: ExecuteWithClient>(&self, t: T) -> T::Output;
|
||||
}
|
||||
|
||||
macro_rules! with_client {
|
||||
{
|
||||
$self:ident,
|
||||
$client:ident,
|
||||
{
|
||||
$( $code:tt )*
|
||||
}
|
||||
} => {
|
||||
match $self {
|
||||
Self::Polkadot($client) => { $( $code )* },
|
||||
#[cfg(feature = "westend")]
|
||||
Self::Westend($client) => { $( $code )* },
|
||||
#[cfg(feature = "kusama")]
|
||||
Self::Kusama($client) => { $( $code )* },
|
||||
#[cfg(feature = "rococo")]
|
||||
Self::Rococo($client) => { $( $code )* },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A client instance of Polkadot.
|
||||
///
|
||||
/// See [`ExecuteWithClient`] for more information.
|
||||
#[derive(Clone)]
|
||||
pub enum Client {
|
||||
Polkadot(Arc<FullClient<polkadot_runtime::RuntimeApi, PolkadotExecutor>>),
|
||||
#[cfg(feature = "westend")]
|
||||
Westend(Arc<FullClient<westend_runtime::RuntimeApi, WestendExecutor>>),
|
||||
#[cfg(feature = "kusama")]
|
||||
Kusama(Arc<FullClient<kusama_runtime::RuntimeApi, KusamaExecutor>>),
|
||||
#[cfg(feature = "rococo")]
|
||||
Rococo(Arc<FullClient<rococo_runtime::RuntimeApi, RococoExecutor>>),
|
||||
}
|
||||
|
||||
impl ClientHandle for Client {
|
||||
fn execute_with<T: ExecuteWithClient>(&self, t: T) -> T::Output {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
T::execute_with_client::<_, _, FullBackend>(t, client.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UsageProvider<Block> for Client {
|
||||
fn usage_info(&self) -> sc_client_api::ClientInfo<Block> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.usage_info()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl sc_client_api::BlockBackend<Block> for Client {
|
||||
fn block_body(
|
||||
&self,
|
||||
id: &BlockId<Block>
|
||||
) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.block_body(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn block(&self, id: &BlockId<Block>) -> sp_blockchain::Result<Option<SignedBlock<Block>>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.block(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn block_status(&self, id: &BlockId<Block>) -> sp_blockchain::Result<BlockStatus> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.block_status(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn justifications(
|
||||
&self,
|
||||
id: &BlockId<Block>
|
||||
) -> sp_blockchain::Result<Option<Justifications>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.justifications(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn block_hash(
|
||||
&self,
|
||||
number: NumberFor<Block>
|
||||
) -> sp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.block_hash(number)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn indexed_transaction(
|
||||
&self,
|
||||
id: &<Block as BlockT>::Hash
|
||||
) -> sp_blockchain::Result<Option<Vec<u8>>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.indexed_transaction(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn block_indexed_body(
|
||||
&self,
|
||||
id: &BlockId<Block>
|
||||
) -> sp_blockchain::Result<Option<Vec<Vec<u8>>>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.block_indexed_body(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl sc_client_api::StorageProvider<Block, crate::FullBackend> for Client {
|
||||
fn storage(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
key: &StorageKey,
|
||||
) -> sp_blockchain::Result<Option<StorageData>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.storage(id, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn storage_keys(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
key_prefix: &StorageKey,
|
||||
) -> sp_blockchain::Result<Vec<StorageKey>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.storage_keys(id, key_prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn storage_hash(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
key: &StorageKey,
|
||||
) -> sp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.storage_hash(id, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn storage_pairs(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
key_prefix: &StorageKey,
|
||||
) -> sp_blockchain::Result<Vec<(StorageKey, StorageData)>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.storage_pairs(id, key_prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn storage_keys_iter<'a>(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
prefix: Option<&'a StorageKey>,
|
||||
start_key: Option<&StorageKey>,
|
||||
) -> sp_blockchain::Result<KeyIterator<'a, <crate::FullBackend as sc_client_api::Backend<Block>>::State, Block>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.storage_keys_iter(id, prefix, start_key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn child_storage(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
child_info: &ChildInfo,
|
||||
key: &StorageKey,
|
||||
) -> sp_blockchain::Result<Option<StorageData>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.child_storage(id, child_info, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn child_storage_keys(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
child_info: &ChildInfo,
|
||||
key_prefix: &StorageKey,
|
||||
) -> sp_blockchain::Result<Vec<StorageKey>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.child_storage_keys(id, child_info, key_prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn child_storage_hash(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
child_info: &ChildInfo,
|
||||
key: &StorageKey,
|
||||
) -> sp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.child_storage_hash(id, child_info, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn max_key_changes_range(
|
||||
&self,
|
||||
first: NumberFor<Block>,
|
||||
last: BlockId<Block>,
|
||||
) -> sp_blockchain::Result<Option<(NumberFor<Block>, BlockId<Block>)>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.max_key_changes_range(first, last)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn key_changes(
|
||||
&self,
|
||||
first: NumberFor<Block>,
|
||||
last: BlockId<Block>,
|
||||
storage_key: Option<&PrefixedStorageKey>,
|
||||
key: &StorageKey,
|
||||
) -> sp_blockchain::Result<Vec<(NumberFor<Block>, u32)>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.key_changes(first, last, storage_key, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_blockchain::HeaderBackend<Block> for Client {
|
||||
fn header(&self, id: BlockId<Block>) -> sp_blockchain::Result<Option<Header>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.header(&id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn info(&self) -> sp_blockchain::Info<Block> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.info()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn status(&self, id: BlockId<Block>) -> sp_blockchain::Result<sp_blockchain::BlockStatus> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.status(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn number(&self, hash: Hash) -> sp_blockchain::Result<Option<BlockNumber>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.number(hash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn hash(&self, number: BlockNumber) -> sp_blockchain::Result<Option<Hash>> {
|
||||
with_client! {
|
||||
self,
|
||||
client,
|
||||
{
|
||||
client.hash(number)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user