Skip to content
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ sc-client-db = { version = "0.54.0", default-features = false }
sc-consensus = { version = "0.57.0" }
sc-consensus-aura = { version = "0.58.0" }
sc-consensus-grandpa = { version = "0.43.0" }
sc-consensus-grandpa-rpc = { version = "0.44.0" }
sc-consensus-manual-seal = { version = "0.59.0" }
sc-executor = { version = "0.50.0" }
sc-keystore = { version = "42.0.0" }
Expand Down
1 change: 1 addition & 0 deletions template/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ sc-client-api = { workspace = true }
sc-consensus = { workspace = true }
sc-consensus-aura = { workspace = true }
sc-consensus-grandpa = { workspace = true }
sc-consensus-grandpa-rpc = { workspace = true }
sc-consensus-manual-seal = { workspace = true }
sc-executor = { workspace = true }
sc-network = { workspace = true }
Expand Down
40 changes: 39 additions & 1 deletion template/node/src/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::H256;
use sp_inherents::CreateInherentDataProviders;
use sp_keystore::Keystore;
use sp_runtime::traits::Block as BlockT;
use sp_runtime::traits::{Block as BlockT, NumberFor};
// Runtime
use orbinum_runtime::{AccountId, Balance, Hash, Nonce};

Expand All @@ -30,6 +30,29 @@ pub use self::eth::{create_eth, EthDeps, LogsJournalConfig};
use self::relayer_author::{RelayerAuthor, RelayerAuthorApiServer};
use self::storage_override::EeSuffixStorageOverride;

/// GRANDPA-specific dependencies.
///
/// Wiring these is what lets a chain be verified from the outside: Hyperbridge's relayer
/// builds Orbinum finality proofs through `grandpa_proveFinality`, and without the RPC it
/// reports the method as missing rather than as unauthorised.
///
/// Everything here serves finality data for blocks that are already final — public by
/// definition, and independently verifiable against the authority set. No keys, no
/// private state. `sc-consensus-grandpa-rpc` marks none of the three methods `unsafe`,
/// so they are served under the `--rpc-methods Safe` the public endpoint runs with.
pub struct GrandpaDeps<B: BlockT, BE> {
/// Shared with the voter, not a fresh empty one: a detached state makes
/// `grandpa_roundState` answer with zeroed rounds instead of failing, which reads as
/// "working" while telling the caller nothing.
pub shared_voter_state: sc_consensus_grandpa::SharedVoterState,
/// Current authority set, for `grandpa_roundState`.
pub shared_authority_set: sc_consensus_grandpa::SharedAuthoritySet<B::Hash, NumberFor<B>>,
/// Justification notifications, for `grandpa_subscribeJustifications`.
pub justification_stream: sc_consensus_grandpa::GrandpaJustificationStream<B>,
/// Serves `grandpa_proveFinality`.
pub finality_provider: Arc<sc_consensus_grandpa::FinalityProofProvider<BE, B>>,
}

/// Full client dependencies.
pub struct FullDeps<B: BlockT, C, P, BE, CT, CIDP> {
/// The client instance to use.
Expand All @@ -45,6 +68,8 @@ pub struct FullDeps<B: BlockT, C, P, BE, CT, CIDP> {
pub keystore: Arc<dyn Keystore>,
/// Ethereum-compatibility specific dependencies.
pub eth: EthDeps<B, C, P, CT, CIDP>,
/// GRANDPA finality RPC dependencies.
pub grandpa: GrandpaDeps<B, BE>,
}

pub struct DefaultEthConfig<C, BE>(std::marker::PhantomData<(C, BE)>);
Expand Down Expand Up @@ -94,11 +119,13 @@ where
u64: From<<<B as BlockT>::Header as sp_runtime::traits::Header>::Number>,
CIDP: CreateInherentDataProviders<B, ()> + Send + 'static,
CT: fp_rpc::ConvertTransaction<<B as BlockT>::Extrinsic> + Send + Sync + 'static,
NumberFor<B>: sc_consensus_grandpa::BlockNumberOps,
{
use pallet_ismp_rpc::{IsmpApiServer, IsmpRpcHandler};
use pallet_relayer_rpc::{Relayer, RelayerApiServer};
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer};
use pallet_zk_verifier_rpc::{ZkVerifier, ZkVerifierApiServer};
use sc_consensus_grandpa_rpc::{Grandpa, GrandpaApiServer};
use sc_consensus_manual_seal::rpc::{ManualSeal, ManualSealApiServer};
use substrate_frame_rpc_system::{System, SystemApiServer};

Expand All @@ -113,9 +140,20 @@ where
command_sink,
keystore,
eth,
grandpa,
} = deps;

io.merge(System::new(client.clone(), pool.clone()).into_rpc())?;
io.merge(
Grandpa::new(
subscription_task_executor.clone(),
grandpa.shared_authority_set,
grandpa.shared_voter_state,
grandpa.justification_stream,
grandpa.finality_provider,
)
.into_rpc(),
)?;
io.merge(TransactionPayment::new(client.clone()).into_rpc())?;
io.merge(ZkVerifier::new(client.clone()).into_rpc())?;
io.merge(Relayer::new(client.clone()).into_rpc())?;
Expand Down
24 changes: 23 additions & 1 deletion template/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,24 @@ where

let evm_key = crate::evm_relay_key::resolve(&config);

// GRANDPA pieces for the RPC, pulled out before `grandpa_link` is moved into the
// voter below. `shared_voter_state` is created here rather than at the voter so both
// sides hold the same one — a detached state leaves `grandpa_roundState` reporting
// zeroed rounds forever.
let shared_voter_state = sc_consensus_grandpa::SharedVoterState::empty();
let grandpa_shared_authority_set = grandpa_link.shared_authority_set().clone();
let grandpa_justification_stream = grandpa_link.justification_stream().clone();
let grandpa_finality_provider = sc_consensus_grandpa::FinalityProofProvider::new_for_service(
backend.clone(),
Some(grandpa_shared_authority_set.clone()),
);

let rpc_builder = {
let client = client.clone();
let shared_voter_state = shared_voter_state.clone();
let grandpa_shared_authority_set = grandpa_shared_authority_set.clone();
let grandpa_justification_stream = grandpa_justification_stream.clone();
let grandpa_finality_provider = grandpa_finality_provider.clone();
// Cloned before the closure takes ownership: the outer `backend` is still
// needed after this point (see the mapping-sync setup below).
let rpc_backend = backend.clone();
Expand Down Expand Up @@ -522,6 +538,12 @@ where
},
keystore: keystore.clone(),
eth: eth_deps,
grandpa: crate::rpc::GrandpaDeps {
shared_voter_state: shared_voter_state.clone(),
shared_authority_set: grandpa_shared_authority_set.clone(),
justification_stream: grandpa_justification_stream.clone(),
finality_provider: grandpa_finality_provider.clone(),
},
};
crate::rpc::create_full(
deps,
Expand Down Expand Up @@ -677,7 +699,7 @@ where
notification_service: grandpa_notification_service,
voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(),
prometheus_registry,
shared_voter_state: sc_consensus_grandpa::SharedVoterState::empty(),
shared_voter_state,
telemetry: telemetry.as_ref().map(|x| x.handle()),
offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool),
})?;
Expand Down
Loading