From 6e484034e90f395693646eb8915c03e5a0c07547 Mon Sep 17 00:00:00 2001 From: vedhavyas Date: Mon, 27 Nov 2023 13:30:40 +0100 Subject: [PATCH] check if the state is available before trying to relay messages --- Cargo.lock | 1 + crates/subspace-node/src/bin/subspace-node.rs | 5 ++ domains/client/relayer/Cargo.toml | 1 + domains/client/relayer/src/worker.rs | 49 ++++++++++++++++--- domains/service/src/domain.rs | 2 + 5 files changed, 51 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 33365dfeff..648a21c5ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2617,6 +2617,7 @@ dependencies = [ "futures", "parity-scale-codec", "sc-client-api", + "sc-state-db", "sc-utils", "sp-api", "sp-blockchain", diff --git a/crates/subspace-node/src/bin/subspace-node.rs b/crates/subspace-node/src/bin/subspace-node.rs index 6b0f0d392c..74be632a16 100644 --- a/crates/subspace-node/src/bin/subspace-node.rs +++ b/crates/subspace-node/src/bin/subspace-node.rs @@ -450,6 +450,10 @@ fn main() -> Result<(), Error> { })? .unwrap_or_default(); + let consensus_state_pruning_mode = consensus_chain_config + .state_pruning + .clone() + .unwrap_or_default(); let consensus_chain_node = { let span = sc_tracing::tracing::info_span!( sc_tracing::logging::PREFIX_LOG_SPAN, @@ -608,6 +612,7 @@ fn main() -> Result<(), Error> { let relayer_worker = domain_client_message_relayer::worker::relay_consensus_chain_messages( consensus_chain_node.client.clone(), + consensus_state_pruning_mode, consensus_chain_node.sync_service.clone(), xdm_gossip_worker_builder.gossip_msg_sink(), ); diff --git a/domains/client/relayer/Cargo.toml b/domains/client/relayer/Cargo.toml index ac4e7928a3..1d78a50b6f 100644 --- a/domains/client/relayer/Cargo.toml +++ b/domains/client/relayer/Cargo.toml @@ -17,6 +17,7 @@ cross-domain-message-gossip = { path = "../../client/cross-domain-message-gossip futures = "0.3.29" parity-scale-codec = { version = "3.6.5", features = ["derive"] } sc-client-api = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "892bf8e938c6bd2b893d3827d1093cd81baa59a1" } +sc-state-db = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "892bf8e938c6bd2b893d3827d1093cd81baa59a1" } sc-utils = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "892bf8e938c6bd2b893d3827d1093cd81baa59a1" } sp-api = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "892bf8e938c6bd2b893d3827d1093cd81baa59a1" } sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "892bf8e938c6bd2b893d3827d1093cd81baa59a1" } diff --git a/domains/client/relayer/src/worker.rs b/domains/client/relayer/src/worker.rs index 58249c1d04..8deb8ce852 100644 --- a/domains/client/relayer/src/worker.rs +++ b/domains/client/relayer/src/worker.rs @@ -2,6 +2,7 @@ use crate::{BlockT, Error, GossipMessageSink, HeaderBackend, HeaderT, Relayer, L use futures::StreamExt; use parity_scale_codec::FullCodec; use sc_client_api::{AuxStore, BlockchainEvents, ProofProvider}; +use sc_state_db::PruningMode; use sp_api::{ApiError, ProvideRuntimeApi}; use sp_consensus::SyncOracle; use sp_domains::DomainsApi; @@ -15,6 +16,7 @@ use std::sync::Arc; /// If the node is in major sync, worker waits waits until the sync is finished. pub async fn relay_consensus_chain_messages( consensus_chain_client: Arc, + state_pruning_mode: PruningMode, sync_oracle: SO, gossip_message_sink: GossipMessageSink, ) where @@ -31,16 +33,17 @@ pub async fn relay_consensus_chain_messages( // since all the relayers will haven embed client to known the canonical chain. let result = start_relaying_messages( NumberFor::::zero(), - consensus_chain_client, + consensus_chain_client.clone(), |client, block_hash| { Relayer::submit_messages_from_consensus_chain(client, block_hash, &gossip_message_sink) }, sync_oracle, - |_, _| -> Result { - // since we just need to provide a storage proof with the state root of Consensus chain - // proof can always be generated for any consensus chain block. - // So we can always relay messages. - Ok(true) + |_, relay_number| -> Result { + Ok(is_state_available( + &state_pruning_mode, + &consensus_chain_client, + relay_number, + )) }, ) .await; @@ -59,6 +62,7 @@ pub async fn relay_consensus_chain_messages( pub async fn relay_domain_messages( consensus_chain_client: Arc, domain_client: Arc, + domain_state_pruning: PruningMode, sync_oracle: SO, gossip_message_sink: GossipMessageSink, ) where @@ -88,7 +92,7 @@ pub async fn relay_domain_messages( let result = start_relaying_messages( relay_confirmation_depth, - domain_client, + domain_client.clone(), |client, block_hash| { Relayer::submit_messages_from_domain( client, @@ -106,6 +110,11 @@ pub async fn relay_domain_messages( ))); }; + // short circuit if the domain state is unavailable to relay messages. + if !is_state_available(&domain_state_pruning, &domain_client, block_number) { + return Ok(false); + } + let api = consensus_chain_client.runtime_api(); let at = consensus_chain_client.info().best_hash; let oldest_tracked_number = api.oldest_receipt_number(at, domain_id)?; @@ -123,6 +132,32 @@ pub async fn relay_domain_messages( } } +fn is_state_available( + state_pruning_mode: &PruningMode, + client: &Arc, + relay_number: NumberFor, +) -> bool +where + Block: BlockT, + Client: HeaderBackend, +{ + match state_pruning_mode { + // all the state is available for archive and archive canonical. + // we can relay any message from any block + PruningMode::ArchiveAll | PruningMode::ArchiveCanonical => true, + // If the pruning mode is constrained, then check if the state is available for the `relay_number` + PruningMode::Constrained(constraints) => { + let max_blocks = NumberFor::::from(constraints.max_blocks.unwrap_or(0)); + let current_best_block = client.info().best_number; + match current_best_block.checked_sub(&max_blocks) { + // we still have the state available as there was no pruning yet. + None => true, + Some(available_block_state) => relay_number >= available_block_state, + } + } + } +} + async fn start_relaying_messages( relay_confirmation_depth: NumberFor, client: Arc, diff --git a/domains/service/src/domain.rs b/domains/service/src/domain.rs index d26560f1c9..f3f10ababc 100644 --- a/domains/service/src/domain.rs +++ b/domains/service/src/domain.rs @@ -371,6 +371,7 @@ where })?; let is_authority = domain_config.role.is_authority(); + let domain_state_pruning = domain_config.state_pruning.clone().unwrap_or_default(); domain_config.rpc_id_provider = provider.rpc_id(); let rpc_builder = { let deps = crate::rpc::FullDeps { @@ -467,6 +468,7 @@ where let relayer_worker = domain_client_message_relayer::worker::relay_domain_messages( consensus_client.clone(), client.clone(), + domain_state_pruning, // domain relayer will use consensus chain sync oracle instead of domain sync orcle // since domain sync oracle will always return `synced` due to force sync being set. consensus_network_sync_oracle,