Skip to content

Commit

Permalink
experimental: put runtime and preset into SharedParams
Browse files Browse the repository at this point in the history
  • Loading branch information
kianenigma committed Jul 24, 2024
1 parent be5e541 commit 3e55a98
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 24 deletions.
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.

23 changes: 23 additions & 0 deletions substrate/bin/node/cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,29 @@ impl SubstrateCli for Cli {
};
Ok(spec)
}

fn load_spec_from_runtime(
&self,
runtime: &[u8],
maybe_preset: Option<&str>,
) -> std::result::Result<Box<dyn sc_cli::ChainSpec>, String> {
use sc_service::{ChainType, Properties};
let mut properties = Properties::new();
properties.insert("tokenDecimals".to_string(), 12.into());
properties.insert("tokenSymbol".to_string(), "SUB-DEV".into());

let mut builder = chain_spec::ChainSpec::builder(runtime.as_ref(), Default::default())
.with_name("Development")
.with_id("dev")
.with_chain_type(ChainType::Development)
.with_properties(properties);

if let Some(preset) = maybe_preset {
builder = builder.with_genesis_config_preset_name(preset);
}

Ok(Box::new(builder.build()))
}
}

/// Parse command line arguments into service configuration.
Expand Down
22 changes: 22 additions & 0 deletions substrate/client/chain-spec/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ enum GenesisBuildAction<EHF> {
NamedPreset(String, PhantomData<EHF>),
}

impl<T> std::fmt::Debug for GenesisBuildAction<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Patch(_) => write!(f, "Patch)"),
Self::Full(_) => write!(f, "Full"),
Self::NamedPreset(ref p, _) => write!(f, "NamedPreset({:?})", p),
}
}
}

impl<EHF> Clone for GenesisBuildAction<EHF> {
fn clone(&self) -> Self {
match self {
Expand All @@ -66,6 +76,17 @@ enum GenesisSource<EHF> {
GenesisBuilderApi(GenesisBuildAction<EHF>, Vec<u8>),
}

impl<T> std::fmt::Debug for GenesisSource<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::File(ref path) => write!(f, "File({:?})", path),
Self::Binary(_) => write!(f, "Binary"),
Self::Storage(_) => write!(f, "Storage"),
Self::GenesisBuilderApi(_, _) => write!(f, "GenesisBuilderApi"),
}
}
}

impl<EHF> Clone for GenesisSource<EHF> {
fn clone(&self) -> Self {
match *self {
Expand All @@ -79,6 +100,7 @@ impl<EHF> Clone for GenesisSource<EHF> {

impl<EHF: HostFunctions> GenesisSource<EHF> {
fn resolve(&self) -> Result<Genesis, String> {
// println!("self = {:?}", self);
/// helper container for deserializing genesis from the JSON file (ChainSpec JSON file is
/// also supported here)
#[derive(Serialize, Deserialize)]
Expand Down
2 changes: 1 addition & 1 deletion substrate/client/chain-spec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ pub trait ChainSpec: BuildStorage + Send + Sync {
fn add_boot_node(&mut self, addr: MultiaddrWithPeerId);
/// Return spec as JSON.
fn as_json(&self, raw: bool) -> Result<String, String>;
/// Return StorageBuilder for this spec.
/// Return `StorageBuilder` for this spec.
fn as_storage_builder(&self) -> &dyn BuildStorage;
/// Returns a cloned `Box<dyn ChainSpec>`.
fn cloned_box(&self) -> Box<dyn ChainSpec>;
Expand Down
1 change: 1 addition & 0 deletions substrate/client/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ sp-keystore = { workspace = true, default-features = true }
sp-panic-handler = { workspace = true, default-features = true }
sp-runtime = { workspace = true, default-features = true }
sp-version = { workspace = true, default-features = true }
sp-genesis-builder = { workspace = true, default-features = true }

[dev-dependencies]
tempfile = { workspace = true }
Expand Down
26 changes: 25 additions & 1 deletion substrate/client/cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ pub(crate) const DEFAULT_NETWORK_CONFIG_PATH: &str = "network";
/// The recommended open file descriptor limit to be configured for the process.
const RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT: u64 = 10_000;

/// The default 'development' preset used to communicate with the runtime via
/// [`sp_genesis_builder`].
pub const DEV_RUNTIME_PRESET: &'static str = "dev";

/// The default port.
pub const RPC_DEFAULT_PORT: u16 = 9944;
/// The default max number of subscriptions per connection.
Expand Down Expand Up @@ -466,6 +470,20 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
Ok(true)
}

/// The genesis preset to use when `--runtime` is being used.
fn genesis_preset(&self, is_dev: bool) -> Option<&str> {
self.shared_params().genesis_preset.as_ref().map_or_else(
|| {
if is_dev {
Some(DEV_RUNTIME_PRESET.as_ref())
} else {
None
}
},
|p| Some(p.as_str()),
)
}

/// Create a Configuration object from the current object
fn create_configuration<C: SubstrateCli>(
&self,
Expand All @@ -474,7 +492,13 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
) -> Result<Configuration> {
let is_dev = self.is_dev()?;
let chain_id = self.chain_id(is_dev)?;
let chain_spec = cli.load_spec(&chain_id)?;
let chain_spec = if let Some(runtime_path) = self.shared_params().runtime.as_ref() {
let runtime = std::fs::read(runtime_path)
.map_err(|e| format!("Failed to read runtime: {}", e))?;
cli.load_spec_from_runtime(&runtime, self.genesis_preset(is_dev))?
} else {
cli.load_spec(&chain_id)?
};
let base_path = base_path_or_default(self.base_path()?, &C::executable_name());
let config_dir = build_config_dir(&base_path, chain_spec.id());
let net_config_dir = build_net_config_dir(&config_dir);
Expand Down
39 changes: 37 additions & 2 deletions substrate/client/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ mod signals;
pub use arg_enums::*;
pub use clap;
pub use commands::*;
pub use config::*;
pub use config::{DEV_RUNTIME_PRESET, *};
pub use error::*;
pub use params::*;
pub use runner::*;
Expand Down Expand Up @@ -89,9 +89,44 @@ pub trait SubstrateCli: Sized {
/// Copyright starting year (x-current year)
fn copyright_start_year() -> i32;

/// Chain spec factory
/// Build the chain spec of a chain, with the given "chain-id".
///
/// This function is exposed to substrate-based-nodes so that they can specify their own special
/// chain-id -> chain-spec mappings. For example, a bitcoin chain might specify
///
/// ```
/// fn main() {
/// # let chain_id = "something";
/// match chain_id
/// "bitcoin" => { todo!() }
/// "bitcoing-dev" => { todo!() }
/// "bitcoing-local" => { todo!() }
/// _ => { todo!("we interpret the chain-id as a path to a pre-generated chain-spec") }
/// }
/// }
/// ```
///
/// By convention, many substrate-based chains follow a similar pattern here, and expose `-dev`
/// and `-local` as special expected chain-ids.
fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn ChainSpec>, String>;

/// Construct a chain-spec on the fly, from the given runtime and preset name.
///
/// This is the other counter-part of [`load_spec`], and can be used to create chain-specs from
/// a wam blob, and a given preset name. Not all fields of the chain-spec are configurable in
/// this mode.
///
/// For now, this is only reasonably useful for testing and local development, when you don't
/// want the hassle of re-generating a chain-spec. For any production chain, using `--chain` and
/// a proper chain-spec is suggested.
fn load_spec_from_runtime(
&self,
_runtime: &[u8],
_preset: Option<&str>,
) -> std::result::Result<Box<dyn ChainSpec>, String> {
panic!("🫵🏻 unsupported: This node does not support on-the-fly chain-spec generation. The code must be updated to provide an impl for `SubstrateCli::load_spec_from_runtime`.\n Try `--chain` instead.")
}

/// Helper function used to parse the command line arguments. This is the equivalent of
/// [`clap::Parser::parse()`].
///
Expand Down
27 changes: 22 additions & 5 deletions substrate/client/cli/src/params/shared_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,32 @@ pub struct SharedParams {
/// Specify the chain specification.
///
/// It can be one of the predefined ones (dev, local, or staging) or it can be a path to
/// a file with the chainspec (such as one exported by the `build-spec` subcommand).
#[arg(long, value_name = "CHAIN_SPEC")]
/// a file with the chain-spec (such as one exported by the `build-spec` subcommand).
#[arg(long, value_name = "CHAIN_SPEC", conflicts_with_all = &["runtime", "genesis_preset"])]
pub chain: Option<String>,

/// Path to a `.wasm` runtime blob.
///
/// This, possibly with `--genesis-preset`, can be used as an alternative to `--chain`.
#[arg(long, value_name = "RUNTIME")]
pub runtime: Option<PathBuf>,

/// A genesis preset to use.
///
/// If not specified, the `Default` preset is used. If `--dev` is preset, it imp
///
/// This, combined with `--runtime`, can be used as an alternative to `--chain`.
#[arg(long, value_name = "GENESIS_PRESET")]
pub genesis_preset: Option<String>,

/// Specify the development chain.
///
/// This flag sets `--chain=dev`, `--force-authoring`, `--rpc-cors=all`,
/// `--alice`, and `--tmp` flags, unless explicitly overridden.
/// It also disables local peer discovery (see --no-mdns and --discover-local)
/// This flag sets `--force-authoring`, `--rpc-cors=all`, `--alice`, and `--tmp` flags, unless
/// explicitly overridden. It also disables local peer discovery (see --no-mdns and
/// --discover-local).
///
/// If combined with `--runtime`, it sets `--genesis-preset=dev`. Otherwise, it implies
/// `--chain=dev`.
#[arg(long, conflicts_with_all = &["chain"])]
pub dev: bool,

Expand Down
5 changes: 4 additions & 1 deletion substrate/client/service/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,15 @@ where
{
let backend = new_db_backend(config.db_config())?;

// println!("Creating genesis block builder");
// println!("chain_spec {:?}", config.chain_spec);
let genesis_block_builder = GenesisBlockBuilder::new(
config.chain_spec.as_storage_builder(),
!config.no_genesis(),
backend.clone(),
executor.clone(),
)?;
)
.unwrap();

new_full_parts_with_genesis_builder(
config,
Expand Down
22 changes: 12 additions & 10 deletions substrate/utils/frame/benchmarking-cli/src/pallet/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ use frame_benchmarking::{
use frame_support::traits::StorageInfo;
use linked_hash_map::LinkedHashMap;
use sc_chain_spec::json_patch::merge as json_merge;
use sc_cli::{execution_method_from_cli, ChainSpec, CliConfiguration, Result, SharedParams};
use sc_cli::{
execution_method_from_cli, ChainSpec, CliConfiguration, Result, SharedParams,
DEV_RUNTIME_PRESET,
};
use sc_client_db::BenchmarkingState;
use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY};
use sp_core::{
Expand Down Expand Up @@ -160,9 +163,6 @@ generate the genesis state is deprecated. Please remove the `--chain`/`--dev`/`-
point `--runtime` to your runtime blob and set `--genesis-builder=runtime`. This warning may \
become a hard error any time after December 2024.";

/// The preset that we expect to find in the GenesisBuilder runtime API.
const GENESIS_PRESET: &str = "development";

impl PalletCmd {
/// Runs the command and benchmarks a pallet.
#[deprecated(
Expand Down Expand Up @@ -574,7 +574,7 @@ impl PalletCmd {
&self,
chain_spec: &Option<Box<dyn ChainSpec>>,
) -> Result<(sp_storage::Storage, OverlayedChanges<H>)> {
Ok(match (self.genesis_builder, self.runtime.is_some()) {
Ok(match (self.genesis_builder, self.shared_params().runtime.is_some()) {
(Some(GenesisBuilder::None), _) => Default::default(),
(Some(GenesisBuilder::Spec), _) | (None, false) => {
log::warn!("{WARN_SPEC_GENESIS_CTOR}");
Expand Down Expand Up @@ -646,7 +646,7 @@ impl PalletCmd {
&mut Default::default(),
&executor,
"GenesisBuilder_get_preset",
&Some::<PresetId>(GENESIS_PRESET.into()).encode(), // Use the default preset
&self.genesis_preset(false).encode(),
&mut Self::build_extensions(executor.clone()),
&runtime_code,
CallContext::Offchain,
Expand All @@ -664,7 +664,7 @@ impl PalletCmd {
json_merge(&mut genesis_json, dev);
} else {
log::warn!(
"Could not find genesis preset '{GENESIS_PRESET}'. Falling back to default."
"Could not find genesis preset '{DEV_RUNTIME_PRESET}'. Falling back to default."
);
}

Expand Down Expand Up @@ -728,7 +728,7 @@ impl PalletCmd {
&self,
state: &'a BenchmarkingState<H>,
) -> Result<FetchedCode<'a, BenchmarkingState<H>, H>> {
if let Some(runtime) = &self.runtime {
if let Some(runtime) = &self.shared_params().runtime {
log::info!("Loading WASM from {}", runtime.display());
let code = fs::read(runtime)?;
let hash = sp_core::blake2_256(&code).to_vec();
Expand Down Expand Up @@ -975,8 +975,10 @@ impl PalletCmd {

/// Sanity check the CLI arguments.
fn check_args(&self) -> Result<()> {
if self.runtime.is_some() && self.shared_params.chain.is_some() {
unreachable!("Clap should not allow both `--runtime` and `--chain` to be provided.")
if (self.shared_params().runtime.is_some() || self.shared_params().genesis_preset.is_some()) &&
self.shared_params.chain.is_some()
{
unreachable!("Clap should not allow both (`--runtime` or `--genesis-preset`) and `--chain` to be provided.")
}

if let Some(output_path) = &self.output {
Expand Down
4 changes: 0 additions & 4 deletions substrate/utils/frame/benchmarking-cli/src/pallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,6 @@ pub struct PalletCmd {
)]
pub wasmtime_instantiation_strategy: WasmtimeInstantiationStrategy,

/// Optional runtime blob to use instead of the one from the genesis config.
#[arg(long, conflicts_with = "chain")]
pub runtime: Option<PathBuf>,

/// Do not fail if there are unknown but also unused host functions in the runtime.
#[arg(long)]
pub allow_missing_host_functions: bool,
Expand Down
2 changes: 2 additions & 0 deletions substrate/utils/frame/benchmarking-cli/src/pallet/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub enum GenesisBuilder {
/// state. However, to keep backwards compatibility, this is not the default.
None,
/// Let the runtime build the genesis state through its `BuildGenesisConfig` runtime API.
///
/// This uses [`sc_cli::DEV_RUNTIME_PRESET`] preset.
Runtime,
/// Use the spec file to build the genesis state. This fails when there is no spec.
Spec,
Expand Down

0 comments on commit 3e55a98

Please sign in to comment.