Skip to content

Commit 2bf5b35

Browse files
Merge pull request #301 from mintlayer/node-chainstate-config-options
Allow to override chainstate options for regtest
2 parents 967aef2 + 56e54da commit 2bf5b35

File tree

10 files changed

+176
-90
lines changed

10 files changed

+176
-90
lines changed

Cargo.lock

Lines changed: 1 addition & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ parity-scale-codec = "3.1"
2121
serde = "1.0"
2222
sscanf = "0.2"
2323
static_assertions = "1.1"
24-
strum = { version = "0.24", features = ["derive"] }
2524
thiserror = "1.0"
2625
hex = "0.4"
2726

common/src/chain/config/mod.rs

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,7 @@ use std::time::Duration;
3636
const DEFAULT_MAX_FUTURE_BLOCK_TIME_OFFSET: Duration = Duration::from_secs(60 * 60);
3737
pub const DEFAULT_TARGET_BLOCK_SPACING: Duration = Duration::from_secs(120);
3838

39-
#[derive(
40-
Debug,
41-
Copy,
42-
Clone,
43-
PartialEq,
44-
Eq,
45-
PartialOrd,
46-
Ord,
47-
strum::Display,
48-
strum::EnumVariantNames,
49-
strum::EnumString,
50-
)]
51-
#[strum(serialize_all = "kebab-case")]
39+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
5240
pub enum ChainType {
5341
Mainnet,
5442
Testnet,
@@ -258,19 +246,6 @@ mod tests {
258246
assert_eq!(config.chain_type(), &ChainType::Mainnet);
259247
}
260248

261-
#[test]
262-
fn chain_type_names() {
263-
use strum::VariantNames;
264-
265-
assert_eq!(&ChainType::Mainnet.to_string(), "mainnet");
266-
assert_eq!(&ChainType::Testnet.to_string(), "testnet");
267-
268-
for chain_type_str in ChainType::VARIANTS {
269-
let chain_type: ChainType = chain_type_str.parse().expect("cannot parse chain type");
270-
assert_eq!(&chain_type.to_string(), chain_type_str);
271-
}
272-
}
273-
274249
#[test]
275250
fn different_magic_bytes() {
276251
let config1 = Builder::new(ChainType::Regtest).build();

node/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ subsystem = { path = "../subsystem/" }
2020
anyhow = "1.0"
2121
clap = { version = "3.1", features = ["derive"] }
2222
jsonrpsee = { version = "0.14", features = ["macros"] }
23-
strum = "0.24"
2423
tokio = { version = "1.19", default-features = false }
2524
thiserror = "1.0"
2625
serde = { version = "1", features = ["derive"] }
2726
toml = "0.5"
2827
directories = "4.0"
28+
paste = "1.0"
2929

3030
[dev-dependencies]
3131
assert_cmd = "2"

node/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
1818
mod config;
1919
mod options;
20+
mod regtest_options;
2021
mod runner;
2122

2223
pub type Error = anyhow::Error;

node/src/options.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ use std::{ffi::OsString, fs, net::SocketAddr, path::PathBuf};
2020
use anyhow::{Context, Result};
2121
use clap::{Args, Parser, Subcommand};
2222
use directories::UserDirs;
23-
use strum::VariantNames;
2423

25-
use common::chain::config::ChainType;
24+
use crate::regtest_options::RegtestOptions;
2625

2726
const DATA_DIR_NAME: &str = ".mintlayer";
2827
const CONFIG_NAME: &str = "config.toml";
@@ -51,16 +50,16 @@ pub struct Options {
5150
pub enum Command {
5251
/// Create a configuration file.
5352
CreateConfig,
54-
Run(RunOptions),
53+
/// Run the mainnet node.
54+
Mainnet(RunOptions),
55+
/// Run the testnet node.
56+
Testnet(RunOptions),
57+
/// Run the regtest node.
58+
Regtest(RegtestOptions),
5559
}
5660

57-
/// Run the node.
5861
#[derive(Args, Debug)]
5962
pub struct RunOptions {
60-
/// Blockchain type.
61-
#[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")]
62-
pub net: ChainType,
63-
6463
/// The number of maximum attempts to process a block.
6564
#[clap(long)]
6665
pub max_db_commit_attempts: Option<usize>,

node/src/regtest_options.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright (c) 2022 RBB S.r.l
2+
3+
// SPDX-License-Identifier: MIT
4+
// Licensed under the MIT License;
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://spdx.org/licenses/MIT
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
use clap::Args;
17+
18+
use crate::RunOptions;
19+
20+
#[derive(Args, Debug)]
21+
pub struct RegtestOptions {
22+
#[clap(flatten)]
23+
pub run_options: RunOptions,
24+
#[clap(flatten)]
25+
pub chain_config: ChainConfigOptions,
26+
}
27+
28+
#[derive(Args, Debug)]
29+
pub struct ChainConfigOptions {
30+
/// Address prefix.
31+
#[clap(long)]
32+
pub chain_address_prefix: Option<String>,
33+
34+
/// Block reward maturity.
35+
#[clap(long)]
36+
pub chain_blockreward_maturity: Option<i64>,
37+
38+
/// The maximum future block offset in seconds.
39+
#[clap(long)]
40+
pub chain_max_future_block_time_offset: Option<u64>,
41+
42+
/// The chain version (major.minor.path).
43+
#[clap(long)]
44+
pub chain_version: Option<String>,
45+
46+
/// Target block spacing in seconds.
47+
#[clap(long)]
48+
pub chain_target_block_spacing: Option<u64>,
49+
50+
/// Coin decimals.
51+
#[clap(long)]
52+
pub chain_coin_decimals: Option<u8>,
53+
54+
/// Emission schedule (`<initial_supply>+<initial_subsidy>[, <height>+<subsidy>]`).
55+
pub chain_emission_schedule: Option<String>,
56+
57+
/// The maximum block header size in bytes.
58+
#[clap(long)]
59+
pub chain_max_block_header_size: Option<usize>,
60+
61+
/// The maximum transactions size in block in bytes.
62+
#[clap(long)]
63+
pub chain_max_block_size_with_standard_txs: Option<usize>,
64+
65+
/// The maximum smart contracts size ib block in bytes.
66+
#[clap(long)]
67+
pub chain_max_block_size_with_smart_contracts: Option<usize>,
68+
}

node/src/runner.rs

Lines changed: 96 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,41 +15,37 @@
1515

1616
//! Node initialisation routine.
1717
18-
use std::{fs, sync::Arc};
18+
use std::{fs, path::Path, str::FromStr, sync::Arc, time::Duration};
1919

20-
use anyhow::{Context, Result};
20+
use anyhow::{anyhow, Context, Result};
21+
use paste::paste;
2122

2223
use chainstate::rpc::ChainstateRpcServer;
23-
use common::chain::config::ChainType;
24+
use common::{
25+
chain::config::{
26+
Builder as ChainConfigBuilder, ChainConfig, ChainType, EmissionScheduleTabular,
27+
},
28+
primitives::{semver::SemVer, BlockDistance},
29+
};
2430
use logging::log;
2531
use p2p::rpc::P2pRpcServer;
2632

2733
use crate::{
2834
config::NodeConfig,
29-
options::{Command, Options},
35+
options::{Command, Options, RunOptions},
36+
regtest_options::ChainConfigOptions,
3037
};
3138

32-
#[derive(Debug, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, thiserror::Error)]
33-
enum Error {
34-
#[error("Chain type '{0}' not yet supported")]
35-
UnsupportedChain(ChainType),
36-
}
37-
3839
/// Initialize the node, giving caller the opportunity to add more subsystems before start.
3940
pub async fn initialize(
40-
chain_type: ChainType,
41+
chain_config: ChainConfig,
4142
node_config: NodeConfig,
4243
) -> Result<subsystem::Manager> {
44+
let chain_config = Arc::new(chain_config);
45+
4346
// Initialize storage.
4447
let storage = chainstate_storage::Store::new_empty()?;
4548

46-
// Initialize chain configuration.
47-
let chain_config = Arc::new(match chain_type {
48-
ChainType::Mainnet => common::chain::config::create_mainnet(),
49-
ChainType::Regtest => common::chain::config::create_regtest(),
50-
chain_ty => return Err(Error::UnsupportedChain(chain_ty).into()),
51-
});
52-
5349
// INITIALIZE SUBSYSTEMS
5450

5551
let mut manager = subsystem::Manager::new("mintlayer");
@@ -105,17 +101,92 @@ pub async fn run(options: Options) -> Result<()> {
105101
.with_context(|| format!("Failed to write config to the '{path:?}' file"))?;
106102
Ok(())
107103
}
108-
Command::Run(ref run_options) => {
109-
let node_config = NodeConfig::read(&options.config_path(), run_options)
110-
.context("Failed to initialize config")?;
111-
log::trace!("Starting with the following config\n: {node_config:#?}");
112-
let manager = initialize(run_options.net, node_config).await?;
113-
#[allow(clippy::unit_arg)]
114-
Ok(manager.main().await)
104+
Command::Mainnet(ref run_options) => {
105+
let chain_config = common::chain::config::create_mainnet();
106+
start(&options.config_path(), run_options, chain_config).await
107+
}
108+
Command::Testnet(ref run_options) => {
109+
let chain_config = ChainConfigBuilder::new(ChainType::Testnet).build();
110+
start(&options.config_path(), run_options, chain_config).await
111+
}
112+
Command::Regtest(ref regtest_options) => {
113+
let chain_config = regtest_chain_config(&regtest_options.chain_config)?;
114+
start(
115+
&options.config_path(),
116+
&regtest_options.run_options,
117+
chain_config,
118+
)
119+
.await
115120
}
116121
}
117122
}
118123

124+
async fn start(
125+
config_path: &Path,
126+
run_options: &RunOptions,
127+
chain_config: ChainConfig,
128+
) -> Result<()> {
129+
let node_config =
130+
NodeConfig::read(config_path, run_options).context("Failed to initialize config")?;
131+
log::info!("Starting with the following config:\n {node_config:#?}");
132+
let manager = initialize(chain_config, node_config).await?;
133+
manager.main().await;
134+
Ok(())
135+
}
136+
137+
fn regtest_chain_config(options: &ChainConfigOptions) -> Result<ChainConfig> {
138+
let ChainConfigOptions {
139+
chain_address_prefix,
140+
chain_blockreward_maturity,
141+
chain_max_future_block_time_offset,
142+
chain_version,
143+
chain_target_block_spacing,
144+
chain_coin_decimals,
145+
chain_emission_schedule,
146+
chain_max_block_header_size,
147+
chain_max_block_size_with_standard_txs,
148+
chain_max_block_size_with_smart_contracts,
149+
} = options;
150+
151+
let mut builder = ChainConfigBuilder::new(ChainType::Regtest);
152+
153+
macro_rules! update_builder {
154+
($field: ident) => {
155+
update_builder!($field, std::convert::identity)
156+
};
157+
($field: ident, $converter: stmt) => {
158+
paste! {
159+
if let Some(val) = [<chain_ $field>] {
160+
builder = builder.$field($converter(val.to_owned()));
161+
}
162+
}
163+
};
164+
($field: ident, $converter: stmt, map_err) => {
165+
paste! {
166+
if let Some(val) = [<chain_ $field>] {
167+
builder = builder.$field($converter(val.to_owned()).map_err(|e| anyhow!(e))?);
168+
}
169+
}
170+
};
171+
}
172+
173+
update_builder!(address_prefix);
174+
update_builder!(blockreward_maturity, BlockDistance::new);
175+
update_builder!(max_future_block_time_offset, Duration::from_secs);
176+
update_builder!(version, SemVer::try_from, map_err);
177+
update_builder!(target_block_spacing, Duration::from_secs);
178+
update_builder!(coin_decimals);
179+
if let Some(val) = chain_emission_schedule {
180+
builder =
181+
builder.emission_schedule_tabular(EmissionScheduleTabular::from_str(val.as_str())?);
182+
}
183+
update_builder!(max_block_header_size);
184+
update_builder!(max_block_size_with_standard_txs);
185+
update_builder!(max_block_size_with_smart_contracts);
186+
187+
Ok(builder.build())
188+
}
189+
119190
#[rpc::rpc(server, namespace = "node")]
120191
trait NodeRpc {
121192
/// Order the node to shutdown

0 commit comments

Comments
 (0)