diff --git a/node/src/rpc.rs b/node/src/rpc.rs index 0d4cd355de..b0877f3469 100644 --- a/node/src/rpc.rs +++ b/node/src/rpc.rs @@ -14,6 +14,10 @@ pub use fc_rpc_core::types::{FeeHistoryCache, FeeHistoryCacheLimit, FilterPool}; use fc_storage::StorageOverride; use jsonrpsee::RpcModule; use node_subtensor_runtime::opaque::Block; +use sc_consensus_grandpa::{FinalityProofProvider, GrandpaJustificationStream}; +use sc_consensus_grandpa::{SharedAuthoritySet, SharedVoterState}; +use sc_consensus_grandpa_rpc::Grandpa; +use sc_consensus_grandpa_rpc::GrandpaApiServer; use sc_consensus_manual_seal::EngineCommand; use sc_network::service::traits::NetworkService; use sc_network_sync::SyncingService; @@ -23,6 +27,7 @@ use sc_transaction_pool_api::TransactionPool; use sp_core::H256; use sp_inherents::CreateInherentDataProviders; use sp_runtime::traits::Block as BlockT; +use subtensor_runtime_common::BlockNumber; use subtensor_runtime_common::Hash; use crate::{ @@ -83,8 +88,22 @@ impl fc_rpc::EthConfig for DefaultEthConfig { >; } +/// Extra dependencies for GRANDPA +pub struct GrandpaDeps { + /// Voting round info. + pub shared_voter_state: SharedVoterState, + /// Authority set info. + pub shared_authority_set: SharedAuthoritySet, + /// Receives notifications about justification events from Grandpa. + pub justification_stream: GrandpaJustificationStream, + /// Executor to drive the subscription manager in the Grandpa RPC handler. + pub subscription_executor: SubscriptionTaskExecutor, + /// Finality proof provider. + pub finality_provider: Arc>, +} + /// Full client dependencies. -pub struct FullDeps { +pub struct FullDeps { /// The client instance to use. pub client: Arc, /// Transaction pool instance. @@ -93,11 +112,15 @@ pub struct FullDeps { pub command_sink: Option>>, /// Ethereum-compatibility specific dependencies. pub eth: EthDeps, + /// GRANDPA specific dependencies. + pub grandpa: GrandpaDeps, + /// The backend used by the node. + pub backend: Arc, } /// Instantiate all full RPC extensions. -pub fn create_full( - deps: FullDeps, +pub fn create_full( + deps: FullDeps, subscription_task_executor: SubscriptionTaskExecutor, pubsub_notification_sinks: Arc< fc_mapping_sync::EthereumBlockNotificationSinks< @@ -110,6 +133,8 @@ where A: ChainApi + 'static, CIDP: CreateInherentDataProviders + Send + Clone + 'static, CT: fp_rpc::ConvertTransaction<::Extrinsic> + Send + Sync + Clone + 'static, + B: sc_client_api::Backend + Send + Sync + 'static, + B::State: sc_client_api::backend::StateBackend>, { use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; use sc_consensus_manual_seal::rpc::{ManualSeal, ManualSealApiServer}; @@ -122,13 +147,32 @@ where pool, command_sink, eth, + grandpa, + backend: _backend, } = deps; + let GrandpaDeps { + shared_voter_state, + shared_authority_set, + justification_stream, + subscription_executor, + finality_provider, + } = grandpa; // Custom RPC methods for Paratensor module.merge(SubtensorCustom::new(client.clone()).into_rpc())?; module.merge(System::new(client.clone(), pool.clone()).into_rpc())?; module.merge(TransactionPayment::new(client).into_rpc())?; + module.merge( + Grandpa::new( + subscription_executor, + shared_authority_set.clone(), + shared_voter_state, + justification_stream, + finality_provider, + ) + .into_rpc(), + )?; // Extend this RPC with a custom API by using the following syntax. // `YourRpcStruct` should have a reference to a client, which is needed diff --git a/node/src/service.rs b/node/src/service.rs index 4ce041b0a4..64eddef20a 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -9,8 +9,10 @@ use sc_consensus::{ BasicQueue, BlockCheckParams, BlockImport, BlockImportParams, BoxBlockImport, ImportResult, }; use sc_consensus_grandpa::BlockNumberOps; +use sc_consensus_grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; use sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging; use sc_network_sync::strategy::warp::{WarpSyncConfig, WarpSyncProvider}; +use sc_rpc::SubscriptionTaskExecutor; use sc_service::{Configuration, PartialComponents, TaskManager, error::Error as ServiceError}; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, log}; use sc_transaction_pool::FullPool; @@ -31,6 +33,7 @@ use crate::ethereum::{ StorageOverride, StorageOverrideHandler, db_config_dir, new_frontier_partial, spawn_frontier_tasks, }; +use crate::rpc::GrandpaDeps; /// The minimum period of blocks on which justifications will be /// imported and generated. @@ -494,6 +497,7 @@ where // for ethereum-compatibility rpc. config.rpc.id_provider = Some(Box::new(fc_rpc::EthereumSubIdProvider)); + let shared_voter_state = sc_consensus_grandpa::SharedVoterState::empty(); let rpc_builder = { let client = client.clone(); let pool = transaction_pool.clone(); @@ -532,47 +536,66 @@ where Ok((slot, timestamp)) }; - Box::new(move |subscription_task_executor| { - let eth_deps = crate::rpc::EthDeps { - client: client.clone(), - pool: pool.clone(), - graph: pool.pool().clone(), - converter: Some(TransactionConverter::::default()), - is_authority, - enable_dev_signer, - network: network.clone(), - sync: sync_service.clone(), - frontier_backend: match &*frontier_backend { - fc_db::Backend::KeyValue(b) => b.clone(), - fc_db::Backend::Sql(b) => b.clone(), - }, - storage_override: storage_override.clone(), - block_data_cache: block_data_cache.clone(), - filter_pool: filter_pool.clone(), - max_past_logs, - fee_history_cache: fee_history_cache.clone(), - fee_history_cache_limit, - execute_gas_limit_multiplier, - forced_parent_hashes: None, - pending_create_inherent_data_providers, - }; - let deps = crate::rpc::FullDeps { - client: client.clone(), - pool: pool.clone(), - command_sink: if sealing.is_some() { - Some(command_sink.clone()) - } else { - None - }, - eth: eth_deps, - }; - crate::rpc::create_full( - deps, - subscription_task_executor, - pubsub_notification_sinks.clone(), - ) - .map_err(Into::into) - }) + let justification_stream = grandpa_link.justification_stream(); + let shared_authority_set = grandpa_link.shared_authority_set().clone(); + let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service( + backend.clone(), + Some(shared_authority_set.clone()), + ); + let backend = backend.clone(); + let shared_voter_state = shared_voter_state.clone(); + + Box::new( + move |subscription_task_executor: SubscriptionTaskExecutor| { + let eth_deps = crate::rpc::EthDeps { + client: client.clone(), + pool: pool.clone(), + graph: pool.pool().clone(), + converter: Some(TransactionConverter::::default()), + is_authority, + enable_dev_signer, + network: network.clone(), + sync: sync_service.clone(), + frontier_backend: match &*frontier_backend { + fc_db::Backend::KeyValue(b) => b.clone(), + fc_db::Backend::Sql(b) => b.clone(), + }, + storage_override: storage_override.clone(), + block_data_cache: block_data_cache.clone(), + filter_pool: filter_pool.clone(), + max_past_logs, + fee_history_cache: fee_history_cache.clone(), + fee_history_cache_limit, + execute_gas_limit_multiplier, + forced_parent_hashes: None, + pending_create_inherent_data_providers, + }; + let deps = crate::rpc::FullDeps { + client: client.clone(), + pool: pool.clone(), + command_sink: if sealing.is_some() { + Some(command_sink.clone()) + } else { + None + }, + backend: backend.clone(), + eth: eth_deps, + grandpa: GrandpaDeps { + shared_voter_state: shared_voter_state.clone(), + shared_authority_set: shared_authority_set.clone(), + justification_stream: justification_stream.clone(), + subscription_executor: subscription_task_executor.clone(), + finality_provider: finality_proof_provider.clone(), + }, + }; + crate::rpc::create_full( + deps, + subscription_task_executor, + pubsub_notification_sinks.clone(), + ) + .map_err(Into::into) + }, + ) }; let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { @@ -704,7 +727,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), })?; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index cbe8a84a68..e1678ea1ee 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -207,7 +207,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 265, + spec_version: 266, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1,