feat: initialize Kurdistan SDK - independent fork of Polkadot SDK

This commit is contained in:
2025-12-13 15:44:15 +03:00
commit 286de54384
6841 changed files with 1848356 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
[package]
name = "pezkuwi-node-subsystem-types"
description = "Subsystem traits and message definitions"
version = "7.0.0"
authors.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
[lints]
workspace = true
[dependencies]
async-trait = { workspace = true }
derive_more = { workspace = true, default-features = true }
fatality = { workspace = true }
futures = { workspace = true }
orchestra = { features = ["futures_channel"], workspace = true }
pezkuwi-node-network-protocol = { workspace = true, default-features = true }
pezkuwi-node-primitives = { workspace = true, default-features = true }
pezkuwi-primitives = { workspace = true, default-features = true }
pezkuwi-statement-table = { workspace = true, default-features = true }
prometheus-endpoint = { workspace = true, default-features = true }
sc-client-api = { workspace = true, default-features = true }
sc-network = { workspace = true, default-features = true }
sc-network-types = { workspace = true, default-features = true }
sc-transaction-pool-api = { workspace = true, default-features = true }
smallvec = { workspace = true, default-features = true }
sp-api = { workspace = true, default-features = true }
sp-authority-discovery = { workspace = true, default-features = true }
sp-blockchain = { workspace = true, default-features = true }
sp-consensus-babe = { workspace = true, default-features = true }
sp-runtime = { workspace = true, default-features = true }
thiserror = { workspace = true }
[features]
runtime-benchmarks = [
"pezkuwi-node-network-protocol/runtime-benchmarks",
"pezkuwi-node-primitives/runtime-benchmarks",
"pezkuwi-primitives/runtime-benchmarks",
"pezkuwi-statement-table/runtime-benchmarks",
"sc-client-api/runtime-benchmarks",
"sc-network/runtime-benchmarks",
"sc-transaction-pool-api/runtime-benchmarks",
"sp-api/runtime-benchmarks",
"sp-authority-discovery/runtime-benchmarks",
"sp-blockchain/runtime-benchmarks",
"sp-consensus-babe/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
+152
View File
@@ -0,0 +1,152 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezkuwi.
// Pezkuwi 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.
// Pezkuwi 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 Pezkuwi. If not, see <http://www.gnu.org/licenses/>.
//! Error types for the subsystem requests.
use ::orchestra::OrchestraError as OverseerError;
use fatality::fatality;
/// A description of an error causing the runtime API request to be unservable.
#[derive(thiserror::Error, Debug, Clone)]
pub enum RuntimeApiError {
/// The runtime API cannot be executed due to a runtime error.
#[error("The runtime API '{runtime_api_name}' cannot be executed: {source}")]
Execution {
/// The runtime API being called
runtime_api_name: &'static str,
/// The wrapped error. Marked as source for tracking the error chain.
#[source]
source: std::sync::Arc<dyn 'static + std::error::Error + Send + Sync>,
},
/// The runtime API request in question cannot be executed because the runtime at the requested
/// relay-parent is an old version.
#[error("The API is not supported by the runtime at the relay-parent")]
NotSupported {
/// The runtime API being called
runtime_api_name: &'static str,
},
}
/// A description of an error causing the chain API request to be unservable.
#[derive(Debug, Clone)]
pub struct ChainApiError {
msg: String,
}
impl From<&str> for ChainApiError {
fn from(s: &str) -> Self {
s.to_owned().into()
}
}
impl From<String> for ChainApiError {
fn from(msg: String) -> Self {
Self { msg }
}
}
impl core::fmt::Display for ChainApiError {
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
write!(f, "{}", self.msg)
}
}
impl std::error::Error for ChainApiError {}
/// An error that may happen during Availability Recovery process.
#[derive(PartialEq, Clone)]
#[fatality(splitable)]
#[allow(missing_docs)]
pub enum RecoveryError {
#[error("Invalid data")]
Invalid,
#[error("Data is unavailable")]
Unavailable,
#[fatal]
#[error("Erasure task channel closed")]
ChannelClosed,
}
/// An error type that describes faults that may happen
///
/// These are:
/// * Channels being closed
/// * Subsystems dying when they are not expected to
/// * Subsystems not dying when they are told to die
/// * etc.
#[derive(thiserror::Error, Debug)]
#[allow(missing_docs)]
pub enum SubsystemError {
#[error(transparent)]
NotifyCancellation(#[from] futures::channel::oneshot::Canceled),
#[error(transparent)]
QueueError(#[from] futures::channel::mpsc::SendError),
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
Infallible(#[from] std::convert::Infallible),
#[error(transparent)]
Prometheus(#[from] prometheus_endpoint::PrometheusError),
#[error("Failed to {0}")]
Context(String),
#[error("Subsystem stalled: {0}")]
SubsystemStalled(&'static str),
/// Generated by the `#[overseer(..)]` proc-macro
#[error(transparent)]
Generated(#[from] OverseerError),
/// Per origin (or subsystem) annotations to wrap an error.
#[error("Error originated in {origin}")]
FromOrigin {
/// An additional annotation tag for the origin of `source`.
origin: &'static str,
/// The wrapped error. Marked as source for tracking the error chain.
#[source]
source: Box<dyn 'static + std::error::Error + Send + Sync>,
},
}
// impl AnnotateErrorOrigin for SubsystemError {
// fn with_origin(self, origin: &'static str) -> Self {
// Self::FromOrigin {
// origin,
// source: Box::new(self),
// }
// }
// }
impl SubsystemError {
/// Adds a `str` as `origin` to the given error `err`.
pub fn with_origin<E: 'static + Send + Sync + std::error::Error>(
origin: &'static str,
err: E,
) -> Self {
Self::FromOrigin { origin, source: Box::new(err) }
}
}
/// Ease the use of subsystem errors.
pub type SubsystemResult<T> = Result<T, self::SubsystemError>;
+119
View File
@@ -0,0 +1,119 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezkuwi.
// Pezkuwi 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.
// Pezkuwi 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 Pezkuwi. If not, see <http://www.gnu.org/licenses/>.
//! Subsystem trait definitions and message types.
//!
//! Node-side logic for Pezkuwi is mostly comprised of Subsystems, which are discrete components
//! that communicate via message-passing. They are coordinated by an overseer, provided by a
//! separate crate.
#![warn(missing_docs)]
use smallvec::SmallVec;
use std::fmt;
pub use pezkuwi_primitives::{Block, BlockNumber, Hash};
/// Keeps the state of a specific block pinned in memory while the handle is alive.
///
/// The handle is reference counted and once the last is dropped, the
/// block is unpinned.
///
/// This is useful for runtime API calls to blocks that are
/// racing against finality, e.g. for slashing purposes.
pub type UnpinHandle = sc_client_api::UnpinHandle<Block>;
pub mod errors;
pub mod messages;
mod runtime_client;
pub use runtime_client::{ChainApiBackend, DefaultSubsystemClient, RuntimeApiSubsystemClient};
/// How many slots are stack-reserved for active leaves updates
///
/// If there are fewer than this number of slots, then we've wasted some stack space.
/// If there are greater than this number of slots, then we fall back to a heap vector.
const ACTIVE_LEAVES_SMALLVEC_CAPACITY: usize = 8;
/// Activated leaf.
#[derive(Debug, Clone)]
pub struct ActivatedLeaf {
/// The block hash.
pub hash: Hash,
/// The block number.
pub number: BlockNumber,
/// A handle to unpin the block on drop.
pub unpin_handle: UnpinHandle,
}
/// Changes in the set of active leaves: the teyrchain heads which we care to work on.
///
/// Note that the activated and deactivated fields indicate deltas, not complete sets.
#[derive(Clone, Default)]
pub struct ActiveLeavesUpdate {
/// New relay chain block of interest.
pub activated: Option<ActivatedLeaf>,
/// Relay chain block hashes no longer of interest.
pub deactivated: SmallVec<[Hash; ACTIVE_LEAVES_SMALLVEC_CAPACITY]>,
}
impl ActiveLeavesUpdate {
/// Create a `ActiveLeavesUpdate` with a single activated hash
pub fn start_work(activated: ActivatedLeaf) -> Self {
Self { activated: Some(activated), ..Default::default() }
}
/// Create a `ActiveLeavesUpdate` with a single deactivated hash
pub fn stop_work(hash: Hash) -> Self {
Self { deactivated: [hash][..].into(), ..Default::default() }
}
/// Is this update empty and doesn't contain any information?
pub fn is_empty(&self) -> bool {
self.activated.is_none() && self.deactivated.is_empty()
}
}
impl PartialEq for ActiveLeavesUpdate {
/// Equality for `ActiveLeavesUpdate` doesn't imply bitwise equality.
///
/// Instead, it means equality when `activated` and `deactivated` are considered as sets.
fn eq(&self, other: &Self) -> bool {
self.activated.as_ref().map(|a| a.hash) == other.activated.as_ref().map(|a| a.hash) &&
self.deactivated.len() == other.deactivated.len() &&
self.deactivated.iter().all(|a| other.deactivated.contains(a))
}
}
impl fmt::Debug for ActiveLeavesUpdate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ActiveLeavesUpdate")
.field("activated", &self.activated)
.field("deactivated", &self.deactivated)
.finish()
}
}
/// Signals sent by an overseer to a subsystem.
#[derive(PartialEq, Clone, Debug)]
pub enum OverseerSignal {
/// Subsystems should adjust their jobs to start and stop work on appropriate block hashes.
ActiveLeaves(ActiveLeavesUpdate),
/// `Subsystem` is informed of a finalized block by its block hash and number.
BlockFinalized(Hash, BlockNumber),
/// Conclude the work of the `Overseer` and all `Subsystem`s.
Conclude,
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,112 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezkuwi.
// Pezkuwi 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.
// Pezkuwi 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 Pezkuwi. If not, see <http://www.gnu.org/licenses/>.
use std::collections::HashSet;
pub use sc_network::ReputationChange;
pub use sc_network_types::PeerId;
use pezkuwi_node_network_protocol::{
grid_topology::SessionGridTopology, peer_set::ProtocolVersion, ObservedRole, OurView, View,
WrongVariant,
};
use pezkuwi_primitives::{AuthorityDiscoveryId, SessionIndex, ValidatorIndex};
/// A struct indicating new gossip topology.
#[derive(Debug, Clone, PartialEq)]
pub struct NewGossipTopology {
/// The session index this topology corresponds to.
pub session: SessionIndex,
/// The topology itself.
pub topology: SessionGridTopology,
/// The local validator index, if any.
pub local_index: Option<ValidatorIndex>,
}
/// Events from network.
#[derive(Debug, Clone, PartialEq)]
pub enum NetworkBridgeEvent<M> {
/// A peer has connected.
PeerConnected(PeerId, ObservedRole, ProtocolVersion, Option<HashSet<AuthorityDiscoveryId>>),
/// A peer has disconnected.
PeerDisconnected(PeerId),
/// Our neighbors in the new gossip topology for the session.
/// We're not necessarily connected to all of them.
///
/// This message is issued only on the validation peer set.
///
/// Note, that the distribution subsystems need to handle the last
/// view update of the newly added gossip peers manually.
NewGossipTopology(NewGossipTopology),
/// Peer has sent a message.
PeerMessage(PeerId, M),
/// Peer's `View` has changed.
PeerViewChange(PeerId, View),
/// Our view has changed.
OurViewChange(OurView),
/// The authority discovery session key has been rotated.
UpdatedAuthorityIds(PeerId, HashSet<AuthorityDiscoveryId>),
}
impl<M> NetworkBridgeEvent<M> {
/// Focus an overarching network-bridge event into some more specific variant.
///
/// This tries to transform M in `PeerMessage` to a message type specific to a subsystem.
/// It is used to dispatch events coming from a peer set to the various subsystems that are
/// handled within that peer set. More concretely a `ValidationProtocol` will be transformed
/// for example into a `BitfieldDistributionMessage` in case of the `BitfieldDistribution`
/// constructor.
///
/// Therefore a `NetworkBridgeEvent<ValidationProtocol>` will become for example a
/// `NetworkBridgeEvent<BitfieldDistributionMessage>`, with the more specific message type
/// `BitfieldDistributionMessage`.
///
/// This acts as a call to `clone`, except in the case where the event is a message event,
/// in which case the clone can be expensive and it only clones if the message type can
/// be focused.
pub fn focus<'a, T>(&'a self) -> Result<NetworkBridgeEvent<T>, WrongVariant>
where
T: 'a + Clone,
T: TryFrom<&'a M, Error = WrongVariant>,
{
Ok(match *self {
NetworkBridgeEvent::PeerMessage(ref peer, ref msg) =>
NetworkBridgeEvent::PeerMessage(*peer, T::try_from(msg)?),
NetworkBridgeEvent::PeerConnected(
ref peer,
ref role,
ref version,
ref authority_id,
) => NetworkBridgeEvent::PeerConnected(*peer, *role, *version, authority_id.clone()),
NetworkBridgeEvent::PeerDisconnected(ref peer) =>
NetworkBridgeEvent::PeerDisconnected(*peer),
NetworkBridgeEvent::NewGossipTopology(ref topology) =>
NetworkBridgeEvent::NewGossipTopology(topology.clone()),
NetworkBridgeEvent::PeerViewChange(ref peer, ref view) =>
NetworkBridgeEvent::PeerViewChange(*peer, view.clone()),
NetworkBridgeEvent::OurViewChange(ref view) =>
NetworkBridgeEvent::OurViewChange(view.clone()),
NetworkBridgeEvent::UpdatedAuthorityIds(ref peer, ref authority_ids) =>
NetworkBridgeEvent::UpdatedAuthorityIds(*peer, authority_ids.clone()),
})
}
}
@@ -0,0 +1,730 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezkuwi.
// Pezkuwi 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.
// Pezkuwi 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 Pezkuwi. If not, see <http://www.gnu.org/licenses/>.
use async_trait::async_trait;
use pezkuwi_primitives::{
async_backing::{self, Constraints},
runtime_api::TeyrchainHost,
slashing, ApprovalVotingParams, Block, BlockNumber, CandidateCommitments, CandidateEvent,
CandidateHash, CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreIndex, CoreState,
DisputeState, ExecutorParams, GroupRotationInfo, Hash, Header, Id, InboundDownwardMessage,
InboundHrmpMessage, NodeFeatures, OccupiedCoreAssumption, PersistedValidationData,
PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo, ValidationCode,
ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature,
};
use sc_client_api::{AuxStore, HeaderBackend};
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
use sp_api::{ApiError, ApiExt, ProvideRuntimeApi};
use sp_authority_discovery::AuthorityDiscoveryApi;
use sp_blockchain::{BlockStatus, Info};
use sp_consensus_babe::{BabeApi, Epoch};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
use std::{
collections::{BTreeMap, VecDeque},
sync::Arc,
};
/// Offers header utilities.
///
/// This is a async wrapper trait for ['HeaderBackend'] to be used with the
/// `ChainApiSubsystem`.
// This trait was introduced to suit the needs of collators. Depending on their operating mode, they
// might not have a client of the relay chain that can supply a synchronous HeaderBackend
// implementation.
#[async_trait]
pub trait ChainApiBackend: Send + Sync {
/// Get block header. Returns `None` if block is not found.
async fn header(&self, hash: Hash) -> sp_blockchain::Result<Option<Header>>;
/// Get blockchain info.
async fn info(&self) -> sp_blockchain::Result<Info<Block>>;
/// Get block number by hash. Returns `None` if the header is not in the chain.
async fn number(
&self,
hash: Hash,
) -> sp_blockchain::Result<Option<<Header as HeaderT>::Number>>;
/// Get block hash by number. Returns `None` if the header is not in the chain.
async fn hash(&self, number: NumberFor<Block>) -> sp_blockchain::Result<Option<Hash>>;
}
#[async_trait]
impl<T> ChainApiBackend for T
where
T: HeaderBackend<Block>,
{
/// Get block header. Returns `None` if block is not found.
async fn header(&self, hash: Hash) -> sp_blockchain::Result<Option<Header>> {
HeaderBackend::header(self, hash)
}
/// Get blockchain info.
async fn info(&self) -> sp_blockchain::Result<Info<Block>> {
Ok(HeaderBackend::info(self))
}
/// Get block number by hash. Returns `None` if the header is not in the chain.
async fn number(
&self,
hash: Hash,
) -> sp_blockchain::Result<Option<<Header as HeaderT>::Number>> {
HeaderBackend::number(self, hash)
}
/// Get block hash by number. Returns `None` if the header is not in the chain.
async fn hash(&self, number: NumberFor<Block>) -> sp_blockchain::Result<Option<Hash>> {
HeaderBackend::hash(self, number)
}
}
/// Exposes all runtime calls that are used by the runtime API subsystem.
#[async_trait]
pub trait RuntimeApiSubsystemClient {
/// Teyrchain host API version
async fn api_version_teyrchain_host(&self, at: Hash) -> Result<Option<u32>, ApiError>;
// === TeyrchainHost API ===
/// Get the current validators.
async fn validators(&self, at: Hash) -> Result<Vec<ValidatorId>, ApiError>;
/// Returns the validator groups and rotation info localized based on the hypothetical child
/// of a block whose state this is invoked on. Note that `now` in the `GroupRotationInfo`
/// should be the successor of the number of the block.
async fn validator_groups(
&self,
at: Hash,
) -> Result<(Vec<Vec<ValidatorIndex>>, GroupRotationInfo<BlockNumber>), ApiError>;
/// Yields information on all availability cores as relevant to the child block.
/// Cores are either free or occupied. Free cores can have paras assigned to them.
async fn availability_cores(
&self,
at: Hash,
) -> Result<Vec<CoreState<Hash, BlockNumber>>, ApiError>;
/// Yields the persisted validation data for the given `ParaId` along with an assumption that
/// should be used if the para currently occupies a core.
///
/// Returns `None` if either the para is not registered or the assumption is `Freed`
/// and the para already occupies a core.
async fn persisted_validation_data(
&self,
at: Hash,
para_id: Id,
assumption: OccupiedCoreAssumption,
) -> Result<Option<PersistedValidationData<Hash, BlockNumber>>, ApiError>;
/// Returns the persisted validation data for the given `ParaId` along with the corresponding
/// validation code hash. Instead of accepting assumption about the para, matches the validation
/// data hash against an expected one and yields `None` if they're not equal.
async fn assumed_validation_data(
&self,
at: Hash,
para_id: Id,
expected_persisted_validation_data_hash: Hash,
) -> Result<Option<(PersistedValidationData<Hash, BlockNumber>, ValidationCodeHash)>, ApiError>;
/// Checks if the given validation outputs pass the acceptance criteria.
async fn check_validation_outputs(
&self,
at: Hash,
para_id: Id,
outputs: CandidateCommitments,
) -> Result<bool, ApiError>;
/// Returns the session index expected at a child of the block.
///
/// This can be used to instantiate a `SigningContext`.
async fn session_index_for_child(&self, at: Hash) -> Result<SessionIndex, ApiError>;
/// Fetch the validation code used by a para, making the given `OccupiedCoreAssumption`.
///
/// Returns `None` if either the para is not registered or the assumption is `Freed`
/// and the para already occupies a core.
async fn validation_code(
&self,
at: Hash,
para_id: Id,
assumption: OccupiedCoreAssumption,
) -> Result<Option<ValidationCode>, ApiError>;
/// Get the receipt of a candidate pending availability. This returns `Some` for any paras
/// assigned to occupied cores in `availability_cores` and `None` otherwise.
async fn candidate_pending_availability(
&self,
at: Hash,
para_id: Id,
) -> Result<Option<CommittedCandidateReceipt<Hash>>, ApiError>;
/// Get a vector of events concerning candidates that occurred within a block.
async fn candidate_events(&self, at: Hash) -> Result<Vec<CandidateEvent<Hash>>, ApiError>;
/// Get all the pending inbound messages in the downward message queue for a para.
async fn dmq_contents(
&self,
at: Hash,
recipient: Id,
) -> Result<Vec<InboundDownwardMessage<BlockNumber>>, ApiError>;
/// Get the contents of all channels addressed to the given recipient. Channels that have no
/// messages in them are also included.
async fn inbound_hrmp_channels_contents(
&self,
at: Hash,
recipient: Id,
) -> Result<BTreeMap<Id, Vec<InboundHrmpMessage<BlockNumber>>>, ApiError>;
/// Get the validation code from its hash.
async fn validation_code_by_hash(
&self,
at: Hash,
hash: ValidationCodeHash,
) -> Result<Option<ValidationCode>, ApiError>;
/// Scrape dispute relevant from on-chain, backing votes and resolved disputes.
async fn on_chain_votes(&self, at: Hash)
-> Result<Option<ScrapedOnChainVotes<Hash>>, ApiError>;
/***** Added in v2 **** */
/// Get the session info for the given session, if stored.
///
/// NOTE: This function is only available since teyrchain host version 2.
async fn session_info(
&self,
at: Hash,
index: SessionIndex,
) -> Result<Option<SessionInfo>, ApiError>;
/// Submits a PVF pre-checking statement into the transaction pool.
///
/// NOTE: This function is only available since teyrchain host version 2.
async fn submit_pvf_check_statement(
&self,
at: Hash,
stmt: PvfCheckStatement,
signature: ValidatorSignature,
) -> Result<(), ApiError>;
/// Returns code hashes of PVFs that require pre-checking by validators in the active set.
///
/// NOTE: This function is only available since teyrchain host version 2.
async fn pvfs_require_precheck(&self, at: Hash) -> Result<Vec<ValidationCodeHash>, ApiError>;
/// Fetch the hash of the validation code used by a para, making the given
/// `OccupiedCoreAssumption`.
///
/// NOTE: This function is only available since teyrchain host version 2.
async fn validation_code_hash(
&self,
at: Hash,
para_id: Id,
assumption: OccupiedCoreAssumption,
) -> Result<Option<ValidationCodeHash>, ApiError>;
/***** Added in v3 **** */
/// Returns all onchain disputes.
async fn disputes(
&self,
at: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, DisputeState<BlockNumber>)>, ApiError>;
/// Returns a list of validators that lost a past session dispute and need to be slashed.
async fn unapplied_slashes(
&self,
at: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>, ApiError>;
/// Returns a merkle proof of a validator session key in a past session.
async fn key_ownership_proof(
&self,
at: Hash,
validator_id: ValidatorId,
) -> Result<Option<slashing::OpaqueKeyOwnershipProof>, ApiError>;
/// Submits an unsigned extrinsic to slash validators who lost a dispute about
/// a candidate of a past session.
async fn submit_report_dispute_lost(
&self,
at: Hash,
dispute_proof: slashing::DisputeProof,
key_ownership_proof: slashing::OpaqueKeyOwnershipProof,
) -> Result<Option<()>, ApiError>;
// === BABE API ===
/// Returns information regarding the current epoch.
async fn current_epoch(&self, at: Hash) -> Result<Epoch, ApiError>;
// === AuthorityDiscovery API ===
/// Retrieve authority identifiers of the current and next authority set.
async fn authorities(
&self,
at: Hash,
) -> std::result::Result<Vec<sp_authority_discovery::AuthorityId>, ApiError>;
/// Get the execution environment parameter set by parent hash, if stored
async fn session_executor_params(
&self,
at: Hash,
session_index: SessionIndex,
) -> Result<Option<ExecutorParams>, ApiError>;
// === v6 ===
/// Get the minimum number of backing votes.
async fn minimum_backing_votes(
&self,
at: Hash,
session_index: SessionIndex,
) -> Result<u32, ApiError>;
// === v7: Asynchronous backing API ===
/// Returns candidate's acceptance limitations for asynchronous backing for a relay parent.
async fn async_backing_params(
&self,
at: Hash,
) -> Result<pezkuwi_primitives::AsyncBackingParams, ApiError>;
/// Returns the state of teyrchain backing for a given para.
/// This is a staging method! Do not use on production runtimes!
async fn para_backing_state(
&self,
at: Hash,
para_id: Id,
) -> Result<Option<async_backing::BackingState>, ApiError>;
// === v8 ===
/// Gets the disabled validators at a specific block height
async fn disabled_validators(&self, at: Hash) -> Result<Vec<ValidatorIndex>, ApiError>;
// === v9 ===
/// Get the node features.
async fn node_features(&self, at: Hash) -> Result<NodeFeatures, ApiError>;
// == v10: Approval voting params ==
/// Approval voting configuration parameters
async fn approval_voting_params(
&self,
at: Hash,
session_index: SessionIndex,
) -> Result<ApprovalVotingParams, ApiError>;
// == v11: Claim queue ==
/// Fetch the `ClaimQueue` from scheduler pallet
async fn claim_queue(&self, at: Hash) -> Result<BTreeMap<CoreIndex, VecDeque<Id>>, ApiError>;
// == v11: Elastic scaling support ==
/// Get the receipts of all candidates pending availability for a `ParaId`.
async fn candidates_pending_availability(
&self,
at: Hash,
para_id: Id,
) -> Result<Vec<CommittedCandidateReceipt<Hash>>, ApiError>;
// == v12 ==
/// Get the constraints on the actions that can be taken by a new teyrchain
/// block.
async fn backing_constraints(
&self,
at: Hash,
para_id: Id,
) -> Result<Option<Constraints>, ApiError>;
// === v12 ===
/// Fetch the scheduling lookahead value
async fn scheduling_lookahead(&self, at: Hash) -> Result<u32, ApiError>;
// === v12 ===
/// Fetch the maximum uncompressed code size.
async fn validation_code_bomb_limit(&self, at: Hash) -> Result<u32, ApiError>;
// == v14 ==
/// Fetch the list of all teyrchain IDs registered in the relay chain.
async fn para_ids(&self, at: Hash) -> Result<Vec<Id>, ApiError>;
// == v15 ==
/// Returns a list of validators that lost a past session dispute and need to be slashed (v2).
async fn unapplied_slashes_v2(
&self,
at: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>, ApiError>;
}
/// Default implementation of [`RuntimeApiSubsystemClient`] using the client.
pub struct DefaultSubsystemClient<Client> {
client: Arc<Client>,
offchain_transaction_pool_factory: OffchainTransactionPoolFactory<Block>,
}
impl<Client> DefaultSubsystemClient<Client> {
/// Create new instance.
pub fn new(
client: Arc<Client>,
offchain_transaction_pool_factory: OffchainTransactionPoolFactory<Block>,
) -> Self {
Self { client, offchain_transaction_pool_factory }
}
}
#[async_trait]
impl<Client> RuntimeApiSubsystemClient for DefaultSubsystemClient<Client>
where
Client: ProvideRuntimeApi<Block> + Send + Sync,
Client::Api: TeyrchainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
{
async fn validators(&self, at: Hash) -> Result<Vec<ValidatorId>, ApiError> {
self.client.runtime_api().validators(at)
}
async fn validator_groups(
&self,
at: Hash,
) -> Result<(Vec<Vec<ValidatorIndex>>, GroupRotationInfo<BlockNumber>), ApiError> {
self.client.runtime_api().validator_groups(at)
}
async fn availability_cores(
&self,
at: Hash,
) -> Result<Vec<CoreState<Hash, BlockNumber>>, ApiError> {
self.client.runtime_api().availability_cores(at)
}
async fn persisted_validation_data(
&self,
at: Hash,
para_id: Id,
assumption: OccupiedCoreAssumption,
) -> Result<Option<PersistedValidationData<Hash, BlockNumber>>, ApiError> {
self.client.runtime_api().persisted_validation_data(at, para_id, assumption)
}
async fn assumed_validation_data(
&self,
at: Hash,
para_id: Id,
expected_persisted_validation_data_hash: Hash,
) -> Result<Option<(PersistedValidationData<Hash, BlockNumber>, ValidationCodeHash)>, ApiError>
{
self.client.runtime_api().assumed_validation_data(
at,
para_id,
expected_persisted_validation_data_hash,
)
}
async fn check_validation_outputs(
&self,
at: Hash,
para_id: Id,
outputs: CandidateCommitments,
) -> Result<bool, ApiError> {
self.client.runtime_api().check_validation_outputs(at, para_id, outputs)
}
async fn session_index_for_child(&self, at: Hash) -> Result<SessionIndex, ApiError> {
self.client.runtime_api().session_index_for_child(at)
}
async fn validation_code(
&self,
at: Hash,
para_id: Id,
assumption: OccupiedCoreAssumption,
) -> Result<Option<ValidationCode>, ApiError> {
self.client.runtime_api().validation_code(at, para_id, assumption)
}
async fn candidate_pending_availability(
&self,
at: Hash,
para_id: Id,
) -> Result<Option<CommittedCandidateReceipt<Hash>>, ApiError> {
self.client.runtime_api().candidate_pending_availability(at, para_id)
}
async fn candidates_pending_availability(
&self,
at: Hash,
para_id: Id,
) -> Result<Vec<CommittedCandidateReceipt<Hash>>, ApiError> {
self.client.runtime_api().candidates_pending_availability(at, para_id)
}
async fn candidate_events(&self, at: Hash) -> Result<Vec<CandidateEvent<Hash>>, ApiError> {
self.client.runtime_api().candidate_events(at)
}
async fn dmq_contents(
&self,
at: Hash,
recipient: Id,
) -> Result<Vec<InboundDownwardMessage<BlockNumber>>, ApiError> {
self.client.runtime_api().dmq_contents(at, recipient)
}
async fn inbound_hrmp_channels_contents(
&self,
at: Hash,
recipient: Id,
) -> Result<BTreeMap<Id, Vec<InboundHrmpMessage<BlockNumber>>>, ApiError> {
self.client.runtime_api().inbound_hrmp_channels_contents(at, recipient)
}
async fn validation_code_by_hash(
&self,
at: Hash,
hash: ValidationCodeHash,
) -> Result<Option<ValidationCode>, ApiError> {
self.client.runtime_api().validation_code_by_hash(at, hash)
}
async fn on_chain_votes(
&self,
at: Hash,
) -> Result<Option<ScrapedOnChainVotes<Hash>>, ApiError> {
self.client.runtime_api().on_chain_votes(at)
}
async fn session_executor_params(
&self,
at: Hash,
session_index: SessionIndex,
) -> Result<Option<ExecutorParams>, ApiError> {
self.client.runtime_api().session_executor_params(at, session_index)
}
async fn session_info(
&self,
at: Hash,
index: SessionIndex,
) -> Result<Option<SessionInfo>, ApiError> {
self.client.runtime_api().session_info(at, index)
}
async fn submit_pvf_check_statement(
&self,
at: Hash,
stmt: PvfCheckStatement,
signature: ValidatorSignature,
) -> Result<(), ApiError> {
let mut runtime_api = self.client.runtime_api();
runtime_api.register_extension(
self.offchain_transaction_pool_factory.offchain_transaction_pool(at),
);
runtime_api.submit_pvf_check_statement(at, stmt, signature)
}
async fn pvfs_require_precheck(&self, at: Hash) -> Result<Vec<ValidationCodeHash>, ApiError> {
self.client.runtime_api().pvfs_require_precheck(at)
}
async fn validation_code_hash(
&self,
at: Hash,
para_id: Id,
assumption: OccupiedCoreAssumption,
) -> Result<Option<ValidationCodeHash>, ApiError> {
self.client.runtime_api().validation_code_hash(at, para_id, assumption)
}
async fn current_epoch(&self, at: Hash) -> Result<Epoch, ApiError> {
self.client.runtime_api().current_epoch(at)
}
async fn authorities(
&self,
at: Hash,
) -> std::result::Result<Vec<sp_authority_discovery::AuthorityId>, ApiError> {
self.client.runtime_api().authorities(at)
}
async fn api_version_teyrchain_host(&self, at: Hash) -> Result<Option<u32>, ApiError> {
self.client.runtime_api().api_version::<dyn TeyrchainHost<Block>>(at)
}
async fn disputes(
&self,
at: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, DisputeState<BlockNumber>)>, ApiError> {
self.client.runtime_api().disputes(at)
}
async fn unapplied_slashes(
&self,
at: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>, ApiError> {
self.client.runtime_api().unapplied_slashes(at)
}
async fn unapplied_slashes_v2(
&self,
at: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>, ApiError> {
self.client.runtime_api().unapplied_slashes_v2(at)
}
async fn key_ownership_proof(
&self,
at: Hash,
validator_id: ValidatorId,
) -> Result<Option<slashing::OpaqueKeyOwnershipProof>, ApiError> {
self.client.runtime_api().key_ownership_proof(at, validator_id)
}
async fn submit_report_dispute_lost(
&self,
at: Hash,
dispute_proof: slashing::DisputeProof,
key_ownership_proof: slashing::OpaqueKeyOwnershipProof,
) -> Result<Option<()>, ApiError> {
let mut runtime_api = self.client.runtime_api();
runtime_api.register_extension(
self.offchain_transaction_pool_factory.offchain_transaction_pool(at),
);
runtime_api.submit_report_dispute_lost(at, dispute_proof, key_ownership_proof)
}
async fn minimum_backing_votes(
&self,
at: Hash,
_session_index: SessionIndex,
) -> Result<u32, ApiError> {
self.client.runtime_api().minimum_backing_votes(at)
}
async fn para_backing_state(
&self,
at: Hash,
para_id: Id,
) -> Result<Option<async_backing::BackingState>, ApiError> {
self.client.runtime_api().para_backing_state(at, para_id)
}
async fn async_backing_params(
&self,
at: Hash,
) -> Result<async_backing::AsyncBackingParams, ApiError> {
self.client.runtime_api().async_backing_params(at)
}
async fn node_features(&self, at: Hash) -> Result<NodeFeatures, ApiError> {
self.client.runtime_api().node_features(at)
}
async fn disabled_validators(&self, at: Hash) -> Result<Vec<ValidatorIndex>, ApiError> {
self.client.runtime_api().disabled_validators(at)
}
/// Approval voting configuration parameters
async fn approval_voting_params(
&self,
at: Hash,
_session_index: SessionIndex,
) -> Result<ApprovalVotingParams, ApiError> {
self.client.runtime_api().approval_voting_params(at)
}
async fn claim_queue(&self, at: Hash) -> Result<BTreeMap<CoreIndex, VecDeque<Id>>, ApiError> {
self.client.runtime_api().claim_queue(at)
}
async fn backing_constraints(
&self,
at: Hash,
para_id: Id,
) -> Result<Option<Constraints>, ApiError> {
self.client.runtime_api().backing_constraints(at, para_id)
}
async fn scheduling_lookahead(&self, at: Hash) -> Result<u32, ApiError> {
self.client.runtime_api().scheduling_lookahead(at)
}
async fn validation_code_bomb_limit(&self, at: Hash) -> Result<u32, ApiError> {
self.client.runtime_api().validation_code_bomb_limit(at)
}
async fn para_ids(&self, at: Hash) -> Result<Vec<Id>, ApiError> {
self.client.runtime_api().para_ids(at)
}
}
impl<Client, Block> HeaderBackend<Block> for DefaultSubsystemClient<Client>
where
Client: HeaderBackend<Block>,
Block: sp_runtime::traits::Block,
{
fn header(
&self,
hash: Block::Hash,
) -> sc_client_api::blockchain::Result<Option<Block::Header>> {
self.client.header(hash)
}
fn info(&self) -> Info<Block> {
self.client.info()
}
fn status(&self, hash: Block::Hash) -> sc_client_api::blockchain::Result<BlockStatus> {
self.client.status(hash)
}
fn number(
&self,
hash: Block::Hash,
) -> sc_client_api::blockchain::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>>
{
self.client.number(hash)
}
fn hash(
&self,
number: NumberFor<Block>,
) -> sc_client_api::blockchain::Result<Option<Block::Hash>> {
self.client.hash(number)
}
}
impl<Client> AuxStore for DefaultSubsystemClient<Client>
where
Client: AuxStore,
{
fn insert_aux<
'a,
'b: 'a,
'c: 'a,
I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
D: IntoIterator<Item = &'a &'b [u8]>,
>(
&self,
insert: I,
delete: D,
) -> sp_blockchain::Result<()> {
self.client.insert_aux(insert, delete)
}
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
self.client.get_aux(key)
}
}