From 4bc92161fdbe783dfa71bf78d1744d8b0b1a149b Mon Sep 17 00:00:00 2001 From: linning Date: Tue, 12 Sep 2023 00:22:34 +0800 Subject: [PATCH 1/4] Add domain subcommand export-execution-receipt to query the ER from the auxiliary storage of the operator Signed-off-by: linning --- Cargo.lock | 1 + crates/subspace-node/Cargo.toml | 1 + crates/subspace-node/src/bin/subspace-node.rs | 29 +++++ crates/subspace-node/src/domain/cli.rs | 118 +++++++++++++++++- .../client/domain-operator/src/aux_schema.rs | 2 +- domains/client/domain-operator/src/lib.rs | 1 + 6 files changed, 148 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b977275dba..d222b9ed2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11536,6 +11536,7 @@ dependencies = [ "sp-consensus", "sp-consensus-subspace", "sp-core", + "sp-domain-digests", "sp-domains", "sp-messenger", "sp-runtime", diff --git a/crates/subspace-node/Cargo.toml b/crates/subspace-node/Cargo.toml index 636b11d463..058561ec02 100644 --- a/crates/subspace-node/Cargo.toml +++ b/crates/subspace-node/Cargo.toml @@ -62,6 +62,7 @@ sp-consensus = { version = "0.10.0-dev", git = "https://github.com/subspace/subs sp-consensus-subspace = { version = "0.1.0", path = "../sp-consensus-subspace" } sp-core = { version = "21.0.0", git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" } sp-domains = { version = "0.1.0", path = "../sp-domains" } +sp-domain-digests = { version = "0.1.0", path = "../../domains/primitives/digests" } sp-messenger = { version = "0.1.0", path = "../../domains/primitives/messenger" } sp-runtime = { version = "24.0.0", git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" } subspace-archiving = { version = "0.1.0", path = "../subspace-archiving" } diff --git a/crates/subspace-node/src/bin/subspace-node.rs b/crates/subspace-node/src/bin/subspace-node.rs index db45cd6ae7..603029adf4 100644 --- a/crates/subspace-node/src/bin/subspace-node.rs +++ b/crates/subspace-node/src/bin/subspace-node.rs @@ -399,6 +399,35 @@ fn main() -> Result<(), Error> { })?; } DomainSubcommand::BuildGenesisConfig(cmd) => cmd.run()?, + DomainSubcommand::ExportExecutionReceipt(cmd) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|consensus_chain_config| { + let domain_cli = DomainCli::new( + cli.run + .base_path()? + .map(|base_path| base_path.path().to_path_buf()), + cmd.domain_args.clone().into_iter(), + ); + let domain_config = domain_cli + .create_domain_configuration(consensus_chain_config.tokio_handle) + .map_err(|error| { + sc_service::Error::Other(format!( + "Failed to create domain configuration: {error:?}" + )) + })?; + + let executor: sc_executor::NativeElseWasmExecutor = + sc_service::new_native_or_wasm_executor(&domain_config); + + let (client, _, _, _) = sc_service::new_full_parts::< + DomainBlock, + evm_domain_runtime::RuntimeApi, + _, + >(&domain_config, None, executor)?; + + cmd.run(&client, &client) + })?; + } _ => unimplemented!("Domain subcommand"), }, None => { diff --git a/crates/subspace-node/src/domain/cli.rs b/crates/subspace-node/src/domain/cli.rs index 9c1f6e33cf..a4452c2713 100644 --- a/crates/subspace-node/src/domain/cli.rs +++ b/crates/subspace-node/src/domain/cli.rs @@ -16,18 +16,26 @@ use crate::domain::evm_chain_spec::{self, SpecId}; use clap::Parser; +use domain_runtime_primitives::opaque::Block as DomainBlock; use sc_cli::{ - ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, - NetworkParams, Result, Role, RunCmd as SubstrateRunCmd, RuntimeVersion, SharedParams, - SubstrateCli, + BlockNumberOrHash, ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, + KeystoreParams, NetworkParams, Result, Role, RunCmd as SubstrateRunCmd, RuntimeVersion, + SharedParams, SubstrateCli, }; +use sc_client_api::backend::AuxStore; use sc_service::config::PrometheusConfig; use sc_service::{BasePath, Configuration}; +use sp_blockchain::HeaderBackend; +use sp_domain_digests::AsPredigest; use sp_domains::DomainId; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::Header; +use sp_runtime::DigestItem; use std::io::Write; use std::net::SocketAddr; use std::num::ParseIntError; use std::path::PathBuf; +use subspace_runtime::Block; /// Sub-commands supported by the executor. #[derive(Debug, clap::Subcommand)] @@ -45,6 +53,9 @@ pub enum Subcommand { /// Build the genesis config of the evm domain chain in json format BuildGenesisConfig(BuildGenesisConfigCmd), + + /// The `export-execution-receipt` command used to get the ER from the auxiliary storage of the operator client + ExportExecutionReceipt(ExportExecutionReceiptCmd), } fn parse_domain_id(s: &str) -> std::result::Result { @@ -320,3 +331,104 @@ impl BuildGenesisConfigCmd { Ok(()) } } + +/// The `export-execution-receipt` command used to get the ER from the auxiliary storage of the operator client +#[derive(Debug, Clone, Parser)] +pub struct ExportExecutionReceiptCmd { + /// Get the `ExecutionReceipt` by domain block number or hash + #[arg(long, conflicts_with_all = &["consensus_block_hash"])] + pub domain_block: Option, + + /// Get the `ExecutionReceipt` by consensus block hash + #[arg(long, conflicts_with_all = &["domain_block"])] + pub consensus_block_hash: Option, + + /// The base struct of the export-execution-receipt command. + #[clap(flatten)] + pub shared_params: SharedParams, + + /// Domain arguments + /// + /// The command-line arguments provided first will be passed to the embedded consensus node, + /// while the arguments provided after `--` will be passed to the domain node. + /// + /// subspace-node export-execution-receipt [consensus-chain-args] -- [domain-args] + #[arg(raw = true)] + pub domain_args: Vec, +} + +impl CliConfiguration for ExportExecutionReceiptCmd { + fn shared_params(&self) -> &SharedParams { + &self.shared_params + } +} + +impl ExportExecutionReceiptCmd { + /// Run the export-execution-receipt command + pub fn run( + &self, + domain_client: &Client, + domain_backend: &Backend, + ) -> sc_cli::Result<()> + where + Backend: AuxStore, + Client: HeaderBackend, + { + let consensus_block_hash = match (&self.consensus_block_hash, &self.domain_block) { + // Get ER by consensus block hash + (Some(raw_consensus_block_hash), None) => { + match raw_consensus_block_hash.parse::()? { + BlockId::Hash(h) => h, + BlockId::Number(_) => { + eprintln!( + "unexpected input {raw_consensus_block_hash:?}, expected consensus block hash", + ); + return Ok(()); + } + } + } + // Get ER by domain block hash or number + (None, Some(raw_domain_block)) => { + let domain_block_hash = match raw_domain_block.parse::()? { + BlockId::Hash(h) => h, + BlockId::Number(number) => domain_client.hash(number)?.ok_or_else(|| { + sp_blockchain::Error::Backend(format!( + "Domain block hash for #{number:?} not found", + )) + })?, + }; + let domain_header = domain_client.header(domain_block_hash)?.ok_or_else(|| { + sp_blockchain::Error::Backend(format!( + "Header for domain block {domain_block_hash:?} not found" + )) + })?; + + domain_header + .digest() + .convert_first(DigestItem::as_consensus_block_info) + .ok_or_else(|| { + sp_blockchain::Error::Application(Box::from( + "Domain block header for {domain_hash:?} must have consensus block info predigest" + )) + })? + } + _ => { + eprintln!("Expect the domain-block or consensus-block-hash argument",); + return Ok(()); + } + }; + + match domain_client_operator::load_execution_receipt::( + domain_backend, + consensus_block_hash, + )? { + Some(er) => { + println!("ExecutionReceipt of consensus block {consensus_block_hash:?}:\n{er:?}",); + } + None => { + println!("ExecutionReceipt of consensus block {consensus_block_hash:?} not found",); + } + } + Ok(()) + } +} diff --git a/domains/client/domain-operator/src/aux_schema.rs b/domains/client/domain-operator/src/aux_schema.rs index da1438e73b..01bfb41f48 100644 --- a/domains/client/domain-operator/src/aux_schema.rs +++ b/domains/client/domain-operator/src/aux_schema.rs @@ -145,7 +145,7 @@ where } /// Load the execution receipt for given consensus block hash. -pub(super) fn load_execution_receipt( +pub fn load_execution_receipt( backend: &Backend, consensus_block_hash: CBlock::Hash, ) -> ClientResult>> diff --git a/domains/client/domain-operator/src/lib.rs b/domains/client/domain-operator/src/lib.rs index 42032858f6..d4013e0b2e 100644 --- a/domains/client/domain-operator/src/lib.rs +++ b/domains/client/domain-operator/src/lib.rs @@ -77,6 +77,7 @@ mod parent_chain; mod tests; mod utils; +pub use self::aux_schema::load_execution_receipt; pub use self::bootstrapper::{BootstrapResult, Bootstrapper}; pub use self::operator::Operator; pub use self::parent_chain::DomainParentChain; From d41cc74d7b2ea94a4aa232ff0748beee348e18af Mon Sep 17 00:00:00 2001 From: Shamil Gadelshin Date: Wed, 13 Sep 2023 15:36:15 +0700 Subject: [PATCH 2/4] node: Enable DSN piece requests. --- crates/subspace-service/src/dsn.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/subspace-service/src/dsn.rs b/crates/subspace-service/src/dsn.rs index 66b84e2c48..16400ce1d2 100644 --- a/crates/subspace-service/src/dsn.rs +++ b/crates/subspace-service/src/dsn.rs @@ -12,8 +12,8 @@ use subspace_networking::libp2p::{identity, Multiaddr}; use subspace_networking::utils::strip_peer_id; use subspace_networking::{ CreationError, NetworkParametersPersistenceError, NetworkingParametersManager, Node, - NodeRunner, PeerInfoProvider, SegmentHeaderBySegmentIndexesRequestHandler, - SegmentHeaderRequest, SegmentHeaderResponse, + NodeRunner, PeerInfoProvider, PieceByIndexRequestHandler, + SegmentHeaderBySegmentIndexesRequestHandler, SegmentHeaderRequest, SegmentHeaderResponse, }; use thiserror::Error; use tracing::{debug, error, trace}; @@ -118,8 +118,10 @@ where listen_on: dsn_config.listen_on, allow_non_global_addresses_in_dht: dsn_config.allow_non_global_addresses_in_dht, networking_parameters_registry, - request_response_protocols: vec![SegmentHeaderBySegmentIndexesRequestHandler::create( - move |_, req| { + request_response_protocols: vec![ + // We need to enable protocol to request pieces + PieceByIndexRequestHandler::create(|_, _| async { None }), + SegmentHeaderBySegmentIndexesRequestHandler::create(move |_, req| { let segment_indexes = match req { SegmentHeaderRequest::SegmentIndexes { segment_indexes } => { segment_indexes.clone() @@ -168,8 +170,8 @@ where }; async move { result } - }, - )], + }), + ], max_established_incoming_connections: dsn_config.max_in_connections, max_established_outgoing_connections: dsn_config.max_out_connections, max_pending_incoming_connections: dsn_config.max_pending_in_connections, From 76ad9b1f3ad44959f5e5b89ff81fcad2cd07023f Mon Sep 17 00:00:00 2001 From: Shamil Gadelshin Date: Wed, 13 Sep 2023 15:55:11 +0700 Subject: [PATCH 3/4] node: Tweak default CLI arguments (connections). --- crates/subspace-node/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/subspace-node/src/lib.rs b/crates/subspace-node/src/lib.rs index d1905bf243..d70d95e2ef 100644 --- a/crates/subspace-node/src/lib.rs +++ b/crates/subspace-node/src/lib.rs @@ -217,7 +217,7 @@ pub struct Cli { pub dsn_in_connections: u32, /// Defines max established outgoing swarm connection limit for DSN. - #[arg(long, default_value_t = 100)] + #[arg(long, default_value_t = 150)] pub dsn_out_connections: u32, /// Defines max pending incoming connection limit for DSN. @@ -225,11 +225,11 @@ pub struct Cli { pub dsn_pending_in_connections: u32, /// Defines max pending outgoing swarm connection limit for DSN. - #[arg(long, default_value_t = 100)] + #[arg(long, default_value_t = 150)] pub dsn_pending_out_connections: u32, /// Defines target total (in and out) connection number for DSN that should be maintained. - #[arg(long, default_value_t = 50)] + #[arg(long, default_value_t = 30)] pub dsn_target_connections: u32, /// Determines whether we allow keeping non-global (private, shared, loopback..) addresses From 40e7a4c9d4d9aeb9ccf026228b0de69fe464aefd Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Wed, 13 Sep 2023 20:18:44 +0300 Subject: [PATCH 4/4] Fix DSN sync --- .../src/sync_from_dsn/import_blocks.rs | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/crates/subspace-service/src/sync_from_dsn/import_blocks.rs b/crates/subspace-service/src/sync_from_dsn/import_blocks.rs index dfb5affcb6..604b08967c 100644 --- a/crates/subspace-service/src/sync_from_dsn/import_blocks.rs +++ b/crates/subspace-service/src/sync_from_dsn/import_blocks.rs @@ -216,17 +216,21 @@ where } } - // Import queue handles verification and importing it into the client - let last_segment = segment_indices_iter.peek().is_none(); - if last_segment { - let last_block = blocks_to_import - .pop() - .expect("Not empty, checked above; qed"); - import_queue_service.import_blocks(BlockOrigin::NetworkInitialSync, blocks_to_import); - // This will notify Substrate's sync mechanism and allow regular Substrate sync to continue gracefully - import_queue_service.import_blocks(BlockOrigin::NetworkBroadcast, vec![last_block]); - } else { - import_queue_service.import_blocks(BlockOrigin::NetworkInitialSync, blocks_to_import); + if !blocks_to_import.is_empty() { + // Import queue handles verification and importing it into the client + let last_segment = segment_indices_iter.peek().is_none(); + if last_segment { + let last_block = blocks_to_import + .pop() + .expect("Not empty, checked above; qed"); + import_queue_service + .import_blocks(BlockOrigin::NetworkInitialSync, blocks_to_import); + // This will notify Substrate's sync mechanism and allow regular Substrate sync to continue gracefully + import_queue_service.import_blocks(BlockOrigin::NetworkBroadcast, vec![last_block]); + } else { + import_queue_service + .import_blocks(BlockOrigin::NetworkInitialSync, blocks_to_import); + } } *last_processed_segment_index = segment_index;