diff --git a/bin/collator/src/local/service.rs b/bin/collator/src/local/service.rs index 3421792c2d..ee53aea2b0 100644 --- a/bin/collator/src/local/service.rs +++ b/bin/collator/src/local/service.rs @@ -368,15 +368,10 @@ pub fn start_node( enable_evm_rpc: true, // enable EVM RPC for dev node by default }; - let pending_consensus_data_provider = Box::new( - fc_rpc::pending::AuraConsensusDataProvider::new(client.clone()), - ); - crate::rpc::create_full( deps, subscription, pubsub_notification_sinks.clone(), - pending_consensus_data_provider, rpc_config.clone(), ) .map_err::(Into::into) @@ -656,17 +651,8 @@ pub fn start_node(config: Configuration) -> Result { enable_evm_rpc: true, // enable EVM RPC for dev node by default }; - let pending_consensus_data_provider = Box::new( - fc_rpc::pending::AuraConsensusDataProvider::new(client.clone()), - ); - - crate::rpc::create_full( - deps, - subscription, - pubsub_notification_sinks.clone(), - pending_consensus_data_provider, - ) - .map_err::(Into::into) + crate::rpc::create_full(deps, subscription, pubsub_notification_sinks.clone()) + .map_err::(Into::into) }) }; diff --git a/bin/collator/src/parachain/mod.rs b/bin/collator/src/parachain/mod.rs index e988e01dba..077a99f1de 100644 --- a/bin/collator/src/parachain/mod.rs +++ b/bin/collator/src/parachain/mod.rs @@ -31,3 +31,7 @@ pub use service::{ astar, build_import_queue, new_partial, shibuya, shiden, start_astar_node, start_shibuya_node, start_shiden_node, HostFunctions, }; + +pub(crate) use shell_upgrade::{ + AuraConsensusDataProviderFallback, PendingCrateInherentDataProvider, +}; diff --git a/bin/collator/src/parachain/service.rs b/bin/collator/src/parachain/service.rs index 8f5ea41ba3..9865e8e88d 100644 --- a/bin/collator/src/parachain/service.rs +++ b/bin/collator/src/parachain/service.rs @@ -494,17 +494,8 @@ where enable_evm_rpc: additional_config.enable_evm_rpc, }; - let pending_consensus_data_provider = Box::new( - fc_rpc::pending::AuraConsensusDataProvider::new(client.clone()), - ); - - crate::rpc::create_full( - deps, - subscription, - pubsub_notification_sinks.clone(), - pending_consensus_data_provider, - ) - .map_err(Into::into) + crate::rpc::create_full(deps, subscription, pubsub_notification_sinks.clone()) + .map_err(Into::into) }) }; @@ -845,15 +836,10 @@ where enable_evm_rpc: additional_config.enable_evm_rpc, }; - let pending_consensus_data_provider = Box::new( - fc_rpc::pending::AuraConsensusDataProvider::new(client.clone()), - ); - crate::rpc::create_full( deps, subscription, pubsub_notification_sinks.clone(), - pending_consensus_data_provider, rpc_config.clone(), ) .map_err(Into::into) diff --git a/bin/collator/src/parachain/shell_upgrade.rs b/bin/collator/src/parachain/shell_upgrade.rs index ce63e84db9..510565bade 100644 --- a/bin/collator/src/parachain/shell_upgrade.rs +++ b/bin/collator/src/parachain/shell_upgrade.rs @@ -21,12 +21,24 @@ use astar_primitives::*; use cumulus_client_consensus_common::{ParachainCandidate, ParachainConsensus}; use cumulus_primitives_core::relay_chain::{Hash as PHash, PersistedValidationData}; +use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; +use fc_rpc::pending::ConsensusDataProvider; use futures::lock::Mutex; +use sc_client_api::{AuxStore, UsageProvider}; use sc_consensus::{import_queue::Verifier as VerifierT, BlockImportParams, ForkChoiceStrategy}; -use sp_api::ApiExt; -use sp_consensus_aura::{sr25519::AuthorityId as AuraId, AuraApi}; -use sp_runtime::traits::Header as HeaderT; -use std::sync::Arc; +use sp_api::{ApiExt, ProvideRuntimeApi}; +use sp_consensus_aura::{ + digests::CompatibleDigestItem, + sr25519::{AuthorityId as AuraId, AuthoritySignature}, + AuraApi, +}; +use sp_inherents::{CreateInherentDataProviders, Error, InherentData}; +use sp_runtime::{ + traits::{Block as BlockT, Header as HeaderT}, + Digest, DigestItem, +}; +use sp_timestamp::TimestampInherentData; +use std::{marker::PhantomData, sync::Arc}; pub enum BuildOnAccess { Uninitialized(Option R + Send + Sync>>), @@ -138,3 +150,140 @@ where } } } + +/// AuraConsensusDataProvider custom implementation which awaits for AuraApi to become available, +/// until then it will return error. Shiden genesis did not start with AuraApi, therefore this +/// implementation makes sure to return digest after AuraApi becomes available. +/// This is currently required by EVM RPC. +pub struct AuraConsensusDataProviderFallback { + client: Arc, + phantom_data: PhantomData, +} + +impl AuraConsensusDataProviderFallback +where + B: BlockT, + C: AuxStore + ProvideRuntimeApi + UsageProvider + Send + Sync, + C::Api: AuraApi, +{ + pub fn new(client: Arc) -> Self { + Self { + client, + phantom_data: Default::default(), + } + } +} + +impl ConsensusDataProvider for AuraConsensusDataProviderFallback +where + B: BlockT, + C: AuxStore + ProvideRuntimeApi + UsageProvider + Send + Sync, + C::Api: AuraApi, +{ + fn create_digest(&self, parent: &B::Header, data: &InherentData) -> Result { + if self + .client + .runtime_api() + .has_api::>(parent.hash()) + .unwrap_or_default() + { + let slot_duration = sc_consensus_aura::slot_duration(&*self.client) + .expect("slot_duration should be present at this point; qed."); + let timestamp = data + .timestamp_inherent_data()? + .expect("Timestamp is always present; qed"); + + let digest_item = + >::aura_pre_digest( + sp_consensus_aura::Slot::from_timestamp(timestamp, slot_duration), + ); + + return Ok(Digest { + logs: vec![digest_item], + }); + } + Err(Error::Application("AuraApi is not present".into())) + } +} + +/// Shiden genesis did not start with AuraApi, therefore this implementation makes sure to return +/// inherent data after AuraApi becomes available. +/// This is currently required by EVM RPC. +pub struct PendingCrateInherentDataProvider { + client: Arc, + phantom_data: PhantomData, +} + +impl PendingCrateInherentDataProvider +where + B: BlockT, + C: AuxStore + ProvideRuntimeApi + UsageProvider + Send + Sync, + C::Api: AuraApi, +{ + pub fn new(client: Arc) -> Self { + Self { + client, + phantom_data: Default::default(), + } + } +} + +#[async_trait::async_trait] +impl CreateInherentDataProviders for PendingCrateInherentDataProvider +where + B: BlockT, + C: AuxStore + ProvideRuntimeApi + UsageProvider + Send + Sync, + C::Api: AuraApi, +{ + type InherentDataProviders = ( + sp_consensus_aura::inherents::InherentDataProvider, + sp_timestamp::InherentDataProvider, + cumulus_primitives_parachain_inherent::ParachainInherentData, + ); + + async fn create_inherent_data_providers( + &self, + parent: B::Hash, + _extra_args: (), + ) -> Result> { + if !self + .client + .runtime_api() + .has_api::>(parent) + .unwrap_or_default() + { + return Err("AuraApi is not present".into()); + } + + let slot_duration = sc_consensus_aura::slot_duration(&*self.client) + .expect("slot_duration should be present at this point; qed."); + let current = sp_timestamp::InherentDataProvider::from_system_time(); + let next_slot = current.timestamp().as_millis() + slot_duration.as_millis(); + let timestamp = sp_timestamp::InherentDataProvider::new(next_slot.into()); + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + // Create a dummy parachain inherent data provider which is required to pass + // the checks by the para chain system. We use dummy values because in the 'pending context' + // neither do we have access to the real values nor do we need them. + let (relay_parent_storage_root, relay_chain_state) = + RelayStateSproofBuilder::default().into_state_root_and_proof(); + let vfp = PersistedValidationData { + // This is a hack to make `cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases` + // happy. Relay parent number can't be bigger than u32::MAX. + relay_parent_number: u32::MAX, + relay_parent_storage_root, + ..Default::default() + }; + let parachain_inherent_data = + cumulus_primitives_parachain_inherent::ParachainInherentData { + validation_data: vfp, + relay_chain_state, + downward_messages: Default::default(), + horizontal_messages: Default::default(), + }; + Ok((slot, timestamp, parachain_inherent_data)) + } +} diff --git a/bin/collator/src/rpc.rs b/bin/collator/src/rpc.rs index 5da4f28d35..b3c143c99d 100644 --- a/bin/collator/src/rpc.rs +++ b/bin/collator/src/rpc.rs @@ -18,17 +18,14 @@ //! Astar RPCs implementation. -use cumulus_primitives_parachain_inherent::ParachainInherentData; -use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; use fc_rpc::{ - pending::ConsensusDataProvider, Eth, EthApiServer, EthBlockDataCacheTask, EthFilter, - EthFilterApiServer, EthPubSub, EthPubSubApiServer, Net, NetApiServer, OverrideHandle, Web3, - Web3ApiServer, + Eth, EthApiServer, EthBlockDataCacheTask, EthFilter, EthFilterApiServer, EthPubSub, + EthPubSubApiServer, Net, NetApiServer, OverrideHandle, Web3, Web3ApiServer, }; use fc_rpc_core::types::{FeeHistoryCache, FilterPool}; use jsonrpsee::RpcModule; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; -use polkadot_primitives::PersistedValidationData; + use sc_client_api::{ AuxStore, Backend, BlockchainEvents, StateBackend, StorageProvider, UsageProvider, }; @@ -149,7 +146,6 @@ pub fn create_full( fc_mapping_sync::EthereumBlockNotification, >, >, - pending_consenus_data_provider: Box>, tracing_config: EvmTracingConfig, ) -> Result, Box> where @@ -182,12 +178,7 @@ where let client = Arc::clone(&deps.client); let graph = Arc::clone(&deps.graph); - let mut io = create_full_rpc( - deps, - subscription_task_executor, - pubsub_notification_sinks, - pending_consenus_data_provider, - )?; + let mut io = create_full_rpc(deps, subscription_task_executor, pubsub_notification_sinks)?; if tracing_config.enable_txpool { io.merge(MoonbeamTxPool::new(Arc::clone(&client), graph).into_rpc())?; @@ -221,7 +212,6 @@ pub fn create_full( fc_mapping_sync::EthereumBlockNotification, >, >, - pending_consenus_data_provider: Box>, ) -> Result, Box> where C: ProvideRuntimeApi @@ -248,12 +238,7 @@ where BE::Blockchain: BlockchainBackend, A: ChainApi + 'static, { - create_full_rpc( - deps, - subscription_task_executor, - pubsub_notification_sinks, - pending_consenus_data_provider, - ) + create_full_rpc(deps, subscription_task_executor, pubsub_notification_sinks) } fn create_full_rpc( @@ -264,7 +249,6 @@ fn create_full_rpc( fc_mapping_sync::EthereumBlockNotification, >, >, - pending_consenus_data_provider: Box>, ) -> Result, Box> where C: ProvideRuntimeApi @@ -319,37 +303,6 @@ where let no_tx_converter: Option = None; - let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let pending_create_inherent_data_providers = move |_, _| async move { - let current = sp_timestamp::InherentDataProvider::from_system_time(); - let next_slot = current.timestamp().as_millis() + slot_duration.as_millis(); - let timestamp = sp_timestamp::InherentDataProvider::new(next_slot.into()); - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - // Create a dummy parachain inherent data provider which is required to pass - // the checks by the para chain system. We use dummy values because in the 'pending context' - // neither do we have access to the real values nor do we need them. - let (relay_parent_storage_root, relay_chain_state) = - RelayStateSproofBuilder::default().into_state_root_and_proof(); - let vfp = PersistedValidationData { - // This is a hack to make `cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases` - // happy. Relay parent number can't be bigger than u32::MAX. - relay_parent_number: u32::MAX, - relay_parent_storage_root, - ..Default::default() - }; - let parachain_inherent_data = ParachainInherentData { - validation_data: vfp, - relay_chain_state, - downward_messages: Default::default(), - horizontal_messages: Default::default(), - }; - Ok((slot, timestamp, parachain_inherent_data)) - }; - io.merge( Eth::<_, _, _, _, _, _, _, ()>::new( client.clone(), @@ -367,8 +320,10 @@ where // Allow 10x max allowed weight for non-transactional calls 10, None, - pending_create_inherent_data_providers, - Some(pending_consenus_data_provider), + crate::parachain::PendingCrateInherentDataProvider::new(client.clone()), + Some(Box::new( + crate::parachain::AuraConsensusDataProviderFallback::new(client.clone()), + )), ) .replace_config::>() .into_rpc(),