Skip to content

Commit

Permalink
Change solochain flag into subcommand (#683)
Browse files Browse the repository at this point in the history
Instead of using tanssi-node --solochain to start a starlight collator, we will use tanssi-node solochain.

This allows us to simplify the argument parsing logic, and remove all the orchestrator args from start_solochain_node.
  • Loading branch information
tmpolaczyk authored Sep 24, 2024
1 parent b525601 commit 98e467c
Show file tree
Hide file tree
Showing 17 changed files with 874 additions and 275 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,11 @@ tap = "1.0.1"
# General (client)
async-io = "1.3"
async-trait = "0.1"
chrono = "0.4.31"
clap = { version = "4.5.3", default-features = false, features = [ "derive" ] }
core_extensions = "1.5.3"
exit-future = { version = "0.2.0" }
fdlimit = "0.3.0"
flume = "0.10.9"
fs2 = "0.4.3"
futures = { version = "0.3.1" }
Expand Down
49 changes: 40 additions & 9 deletions client/consensus/src/collators/lookahead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,32 @@ pub struct Params<
pub authoring_duration: Duration,
pub force_authoring: bool,
pub cancellation_token: CancellationToken,
pub orchestrator_tx_pool: Arc<TxPool>,
pub orchestrator_client: Arc<OClient>,
pub solochain: bool,
pub buy_core_params: BuyCoreParams<TxPool, OClient>,
}

pub enum BuyCoreParams<TxPool, OClient> {
Orchestrator {
orchestrator_tx_pool: Arc<TxPool>,
orchestrator_client: Arc<OClient>,
},
Solochain {
// TODO: relay_tx_pool
},
}

impl<TxPool, OClient> Clone for BuyCoreParams<TxPool, OClient> {
fn clone(&self) -> Self {
match self {
Self::Orchestrator {
orchestrator_tx_pool,
orchestrator_client,
} => Self::Orchestrator {
orchestrator_tx_pool: orchestrator_tx_pool.clone(),
orchestrator_client: orchestrator_client.clone(),
},
Self::Solochain {} => Self::Solochain {},
}
}
}

/// Run async-backing-friendly for Tanssi Aura.
Expand Down Expand Up @@ -637,12 +660,20 @@ where
let slot = inherent_providers.slot();
let container_chain_slot_duration = (params.get_current_slot_duration)(parent_header.hash());

let buy_core_result = if params.solochain {
// TODO: implement parathread support for solochain
log::warn!("Unimplemented: cannot buy core for parathread in solochain");
break;
} else {
try_to_buy_core::<_, _, <<OBlock as BlockT>::Header as HeaderT>::Number, _, CIDP, _, _>(params.para_id, aux_data, inherent_providers, &params.keystore, params.orchestrator_client.clone(), params.orchestrator_tx_pool.clone(), parent_header, params.orchestrator_slot_duration, container_chain_slot_duration).await
let buy_core_result = match &params.buy_core_params {
BuyCoreParams::Orchestrator {
orchestrator_client,
orchestrator_tx_pool,
} => {
try_to_buy_core::<_, _, <<OBlock as BlockT>::Header as HeaderT>::Number, _, CIDP, _, _>(params.para_id, aux_data, inherent_providers, &params.keystore, orchestrator_client.clone(), orchestrator_tx_pool.clone(), parent_header, params.orchestrator_slot_duration, container_chain_slot_duration).await
}
BuyCoreParams::Solochain {

} => {
// TODO: implement parathread support for solochain
log::warn!("Unimplemented: cannot buy core for parathread in solochain");
break;
}
};
match buy_core_result {
Ok(block_hash) => {
Expand Down
26 changes: 14 additions & 12 deletions client/consensus/src/mocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@

use {
crate::{
collators::lookahead::Params as LookAheadParams, OrchestratorAuraWorkerAuxData,
SlotFrequency,
collators::lookahead::{BuyCoreParams, Params as LookAheadParams},
OrchestratorAuraWorkerAuxData, SlotFrequency,
},
async_trait::async_trait,
cumulus_client_collator::service::CollatorService,
cumulus_client_consensus_common::{ParachainBlockImportMarker, ValidationCodeHashProvider},
cumulus_client_consensus_proposer::Proposer as ConsensusProposer,
cumulus_primitives_core::{relay_chain::BlockId, CollationInfo, CollectCollationInfo, ParaId},
cumulus_primitives_core::{
relay_chain::{BlockId, ValidationCodeHash},
CollationInfo, CollectCollationInfo, ParaId,
},
cumulus_relay_chain_interface::{
CommittedCandidateReceipt, OverseerHandle, RelayChainInterface, RelayChainResult,
StorageValue,
Expand All @@ -35,7 +38,10 @@ use {
pallet_xcm_core_buyer_runtime_api::BuyingError,
parity_scale_codec::Encode,
polkadot_core_primitives::{Header as PHeader, InboundDownwardMessage, InboundHrmpMessage},
polkadot_node_subsystem::messages::{RuntimeApiMessage, RuntimeApiRequest},
polkadot_node_subsystem::{
messages::{RuntimeApiMessage, RuntimeApiRequest},
overseer, OverseerSignal,
},
polkadot_overseer::dummy::dummy_overseer_builder,
polkadot_parachain_primitives::primitives::HeadData,
polkadot_primitives::{
Expand Down Expand Up @@ -512,11 +518,6 @@ impl<B: BlockT> sc_consensus::Verifier<B> for SealExtractorVerfier {
}
}

use {
cumulus_primitives_core::relay_chain::ValidationCodeHash,
polkadot_node_subsystem::{overseer, OverseerSignal},
};

pub struct DummyCodeHashProvider;
impl ValidationCodeHashProvider<PHash> for DummyCodeHashProvider {
fn code_hash_at(&self, _at: PHash) -> Option<ValidationCodeHash> {
Expand Down Expand Up @@ -984,10 +985,11 @@ impl CollatorLookaheadTestBuilder {
para_client: environ.clone().into(),
sync_oracle: DummyOracle,
para_backend: backend,
orchestrator_client: environ.into(),
buy_core_params: BuyCoreParams::Orchestrator {
orchestrator_client: environ.into(),
orchestrator_tx_pool: orchestrator_tx_pool.clone(),
},
orchestrator_slot_duration: SlotDuration::from_millis(SLOT_DURATION_MS),
orchestrator_tx_pool: orchestrator_tx_pool.clone(),
solochain: false,
};
let (fut, exit_notification_receiver) = crate::collators::lookahead::run::<
_,
Expand Down
2 changes: 2 additions & 0 deletions client/service-container-chain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ log = { workspace = true }
serde = { workspace = true }
tokio = { workspace = true }
tokio-util = { workspace = true }
url = { workspace = true }

# Local
ccp-authorities-noting-inherent = { workspace = true, features = [ "std" ] }
Expand Down Expand Up @@ -70,6 +71,7 @@ sp-timestamp = { workspace = true, features = [ "std" ] }
polkadot-primitives = { workspace = true }

# Cumulus
cumulus-client-cli = { workspace = true }
cumulus-client-collator = { workspace = true }
cumulus-client-consensus-aura = { workspace = true }
cumulus-client-consensus-common = { workspace = true }
Expand Down
125 changes: 111 additions & 14 deletions client/service-container-chain/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@

use {
crate::chain_spec::RawGenesisConfig,
cumulus_client_cli::{CollatorOptions, RelayChainMode},
dc_orchestrator_chain_interface::ContainerChainGenesisData,
dp_container_chain_genesis_data::json::properties_to_map,
sc_chain_spec::ChainSpec,
sc_cli::{CliConfiguration, SubstrateCli},
sc_network::config::MultiaddrWithPeerId,
sc_service::BasePath,
sp_runtime::Storage,
std::{collections::BTreeMap, net::SocketAddr, path::PathBuf},
std::{collections::BTreeMap, net::SocketAddr},
url::Url,
};

/// The `run` command used to run a container chain node.
Expand All @@ -45,16 +49,76 @@ pub struct ContainerChainRunCmd {
/// Keep container-chain db after changing collator assignments
#[arg(long)]
pub keep_db: bool,

/// Creates a less resource-hungry node that retrieves relay chain data from an RPC endpoint.
///
/// The provided URLs should point to RPC endpoints of the relay chain.
/// This node connects to the remote nodes following the order they were specified in. If the
/// connection fails, it attempts to connect to the next endpoint in the list.
///
/// Note: This option doesn't stop the node from connecting to the relay chain network but
/// reduces bandwidth use.
#[arg(
long,
value_parser = validate_relay_chain_url,
num_args = 0..,
alias = "relay-chain-rpc-url"
)]
pub relay_chain_rpc_urls: Vec<Url>,

/// EXPERIMENTAL: Embed a light client for the relay chain. Only supported for full-nodes.
/// Will use the specified relay chain chainspec.
#[arg(long, conflicts_with_all = ["relay_chain_rpc_urls", "collator"])]
pub relay_chain_light_client: bool,
}

impl ContainerChainRunCmd {
/// Create a [`NormalizedRunCmd`] which merges the `collator` cli argument into `validator` to
/// have only one.
pub fn normalize(&self) -> ContainerChainCli {
let mut new_base = self.clone();

new_base.base.validator = self.base.validator || self.collator;

// Append `containers/` to base_path for this object. This is to ensure that when spawning
// a new container chain, its database is always inside the `containers` folder.
// So if the user passes `--base-path /tmp/node`, we want the ephemeral container data in
// `/tmp/node/containers`, and the persistent storage in `/tmp/node/config`.
let base_path = base_path_or_default(
self.base.base_path().expect("failed to get base_path"),
&ContainerChainCli::executable_name(),
);

let base_path = base_path.path().join("containers");
new_base.base.shared_params.base_path = Some(base_path);

ContainerChainCli {
base: new_base,
preloaded_chain_spec: None,
}
}

/// Create [`CollatorOptions`] representing options only relevant to parachain collator nodes
// Copied from polkadot-sdk/cumulus/client/cli/src/lib.rs
pub fn collator_options(&self) -> CollatorOptions {
let relay_chain_mode = match (
self.relay_chain_light_client,
!self.relay_chain_rpc_urls.is_empty(),
) {
(true, _) => RelayChainMode::LightClient,
(_, true) => RelayChainMode::ExternalRpc(self.relay_chain_rpc_urls.clone()),
_ => RelayChainMode::Embedded,
};

CollatorOptions { relay_chain_mode }
}
}

#[derive(Debug)]
pub struct ContainerChainCli {
/// The actual container chain cli object.
pub base: ContainerChainRunCmd,

/// The base path that should be used by the container chain.
pub base_path: PathBuf,

/// The ChainSpecs that this struct can initialize. This starts empty and gets filled
/// by calling preload_chain_spec_file.
pub preloaded_chain_spec: Option<Box<dyn sc_chain_spec::ChainSpec>>,
Expand All @@ -64,7 +128,6 @@ impl Clone for ContainerChainCli {
fn clone(&self) -> Self {
Self {
base: self.base.clone(),
base_path: self.base_path.clone(),
preloaded_chain_spec: self.preloaded_chain_spec.as_ref().map(|x| x.cloned_box()),
}
}
Expand All @@ -76,13 +139,27 @@ impl ContainerChainCli {
para_config: &sc_service::Configuration,
container_chain_args: impl Iterator<Item = &'a String>,
) -> Self {
let base_path = para_config.base_path.path().join("containers");
let mut base: ContainerChainRunCmd = clap::Parser::parse_from(container_chain_args);

Self {
base_path,
base: clap::Parser::parse_from(container_chain_args),
preloaded_chain_spec: None,
// Copy some parachain args into container chain args

// If the container chain args have no --wasmtime-precompiled flag, use the same as the orchestrator
if base.base.import_params.wasmtime_precompiled.is_none() {
base.base
.import_params
.wasmtime_precompiled
.clone_from(&para_config.wasmtime_precompiled);
}

// Set container base path to the same value as orchestrator base_path.
// "containers" is appended in `base.normalize()`
if base.base.shared_params.base_path.is_some() {
log::warn!("Container chain --base-path is being ignored");
}
let base_path = para_config.base_path.path().to_owned();
base.base.shared_params.base_path = Some(base_path);

base.normalize()
}

pub fn chain_spec_from_genesis_data(
Expand Down Expand Up @@ -249,10 +326,7 @@ impl sc_cli::CliConfiguration<Self> for ContainerChainCli {
}

fn base_path(&self) -> sc_cli::Result<Option<sc_service::BasePath>> {
Ok(self
.shared_params()
.base_path()?
.or_else(|| Some(self.base_path.clone().into())))
self.shared_params().base_path()
}

fn rpc_addr(&self, default_listen_port: u16) -> sc_cli::Result<Option<SocketAddr>> {
Expand Down Expand Up @@ -366,3 +440,26 @@ fn parse_container_chain_id_str(id: &str) -> std::result::Result<u32, String> {
})
.ok_or_else(|| format!("load_spec called with invalid id: {:?}", id))
}

// Copied from polkadot-sdk/cumulus/client/cli/src/lib.rs
fn validate_relay_chain_url(arg: &str) -> Result<Url, String> {
let url = Url::parse(arg).map_err(|e| e.to_string())?;

let scheme = url.scheme();
if scheme == "ws" || scheme == "wss" {
Ok(url)
} else {
Err(format!(
"'{}' URL scheme not supported. Only websocket RPC is currently supported",
url.scheme()
))
}
}

/// Returns the value of `base_path` or the default_path if it is None
pub(crate) fn base_path_or_default(
base_path: Option<BasePath>,
executable_name: &String,
) -> BasePath {
base_path.unwrap_or_else(|| BasePath::from_project("", "", executable_name))
}
Loading

0 comments on commit 98e467c

Please sign in to comment.