Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finalize domain blocks and default domain block and state pruning #3372

Merged
merged 9 commits into from
Feb 10, 2025
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.

Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use std::path::PathBuf;
use std::sync::Arc;
use subspace_runtime::RuntimeApi as CRuntimeApi;
use subspace_runtime_primitives::opaque::Block as CBlock;
use subspace_runtime_primitives::AccountId;
use subspace_runtime_primitives::{AccountId, DOMAINS_BLOCK_PRUNING_DEPTH};
use subspace_service::FullClient as CFullClient;

/// `DomainInstanceStarter` used to start a domain instance node based on the given
Expand Down Expand Up @@ -166,6 +166,7 @@ impl DomainInstanceStarter {
consensus_chain_sync_params: None::<
ConsensusChainSyncParams<_, Arc<dyn NetworkRequest + Sync + Send>>,
>,
challenge_period: DOMAINS_BLOCK_PRUNING_DEPTH,
};

let mut domain_node = domain_service::new_full::<
Expand Down Expand Up @@ -228,6 +229,7 @@ impl DomainInstanceStarter {
consensus_chain_sync_params: None::<
ConsensusChainSyncParams<_, Arc<dyn NetworkRequest + Sync + Send>>,
>,
challenge_period: DOMAINS_BLOCK_PRUNING_DEPTH,
};

let mut domain_node = domain_service::new_full::<
Expand Down
59 changes: 57 additions & 2 deletions crates/subspace-node/src/commands/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use futures::stream::StreamExt;
use futures::FutureExt;
use sc_cli::Signals;
use sc_consensus_slots::SlotProportion;
use sc_service::{BlocksPruning, Configuration, PruningMode};
use sc_state_db::Constraints;
use sc_storage_monitor::StorageMonitorService;
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
use sc_utils::mpsc::tracing_unbounded;
Expand All @@ -30,6 +32,7 @@ use std::sync::Arc;
use subspace_logging::init_logger;
use subspace_metrics::{start_prometheus_metrics_server, RegistryAdapter};
use subspace_runtime::{Block, RuntimeApi};
use subspace_runtime_primitives::{DOMAINS_BLOCK_PRUNING_DEPTH, DOMAINS_PRUNING_DEPTH_MULTIPLIER};
use subspace_service::config::ChainSyncMode;
use tracing::{debug, error, info, info_span, warn};

Expand Down Expand Up @@ -88,7 +91,7 @@ pub async fn run(run_options: RunOptions) -> Result<(), Error> {

let ConsensusChainConfiguration {
maybe_tmp_dir: _maybe_tmp_dir,
subspace_configuration,
mut subspace_configuration,
dev,
pot_external_entropy,
storage_monitor,
Expand Down Expand Up @@ -128,6 +131,10 @@ pub async fn run(run_options: RunOptions) -> Result<(), Error> {
None
};

if maybe_domain_configuration.is_some() {
ensure_block_and_state_pruning_params(&mut subspace_configuration.base)
}

let mut task_manager = {
let subspace_link;
let consensus_chain_node = {
Expand Down Expand Up @@ -182,7 +189,8 @@ pub async fn run(run_options: RunOptions) -> Result<(), Error> {
})?;

// Run a domain
if let Some(domain_configuration) = maybe_domain_configuration {
if let Some(mut domain_configuration) = maybe_domain_configuration {
ensure_block_and_state_pruning_params(&mut domain_configuration.domain_config);
let mut xdm_gossip_worker_builder = GossipWorkerBuilder::new();
let gossip_message_sink = xdm_gossip_worker_builder.gossip_msg_sink();
let (domain_message_sink, domain_message_receiver) =
Expand Down Expand Up @@ -372,3 +380,50 @@ pub async fn run(run_options: RunOptions) -> Result<(), Error> {
.await
.map_err(Into::into)
}

pub fn ensure_block_and_state_pruning_params(config: &mut Configuration) {
let blocks_to_prune =
DOMAINS_BLOCK_PRUNING_DEPTH.saturating_mul(DOMAINS_PRUNING_DEPTH_MULTIPLIER);

if let BlocksPruning::Some(blocks) = config.blocks_pruning {
config.blocks_pruning = BlocksPruning::Some(if blocks >= blocks_to_prune {
blocks
} else {
warn!(
"Blocks pruning constraints needs to be atleast {:?}",
blocks_to_prune
);
blocks_to_prune
});
}

match &config.state_pruning {
None => {
config.state_pruning = Some(PruningMode::Constrained(Constraints {
max_blocks: Some(blocks_to_prune),
}))
}
Some(pruning_mode) => {
if let PruningMode::Constrained(constraints) = pruning_mode {
let blocks_to_prune = match constraints.max_blocks {
None => blocks_to_prune,
Some(blocks) => {
if blocks >= blocks_to_prune {
blocks
} else {
warn!(
"State pruning constraints needs to be atleast {:?}",
blocks_to_prune
);
blocks_to_prune
}
}
};

config.state_pruning = Some(PruningMode::Constrained(Constraints {
max_blocks: Some(blocks_to_prune),
}))
}
}
}
}
39 changes: 4 additions & 35 deletions crates/subspace-node/src/commands/run/domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ use sc_network::config::{MultiaddrWithPeerId, NonReservedPeerMode, SetConfig, Tr
use sc_network::{NetworkPeers, NetworkRequest};
use sc_proof_of_time::source::PotSlotInfo;
use sc_service::config::KeystoreConfig;
use sc_service::{BlocksPruning, Configuration, PruningMode};
use sc_state_db::Constraints;
use sc_service::Configuration;
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
use sc_utils::mpsc::{TracingUnboundedReceiver, TracingUnboundedSender};
use sp_api::ProvideRuntimeApi;
Expand All @@ -38,15 +37,13 @@ use std::net::SocketAddr;
use std::sync::Arc;
use subspace_runtime::RuntimeApi as CRuntimeApi;
use subspace_runtime_primitives::opaque::Block as CBlock;
use subspace_runtime_primitives::DOMAINS_BLOCK_PRUNING_DEPTH;
use subspace_service::FullClient as CFullClient;
use tokio::sync::broadcast::Receiver;
use tokio_stream::wrappers::errors::BroadcastStreamRecvError;
use tracing::log::info;
use tracing::warn;

/// Pruning depth multiplier
const PRUNING_DEPTH_MULTIPLIER: u32 = 2;

/// Options for Substrate networking
#[derive(Debug, Parser)]
struct SubstrateNetworkOptions {
Expand Down Expand Up @@ -487,36 +484,6 @@ where
.map(|params| params.snap_sync_orchestrator.domain_snap_sync_finished()),
));

// domain blocks that we want to prune below finalized domain blocks are
// (confirmation_depth * multiplier) + user provided blocks
let blocks_to_prune = chain_constants
.confirmation_depth_k()
.saturating_mul(PRUNING_DEPTH_MULTIPLIER);

if let BlocksPruning::Some(blocks) = domain_config.blocks_pruning {
domain_config.blocks_pruning = BlocksPruning::Some(blocks_to_prune + blocks)
}

match &domain_config.state_pruning {
None => {
domain_config.state_pruning = Some(PruningMode::Constrained(Constraints {
max_blocks: Some(blocks_to_prune),
}))
}
Some(pruning_mode) => {
if let PruningMode::Constrained(constraints) = pruning_mode {
let blocks_to_prune = match constraints.max_blocks {
None => blocks_to_prune,
Some(blocks) => blocks_to_prune + blocks,
};

domain_config.state_pruning = Some(PruningMode::Constrained(Constraints {
max_blocks: Some(blocks_to_prune),
}))
}
}
}

match runtime_type {
RuntimeType::Evm => {
let eth_provider = EthProvider::<
Expand Down Expand Up @@ -547,6 +514,7 @@ where
maybe_operator_id: operator_id,
confirmation_depth_k: chain_constants.confirmation_depth_k(),
consensus_chain_sync_params,
challenge_period: DOMAINS_BLOCK_PRUNING_DEPTH,
};

let mut domain_node = domain_service::new_full::<
Expand Down Expand Up @@ -587,6 +555,7 @@ where
maybe_operator_id: operator_id,
confirmation_depth_k: chain_constants.confirmation_depth_k(),
consensus_chain_sync_params,
challenge_period: DOMAINS_BLOCK_PRUNING_DEPTH,
};

let mut domain_node = domain_service::new_full::<
Expand Down
6 changes: 6 additions & 0 deletions crates/subspace-runtime-primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ pub const BLOCK_WEIGHT_FOR_2_SEC: Weight =
/// Maximum block length for non-`Normal` extrinsic is 5 MiB.
pub const MAX_BLOCK_LENGTH: u32 = 5 * 1024 * 1024;

/// Pruning depth multiplier for state and blocks pruning.
pub const DOMAINS_PRUNING_DEPTH_MULTIPLIER: u32 = 2;

/// Domains Block pruning depth.
pub const DOMAINS_BLOCK_PRUNING_DEPTH: u32 = 14_400;

/// We allow for 3.75 MiB for `Normal` extrinsic with 5 MiB maximum block length.
pub fn maximum_normal_block_length() -> BlockLength {
BlockLength::max_with_normal_ratio(MAX_BLOCK_LENGTH, NORMAL_DISPATCH_RATIO)
Expand Down
6 changes: 3 additions & 3 deletions crates/subspace-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ use subspace_runtime_primitives::utility::MaybeIntoUtilityCall;
use subspace_runtime_primitives::{
maximum_normal_block_length, AccountId, Balance, BlockNumber, FindBlockRewardAddress, Hash,
HoldIdentifier, Moment, Nonce, Signature, SlowAdjustingFeeUpdate, BLOCK_WEIGHT_FOR_2_SEC,
MAX_BLOCK_LENGTH, MIN_REPLICATION_FACTOR, NORMAL_DISPATCH_RATIO, SHANNON, SLOT_PROBABILITY,
SSC,
DOMAINS_BLOCK_PRUNING_DEPTH, MAX_BLOCK_LENGTH, MIN_REPLICATION_FACTOR, NORMAL_DISPATCH_RATIO,
SHANNON, SLOT_PROBABILITY, SSC,
};

sp_runtime::impl_opaque_keys! {
Expand Down Expand Up @@ -742,7 +742,7 @@ parameter_types! {
pub MaxDomainBlockWeight: Weight = maximum_domain_block_weight();
pub const DomainInstantiationDeposit: Balance = 100 * SSC;
pub const MaxDomainNameLength: u32 = 32;
pub const BlockTreePruningDepth: u32 = 14_400;
pub const BlockTreePruningDepth: u32 = DOMAINS_BLOCK_PRUNING_DEPTH;
pub const StakeWithdrawalLockingPeriod: DomainNumber = 14_400;
// TODO: revisit these. For now epoch every 10 mins for a 6 second block and only 100 number of staking
// operations allowed within each epoch.
Expand Down
16 changes: 7 additions & 9 deletions domains/client/domain-operator/src/aux_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use sp_runtime::Saturating;
use std::collections::BTreeSet;
use std::sync::Arc;
use subspace_core_primitives::BlockNumber;
use subspace_runtime_primitives::DOMAINS_PRUNING_DEPTH_MULTIPLIER;

const EXECUTION_RECEIPT: &[u8] = b"execution_receipt";
const EXECUTION_RECEIPT_START: &[u8] = b"execution_receipt_start";
Expand Down Expand Up @@ -42,9 +43,6 @@ const BEST_DOMAIN_HASH: &[u8] = b"best_domain_hash";
/// Tracks a list of tracked domain block hash keys at a given height.
const BEST_DOMAIN_HASH_KEYS: &[u8] = b"best_domain_hash_keys";

/// Pruning depth multiplier to prune receipts at and below the confirmation_depth_k * multiplier.
const PRUNING_DEPTH_MULTIPLIER: u32 = 2;

fn execution_receipt_key(block_hash: impl Encode) -> Vec<u8> {
(EXECUTION_RECEIPT, block_hash).encode()
}
Expand All @@ -69,7 +67,7 @@ pub(super) fn write_execution_receipt<Backend, Block, CBlock>(
backend: &Backend,
oldest_unconfirmed_receipt_number: Option<NumberFor<Block>>,
execution_receipt: &ExecutionReceiptFor<Block, CBlock>,
confirmation_depth_k: NumberFor<CBlock>,
challenge_period: NumberFor<CBlock>,
) -> Result<(), sp_blockchain::Error>
where
Backend: AuxStore,
Expand All @@ -94,7 +92,7 @@ where
let mut keys_to_delete = vec![];

if let Some(pruning_block_number) =
confirmation_depth_k.checked_mul(&PRUNING_DEPTH_MULTIPLIER.saturated_into())
challenge_period.checked_mul(&DOMAINS_PRUNING_DEPTH_MULTIPLIER.saturated_into())
{
// Delete ER that have confirmed long time ago
if let Some(delete_receipts_to) = oldest_unconfirmed_receipt_number
Expand Down Expand Up @@ -379,7 +377,7 @@ mod tests {
#[test]
fn normal_prune_execution_receipt_works() {
let block_tree_pruning_depth = 256;
let confirmation_depth_k = 500;
let challenge_period = 500;
let client = TestClient::default();

let receipt_start = || {
Expand Down Expand Up @@ -407,7 +405,7 @@ mod tests {
&client,
oldest_unconfirmed_receipt_number,
receipt,
confirmation_depth_k,
challenge_period,
)
.unwrap()
};
Expand Down Expand Up @@ -481,7 +479,7 @@ mod tests {
#[test]
fn execution_receipts_should_be_kept_against_oldest_unconfirmed_receipt_number() {
let block_tree_pruning_depth = 256;
let confirmation_depth_k = 500;
let challenge_period = 500;
let client = TestClient::default();

let receipt_start = || {
Expand All @@ -507,7 +505,7 @@ mod tests {
&client,
oldest_unconfirmed_receipt_number,
receipt,
confirmation_depth_k,
challenge_period,
)
.unwrap()
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ where
pub(crate) import_notification_sinks: DomainImportNotificationSinks<Block, CBlock>,
pub(crate) domain_sync_oracle: Arc<dyn SyncOracle + Send + Sync>,
pub(crate) domain_executor: Arc<Executor>,
pub(crate) confirmation_depth_k: NumberFor<CBlock>,
pub(crate) challenge_period: NumberFor<CBlock>,
}

impl<Block, CBlock, Client, CClient, Backend, Executor> Clone
Expand All @@ -86,7 +86,7 @@ where
import_notification_sinks: self.import_notification_sinks.clone(),
domain_sync_oracle: self.domain_sync_oracle.clone(),
domain_executor: self.domain_executor.clone(),
confirmation_depth_k: self.confirmation_depth_k,
challenge_period: self.challenge_period,
}
}
}
Expand Down Expand Up @@ -515,7 +515,7 @@ where
&*self.client,
oldest_unconfirmed_receipt_number,
&execution_receipt,
self.confirmation_depth_k,
self.challenge_period,
)?;

// Notify the imported domain block when the receipt processing is done.
Expand Down
1 change: 1 addition & 0 deletions domains/client/domain-operator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ pub struct OperatorParams<
pub bundle_sender: Arc<BundleSender<Block, CBlock>>,
pub operator_streams: OperatorStreams<CBlock, IBNS, CIBNS, NSNS, ASS>,
pub consensus_confirmation_depth_k: NumberFor<CBlock>,
pub challenge_period: NumberFor<CBlock>,
pub block_import: Arc<BoxBlockImport<Block>>,
pub skip_empty_bundle_production: bool,
pub skip_out_of_order_slot: bool,
Expand Down
4 changes: 2 additions & 2 deletions domains/client/domain-operator/src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ where
import_notification_sinks: Default::default(),
domain_sync_oracle: params.domain_sync_oracle.clone(),
domain_executor: params.code_executor.clone(),
confirmation_depth_k: params.consensus_confirmation_depth_k,
challenge_period: params.challenge_period,
};

let receipts_checker = ReceiptsChecker {
Expand Down Expand Up @@ -226,7 +226,7 @@ where
consensus_chain_sync_params: consensus_sync_params,
domain_fork_id: params.domain_fork_id,
receipt_provider: params.domain_execution_receipt_provider,
confirmation_depth_k: params.consensus_confirmation_depth_k,
challenge_period: params.challenge_period,
});

if let Some(sync_params) = sync_params {
Expand Down
4 changes: 2 additions & 2 deletions domains/client/domain-operator/src/snap_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ where
pub domain_block_downloader: Arc<dyn BlockDownloader<Block>>,
pub receipt_provider: Arc<dyn LastDomainBlockReceiptProvider<Block, CBlock>>,
pub consensus_chain_sync_params: ConsensusChainSyncParams<CBlock, CNR>,
pub confirmation_depth_k: NumberFor<CBlock>,
pub challenge_period: NumberFor<CBlock>,
}

async fn get_last_confirmed_block<Block: BlockT>(
Expand Down Expand Up @@ -416,7 +416,7 @@ where
sync_params.domain_client.as_ref(),
None,
&last_confirmed_block_receipt,
sync_params.confirmation_depth_k,
sync_params.challenge_period,
)?;

sync_params
Expand Down
2 changes: 1 addition & 1 deletion domains/client/domain-operator/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1304,7 +1304,7 @@ async fn test_processing_empty_consensus_block() {
import_notification_sinks: Default::default(),
domain_sync_oracle: ferdie.sync_service.clone(),
domain_executor: alice.code_executor.clone(),
confirmation_depth_k: 100u32,
challenge_period: 100u32,
};

let domain_genesis_hash = alice.client.info().best_hash;
Expand Down
Loading
Loading