diff --git a/crates/sc-consensus-subspace/Cargo.toml b/crates/sc-consensus-subspace/Cargo.toml index c1ba02ada4..4d6d650e60 100644 --- a/crates/sc-consensus-subspace/Cargo.toml +++ b/crates/sc-consensus-subspace/Cargo.toml @@ -62,7 +62,3 @@ tracing = "0.1.40" #substrate-test-runtime = { version = "2.0.0", path = "../../substrate/substrate-test-runtime" } #substrate-test-runtime-client = { version = "2.0.0", path = "../../substrate/substrate-test-runtime-client" } #tokio = "1.27.0" - -[features] -# Temporary feature, TODO: replace with a CLI option -full-archive = [] diff --git a/crates/sc-consensus-subspace/src/archiver.rs b/crates/sc-consensus-subspace/src/archiver.rs index 3b1935907d..528566b069 100644 --- a/crates/sc-consensus-subspace/src/archiver.rs +++ b/crates/sc-consensus-subspace/src/archiver.rs @@ -360,6 +360,7 @@ fn find_last_archived_block( client: &Client, segment_headers_store: &SegmentHeadersStore, best_block_to_archive: NumberFor, + create_object_mappings: bool, ) -> sp_blockchain::Result, BlockObjectMapping)>> where Block: BlockT, @@ -399,8 +400,7 @@ where .block(last_archived_block_hash)? .expect("Last archived block must always be retrievable; qed"); - // RPC clients only want these mappings in full mapping mode - let block_object_mappings = if cfg!(feature = "full-archive") { + let block_object_mappings = if create_object_mappings { client .runtime_api() .extract_block_object_mapping( @@ -542,6 +542,7 @@ fn initialize_archiver( segment_headers_store: &SegmentHeadersStore, subspace_link: &SubspaceLink, client: &Client, + create_object_mappings: bool, ) -> sp_blockchain::Result> where Block: BlockT, @@ -567,8 +568,12 @@ where best_block_to_archive = best_block_number; } - let maybe_last_archived_block = - find_last_archived_block(client, segment_headers_store, best_block_to_archive.into())?; + let maybe_last_archived_block = find_last_archived_block( + client, + segment_headers_store, + best_block_to_archive.into(), + create_object_mappings, + )?; let have_last_segment_header = maybe_last_archived_block.is_some(); let mut best_archived_block = None; @@ -659,8 +664,7 @@ where .block(block_hash)? .expect("All blocks since last archived must be present; qed"); - // RPC clients only want these mappings in full mapping mode - let block_object_mappings = if cfg!(feature = "full-archive") { + let block_object_mappings = if create_object_mappings { runtime_api .extract_block_object_mapping( *block.block.header().parent_hash(), @@ -781,8 +785,8 @@ fn finalize_block( /// processing, which is necessary for ensuring that when the next block is imported, inherents will /// contain segment header of newly archived block (must happen exactly in the next block). /// -/// When a block with object mappings is produced, notification ([`SubspaceLink::object_mapping_notification_stream`]) -/// will be sent. +/// If `create_object_mappings` is set, when a block with object mappings is archived, notification +/// ([`SubspaceLink::object_mapping_notification_stream`]) will be sent. /// /// Once segment header is archived, notification ([`SubspaceLink::archived_segment_notification_stream`]) /// will be sent and archiver will be paused until all receivers have provided an acknowledgement @@ -797,6 +801,7 @@ pub fn create_subspace_archiver( client: Arc, sync_oracle: SubspaceSyncOracle, telemetry: Option, + create_object_mappings: bool, ) -> sp_blockchain::Result> + Send + 'static> where Block: BlockT, @@ -819,6 +824,7 @@ where &segment_headers_store, &subspace_link, client.as_ref(), + create_object_mappings, )?) } else { None @@ -832,7 +838,12 @@ where Ok(async move { let archiver = match maybe_archiver { Some(archiver) => archiver, - None => initialize_archiver(&segment_headers_store, &subspace_link, client.as_ref())?, + None => initialize_archiver( + &segment_headers_store, + &subspace_link, + client.as_ref(), + create_object_mappings, + )?, }; let confirmation_depth_k = subspace_link.chain_constants.confirmation_depth_k().into(); @@ -870,9 +881,9 @@ where "Checking if block needs to be skipped" ); - // TODO: turn this into a command-line argument named `--full-mapping` - let skip_last_archived_blocks = last_archived_block_number > block_number_to_archive - && !cfg!(feature = "full-archive"); + // Skip archived blocks, unless we're producing object mappings for the full history + let skip_last_archived_blocks = + last_archived_block_number > block_number_to_archive && !create_object_mappings; if best_archived_block_number >= block_number_to_archive || skip_last_archived_blocks { // This block was already archived, skip debug!( @@ -893,7 +904,12 @@ where InitializedArchiver { archiver, best_archived_block: (best_archived_block_hash, best_archived_block_number), - } = initialize_archiver(&segment_headers_store, &subspace_link, client.as_ref())?; + } = initialize_archiver( + &segment_headers_store, + &subspace_link, + client.as_ref(), + create_object_mappings, + )?; if best_archived_block_number + One::one() == block_number_to_archive { // As expected, can continue now @@ -934,6 +950,7 @@ where subspace_link.archived_segment_notification_sender.clone(), best_archived_block_hash, block_number_to_archive, + create_object_mappings, ) .await?; } @@ -954,6 +971,7 @@ async fn archive_block( archived_segment_notification_sender: SubspaceNotificationSender, best_archived_block_hash: Block::Hash, block_number_to_archive: NumberFor, + create_object_mappings: bool, ) -> sp_blockchain::Result<(Block::Hash, NumberFor)> where Block: BlockT, @@ -998,14 +1016,18 @@ where ))); } - let block_object_mappings = client - .runtime_api() - .extract_block_object_mapping(parent_block_hash, block.block.clone()) - .map_err(|error| { - sp_blockchain::Error::Application( - format!("Failed to retrieve block object mappings: {error}").into(), - ) - })?; + let block_object_mappings = if create_object_mappings { + client + .runtime_api() + .extract_block_object_mapping(parent_block_hash, block.block.clone()) + .map_err(|error| { + sp_blockchain::Error::Application( + format!("Failed to retrieve block object mappings: {error}").into(), + ) + })? + } else { + BlockObjectMapping::default() + }; let encoded_block = encode_block(block); debug!( diff --git a/crates/subspace-malicious-operator/src/bin/subspace-malicious-operator.rs b/crates/subspace-malicious-operator/src/bin/subspace-malicious-operator.rs index f3b846b280..101067b5fe 100644 --- a/crates/subspace-malicious-operator/src/bin/subspace-malicious-operator.rs +++ b/crates/subspace-malicious-operator/src/bin/subspace-malicious-operator.rs @@ -199,6 +199,7 @@ fn main() -> Result<(), Error> { base: consensus_chain_config, // Domain node needs slots notifications for bundle production. force_new_slot_notifications: true, + create_object_mappings: true, subspace_networking: SubspaceNetworking::Create { config: dsn_config }, dsn_piece_getter: None, sync: Default::default(), diff --git a/crates/subspace-node/src/commands/run/consensus.rs b/crates/subspace-node/src/commands/run/consensus.rs index b027d03ca9..f589d5a6f4 100644 --- a/crates/subspace-node/src/commands/run/consensus.rs +++ b/crates/subspace-node/src/commands/run/consensus.rs @@ -333,6 +333,7 @@ pub(super) struct ConsensusChainOptions { /// * `--tmp` (unless `--base-path` specified explicitly) /// * `--force-synced` /// * `--force-authoring` + /// * `--create-object-mappings` /// * `--allow-private-ips` /// * `--rpc-cors all` (unless specified explicitly) /// * `--dsn-disable-bootstrap-on-start` @@ -389,6 +390,13 @@ pub(super) struct ConsensusChainOptions { #[arg(long)] force_authoring: bool, + /// Create object mappings for new blocks, and blocks that have already been archived. + /// By default, mappings are not created for any blocks. + /// + /// --dev mode enables this option automatically. + #[arg(long)] + create_object_mappings: bool, + /// External entropy, used initially when PoT chain starts to derive the first seed #[arg(long)] pot_external_entropy: Option, @@ -446,6 +454,7 @@ pub(super) fn create_consensus_chain_configuration( pool_config, mut force_synced, mut force_authoring, + mut create_object_mappings, pot_external_entropy, dsn_options, storage_monitor, @@ -466,6 +475,7 @@ pub(super) fn create_consensus_chain_configuration( tmp = true; force_synced = true; force_authoring = true; + create_object_mappings = true; network_options.allow_private_ips = true; timekeeper_options.timekeeper = true; @@ -677,6 +687,7 @@ pub(super) fn create_consensus_chain_configuration( base: consensus_chain_config, // Domain node needs slots notifications for bundle production. force_new_slot_notifications: domains_enabled, + create_object_mappings, subspace_networking: SubspaceNetworking::Create { config: dsn_config }, dsn_piece_getter: None, sync, diff --git a/crates/subspace-service/src/config.rs b/crates/subspace-service/src/config.rs index 60b606ee5c..80fe6bd3e7 100644 --- a/crates/subspace-service/src/config.rs +++ b/crates/subspace-service/src/config.rs @@ -302,6 +302,8 @@ pub struct SubspaceConfiguration { /// Whether slot notifications need to be present even if node is not responsible for block /// authoring. pub force_new_slot_notifications: bool, + /// Create object mappings for new blocks, and blocks that have already been archived. + pub create_object_mappings: bool, /// Subspace networking (DSN). pub subspace_networking: SubspaceNetworking, /// DSN piece getter diff --git a/crates/subspace-service/src/lib.rs b/crates/subspace-service/src/lib.rs index da826734a6..7e485d7821 100644 --- a/crates/subspace-service/src/lib.rs +++ b/crates/subspace-service/src/lib.rs @@ -1043,6 +1043,7 @@ where client.clone(), sync_oracle.clone(), telemetry.as_ref().map(|telemetry| telemetry.handle()), + config.create_object_mappings, ) }) .map_err(ServiceError::Client)?;