Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define SubstrateBeefy RPC client #1615

Merged
merged 1 commit into from
Oct 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions relays/client-substrate/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
use crate::{
chain::{Chain, ChainWithBalances},
rpc::{
SubstrateAuthorClient, SubstrateChainClient, SubstrateFrameSystemClient,
SubstrateGrandpaClient, SubstrateStateClient, SubstrateSystemClient,
SubstrateAuthorClient, SubstrateChainClient, SubstrateFinalityClient,
SubstrateFrameSystemClient, SubstrateStateClient, SubstrateSystemClient,
SubstrateTransactionPaymentClient,
},
transaction_stall_timeout, ConnectionParams, Error, HashOf, HeaderIdOf, Result, SignParam,
Expand Down Expand Up @@ -642,11 +642,13 @@ impl<C: Chain> Client<C> {
.await
}

/// Return new GRANDPA justifications stream.
pub async fn subscribe_grandpa_justifications(&self) -> Result<Subscription<Bytes>> {
/// Return new finality justifications stream.
pub async fn subscribe_finality_justifications<FC: SubstrateFinalityClient<C>>(
&self,
) -> Result<Subscription<Bytes>> {
let subscription = self
.jsonrpsee_execute(move |client| async move {
Ok(SubstrateGrandpaClient::<C>::subscribe_justifications(&*client).await?)
Ok(FC::subscribe_justifications(&client).await?)
})
.await?;
let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY);
Expand Down
1 change: 1 addition & 0 deletions relays/client-substrate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub use crate::{
},
client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription},
error::{Error, Result},
rpc::{SubstrateBeefyFinalityClient, SubstrateFinalityClient, SubstrateGrandpaFinalityClient},
sync_header::SyncHeader,
transaction_tracker::TransactionTracker,
};
Expand Down
47 changes: 44 additions & 3 deletions relays/client-substrate/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,15 @@

//! The most generic Substrate node RPC interface.

use crate::{Chain, TransactionStatusOf};
use async_trait::async_trait;

use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use crate::{Chain, ChainWithGrandpa, TransactionStatusOf};

use jsonrpsee::{
core::{client::Subscription, RpcResult},
proc_macros::rpc,
ws_client::WsClient,
};
use pallet_transaction_payment_rpc_runtime_api::FeeDetails;
use sc_rpc_api::{state::ReadProof, system::Health};
use sp_core::{
Expand Down Expand Up @@ -100,14 +106,49 @@ pub(crate) trait SubstrateState<C> {
) -> RpcResult<ReadProof<C::Hash>>;
}

/// RPC methods that we are using for a certain finality gadget.
#[async_trait]
pub trait SubstrateFinalityClient<C: Chain> {
/// Subscribe to finality justifications.
async fn subscribe_justifications(client: &WsClient) -> RpcResult<Subscription<Bytes>>;
}

/// RPC methods of Substrate `grandpa` namespace, that we are using.
#[rpc(client, client_bounds(C: Chain), namespace = "grandpa")]
#[rpc(client, client_bounds(C: ChainWithGrandpa), namespace = "grandpa")]
pub(crate) trait SubstrateGrandpa<C> {
/// Subscribe to GRANDPA justifications.
#[subscription(name = "subscribeJustifications", unsubscribe = "unsubscribeJustifications", item = Bytes)]
fn subscribe_justifications(&self);
}

/// RPC finality methods of Substrate `grandpa` namespace, that we are using.
pub struct SubstrateGrandpaFinalityClient;
#[async_trait]
impl<C: ChainWithGrandpa> SubstrateFinalityClient<C> for SubstrateGrandpaFinalityClient {
async fn subscribe_justifications(client: &WsClient) -> RpcResult<Subscription<Bytes>> {
SubstrateGrandpaClient::<C>::subscribe_justifications(client).await
}
}

// TODO: Use `ChainWithBeefy` instead of `Chain` after #1606 is merged
/// RPC methods of Substrate `beefy` namespace, that we are using.
#[rpc(client, client_bounds(C: Chain), namespace = "beefy")]
pub(crate) trait SubstrateBeefy<C> {
/// Subscribe to BEEFY justifications.
#[subscription(name = "subscribeJustifications", unsubscribe = "unsubscribeJustifications", item = Bytes)]
fn subscribe_justifications(&self);
}

/// RPC finality methods of Substrate `beefy` namespace, that we are using.
pub struct SubstrateBeefyFinalityClient;
// TODO: Use `ChainWithBeefy` instead of `Chain` after #1606 is merged
#[async_trait]
impl<C: Chain> SubstrateFinalityClient<C> for SubstrateBeefyFinalityClient {
async fn subscribe_justifications(client: &WsClient) -> RpcResult<Subscription<Bytes>> {
SubstrateBeefyClient::<C>::subscribe_justifications(client).await
}
}

/// RPC methods of Substrate `system` frame pallet, that we are using.
#[rpc(client, client_bounds(C: Chain), namespace = "system")]
pub(crate) trait SubstrateFrameSystem<C> {
Expand Down
18 changes: 9 additions & 9 deletions relays/lib-substrate-relay/src/finality/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,20 @@ use finality_grandpa::voter_set::VoterSet;
use num_traits::{One, Zero};
use relay_substrate_client::{
BlockNumberOf, Chain, ChainWithGrandpa, Client, Error as SubstrateError, HashOf, HeaderOf,
Subscription,
Subscription, SubstrateFinalityClient, SubstrateGrandpaFinalityClient,
};
use sp_core::{storage::StorageKey, Bytes};
use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet;
use sp_runtime::{traits::Header, ConsensusEngineId};
use std::marker::PhantomData;

/// Finality enfine, used by the Substrate chain.
/// Finality engine, used by the Substrate chain.
#[async_trait]
pub trait Engine<C: Chain>: Send {
/// Unique consensus engine identifier.
const ID: ConsensusEngineId;
/// Type of Finality RPC client used by this engine.
type FinalityClient: SubstrateFinalityClient<C>;
/// Type of finality proofs, used by consensus engine.
type FinalityProof: FinalityProof<BlockNumberOf<C>> + Decode + Encode;
/// Type of bridge pallet initialization data.
Expand All @@ -57,7 +59,9 @@ pub trait Engine<C: Chain>: Send {
/// Note that we don't care about type of the value - just if it present or not.
fn is_initialized_key() -> StorageKey;
/// A method to subscribe to encoded finality proofs, given source client.
async fn finality_proofs(client: Client<C>) -> Result<Subscription<Bytes>, SubstrateError>;
async fn finality_proofs(client: &Client<C>) -> Result<Subscription<Bytes>, SubstrateError> {
client.subscribe_finality_justifications::<Self::FinalityClient>().await
}
/// Prepare initialization data for the finality bridge pallet.
async fn prepare_initialization_data(
client: Client<C>,
Expand Down Expand Up @@ -117,6 +121,7 @@ impl<C: ChainWithGrandpa> Grandpa<C> {
#[async_trait]
impl<C: ChainWithGrandpa> Engine<C> for Grandpa<C> {
const ID: ConsensusEngineId = sp_finality_grandpa::GRANDPA_ENGINE_ID;
type FinalityClient = SubstrateGrandpaFinalityClient;
type FinalityProof = GrandpaJustification<HeaderOf<C>>;
type InitializationData = bp_header_chain::InitializationData<C::Header>;
type OperatingMode = BasicOperatingMode;
Expand All @@ -129,10 +134,6 @@ impl<C: ChainWithGrandpa> Engine<C> for Grandpa<C> {
bp_header_chain::storage_keys::best_finalized_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME)
}

async fn finality_proofs(client: Client<C>) -> Result<Subscription<Bytes>, SubstrateError> {
client.subscribe_grandpa_justifications().await
}

/// Prepare initialization data for the GRANDPA verifier pallet.
async fn prepare_initialization_data(
source_client: Client<C>,
Expand All @@ -144,8 +145,7 @@ impl<C: ChainWithGrandpa> Engine<C> for Grandpa<C> {
// But now there are problems with this approach - `CurrentSetId` may return invalid value.
// So here we're waiting for the next justification, read the authorities set and then try
// to figure out the set id with bruteforce.
let justifications = source_client
.subscribe_grandpa_justifications()
let justifications = Self::finality_proofs(&source_client)
.await
.map_err(|err| Error::Subscribe(C::NAME, err))?;
// Read next justification - the header that it finalizes will be used as initial header.
Expand Down
2 changes: 1 addition & 1 deletion relays/lib-substrate-relay/src/finality/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl<P: SubstrateFinalitySyncPipeline> SourceClient<FinalitySyncPipelineAdapter<

async fn finality_proofs(&self) -> Result<Self::FinalityProofsStream, Error> {
Ok(unfold(
P::FinalityEngine::finality_proofs(self.client.clone()).await?,
P::FinalityEngine::finality_proofs(&self.client).await?,
move |subscription| async move {
loop {
let log_error = |err| {
Expand Down