feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies' Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk. Key changes include: - Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks. - Modified internal documentation and code comments to reflect PezkuwiChain naming and structure. - Replaced direct references to with or specific paths within the for XCM, Pezkuwi, and other modules. - Cleaned up deprecated issue and PR references in various and files, particularly in and modules. - Adjusted image and logo URLs in documentation to point to PezkuwiChain assets. - Removed or rephrased comments related to external Polkadot/Substrate PRs and issues. This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
@@ -0,0 +1,540 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezcumulus.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// Pezcumulus 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.
|
||||
|
||||
// Pezcumulus 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 Pezcumulus. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::{
|
||||
collections::{BTreeMap, VecDeque},
|
||||
pin::Pin,
|
||||
};
|
||||
|
||||
use cumulus_primitives_core::{InboundDownwardMessage, ParaId, PersistedValidationData};
|
||||
use cumulus_relay_chain_interface::{RelayChainError, RelayChainResult};
|
||||
use cumulus_relay_chain_rpc_interface::RelayChainRpcClient;
|
||||
use futures::{Stream, StreamExt};
|
||||
use pezkuwi_core_primitives::{Block, BlockNumber, Hash, Header};
|
||||
use pezkuwi_overseer::{ChainApiBackend, RuntimeApiSubsystemClient};
|
||||
use pezkuwi_primitives::{
|
||||
async_backing::{AsyncBackingParams, BackingState, Constraints},
|
||||
slashing, ApprovalVotingParams, CoreIndex, NodeFeatures,
|
||||
};
|
||||
use pezsc_authority_discovery::{AuthorityDiscovery, Error as AuthorityDiscoveryError};
|
||||
use pezsc_client_api::AuxStore;
|
||||
use pezsp_api::{ApiError, RuntimeApiInfo};
|
||||
use pezsp_blockchain::Info;
|
||||
use pezsp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BlockChainRpcClient {
|
||||
rpc_client: RelayChainRpcClient,
|
||||
}
|
||||
|
||||
impl BlockChainRpcClient {
|
||||
pub fn new(rpc_client: RelayChainRpcClient) -> Self {
|
||||
Self { rpc_client }
|
||||
}
|
||||
|
||||
pub async fn chain_get_header(
|
||||
&self,
|
||||
hash: Option<Hash>,
|
||||
) -> Result<Option<Header>, RelayChainError> {
|
||||
self.rpc_client.chain_get_header(hash).await
|
||||
}
|
||||
|
||||
pub async fn block_get_hash(
|
||||
&self,
|
||||
number: Option<BlockNumber>,
|
||||
) -> Result<Option<Hash>, RelayChainError> {
|
||||
self.rpc_client.chain_get_block_hash(number).await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl ChainApiBackend for BlockChainRpcClient {
|
||||
async fn header(
|
||||
&self,
|
||||
hash: <Block as BlockT>::Hash,
|
||||
) -> pezsp_blockchain::Result<Option<<Block as BlockT>::Header>> {
|
||||
Ok(self.rpc_client.chain_get_header(Some(hash)).await?)
|
||||
}
|
||||
|
||||
async fn info(&self) -> pezsp_blockchain::Result<Info<Block>> {
|
||||
let (best_header_opt, genesis_hash, finalized_head) = futures::try_join!(
|
||||
self.rpc_client.chain_get_header(None),
|
||||
self.rpc_client.chain_get_head(Some(0)),
|
||||
self.rpc_client.chain_get_finalized_head()
|
||||
)?;
|
||||
let best_header = best_header_opt.ok_or_else(|| {
|
||||
RelayChainError::GenericError(
|
||||
"Unable to retrieve best header from relay chain.".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let finalized_header =
|
||||
self.rpc_client.chain_get_header(Some(finalized_head)).await?.ok_or_else(|| {
|
||||
RelayChainError::GenericError(
|
||||
"Unable to retrieve finalized header from relay chain.".to_string(),
|
||||
)
|
||||
})?;
|
||||
Ok(Info {
|
||||
best_hash: best_header.hash(),
|
||||
best_number: best_header.number,
|
||||
genesis_hash,
|
||||
finalized_hash: finalized_head,
|
||||
finalized_number: finalized_header.number,
|
||||
finalized_state: Some((finalized_header.hash(), finalized_header.number)),
|
||||
number_leaves: 1,
|
||||
block_gap: None,
|
||||
})
|
||||
}
|
||||
|
||||
async fn number(
|
||||
&self,
|
||||
hash: <Block as BlockT>::Hash,
|
||||
) -> pezsp_blockchain::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.chain_get_header(Some(hash))
|
||||
.await?
|
||||
.map(|maybe_header| maybe_header.number))
|
||||
}
|
||||
|
||||
async fn hash(
|
||||
&self,
|
||||
number: NumberFor<Block>,
|
||||
) -> pezsp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
|
||||
Ok(self.rpc_client.chain_get_block_hash(number.into()).await?)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl RuntimeApiSubsystemClient for BlockChainRpcClient {
|
||||
async fn validators(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<Vec<pezkuwi_primitives::ValidatorId>, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_validators(at).await?)
|
||||
}
|
||||
|
||||
async fn validator_groups(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<
|
||||
(
|
||||
Vec<Vec<pezkuwi_primitives::ValidatorIndex>>,
|
||||
pezkuwi_primitives::GroupRotationInfo<BlockNumber>,
|
||||
),
|
||||
pezsp_api::ApiError,
|
||||
> {
|
||||
Ok(self.rpc_client.teyrchain_host_validator_groups(at).await?)
|
||||
}
|
||||
|
||||
async fn availability_cores(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<
|
||||
Vec<pezkuwi_primitives::CoreState<Hash, pezkuwi_core_primitives::BlockNumber>>,
|
||||
pezsp_api::ApiError,
|
||||
> {
|
||||
Ok(self.rpc_client.teyrchain_host_availability_cores(at).await?)
|
||||
}
|
||||
|
||||
async fn persisted_validation_data(
|
||||
&self,
|
||||
at: Hash,
|
||||
para_id: ParaId,
|
||||
assumption: pezkuwi_primitives::OccupiedCoreAssumption,
|
||||
) -> Result<Option<PersistedValidationData<Hash, BlockNumber>>, pezsp_api::ApiError> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_persisted_validation_data(at, para_id, assumption)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn assumed_validation_data(
|
||||
&self,
|
||||
at: Hash,
|
||||
para_id: ParaId,
|
||||
expected_persisted_validation_data_hash: Hash,
|
||||
) -> Result<
|
||||
Option<(
|
||||
PersistedValidationData<Hash, BlockNumber>,
|
||||
pezkuwi_primitives::ValidationCodeHash,
|
||||
)>,
|
||||
pezsp_api::ApiError,
|
||||
> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_assumed_validation_data(
|
||||
at,
|
||||
para_id,
|
||||
expected_persisted_validation_data_hash,
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn check_validation_outputs(
|
||||
&self,
|
||||
at: Hash,
|
||||
para_id: ParaId,
|
||||
outputs: pezkuwi_primitives::CandidateCommitments,
|
||||
) -> Result<bool, pezsp_api::ApiError> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_check_validation_outputs(at, para_id, outputs)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn session_index_for_child(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<pezkuwi_primitives::SessionIndex, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_session_index_for_child(at).await?)
|
||||
}
|
||||
|
||||
async fn validation_code(
|
||||
&self,
|
||||
at: Hash,
|
||||
para_id: ParaId,
|
||||
assumption: pezkuwi_primitives::OccupiedCoreAssumption,
|
||||
) -> Result<Option<pezkuwi_primitives::ValidationCode>, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_validation_code(at, para_id, assumption).await?)
|
||||
}
|
||||
|
||||
async fn candidate_pending_availability(
|
||||
&self,
|
||||
at: Hash,
|
||||
para_id: cumulus_primitives_core::ParaId,
|
||||
) -> Result<Option<pezkuwi_primitives::CommittedCandidateReceiptV2<Hash>>, pezsp_api::ApiError> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_candidate_pending_availability(at, para_id)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn candidate_events(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<Vec<pezkuwi_primitives::CandidateEvent<Hash>>, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_candidate_events(at).await?)
|
||||
}
|
||||
|
||||
async fn dmq_contents(
|
||||
&self,
|
||||
at: Hash,
|
||||
recipient: ParaId,
|
||||
) -> Result<Vec<InboundDownwardMessage<BlockNumber>>, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_dmq_contents(recipient, at).await?)
|
||||
}
|
||||
|
||||
async fn inbound_hrmp_channels_contents(
|
||||
&self,
|
||||
at: Hash,
|
||||
recipient: ParaId,
|
||||
) -> Result<
|
||||
std::collections::BTreeMap<
|
||||
ParaId,
|
||||
Vec<pezkuwi_core_primitives::InboundHrmpMessage<BlockNumber>>,
|
||||
>,
|
||||
pezsp_api::ApiError,
|
||||
> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_inbound_hrmp_channels_contents(recipient, at)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn validation_code_by_hash(
|
||||
&self,
|
||||
at: Hash,
|
||||
validation_code_hash: pezkuwi_primitives::ValidationCodeHash,
|
||||
) -> Result<Option<pezkuwi_primitives::ValidationCode>, pezsp_api::ApiError> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_validation_code_by_hash(at, validation_code_hash)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn on_chain_votes(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<Option<pezkuwi_primitives::ScrapedOnChainVotes<Hash>>, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_on_chain_votes(at).await?)
|
||||
}
|
||||
|
||||
async fn session_info(
|
||||
&self,
|
||||
at: Hash,
|
||||
index: pezkuwi_primitives::SessionIndex,
|
||||
) -> Result<Option<pezkuwi_primitives::SessionInfo>, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_session_info(at, index).await?)
|
||||
}
|
||||
|
||||
async fn session_executor_params(
|
||||
&self,
|
||||
at: Hash,
|
||||
session_index: pezkuwi_primitives::SessionIndex,
|
||||
) -> Result<Option<pezkuwi_primitives::ExecutorParams>, pezsp_api::ApiError> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_session_executor_params(at, session_index)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn submit_pvf_check_statement(
|
||||
&self,
|
||||
at: Hash,
|
||||
stmt: pezkuwi_primitives::PvfCheckStatement,
|
||||
signature: pezkuwi_primitives::ValidatorSignature,
|
||||
) -> Result<(), pezsp_api::ApiError> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_submit_pvf_check_statement(at, stmt, signature)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn pvfs_require_precheck(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<Vec<pezkuwi_primitives::ValidationCodeHash>, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_pvfs_require_precheck(at).await?)
|
||||
}
|
||||
|
||||
async fn validation_code_hash(
|
||||
&self,
|
||||
at: Hash,
|
||||
para_id: ParaId,
|
||||
assumption: pezkuwi_primitives::OccupiedCoreAssumption,
|
||||
) -> Result<Option<pezkuwi_primitives::ValidationCodeHash>, pezsp_api::ApiError> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_validation_code_hash(at, para_id, assumption)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn current_epoch(&self, at: Hash) -> Result<pezsp_consensus_babe::Epoch, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.babe_api_current_epoch(at).await?)
|
||||
}
|
||||
|
||||
async fn authorities(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> std::result::Result<Vec<pezkuwi_primitives::AuthorityDiscoveryId>, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.authority_discovery_authorities(at).await?)
|
||||
}
|
||||
|
||||
async fn api_version_teyrchain_host(&self, at: Hash) -> Result<Option<u32>, pezsp_api::ApiError> {
|
||||
let api_id = <dyn pezkuwi_primitives::runtime_api::TeyrchainHost<Block>>::ID;
|
||||
Ok(self.rpc_client.runtime_version(at).await.map(|v| v.api_version(&api_id))?)
|
||||
}
|
||||
|
||||
async fn disputes(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<
|
||||
Vec<(
|
||||
pezkuwi_primitives::SessionIndex,
|
||||
pezkuwi_primitives::CandidateHash,
|
||||
pezkuwi_primitives::DisputeState<pezkuwi_primitives::BlockNumber>,
|
||||
)>,
|
||||
ApiError,
|
||||
> {
|
||||
Ok(self.rpc_client.teyrchain_host_disputes(at).await?)
|
||||
}
|
||||
|
||||
async fn unapplied_slashes(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<
|
||||
Vec<(
|
||||
pezkuwi_primitives::SessionIndex,
|
||||
pezkuwi_primitives::CandidateHash,
|
||||
slashing::LegacyPendingSlashes,
|
||||
)>,
|
||||
ApiError,
|
||||
> {
|
||||
Ok(self.rpc_client.teyrchain_host_unapplied_slashes(at).await?)
|
||||
}
|
||||
|
||||
async fn unapplied_slashes_v2(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<
|
||||
Vec<(
|
||||
pezkuwi_primitives::SessionIndex,
|
||||
pezkuwi_primitives::CandidateHash,
|
||||
slashing::PendingSlashes,
|
||||
)>,
|
||||
ApiError,
|
||||
> {
|
||||
Ok(self.rpc_client.teyrchain_host_unapplied_slashes_v2(at).await?)
|
||||
}
|
||||
|
||||
async fn key_ownership_proof(
|
||||
&self,
|
||||
at: Hash,
|
||||
validator_id: pezkuwi_primitives::ValidatorId,
|
||||
) -> Result<Option<slashing::OpaqueKeyOwnershipProof>, ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_key_ownership_proof(at, validator_id).await?)
|
||||
}
|
||||
|
||||
async fn submit_report_dispute_lost(
|
||||
&self,
|
||||
at: Hash,
|
||||
dispute_proof: slashing::DisputeProof,
|
||||
key_ownership_proof: slashing::OpaqueKeyOwnershipProof,
|
||||
) -> Result<Option<()>, ApiError> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_submit_report_dispute_lost(at, dispute_proof, key_ownership_proof)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn minimum_backing_votes(
|
||||
&self,
|
||||
at: Hash,
|
||||
session_index: pezkuwi_primitives::SessionIndex,
|
||||
) -> Result<u32, ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_minimum_backing_votes(at, session_index).await?)
|
||||
}
|
||||
|
||||
async fn disabled_validators(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<Vec<pezkuwi_primitives::ValidatorIndex>, ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_disabled_validators(at).await?)
|
||||
}
|
||||
|
||||
async fn async_backing_params(&self, at: Hash) -> Result<AsyncBackingParams, ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_async_backing_params(at).await?)
|
||||
}
|
||||
|
||||
async fn para_backing_state(
|
||||
&self,
|
||||
at: Hash,
|
||||
para_id: ParaId,
|
||||
) -> Result<Option<BackingState>, ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_para_backing_state(at, para_id).await?)
|
||||
}
|
||||
|
||||
/// Approval voting configuration parameters
|
||||
async fn approval_voting_params(
|
||||
&self,
|
||||
at: Hash,
|
||||
session_index: pezkuwi_primitives::SessionIndex,
|
||||
) -> Result<ApprovalVotingParams, ApiError> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_staging_approval_voting_params(at, session_index)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn node_features(&self, at: Hash) -> Result<NodeFeatures, ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_node_features(at).await?)
|
||||
}
|
||||
|
||||
async fn claim_queue(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> Result<BTreeMap<CoreIndex, VecDeque<ParaId>>, ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_claim_queue(at).await?)
|
||||
}
|
||||
|
||||
async fn candidates_pending_availability(
|
||||
&self,
|
||||
at: Hash,
|
||||
para_id: cumulus_primitives_core::ParaId,
|
||||
) -> Result<Vec<pezkuwi_primitives::CommittedCandidateReceiptV2<Hash>>, pezsp_api::ApiError> {
|
||||
Ok(self
|
||||
.rpc_client
|
||||
.teyrchain_host_candidates_pending_availability(at, para_id)
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn backing_constraints(
|
||||
&self,
|
||||
at: Hash,
|
||||
para_id: ParaId,
|
||||
) -> Result<Option<Constraints>, ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_backing_constraints(at, para_id).await?)
|
||||
}
|
||||
|
||||
async fn scheduling_lookahead(&self, at: Hash) -> Result<u32, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_scheduling_lookahead(at).await?)
|
||||
}
|
||||
|
||||
async fn validation_code_bomb_limit(&self, at: Hash) -> Result<u32, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_validation_code_bomb_limit(at).await?)
|
||||
}
|
||||
|
||||
async fn para_ids(&self, at: Hash) -> Result<Vec<ParaId>, pezsp_api::ApiError> {
|
||||
Ok(self.rpc_client.teyrchain_host_para_ids(at).await?)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AuthorityDiscovery<Block> for BlockChainRpcClient {
|
||||
async fn authorities(
|
||||
&self,
|
||||
at: Hash,
|
||||
) -> std::result::Result<Vec<pezkuwi_primitives::AuthorityDiscoveryId>, pezsp_api::ApiError> {
|
||||
let result = self.rpc_client.authority_discovery_authorities(at).await?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
async fn best_hash(&self) -> std::result::Result<Hash, AuthorityDiscoveryError> {
|
||||
self.block_get_hash(None)
|
||||
.await
|
||||
.ok()
|
||||
.flatten()
|
||||
.ok_or_else(|| AuthorityDiscoveryError::BestBlockFetchingError)
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockChainRpcClient {
|
||||
pub async fn import_notification_stream(
|
||||
&self,
|
||||
) -> RelayChainResult<Pin<Box<dyn Stream<Item = Header> + Send>>> {
|
||||
Ok(self.rpc_client.get_imported_heads_stream()?.boxed())
|
||||
}
|
||||
|
||||
pub async fn finality_notification_stream(
|
||||
&self,
|
||||
) -> RelayChainResult<Pin<Box<dyn Stream<Item = Header> + Send>>> {
|
||||
Ok(self.rpc_client.get_finalized_heads_stream()?.boxed())
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation required by ChainApiSubsystem
|
||||
// but never called in our case.
|
||||
impl AuxStore for BlockChainRpcClient {
|
||||
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,
|
||||
) -> pezsp_blockchain::Result<()> {
|
||||
unimplemented!("Not supported on the RPC collator")
|
||||
}
|
||||
|
||||
fn get_aux(&self, _key: &[u8]) -> pezsp_blockchain::Result<Option<Vec<u8>>> {
|
||||
unimplemented!("Not supported on the RPC collator")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezcumulus.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// Pezcumulus 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.
|
||||
|
||||
// Pezcumulus 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 Pezcumulus. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use futures::{select, StreamExt};
|
||||
use std::sync::Arc;
|
||||
|
||||
use pezkuwi_overseer::{
|
||||
BlockInfo, Handle, Overseer, OverseerConnector, OverseerHandle, SpawnGlue, UnpinHandle,
|
||||
};
|
||||
use pezkuwi_service::overseer::{collator_overseer_builder, OverseerGenArgs};
|
||||
|
||||
use pezsc_network::{request_responses::IncomingRequest, service::traits::NetworkService};
|
||||
use pezsc_service::TaskManager;
|
||||
use pezsc_utils::mpsc::tracing_unbounded;
|
||||
|
||||
use cumulus_relay_chain_interface::RelayChainError;
|
||||
|
||||
use crate::BlockChainRpcClient;
|
||||
|
||||
fn build_overseer(
|
||||
connector: OverseerConnector,
|
||||
args: OverseerGenArgs<pezsc_service::SpawnTaskHandle, BlockChainRpcClient>,
|
||||
) -> Result<
|
||||
(Overseer<SpawnGlue<pezsc_service::SpawnTaskHandle>, Arc<BlockChainRpcClient>>, OverseerHandle),
|
||||
RelayChainError,
|
||||
> {
|
||||
let builder =
|
||||
collator_overseer_builder(args).map_err(|e| RelayChainError::Application(e.into()))?;
|
||||
|
||||
builder
|
||||
.build_with_connector(connector)
|
||||
.map_err(|e| RelayChainError::Application(e.into()))
|
||||
}
|
||||
|
||||
pub(crate) fn spawn_overseer(
|
||||
overseer_args: OverseerGenArgs<pezsc_service::SpawnTaskHandle, BlockChainRpcClient>,
|
||||
task_manager: &TaskManager,
|
||||
relay_chain_rpc_client: Arc<BlockChainRpcClient>,
|
||||
) -> Result<pezkuwi_overseer::Handle, RelayChainError> {
|
||||
let (overseer, overseer_handle) = build_overseer(OverseerConnector::default(), overseer_args)
|
||||
.map_err(|e| {
|
||||
tracing::error!("Failed to initialize overseer: {}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let overseer_handle = Handle::new(overseer_handle);
|
||||
{
|
||||
let handle = overseer_handle.clone();
|
||||
task_manager.spawn_essential_handle().spawn_blocking(
|
||||
"overseer",
|
||||
None,
|
||||
Box::pin(async move {
|
||||
use futures::{pin_mut, FutureExt};
|
||||
|
||||
let forward = forward_collator_events(relay_chain_rpc_client, handle).fuse();
|
||||
|
||||
let overseer_fut = overseer.run().fuse();
|
||||
|
||||
pin_mut!(overseer_fut);
|
||||
pin_mut!(forward);
|
||||
|
||||
select! {
|
||||
_ = forward => (),
|
||||
_ = overseer_fut => (),
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
Ok(overseer_handle)
|
||||
}
|
||||
|
||||
/// Minimal relay chain node representation
|
||||
pub struct NewMinimalNode {
|
||||
/// Task manager running all tasks for the minimal node
|
||||
pub task_manager: TaskManager,
|
||||
/// Overseer handle to interact with subsystems
|
||||
pub overseer_handle: Handle,
|
||||
/// Network service
|
||||
pub network_service: Arc<dyn NetworkService>,
|
||||
/// Teyrchain bootnode request-response protocol receiver
|
||||
pub paranode_rx: async_channel::Receiver<IncomingRequest>,
|
||||
}
|
||||
|
||||
/// Glues together the [`Overseer`] and `BlockchainEvents` by forwarding
|
||||
/// import and finality notifications into the [`OverseerHandle`].
|
||||
async fn forward_collator_events(
|
||||
client: Arc<BlockChainRpcClient>,
|
||||
mut handle: Handle,
|
||||
) -> Result<(), RelayChainError> {
|
||||
let mut finality = client.finality_notification_stream().await?.fuse();
|
||||
let mut imports = client.import_notification_stream().await?.fuse();
|
||||
// Collators do no need to pin any specific blocks
|
||||
let (dummy_sink, _) = tracing_unbounded("does-not-matter", 42);
|
||||
let dummy_unpin_handle = UnpinHandle::new(Default::default(), dummy_sink);
|
||||
|
||||
loop {
|
||||
select! {
|
||||
f = finality.next() => {
|
||||
match f {
|
||||
Some(header) => {
|
||||
let hash = header.hash();
|
||||
tracing::info!(
|
||||
target: "minimal-pezkuwi-node",
|
||||
"Received finalized block via RPC: #{} ({} -> {})",
|
||||
header.number,
|
||||
header.parent_hash,
|
||||
hash,
|
||||
);
|
||||
let unpin_handle = dummy_unpin_handle.clone();
|
||||
let block_info = BlockInfo { hash, parent_hash: header.parent_hash, number: header.number, unpin_handle };
|
||||
handle.block_finalized(block_info).await;
|
||||
}
|
||||
None => return Err(RelayChainError::GenericError("Relay chain finality stream ended.".to_string())),
|
||||
}
|
||||
},
|
||||
i = imports.next() => {
|
||||
match i {
|
||||
Some(header) => {
|
||||
let hash = header.hash();
|
||||
tracing::info!(
|
||||
target: "minimal-pezkuwi-node",
|
||||
"Received imported block via RPC: #{} ({} -> {})",
|
||||
header.number,
|
||||
header.parent_hash,
|
||||
hash,
|
||||
);
|
||||
let unpin_handle = dummy_unpin_handle.clone();
|
||||
let block_info = BlockInfo { hash, parent_hash: header.parent_hash, number: header.number, unpin_handle };
|
||||
handle.block_imported(block_info).await;
|
||||
}
|
||||
None => return Err(RelayChainError::GenericError("Relay chain import stream ended.".to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezcumulus.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// Pezcumulus 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.
|
||||
|
||||
// Pezcumulus 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 Pezcumulus. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use collator_overseer::NewMinimalNode;
|
||||
|
||||
use cumulus_client_bootnodes::bootnode_request_response_config;
|
||||
use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface, RelayChainResult};
|
||||
use cumulus_relay_chain_rpc_interface::{RelayChainRpcClient, RelayChainRpcInterface, Url};
|
||||
use network::build_collator_network;
|
||||
use pezkuwi_network_bridge::{peer_sets_info, IsAuthority};
|
||||
use pezkuwi_node_network_protocol::{
|
||||
peer_set::{PeerSet, PeerSetProtocolNames},
|
||||
request_response::{
|
||||
v1, v2, IncomingRequest, IncomingRequestReceiver, Protocol, ReqProtocolNames,
|
||||
},
|
||||
};
|
||||
|
||||
use pezkuwi_core_primitives::{Block as RelayBlock, Hash as RelayHash};
|
||||
use pezkuwi_node_subsystem_util::metrics::prometheus::Registry;
|
||||
use pezkuwi_primitives::CollatorPair;
|
||||
use pezkuwi_service::{overseer::OverseerGenArgs, IsTeyrchainNode};
|
||||
|
||||
use pezsc_authority_discovery::Service as AuthorityDiscoveryService;
|
||||
use pezsc_network::{
|
||||
config::FullNetworkConfiguration, request_responses::IncomingRequest as GenericIncomingRequest,
|
||||
service::traits::NetworkService, Event, NetworkBackend, NetworkEventStream,
|
||||
};
|
||||
use pezsc_service::{config::PrometheusConfig, Configuration, TaskManager};
|
||||
use pezsp_runtime::{app_crypto::Pair, traits::Block as BlockT};
|
||||
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use std::sync::Arc;
|
||||
|
||||
mod blockchain_rpc_client;
|
||||
mod collator_overseer;
|
||||
mod network;
|
||||
|
||||
pub use blockchain_rpc_client::BlockChainRpcClient;
|
||||
|
||||
const LOG_TARGET: &str = "minimal-relaychain-node";
|
||||
|
||||
fn build_authority_discovery_service<Block: BlockT>(
|
||||
task_manager: &TaskManager,
|
||||
client: Arc<BlockChainRpcClient>,
|
||||
config: &Configuration,
|
||||
network: Arc<dyn NetworkService>,
|
||||
prometheus_registry: Option<Registry>,
|
||||
) -> AuthorityDiscoveryService {
|
||||
let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht;
|
||||
let auth_disc_public_addresses = config.network.public_addresses.clone();
|
||||
let authority_discovery_role = pezsc_authority_discovery::Role::Discover;
|
||||
let dht_event_stream = network.event_stream("authority-discovery").filter_map(|e| async move {
|
||||
match e {
|
||||
Event::Dht(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
});
|
||||
let net_config_path = config.network.net_config_path.clone();
|
||||
let (worker, service) = pezsc_authority_discovery::new_worker_and_service_with_config(
|
||||
pezsc_authority_discovery::WorkerConfig {
|
||||
publish_non_global_ips: auth_disc_publish_non_global_ips,
|
||||
public_addresses: auth_disc_public_addresses,
|
||||
// Require that authority discovery records are signed.
|
||||
strict_record_validation: true,
|
||||
persisted_cache_directory: net_config_path,
|
||||
..Default::default()
|
||||
},
|
||||
client,
|
||||
Arc::new(network.clone()),
|
||||
Box::pin(dht_event_stream),
|
||||
authority_discovery_role,
|
||||
prometheus_registry,
|
||||
task_manager.spawn_handle(),
|
||||
);
|
||||
|
||||
task_manager.spawn_handle().spawn(
|
||||
"authority-discovery-worker",
|
||||
Some("authority-discovery"),
|
||||
worker.run(),
|
||||
);
|
||||
service
|
||||
}
|
||||
|
||||
async fn build_interface(
|
||||
pezkuwi_config: Configuration,
|
||||
task_manager: &mut TaskManager,
|
||||
client: RelayChainRpcClient,
|
||||
) -> RelayChainResult<(
|
||||
Arc<dyn RelayChainInterface + 'static>,
|
||||
Option<CollatorPair>,
|
||||
Arc<dyn NetworkService>,
|
||||
async_channel::Receiver<GenericIncomingRequest>,
|
||||
)> {
|
||||
let collator_pair = CollatorPair::generate().0;
|
||||
let blockchain_rpc_client = Arc::new(BlockChainRpcClient::new(client.clone()));
|
||||
let collator_node = match pezkuwi_config.network.network_backend {
|
||||
pezsc_network::config::NetworkBackendType::Libp2p =>
|
||||
new_minimal_relay_chain::<RelayBlock, pezsc_network::NetworkWorker<RelayBlock, RelayHash>>(
|
||||
pezkuwi_config,
|
||||
collator_pair.clone(),
|
||||
blockchain_rpc_client,
|
||||
)
|
||||
.await?,
|
||||
pezsc_network::config::NetworkBackendType::Litep2p =>
|
||||
new_minimal_relay_chain::<RelayBlock, pezsc_network::Litep2pNetworkBackend>(
|
||||
pezkuwi_config,
|
||||
collator_pair.clone(),
|
||||
blockchain_rpc_client,
|
||||
)
|
||||
.await?,
|
||||
};
|
||||
task_manager.add_child(collator_node.task_manager);
|
||||
Ok((
|
||||
Arc::new(RelayChainRpcInterface::new(client, collator_node.overseer_handle)),
|
||||
Some(collator_pair),
|
||||
collator_node.network_service,
|
||||
collator_node.paranode_rx,
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn build_minimal_relay_chain_node_with_rpc(
|
||||
relay_chain_config: Configuration,
|
||||
teyrchain_prometheus_registry: Option<&Registry>,
|
||||
task_manager: &mut TaskManager,
|
||||
relay_chain_url: Vec<Url>,
|
||||
) -> RelayChainResult<(
|
||||
Arc<dyn RelayChainInterface + 'static>,
|
||||
Option<CollatorPair>,
|
||||
Arc<dyn NetworkService>,
|
||||
async_channel::Receiver<GenericIncomingRequest>,
|
||||
)> {
|
||||
let client = cumulus_relay_chain_rpc_interface::create_client_and_start_worker(
|
||||
relay_chain_url,
|
||||
task_manager,
|
||||
teyrchain_prometheus_registry,
|
||||
)
|
||||
.await?;
|
||||
|
||||
build_interface(relay_chain_config, task_manager, client).await
|
||||
}
|
||||
|
||||
/// Builds a minimal relay chain node. Chain data is fetched
|
||||
/// via [`BlockChainRpcClient`] and fed into the overseer and its subsystems.
|
||||
///
|
||||
/// Instead of spawning all subsystems, this minimal node will only spawn subsystems
|
||||
/// required to collate:
|
||||
/// - AvailabilityRecovery
|
||||
/// - CollationGeneration
|
||||
/// - CollatorProtocol
|
||||
/// - NetworkBridgeRx
|
||||
/// - NetworkBridgeTx
|
||||
/// - RuntimeApi
|
||||
#[pezsc_tracing::logging::prefix_logs_with("Relaychain")]
|
||||
async fn new_minimal_relay_chain<Block: BlockT, Network: NetworkBackend<RelayBlock, RelayHash>>(
|
||||
config: Configuration,
|
||||
collator_pair: CollatorPair,
|
||||
relay_chain_rpc_client: Arc<BlockChainRpcClient>,
|
||||
) -> Result<NewMinimalNode, RelayChainError> {
|
||||
let role = config.role;
|
||||
let mut net_config = pezsc_network::config::FullNetworkConfiguration::<_, _, Network>::new(
|
||||
&config.network,
|
||||
config.prometheus_config.as_ref().map(|cfg| cfg.registry.clone()),
|
||||
);
|
||||
let metrics = Network::register_notification_metrics(
|
||||
config.prometheus_config.as_ref().map(|cfg| &cfg.registry),
|
||||
);
|
||||
let peer_store_handle = net_config.peer_store_handle();
|
||||
|
||||
let prometheus_registry = config.prometheus_registry();
|
||||
let task_manager = TaskManager::new(config.tokio_handle.clone(), prometheus_registry)?;
|
||||
|
||||
if let Some(PrometheusConfig { port, registry }) = config.prometheus_config.clone() {
|
||||
task_manager.spawn_handle().spawn(
|
||||
"prometheus-endpoint",
|
||||
None,
|
||||
prometheus_endpoint::init_prometheus(port, registry).map(drop),
|
||||
);
|
||||
}
|
||||
|
||||
let genesis_hash = relay_chain_rpc_client.block_get_hash(Some(0)).await?.unwrap_or_default();
|
||||
let peerset_protocol_names =
|
||||
PeerSetProtocolNames::new(genesis_hash, config.chain_spec.fork_id());
|
||||
let is_authority = if role.is_authority() { IsAuthority::Yes } else { IsAuthority::No };
|
||||
let notification_services = peer_sets_info::<_, Network>(
|
||||
is_authority,
|
||||
&peerset_protocol_names,
|
||||
metrics.clone(),
|
||||
Arc::clone(&peer_store_handle),
|
||||
)
|
||||
.into_iter()
|
||||
.map(|(config, (peerset, service))| {
|
||||
net_config.add_notification_protocol(config);
|
||||
(peerset, service)
|
||||
})
|
||||
.collect::<std::collections::HashMap<PeerSet, Box<dyn pezsc_network::NotificationService>>>();
|
||||
|
||||
let request_protocol_names = ReqProtocolNames::new(genesis_hash, config.chain_spec.fork_id());
|
||||
let (collation_req_v1_receiver, collation_req_v2_receiver, available_data_req_receiver) =
|
||||
build_request_response_protocol_receivers(&request_protocol_names, &mut net_config);
|
||||
|
||||
let (cfg, paranode_rx) = bootnode_request_response_config::<_, _, Network>(
|
||||
genesis_hash,
|
||||
config.chain_spec.fork_id(),
|
||||
);
|
||||
net_config.add_request_response_protocol(cfg);
|
||||
|
||||
let best_header = relay_chain_rpc_client
|
||||
.chain_get_header(None)
|
||||
.await?
|
||||
.ok_or_else(|| RelayChainError::RpcCallError("Unable to fetch best header".to_string()))?;
|
||||
let (network, sync_service) = build_collator_network::<Network>(
|
||||
&config,
|
||||
net_config,
|
||||
task_manager.spawn_handle(),
|
||||
genesis_hash,
|
||||
best_header,
|
||||
metrics,
|
||||
)
|
||||
.map_err(|e| RelayChainError::Application(Box::new(e)))?;
|
||||
|
||||
let authority_discovery_service = build_authority_discovery_service::<Block>(
|
||||
&task_manager,
|
||||
relay_chain_rpc_client.clone(),
|
||||
&config,
|
||||
network.clone(),
|
||||
prometheus_registry.cloned(),
|
||||
);
|
||||
|
||||
let overseer_args = OverseerGenArgs {
|
||||
runtime_client: relay_chain_rpc_client.clone(),
|
||||
network_service: network.clone(),
|
||||
sync_service,
|
||||
authority_discovery_service,
|
||||
collation_req_v1_receiver,
|
||||
collation_req_v2_receiver,
|
||||
available_data_req_receiver,
|
||||
registry: prometheus_registry,
|
||||
spawner: task_manager.spawn_handle(),
|
||||
is_teyrchain_node: IsTeyrchainNode::Collator(collator_pair),
|
||||
overseer_message_channel_capacity_override: None,
|
||||
req_protocol_names: request_protocol_names,
|
||||
peerset_protocol_names,
|
||||
notification_services,
|
||||
};
|
||||
|
||||
let overseer_handle =
|
||||
collator_overseer::spawn_overseer(overseer_args, &task_manager, relay_chain_rpc_client)?;
|
||||
|
||||
Ok(NewMinimalNode { task_manager, overseer_handle, network_service: network, paranode_rx })
|
||||
}
|
||||
|
||||
fn build_request_response_protocol_receivers<
|
||||
Block: BlockT,
|
||||
Network: NetworkBackend<Block, <Block as BlockT>::Hash>,
|
||||
>(
|
||||
request_protocol_names: &ReqProtocolNames,
|
||||
config: &mut FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Network>,
|
||||
) -> (
|
||||
IncomingRequestReceiver<v1::CollationFetchingRequest>,
|
||||
IncomingRequestReceiver<v2::CollationFetchingRequest>,
|
||||
IncomingRequestReceiver<v1::AvailableDataFetchingRequest>,
|
||||
) {
|
||||
let (collation_req_v1_receiver, cfg) =
|
||||
IncomingRequest::get_config_receiver::<_, Network>(request_protocol_names);
|
||||
config.add_request_response_protocol(cfg);
|
||||
let (collation_req_v2_receiver, cfg) =
|
||||
IncomingRequest::get_config_receiver::<_, Network>(request_protocol_names);
|
||||
config.add_request_response_protocol(cfg);
|
||||
let (available_data_req_receiver, cfg) =
|
||||
IncomingRequest::get_config_receiver::<_, Network>(request_protocol_names);
|
||||
config.add_request_response_protocol(cfg);
|
||||
let cfg =
|
||||
Protocol::ChunkFetchingV1.get_outbound_only_config::<_, Network>(request_protocol_names);
|
||||
config.add_request_response_protocol(cfg);
|
||||
let cfg =
|
||||
Protocol::ChunkFetchingV2.get_outbound_only_config::<_, Network>(request_protocol_names);
|
||||
config.add_request_response_protocol(cfg);
|
||||
(collation_req_v1_receiver, collation_req_v2_receiver, available_data_req_receiver)
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezcumulus.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// Pezcumulus 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.
|
||||
|
||||
// Pezcumulus 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 Pezcumulus. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use pezkuwi_core_primitives::{Block, Hash, Header};
|
||||
use pezsp_runtime::traits::NumberFor;
|
||||
|
||||
use pezsc_network::{
|
||||
config::{
|
||||
NetworkConfiguration, NonReservedPeerMode, NotificationHandshake, PeerStore, ProtocolId,
|
||||
SetConfig,
|
||||
},
|
||||
peer_store::PeerStoreProvider,
|
||||
service::traits::NetworkService,
|
||||
NotificationMetrics,
|
||||
};
|
||||
|
||||
use pezsc_network::{config::FullNetworkConfiguration, NetworkBackend, NotificationService};
|
||||
use pezsc_network_common::{role::Roles, sync::message::BlockAnnouncesHandshake};
|
||||
use pezsc_service::{error::Error, Configuration, SpawnTaskHandle};
|
||||
|
||||
use std::{iter, sync::Arc};
|
||||
|
||||
/// Build the network service, the network status sinks and an RPC sender.
|
||||
pub(crate) fn build_collator_network<Network: NetworkBackend<Block, Hash>>(
|
||||
config: &Configuration,
|
||||
mut network_config: FullNetworkConfiguration<Block, Hash, Network>,
|
||||
spawn_handle: SpawnTaskHandle,
|
||||
genesis_hash: Hash,
|
||||
best_header: Header,
|
||||
notification_metrics: NotificationMetrics,
|
||||
) -> Result<(Arc<dyn NetworkService>, Arc<dyn pezsp_consensus::SyncOracle + Send + Sync>), Error> {
|
||||
let protocol_id = config.protocol_id();
|
||||
let (block_announce_config, notification_service) = get_block_announce_proto_config::<Network>(
|
||||
protocol_id.clone(),
|
||||
&None,
|
||||
Roles::from(&config.role),
|
||||
best_header.number,
|
||||
best_header.hash(),
|
||||
genesis_hash,
|
||||
notification_metrics.clone(),
|
||||
network_config.peer_store_handle(),
|
||||
);
|
||||
|
||||
// Since this node has no syncing, we do not want light-clients to connect to it.
|
||||
// Here we set any potential light-client slots to 0.
|
||||
adjust_network_config_light_in_peers(&mut network_config.network_config);
|
||||
|
||||
let peer_store = network_config.take_peer_store();
|
||||
spawn_handle.spawn("peer-store", Some("networking"), peer_store.run());
|
||||
|
||||
let network_params = pezsc_network::config::Params::<Block, Hash, Network> {
|
||||
role: config.role,
|
||||
executor: {
|
||||
let spawn_handle = Clone::clone(&spawn_handle);
|
||||
Box::new(move |fut| {
|
||||
spawn_handle.spawn("libp2p-node", Some("networking"), fut);
|
||||
})
|
||||
},
|
||||
fork_id: None,
|
||||
network_config,
|
||||
genesis_hash,
|
||||
protocol_id,
|
||||
metrics_registry: config.prometheus_config.as_ref().map(|config| config.registry.clone()),
|
||||
block_announce_config,
|
||||
bitswap_config: None,
|
||||
notification_metrics,
|
||||
};
|
||||
|
||||
let network_worker = Network::new(network_params)?;
|
||||
let network_service = network_worker.network_service();
|
||||
|
||||
// The network worker is responsible for gathering all network messages and processing
|
||||
// them. This is quite a heavy task, and at the time of the writing of this comment it
|
||||
// frequently happens that this future takes several seconds or in some situations
|
||||
// even more than a minute until it has processed its entire queue. This is clearly an
|
||||
// issue, and ideally we would like to fix the network future to take as little time as
|
||||
// possible, but we also take the extra harm-prevention measure to execute the networking
|
||||
// future using `spawn_blocking`.
|
||||
spawn_handle.spawn_blocking("network-worker", Some("networking"), async move {
|
||||
// The notification service must be kept alive to allow litep2p to handle
|
||||
// requests under the hood. It has been noted that without the notification
|
||||
// service of the `/block-announces/1` protocol, collators are not advertised
|
||||
// and their produced blocks do not propagate:
|
||||
// https://github.com/pezkuwichain/pezkuwi-sdk/issues/154
|
||||
//
|
||||
// This is because the full nodes on the relay chain will attempt to establish
|
||||
// a connection to the minimal relay chain. By dropping the notification service,
|
||||
// litep2p would terminate the background task which handles the `/block-announces/1`
|
||||
// notification protocol. The downstream effect of this is that the full node
|
||||
// would ban and disconnect the the minimal relay chain node.
|
||||
let _notification_service = notification_service;
|
||||
network_worker.run().await;
|
||||
});
|
||||
|
||||
Ok((network_service, Arc::new(SyncOracle {})))
|
||||
}
|
||||
|
||||
fn adjust_network_config_light_in_peers(config: &mut NetworkConfiguration) {
|
||||
let light_client_in_peers = (config.default_peers_set.in_peers +
|
||||
config.default_peers_set.out_peers)
|
||||
.saturating_sub(config.default_peers_set_num_full);
|
||||
if light_client_in_peers > 0 {
|
||||
tracing::debug!(target: crate::LOG_TARGET, "Detected {light_client_in_peers} peer slots for light clients. Since this minimal node does support\
|
||||
neither syncing nor light-client request/response, we are setting them to 0.");
|
||||
}
|
||||
config.default_peers_set.in_peers =
|
||||
config.default_peers_set.in_peers.saturating_sub(light_client_in_peers);
|
||||
}
|
||||
|
||||
struct SyncOracle;
|
||||
|
||||
impl pezsp_consensus::SyncOracle for SyncOracle {
|
||||
fn is_major_syncing(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn is_offline(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn get_block_announce_proto_config<Network: NetworkBackend<Block, Hash>>(
|
||||
protocol_id: ProtocolId,
|
||||
fork_id: &Option<String>,
|
||||
roles: Roles,
|
||||
best_number: NumberFor<Block>,
|
||||
best_hash: Hash,
|
||||
genesis_hash: Hash,
|
||||
metrics: NotificationMetrics,
|
||||
peer_store_handle: Arc<dyn PeerStoreProvider>,
|
||||
) -> (Network::NotificationProtocolConfig, Box<dyn NotificationService>) {
|
||||
let block_announces_protocol = {
|
||||
let genesis_hash = genesis_hash.as_ref();
|
||||
if let Some(ref fork_id) = fork_id {
|
||||
format!("/{}/{}/block-announces/1", array_bytes::bytes2hex("", genesis_hash), fork_id)
|
||||
} else {
|
||||
format!("/{}/block-announces/1", array_bytes::bytes2hex("", genesis_hash))
|
||||
}
|
||||
};
|
||||
|
||||
Network::notification_config(
|
||||
block_announces_protocol.into(),
|
||||
iter::once(format!("/{}/block-announces/1", protocol_id.as_ref()).into()).collect(),
|
||||
1024 * 1024,
|
||||
Some(NotificationHandshake::new(BlockAnnouncesHandshake::<Block>::build(
|
||||
roles,
|
||||
best_number,
|
||||
best_hash,
|
||||
genesis_hash,
|
||||
))),
|
||||
// NOTE: `set_config` will be ignored by `protocol.rs` as the block announcement
|
||||
// protocol is still hardcoded into the peerset.
|
||||
SetConfig {
|
||||
in_peers: 0,
|
||||
out_peers: 0,
|
||||
reserved_nodes: Vec::new(),
|
||||
non_reserved_mode: NonReservedPeerMode::Deny,
|
||||
},
|
||||
metrics,
|
||||
peer_store_handle,
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user