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

Allow to override chainstate options for regtest #301

Merged
merged 14 commits into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 1 addition & 24 deletions Cargo.lock

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

1 change: 0 additions & 1 deletion common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ parity-scale-codec = "3.1"
serde = "1.0"
sscanf = "0.2"
static_assertions = "1.1"
strum = { version = "0.24", features = ["derive"] }
thiserror = "1.0"
hex = "0.4"

Expand Down
27 changes: 1 addition & 26 deletions common/src/chain/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,7 @@ use std::time::Duration;
const DEFAULT_MAX_FUTURE_BLOCK_TIME_OFFSET: Duration = Duration::from_secs(60 * 60);
pub const DEFAULT_TARGET_BLOCK_SPACING: Duration = Duration::from_secs(120);

#[derive(
Debug,
Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
strum::Display,
strum::EnumVariantNames,
strum::EnumString,
)]
#[strum(serialize_all = "kebab-case")]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ChainType {
Mainnet,
Testnet,
Expand Down Expand Up @@ -279,19 +267,6 @@ mod tests {
assert_eq!(config.chain_type(), &ChainType::Mainnet);
}

#[test]
fn chain_type_names() {
use strum::VariantNames;

assert_eq!(&ChainType::Mainnet.to_string(), "mainnet");
assert_eq!(&ChainType::Testnet.to_string(), "testnet");

for chain_type_str in ChainType::VARIANTS {
let chain_type: ChainType = chain_type_str.parse().expect("cannot parse chain type");
assert_eq!(&chain_type.to_string(), chain_type_str);
}
}

#[test]
fn different_magic_bytes() {
let config1 = Builder::new(ChainType::Regtest).build();
Expand Down
2 changes: 1 addition & 1 deletion node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ subsystem = { path = "../subsystem/" }
anyhow = "1.0"
clap = { version = "3.1", features = ["derive"] }
jsonrpsee = { version = "0.14", features = ["macros"] }
strum = "0.24"
stanislav-tkach marked this conversation as resolved.
Show resolved Hide resolved
tokio = { version = "1.19", default-features = false }
thiserror = "1.0"
serde = { version = "1", features = ["derive"] }
toml = "0.5"
directories = "4.0"
paste = "1.0"

[dev-dependencies]
assert_cmd = "2"
Expand Down
56 changes: 47 additions & 9 deletions node/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ use std::{ffi::OsString, fs, net::SocketAddr, path::PathBuf};
use anyhow::{Context, Result};
use clap::{Args, Parser, Subcommand};
use directories::UserDirs;
use strum::VariantNames;

use common::chain::config::ChainType;

const DATA_DIR_NAME: &str = ".mintlayer";
const CONFIG_NAME: &str = "config.toml";
Expand Down Expand Up @@ -51,16 +48,13 @@ pub struct Options {
pub enum Command {
/// Create a configuration file.
CreateConfig,
Run(RunOptions),
Mainnet(RunOptions),
Regtest(RegtestOptions),
stanislav-tkach marked this conversation as resolved.
Show resolved Hide resolved
}

/// Run the node.
/// Run the mainnet node.
#[derive(Args, Debug)]
pub struct RunOptions {
/// Blockchain type.
#[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")]
pub net: ChainType,

/// The number of maximum attempts to process a block.
#[clap(long)]
pub max_db_commit_attempts: Option<usize>,
Expand All @@ -86,6 +80,50 @@ pub struct RunOptions {
pub rpc_addr: Option<SocketAddr>,
}

/// Run the regtest node.
#[derive(Args, Debug)]
stanislav-tkach marked this conversation as resolved.
Show resolved Hide resolved
pub struct RegtestOptions {
#[clap(flatten)]
pub run_options: RunOptions,
#[clap(flatten)]
pub chain_config: ChainConfigOptions,
}

#[derive(Args, Debug)]
pub struct ChainConfigOptions {
stanislav-tkach marked this conversation as resolved.
Show resolved Hide resolved
/// Address prefix.
#[clap(long)]
pub chain_address_prefix: Option<String>,

/// Block reward maturity.
#[clap(long)]
pub chain_blockreward_maturity: Option<i64>,

/// The maximum future block offset in seconds.
#[clap(long)]
pub chain_max_future_block_time_offset: Option<u64>,

/// The chain version (major.minor.path).
#[clap(long)]
pub chain_version: Option<String>,

/// Target block spacing in seconds.
#[clap(long)]
pub chain_target_block_spacing: Option<u64>,

/// The maximum block header size in bytes.
#[clap(long)]
pub chain_max_block_header_size: Option<usize>,

/// The maximum transactions size in block in bytes.
#[clap(long)]
pub chain_max_block_size_with_standard_txs: Option<usize>,

/// The maximum smart contracts size ib block in bytes.
#[clap(long)]
pub chain_max_block_size_with_smart_contracts: Option<usize>,
}

impl Options {
/// Constructs an instance by parsing the given arguments.
///
Expand Down
107 changes: 82 additions & 25 deletions node/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,34 @@

//! Node initialisation routine.

use std::{fs, sync::Arc};
use std::{fs, path::Path, sync::Arc, time::Duration};

use anyhow::{Context, Result};
use anyhow::{anyhow, Context, Result};
use paste::paste;

use chainstate::rpc::ChainstateRpcServer;
use common::chain::config::ChainType;
use common::{
chain::config::{Builder as ChainConfigBuilder, ChainConfig, ChainType},
primitives::{semver::SemVer, BlockDistance},
};
use logging::log;
use p2p::rpc::P2pRpcServer;

use crate::{
config::NodeConfig,
options::{Command, Options},
options::{ChainConfigOptions, Command, Options, RunOptions},
};

#[derive(Debug, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, thiserror::Error)]
enum Error {
#[error("Chain type '{0}' not yet supported")]
UnsupportedChain(ChainType),
}

/// Initialize the node, giving caller the opportunity to add more subsystems before start.
pub async fn initialize(
chain_type: ChainType,
chain_config: ChainConfig,
node_config: NodeConfig,
) -> Result<subsystem::Manager> {
let chain_config = Arc::new(chain_config);

// Initialize storage.
let storage = chainstate_storage::Store::new_empty()?;

// Initialize chain configuration.
let chain_config = Arc::new(match chain_type {
ChainType::Mainnet => common::chain::config::create_mainnet(),
ChainType::Regtest => common::chain::config::create_regtest(),
chain_ty => return Err(Error::UnsupportedChain(chain_ty).into()),
});

// INITIALIZE SUBSYSTEMS

let mut manager = subsystem::Manager::new("mintlayer");
Expand Down Expand Up @@ -105,17 +98,81 @@ pub async fn run(options: Options) -> Result<()> {
.with_context(|| format!("Failed to write config to the '{path:?}' file"))?;
Ok(())
}
Command::Run(ref run_options) => {
let node_config = NodeConfig::read(&options.config_path(), run_options)
.context("Failed to initialize config")?;
log::trace!("Starting with the following config\n: {node_config:#?}");
let manager = initialize(run_options.net, node_config).await?;
#[allow(clippy::unit_arg)]
Ok(manager.main().await)
Command::Mainnet(ref run_options) => {
let chain_config = common::chain::config::create_mainnet();
start(&options.config_path(), run_options, chain_config).await
}
Command::Regtest(ref regtest_options) => {
let chain_config = regtest_chain_config(&regtest_options.chain_config)?;
start(
&options.config_path(),
&regtest_options.run_options,
chain_config,
)
.await
}
}
}

async fn start(
config_path: &Path,
run_options: &RunOptions,
chain_config: ChainConfig,
) -> Result<()> {
let node_config =
NodeConfig::read(config_path, run_options).context("Failed to initialize config")?;
log::trace!("Starting with the following config\n: {node_config:#?}");
stanislav-tkach marked this conversation as resolved.
Show resolved Hide resolved
let manager = initialize(chain_config, node_config).await?;
manager.main().await;
Ok(())
}

fn regtest_chain_config(options: &ChainConfigOptions) -> Result<ChainConfig> {
let ChainConfigOptions {
chain_address_prefix,
chain_blockreward_maturity,
chain_max_future_block_time_offset,
chain_version,
chain_target_block_spacing,
chain_max_block_header_size,
chain_max_block_size_with_standard_txs,
chain_max_block_size_with_smart_contracts,
} = options;

let mut builder = ChainConfigBuilder::new(ChainType::Regtest);

macro_rules! update_builder {
($field: ident) => {
update_builder!($field, std::convert::identity)
};
($field: ident, $converter: stmt) => {
paste! {
if let Some(val) = [<chain_ $field>] {
builder = builder.$field($converter(val.to_owned()));
}
}
};
iljakuklic marked this conversation as resolved.
Show resolved Hide resolved
($field: ident, $converter: stmt, map_err) => {
paste! {
if let Some(val) = [<chain_ $field>] {
builder = builder.$field($converter(val.to_owned()).map_err(|e| anyhow!(e))?);
}
}
};
}
iljakuklic marked this conversation as resolved.
Show resolved Hide resolved

update_builder!(address_prefix);
update_builder!(blockreward_maturity, BlockDistance::new);
update_builder!(max_future_block_time_offset, Duration::from_secs);
update_builder!(version, SemVer::try_from, map_err);
update_builder!(target_block_spacing, Duration::from_secs);
update_builder!(max_block_header_size);
update_builder!(max_block_size_with_standard_txs);
update_builder!(max_block_size_with_smart_contracts);

Ok(builder.build())
}

#[rpc::rpc(server, namespace = "node")]
trait NodeRpc {
/// Order the node to shutdown
Expand Down
3 changes: 0 additions & 3 deletions node/tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use assert_cmd::Command;
use directories::UserDirs;
use tempdir::TempDir;

use common::chain::config::ChainType;
use node::{NodeConfig, RunOptions};

const BIN_NAME: &str = env!("CARGO_BIN_EXE_node");
Expand Down Expand Up @@ -90,7 +89,6 @@ fn read_config_override_values() {
let rpc_addr = SocketAddr::from_str("127.0.0.1:5432").unwrap();

let options = RunOptions {
net: ChainType::Mainnet,
max_db_commit_attempts: Some(max_db_commit_attempts),
max_orphan_blocks: Some(max_orphan_blocks),
p2p_addr: Some(p2p_addr.into()),
Expand Down Expand Up @@ -162,7 +160,6 @@ fn custom_config_path_and_data_dir() {

fn default_run_options() -> RunOptions {
RunOptions {
net: ChainType::Mainnet,
max_db_commit_attempts: None,
max_orphan_blocks: None,
p2p_addr: None,
Expand Down
3 changes: 1 addition & 2 deletions test/functional/test_framework/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ def __init__(self, i, datadir, *, chain, rpchost, timewait, timeout_factor, bitc
self.args = [
self.binary,
"--datadir={}".format(datadir_path),
"run",
"--net=regtest",
"regtest",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool I kind of like the command-based interface.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Glad to hear! I was afraid that no one would like this approach.

"--rpc-addr={}".format(rpc_addr),
"--p2p-addr={}".format(p2p_addr),
#"-X",
Expand Down