Skip to content

Commit fe890d3

Browse files
committed
Wire BEEFY into demo runtime/node
1 parent 6dce68f commit fe890d3

File tree

14 files changed

+1049
-408
lines changed

14 files changed

+1049
-408
lines changed

Cargo.lock

Lines changed: 532 additions & 302 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 79 additions & 73 deletions
Large diffs are not rendered by default.

demo/node/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ sp-consensus-aura = { workspace = true }
3838
sp-partner-chains-consensus-aura = { workspace = true }
3939
sp-consensus = { workspace = true }
4040
sc-consensus = { workspace = true }
41+
sc-consensus-beefy = { workspace = true }
42+
sc-consensus-beefy-rpc = { workspace = true }
43+
sp-consensus-beefy = { workspace = true }
4144
sc-consensus-grandpa = { workspace = true }
4245
sc-consensus-grandpa-rpc = { workspace = true }
4346
sp-consensus-grandpa = { workspace = true }

demo/node/src/chain_spec.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub fn pc_create_chain_spec(config: &CreateChainSpecConfig<SessionKeys>) -> serd
4343
system: partner_chains_demo_runtime::SystemConfig::default(),
4444
balances: partner_chains_demo_runtime::BalancesConfig::default(),
4545
aura: partner_chains_demo_runtime::AuraConfig::default(),
46+
beefy: partner_chains_demo_runtime::BeefyConfig::default(),
4647
grandpa: partner_chains_demo_runtime::GrandpaConfig::default(),
4748
sudo: partner_chains_demo_runtime::SudoConfig::default(),
4849
transaction_payment: Default::default(),

demo/node/src/rpc.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ use partner_chains_demo_runtime::{
1717
opaque::{Block, SessionKeys},
1818
};
1919
use partner_chains_demo_runtime::{BlockNumber, BlockProducerMetadataType, CrossChainPublic, Hash};
20+
use sc_consensus_beefy::communication::notification::{
21+
BeefyBestBlockStream, BeefyVersionedFinalityProofStream,
22+
};
23+
use sc_consensus_beefy_rpc::Beefy;
2024
use sc_consensus_grandpa::{
2125
FinalityProofProvider, GrandpaJustificationStream, SharedAuthoritySet, SharedVoterState,
2226
};
@@ -28,6 +32,7 @@ use sidechain_domain::mainchain_epoch::MainchainEpochConfig;
2832
use sp_api::{CallApiAt, ProvideRuntimeApi};
2933
use sp_block_builder::BlockBuilder;
3034
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
35+
use sp_consensus_beefy::AuthorityIdBound;
3136
use sp_session_validator_management_query::SessionValidatorManagementQuery;
3237
use sp_sidechain::GetEpochDurationApi;
3338
use std::sync::Arc;
@@ -47,23 +52,35 @@ pub struct GrandpaDeps<B> {
4752
pub finality_provider: Arc<FinalityProofProvider<B, Block>>,
4853
}
4954

55+
/// Dependencies for BEEFY
56+
pub struct BeefyDeps<AuthorityId: AuthorityIdBound> {
57+
/// Receives notifications about finality proof events from BEEFY.
58+
pub beefy_finality_proof_stream: BeefyVersionedFinalityProofStream<Block, AuthorityId>,
59+
/// Receives notifications about best block events from BEEFY.
60+
pub beefy_best_block_stream: BeefyBestBlockStream<Block>,
61+
/// Executor to drive the subscription manager in the BEEFY RPC handler.
62+
pub subscription_executor: sc_rpc::SubscriptionTaskExecutor,
63+
}
64+
5065
/// Full client dependencies.
51-
pub struct FullDeps<C, P, B, T> {
66+
pub struct FullDeps<C, P, B, T, AuthorityId: AuthorityIdBound> {
5267
/// The client instance to use.
5368
pub client: Arc<C>,
5469
/// Transaction pool instance.
5570
pub pool: Arc<P>,
5671
/// GRANDPA specific dependencies.
5772
pub grandpa: GrandpaDeps<B>,
73+
/// BEEFY specific dependencies.
74+
pub beefy: BeefyDeps<AuthorityId>,
5875
/// Data sources.
5976
pub data_sources: DataSources,
6077
/// Source of system time
6178
pub time_source: Arc<T>,
6279
}
6380

6481
/// Instantiate all full RPC extensions.
65-
pub fn create_full<C, P, B, T>(
66-
deps: FullDeps<C, P, B, T>,
82+
pub fn create_full<C, P, B, T, AuthorityId: AuthorityIdBound>(
83+
deps: FullDeps<C, P, B, T, AuthorityId>,
6784
) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
6885
where
6986
C: ProvideRuntimeApi<Block>,
@@ -93,10 +110,11 @@ where
93110
T: TimeSource + Send + Sync + 'static,
94111
{
95112
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer};
113+
use sc_consensus_beefy_rpc::BeefyApiServer;
96114
use substrate_frame_rpc_system::{System, SystemApiServer};
97115

98116
let mut module = RpcModule::new(());
99-
let FullDeps { client, pool, grandpa, data_sources, time_source } = deps;
117+
let FullDeps { client, pool, grandpa, beefy, data_sources, time_source } = deps;
100118

101119
module.merge(System::new(client.clone(), pool.clone()).into_rpc())?;
102120
module.merge(TransactionPayment::new(client.clone()).into_rpc())?;
@@ -137,6 +155,15 @@ where
137155
.into_rpc(),
138156
)?;
139157

158+
module.merge(
159+
Beefy::<Block, AuthorityId>::new(
160+
beefy.beefy_finality_proof_stream,
161+
beefy.beefy_best_block_stream,
162+
beefy.subscription_executor,
163+
)?
164+
.into_rpc(),
165+
)?;
166+
140167
// Extend this RPC with a custom API by using the following syntax.
141168
// `YourRpcStruct` should have a reference to a client, which is needed
142169
// to call into the runtime.

demo/node/src/service.rs

Lines changed: 113 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,25 @@
22
33
use crate::data_sources::DataSources;
44
use crate::inherent_data::{CreateInherentDataConfig, ProposalCIDP, VerifierCIDP};
5-
use crate::rpc::GrandpaDeps;
5+
use crate::rpc::{BeefyDeps, GrandpaDeps};
66
use authority_selection_inherents::AuthoritySelectionDataSource;
77
use partner_chains_data_source_metrics::{McFollowerMetrics, register_metrics_warn_errors};
88
use partner_chains_demo_runtime::{self, RuntimeApi, opaque::Block};
99
use sc_client_api::BlockBackend;
1010
use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams};
11+
use sc_consensus_beefy::{BeefyRPCLinks, BeefyVoterLinks};
1112
use sc_consensus_grandpa::SharedVoterState;
1213
pub use sc_executor::WasmExecutor;
1314
use sc_partner_chains_consensus_aura::import_queue as partner_chains_aura_import_queue;
15+
use sc_rpc::SubscriptionTaskExecutor;
1416
use sc_service::{Configuration, TaskManager, WarpSyncConfig, error::Error as ServiceError};
1517
use sc_telemetry::{Telemetry, TelemetryWorker};
1618
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
1719
use sidechain_domain::mainchain_epoch::MainchainEpochConfig;
1820
use sidechain_mc_hash::McHashInherentDigest;
1921
use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
22+
use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId;
23+
2024
use sp_partner_chains_consensus_aura::block_proposal::PartnerChainsProposerFactory;
2125
use sp_runtime::traits::Block as BlockT;
2226
use std::{sync::Arc, time::Duration};
@@ -76,6 +80,8 @@ pub fn new_partial(
7680
Option<Telemetry>,
7781
DataSources,
7882
Option<McFollowerMetrics>,
83+
BeefyVoterLinks<Block, BeefyId>,
84+
BeefyRPCLinks<Block, BeefyId>,
7985
),
8086
>,
8187
ServiceError,
@@ -133,6 +139,15 @@ pub fn new_partial(
133139
select_chain.clone(),
134140
telemetry.as_ref().map(|x| x.handle()),
135141
)?;
142+
let justification_import = grandpa_block_import.clone();
143+
144+
let (block_import, beefy_voter_links, beefy_rpc_links) =
145+
sc_consensus_beefy::beefy_block_import_and_links(
146+
grandpa_block_import.clone(),
147+
backend.clone(),
148+
client.clone(),
149+
config.prometheus_registry().cloned(),
150+
);
136151

137152
let sc_slot_config = sidechain_slots::runtime_api_client::slot_config(&*client)
138153
.map_err(sp_blockchain::Error::from)?;
@@ -151,8 +166,8 @@ pub fn new_partial(
151166
_,
152167
McHashInherentDigest,
153168
>(ImportQueueParams {
154-
block_import: grandpa_block_import.clone(),
155-
justification_import: Some(Box::new(grandpa_block_import.clone())),
169+
block_import: block_import.clone(),
170+
justification_import: Some(Box::new(justification_import)),
156171
client: client.clone(),
157172
create_inherent_data_providers: VerifierCIDP::new(
158173
inherent_config,
@@ -178,7 +193,15 @@ pub fn new_partial(
178193
keystore_container,
179194
select_chain,
180195
transaction_pool,
181-
other: (grandpa_block_import, grandpa_link, telemetry, data_sources, mc_follower_metrics),
196+
other: (
197+
grandpa_block_import,
198+
grandpa_link,
199+
telemetry,
200+
data_sources,
201+
mc_follower_metrics,
202+
beefy_voter_links,
203+
beefy_rpc_links,
204+
),
182205
})
183206
}
184207

@@ -210,7 +233,16 @@ pub async fn new_full_base<Network: sc_network::NetworkBackend<Block, <Block as
210233
keystore_container,
211234
select_chain,
212235
transaction_pool,
213-
other: (block_import, grandpa_link, mut telemetry, data_sources, _),
236+
other:
237+
(
238+
block_import,
239+
grandpa_link,
240+
mut telemetry,
241+
data_sources,
242+
_,
243+
beefy_voter_links,
244+
beefy_rpc_links,
245+
),
214246
} = new_partial(&config)?;
215247

216248
let metrics = Network::register_notification_metrics(config.prometheus_registry());
@@ -223,7 +255,10 @@ pub async fn new_full_base<Network: sc_network::NetworkBackend<Block, <Block as
223255
&client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"),
224256
&config.chain_spec,
225257
);
258+
let genesis_hash = client.chain_info().genesis_hash;
226259
let peer_store_handle = net_config.peer_store_handle();
260+
let prometheus_registry = config.prometheus_registry().cloned();
261+
227262
let (grandpa_protocol_config, grandpa_notification_service) =
228263
sc_consensus_grandpa::grandpa_peers_set_config::<_, Network>(
229264
grandpa_protocol_name.clone(),
@@ -232,6 +267,29 @@ pub async fn new_full_base<Network: sc_network::NetworkBackend<Block, <Block as
232267
);
233268
net_config.add_notification_protocol(grandpa_protocol_config);
234269

270+
let beefy_gossip_proto_name =
271+
sc_consensus_beefy::gossip_protocol_name(&genesis_hash, config.chain_spec.fork_id());
272+
// `beefy_on_demand_justifications_handler` is given to `beefy-gadget` task to be run,
273+
// while `beefy_req_resp_cfg` is added to `config.network.request_response_protocols`.
274+
let (beefy_on_demand_justifications_handler, beefy_req_resp_cfg) =
275+
sc_consensus_beefy::communication::request_response::BeefyJustifsRequestHandler::new::<
276+
_,
277+
Network,
278+
>(&genesis_hash, config.chain_spec.fork_id(), client.clone(), prometheus_registry.clone());
279+
let beefy_notification_service = {
280+
let (beefy_notification_config, beefy_notification_service) =
281+
sc_consensus_beefy::communication::beefy_peers_set_config::<_, Network>(
282+
beefy_gossip_proto_name.clone(),
283+
metrics.clone(),
284+
Arc::clone(&peer_store_handle),
285+
);
286+
287+
net_config.add_notification_protocol(beefy_notification_config);
288+
net_config.add_request_response_protocol(beefy_req_resp_cfg);
289+
// For now we always initialize it
290+
Some(beefy_notification_service)
291+
};
292+
235293
let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new(
236294
backend.clone(),
237295
grandpa_link.shared_authority_set().clone(),
@@ -269,21 +327,27 @@ pub async fn new_full_base<Network: sc_network::NetworkBackend<Block, <Block as
269327
let justification_stream = grandpa_link.justification_stream();
270328
let data_sources = data_sources.clone();
271329

272-
move |subscription_executor| {
330+
move |subscription_executor: SubscriptionTaskExecutor| {
273331
let grandpa = GrandpaDeps {
274332
shared_voter_state: shared_voter_state.clone(),
275333
shared_authority_set: shared_authority_set.clone(),
276334
justification_stream: justification_stream.clone(),
277-
subscription_executor,
335+
subscription_executor: subscription_executor.clone(),
278336
finality_provider: sc_consensus_grandpa::FinalityProofProvider::new_for_service(
279337
backend.clone(),
280338
Some(shared_authority_set.clone()),
281339
),
282340
};
341+
let beefy = BeefyDeps::<BeefyId> {
342+
beefy_finality_proof_stream: beefy_rpc_links.from_voter_justif_stream.clone(),
343+
beefy_best_block_stream: beefy_rpc_links.from_voter_best_beefy_stream.clone(),
344+
subscription_executor,
345+
};
283346
let deps = crate::rpc::FullDeps {
284347
client: client.clone(),
285348
pool: pool.clone(),
286349
grandpa,
350+
beefy,
287351
data_sources: data_sources.clone(),
288352
time_source: Arc::new(SystemTimeSource),
289353
};
@@ -298,12 +362,13 @@ pub async fn new_full_base<Network: sc_network::NetworkBackend<Block, <Block as
298362
task_manager: &mut task_manager,
299363
transaction_pool: transaction_pool.clone(),
300364
rpc_builder: Box::new(rpc_extensions_builder),
301-
backend,
365+
backend: backend.clone(),
302366
system_rpc_tx,
303367
tx_handler_controller,
304368
sync_service: sync_service.clone(),
305369
config,
306370
telemetry: telemetry.as_mut(),
371+
tracing_execute_block: None,
307372
})?;
308373

309374
if role.is_authority() {
@@ -370,6 +435,46 @@ pub async fn new_full_base<Network: sc_network::NetworkBackend<Block, <Block as
370435
.spawn_blocking("aura", Some("block-authoring"), aura);
371436
}
372437

438+
// if the node isn't actively participating in consensus then it doesn't
439+
// need a keystore, regardless of which protocol we use below.
440+
let keystore_opt = if role.is_authority() { Some(keystore_container.keystore()) } else { None };
441+
442+
// beefy is enabled if its notification service exists
443+
if let Some(notification_service) = beefy_notification_service {
444+
let justifications_protocol_name = beefy_on_demand_justifications_handler.protocol_name();
445+
let network_params = sc_consensus_beefy::BeefyNetworkParams {
446+
network: Arc::new(network.clone()),
447+
sync: sync_service.clone(),
448+
gossip_protocol_name: beefy_gossip_proto_name,
449+
justifications_protocol_name,
450+
notification_service,
451+
_phantom: core::marker::PhantomData::<Block>,
452+
};
453+
let payload_provider = sp_consensus_beefy::mmr::MmrRootProvider::new(client.clone());
454+
let beefy_params = sc_consensus_beefy::BeefyParams {
455+
client: client.clone(),
456+
backend: backend.clone(),
457+
payload_provider,
458+
runtime: client.clone(),
459+
key_store: keystore_opt.clone(),
460+
network_params,
461+
min_block_delta: 8,
462+
prometheus_registry: prometheus_registry.clone(),
463+
links: beefy_voter_links,
464+
on_demand_justifications_handler: beefy_on_demand_justifications_handler,
465+
is_authority: role.is_authority(),
466+
};
467+
468+
let gadget =
469+
sc_consensus_beefy::start_beefy_gadget::<_, _, _, _, _, _, _, BeefyId>(beefy_params);
470+
471+
// BEEFY is part of consensus, if it fails we'll bring the node down with it to make
472+
// sure it is noticed.
473+
task_manager
474+
.spawn_essential_handle()
475+
.spawn_blocking("beefy-gadget", None, gadget);
476+
}
477+
373478
if enable_grandpa {
374479
// if the node isn't actively participating in consensus then it doesn't
375480
// need a keystore, regardless of which protocol we use below.

0 commit comments

Comments
 (0)