From d1e24819ffdd098e9bdcc3dcc029ba64a58a78d2 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 6 Jul 2022 00:41:03 +0200 Subject: [PATCH 01/30] Raw prototype of subsystems configuration --- Cargo.lock | 3 +++ chainstate/Cargo.toml | 3 ++- chainstate/src/config.rs | 20 ++++++++++++++ .../src/detail/tests/processing_tests.rs | 11 ++++++-- chainstate/src/lib.rs | 9 ++++--- chainstate/src/rpc.rs | 7 +++-- node/src/options.rs | 20 +++++++------- node/src/runner.rs | 5 ++-- p2p/Cargo.toml | 1 + p2p/src/config.rs | 24 +++++++++++++++++ p2p/src/lib.rs | 7 +++-- p2p/src/sync/tests/mod.rs | 4 +-- p2p/test-utils/src/lib.rs | 9 ++++++- rpc/Cargo.toml | 1 + rpc/src/config.rs | 26 +++++++++++++++++++ rpc/src/lib.rs | 18 +++++++------ 16 files changed, 132 insertions(+), 36 deletions(-) create mode 100644 chainstate/src/config.rs create mode 100644 p2p/src/config.rs create mode 100644 rpc/src/config.rs diff --git a/Cargo.lock b/Cargo.lock index 71c23df7e4..18c210ea5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -499,6 +499,7 @@ dependencies = [ "async-trait", "chainstate-storage", "chainstate-types", + "clap 3.2.5", "common", "crypto", "hex", @@ -2551,6 +2552,7 @@ dependencies = [ "async-trait", "chainstate", "chainstate-storage", + "clap 3.2.5", "common", "crypto", "futures", @@ -3233,6 +3235,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "clap 3.2.5", "jsonrpsee", "logging", "subsystem", diff --git a/chainstate/Cargo.toml b/chainstate/Cargo.toml index 88bf1ee121..c8306efe0d 100644 --- a/chainstate/Cargo.toml +++ b/chainstate/Cargo.toml @@ -7,7 +7,6 @@ version = "0.1.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -async-trait = "0.1" chainstate-storage = {path = '../chainstate-storage'} chainstate-types = {path = '../chainstate-types'} common = {path = '../common'} @@ -18,6 +17,7 @@ serialization = {path = "../serialization"} subsystem = {path = '../subsystem'} utils = {path = '../utils'} +async-trait = "0.1" hex = "0.4" itertools = "0.10" jsonrpsee = {version = "0.14", features = ["macros"]} @@ -25,6 +25,7 @@ num = "0.4.0" proptest = "1.0" replace_with = "0.1" thiserror = "1.0" +clap = { version = "3.1", features = ["derive"] } [dev-dependencies] mockall = "0.11" diff --git a/chainstate/src/config.rs b/chainstate/src/config.rs new file mode 100644 index 0000000000..52a28e6dc6 --- /dev/null +++ b/chainstate/src/config.rs @@ -0,0 +1,20 @@ +// Copyright (c) 2022 RBB S.r.l +// opensource@mintlayer.org +// SPDX-License-Identifier: MIT +// Licensed under the MIT License; +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://spdx.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use clap::Args; + +/// The chainstate subsystem configuration. +#[derive(Args, Debug)] +pub struct Config {} diff --git a/chainstate/src/detail/tests/processing_tests.rs b/chainstate/src/detail/tests/processing_tests.rs index 719181cf01..0a06b6766e 100644 --- a/chainstate/src/detail/tests/processing_tests.rs +++ b/chainstate/src/detail/tests/processing_tests.rs @@ -23,7 +23,7 @@ use crate::{ pow::error::ConsensusPoWError, tests::{test_framework::BlockTestFramework, *}, }, - make_chainstate, + make_chainstate, Config as ChainstateConfig, }; use chainstate_storage::{BlockchainStorageRead, Store}; use common::{ @@ -771,7 +771,14 @@ fn blocks_from_the_future() { fn test_mainnet_initialization() { let config = Arc::new(common::chain::config::create_mainnet()); let storage = Store::new_empty().unwrap(); - make_chainstate(config, storage, None, Default::default()).unwrap(); + make_chainstate( + config, + storage, + None, + Default::default(), + ChainstateConfig {}, + ) + .unwrap(); } fn make_invalid_pow_block( diff --git a/chainstate/src/lib.rs b/chainstate/src/lib.rs index 0fd87a0a02..2f7776c4f8 100644 --- a/chainstate/src/lib.rs +++ b/chainstate/src/lib.rs @@ -15,6 +15,7 @@ // // Author(s): S. Afach, A. Sinitsyn +mod config; mod detail; pub mod rpc; @@ -33,10 +34,9 @@ use common::{ chain::{block::Block, ChainConfig}, primitives::{BlockHeight, Id}, }; -use detail::time_getter::TimeGetter; -pub use detail::BlockError; -use detail::PropertyQueryError; -pub use detail::{BlockSource, Chainstate}; +pub use config::Config; +use detail::{time_getter::TimeGetter, PropertyQueryError}; +pub use detail::{BlockError, BlockSource, Chainstate}; #[derive(Debug, Clone)] pub enum ChainstateEvent { @@ -62,6 +62,7 @@ pub fn make_chainstate( chainstate_storage: chainstate_storage::Store, custom_orphan_error_hook: Option>, time_getter: TimeGetter, + _config: Config, ) -> Result, ChainstateError> { let cons = Chainstate::new( chain_config, diff --git a/chainstate/src/rpc.rs b/chainstate/src/rpc.rs index 898145e2a2..3f8cac7f20 100644 --- a/chainstate/src/rpc.rs +++ b/chainstate/src/rpc.rs @@ -15,9 +15,7 @@ //! Chainstate subsystem RPC handler -use crate::ChainstateError; - -use crate::{Block, BlockSource}; +use crate::{Block, BlockSource, ChainstateError}; use common::primitives::BlockHeight; use serialization::Decode; use subsystem::subsystem::CallError; @@ -87,6 +85,7 @@ fn handle_error(e: Result, CallError>) -> rpc::Res #[cfg(test)] mod test { use super::*; + use crate::Config; use serde_json::Value; use std::{future::Future, sync::Arc}; @@ -98,7 +97,7 @@ mod test { let mut man = subsystem::Manager::new("rpctest"); let handle = man.add_subsystem( "chainstate", - crate::make_chainstate(cfg, storage, None, Default::default()).unwrap(), + crate::make_chainstate(cfg, storage, None, Default::default(), Config {}).unwrap(), ); let _ = man.add_raw_subsystem( "test", diff --git a/node/src/options.rs b/node/src/options.rs index 81b287611d..2a41a81462 100644 --- a/node/src/options.rs +++ b/node/src/options.rs @@ -15,9 +15,8 @@ //! Node configuration options -use std::ffi::OsString; -use std::net::SocketAddr; -use std::path::PathBuf; +use std::{ffi::OsString, path::PathBuf}; + use strum::VariantNames; use common::chain::config::ChainType; @@ -30,17 +29,18 @@ pub struct Options { #[clap(long, value_name = "PATH")] pub log_path: Option, - /// Address to bind RPC to - #[clap(long, value_name = "ADDR", default_value = "127.0.0.1:3030")] - pub rpc_addr: SocketAddr, - /// Blockchain type #[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")] pub net: ChainType, - /// Address to bind P2P to - #[clap(long, value_name = "ADDR", default_value = "/ip6/::1/tcp/3031")] - pub p2p_addr: String, + #[clap(flatten)] + pub chainstate_config: chainstate::Config, + + #[clap(flatten)] + pub p2p_config: p2p::Config, + + #[clap(flatten)] + pub rpc_config: rpc::Config, } impl Options { diff --git a/node/src/runner.rs b/node/src/runner.rs index 0d0377ae5a..829cb14139 100644 --- a/node/src/runner.rs +++ b/node/src/runner.rs @@ -52,6 +52,7 @@ pub async fn initialize(opts: Options) -> anyhow::Result { storage.clone(), None, Default::default(), + opts.chainstate_config, )?, ); @@ -61,7 +62,7 @@ pub async fn initialize(opts: Options) -> anyhow::Result { p2p::make_p2p::( Arc::clone(&chain_config), chainstate.clone(), - opts.p2p_addr, + opts.p2p_config, ) .await .expect("The p2p subsystem initialization failed"), @@ -70,7 +71,7 @@ pub async fn initialize(opts: Options) -> anyhow::Result { // RPC subsystem let _rpc = manager.add_subsystem( "rpc", - rpc::Builder::new(opts.rpc_addr) + rpc::Builder::new(opts.rpc_config) .register(chainstate.clone().into_rpc()) .register(NodeRpc::new(manager.make_shutdown_trigger()).into_rpc()) .register(p2p.clone().into_rpc()) diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml index cd0d0ff934..b105c1238d 100644 --- a/p2p/Cargo.toml +++ b/p2p/Cargo.toml @@ -14,6 +14,7 @@ parity-scale-codec = "3.1" sscanf = "0.2" thiserror = "1.0" void = "1.0" +clap = { version = "3.1", features = ["derive"] } # local dependencies common = { path = "../common/" } diff --git a/p2p/src/config.rs b/p2p/src/config.rs new file mode 100644 index 0000000000..a8e217ef25 --- /dev/null +++ b/p2p/src/config.rs @@ -0,0 +1,24 @@ +// Copyright (c) 2022 RBB S.r.l +// opensource@mintlayer.org +// SPDX-License-Identifier: MIT +// Licensed under the MIT License; +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://spdx.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use clap::Args; + +/// The p2p subsystem configuration. +#[derive(Args, Debug)] +pub struct Config { + /// Address to bind P2P to. + #[clap(long, value_name = "ADDR", default_value = "/ip6/::1/tcp/3031")] + pub p2p_addr: String, +} diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index 8bc0abb53a..dad50aed4e 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -24,6 +24,9 @@ use logging::log; use std::{fmt::Debug, str::FromStr, sync::Arc, time::Duration}; use tokio::sync::{mpsc, oneshot}; +mod config; +pub use config::Config; + pub mod error; pub mod event; pub mod message; @@ -231,7 +234,7 @@ pub type P2pHandle = subsystem::Handle>; pub async fn make_p2p( chain_config: Arc, consensus_handle: subsystem::Handle>, - bind_addr: String, + config: Config, ) -> crate::Result> where T: NetworkingService + 'static, @@ -244,6 +247,6 @@ where <::PeerId as FromStr>::Err: Debug, { Ok(P2pInterface { - p2p: P2P::new(bind_addr, chain_config, consensus_handle).await?, + p2p: P2P::new(config.p2p_addr, chain_config, consensus_handle).await?, }) } diff --git a/p2p/src/sync/tests/mod.rs b/p2p/src/sync/tests/mod.rs index 27355d8d75..14f3d7208e 100644 --- a/p2p/src/sync/tests/mod.rs +++ b/p2p/src/sync/tests/mod.rs @@ -19,7 +19,7 @@ use crate::{ event::{PubSubControlEvent, SwarmEvent, SyncControlEvent}, net::{libp2p::Libp2pService, types::ConnectivityEvent, ConnectivityService}, }; -use chainstate::make_chainstate; +use chainstate::{make_chainstate, Config as ChainstateConfig}; use libp2p::PeerId; #[cfg(test)] @@ -53,7 +53,7 @@ where let mut man = subsystem::Manager::new("TODO"); let handle = man.add_subsystem( "consensus", - make_chainstate(cfg, storage, None, Default::default()).unwrap(), + make_chainstate(cfg, storage, None, Default::default(), ChainstateConfig {}).unwrap(), ); tokio::spawn(async move { man.main().await }); diff --git a/p2p/test-utils/src/lib.rs b/p2p/test-utils/src/lib.rs index 398ed5d048..a175c7dff7 100644 --- a/p2p/test-utils/src/lib.rs +++ b/p2p/test-utils/src/lib.rs @@ -144,7 +144,14 @@ pub async fn start_chainstate( let mut man = subsystem::Manager::new("TODO"); let handle = man.add_subsystem( "chainstate", - make_chainstate(config, storage, None, Default::default()).unwrap(), + make_chainstate( + config, + storage, + None, + Default::default(), + chainstate::Config {}, + ) + .unwrap(), ); tokio::spawn(async move { man.main().await }); handle diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index abaaed2ae7..50d1581797 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -15,6 +15,7 @@ logging = { path = "../logging" } anyhow = "1.0" async-trait = "0.1" jsonrpsee = { version = "0.14", features = ["full"] } +clap = { version = "3.1", features = ["derive"] } [dev-dependencies] async-trait = "0.1" diff --git a/rpc/src/config.rs b/rpc/src/config.rs new file mode 100644 index 0000000000..8d9d7657c5 --- /dev/null +++ b/rpc/src/config.rs @@ -0,0 +1,26 @@ +// Copyright (c) 2022 RBB S.r.l +// opensource@mintlayer.org +// SPDX-License-Identifier: MIT +// Licensed under the MIT License; +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://spdx.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::net::SocketAddr; + +use clap::Args; + +/// The rpc subsystem configuration. +#[derive(Args, Debug)] +pub struct Config { + /// Address to bind RPC to. + #[clap(long, value_name = "ADDR", default_value = "127.0.0.1:3030")] + pub rpc_addr: SocketAddr, +} diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 5679fc3060..67440b4602 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -15,8 +15,7 @@ use std::net::SocketAddr; -use jsonrpsee::http_server::HttpServerBuilder; -use jsonrpsee::http_server::HttpServerHandle; +use jsonrpsee::http_server::{HttpServerBuilder, HttpServerHandle}; pub use jsonrpsee::core::server::rpc_module::Methods; pub use jsonrpsee::core::Error; @@ -24,6 +23,9 @@ pub use jsonrpsee::proc_macros::rpc; use logging::log; +mod config; +pub use config::Config; + /// The Result type with RPC-specific error. pub type Result = core::result::Result; @@ -54,8 +56,8 @@ impl Builder { } /// New builder pre-populated with RPC info methods - pub fn new(address: SocketAddr) -> Self { - Self::new_empty(address).register(RpcInfo.into_rpc()) + pub fn new(config: Config) -> Self { + Self::new_empty(config.rpc_addr).register(RpcInfo.into_rpc()) } /// Add methods handlers to the RPC server @@ -129,10 +131,10 @@ mod tests { #[tokio::test] async fn rpc_server() -> anyhow::Result<()> { - let rpc = Builder::new("127.0.0.1:3030".parse().unwrap()) - .register(SubsystemRpcImpl.into_rpc()) - .build() - .await?; + let config = Config { + rpc_addr: "127.0.0.1:3030".parse().unwrap(), + }; + let rpc = Builder::new(config).register(SubsystemRpcImpl.into_rpc()).build().await?; let url = format!("http://{}", rpc.address()); let client = HttpClientBuilder::default().build(url)?; From e3de6d72c6d57973b8d6a12b9c728f30184b0ede Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Fri, 8 Jul 2022 00:00:05 +0200 Subject: [PATCH 02/30] Remove clap dependency from subsystem --- Cargo.lock | 6 +++--- chainstate/Cargo.toml | 2 +- chainstate/src/config.rs | 4 +--- p2p/Cargo.toml | 2 +- p2p/src/config.rs | 4 +--- rpc/Cargo.toml | 2 +- rpc/src/config.rs | 4 +--- 7 files changed, 9 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18c210ea5c..3562b1ca93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -499,7 +499,6 @@ dependencies = [ "async-trait", "chainstate-storage", "chainstate-types", - "clap 3.2.5", "common", "crypto", "hex", @@ -511,6 +510,7 @@ dependencies = [ "proptest", "replace_with", "rpc", + "serde", "serde_json", "serialization", "static_assertions", @@ -2552,7 +2552,6 @@ dependencies = [ "async-trait", "chainstate", "chainstate-storage", - "clap 3.2.5", "common", "crypto", "futures", @@ -2565,6 +2564,7 @@ dependencies = [ "parity-scale-codec", "portpicker", "rpc", + "serde", "serialization", "sscanf", "subsystem", @@ -3235,9 +3235,9 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "clap 3.2.5", "jsonrpsee", "logging", + "serde", "subsystem", "tokio", ] diff --git a/chainstate/Cargo.toml b/chainstate/Cargo.toml index c8306efe0d..5739633fcd 100644 --- a/chainstate/Cargo.toml +++ b/chainstate/Cargo.toml @@ -25,7 +25,7 @@ num = "0.4.0" proptest = "1.0" replace_with = "0.1" thiserror = "1.0" -clap = { version = "3.1", features = ["derive"] } +serde = { version = "1", features = ["derive"] } [dev-dependencies] mockall = "0.11" diff --git a/chainstate/src/config.rs b/chainstate/src/config.rs index 52a28e6dc6..c9b2ff1085 100644 --- a/chainstate/src/config.rs +++ b/chainstate/src/config.rs @@ -13,8 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use clap::Args; - /// The chainstate subsystem configuration. -#[derive(Args, Debug)] +#[derive(serde::Deserialize, Debug)] pub struct Config {} diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml index b105c1238d..e6048a1138 100644 --- a/p2p/Cargo.toml +++ b/p2p/Cargo.toml @@ -14,7 +14,7 @@ parity-scale-codec = "3.1" sscanf = "0.2" thiserror = "1.0" void = "1.0" -clap = { version = "3.1", features = ["derive"] } +serde = { version = "1", features = ["derive"] } # local dependencies common = { path = "../common/" } diff --git a/p2p/src/config.rs b/p2p/src/config.rs index a8e217ef25..43431ae731 100644 --- a/p2p/src/config.rs +++ b/p2p/src/config.rs @@ -13,10 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use clap::Args; - /// The p2p subsystem configuration. -#[derive(Args, Debug)] +#[derive(serde::Deserialize, Debug)] pub struct Config { /// Address to bind P2P to. #[clap(long, value_name = "ADDR", default_value = "/ip6/::1/tcp/3031")] diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 50d1581797..71884cd543 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -15,7 +15,7 @@ logging = { path = "../logging" } anyhow = "1.0" async-trait = "0.1" jsonrpsee = { version = "0.14", features = ["full"] } -clap = { version = "3.1", features = ["derive"] } +serde = { version = "1", features = ["derive"] } [dev-dependencies] async-trait = "0.1" diff --git a/rpc/src/config.rs b/rpc/src/config.rs index 8d9d7657c5..52f186e194 100644 --- a/rpc/src/config.rs +++ b/rpc/src/config.rs @@ -15,10 +15,8 @@ use std::net::SocketAddr; -use clap::Args; - /// The rpc subsystem configuration. -#[derive(Args, Debug)] +#[derive(serde::Deserialize, Debug)] pub struct Config { /// Address to bind RPC to. #[clap(long, value_name = "ADDR", default_value = "127.0.0.1:3030")] From 7df933c8942daa81cb8e9295ff31f1ac4a7cc68c Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Fri, 8 Jul 2022 21:09:17 +0200 Subject: [PATCH 03/30] Add config struct --- Cargo.lock | 2 ++ chainstate/src/config.rs | 13 ++++++++- node/Cargo.toml | 2 ++ node/src/config.rs | 60 ++++++++++++++++++++++++++++++++++++++++ node/src/lib.rs | 4 ++- node/src/main.rs | 28 +++++++++++++++---- node/src/options.rs | 31 +++++++++++++++------ node/src/runner.rs | 29 +++++++++++-------- p2p/src/config.rs | 18 ++++++++++-- p2p/src/lib.rs | 2 +- rpc/src/config.rs | 19 ++++++++++--- rpc/src/lib.rs | 4 +-- 12 files changed, 174 insertions(+), 38 deletions(-) create mode 100644 node/src/config.rs diff --git a/Cargo.lock b/Cargo.lock index 3562b1ca93..5b74df1775 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2397,10 +2397,12 @@ dependencies = [ "logging", "p2p", "rpc", + "serde", "strum", "subsystem", "thiserror", "tokio", + "toml", ] [[package]] diff --git a/chainstate/src/config.rs b/chainstate/src/config.rs index c9b2ff1085..34d38bf50b 100644 --- a/chainstate/src/config.rs +++ b/chainstate/src/config.rs @@ -13,6 +13,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +use serde::{Deserialize, Serialize}; + +use common::chain::config::ChainType; + /// The chainstate subsystem configuration. -#[derive(serde::Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug)] pub struct Config {} + +impl Config { + /// Creates a new chainstate configuration isntance. + pub fn new(net: ChainType) -> Self { + Self {} + } +} diff --git a/node/Cargo.toml b/node/Cargo.toml index 351dc1ece5..bb22bd6450 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -23,3 +23,5 @@ jsonrpsee = { version = "0.14", features = ["macros"] } strum = "0.24" tokio = { version = "1.19", default-features = false } thiserror = "1.0" +serde = { version = "1", features = ["derive"] } +toml = "0.5" diff --git a/node/src/config.rs b/node/src/config.rs new file mode 100644 index 0000000000..79ea280208 --- /dev/null +++ b/node/src/config.rs @@ -0,0 +1,60 @@ +// Copyright (c) 2022 RBB S.r.l +// opensource@mintlayer.org +// SPDX-License-Identifier: MIT +// Licensed under the MIT License; +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://spdx.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! The node configuration. + +use std::fs; + +use anyhow::{Context, Result}; +use serde::{Deserialize, Serialize}; + +use common::chain::config::ChainType; + +use crate::RunOptions; + +#[derive(Serialize, Deserialize, Debug)] +pub struct Config { + // Subsystems configurations. + pub chainstate: chainstate::Config, + pub p2p: p2p::Config, + pub rpc: rpc::Config, +} + +impl Config { + /// Creates a new `Config` instance for the specified chain type. + pub fn new(net: ChainType) -> Result { + let chainstate = chainstate::Config::new(net); + let p2p = p2p::Config::new(net); + let rpc = rpc::Config::new()?; + Ok(Self { + chainstate, + p2p, + rpc, + }) + } + + /// Reads a configuration from the path specified in options and overrides the provided + /// parameters. + pub fn read(options: &RunOptions) -> Result { + let config = fs::read_to_string(&options.config_path).context("Failed to read config")?; + let mut config = toml::from_str(&config).context("Failed to deserialize config")?; + + // if Some(x) = options.x { + // config.x = x; + // } + + Ok(config) + } +} diff --git a/node/src/lib.rs b/node/src/lib.rs index f4b50452da..058659f362 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -15,12 +15,14 @@ //! Top-level node runner as a library +mod config; mod options; mod runner; pub type Error = anyhow::Error; -pub use options::Options; +pub use config::Config; +pub use options::{Command, Options, RunOptions}; pub use runner::{initialize, run}; pub fn init_logging(opts: &Options) { diff --git a/node/src/main.rs b/node/src/main.rs index 5e4b3d7449..28e57fe0ff 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -15,16 +15,32 @@ //! Top-level node binary -mod options; -mod runner; +use std::fs; -async fn run() -> anyhow::Result<()> { - let opts = options::Options::from_args(std::env::args_os()); +use anyhow::{Context, Result}; + +use logging::log; +use node::{Command, Config, Options}; + +async fn run() -> anyhow::Result<()> { + let opts = Options::from_args(std::env::args_os()); logging::init_logging(opts.log_path.as_ref()); - logging::log::trace!("Command line options: {:?}", opts); + log::trace!("Command line options: {opts:?}"); - runner::run(opts).await + match opts.command { + Command::CreateConfig { path, net } => { + let config = Config::new(net)?; + let config = toml::to_string(&config).context("Failed to serialize config")?; + log::trace!("Saving config to {path:?}: {config:#?}"); + fs::write(path, config).context("Failed to write config")?; + Ok(()) + } + Command::Run(options) => { + let config = Config::read(&options).context("Failed to initialize config")?; + node::run(config).await + } + } } #[tokio::main] diff --git a/node/src/options.rs b/node/src/options.rs index 2a41a81462..a78a4c326e 100644 --- a/node/src/options.rs +++ b/node/src/options.rs @@ -13,16 +13,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Node configuration options +//! The node command line options. use std::{ffi::OsString, path::PathBuf}; +use clap::{Args, Parser, Subcommand}; use strum::VariantNames; use common::chain::config::ChainType; /// Mintlayer node executable -#[derive(clap::Parser, Debug)] +#[derive(Parser, Debug)] #[clap(author, version, about)] pub struct Options { /// Where to write logs @@ -33,14 +34,28 @@ pub struct Options { #[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")] pub net: ChainType, - #[clap(flatten)] - pub chainstate_config: chainstate::Config, + #[clap(subcommand)] + pub command: Command, +} - #[clap(flatten)] - pub p2p_config: p2p::Config, +#[derive(Subcommand, Debug)] +pub enum Command { + Run(RunOptions), + /// Create a configuration file. + CreateConfig { + /// The path where config will be created. + #[clap(short, long, default_value = "./mintlayer.toml")] + path: PathBuf, + /// Blockchain type. + #[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")] + net: ChainType, + }, +} - #[clap(flatten)] - pub rpc_config: rpc::Config, +#[derive(Args, Debug)] +pub struct RunOptions { + #[clap(short, long, default_value = "./mintlayer.toml")] + pub config_path: PathBuf, } impl Options { diff --git a/node/src/runner.rs b/node/src/runner.rs index 829cb14139..5317f3b784 100644 --- a/node/src/runner.rs +++ b/node/src/runner.rs @@ -15,7 +15,7 @@ //! Node initialisation routine. -use crate::options::Options; +use crate::{config::Config, options::Options}; use chainstate::rpc::ChainstateRpcServer; use common::chain::config::ChainType; use p2p::rpc::P2pRpcServer; @@ -28,16 +28,21 @@ enum Error { } /// Initialize the node, giving caller the opportunity to add more subsystems before start. -pub async fn initialize(opts: Options) -> anyhow::Result { +pub async fn initialize(config: Config) -> anyhow::Result { // Initialize storage and chain configuration let storage = chainstate_storage::Store::new_empty()?; // Chain configuration - let chain_config = match opts.net { - ChainType::Mainnet => Arc::new(common::chain::config::create_mainnet()), - ChainType::Regtest => Arc::new(common::chain::config::create_regtest()), - chain_ty => return Err(Error::UnsupportedChain(chain_ty).into()), - }; + let chain_config = todo!(); + // let chain_config = match opts.net { + // ChainType::Mainnet => Arc::new(common::chain::config::create_mainnet()), + // ChainType::Regtest => Arc::new(common::chain::config::create_regtest()), + // chain_ty => return Err(Error::UnsupportedChain(chain_ty).into()), + // }; + // let config: Config = todo!(); + + // TODO: FIXME: Early return. + todo!(); // INITIALIZE SUBSYSTEMS @@ -52,7 +57,7 @@ pub async fn initialize(opts: Options) -> anyhow::Result { storage.clone(), None, Default::default(), - opts.chainstate_config, + config.chainstate, )?, ); @@ -62,7 +67,7 @@ pub async fn initialize(opts: Options) -> anyhow::Result { p2p::make_p2p::( Arc::clone(&chain_config), chainstate.clone(), - opts.p2p_config, + config.p2p, ) .await .expect("The p2p subsystem initialization failed"), @@ -71,7 +76,7 @@ pub async fn initialize(opts: Options) -> anyhow::Result { // RPC subsystem let _rpc = manager.add_subsystem( "rpc", - rpc::Builder::new(opts.rpc_config) + rpc::Builder::new(config.rpc) .register(chainstate.clone().into_rpc()) .register(NodeRpc::new(manager.make_shutdown_trigger()).into_rpc()) .register(p2p.clone().into_rpc()) @@ -83,8 +88,8 @@ pub async fn initialize(opts: Options) -> anyhow::Result { } /// Initialize and run the node -pub async fn run(opts: Options) -> anyhow::Result<()> { - let manager = initialize(opts).await?; +pub async fn run(config: Config) -> anyhow::Result<()> { + let manager = initialize(config).await?; #[allow(clippy::unit_arg)] Ok(manager.main().await) diff --git a/p2p/src/config.rs b/p2p/src/config.rs index 43431ae731..c745136603 100644 --- a/p2p/src/config.rs +++ b/p2p/src/config.rs @@ -13,10 +13,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +use serde::{Deserialize, Serialize}; + +use common::chain::config::ChainType; + /// The p2p subsystem configuration. -#[derive(serde::Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug)] pub struct Config { /// Address to bind P2P to. - #[clap(long, value_name = "ADDR", default_value = "/ip6/::1/tcp/3031")] - pub p2p_addr: String, + pub address: String, +} + +impl Config { + /// Creates a new p2p configuration instance. + pub fn new(net: ChainType) -> Self { + Self { + address: "/ip/::1/tcp/3031".into(), + } + } } diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index dad50aed4e..3bcace9fa5 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -247,6 +247,6 @@ where <::PeerId as FromStr>::Err: Debug, { Ok(P2pInterface { - p2p: P2P::new(config.p2p_addr, chain_config, consensus_handle).await?, + p2p: P2P::new(config.address, chain_config, consensus_handle).await?, }) } diff --git a/rpc/src/config.rs b/rpc/src/config.rs index 52f186e194..ebcf5dd850 100644 --- a/rpc/src/config.rs +++ b/rpc/src/config.rs @@ -13,12 +13,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::net::SocketAddr; +use std::{net::SocketAddr, str::FromStr}; + +use anyhow::Result; +use serde::{Deserialize, Serialize}; /// The rpc subsystem configuration. -#[derive(serde::Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug)] pub struct Config { /// Address to bind RPC to. - #[clap(long, value_name = "ADDR", default_value = "127.0.0.1:3030")] - pub rpc_addr: SocketAddr, + pub address: SocketAddr, +} + +impl Config { + /// Creates a new rpc configuration instance. + pub fn new() -> Result { + Ok(Self { + address: SocketAddr::from_str("127.0.0.1:3030")?, + }) + } } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 67440b4602..2d972c7ded 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -57,7 +57,7 @@ impl Builder { /// New builder pre-populated with RPC info methods pub fn new(config: Config) -> Self { - Self::new_empty(config.rpc_addr).register(RpcInfo.into_rpc()) + Self::new_empty(config.address).register(RpcInfo.into_rpc()) } /// Add methods handlers to the RPC server @@ -132,7 +132,7 @@ mod tests { #[tokio::test] async fn rpc_server() -> anyhow::Result<()> { let config = Config { - rpc_addr: "127.0.0.1:3030".parse().unwrap(), + address: "127.0.0.1:3030".parse().unwrap(), }; let rpc = Builder::new(config).register(SubsystemRpcImpl.into_rpc()).build().await?; From 6559338c17b1add9acfc3b095a051f295e37148d Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Sat, 9 Jul 2022 01:02:58 +0200 Subject: [PATCH 04/30] (Mostly) implement p2p config --- chainstate/src/config.rs | 22 +++++-- .../src/detail/block_index_history_iter.rs | 13 ++++- chainstate/src/detail/chainstateref.rs | 25 ++++---- chainstate/src/detail/median_time.rs | 9 ++- chainstate/src/detail/mod.rs | 10 +++- chainstate/src/detail/tests/events_tests.rs | 24 ++++++-- chainstate/src/detail/tests/mod.rs | 1 + .../src/detail/tests/processing_tests.rs | 33 +++++------ chainstate/src/detail/tests/reorgs_tests.rs | 12 ++-- chainstate/src/lib.rs | 3 +- chainstate/src/rpc.rs | 3 +- common/src/chain/config/builder.rs | 37 +----------- common/src/chain/config/mod.rs | 57 +------------------ common/src/primitives/height.rs | 12 +++- common/src/primitives/semver.rs | 5 +- node/src/config.rs | 2 +- node/src/main.rs | 2 +- node/src/runner.rs | 4 +- p2p/src/config.rs | 11 +++- p2p/src/lib.rs | 14 ++--- p2p/src/net/libp2p/behaviour.rs | 10 +--- p2p/src/net/libp2p/mod.rs | 5 +- p2p/src/net/libp2p/tests/mod.rs | 29 +++++----- p2p/src/net/mock/mod.rs | 3 +- p2p/src/net/mod.rs | 8 +-- p2p/src/pubsub.rs | 10 ++-- p2p/src/swarm/mod.rs | 15 ++--- p2p/src/sync/mod.rs | 10 ++-- p2p/src/sync/tests/mod.rs | 3 +- p2p/test-utils/src/lib.rs | 7 ++- 30 files changed, 189 insertions(+), 210 deletions(-) diff --git a/chainstate/src/config.rs b/chainstate/src/config.rs index 34d38bf50b..3acdd33e3e 100644 --- a/chainstate/src/config.rs +++ b/chainstate/src/config.rs @@ -13,17 +13,31 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::time::Duration; + use serde::{Deserialize, Serialize}; -use common::chain::config::ChainType; +use common::primitives::BlockDistance; /// The chainstate subsystem configuration. #[derive(Serialize, Deserialize, Debug)] -pub struct Config {} +pub struct Config { + pub max_block_header_size: usize, + pub max_block_size_from_txs: usize, + pub max_block_size_from_smart_contracts: usize, + pub max_future_block_time_offset: Duration, + pub blockreward_maturity: BlockDistance, +} impl Config { /// Creates a new chainstate configuration isntance. - pub fn new(net: ChainType) -> Self { - Self {} + pub fn new() -> Self { + Self { + max_block_header_size: 1024, + max_block_size_from_txs: 524_288, + max_block_size_from_smart_contracts: 524_288, + max_future_block_time_offset: Duration::from_secs(60 * 60), + blockreward_maturity: BlockDistance::new(500), + } } } diff --git a/chainstate/src/detail/block_index_history_iter.rs b/chainstate/src/detail/block_index_history_iter.rs index 83c3b9a7f7..7076465e31 100644 --- a/chainstate/src/detail/block_index_history_iter.rs +++ b/chainstate/src/detail/block_index_history_iter.rs @@ -75,7 +75,7 @@ mod tests { primitives::{time, Idable, H256}, }; - use crate::{BlockSource, Chainstate}; + use crate::{BlockSource, Chainstate, Config}; use super::*; @@ -83,9 +83,16 @@ mod tests { fn history_iteration() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); + let config = Config::new(); let storage = Store::new_empty().unwrap(); - let mut chainstate = - Chainstate::new(chain_config.clone(), storage, None, Default::default()).unwrap(); + let mut chainstate = Chainstate::new( + chain_config.clone(), + config, + storage, + None, + Default::default(), + ) + .unwrap(); // put three blocks in a chain after genesis let block1 = Block::new( diff --git a/chainstate/src/detail/chainstateref.rs b/chainstate/src/detail/chainstateref.rs index e94aac862a..8ad9617ea3 100644 --- a/chainstate/src/detail/chainstateref.rs +++ b/chainstate/src/detail/chainstateref.rs @@ -32,7 +32,7 @@ use common::{ use logging::log; use utils::ensure; -use crate::{BlockError, BlockSource}; +use crate::{BlockError, BlockSource, Config}; use super::{ consensus_validator::{self, BlockIndexHandle}, @@ -44,6 +44,7 @@ use super::{ pub(crate) struct ChainstateRef<'a, S, O> { chain_config: &'a ChainConfig, + config: &'a Config, db_tx: S, orphan_blocks: O, time_getter: &'a TimeGetterFn, @@ -92,12 +93,14 @@ impl<'a, S: TransactionRw, O> ChainstateRef<' impl<'a, S: BlockchainStorageRead, O: OrphanBlocks> ChainstateRef<'a, S, O> { pub fn new_rw( chain_config: &'a ChainConfig, + config: &'a Config, db_tx: S, orphan_blocks: O, time_getter: &'a TimeGetterFn, ) -> ChainstateRef<'a, S, O> { ChainstateRef { chain_config, + config, db_tx, orphan_blocks, time_getter, @@ -106,12 +109,14 @@ impl<'a, S: BlockchainStorageRead, O: OrphanBlocks> ChainstateRef<'a, S, O> { pub fn new_ro( chain_config: &'a ChainConfig, + config: &'a Config, db_tx: S, orphan_blocks: O, time_getter: &'a TimeGetterFn, ) -> ChainstateRef<'a, S, O> { ChainstateRef { chain_config, + config, db_tx, orphan_blocks, time_getter, @@ -366,11 +371,11 @@ impl<'a, S: BlockchainStorageRead, O: OrphanBlocks> ChainstateRef<'a, S, O> { CheckBlockError::BlockTimeOrderInvalid, ); - let max_future_offset = self.chain_config.max_future_block_time_offset(); + let max_future_offset = self.config.max_future_block_time_offset; let current_time = self.current_time(); let block_timestamp = block.timestamp(); ensure!( - block_timestamp.as_duration_since_epoch() <= current_time + *max_future_offset, + block_timestamp.as_duration_since_epoch() <= current_time + max_future_offset, CheckBlockError::BlockFromTheFuture, ); } @@ -395,27 +400,27 @@ impl<'a, S: BlockchainStorageRead, O: OrphanBlocks> ChainstateRef<'a, S, O> { let block_size = block.block_size(); ensure!( - block_size.size_from_header() <= self.chain_config.max_block_header_size(), + block_size.size_from_header() <= self.config.max_block_header_size, BlockSizeError::Header( block_size.size_from_header(), - self.chain_config.max_block_header_size() + self.config.max_block_header_size, ) ); ensure!( - block_size.size_from_txs() <= self.chain_config.max_block_size_from_txs(), + block_size.size_from_txs() <= self.config.max_block_size_from_txs, BlockSizeError::SizeOfTxs( block_size.size_from_txs(), - self.chain_config.max_block_size_from_txs() + self.config.max_block_size_from_txs ) ); ensure!( block_size.size_from_smart_contracts() - <= self.chain_config.max_block_size_from_smart_contracts(), + <= self.config.max_block_size_from_smart_contracts, BlockSizeError::SizeOfSmartContracts( block_size.size_from_smart_contracts(), - self.chain_config.max_block_size_from_smart_contracts() + self.config.max_block_size_from_smart_contracts ) ); @@ -653,7 +658,7 @@ impl<'a, S: BlockchainStorageWrite, O: OrphanBlocksMut> ChainstateRef<'a, S, O> self.connect_transactions( &block, &new_tip_block_index.block_height(), - self.chain_config.blockreward_maturity(), + &self.config.blockreward_maturity, )?; } diff --git a/chainstate/src/detail/median_time.rs b/chainstate/src/detail/median_time.rs index dc8d343bd7..8eb25e4917 100644 --- a/chainstate/src/detail/median_time.rs +++ b/chainstate/src/detail/median_time.rs @@ -42,7 +42,7 @@ pub fn calculate_median_time_past( #[cfg(test)] mod test { - use crate::{detail::time_getter::TimeGetter, BlockSource, Chainstate}; + use crate::{detail::time_getter::TimeGetter, BlockSource, Chainstate, Config}; use super::*; use chainstate_storage::Store; @@ -86,9 +86,10 @@ mod test { fn blocks_median_time() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); + let config = Config::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = - Chainstate::new(chain_config, storage, None, Default::default()).unwrap(); + Chainstate::new(chain_config, config, storage, None, Default::default()).unwrap(); let block_count = 500; @@ -151,7 +152,9 @@ mod test { })); let storage = Store::new_empty().unwrap(); - let mut chainstate = Chainstate::new(chain_config, storage, None, time_getter).unwrap(); + let config = Config::new(); + let mut chainstate = + Chainstate::new(chain_config, config, storage, None, time_getter).unwrap(); // we use unordered block times, and ensure that the median will be in the right spot let block1_time = current_time.load(Ordering::SeqCst) as u32 + 1; diff --git a/chainstate/src/detail/mod.rs b/chainstate/src/detail/mod.rs index 96ad25f148..2f73e233cc 100644 --- a/chainstate/src/detail/mod.rs +++ b/chainstate/src/detail/mod.rs @@ -15,8 +15,7 @@ // // Author(s): S. Afach, A. Sinitsyn -use crate::detail::orphan_blocks::OrphanBlocksPool; -use crate::ChainstateEvent; +use crate::{detail::orphan_blocks::OrphanBlocksPool, ChainstateEvent, Config}; use chainstate_storage::Transactional; use chainstate_types::block_index::BlockIndex; use common::chain::block::{Block, BlockHeader}; @@ -58,6 +57,7 @@ use time_getter::TimeGetter; #[must_use] pub struct Chainstate { chain_config: Arc, + config: Config, chainstate_storage: chainstate_storage::Store, orphan_blocks: OrphanBlocksPool, custom_orphan_error_hook: Option>, @@ -81,6 +81,7 @@ impl Chainstate { let db_tx = self.chainstate_storage.transaction_rw(); chainstateref::ChainstateRef::new_rw( &self.chain_config, + &self.config, db_tx, self.orphan_blocks.as_rw_ref(), self.time_getter.getter(), @@ -92,6 +93,7 @@ impl Chainstate { let db_tx = self.chainstate_storage.transaction_ro(); chainstateref::ChainstateRef::new_ro( &self.chain_config, + &self.config, db_tx, self.orphan_blocks.as_ro_ref(), self.time_getter.getter(), @@ -104,6 +106,7 @@ impl Chainstate { pub fn new( chain_config: Arc, + config: Config, chainstate_storage: chainstate_storage::Store, custom_orphan_error_hook: Option>, time_getter: TimeGetter, @@ -112,6 +115,7 @@ impl Chainstate { let mut cons = Self::new_no_genesis( chain_config, + config, chainstate_storage, custom_orphan_error_hook, time_getter, @@ -138,12 +142,14 @@ impl Chainstate { fn new_no_genesis( chain_config: Arc, + config: Config, chainstate_storage: chainstate_storage::Store, custom_orphan_error_hook: Option>, time_getter: TimeGetter, ) -> Result { let cons = Self { chain_config, + config, chainstate_storage, orphan_blocks: OrphanBlocksPool::new_default(), custom_orphan_error_hook, diff --git a/chainstate/src/detail/tests/events_tests.rs b/chainstate/src/detail/tests/events_tests.rs index f16b88ea4d..9794a2a962 100644 --- a/chainstate/src/detail/tests/events_tests.rs +++ b/chainstate/src/detail/tests/events_tests.rs @@ -121,10 +121,17 @@ fn several_subscribers_several_events() { fn orphan_block() { common::concurrency::model(|| { let config = Arc::new(create_unit_test_config()); + let config_ = Config::new(); let storage = Store::new_empty().unwrap(); let (orphan_error_hook, errors) = orphan_error_hook(); - let mut chainstate = - Chainstate::new(config, storage, Some(orphan_error_hook), Default::default()).unwrap(); + let mut chainstate = Chainstate::new( + config, + config_, + storage, + Some(orphan_error_hook), + Default::default(), + ) + .unwrap(); let events = subscribe(&mut chainstate, 1); assert!(!chainstate.events_controller.subscribers().is_empty()); @@ -144,10 +151,17 @@ fn orphan_block() { fn custom_orphan_error_hook() { common::concurrency::model(|| { let config = Arc::new(create_unit_test_config()); + let config_ = Config::new(); let storage = Store::new_empty().unwrap(); let (orphan_error_hook, errors) = orphan_error_hook(); - let mut chainstate = - Chainstate::new(config, storage, Some(orphan_error_hook), Default::default()).unwrap(); + let mut chainstate = Chainstate::new( + config, + config_, + storage, + Some(orphan_error_hook), + Default::default(), + ) + .unwrap(); let events = subscribe(&mut chainstate, 1); assert!(!chainstate.events_controller.subscribers().is_empty()); @@ -155,7 +169,7 @@ fn custom_orphan_error_hook() { let first_block = produce_test_block(chainstate.chain_config.genesis_block(), false); // Produce a block with a bad timestamp. let timestamp = chainstate.chain_config.genesis_block().timestamp().as_int_seconds() - + chainstate.chain_config.max_future_block_time_offset().as_secs() as u32; + + chainstate.config.max_future_block_time_offset.as_secs() as u32; let second_block = Block::new( vec![], Some(first_block.get_id()), diff --git a/chainstate/src/detail/tests/mod.rs b/chainstate/src/detail/tests/mod.rs index 73a499bf54..db8d7f2c5d 100644 --- a/chainstate/src/detail/tests/mod.rs +++ b/chainstate/src/detail/tests/mod.rs @@ -89,6 +89,7 @@ fn setup_chainstate() -> Chainstate { fn chainstate_with_config(config: ChainConfig) -> Chainstate { Chainstate::new( Arc::new(config), + todo!(), Store::new_empty().unwrap(), None, Default::default(), diff --git a/chainstate/src/detail/tests/processing_tests.rs b/chainstate/src/detail/tests/processing_tests.rs index 0a06b6766e..a3e116ebc1 100644 --- a/chainstate/src/detail/tests/processing_tests.rs +++ b/chainstate/src/detail/tests/processing_tests.rs @@ -23,7 +23,7 @@ use crate::{ pow::error::ConsensusPoWError, tests::{test_framework::BlockTestFramework, *}, }, - make_chainstate, Config as ChainstateConfig, + make_chainstate, Config, }; use chainstate_storage::{BlockchainStorageRead, Store}; use common::{ @@ -43,9 +43,11 @@ use crypto::random::{self, Rng}; fn genesis_peer_block() { common::concurrency::model(|| { let config = Arc::new(create_unit_test_config()); + let config_ = Config::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = - Chainstate::new_no_genesis(config.clone(), storage, None, Default::default()).unwrap(); + Chainstate::new_no_genesis(config.clone(), config_, storage, None, Default::default()) + .unwrap(); assert_eq!( chainstate .process_block(config.genesis_block().clone(), BlockSource::Peer) @@ -59,9 +61,10 @@ fn genesis_peer_block() { fn process_genesis_block() { common::concurrency::model(|| { let config = Arc::new(create_unit_test_config()); + let config_ = Config::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = - Chainstate::new_no_genesis(config, storage, None, Default::default()).unwrap(); + Chainstate::new_no_genesis(config, config_, storage, None, Default::default()).unwrap(); let block_index = chainstate .process_block( @@ -138,9 +141,10 @@ fn test_orphans_chains() { fn empty_chainstate() { common::concurrency::model(|| { let config = Arc::new(create_unit_test_config()); + let config_ = Config::new(); let storage = Store::new_empty().unwrap(); let chainstate = - Chainstate::new_no_genesis(config, storage, None, Default::default()).unwrap(); + Chainstate::new_no_genesis(config, config_, storage, None, Default::default()).unwrap(); assert_eq!(chainstate.get_best_block_id().unwrap(), None); assert_eq!( chainstate @@ -222,9 +226,10 @@ fn spend_inputs_simple() { fn straight_chain() { common::concurrency::model(|| { let config = Arc::new(create_unit_test_config()); + let config_ = Config::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = - Chainstate::new_no_genesis(config, storage, None, Default::default()).unwrap(); + Chainstate::new_no_genesis(config, config_, storage, None, Default::default()).unwrap(); let genesis_index = chainstate .process_block( @@ -689,7 +694,8 @@ fn blocks_from_the_future() { })); let storage = Store::new_empty().unwrap(); - let mut chainstate = Chainstate::new(config, storage, None, time_getter).unwrap(); + let mut chainstate = + Chainstate::new(config, Config::new(), storage, None, time_getter).unwrap(); { // ensure no blocks are in chain, so that median time can be the genesis time @@ -712,8 +718,7 @@ fn blocks_from_the_future() { { // submit a block on the threshold of being rejected for being from the future - let max_future_offset = - chainstate.chain_config.max_future_block_time_offset().as_secs() as u32; + let max_future_offset = chainstate.config.max_future_block_time_offset.as_secs() as u32; let good_block = Block::new( vec![], @@ -730,8 +735,7 @@ fn blocks_from_the_future() { { // submit a block a second after the allowed threshold in the future - let max_future_offset = - chainstate.chain_config.max_future_block_time_offset().as_secs() as u32; + let max_future_offset = chainstate.config.max_future_block_time_offset.as_secs() as u32; let bad_block_in_future = Block::new( vec![], @@ -771,14 +775,7 @@ fn blocks_from_the_future() { fn test_mainnet_initialization() { let config = Arc::new(common::chain::config::create_mainnet()); let storage = Store::new_empty().unwrap(); - make_chainstate( - config, - storage, - None, - Default::default(), - ChainstateConfig {}, - ) - .unwrap(); + make_chainstate(config, Config::new(), storage, None, Default::default()).unwrap(); } fn make_invalid_pow_block( diff --git a/chainstate/src/detail/tests/reorgs_tests.rs b/chainstate/src/detail/tests/reorgs_tests.rs index 017f11f35c..ea2654bbca 100644 --- a/chainstate/src/detail/tests/reorgs_tests.rs +++ b/chainstate/src/detail/tests/reorgs_tests.rs @@ -17,9 +17,12 @@ use std::sync::Mutex; -use crate::detail::tests::{ - test_framework::{BlockTestFramework, TestBlockParams, TestSpentStatus}, - *, +use crate::{ + detail::tests::{ + test_framework::{BlockTestFramework, TestBlockParams, TestSpentStatus}, + *, + }, + Config, }; use chainstate_storage::{BlockchainStorageRead, Store}; use common::chain::config::create_unit_test_config; @@ -29,9 +32,10 @@ use common::chain::config::create_unit_test_config; fn reorg_simple() { common::concurrency::model(|| { let config = Arc::new(create_unit_test_config()); + let config_ = Config::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = - Chainstate::new_no_genesis(config, storage, None, Default::default()).unwrap(); + Chainstate::new_no_genesis(config, config_, storage, None, Default::default()).unwrap(); // Process the genesis block. chainstate diff --git a/chainstate/src/lib.rs b/chainstate/src/lib.rs index 2f7776c4f8..0f0b4274a7 100644 --- a/chainstate/src/lib.rs +++ b/chainstate/src/lib.rs @@ -59,13 +59,14 @@ type ChainstateHandle = subsystem::Handle>; pub fn make_chainstate( chain_config: Arc, + config: Config, chainstate_storage: chainstate_storage::Store, custom_orphan_error_hook: Option>, time_getter: TimeGetter, - _config: Config, ) -> Result, ChainstateError> { let cons = Chainstate::new( chain_config, + config, chainstate_storage, custom_orphan_error_hook, time_getter, diff --git a/chainstate/src/rpc.rs b/chainstate/src/rpc.rs index 3f8cac7f20..f2a48a4331 100644 --- a/chainstate/src/rpc.rs +++ b/chainstate/src/rpc.rs @@ -94,10 +94,11 @@ mod test { ) { let storage = chainstate_storage::Store::new_empty().unwrap(); let cfg = Arc::new(common::chain::config::create_unit_test_config()); + let config = Config::new(); let mut man = subsystem::Manager::new("rpctest"); let handle = man.add_subsystem( "chainstate", - crate::make_chainstate(cfg, storage, None, Default::default(), Config {}).unwrap(), + crate::make_chainstate(cfg, config, storage, None, Default::default()).unwrap(), ); let _ = man.add_raw_subsystem( "test", diff --git a/common/src/chain/config/builder.rs b/common/src/chain/config/builder.rs index 1f4962c725..99e756db0b 100644 --- a/common/src/chain/config/builder.rs +++ b/common/src/chain/config/builder.rs @@ -19,7 +19,7 @@ use super::{create_mainnet_genesis, create_unit_test_genesis, ChainConfig, Chain use crate::chain::{ block::Block, ConsensusUpgrade, Destination, NetUpgrades, PoWChainConfig, UpgradeVersion, }; -use crate::primitives::{semver::SemVer, BlockDistance, BlockHeight, Idable}; +use crate::primitives::{BlockHeight, Idable}; use std::collections::BTreeMap; use std::time::Duration; @@ -87,15 +87,8 @@ pub struct Builder { address_prefix: String, rpc_port: u16, p2p_port: u16, - magic_bytes: [u8; 4], - blockreward_maturity: BlockDistance, - max_future_block_time_offset: Duration, - version: SemVer, target_block_spacing: Duration, coin_decimals: u8, - max_block_header_size: usize, - max_block_size_with_standard_txs: usize, - max_block_size_with_smart_contracts: usize, net_upgrades: NetUpgrades, genesis_block: GenesisBlockInit, emission_schedule: EmissionScheduleInit, @@ -107,14 +100,7 @@ impl Builder { Self { chain_type, address_prefix: chain_type.default_address_prefix().to_string(), - blockreward_maturity: super::MAINNET_BLOCKREWARD_MATURITY, coin_decimals: Mlt::DECIMALS, - magic_bytes: chain_type.default_magic_bytes(), - version: SemVer::new(0, 1, 0), - max_block_header_size: super::MAX_BLOCK_HEADER_SIZE, - max_block_size_with_standard_txs: super::MAX_BLOCK_TXS_SIZE, - max_block_size_with_smart_contracts: super::MAX_BLOCK_CONTRACTS_SIZE, - max_future_block_time_offset: super::DEFAULT_MAX_FUTURE_BLOCK_TIME_OFFSET, target_block_spacing: super::DEFAULT_TARGET_BLOCK_SPACING, p2p_port: 8978, rpc_port: 15234, @@ -136,14 +122,7 @@ impl Builder { let Self { chain_type, address_prefix, - blockreward_maturity, coin_decimals, - magic_bytes, - version, - max_block_header_size, - max_block_size_with_standard_txs, - max_block_size_with_smart_contracts, - max_future_block_time_offset, target_block_spacing, p2p_port, rpc_port, @@ -171,14 +150,7 @@ impl Builder { ChainConfig { chain_type, address_prefix, - blockreward_maturity, coin_decimals, - magic_bytes, - version, - max_block_header_size, - max_block_size_with_standard_txs, - max_block_size_with_smart_contracts, - max_future_block_time_offset, target_block_spacing, p2p_port, rpc_port, @@ -209,15 +181,8 @@ impl Builder { builder_method!(address_prefix: String); builder_method!(rpc_port: u16); builder_method!(p2p_port: u16); - builder_method!(magic_bytes: [u8; 4]); - builder_method!(blockreward_maturity: BlockDistance); - builder_method!(max_future_block_time_offset: Duration); - builder_method!(version: SemVer); builder_method!(target_block_spacing: Duration); builder_method!(coin_decimals: u8); - builder_method!(max_block_header_size: usize); - builder_method!(max_block_size_with_standard_txs: usize); - builder_method!(max_block_size_with_smart_contracts: usize); builder_method!(net_upgrades: NetUpgrades); /// Set the genesis block to be the unit test version diff --git a/common/src/chain/config/mod.rs b/common/src/chain/config/mod.rs index 61c33b8b94..89ef2c85b2 100644 --- a/common/src/chain/config/mod.rs +++ b/common/src/chain/config/mod.rs @@ -37,7 +37,6 @@ use crate::primitives::{semver::SemVer, BlockHeight}; use std::collections::BTreeMap; 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( @@ -70,7 +69,7 @@ impl ChainType { } } - const fn default_magic_bytes(&self) -> [u8; 4] { + pub const fn default_magic_bytes(&self) -> [u8; 4] { match self { ChainType::Mainnet => [0x1a, 0x64, 0xe5, 0xf1], ChainType::Testnet => [0x2b, 0x7e, 0x19, 0xf6], @@ -88,18 +87,11 @@ pub struct ChainConfig { p2p_port: u16, height_checkpoint_data: BTreeMap>, net_upgrades: NetUpgrades, - magic_bytes: [u8; 4], genesis_block: Block, genesis_block_id: Id, - blockreward_maturity: BlockDistance, - max_future_block_time_offset: Duration, - version: SemVer, target_block_spacing: Duration, coin_decimals: u8, emission_schedule: EmissionSchedule, - max_block_header_size: usize, - max_block_size_with_standard_txs: usize, - max_block_size_with_smart_contracts: usize, } impl ChainConfig { @@ -115,18 +107,6 @@ impl ChainConfig { &self.genesis_block } - pub fn magic_bytes(&self) -> &[u8; 4] { - &self.magic_bytes - } - - pub fn magic_bytes_as_u32(&self) -> u32 { - u32::from_le_bytes(*self.magic_bytes()) - } - - pub fn version(&self) -> &SemVer { - &self.version - } - pub fn chain_type(&self) -> &ChainType { &self.chain_type } @@ -159,43 +139,16 @@ impl ChainConfig { self.coin_decimals } - pub fn max_future_block_time_offset(&self) -> &Duration { - &self.max_future_block_time_offset - } - pub fn block_subsidy_at_height(&self, height: &BlockHeight) -> Amount { self.emission_schedule().subsidy(*height).to_amount_atoms() } - pub fn max_block_header_size(&self) -> usize { - self.max_block_header_size - } - - pub fn max_block_size_from_txs(&self) -> usize { - self.max_block_size_with_standard_txs - } - - pub fn max_block_size_from_smart_contracts(&self) -> usize { - self.max_block_size_with_smart_contracts - } - // TODO: this should be part of net-upgrades. There should be no canonical definition of PoW for any chain config pub const fn get_proof_of_work_config(&self) -> PoWChainConfig { PoWChainConfig::new(self.chain_type) } - - pub const fn blockreward_maturity(&self) -> &BlockDistance { - &self.blockreward_maturity - } } -// If block time is 2 minutes (which is my goal eventually), then 500 is equivalent to 100 in bitcoin's 10 minutes. -const MAINNET_BLOCKREWARD_MATURITY: BlockDistance = BlockDistance::new(500); -// DSA allows us to have blocks up to 1mb -const MAX_BLOCK_HEADER_SIZE: usize = 1024; -const MAX_BLOCK_TXS_SIZE: usize = 524_288; -const MAX_BLOCK_CONTRACTS_SIZE: usize = 524_288; - fn create_mainnet_genesis() -> Block { use crate::chain::transaction::{TxInput, TxOutput}; @@ -301,12 +254,4 @@ mod tests { assert_eq!(&chain_type.to_string(), chain_type_str); } } - - #[test] - fn different_magic_bytes() { - let config1 = Builder::new(ChainType::Regtest).build(); - let config2 = Builder::new(ChainType::Regtest).magic_bytes([1, 2, 3, 4]).build(); - - assert_ne!(config1.magic_bytes(), config2.magic_bytes()); - } } diff --git a/common/src/primitives/height.rs b/common/src/primitives/height.rs index 6f248528aa..84d89b1639 100644 --- a/common/src/primitives/height.rs +++ b/common/src/primitives/height.rs @@ -13,8 +13,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::fmt; -use std::ops::{Add, Sub}; +use std::{ + fmt, + ops::{Add, Sub}, +}; + +use serde::{Deserialize, Serialize}; use serialization::{Decode, Encode}; @@ -162,7 +166,9 @@ impl BlockHeight { ///////////////////////////// -#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Encode, Decode)] +#[derive( + Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Encode, Decode, Serialize, Deserialize, +)] pub struct BlockDistance(DistanceIntType); impl BlockDistance { diff --git a/common/src/primitives/semver.rs b/common/src/primitives/semver.rs index a0efddebca..a7bf825803 100644 --- a/common/src/primitives/semver.rs +++ b/common/src/primitives/semver.rs @@ -14,9 +14,12 @@ // limitations under the License. // // Author(s): A. Altonen + +use serde::{Deserialize, Serialize}; + use serialization::{Decode, Encode}; -#[derive(Debug, PartialEq, Eq, Encode, Decode, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Encode, Decode, Copy, Clone, Serialize, Deserialize)] pub struct SemVer { pub major: u8, pub minor: u8, diff --git a/node/src/config.rs b/node/src/config.rs index 79ea280208..281f303bc2 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -35,7 +35,7 @@ pub struct Config { impl Config { /// Creates a new `Config` instance for the specified chain type. pub fn new(net: ChainType) -> Result { - let chainstate = chainstate::Config::new(net); + let chainstate = chainstate::Config::new(); let p2p = p2p::Config::new(net); let rpc = rpc::Config::new()?; Ok(Self { diff --git a/node/src/main.rs b/node/src/main.rs index 28e57fe0ff..03b8b6ab2d 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -23,7 +23,7 @@ use logging::log; use node::{Command, Config, Options}; -async fn run() -> anyhow::Result<()> { +async fn run() -> Result<()> { let opts = Options::from_args(std::env::args_os()); logging::init_logging(opts.log_path.as_ref()); log::trace!("Command line options: {opts:?}"); diff --git a/node/src/runner.rs b/node/src/runner.rs index 5317f3b784..ee78379c3a 100644 --- a/node/src/runner.rs +++ b/node/src/runner.rs @@ -54,10 +54,10 @@ pub async fn initialize(config: Config) -> anyhow::Result { "chainstate", chainstate::make_chainstate( Arc::clone(&chain_config), + config.chainstate, storage.clone(), None, Default::default(), - config.chainstate, )?, ); @@ -66,8 +66,8 @@ pub async fn initialize(config: Config) -> anyhow::Result { "p2p", p2p::make_p2p::( Arc::clone(&chain_config), - chainstate.clone(), config.p2p, + chainstate.clone(), ) .await .expect("The p2p subsystem initialization failed"), diff --git a/p2p/src/config.rs b/p2p/src/config.rs index c745136603..95f6b3ffc2 100644 --- a/p2p/src/config.rs +++ b/p2p/src/config.rs @@ -15,13 +15,15 @@ use serde::{Deserialize, Serialize}; -use common::chain::config::ChainType; +use common::{chain::config::ChainType, primitives::semver::SemVer}; /// The p2p subsystem configuration. #[derive(Serialize, Deserialize, Debug)] pub struct Config { /// Address to bind P2P to. pub address: String, + pub version: SemVer, + pub magic_bytes: [u8; 4], } impl Config { @@ -29,6 +31,13 @@ impl Config { pub fn new(net: ChainType) -> Self { Self { address: "/ip/::1/tcp/3031".into(), + version: SemVer::new(0, 1, 0), + magic_bytes: net.default_magic_bytes(), } } + + /// Returns magic bytes as little endian `u32`. + pub fn magic_bytes_as_u32(&self) -> u32 { + u32::from_le_bytes(self.magic_bytes) + } } diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index 3bcace9fa5..1a015390c6 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -19,7 +19,6 @@ use crate::{ net::{ConnectivityService, NetworkingService, PubSubService, SyncingCodecService}, }; use chainstate::chainstate_interface; -use common::chain::ChainConfig; use logging::log; use std::{fmt::Debug, str::FromStr, sync::Arc, time::Duration}; use tokio::sync::{mpsc, oneshot}; @@ -154,17 +153,17 @@ where /// /// This function starts the networking backend and individual manager objects. pub async fn new( - bind_addr: String, - config: Arc, + config: Config, consensus_handle: subsystem::Handle>, ) -> crate::Result where ::Address: FromStr, <::Address as FromStr>::Err: Debug, { + let config = Arc::new(config); let (conn, pubsub, sync) = T::start( - bind_addr.parse::().map_err(|_| { - P2pError::ConversionError(ConversionError::InvalidAddress(bind_addr)) + config.address.parse::().map_err(|_| { + P2pError::ConversionError(ConversionError::InvalidAddress(config.address)) })?, &[], Arc::clone(&config), @@ -232,9 +231,8 @@ impl subsystem::Subsystem for P2pInterface {} pub type P2pHandle = subsystem::Handle>; pub async fn make_p2p( - chain_config: Arc, - consensus_handle: subsystem::Handle>, config: Config, + consensus_handle: subsystem::Handle>, ) -> crate::Result> where T: NetworkingService + 'static, @@ -247,6 +245,6 @@ where <::PeerId as FromStr>::Err: Debug, { Ok(P2pInterface { - p2p: P2P::new(config.address, chain_config, consensus_handle).await?, + p2p: P2P::new(config, consensus_handle).await?, }) } diff --git a/p2p/src/net/libp2p/behaviour.rs b/p2p/src/net/libp2p/behaviour.rs index b88f6a8087..34f1299daf 100644 --- a/p2p/src/net/libp2p/behaviour.rs +++ b/p2p/src/net/libp2p/behaviour.rs @@ -27,8 +27,8 @@ use crate::{ types::{self, ConnectivityEvent, Libp2pBehaviourEvent, PubSubEvent}, }, }, + Config, }; -use common::chain::config::ChainConfig; use libp2p::{ core::PeerId, gossipsub::{self, Gossipsub, GossipsubConfigBuilder, MessageAuthenticity, ValidationMode}, @@ -92,11 +92,7 @@ type Libp2pNetworkBehaviourAction = NetworkBehaviourAction< as IntoConnectionHandler>::Handler as ConnectionHandler>::InEvent>; impl Libp2pBehaviour { - pub async fn new( - config: Arc, - id_keys: identity::Keypair, - relay_mdns: bool, - ) -> Self { + pub async fn new(config: Arc, id_keys: identity::Keypair, relay_mdns: bool) -> Self { let gossipsub_config = GossipsubConfigBuilder::default() .heartbeat_interval(GOSSIPSUB_HEARTBEAT) .validation_mode(ValidationMode::Strict) @@ -105,7 +101,7 @@ impl Libp2pBehaviour { .build() .expect("configuration to be valid"); - let version = config.version(); + let version = config.version; let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", version.major, diff --git a/p2p/src/net/libp2p/mod.rs b/p2p/src/net/libp2p/mod.rs index 0b5f51be0d..613c048952 100644 --- a/p2p/src/net/libp2p/mod.rs +++ b/p2p/src/net/libp2p/mod.rs @@ -25,6 +25,7 @@ use crate::{ types::{ConnectivityEvent, PubSubEvent, PubSubTopic, SyncingEvent}, ConnectivityService, NetworkingService, PubSubService, SyncingCodecService, }, + Config, }; use async_trait::async_trait; use itertools::*; @@ -230,7 +231,7 @@ impl NetworkingService for Libp2pService { async fn start( bind_addr: Self::Address, strategies: &[Self::DiscoveryStrategy], - chain_config: Arc, + config: Arc, timeout: std::time::Duration, ) -> crate::Result<( Self::ConnectivityHandle, @@ -258,7 +259,7 @@ impl NetworkingService for Libp2pService { let swarm = SwarmBuilder::new( transport, - behaviour::Libp2pBehaviour::new(Arc::clone(&chain_config), id_keys, relay_mdns).await, + behaviour::Libp2pBehaviour::new(Arc::clone(&config), id_keys, relay_mdns).await, peer_id, ) .build(); diff --git a/p2p/src/net/libp2p/tests/mod.rs b/p2p/src/net/libp2p/tests/mod.rs index 9ef6dc274c..f02c2f5efa 100644 --- a/p2p/src/net/libp2p/tests/mod.rs +++ b/p2p/src/net/libp2p/tests/mod.rs @@ -14,10 +14,13 @@ // limitations under the License. // // Author(s): A. Altonen -use crate::net::{ - self, - libp2p::sync::*, - libp2p::{backend::Backend, behaviour, types}, +use crate::{ + net::{ + self, + libp2p::sync::*, + libp2p::{backend::Backend, behaviour, types}, + }, + Config, }; use futures::prelude::*; use libp2p::{ @@ -56,7 +59,7 @@ mod ping; #[allow(dead_code)] pub async fn make_libp2p( - config: common::chain::ChainConfig, + config: Config, addr: Multiaddr, topics: &[net::types::PubSubTopic], relay_mdns: bool, @@ -90,8 +93,8 @@ pub async fn make_libp2p( .build() .expect("configuration to be valid"); - let version = config.version(); - let magic = config.magic_bytes(); + let version = config.version; + let magic = config.magic_bytes; let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", version.major, @@ -156,7 +159,7 @@ pub async fn make_libp2p( #[allow(dead_code)] pub async fn make_libp2p_with_ping( - config: common::chain::ChainConfig, + config: Config, addr: Multiaddr, topics: &[net::types::PubSubTopic], ping: libp2p_ping::Behaviour, @@ -191,8 +194,8 @@ pub async fn make_libp2p_with_ping( .build() .expect("configuration to be valid"); - let version = config.version(); - let magic = config.magic_bytes(); + let version = config.version; + let magic = config.magic_bytes; let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", version.major, @@ -299,9 +302,9 @@ pub fn make_transport_and_keys() -> (Boxed<(PeerId, StreamMuxerBox)>, PeerId, id } #[allow(dead_code)] -pub fn make_identify(config: common::chain::ChainConfig, id_keys: identity::Keypair) -> Identify { - let version = config.version(); - let magic = config.magic_bytes(); +pub fn make_identify(config: Config, id_keys: identity::Keypair) -> Identify { + let version = config.version; + let magic = config.magic_bytes; let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", version.major, diff --git a/p2p/src/net/mock/mod.rs b/p2p/src/net/mock/mod.rs index 95f2394090..6511880287 100644 --- a/p2p/src/net/mock/mod.rs +++ b/p2p/src/net/mock/mod.rs @@ -20,6 +20,7 @@ use crate::{ types::{ConnectivityEvent, PubSubEvent, PubSubTopic, SyncingEvent, ValidationResult}, ConnectivityService, NetworkingService, PubSubService, SyncingCodecService, }, + Config, }; use async_trait::async_trait; use logging::log; @@ -97,7 +98,7 @@ impl NetworkingService for MockService { async fn start( addr: Self::Address, _strategies: &[Self::DiscoveryStrategy], - _config: Arc, + _config: Arc, timeout: std::time::Duration, ) -> crate::Result<( Self::ConnectivityHandle, diff --git a/p2p/src/net/mod.rs b/p2p/src/net/mod.rs index bc28ad8fdd..4b654ee8e1 100644 --- a/p2p/src/net/mod.rs +++ b/p2p/src/net/mod.rs @@ -14,7 +14,7 @@ // limitations under the License. // // Author(s): A. Altonen -use crate::{error, message}; +use crate::{error, message, Config}; use async_trait::async_trait; use common::primitives; use std::{ @@ -72,15 +72,13 @@ pub trait NetworkingService { /// /// `strategies` - list of strategies that are used for peer discovery /// - /// `topics` - list of pubsub topics that the implementation should subscribe to - /// - /// `chain_config` - chain config of the node + /// `config` - p2p config. /// /// `timeout` - timeout for outbound connections async fn start( bind_addr: Self::Address, strategies: &[Self::DiscoveryStrategy], - chain_config: Arc, + config: Arc, timeout: std::time::Duration, ) -> crate::Result<( Self::ConnectivityHandle, diff --git a/p2p/src/pubsub.rs b/p2p/src/pubsub.rs index 55858d2d56..11d4b8f63e 100644 --- a/p2p/src/pubsub.rs +++ b/p2p/src/pubsub.rs @@ -24,16 +24,14 @@ use crate::{ types::{PubSubEvent, PubSubTopic, ValidationResult}, NetworkingService, PubSubService, }, + Config, }; use chainstate::{ ban_score::BanScore, chainstate_interface, BlockError, ChainstateError::{FailedToInitializeChainstate, FailedToReadProperty, ProcessBlockError}, }; -use common::{ - chain::{block::Block, ChainConfig}, - primitives::Id, -}; +use common::{chain::block::Block, primitives::Id}; use futures::FutureExt; use logging::log; use std::sync::Arc; @@ -45,7 +43,7 @@ const CHANNEL_SIZE: usize = 64; /// Publish-subscribe message handler pub struct PubSubMessageHandler { /// Chain config - _chain_config: Arc, + _chain_config: Arc, /// Handle for communication with networking service pubsub_handle: T::PubSubHandle, @@ -73,7 +71,7 @@ where /// * `chainstate_handle` - handle for communication with chainstate /// * `rx_pubsub` - RX channel for receiving control events pub fn new( - _chain_config: Arc, + _chain_config: Arc, pubsub_handle: T::PubSubHandle, chainstate_handle: subsystem::Handle>, rx_pubsub: mpsc::Receiver, diff --git a/p2p/src/swarm/mod.rs b/p2p/src/swarm/mod.rs index c41ccdd55b..72339cb104 100644 --- a/p2p/src/swarm/mod.rs +++ b/p2p/src/swarm/mod.rs @@ -26,8 +26,9 @@ use crate::{ error::{P2pError, PeerError, ProtocolError}, event, net::{self, ConnectivityService, NetworkingService}, + Config, }; -use common::{chain::ChainConfig, primitives::semver}; +use common::primitives::semver; use futures::FutureExt; use logging::log; use std::{collections::HashMap, fmt::Debug, str::FromStr, sync::Arc, time::Duration}; @@ -47,7 +48,7 @@ where T: NetworkingService, { /// Chain config - config: Arc, + config: Arc, /// Handle for sending/receiving connectivity events handle: T::ConnectivityHandle, @@ -76,7 +77,7 @@ where <::Address as FromStr>::Err: Debug, { pub fn new( - config: Arc, + config: Arc, handle: T::ConnectivityHandle, rx_swarm: mpsc::Receiver>, tx_sync: mpsc::Sender>, @@ -156,7 +157,7 @@ where /// /// Make sure that local and remote peer have the same software version fn validate_version(&self, version: &semver::SemVer) -> bool { - version == self.config.version() + version == &self.config.version } /// Handle connection established event @@ -168,16 +169,16 @@ where log::debug!("{}", info); ensure!( - info.magic_bytes == *self.config.magic_bytes(), + info.magic_bytes == self.config.magic_bytes, P2pError::ProtocolError(ProtocolError::DifferentNetwork( - *self.config.magic_bytes(), + self.config.magic_bytes, info.magic_bytes, )) ); ensure!( self.validate_version(&info.version), P2pError::ProtocolError(ProtocolError::InvalidVersion( - *self.config.version(), + self.config.version, info.version )) ); diff --git a/p2p/src/sync/mod.rs b/p2p/src/sync/mod.rs index 558174dea4..4d7b256407 100644 --- a/p2p/src/sync/mod.rs +++ b/p2p/src/sync/mod.rs @@ -18,15 +18,13 @@ use crate::{ error::{P2pError, PeerError, ProtocolError}, event, message, net::{self, types::SyncingEvent, NetworkingService, SyncingCodecService}, + Config, }; use chainstate::{ ban_score::BanScore, chainstate_interface, BlockError, ChainstateError::ProcessBlockError, }; use common::{ - chain::{ - block::{Block, BlockHeader}, - config::ChainConfig, - }, + chain::block::{Block, BlockHeader}, primitives::{Id, Idable}, }; use futures::FutureExt; @@ -73,7 +71,7 @@ pub enum SyncState { /// peer it's connected to and actively keep track of the peer's state. pub struct SyncManager { /// Chain config - config: Arc, + config: Arc, /// Syncing state of the local node state: SyncState, @@ -107,7 +105,7 @@ where T::SyncingCodecHandle: SyncingCodecService, { pub fn new( - config: Arc, + config: Arc, handle: T::SyncingCodecHandle, chainstate_handle: subsystem::Handle>, rx_sync: mpsc::Receiver>, diff --git a/p2p/src/sync/tests/mod.rs b/p2p/src/sync/tests/mod.rs index 14f3d7208e..4663a8b11f 100644 --- a/p2p/src/sync/tests/mod.rs +++ b/p2p/src/sync/tests/mod.rs @@ -50,10 +50,11 @@ where let (tx_swarm, rx_swarm) = mpsc::channel(16); let storage = chainstate_storage::Store::new_empty().unwrap(); let cfg = Arc::new(common::chain::config::create_unit_test_config()); + let config = ChainstateConfig::new(); let mut man = subsystem::Manager::new("TODO"); let handle = man.add_subsystem( "consensus", - make_chainstate(cfg, storage, None, Default::default(), ChainstateConfig {}).unwrap(), + make_chainstate(cfg, config, storage, None, Default::default()).unwrap(), ); tokio::spawn(async move { man.main().await }); diff --git a/p2p/test-utils/src/lib.rs b/p2p/test-utils/src/lib.rs index a175c7dff7..9c7c1d87bc 100644 --- a/p2p/test-utils/src/lib.rs +++ b/p2p/test-utils/src/lib.rs @@ -17,7 +17,10 @@ #![allow(clippy::unwrap_used)] -use chainstate::{chainstate_interface::ChainstateInterface, make_chainstate, BlockSource}; +use chainstate::{ + chainstate_interface::ChainstateInterface, make_chainstate, BlockSource, + Config as ChainstateConfig, +}; use common::{ chain::{ block::{timestamp::BlockTimestamp, Block, ConsensusData}, @@ -146,10 +149,10 @@ pub async fn start_chainstate( "chainstate", make_chainstate( config, + ChainstateConfig::new(), storage, None, Default::default(), - chainstate::Config {}, ) .unwrap(), ); From dcc980c2774a44b2bd871e71d6ac5266fa1a0c00 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Sat, 9 Jul 2022 23:52:46 +0200 Subject: [PATCH 05/30] Add example of option override --- common/src/chain/config/mod.rs | 3 +-- node/src/config.rs | 10 +++++----- node/src/main.rs | 2 +- node/src/options.rs | 3 +++ node/src/runner.rs | 10 +++------- p2p/src/lib.rs | 2 +- p2p/src/sync/mod.rs | 4 +++- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/common/src/chain/config/mod.rs b/common/src/chain/config/mod.rs index 89ef2c85b2..b81bc28bbb 100644 --- a/common/src/chain/config/mod.rs +++ b/common/src/chain/config/mod.rs @@ -32,8 +32,7 @@ use crate::chain::OutputPurpose; use crate::chain::{PoWChainConfig, UpgradeVersion}; use crate::primitives::id::{Id, H256}; use crate::primitives::Amount; -use crate::primitives::BlockDistance; -use crate::primitives::{semver::SemVer, BlockHeight}; +use crate::primitives::BlockHeight; use std::collections::BTreeMap; use std::time::Duration; diff --git a/node/src/config.rs b/node/src/config.rs index 281f303bc2..3660073247 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -47,13 +47,13 @@ impl Config { /// Reads a configuration from the path specified in options and overrides the provided /// parameters. - pub fn read(options: &RunOptions) -> Result { + pub fn read(options: RunOptions) -> Result { let config = fs::read_to_string(&options.config_path).context("Failed to read config")?; - let mut config = toml::from_str(&config).context("Failed to deserialize config")?; + let mut config: Config = toml::from_str(&config).context("Failed to deserialize config")?; - // if Some(x) = options.x { - // config.x = x; - // } + if let Some(address) = options.p2p_addr { + config.p2p.address = address; + } Ok(config) } diff --git a/node/src/main.rs b/node/src/main.rs index 03b8b6ab2d..bae0b87135 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -37,7 +37,7 @@ async fn run() -> Result<()> { Ok(()) } Command::Run(options) => { - let config = Config::read(&options).context("Failed to initialize config")?; + let config = Config::read(options).context("Failed to initialize config")?; node::run(config).await } } diff --git a/node/src/options.rs b/node/src/options.rs index a78a4c326e..cd29f3757a 100644 --- a/node/src/options.rs +++ b/node/src/options.rs @@ -54,8 +54,11 @@ pub enum Command { #[derive(Args, Debug)] pub struct RunOptions { + /// The path to the configuration file. #[clap(short, long, default_value = "./mintlayer.toml")] pub config_path: PathBuf, + #[clap(long, value_name = "ADDR")] + pub p2p_addr: Option, } impl Options { diff --git a/node/src/runner.rs b/node/src/runner.rs index ee78379c3a..20f95e6c8f 100644 --- a/node/src/runner.rs +++ b/node/src/runner.rs @@ -64,13 +64,9 @@ pub async fn initialize(config: Config) -> anyhow::Result { // P2P subsystem let p2p = manager.add_subsystem( "p2p", - p2p::make_p2p::( - Arc::clone(&chain_config), - config.p2p, - chainstate.clone(), - ) - .await - .expect("The p2p subsystem initialization failed"), + p2p::make_p2p::(config.p2p, chainstate.clone()) + .await + .expect("The p2p subsystem initialization failed"), ); // RPC subsystem diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index 1a015390c6..ad8ee8e0ef 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -163,7 +163,7 @@ where let config = Arc::new(config); let (conn, pubsub, sync) = T::start( config.address.parse::().map_err(|_| { - P2pError::ConversionError(ConversionError::InvalidAddress(config.address)) + P2pError::ConversionError(ConversionError::InvalidAddress(config.address.clone())) })?, &[], Arc::clone(&config), diff --git a/p2p/src/sync/mod.rs b/p2p/src/sync/mod.rs index 4d7b256407..f310dbb349 100644 --- a/p2p/src/sync/mod.rs +++ b/p2p/src/sync/mod.rs @@ -227,7 +227,9 @@ where locator .iter() .any(|header| &Some(header.get_id()) == headers[0].prev_block_id()) - || &Some(self.config.genesis_block_id()) == headers[0].prev_block_id(), + // TODO: FIXME: + || &Some(todo!()) == headers[0].prev_block_id(), + //|| &Some(self.config.genesis_block_id()) == headers[0].prev_block_id(), P2pError::ProtocolError(ProtocolError::InvalidMessage), ); } From 01c07d51eb71d5df7bb397073ee02af09b4a6589 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Sun, 10 Jul 2022 21:50:57 +0200 Subject: [PATCH 06/30] Fix p2p address --- p2p/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/p2p/src/config.rs b/p2p/src/config.rs index 95f6b3ffc2..8fa3241057 100644 --- a/p2p/src/config.rs +++ b/p2p/src/config.rs @@ -30,7 +30,7 @@ impl Config { /// Creates a new p2p configuration instance. pub fn new(net: ChainType) -> Self { Self { - address: "/ip/::1/tcp/3031".into(), + address: "/ip6/::1/tcp/3031".into(), version: SemVer::new(0, 1, 0), magic_bytes: net.default_magic_bytes(), } From 51879770e95616493de6d5443fe9d47236241071 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Mon, 11 Jul 2022 21:48:52 +0200 Subject: [PATCH 07/30] Add chain config to the configuration --- common/src/chain/config/mod.rs | 5 ----- node/src/config.rs | 10 ++++++++-- node/src/options.rs | 8 ++++---- p2p/src/config.rs | 13 +------------ 4 files changed, 13 insertions(+), 23 deletions(-) diff --git a/common/src/chain/config/mod.rs b/common/src/chain/config/mod.rs index b81bc28bbb..4d90df5a0a 100644 --- a/common/src/chain/config/mod.rs +++ b/common/src/chain/config/mod.rs @@ -81,13 +81,8 @@ impl ChainType { #[derive(Debug, Clone)] pub struct ChainConfig { chain_type: ChainType, - address_prefix: String, - rpc_port: u16, - p2p_port: u16, - height_checkpoint_data: BTreeMap>, net_upgrades: NetUpgrades, genesis_block: Block, - genesis_block_id: Id, target_block_spacing: Duration, coin_decimals: u8, emission_schedule: EmissionSchedule, diff --git a/node/src/config.rs b/node/src/config.rs index 3660073247..7e9035267c 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -20,12 +20,16 @@ use std::fs; use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; -use common::chain::config::ChainType; +use common::chain::config::{ChainConfig, ChainType}; use crate::RunOptions; #[derive(Serialize, Deserialize, Debug)] pub struct Config { + /// Shared chain configuration. + #[serde(flatten)] + chain_config: ChainConfig, + // Subsystems configurations. pub chainstate: chainstate::Config, pub p2p: p2p::Config, @@ -35,10 +39,12 @@ pub struct Config { impl Config { /// Creates a new `Config` instance for the specified chain type. pub fn new(net: ChainType) -> Result { + let chain_config = ChainConfig::new(net); let chainstate = chainstate::Config::new(); - let p2p = p2p::Config::new(net); + let p2p = p2p::Config::new(); let rpc = rpc::Config::new()?; Ok(Self { + chain_config, chainstate, p2p, rpc, diff --git a/node/src/options.rs b/node/src/options.rs index cd29f3757a..1aa7022f36 100644 --- a/node/src/options.rs +++ b/node/src/options.rs @@ -30,10 +30,6 @@ pub struct Options { #[clap(long, value_name = "PATH")] pub log_path: Option, - /// Blockchain type - #[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")] - pub net: ChainType, - #[clap(subcommand)] pub command: Command, } @@ -57,6 +53,10 @@ pub struct RunOptions { /// The path to the configuration file. #[clap(short, long, default_value = "./mintlayer.toml")] pub config_path: PathBuf, + /// Blockchain type. + #[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")] + net: Option, + /// Address to bind P2P to. #[clap(long, value_name = "ADDR")] pub p2p_addr: Option, } diff --git a/p2p/src/config.rs b/p2p/src/config.rs index 8fa3241057..0d11ca2e4d 100644 --- a/p2p/src/config.rs +++ b/p2p/src/config.rs @@ -15,29 +15,18 @@ use serde::{Deserialize, Serialize}; -use common::{chain::config::ChainType, primitives::semver::SemVer}; - /// The p2p subsystem configuration. #[derive(Serialize, Deserialize, Debug)] pub struct Config { /// Address to bind P2P to. pub address: String, - pub version: SemVer, - pub magic_bytes: [u8; 4], } impl Config { /// Creates a new p2p configuration instance. - pub fn new(net: ChainType) -> Self { + pub fn new() -> Self { Self { address: "/ip6/::1/tcp/3031".into(), - version: SemVer::new(0, 1, 0), - magic_bytes: net.default_magic_bytes(), } } - - /// Returns magic bytes as little endian `u32`. - pub fn magic_bytes_as_u32(&self) -> u32 { - u32::from_le_bytes(self.magic_bytes) - } } From 9f98689dcabbd175d9932d06ffe6ae3e4872466d Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 12 Jul 2022 13:27:47 +0200 Subject: [PATCH 08/30] Add some assert_cmd tests --- Cargo.lock | 23 +++++++++++++++++++++++ node/Cargo.toml | 3 +++ node/tests/cli.rs | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 node/tests/cli.rs diff --git a/Cargo.lock b/Cargo.lock index 5b74df1775..4e1414b411 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,6 +108,20 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e22d1f4b888c298a027c99dc9048015fac177587de20fc30232a057dfbe24a21" +[[package]] +name = "assert_cmd" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ae1ddd39efd67689deb1979d80bad3bf7f2b09c6e6117c8d1f2443b5e2f83e" +dependencies = [ + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + [[package]] name = "async-channel" version = "1.6.1" @@ -397,7 +411,9 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ + "lazy_static", "memchr", + "regex-automata", ] [[package]] @@ -933,6 +949,12 @@ dependencies = [ "quick-error 1.2.3", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "downcast" version = "0.11.0" @@ -2389,6 +2411,7 @@ name = "node" version = "0.1.0" dependencies = [ "anyhow", + "assert_cmd", "chainstate", "chainstate-storage", "clap 3.2.5", diff --git a/node/Cargo.toml b/node/Cargo.toml index bb22bd6450..9dfaa7175f 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -25,3 +25,6 @@ tokio = { version = "1.19", default-features = false } thiserror = "1.0" serde = { version = "1", features = ["derive"] } toml = "0.5" + +[dev-dependencies] +assert_cmd = "2" diff --git a/node/tests/cli.rs b/node/tests/cli.rs new file mode 100644 index 0000000000..2ef9e9d5c6 --- /dev/null +++ b/node/tests/cli.rs @@ -0,0 +1,37 @@ +// Copyright (c) 2022 RBB S.r.l +// opensource@mintlayer.org +// SPDX-License-Identifier: MIT +// Licensed under the MIT License; +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://spdx.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::path::Path; + +use assert_cmd::Command; + +const BIN_NAME: &str = env!("CARGO_BIN_EXE_node"); + +// This tests is only needed because the node name ix hardcoded here, so we get an easy to understand error if the name is changed. +#[test] +fn path_is_correct() { + assert!(Path::new(BIN_NAME).is_file()); +} + +#[test] +fn no_args() { + Command::new(BIN_NAME).assert().success().stdout(all_predicate()); +} + +#[test] +fn create_config() { + Command::new(BIN_NAME).arg("--create-config").assert().success(); + // TODO: FIXME: Check the config after creation. +} From dd78bb928a7c65487fdc0ed7cb23f4cffe0d89e1 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 12 Jul 2022 20:59:35 +0200 Subject: [PATCH 09/30] Two configs --- chainstate/src/detail/tests/events_tests.rs | 12 ++-- chainstate/src/detail/tests/mod.rs | 6 +- .../src/detail/tests/processing_tests.rs | 38 ++++++++----- chainstate/src/detail/tests/reorgs_tests.rs | 7 ++- chainstate/src/lib.rs | 15 ++--- common/src/chain/config/builder.rs | 20 +------ common/src/chain/config/mod.rs | 55 ++++++++++--------- common/src/primitives/semver.rs | 2 +- node/src/config.rs | 27 ++++++++- node/src/main.rs | 3 +- node/src/options.rs | 20 +++++-- node/src/runner.rs | 26 ++++----- node/tests/cli.rs | 12 +++- p2p/src/lib.rs | 14 +++-- p2p/src/net/libp2p/behaviour.rs | 15 +++-- p2p/src/net/libp2p/mod.rs | 5 +- p2p/src/net/libp2p/tests/mod.rs | 27 ++++----- p2p/src/net/mock/mod.rs | 3 +- p2p/src/net/mod.rs | 7 ++- p2p/src/pubsub.rs | 9 ++- p2p/src/swarm/mod.rs | 11 ++-- p2p/src/sync/mod.rs | 14 ++--- 22 files changed, 195 insertions(+), 153 deletions(-) diff --git a/chainstate/src/detail/tests/events_tests.rs b/chainstate/src/detail/tests/events_tests.rs index 9794a2a962..e56ddb892e 100644 --- a/chainstate/src/detail/tests/events_tests.rs +++ b/chainstate/src/detail/tests/events_tests.rs @@ -120,13 +120,13 @@ fn several_subscribers_several_events() { #[test] fn orphan_block() { common::concurrency::model(|| { - let config = Arc::new(create_unit_test_config()); - let config_ = Config::new(); + let chain_config = Arc::new(create_unit_test_config()); + let config = Config::new(); let storage = Store::new_empty().unwrap(); let (orphan_error_hook, errors) = orphan_error_hook(); let mut chainstate = Chainstate::new( + chain_config, config, - config_, storage, Some(orphan_error_hook), Default::default(), @@ -150,13 +150,13 @@ fn orphan_block() { #[test] fn custom_orphan_error_hook() { common::concurrency::model(|| { - let config = Arc::new(create_unit_test_config()); - let config_ = Config::new(); + let chain_config = Arc::new(create_unit_test_config()); + let config = Config::new(); let storage = Store::new_empty().unwrap(); let (orphan_error_hook, errors) = orphan_error_hook(); let mut chainstate = Chainstate::new( + chain_config, config, - config_, storage, Some(orphan_error_hook), Default::default(), diff --git a/chainstate/src/detail/tests/mod.rs b/chainstate/src/detail/tests/mod.rs index db8d7f2c5d..70e8b668f0 100644 --- a/chainstate/src/detail/tests/mod.rs +++ b/chainstate/src/detail/tests/mod.rs @@ -86,10 +86,10 @@ fn setup_chainstate() -> Chainstate { chainstate_with_config(create_unit_test_config()) } -fn chainstate_with_config(config: ChainConfig) -> Chainstate { +fn chainstate_with_config(chain_config: ChainConfig, config: Config) -> Chainstate { Chainstate::new( - Arc::new(config), - todo!(), + Arc::new(chain_config), + config, Store::new_empty().unwrap(), None, Default::default(), diff --git a/chainstate/src/detail/tests/processing_tests.rs b/chainstate/src/detail/tests/processing_tests.rs index a3e116ebc1..ab3645b67a 100644 --- a/chainstate/src/detail/tests/processing_tests.rs +++ b/chainstate/src/detail/tests/processing_tests.rs @@ -42,15 +42,20 @@ use crypto::random::{self, Rng}; #[test] fn genesis_peer_block() { common::concurrency::model(|| { - let config = Arc::new(create_unit_test_config()); - let config_ = Config::new(); + let chain_config = Arc::new(create_unit_test_config()); + let config = Config::new(); let storage = Store::new_empty().unwrap(); - let mut chainstate = - Chainstate::new_no_genesis(config.clone(), config_, storage, None, Default::default()) - .unwrap(); + let mut chainstate = Chainstate::new_no_genesis( + chain_config.clone(), + config, + storage, + None, + Default::default(), + ) + .unwrap(); assert_eq!( chainstate - .process_block(config.genesis_block().clone(), BlockSource::Peer) + .process_block(chain_config.genesis_block().clone(), BlockSource::Peer) .unwrap_err(), BlockError::InvalidBlockSource ); @@ -60,11 +65,12 @@ fn genesis_peer_block() { #[test] fn process_genesis_block() { common::concurrency::model(|| { - let config = Arc::new(create_unit_test_config()); - let config_ = Config::new(); + let chain_config = Arc::new(create_unit_test_config()); + let config = Config::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = - Chainstate::new_no_genesis(config, config_, storage, None, Default::default()).unwrap(); + Chainstate::new_no_genesis(chain_config, config, storage, None, Default::default()) + .unwrap(); let block_index = chainstate .process_block( @@ -140,11 +146,12 @@ fn test_orphans_chains() { #[test] fn empty_chainstate() { common::concurrency::model(|| { - let config = Arc::new(create_unit_test_config()); - let config_ = Config::new(); + let chain_config = Arc::new(create_unit_test_config()); + let config = Config::new(); let storage = Store::new_empty().unwrap(); let chainstate = - Chainstate::new_no_genesis(config, config_, storage, None, Default::default()).unwrap(); + Chainstate::new_no_genesis(chain_config, config, storage, None, Default::default()) + .unwrap(); assert_eq!(chainstate.get_best_block_id().unwrap(), None); assert_eq!( chainstate @@ -225,11 +232,12 @@ fn spend_inputs_simple() { #[test] fn straight_chain() { common::concurrency::model(|| { - let config = Arc::new(create_unit_test_config()); - let config_ = Config::new(); + let chain_config = Arc::new(create_unit_test_config()); + let config = Config::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = - Chainstate::new_no_genesis(config, config_, storage, None, Default::default()).unwrap(); + Chainstate::new_no_genesis(chain_config, config, storage, None, Default::default()) + .unwrap(); let genesis_index = chainstate .process_block( diff --git a/chainstate/src/detail/tests/reorgs_tests.rs b/chainstate/src/detail/tests/reorgs_tests.rs index ea2654bbca..5aca3cdc67 100644 --- a/chainstate/src/detail/tests/reorgs_tests.rs +++ b/chainstate/src/detail/tests/reorgs_tests.rs @@ -31,11 +31,12 @@ use common::chain::config::create_unit_test_config; #[test] fn reorg_simple() { common::concurrency::model(|| { - let config = Arc::new(create_unit_test_config()); - let config_ = Config::new(); + let chain_config = Arc::new(create_unit_test_config()); + let config = Config::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = - Chainstate::new_no_genesis(config, config_, storage, None, Default::default()).unwrap(); + Chainstate::new_no_genesis(chain_config, config, storage, None, Default::default()) + .unwrap(); // Process the genesis block. chainstate diff --git a/chainstate/src/lib.rs b/chainstate/src/lib.rs index 0f0b4274a7..88aff538b0 100644 --- a/chainstate/src/lib.rs +++ b/chainstate/src/lib.rs @@ -18,25 +18,22 @@ mod config; mod detail; -pub mod rpc; - -pub mod chainstate_interface_impl; - pub mod chainstate_interface; - -pub use detail::ban_score; +pub mod chainstate_interface_impl; +pub mod rpc; use std::sync::Arc; use chainstate_interface::ChainstateInterface; -pub use chainstate_interface_impl::ChainstateInterfaceImpl; use common::{ chain::{block::Block, ChainConfig}, primitives::{BlockHeight, Id}, }; -pub use config::Config; use detail::{time_getter::TimeGetter, PropertyQueryError}; -pub use detail::{BlockError, BlockSource, Chainstate}; + +pub use chainstate_interface_impl::ChainstateInterfaceImpl; +pub use config::Config; +pub use detail::{ban_score, BlockError, BlockSource, Chainstate}; #[derive(Debug, Clone)] pub enum ChainstateEvent { diff --git a/common/src/chain/config/builder.rs b/common/src/chain/config/builder.rs index 99e756db0b..f9f5a86070 100644 --- a/common/src/chain/config/builder.rs +++ b/common/src/chain/config/builder.rs @@ -13,6 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::{collections::BTreeMap, time::Duration}; + use super::emission_schedule::{self, *}; use super::{create_mainnet_genesis, create_unit_test_genesis, ChainConfig, ChainType}; @@ -21,9 +23,6 @@ use crate::chain::{ }; use crate::primitives::{BlockHeight, Idable}; -use std::collections::BTreeMap; -use std::time::Duration; - impl ChainType { fn default_genesis_init(&self) -> GenesisBlockInit { match self { @@ -84,9 +83,6 @@ impl GenesisBlockInit { #[derive(Clone)] pub struct Builder { chain_type: ChainType, - address_prefix: String, - rpc_port: u16, - p2p_port: u16, target_block_spacing: Duration, coin_decimals: u8, net_upgrades: NetUpgrades, @@ -99,11 +95,8 @@ impl Builder { pub fn new(chain_type: ChainType) -> Self { Self { chain_type, - address_prefix: chain_type.default_address_prefix().to_string(), coin_decimals: Mlt::DECIMALS, target_block_spacing: super::DEFAULT_TARGET_BLOCK_SPACING, - p2p_port: 8978, - rpc_port: 15234, genesis_block: chain_type.default_genesis_init(), emission_schedule: EmissionScheduleInit::Mainnet, net_upgrades: chain_type.default_net_upgrades(), @@ -121,11 +114,8 @@ impl Builder { pub fn build(self) -> ChainConfig { let Self { chain_type, - address_prefix, coin_decimals, target_block_spacing, - p2p_port, - rpc_port, genesis_block, emission_schedule, net_upgrades, @@ -149,11 +139,8 @@ impl Builder { ChainConfig { chain_type, - address_prefix, coin_decimals, target_block_spacing, - p2p_port, - rpc_port, genesis_block_id: genesis_block.get_id(), genesis_block, height_checkpoint_data: BTreeMap::new(), @@ -178,9 +165,6 @@ macro_rules! builder_method { impl Builder { builder_method!(chain_type: ChainType); - builder_method!(address_prefix: String); - builder_method!(rpc_port: u16); - builder_method!(p2p_port: u16); builder_method!(target_block_spacing: Duration); builder_method!(coin_decimals: u8); builder_method!(net_upgrades: NetUpgrades); diff --git a/common/src/chain/config/mod.rs b/common/src/chain/config/mod.rs index 4d90df5a0a..eca497eb74 100644 --- a/common/src/chain/config/mod.rs +++ b/common/src/chain/config/mod.rs @@ -19,24 +19,23 @@ pub mod emission_schedule; pub use builder::Builder; pub use emission_schedule::{EmissionSchedule, EmissionScheduleTabular, Mlt}; +use std::{collections::BTreeMap, time::Duration}; + use hex::FromHex; -use crate::chain::block::timestamp::BlockTimestamp; -use crate::chain::block::Block; -use crate::chain::block::ConsensusData; -use crate::chain::signature::inputsig::InputWitness; -use crate::chain::transaction::Destination; -use crate::chain::transaction::Transaction; -use crate::chain::upgrades::NetUpgrades; -use crate::chain::OutputPurpose; -use crate::chain::{PoWChainConfig, UpgradeVersion}; -use crate::primitives::id::{Id, H256}; -use crate::primitives::Amount; -use crate::primitives::BlockHeight; -use std::collections::BTreeMap; -use std::time::Duration; +use crate::{ + chain::{ + block::{timestamp::BlockTimestamp, Block, ConsensusData}, + signature::inputsig::InputWitness, + transaction::{Destination, Transaction}, + upgrades::NetUpgrades, + OutputPurpose, PoWChainConfig, UpgradeVersion, + }, + primitives::{semver::SemVer, Amount, BlockHeight id::{Id, H256}}, +}; pub const DEFAULT_TARGET_BLOCK_SPACING: Duration = Duration::from_secs(120); +pub const VERSION: SemVer = SemVer::new(0, 1, 0); #[derive( Debug, @@ -59,7 +58,7 @@ pub enum ChainType { } impl ChainType { - const fn default_address_prefix(&self) -> &'static str { + const fn address_prefix(&self) -> &'static str { match self { ChainType::Mainnet => "mtc", ChainType::Testnet => "tmt", @@ -68,7 +67,7 @@ impl ChainType { } } - pub const fn default_magic_bytes(&self) -> [u8; 4] { + pub const fn magic_bytes(&self) -> [u8; 4] { match self { ChainType::Mainnet => [0x1a, 0x64, 0xe5, 0xf1], ChainType::Testnet => [0x2b, 0x7e, 0x19, 0xf6], @@ -83,14 +82,18 @@ pub struct ChainConfig { chain_type: ChainType, net_upgrades: NetUpgrades, genesis_block: Block, - target_block_spacing: Duration, + pub target_block_spacing: Duration, coin_decimals: u8, emission_schedule: EmissionSchedule, } impl ChainConfig { + pub fn new(chain_type: ChainType) -> Self { + Builder::new(chain_type).build() + } + pub fn address_prefix(&self) -> &str { - &self.address_prefix + &self.chain_type.address_prefix() } pub fn genesis_block_id(&self) -> Id { @@ -101,20 +104,20 @@ impl ChainConfig { &self.genesis_block } - pub fn chain_type(&self) -> &ChainType { - &self.chain_type + pub fn magic_bytes(&self) -> &[u8; 4] { + &self.chain_type.magic_bytes() } - pub fn net_upgrade(&self) -> &NetUpgrades { - &self.net_upgrades + pub fn magic_bytes_as_u32(&self) -> u32 { + u32::from_le_bytes(*self.magic_bytes()) } - pub fn p2p_port(&self) -> u16 { - self.p2p_port + pub fn chain_type(&self) -> &ChainType { + &self.chain_type } - pub fn rpc_port(&self) -> u16 { - self.rpc_port + pub fn net_upgrade(&self) -> &NetUpgrades { + &self.net_upgrades } pub fn height_checkpoints(&self) -> &BTreeMap> { diff --git a/common/src/primitives/semver.rs b/common/src/primitives/semver.rs index a7bf825803..94b6eb8199 100644 --- a/common/src/primitives/semver.rs +++ b/common/src/primitives/semver.rs @@ -27,7 +27,7 @@ pub struct SemVer { } impl SemVer { - pub fn new(major: u8, minor: u8, patch: u16) -> Self { + pub const fn new(major: u8, minor: u8, patch: u16) -> Self { Self { major, minor, diff --git a/node/src/config.rs b/node/src/config.rs index 7e9035267c..4e9d550e2b 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -24,11 +24,12 @@ use common::chain::config::{ChainConfig, ChainType}; use crate::RunOptions; +/// The node configuration. #[derive(Serialize, Deserialize, Debug)] -pub struct Config { +struct Config { /// Shared chain configuration. #[serde(flatten)] - chain_config: ChainConfig, + pub chain_config: ChainConfig, // Subsystems configurations. pub chainstate: chainstate::Config, @@ -57,10 +58,32 @@ impl Config { let config = fs::read_to_string(&options.config_path).context("Failed to read config")?; let mut config: Config = toml::from_str(&config).context("Failed to deserialize config")?; + // Chain options. + if let Some(block_spacing) = options.target_block_spacing { + config.chain_config.target_block_spacing = block_spacing; + } + + // Chainstate options. + if let Some(max_size) = options.max_block_header_size { + config.chainstate.max_block_header_size = max_size; + } + if let Some(max_size) = options.max_block_size_from_txs { + config.chainstate.max_block_size_from_txs = max_size; + } + if let Some(max_size) = options.max_block_size_from_smart_contracts { + config.chainstate.max_block_size_from_smart_contracts = max_size; + } + + // P2p options. if let Some(address) = options.p2p_addr { config.p2p.address = address; } + // Rpc options. + if let Some(address) = options.rpc_addr { + config.rpc.address = address; + } + Ok(config) } } diff --git a/node/src/main.rs b/node/src/main.rs index bae0b87135..fb185e3837 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -32,12 +32,13 @@ async fn run() -> Result<()> { Command::CreateConfig { path, net } => { let config = Config::new(net)?; let config = toml::to_string(&config).context("Failed to serialize config")?; - log::trace!("Saving config to {path:?}: {config:#?}"); + log::trace!("Saving config to {path:?}\n: {config:#?}"); fs::write(path, config).context("Failed to write config")?; Ok(()) } Command::Run(options) => { let config = Config::read(options).context("Failed to initialize config")?; + log::trace!("Starting with the following config\n: {config:#?}"); node::run(config).await } } diff --git a/node/src/options.rs b/node/src/options.rs index 1aa7022f36..1a42210d01 100644 --- a/node/src/options.rs +++ b/node/src/options.rs @@ -15,7 +15,7 @@ //! The node command line options. -use std::{ffi::OsString, path::PathBuf}; +use std::{ffi::OsString, net::SocketAddr, path::PathBuf, time::Duration}; use clap::{Args, Parser, Subcommand}; use strum::VariantNames; @@ -53,12 +53,24 @@ pub struct RunOptions { /// The path to the configuration file. #[clap(short, long, default_value = "./mintlayer.toml")] pub config_path: PathBuf, - /// Blockchain type. - #[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")] - net: Option, + /// Target block spacing. + #[clap(long)] + pub target_block_spacing: Option, + /// Maximum header size. + #[clap(long)] + pub max_block_header_size: Option, + /// Maximum transactions size in a block. + #[clap(long)] + pub max_block_size_from_txs: Option, + /// Maximum smart contracts size in a block. + #[clap(long)] + pub max_block_size_from_smart_contracts: usize, /// Address to bind P2P to. #[clap(long, value_name = "ADDR")] pub p2p_addr: Option, + /// Address to bind RPC to. + #[clap(long, value_name = "ADDR")] + pub rpc_addr: Option, } impl Options { diff --git a/node/src/runner.rs b/node/src/runner.rs index 20f95e6c8f..a923f56a0b 100644 --- a/node/src/runner.rs +++ b/node/src/runner.rs @@ -29,20 +29,10 @@ enum Error { /// Initialize the node, giving caller the opportunity to add more subsystems before start. pub async fn initialize(config: Config) -> anyhow::Result { - // Initialize storage and chain configuration + // Initialize storage. let storage = chainstate_storage::Store::new_empty()?; - // Chain configuration - let chain_config = todo!(); - // let chain_config = match opts.net { - // ChainType::Mainnet => Arc::new(common::chain::config::create_mainnet()), - // ChainType::Regtest => Arc::new(common::chain::config::create_regtest()), - // chain_ty => return Err(Error::UnsupportedChain(chain_ty).into()), - // }; - // let config: Config = todo!(); - - // TODO: FIXME: Early return. - todo!(); + let chain_config = Arc::new(config.chain_config); // INITIALIZE SUBSYSTEMS @@ -64,15 +54,19 @@ pub async fn initialize(config: Config) -> anyhow::Result { // P2P subsystem let p2p = manager.add_subsystem( "p2p", - p2p::make_p2p::(config.p2p, chainstate.clone()) - .await - .expect("The p2p subsystem initialization failed"), + p2p::make_p2p::( + Arc::clone(&chain_config), + config.p2p, + chainstate.clone(), + ) + .await + .expect("The p2p subsystem initialization failed"), ); // RPC subsystem let _rpc = manager.add_subsystem( "rpc", - rpc::Builder::new(config.rpc) + rpc::Builder::new(Arc::clone(&chain_config), config.rpc) .register(chainstate.clone().into_rpc()) .register(NodeRpc::new(manager.make_shutdown_trigger()).into_rpc()) .register(p2p.clone().into_rpc()) diff --git a/node/tests/cli.rs b/node/tests/cli.rs index 2ef9e9d5c6..fdfcdd95c2 100644 --- a/node/tests/cli.rs +++ b/node/tests/cli.rs @@ -19,7 +19,8 @@ use assert_cmd::Command; const BIN_NAME: &str = env!("CARGO_BIN_EXE_node"); -// This tests is only needed because the node name ix hardcoded here, so we get an easy to understand error if the name is changed. +// This test is only needed because the node name ix hardcoded here, so if the name is changed we +// get an error that is easy to understand. #[test] fn path_is_correct() { assert!(Path::new(BIN_NAME).is_file()); @@ -27,11 +28,18 @@ fn path_is_correct() { #[test] fn no_args() { - Command::new(BIN_NAME).assert().success().stdout(all_predicate()); + Command::new(BIN_NAME).assert().success(); + // TODO: Check predicates?.. + todo!(); + todo!(); } #[test] fn create_config() { Command::new(BIN_NAME).arg("--create-config").assert().success(); // TODO: FIXME: Check the config after creation. + todo!(); + todo!(); } + +// TODO: Create config with args? diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index ad8ee8e0ef..5c5463abee 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -19,6 +19,7 @@ use crate::{ net::{ConnectivityService, NetworkingService, PubSubService, SyncingCodecService}, }; use chainstate::chainstate_interface; +use common::chain::ChainConfig; use logging::log; use std::{fmt::Debug, str::FromStr, sync::Arc, time::Duration}; use tokio::sync::{mpsc, oneshot}; @@ -153,6 +154,7 @@ where /// /// This function starts the networking backend and individual manager objects. pub async fn new( + chain_config: Arc, config: Config, consensus_handle: subsystem::Handle>, ) -> crate::Result @@ -160,13 +162,12 @@ where ::Address: FromStr, <::Address as FromStr>::Err: Debug, { - let config = Arc::new(config); let (conn, pubsub, sync) = T::start( config.address.parse::().map_err(|_| { P2pError::ConversionError(ConversionError::InvalidAddress(config.address.clone())) })?, &[], - Arc::clone(&config), + Arc::clone(&chain_config), TIMEOUT, ) .await?; @@ -177,7 +178,7 @@ where let (_tx_sync, _rx_sync) = mpsc::channel(CHANNEL_SIZE); let (tx_pubsub, rx_pubsub) = mpsc::channel(CHANNEL_SIZE); - let swarm_config = Arc::clone(&config); + let swarm_config = Arc::clone(&chain_config); tokio::spawn(async move { if let Err(e) = swarm::PeerManager::::new(swarm_config, conn, rx_swarm, tx_p2p_sync) .run() @@ -189,7 +190,7 @@ where let sync_handle = consensus_handle.clone(); let swarm_tx = tx_swarm.clone(); - let sync_config = Arc::clone(&config); + let sync_config = Arc::clone(&chain_config); tokio::spawn(async move { if let Err(e) = sync::SyncManager::::new( sync_config, @@ -209,7 +210,7 @@ where // TODO: merge with syncmanager when appropriate tokio::spawn(async move { if let Err(e) = pubsub::PubSubMessageHandler::::new( - config, + chain_config, pubsub, consensus_handle, rx_pubsub, @@ -231,6 +232,7 @@ impl subsystem::Subsystem for P2pInterface {} pub type P2pHandle = subsystem::Handle>; pub async fn make_p2p( + chain_config: Arc, config: Config, consensus_handle: subsystem::Handle>, ) -> crate::Result> @@ -245,6 +247,6 @@ where <::PeerId as FromStr>::Err: Debug, { Ok(P2pInterface { - p2p: P2P::new(config, consensus_handle).await?, + p2p: P2P::new(chain_config, config, consensus_handle).await?, }) } diff --git a/p2p/src/net/libp2p/behaviour.rs b/p2p/src/net/libp2p/behaviour.rs index 34f1299daf..785a23ff3f 100644 --- a/p2p/src/net/libp2p/behaviour.rs +++ b/p2p/src/net/libp2p/behaviour.rs @@ -27,8 +27,8 @@ use crate::{ types::{self, ConnectivityEvent, Libp2pBehaviourEvent, PubSubEvent}, }, }, - Config, }; +use common::chain::{config::VERSION, ChainConfig}; use libp2p::{ core::PeerId, gossipsub::{self, Gossipsub, GossipsubConfigBuilder, MessageAuthenticity, ValidationMode}, @@ -92,7 +92,11 @@ type Libp2pNetworkBehaviourAction = NetworkBehaviourAction< as IntoConnectionHandler>::Handler as ConnectionHandler>::InEvent>; impl Libp2pBehaviour { - pub async fn new(config: Arc, id_keys: identity::Keypair, relay_mdns: bool) -> Self { + pub async fn new( + config: Arc, + id_keys: identity::Keypair, + relay_mdns: bool, + ) -> Self { let gossipsub_config = GossipsubConfigBuilder::default() .heartbeat_interval(GOSSIPSUB_HEARTBEAT) .validation_mode(ValidationMode::Strict) @@ -101,12 +105,11 @@ impl Libp2pBehaviour { .build() .expect("configuration to be valid"); - let version = config.version; let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", - version.major, - version.minor, - version.patch, + VERSION.major, + VERSION.minor, + VERSION.patch, config.magic_bytes_as_u32(), ); let mut req_cfg = RequestResponseConfig::default(); diff --git a/p2p/src/net/libp2p/mod.rs b/p2p/src/net/libp2p/mod.rs index 613c048952..6fecb4ffa3 100644 --- a/p2p/src/net/libp2p/mod.rs +++ b/p2p/src/net/libp2p/mod.rs @@ -25,7 +25,6 @@ use crate::{ types::{ConnectivityEvent, PubSubEvent, PubSubTopic, SyncingEvent}, ConnectivityService, NetworkingService, PubSubService, SyncingCodecService, }, - Config, }; use async_trait::async_trait; use itertools::*; @@ -231,7 +230,7 @@ impl NetworkingService for Libp2pService { async fn start( bind_addr: Self::Address, strategies: &[Self::DiscoveryStrategy], - config: Arc, + chain_config: Arc, timeout: std::time::Duration, ) -> crate::Result<( Self::ConnectivityHandle, @@ -259,7 +258,7 @@ impl NetworkingService for Libp2pService { let swarm = SwarmBuilder::new( transport, - behaviour::Libp2pBehaviour::new(Arc::clone(&config), id_keys, relay_mdns).await, + behaviour::Libp2pBehaviour::new(Arc::clone(&chain_config), id_keys, relay_mdns).await, peer_id, ) .build(); diff --git a/p2p/src/net/libp2p/tests/mod.rs b/p2p/src/net/libp2p/tests/mod.rs index f02c2f5efa..0ef7dfc2eb 100644 --- a/p2p/src/net/libp2p/tests/mod.rs +++ b/p2p/src/net/libp2p/tests/mod.rs @@ -14,6 +14,7 @@ // limitations under the License. // // Author(s): A. Altonen + use crate::{ net::{ self, @@ -22,6 +23,7 @@ use crate::{ }, Config, }; +use common::chain::{config::VERSION, ChainConfig}; use futures::prelude::*; use libp2p::{ core::{muxing::StreamMuxerBox, transport::Boxed, upgrade, PeerId}, @@ -59,6 +61,7 @@ mod ping; #[allow(dead_code)] pub async fn make_libp2p( + chain_config: ChainConfig, config: Config, addr: Multiaddr, topics: &[net::types::PubSubTopic], @@ -93,13 +96,12 @@ pub async fn make_libp2p( .build() .expect("configuration to be valid"); - let version = config.version; let magic = config.magic_bytes; let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", - version.major, - version.minor, - version.patch, + VERSION.major, + VERSION.minor, + VERSION.patch, ((magic[0] as u32) << 24) | ((magic[1] as u32) << 16) | ((magic[2] as u32) << 8) @@ -159,6 +161,7 @@ pub async fn make_libp2p( #[allow(dead_code)] pub async fn make_libp2p_with_ping( + chain_config: ChainConfig, config: Config, addr: Multiaddr, topics: &[net::types::PubSubTopic], @@ -194,13 +197,12 @@ pub async fn make_libp2p_with_ping( .build() .expect("configuration to be valid"); - let version = config.version; let magic = config.magic_bytes; let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", - version.major, - version.minor, - version.patch, + VERSION.major, + VERSION.minor, + VERSION.patch, ((magic[0] as u32) << 24) | ((magic[1] as u32) << 16) | ((magic[2] as u32) << 8) @@ -302,14 +304,13 @@ pub fn make_transport_and_keys() -> (Boxed<(PeerId, StreamMuxerBox)>, PeerId, id } #[allow(dead_code)] -pub fn make_identify(config: Config, id_keys: identity::Keypair) -> Identify { - let version = config.version; +pub fn make_identify(config: ChainConfig, id_keys: identity::Keypair) -> Identify { let magic = config.magic_bytes; let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", - version.major, - version.minor, - version.patch, + VERSION.major, + VERSION.minor, + VERSION.patch, ((magic[0] as u32) << 24) | ((magic[1] as u32) << 16) | ((magic[2] as u32) << 8) diff --git a/p2p/src/net/mock/mod.rs b/p2p/src/net/mock/mod.rs index 6511880287..95f2394090 100644 --- a/p2p/src/net/mock/mod.rs +++ b/p2p/src/net/mock/mod.rs @@ -20,7 +20,6 @@ use crate::{ types::{ConnectivityEvent, PubSubEvent, PubSubTopic, SyncingEvent, ValidationResult}, ConnectivityService, NetworkingService, PubSubService, SyncingCodecService, }, - Config, }; use async_trait::async_trait; use logging::log; @@ -98,7 +97,7 @@ impl NetworkingService for MockService { async fn start( addr: Self::Address, _strategies: &[Self::DiscoveryStrategy], - _config: Arc, + _config: Arc, timeout: std::time::Duration, ) -> crate::Result<( Self::ConnectivityHandle, diff --git a/p2p/src/net/mod.rs b/p2p/src/net/mod.rs index 4b654ee8e1..39d25eef3c 100644 --- a/p2p/src/net/mod.rs +++ b/p2p/src/net/mod.rs @@ -14,7 +14,8 @@ // limitations under the License. // // Author(s): A. Altonen -use crate::{error, message, Config}; + +use crate::{error, message}; use async_trait::async_trait; use common::primitives; use std::{ @@ -72,13 +73,13 @@ pub trait NetworkingService { /// /// `strategies` - list of strategies that are used for peer discovery /// - /// `config` - p2p config. + /// `chain_config` - chain config of the node /// /// `timeout` - timeout for outbound connections async fn start( bind_addr: Self::Address, strategies: &[Self::DiscoveryStrategy], - config: Arc, + chain_config: Arc, timeout: std::time::Duration, ) -> crate::Result<( Self::ConnectivityHandle, diff --git a/p2p/src/pubsub.rs b/p2p/src/pubsub.rs index 11d4b8f63e..2b45e5fb2f 100644 --- a/p2p/src/pubsub.rs +++ b/p2p/src/pubsub.rs @@ -31,7 +31,10 @@ use chainstate::{ chainstate_interface, BlockError, ChainstateError::{FailedToInitializeChainstate, FailedToReadProperty, ProcessBlockError}, }; -use common::{chain::block::Block, primitives::Id}; +use common::{ + chain::{block::Block, ChainConfig}, + primitives::Id, +}; use futures::FutureExt; use logging::log; use std::sync::Arc; @@ -43,7 +46,7 @@ const CHANNEL_SIZE: usize = 64; /// Publish-subscribe message handler pub struct PubSubMessageHandler { /// Chain config - _chain_config: Arc, + _chain_config: Arc, /// Handle for communication with networking service pubsub_handle: T::PubSubHandle, @@ -71,7 +74,7 @@ where /// * `chainstate_handle` - handle for communication with chainstate /// * `rx_pubsub` - RX channel for receiving control events pub fn new( - _chain_config: Arc, + _chain_config: Arc, pubsub_handle: T::PubSubHandle, chainstate_handle: subsystem::Handle>, rx_pubsub: mpsc::Receiver, diff --git a/p2p/src/swarm/mod.rs b/p2p/src/swarm/mod.rs index 72339cb104..fd98a226cb 100644 --- a/p2p/src/swarm/mod.rs +++ b/p2p/src/swarm/mod.rs @@ -28,7 +28,10 @@ use crate::{ net::{self, ConnectivityService, NetworkingService}, Config, }; -use common::primitives::semver; +use common::{ + chain::{config::VERSION, ChainConfig}, + primitives::semver, +}; use futures::FutureExt; use logging::log; use std::{collections::HashMap, fmt::Debug, str::FromStr, sync::Arc, time::Duration}; @@ -48,7 +51,7 @@ where T: NetworkingService, { /// Chain config - config: Arc, + config: Arc, /// Handle for sending/receiving connectivity events handle: T::ConnectivityHandle, @@ -77,7 +80,7 @@ where <::Address as FromStr>::Err: Debug, { pub fn new( - config: Arc, + config: Arc, handle: T::ConnectivityHandle, rx_swarm: mpsc::Receiver>, tx_sync: mpsc::Sender>, @@ -157,7 +160,7 @@ where /// /// Make sure that local and remote peer have the same software version fn validate_version(&self, version: &semver::SemVer) -> bool { - version == &self.config.version + version == VERSION } /// Handle connection established event diff --git a/p2p/src/sync/mod.rs b/p2p/src/sync/mod.rs index f310dbb349..558174dea4 100644 --- a/p2p/src/sync/mod.rs +++ b/p2p/src/sync/mod.rs @@ -18,13 +18,15 @@ use crate::{ error::{P2pError, PeerError, ProtocolError}, event, message, net::{self, types::SyncingEvent, NetworkingService, SyncingCodecService}, - Config, }; use chainstate::{ ban_score::BanScore, chainstate_interface, BlockError, ChainstateError::ProcessBlockError, }; use common::{ - chain::block::{Block, BlockHeader}, + chain::{ + block::{Block, BlockHeader}, + config::ChainConfig, + }, primitives::{Id, Idable}, }; use futures::FutureExt; @@ -71,7 +73,7 @@ pub enum SyncState { /// peer it's connected to and actively keep track of the peer's state. pub struct SyncManager { /// Chain config - config: Arc, + config: Arc, /// Syncing state of the local node state: SyncState, @@ -105,7 +107,7 @@ where T::SyncingCodecHandle: SyncingCodecService, { pub fn new( - config: Arc, + config: Arc, handle: T::SyncingCodecHandle, chainstate_handle: subsystem::Handle>, rx_sync: mpsc::Receiver>, @@ -227,9 +229,7 @@ where locator .iter() .any(|header| &Some(header.get_id()) == headers[0].prev_block_id()) - // TODO: FIXME: - || &Some(todo!()) == headers[0].prev_block_id(), - //|| &Some(self.config.genesis_block_id()) == headers[0].prev_block_id(), + || &Some(self.config.genesis_block_id()) == headers[0].prev_block_id(), P2pError::ProtocolError(ProtocolError::InvalidMessage), ); } From 59f11444dba3ad2113c0af0e198704bbd721d417 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 12 Jul 2022 21:35:03 +0200 Subject: [PATCH 10/30] Configs refactoring --- chainstate/src/detail/tests/mod.rs | 7 +++--- .../src/detail/tests/processing_tests.rs | 10 ++++---- common/Cargo.toml | 2 +- common/src/chain/config/builder.rs | 3 +-- common/src/chain/config/mod.rs | 23 +++++++++++++------ node/src/config.rs | 18 ++++----------- node/src/main.rs | 13 ++++++++--- node/src/options.rs | 7 ++---- node/src/runner.rs | 23 ++++++++----------- p2p/src/net/libp2p/mod.rs | 2 +- p2p/src/net/libp2p/tests/mod.rs | 19 ++++++--------- p2p/src/pubsub.rs | 1 - p2p/src/swarm/mod.rs | 12 ++++------ 13 files changed, 67 insertions(+), 73 deletions(-) diff --git a/chainstate/src/detail/tests/mod.rs b/chainstate/src/detail/tests/mod.rs index 70e8b668f0..cd6e474910 100644 --- a/chainstate/src/detail/tests/mod.rs +++ b/chainstate/src/detail/tests/mod.rs @@ -83,7 +83,7 @@ fn create_utxo_data( } fn setup_chainstate() -> Chainstate { - chainstate_with_config(create_unit_test_config()) + chainstate_with_config(create_unit_test_config(), Config::new()) } fn chainstate_with_config(chain_config: ChainConfig, config: Config) -> Chainstate { @@ -136,8 +136,9 @@ fn create_new_outputs(tx: &Transaction) -> Vec<(TxInput, TxOutput)> { #[ignore] #[test] fn generate_blocks_for_functional_tests() { - let config = create_regtest(); - let chainstate = chainstate_with_config(config); + let chain_config = create_regtest(); + let config = Config::new(); + let chainstate = chainstate_with_config(chain_config, config); let mut btf = BlockTestFramework::with_chainstate(chainstate); let difficulty = Uint256([0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF]); diff --git a/chainstate/src/detail/tests/processing_tests.rs b/chainstate/src/detail/tests/processing_tests.rs index ab3645b67a..2ee9aea3df 100644 --- a/chainstate/src/detail/tests/processing_tests.rs +++ b/chainstate/src/detail/tests/processing_tests.rs @@ -508,8 +508,9 @@ fn consensus_type() { // This should succeed because config::Builder by default uses create_mainnet_genesis to // create the genesis_block, and this function creates a genesis block with // ConsenssuData::None, which agreess with the net_upgrades we defined above. - let config = ConfigBuilder::test_chain().net_upgrades(net_upgrades).build(); - let chainstate = chainstate_with_config(config); + let chain_config = ConfigBuilder::test_chain().net_upgrades(net_upgrades).build(); + let config = Config::new(); + let chainstate = chainstate_with_config(chain_config, config); let mut btf = BlockTestFramework::with_chainstate(chainstate); @@ -645,8 +646,9 @@ fn pow() { // This should succeed because TestChainConfig by default uses create_mainnet_genesis to // create the genesis_block, and this function creates a genesis block with // ConsenssuData::None, which agreess with the net_upgrades we defined above. - let config = ConfigBuilder::test_chain().net_upgrades(net_upgrades).build(); - let chainstate = chainstate_with_config(config); + let chain_config = ConfigBuilder::test_chain().net_upgrades(net_upgrades).build(); + let config = Config::new(); + let chainstate = chainstate_with_config(chain_config, config); let mut btf = BlockTestFramework::with_chainstate(chainstate); diff --git a/common/Cargo.toml b/common/Cargo.toml index 7cecc1eac3..169e2d6aa4 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -19,7 +19,7 @@ hex-literal = "0.3" lazy_static = "1.4" merkletree = "0.21" parity-scale-codec = "3.1" -serde = "1.0" +serde = { version = "1", features = ["derive"] } sscanf = "0.2" static_assertions = "1.1" strum = { version = "0.24", features = ["derive"] } diff --git a/common/src/chain/config/builder.rs b/common/src/chain/config/builder.rs index f9f5a86070..62dc9aafa1 100644 --- a/common/src/chain/config/builder.rs +++ b/common/src/chain/config/builder.rs @@ -21,7 +21,7 @@ use super::{create_mainnet_genesis, create_unit_test_genesis, ChainConfig, Chain use crate::chain::{ block::Block, ConsensusUpgrade, Destination, NetUpgrades, PoWChainConfig, UpgradeVersion, }; -use crate::primitives::{BlockHeight, Idable}; +use crate::primitives::BlockHeight; impl ChainType { fn default_genesis_init(&self) -> GenesisBlockInit { @@ -141,7 +141,6 @@ impl Builder { chain_type, coin_decimals, target_block_spacing, - genesis_block_id: genesis_block.get_id(), genesis_block, height_checkpoint_data: BTreeMap::new(), emission_schedule, diff --git a/common/src/chain/config/mod.rs b/common/src/chain/config/mod.rs index eca497eb74..d68953dd6f 100644 --- a/common/src/chain/config/mod.rs +++ b/common/src/chain/config/mod.rs @@ -22,7 +22,9 @@ pub use emission_schedule::{EmissionSchedule, EmissionScheduleTabular, Mlt}; use std::{collections::BTreeMap, time::Duration}; use hex::FromHex; +use serde::{Deserialize, Serialize}; +use crate::primitives::Idable; use crate::{ chain::{ block::{timestamp::BlockTimestamp, Block, ConsensusData}, @@ -31,7 +33,11 @@ use crate::{ upgrades::NetUpgrades, OutputPurpose, PoWChainConfig, UpgradeVersion, }, - primitives::{semver::SemVer, Amount, BlockHeight id::{Id, H256}}, + primitives::{ + id::{Id, H256}, + semver::SemVer, + Amount, BlockHeight, + }, }; pub const DEFAULT_TARGET_BLOCK_SPACING: Duration = Duration::from_secs(120); @@ -48,6 +54,8 @@ pub const VERSION: SemVer = SemVer::new(0, 1, 0); strum::Display, strum::EnumVariantNames, strum::EnumString, + Serialize, + Deserialize, )] #[strum(serialize_all = "kebab-case")] pub enum ChainType { @@ -67,12 +75,12 @@ impl ChainType { } } - pub const fn magic_bytes(&self) -> [u8; 4] { + pub const fn magic_bytes(&self) -> &'static [u8; 4] { match self { - ChainType::Mainnet => [0x1a, 0x64, 0xe5, 0xf1], - ChainType::Testnet => [0x2b, 0x7e, 0x19, 0xf6], - ChainType::Regtest => [0xaa, 0xbb, 0xcc, 0xdd], - ChainType::Signet => [0xf3, 0xf7, 0x7b, 0x45], + ChainType::Mainnet => &[0x1a, 0x64, 0xe5, 0xf1], + ChainType::Testnet => &[0x2b, 0x7e, 0x19, 0xf6], + ChainType::Regtest => &[0xaa, 0xbb, 0xcc, 0xdd], + ChainType::Signet => &[0xf3, 0xf7, 0x7b, 0x45], } } } @@ -80,6 +88,7 @@ impl ChainType { #[derive(Debug, Clone)] pub struct ChainConfig { chain_type: ChainType, + height_checkpoint_data: BTreeMap>, net_upgrades: NetUpgrades, genesis_block: Block, pub target_block_spacing: Duration, @@ -97,7 +106,7 @@ impl ChainConfig { } pub fn genesis_block_id(&self) -> Id { - self.genesis_block_id.clone() + self.genesis_block.get_id() } pub fn genesis_block(&self) -> &Block { diff --git a/node/src/config.rs b/node/src/config.rs index 4e9d550e2b..f6dc24b48b 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -20,16 +20,14 @@ use std::fs; use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; -use common::chain::config::{ChainConfig, ChainType}; +use common::chain::config::ChainType; use crate::RunOptions; /// The node configuration. #[derive(Serialize, Deserialize, Debug)] -struct Config { - /// Shared chain configuration. - #[serde(flatten)] - pub chain_config: ChainConfig, +pub struct Config { + pub chain_type: ChainType, // Subsystems configurations. pub chainstate: chainstate::Config, @@ -39,13 +37,12 @@ struct Config { impl Config { /// Creates a new `Config` instance for the specified chain type. - pub fn new(net: ChainType) -> Result { - let chain_config = ChainConfig::new(net); + pub fn new(chain_type: ChainType) -> Result { let chainstate = chainstate::Config::new(); let p2p = p2p::Config::new(); let rpc = rpc::Config::new()?; Ok(Self { - chain_config, + chain_type, chainstate, p2p, rpc, @@ -58,11 +55,6 @@ impl Config { let config = fs::read_to_string(&options.config_path).context("Failed to read config")?; let mut config: Config = toml::from_str(&config).context("Failed to deserialize config")?; - // Chain options. - if let Some(block_spacing) = options.target_block_spacing { - config.chain_config.target_block_spacing = block_spacing; - } - // Chainstate options. if let Some(max_size) = options.max_block_header_size { config.chainstate.max_block_header_size = max_size; diff --git a/node/src/main.rs b/node/src/main.rs index fb185e3837..23abc7d254 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -17,10 +17,10 @@ use std::fs; -use anyhow::{Context, Result}; +use anyhow::{anyhow, Context, Result}; +use common::chain::{config::ChainType, ChainConfig}; use logging::log; - use node::{Command, Config, Options}; async fn run() -> Result<()> { @@ -38,8 +38,15 @@ async fn run() -> Result<()> { } Command::Run(options) => { let config = Config::read(options).context("Failed to initialize config")?; + if config.chain_type != ChainType::Mainnet && config.chain_type != ChainType::Regtest { + return Err(anyhow!( + "Chain type '{:?}' not yet supported", + config.chain_type + )); + } + let chain_config = ChainConfig::new(config.chain_type); log::trace!("Starting with the following config\n: {config:#?}"); - node::run(config).await + node::run(chain_config, config).await } } } diff --git a/node/src/options.rs b/node/src/options.rs index 1a42210d01..c27dd5f77f 100644 --- a/node/src/options.rs +++ b/node/src/options.rs @@ -15,7 +15,7 @@ //! The node command line options. -use std::{ffi::OsString, net::SocketAddr, path::PathBuf, time::Duration}; +use std::{ffi::OsString, net::SocketAddr, path::PathBuf}; use clap::{Args, Parser, Subcommand}; use strum::VariantNames; @@ -53,9 +53,6 @@ pub struct RunOptions { /// The path to the configuration file. #[clap(short, long, default_value = "./mintlayer.toml")] pub config_path: PathBuf, - /// Target block spacing. - #[clap(long)] - pub target_block_spacing: Option, /// Maximum header size. #[clap(long)] pub max_block_header_size: Option, @@ -64,7 +61,7 @@ pub struct RunOptions { pub max_block_size_from_txs: Option, /// Maximum smart contracts size in a block. #[clap(long)] - pub max_block_size_from_smart_contracts: usize, + pub max_block_size_from_smart_contracts: Option, /// Address to bind P2P to. #[clap(long, value_name = "ADDR")] pub p2p_addr: Option, diff --git a/node/src/runner.rs b/node/src/runner.rs index a923f56a0b..f089ca1a41 100644 --- a/node/src/runner.rs +++ b/node/src/runner.rs @@ -15,24 +15,21 @@ //! Node initialisation routine. -use crate::{config::Config, options::Options}; +use crate::config::Config; use chainstate::rpc::ChainstateRpcServer; -use common::chain::config::ChainType; +use common::chain::config::ChainConfig; use p2p::rpc::P2pRpcServer; use std::sync::Arc; -#[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(config: Config) -> anyhow::Result { +pub async fn initialize( + chain_config: ChainConfig, + config: Config, +) -> anyhow::Result { // Initialize storage. let storage = chainstate_storage::Store::new_empty()?; - let chain_config = Arc::new(config.chain_config); + let chain_config = Arc::new(chain_config); // INITIALIZE SUBSYSTEMS @@ -66,7 +63,7 @@ pub async fn initialize(config: Config) -> anyhow::Result { // RPC subsystem let _rpc = manager.add_subsystem( "rpc", - rpc::Builder::new(Arc::clone(&chain_config), config.rpc) + rpc::Builder::new(config.rpc) .register(chainstate.clone().into_rpc()) .register(NodeRpc::new(manager.make_shutdown_trigger()).into_rpc()) .register(p2p.clone().into_rpc()) @@ -78,8 +75,8 @@ pub async fn initialize(config: Config) -> anyhow::Result { } /// Initialize and run the node -pub async fn run(config: Config) -> anyhow::Result<()> { - let manager = initialize(config).await?; +pub async fn run(chain_config: ChainConfig, config: Config) -> anyhow::Result<()> { + let manager = initialize(chain_config, config).await?; #[allow(clippy::unit_arg)] Ok(manager.main().await) diff --git a/p2p/src/net/libp2p/mod.rs b/p2p/src/net/libp2p/mod.rs index 6fecb4ffa3..0b5f51be0d 100644 --- a/p2p/src/net/libp2p/mod.rs +++ b/p2p/src/net/libp2p/mod.rs @@ -230,7 +230,7 @@ impl NetworkingService for Libp2pService { async fn start( bind_addr: Self::Address, strategies: &[Self::DiscoveryStrategy], - chain_config: Arc, + chain_config: Arc, timeout: std::time::Duration, ) -> crate::Result<( Self::ConnectivityHandle, diff --git a/p2p/src/net/libp2p/tests/mod.rs b/p2p/src/net/libp2p/tests/mod.rs index 0ef7dfc2eb..9ce3afca10 100644 --- a/p2p/src/net/libp2p/tests/mod.rs +++ b/p2p/src/net/libp2p/tests/mod.rs @@ -15,13 +15,10 @@ // // Author(s): A. Altonen -use crate::{ - net::{ - self, - libp2p::sync::*, - libp2p::{backend::Backend, behaviour, types}, - }, - Config, +use crate::net::{ + self, + libp2p::sync::*, + libp2p::{backend::Backend, behaviour, types}, }; use common::chain::{config::VERSION, ChainConfig}; use futures::prelude::*; @@ -62,7 +59,6 @@ mod ping; #[allow(dead_code)] pub async fn make_libp2p( chain_config: ChainConfig, - config: Config, addr: Multiaddr, topics: &[net::types::PubSubTopic], relay_mdns: bool, @@ -96,7 +92,7 @@ pub async fn make_libp2p( .build() .expect("configuration to be valid"); - let magic = config.magic_bytes; + let magic = chain_config.magic_bytes(); let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", VERSION.major, @@ -162,7 +158,6 @@ pub async fn make_libp2p( #[allow(dead_code)] pub async fn make_libp2p_with_ping( chain_config: ChainConfig, - config: Config, addr: Multiaddr, topics: &[net::types::PubSubTopic], ping: libp2p_ping::Behaviour, @@ -197,7 +192,7 @@ pub async fn make_libp2p_with_ping( .build() .expect("configuration to be valid"); - let magic = config.magic_bytes; + let magic = chain_config.magic_bytes(); let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", VERSION.major, @@ -305,7 +300,7 @@ pub fn make_transport_and_keys() -> (Boxed<(PeerId, StreamMuxerBox)>, PeerId, id #[allow(dead_code)] pub fn make_identify(config: ChainConfig, id_keys: identity::Keypair) -> Identify { - let magic = config.magic_bytes; + let magic = config.magic_bytes(); let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", VERSION.major, diff --git a/p2p/src/pubsub.rs b/p2p/src/pubsub.rs index 2b45e5fb2f..55858d2d56 100644 --- a/p2p/src/pubsub.rs +++ b/p2p/src/pubsub.rs @@ -24,7 +24,6 @@ use crate::{ types::{PubSubEvent, PubSubTopic, ValidationResult}, NetworkingService, PubSubService, }, - Config, }; use chainstate::{ ban_score::BanScore, diff --git a/p2p/src/swarm/mod.rs b/p2p/src/swarm/mod.rs index fd98a226cb..7af699ba37 100644 --- a/p2p/src/swarm/mod.rs +++ b/p2p/src/swarm/mod.rs @@ -26,7 +26,6 @@ use crate::{ error::{P2pError, PeerError, ProtocolError}, event, net::{self, ConnectivityService, NetworkingService}, - Config, }; use common::{ chain::{config::VERSION, ChainConfig}, @@ -160,7 +159,7 @@ where /// /// Make sure that local and remote peer have the same software version fn validate_version(&self, version: &semver::SemVer) -> bool { - version == VERSION + version == &VERSION } /// Handle connection established event @@ -172,18 +171,15 @@ where log::debug!("{}", info); ensure!( - info.magic_bytes == self.config.magic_bytes, + &info.magic_bytes == self.config.magic_bytes(), P2pError::ProtocolError(ProtocolError::DifferentNetwork( - self.config.magic_bytes, + self.config.magic_bytes().to_owned(), info.magic_bytes, )) ); ensure!( self.validate_version(&info.version), - P2pError::ProtocolError(ProtocolError::InvalidVersion( - self.config.version, - info.version - )) + P2pError::ProtocolError(ProtocolError::InvalidVersion(VERSION, info.version)) ); ensure!( self.validate_supported_protocols(&info.protocols), From 1dd1d681a22434423bbbd8c97c1fdaedf3b04698 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 12 Jul 2022 21:53:23 +0200 Subject: [PATCH 11/30] Use debug formatting for error --- node/src/main.rs | 3 ++- node/tests/cli.rs | 10 ++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/node/src/main.rs b/node/src/main.rs index 23abc7d254..d339762e6b 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -31,6 +31,7 @@ async fn run() -> Result<()> { match opts.command { Command::CreateConfig { path, net } => { let config = Config::new(net)?; + println!("{config:#?}"); let config = toml::to_string(&config).context("Failed to serialize config")?; log::trace!("Saving config to {path:?}\n: {config:#?}"); fs::write(path, config).context("Failed to write config")?; @@ -54,7 +55,7 @@ async fn run() -> Result<()> { #[tokio::main] async fn main() { run().await.unwrap_or_else(|err| { - eprintln!("ERROR: {}", err); + eprintln!("ERROR: {:?}", err); std::process::exit(1) }) } diff --git a/node/tests/cli.rs b/node/tests/cli.rs index fdfcdd95c2..4b89c34a08 100644 --- a/node/tests/cli.rs +++ b/node/tests/cli.rs @@ -28,18 +28,12 @@ fn path_is_correct() { #[test] fn no_args() { - Command::new(BIN_NAME).assert().success(); - // TODO: Check predicates?.. - todo!(); - todo!(); + Command::new(BIN_NAME).assert().failure(); } #[test] fn create_config() { - Command::new(BIN_NAME).arg("--create-config").assert().success(); - // TODO: FIXME: Check the config after creation. - todo!(); - todo!(); + Command::new(BIN_NAME).arg("create-config").assert().success(); } // TODO: Create config with args? From 06ef0e4c707471cf49422049aa44aafaf1dd4f0d Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 12 Jul 2022 22:37:24 +0200 Subject: [PATCH 12/30] Change fields order --- chainstate/src/config.rs | 4 ++-- node/mintlayer.toml | 17 +++++++++++++++++ node/src/main.rs | 1 - 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 node/mintlayer.toml diff --git a/chainstate/src/config.rs b/chainstate/src/config.rs index 3acdd33e3e..959a07efef 100644 --- a/chainstate/src/config.rs +++ b/chainstate/src/config.rs @@ -25,8 +25,8 @@ pub struct Config { pub max_block_header_size: usize, pub max_block_size_from_txs: usize, pub max_block_size_from_smart_contracts: usize, - pub max_future_block_time_offset: Duration, pub blockreward_maturity: BlockDistance, + pub max_future_block_time_offset: Duration, } impl Config { @@ -36,8 +36,8 @@ impl Config { max_block_header_size: 1024, max_block_size_from_txs: 524_288, max_block_size_from_smart_contracts: 524_288, - max_future_block_time_offset: Duration::from_secs(60 * 60), blockreward_maturity: BlockDistance::new(500), + max_future_block_time_offset: Duration::from_secs(60 * 60), } } } diff --git a/node/mintlayer.toml b/node/mintlayer.toml new file mode 100644 index 0000000000..218e87cc6c --- /dev/null +++ b/node/mintlayer.toml @@ -0,0 +1,17 @@ +chain_type = "Mainnet" + +[chainstate] +max_block_header_size = 1024 +max_block_size_from_txs = 524288 +max_block_size_from_smart_contracts = 524288 +blockreward_maturity = 500 + +[chainstate.max_future_block_time_offset] +secs = 3600 +nanos = 0 + +[p2p] +address = "/ip6/::1/tcp/3031" + +[rpc] +address = "127.0.0.1:3030" diff --git a/node/src/main.rs b/node/src/main.rs index d339762e6b..c82d5890a0 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -31,7 +31,6 @@ async fn run() -> Result<()> { match opts.command { Command::CreateConfig { path, net } => { let config = Config::new(net)?; - println!("{config:#?}"); let config = toml::to_string(&config).context("Failed to serialize config")?; log::trace!("Saving config to {path:?}\n: {config:#?}"); fs::write(path, config).context("Failed to write config")?; From be3b61a24b0ae17e9db085d50925aceb734f296a Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 12 Jul 2022 22:52:58 +0200 Subject: [PATCH 13/30] Update the create_config test --- node/tests/cli.rs | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/node/tests/cli.rs b/node/tests/cli.rs index 4b89c34a08..036fdce30a 100644 --- a/node/tests/cli.rs +++ b/node/tests/cli.rs @@ -17,6 +17,8 @@ use std::path::Path; use assert_cmd::Command; +use node::{Config, RunOptions}; + const BIN_NAME: &str = env!("CARGO_BIN_EXE_node"); // This test is only needed because the node name ix hardcoded here, so if the name is changed we @@ -33,7 +35,36 @@ fn no_args() { #[test] fn create_config() { - Command::new(BIN_NAME).arg("create-config").assert().success(); -} + let config_path = concat!(env!("CARGO_TARGET_TMPDIR"), "/test_mintlayer.toml"); + let max_block_header_size = 100; + let max_block_size_from_txs = 200; + let max_block_size_from_smart_contracts = 300; -// TODO: Create config with args? + Command::new(BIN_NAME) + .arg("create-config") + .arg("--path") + .arg(config_path) + .assert() + .success(); + let run_options = RunOptions { + config_path: config_path.into(), + max_block_header_size: Some(max_block_header_size), + max_block_size_from_txs: Some(max_block_size_from_txs), + max_block_size_from_smart_contracts: Some(max_block_size_from_smart_contracts), + p2p_addr: None, + rpc_addr: None, + }; + let config = Config::read(run_options).unwrap(); + assert_eq!( + config.chainstate.max_block_header_size, + max_block_header_size + ); + assert_eq!( + config.chainstate.max_block_size_from_txs, + max_block_size_from_txs + ); + assert_eq!( + config.chainstate.max_block_size_from_smart_contracts, + max_block_size_from_smart_contracts + ); +} From e8de616283c060dd9a85ebbd6b4dbc7caaefa9b6 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 13 Jul 2022 18:46:45 +0200 Subject: [PATCH 14/30] Rename configs --- chainstate/src/config.rs | 2 +- chainstate/src/lib.rs | 8 +++++--- node/src/config.rs | 9 ++++++--- p2p/src/config.rs | 4 ++-- p2p/src/lib.rs | 4 +--- rpc/src/config.rs | 4 ++-- rpc/src/lib.rs | 6 +++--- 7 files changed, 20 insertions(+), 17 deletions(-) diff --git a/chainstate/src/config.rs b/chainstate/src/config.rs index 959a07efef..fd118fe7fb 100644 --- a/chainstate/src/config.rs +++ b/chainstate/src/config.rs @@ -21,7 +21,7 @@ use common::primitives::BlockDistance; /// The chainstate subsystem configuration. #[derive(Serialize, Deserialize, Debug)] -pub struct Config { +pub struct ChainstateConfig { pub max_block_header_size: usize, pub max_block_size_from_txs: usize, pub max_block_size_from_smart_contracts: usize, diff --git a/chainstate/src/lib.rs b/chainstate/src/lib.rs index 88aff538b0..0ed60802ec 100644 --- a/chainstate/src/lib.rs +++ b/chainstate/src/lib.rs @@ -31,9 +31,11 @@ use common::{ }; use detail::{time_getter::TimeGetter, PropertyQueryError}; -pub use chainstate_interface_impl::ChainstateInterfaceImpl; -pub use config::Config; -pub use detail::{ban_score, BlockError, BlockSource, Chainstate}; +pub use crate::{ + chainstate_interface_impl::ChainstateInterfaceImpl, + config::ChainstateConfig, + detail::{ban_score, BlockError, BlockSource, Chainstate}, +}; #[derive(Debug, Clone)] pub enum ChainstateEvent { diff --git a/node/src/config.rs b/node/src/config.rs index f6dc24b48b..5894d8cd1e 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -20,7 +20,10 @@ use std::fs; use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; +use chainstate::ChainstateConfig; use common::chain::config::ChainType; +use p2p::config::P2pConfig; +use rpc::RpcConfig; use crate::RunOptions; @@ -30,9 +33,9 @@ pub struct Config { pub chain_type: ChainType, // Subsystems configurations. - pub chainstate: chainstate::Config, - pub p2p: p2p::Config, - pub rpc: rpc::Config, + pub chainstate: ChainstateConfig, + pub p2p: P2pConfig, + pub rpc: RpcConfig, } impl Config { diff --git a/p2p/src/config.rs b/p2p/src/config.rs index 0d11ca2e4d..c07fcde8ad 100644 --- a/p2p/src/config.rs +++ b/p2p/src/config.rs @@ -17,12 +17,12 @@ use serde::{Deserialize, Serialize}; /// The p2p subsystem configuration. #[derive(Serialize, Deserialize, Debug)] -pub struct Config { +pub struct P2pConfig { /// Address to bind P2P to. pub address: String, } -impl Config { +impl P2pConfig { /// Creates a new p2p configuration instance. pub fn new() -> Self { Self { diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index 5c5463abee..c4a96f9003 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -24,9 +24,7 @@ use logging::log; use std::{fmt::Debug, str::FromStr, sync::Arc, time::Duration}; use tokio::sync::{mpsc, oneshot}; -mod config; -pub use config::Config; - +pub mod config; pub mod error; pub mod event; pub mod message; diff --git a/rpc/src/config.rs b/rpc/src/config.rs index ebcf5dd850..5aa3019c55 100644 --- a/rpc/src/config.rs +++ b/rpc/src/config.rs @@ -20,12 +20,12 @@ use serde::{Deserialize, Serialize}; /// The rpc subsystem configuration. #[derive(Serialize, Deserialize, Debug)] -pub struct Config { +pub struct RpcConfig { /// Address to bind RPC to. pub address: SocketAddr, } -impl Config { +impl RpcConfig { /// Creates a new rpc configuration instance. pub fn new() -> Result { Ok(Self { diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 2d972c7ded..2e26b9f4e9 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -17,14 +17,14 @@ use std::net::SocketAddr; use jsonrpsee::http_server::{HttpServerBuilder, HttpServerHandle}; +use logging::log; + +pub use config::RpcConfig; pub use jsonrpsee::core::server::rpc_module::Methods; pub use jsonrpsee::core::Error; pub use jsonrpsee::proc_macros::rpc; -use logging::log; - mod config; -pub use config::Config; /// The Result type with RPC-specific error. pub type Result = core::result::Result; From d78cefde1f85c43f328bc01678eb6bb07799fd8f Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 13 Jul 2022 19:42:18 +0200 Subject: [PATCH 15/30] Revert chain config changes --- chainstate/src/config.rs | 15 +-- .../src/detail/block_index_history_iter.rs | 6 +- chainstate/src/detail/chainstateref.rs | 30 ++--- chainstate/src/detail/median_time.rs | 19 ++- chainstate/src/detail/mod.rs | 16 +-- chainstate/src/detail/tests/events_tests.rs | 10 +- chainstate/src/detail/tests/mod.rs | 13 +- .../src/detail/tests/processing_tests.rs | 73 +++++++---- chainstate/src/detail/tests/reorgs_tests.rs | 15 ++- chainstate/src/lib.rs | 16 +-- chainstate/src/rpc.rs | 15 ++- common/Cargo.toml | 2 +- common/src/chain/config/builder.rs | 57 ++++++++- common/src/chain/config/mod.rs | 116 +++++++++++++----- common/src/primitives/height.rs | 12 +- common/src/primitives/semver.rs | 6 +- node/mintlayer.toml | 17 --- p2p/src/lib.rs | 10 +- p2p/src/net/libp2p/behaviour.rs | 9 +- p2p/src/net/libp2p/tests/mod.rs | 30 ++--- p2p/src/swarm/mod.rs | 16 +-- p2p/src/sync/tests/mod.rs | 14 ++- p2p/test-utils/src/lib.rs | 7 +- rpc/src/lib.rs | 8 +- 24 files changed, 331 insertions(+), 201 deletions(-) delete mode 100644 node/mintlayer.toml diff --git a/chainstate/src/config.rs b/chainstate/src/config.rs index fd118fe7fb..89f66ddccb 100644 --- a/chainstate/src/config.rs +++ b/chainstate/src/config.rs @@ -22,22 +22,13 @@ use common::primitives::BlockDistance; /// The chainstate subsystem configuration. #[derive(Serialize, Deserialize, Debug)] pub struct ChainstateConfig { - pub max_block_header_size: usize, - pub max_block_size_from_txs: usize, - pub max_block_size_from_smart_contracts: usize, - pub blockreward_maturity: BlockDistance, - pub max_future_block_time_offset: Duration, + // TODO: FIXME! } impl Config { /// Creates a new chainstate configuration isntance. pub fn new() -> Self { - Self { - max_block_header_size: 1024, - max_block_size_from_txs: 524_288, - max_block_size_from_smart_contracts: 524_288, - blockreward_maturity: BlockDistance::new(500), - max_future_block_time_offset: Duration::from_secs(60 * 60), - } + todo!(); + Self {} } } diff --git a/chainstate/src/detail/block_index_history_iter.rs b/chainstate/src/detail/block_index_history_iter.rs index 7076465e31..405a3058aa 100644 --- a/chainstate/src/detail/block_index_history_iter.rs +++ b/chainstate/src/detail/block_index_history_iter.rs @@ -75,7 +75,7 @@ mod tests { primitives::{time, Idable, H256}, }; - use crate::{BlockSource, Chainstate, Config}; + use crate::{BlockSource, Chainstate, ChainstateConfig}; use super::*; @@ -83,11 +83,11 @@ mod tests { fn history_iteration() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); - let config = Config::new(); + let chainstte_config = Config::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = Chainstate::new( chain_config.clone(), - config, + chainstte_config, storage, None, Default::default(), diff --git a/chainstate/src/detail/chainstateref.rs b/chainstate/src/detail/chainstateref.rs index 8ad9617ea3..ecdbcc6711 100644 --- a/chainstate/src/detail/chainstateref.rs +++ b/chainstate/src/detail/chainstateref.rs @@ -32,7 +32,7 @@ use common::{ use logging::log; use utils::ensure; -use crate::{BlockError, BlockSource, Config}; +use crate::{BlockError, BlockSource, ChainstateConfig}; use super::{ consensus_validator::{self, BlockIndexHandle}, @@ -44,7 +44,7 @@ use super::{ pub(crate) struct ChainstateRef<'a, S, O> { chain_config: &'a ChainConfig, - config: &'a Config, + chainstate_config: &'a ChainstateConfig, db_tx: S, orphan_blocks: O, time_getter: &'a TimeGetterFn, @@ -93,14 +93,14 @@ impl<'a, S: TransactionRw, O> ChainstateRef<' impl<'a, S: BlockchainStorageRead, O: OrphanBlocks> ChainstateRef<'a, S, O> { pub fn new_rw( chain_config: &'a ChainConfig, - config: &'a Config, + chainstate_config: &'a ChainstateConfig, db_tx: S, orphan_blocks: O, time_getter: &'a TimeGetterFn, ) -> ChainstateRef<'a, S, O> { ChainstateRef { chain_config, - config, + chainstate_config, db_tx, orphan_blocks, time_getter, @@ -109,14 +109,14 @@ impl<'a, S: BlockchainStorageRead, O: OrphanBlocks> ChainstateRef<'a, S, O> { pub fn new_ro( chain_config: &'a ChainConfig, - config: &'a Config, + chainstete_config: &'a ChainstateConfig, db_tx: S, orphan_blocks: O, time_getter: &'a TimeGetterFn, ) -> ChainstateRef<'a, S, O> { ChainstateRef { chain_config, - config, + chainstate_config, db_tx, orphan_blocks, time_getter, @@ -371,11 +371,11 @@ impl<'a, S: BlockchainStorageRead, O: OrphanBlocks> ChainstateRef<'a, S, O> { CheckBlockError::BlockTimeOrderInvalid, ); - let max_future_offset = self.config.max_future_block_time_offset; + let max_future_offset = self.chain_config.max_future_block_time_offset(); let current_time = self.current_time(); let block_timestamp = block.timestamp(); ensure!( - block_timestamp.as_duration_since_epoch() <= current_time + max_future_offset, + block_timestamp.as_duration_since_epoch() <= current_time + *max_future_offset, CheckBlockError::BlockFromTheFuture, ); } @@ -400,27 +400,27 @@ impl<'a, S: BlockchainStorageRead, O: OrphanBlocks> ChainstateRef<'a, S, O> { let block_size = block.block_size(); ensure!( - block_size.size_from_header() <= self.config.max_block_header_size, + block_size.size_from_header() <= self.chain_config.max_block_header_size(), BlockSizeError::Header( block_size.size_from_header(), - self.config.max_block_header_size, + self.chain_config.max_block_header_size() ) ); ensure!( - block_size.size_from_txs() <= self.config.max_block_size_from_txs, + block_size.size_from_txs() <= self.chain_config.max_block_size_from_txs(), BlockSizeError::SizeOfTxs( block_size.size_from_txs(), - self.config.max_block_size_from_txs + self.chain_config.max_block_size_from_txs() ) ); ensure!( block_size.size_from_smart_contracts() - <= self.config.max_block_size_from_smart_contracts, + <= self.chain_config.max_block_size_from_smart_contracts(), BlockSizeError::SizeOfSmartContracts( block_size.size_from_smart_contracts(), - self.config.max_block_size_from_smart_contracts + self.chain_config.max_block_size_from_smart_contracts() ) ); @@ -658,7 +658,7 @@ impl<'a, S: BlockchainStorageWrite, O: OrphanBlocksMut> ChainstateRef<'a, S, O> self.connect_transactions( &block, &new_tip_block_index.block_height(), - &self.config.blockreward_maturity, + self.chain_config.blockreward_maturity(), )?; } diff --git a/chainstate/src/detail/median_time.rs b/chainstate/src/detail/median_time.rs index 8eb25e4917..68248446eb 100644 --- a/chainstate/src/detail/median_time.rs +++ b/chainstate/src/detail/median_time.rs @@ -42,7 +42,7 @@ pub fn calculate_median_time_past( #[cfg(test)] mod test { - use crate::{detail::time_getter::TimeGetter, BlockSource, Chainstate, Config}; + use crate::{detail::time_getter::TimeGetter, BlockSource, Chainstate, ChainstateConfig}; use super::*; use chainstate_storage::Store; @@ -86,10 +86,16 @@ mod test { fn blocks_median_time() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); - let config = Config::new(); + let chainstate_config = ChainstateConfig::new(); let storage = Store::new_empty().unwrap(); - let mut chainstate = - Chainstate::new(chain_config, config, storage, None, Default::default()).unwrap(); + let mut chainstate = Chainstate::new( + chain_config, + chainstate_config, + storage, + None, + Default::default(), + ) + .unwrap(); let block_count = 500; @@ -152,9 +158,10 @@ mod test { })); let storage = Store::new_empty().unwrap(); - let config = Config::new(); + let chainstate_config = ChainstateConfig::new(); let mut chainstate = - Chainstate::new(chain_config, config, storage, None, time_getter).unwrap(); + Chainstate::new(chain_config, chainstate_config, storage, None, time_getter) + .unwrap(); // we use unordered block times, and ensure that the median will be in the right spot let block1_time = current_time.load(Ordering::SeqCst) as u32 + 1; diff --git a/chainstate/src/detail/mod.rs b/chainstate/src/detail/mod.rs index 2f73e233cc..0a4b68e1c1 100644 --- a/chainstate/src/detail/mod.rs +++ b/chainstate/src/detail/mod.rs @@ -15,7 +15,7 @@ // // Author(s): S. Afach, A. Sinitsyn -use crate::{detail::orphan_blocks::OrphanBlocksPool, ChainstateEvent, Config}; +use crate::{detail::orphan_blocks::OrphanBlocksPool, ChainstateConfig, ChainstateEvent}; use chainstate_storage::Transactional; use chainstate_types::block_index::BlockIndex; use common::chain::block::{Block, BlockHeader}; @@ -57,7 +57,7 @@ use time_getter::TimeGetter; #[must_use] pub struct Chainstate { chain_config: Arc, - config: Config, + chainstate_config: ChainstateConfig, chainstate_storage: chainstate_storage::Store, orphan_blocks: OrphanBlocksPool, custom_orphan_error_hook: Option>, @@ -81,7 +81,7 @@ impl Chainstate { let db_tx = self.chainstate_storage.transaction_rw(); chainstateref::ChainstateRef::new_rw( &self.chain_config, - &self.config, + &self.chainstate_config, db_tx, self.orphan_blocks.as_rw_ref(), self.time_getter.getter(), @@ -93,7 +93,7 @@ impl Chainstate { let db_tx = self.chainstate_storage.transaction_ro(); chainstateref::ChainstateRef::new_ro( &self.chain_config, - &self.config, + &self.chainstate_config, db_tx, self.orphan_blocks.as_ro_ref(), self.time_getter.getter(), @@ -106,7 +106,7 @@ impl Chainstate { pub fn new( chain_config: Arc, - config: Config, + chainstate_config: ChainstateConfig, chainstate_storage: chainstate_storage::Store, custom_orphan_error_hook: Option>, time_getter: TimeGetter, @@ -115,7 +115,7 @@ impl Chainstate { let mut cons = Self::new_no_genesis( chain_config, - config, + chainstate_config, chainstate_storage, custom_orphan_error_hook, time_getter, @@ -142,14 +142,14 @@ impl Chainstate { fn new_no_genesis( chain_config: Arc, - config: Config, + chainstate_config: ChainstateConfig, chainstate_storage: chainstate_storage::Store, custom_orphan_error_hook: Option>, time_getter: TimeGetter, ) -> Result { let cons = Self { chain_config, - config, + chainstate_config, chainstate_storage, orphan_blocks: OrphanBlocksPool::new_default(), custom_orphan_error_hook, diff --git a/chainstate/src/detail/tests/events_tests.rs b/chainstate/src/detail/tests/events_tests.rs index e56ddb892e..515d47ba8e 100644 --- a/chainstate/src/detail/tests/events_tests.rs +++ b/chainstate/src/detail/tests/events_tests.rs @@ -121,12 +121,12 @@ fn several_subscribers_several_events() { fn orphan_block() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); - let config = Config::new(); + let chainstate_config = ChainstateConfig::new(); let storage = Store::new_empty().unwrap(); let (orphan_error_hook, errors) = orphan_error_hook(); let mut chainstate = Chainstate::new( chain_config, - config, + chainstate_config, storage, Some(orphan_error_hook), Default::default(), @@ -151,12 +151,12 @@ fn orphan_block() { fn custom_orphan_error_hook() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); - let config = Config::new(); + let chainstate_config = ChainstateConfig::new(); let storage = Store::new_empty().unwrap(); let (orphan_error_hook, errors) = orphan_error_hook(); let mut chainstate = Chainstate::new( chain_config, - config, + chainstate_config, storage, Some(orphan_error_hook), Default::default(), @@ -169,7 +169,7 @@ fn custom_orphan_error_hook() { let first_block = produce_test_block(chainstate.chain_config.genesis_block(), false); // Produce a block with a bad timestamp. let timestamp = chainstate.chain_config.genesis_block().timestamp().as_int_seconds() - + chainstate.config.max_future_block_time_offset.as_secs() as u32; + + chainstate.chain_config.max_future_block_time_offset().as_secs() as u32; let second_block = Block::new( vec![], Some(first_block.get_id()), diff --git a/chainstate/src/detail/tests/mod.rs b/chainstate/src/detail/tests/mod.rs index cd6e474910..ee748d3a05 100644 --- a/chainstate/src/detail/tests/mod.rs +++ b/chainstate/src/detail/tests/mod.rs @@ -83,13 +83,16 @@ fn create_utxo_data( } fn setup_chainstate() -> Chainstate { - chainstate_with_config(create_unit_test_config(), Config::new()) + chainstate_with_config(create_unit_test_config(), ChainstateConfig::new()) } -fn chainstate_with_config(chain_config: ChainConfig, config: Config) -> Chainstate { +fn chainstate_with_config( + chain_config: ChainConfig, + chainstate_config: ChainstateConfig, +) -> Chainstate { Chainstate::new( Arc::new(chain_config), - config, + chainstate_config, Store::new_empty().unwrap(), None, Default::default(), @@ -137,8 +140,8 @@ fn create_new_outputs(tx: &Transaction) -> Vec<(TxInput, TxOutput)> { #[test] fn generate_blocks_for_functional_tests() { let chain_config = create_regtest(); - let config = Config::new(); - let chainstate = chainstate_with_config(chain_config, config); + let chainstate_config = ChainstateConfig::new(); + let chainstate = chainstate_with_config(chain_config, chainstate_config); let mut btf = BlockTestFramework::with_chainstate(chainstate); let difficulty = Uint256([0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF]); diff --git a/chainstate/src/detail/tests/processing_tests.rs b/chainstate/src/detail/tests/processing_tests.rs index 2ee9aea3df..b25bd4582e 100644 --- a/chainstate/src/detail/tests/processing_tests.rs +++ b/chainstate/src/detail/tests/processing_tests.rs @@ -23,7 +23,7 @@ use crate::{ pow::error::ConsensusPoWError, tests::{test_framework::BlockTestFramework, *}, }, - make_chainstate, Config, + make_chainstate, ChainstateConfig, }; use chainstate_storage::{BlockchainStorageRead, Store}; use common::{ @@ -43,11 +43,11 @@ use crypto::random::{self, Rng}; fn genesis_peer_block() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); - let config = Config::new(); + let chainstate_config = ChainstateConfig::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = Chainstate::new_no_genesis( chain_config.clone(), - config, + chainstate_config, storage, None, Default::default(), @@ -66,11 +66,16 @@ fn genesis_peer_block() { fn process_genesis_block() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); - let config = Config::new(); + let chainstate_config = ChainstateConfig::new(); let storage = Store::new_empty().unwrap(); - let mut chainstate = - Chainstate::new_no_genesis(chain_config, config, storage, None, Default::default()) - .unwrap(); + let mut chainstate = Chainstate::new_no_genesis( + chain_config, + chainstate_config, + storage, + None, + Default::default(), + ) + .unwrap(); let block_index = chainstate .process_block( @@ -147,11 +152,16 @@ fn test_orphans_chains() { fn empty_chainstate() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); - let config = Config::new(); + let chainstate_config = ChainstateConfig::new(); let storage = Store::new_empty().unwrap(); - let chainstate = - Chainstate::new_no_genesis(chain_config, config, storage, None, Default::default()) - .unwrap(); + let chainstate = Chainstate::new_no_genesis( + chain_config, + chainstate_config, + storage, + None, + Default::default(), + ) + .unwrap(); assert_eq!(chainstate.get_best_block_id().unwrap(), None); assert_eq!( chainstate @@ -233,11 +243,16 @@ fn spend_inputs_simple() { fn straight_chain() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); - let config = Config::new(); + let chainstate_config = ChainstateConfig::new(); let storage = Store::new_empty().unwrap(); - let mut chainstate = - Chainstate::new_no_genesis(chain_config, config, storage, None, Default::default()) - .unwrap(); + let mut chainstate = Chainstate::new_no_genesis( + chain_config, + chainstate_config, + storage, + None, + Default::default(), + ) + .unwrap(); let genesis_index = chainstate .process_block( @@ -509,8 +524,8 @@ fn consensus_type() { // create the genesis_block, and this function creates a genesis block with // ConsenssuData::None, which agreess with the net_upgrades we defined above. let chain_config = ConfigBuilder::test_chain().net_upgrades(net_upgrades).build(); - let config = Config::new(); - let chainstate = chainstate_with_config(chain_config, config); + let chainstate_config = ChainstateConfig::new(); + let chainstate = chainstate_with_config(chain_config, chainstate_config); let mut btf = BlockTestFramework::with_chainstate(chainstate); @@ -647,8 +662,8 @@ fn pow() { // create the genesis_block, and this function creates a genesis block with // ConsenssuData::None, which agreess with the net_upgrades we defined above. let chain_config = ConfigBuilder::test_chain().net_upgrades(net_upgrades).build(); - let config = Config::new(); - let chainstate = chainstate_with_config(chain_config, config); + let chainstate_config = ChainstateConfig::new(); + let chainstate = chainstate_with_config(chain_config, chainstate_config); let mut btf = BlockTestFramework::with_chainstate(chainstate); @@ -705,7 +720,7 @@ fn blocks_from_the_future() { let storage = Store::new_empty().unwrap(); let mut chainstate = - Chainstate::new(config, Config::new(), storage, None, time_getter).unwrap(); + Chainstate::new(config, ChainstateConfig::new(), storage, None, time_getter).unwrap(); { // ensure no blocks are in chain, so that median time can be the genesis time @@ -728,7 +743,8 @@ fn blocks_from_the_future() { { // submit a block on the threshold of being rejected for being from the future - let max_future_offset = chainstate.config.max_future_block_time_offset.as_secs() as u32; + let max_future_offset = + chainstate.chain_config.max_future_block_time_offset().as_secs() as u32; let good_block = Block::new( vec![], @@ -745,7 +761,8 @@ fn blocks_from_the_future() { { // submit a block a second after the allowed threshold in the future - let max_future_offset = chainstate.config.max_future_block_time_offset.as_secs() as u32; + let max_future_offset = + chainstate.chain_config.max_future_block_time_offset().as_secs() as u32; let bad_block_in_future = Block::new( vec![], @@ -783,9 +800,17 @@ fn blocks_from_the_future() { #[test] fn test_mainnet_initialization() { - let config = Arc::new(common::chain::config::create_mainnet()); + let chain_config = Arc::new(common::chain::config::create_mainnet()); + let chainstate_config = ChainstateConfig::new(); let storage = Store::new_empty().unwrap(); - make_chainstate(config, Config::new(), storage, None, Default::default()).unwrap(); + make_chainstate( + chain_config, + chainstate_config, + storage, + None, + Default::default(), + ) + .unwrap(); } fn make_invalid_pow_block( diff --git a/chainstate/src/detail/tests/reorgs_tests.rs b/chainstate/src/detail/tests/reorgs_tests.rs index 5aca3cdc67..d46854a0d8 100644 --- a/chainstate/src/detail/tests/reorgs_tests.rs +++ b/chainstate/src/detail/tests/reorgs_tests.rs @@ -22,7 +22,7 @@ use crate::{ test_framework::{BlockTestFramework, TestBlockParams, TestSpentStatus}, *, }, - Config, + ChainstateConfig, }; use chainstate_storage::{BlockchainStorageRead, Store}; use common::chain::config::create_unit_test_config; @@ -32,11 +32,16 @@ use common::chain::config::create_unit_test_config; fn reorg_simple() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); - let config = Config::new(); + let chainstate_config = ChainstateConfig::new(); let storage = Store::new_empty().unwrap(); - let mut chainstate = - Chainstate::new_no_genesis(chain_config, config, storage, None, Default::default()) - .unwrap(); + let mut chainstate = Chainstate::new_no_genesis( + chain_config, + chainstate_config, + storage, + None, + Default::default(), + ) + .unwrap(); // Process the genesis block. chainstate diff --git a/chainstate/src/lib.rs b/chainstate/src/lib.rs index 0ed60802ec..b599fa750c 100644 --- a/chainstate/src/lib.rs +++ b/chainstate/src/lib.rs @@ -22,6 +22,12 @@ pub mod chainstate_interface; pub mod chainstate_interface_impl; pub mod rpc; +pub use crate::{ + chainstate_interface_impl::ChainstateInterfaceImpl, + config::ChainstateConfig, + detail::{ban_score, BlockError, BlockSource, Chainstate}, +}; + use std::sync::Arc; use chainstate_interface::ChainstateInterface; @@ -31,12 +37,6 @@ use common::{ }; use detail::{time_getter::TimeGetter, PropertyQueryError}; -pub use crate::{ - chainstate_interface_impl::ChainstateInterfaceImpl, - config::ChainstateConfig, - detail::{ban_score, BlockError, BlockSource, Chainstate}, -}; - #[derive(Debug, Clone)] pub enum ChainstateEvent { NewTip(Id, BlockHeight), @@ -58,14 +58,14 @@ type ChainstateHandle = subsystem::Handle>; pub fn make_chainstate( chain_config: Arc, - config: Config, + chainstate_config: ChainstateConfig, chainstate_storage: chainstate_storage::Store, custom_orphan_error_hook: Option>, time_getter: TimeGetter, ) -> Result, ChainstateError> { let cons = Chainstate::new( chain_config, - config, + chainstate_config, chainstate_storage, custom_orphan_error_hook, time_getter, diff --git a/chainstate/src/rpc.rs b/chainstate/src/rpc.rs index f2a48a4331..2aa95954d9 100644 --- a/chainstate/src/rpc.rs +++ b/chainstate/src/rpc.rs @@ -85,7 +85,7 @@ fn handle_error(e: Result, CallError>) -> rpc::Res #[cfg(test)] mod test { use super::*; - use crate::Config; + use crate::ChainstateConfig; use serde_json::Value; use std::{future::Future, sync::Arc}; @@ -93,12 +93,19 @@ mod test { proc: impl 'static + Send + FnOnce(crate::ChainstateHandle) -> F, ) { let storage = chainstate_storage::Store::new_empty().unwrap(); - let cfg = Arc::new(common::chain::config::create_unit_test_config()); - let config = Config::new(); + let chain_config = Arc::new(common::chain::config::create_unit_test_config()); + let chainstate_config = ChainstateConfig::new(); let mut man = subsystem::Manager::new("rpctest"); let handle = man.add_subsystem( "chainstate", - crate::make_chainstate(cfg, config, storage, None, Default::default()).unwrap(), + crate::make_chainstate( + chain_config, + chainstate_config, + storage, + None, + Default::default(), + ) + .unwrap(), ); let _ = man.add_raw_subsystem( "test", diff --git a/common/Cargo.toml b/common/Cargo.toml index 169e2d6aa4..7cecc1eac3 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -19,7 +19,7 @@ hex-literal = "0.3" lazy_static = "1.4" merkletree = "0.21" parity-scale-codec = "3.1" -serde = { version = "1", features = ["derive"] } +serde = "1.0" sscanf = "0.2" static_assertions = "1.1" strum = { version = "0.24", features = ["derive"] } diff --git a/common/src/chain/config/builder.rs b/common/src/chain/config/builder.rs index 62dc9aafa1..3bbd5a5f2f 100644 --- a/common/src/chain/config/builder.rs +++ b/common/src/chain/config/builder.rs @@ -13,15 +13,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{collections::BTreeMap, time::Duration}; - use super::emission_schedule::{self, *}; use super::{create_mainnet_genesis, create_unit_test_genesis, ChainConfig, ChainType}; use crate::chain::{ block::Block, ConsensusUpgrade, Destination, NetUpgrades, PoWChainConfig, UpgradeVersion, }; -use crate::primitives::BlockHeight; +use crate::primitives::{semver::SemVer, BlockDistance, BlockHeight, Idable}; + +use std::collections::BTreeMap; +use std::time::Duration; impl ChainType { fn default_genesis_init(&self) -> GenesisBlockInit { @@ -83,8 +84,18 @@ impl GenesisBlockInit { #[derive(Clone)] pub struct Builder { chain_type: ChainType, + address_prefix: String, + rpc_port: u16, + p2p_port: u16, + magic_bytes: [u8; 4], + blockreward_maturity: BlockDistance, + max_future_block_time_offset: Duration, + version: SemVer, target_block_spacing: Duration, coin_decimals: u8, + max_block_header_size: usize, + max_block_size_with_standard_txs: usize, + max_block_size_with_smart_contracts: usize, net_upgrades: NetUpgrades, genesis_block: GenesisBlockInit, emission_schedule: EmissionScheduleInit, @@ -95,8 +106,18 @@ impl Builder { pub fn new(chain_type: ChainType) -> Self { Self { chain_type, + address_prefix: chain_type.default_address_prefix().to_string(), + blockreward_maturity: super::MAINNET_BLOCKREWARD_MATURITY, coin_decimals: Mlt::DECIMALS, + magic_bytes: chain_type.default_magic_bytes(), + version: SemVer::new(0, 1, 0), + max_block_header_size: super::MAX_BLOCK_HEADER_SIZE, + max_block_size_with_standard_txs: super::MAX_BLOCK_TXS_SIZE, + max_block_size_with_smart_contracts: super::MAX_BLOCK_CONTRACTS_SIZE, + max_future_block_time_offset: super::DEFAULT_MAX_FUTURE_BLOCK_TIME_OFFSET target_block_spacing: super::DEFAULT_TARGET_BLOCK_SPACING, + p2p_port: 8978, + rpc_port: 15234, genesis_block: chain_type.default_genesis_init(), emission_schedule: EmissionScheduleInit::Mainnet, net_upgrades: chain_type.default_net_upgrades(), @@ -114,8 +135,18 @@ impl Builder { pub fn build(self) -> ChainConfig { let Self { chain_type, + address_prefix, + blockreward_maturity, coin_decimals, + magic_bytes, + version, + max_block_header_size, + max_block_size_with_standard_txs, + max_block_size_with_smart_contracts, + max_future_block_time_offset, target_block_spacing, + p2p_port, + rpc_port, genesis_block, emission_schedule, net_upgrades, @@ -139,8 +170,18 @@ impl Builder { ChainConfig { chain_type, + address_prefix, + blockreward_maturity, coin_decimals, + magic_bytes, + version, + max_block_header_size, + max_block_size_with_standard_txs, + max_block_size_with_smart_contracts, + max_future_block_time_offset, target_block_spacing, + p2p_port, + rpc_port, genesis_block, height_checkpoint_data: BTreeMap::new(), emission_schedule, @@ -164,8 +205,18 @@ macro_rules! builder_method { impl Builder { builder_method!(chain_type: ChainType); + builder_method!(address_prefix: String); + builder_method!(rpc_port: u16); + builder_method!(p2p_port: u16); + builder_method!(magic_bytes: [u8; 4]); + builder_method!(blockreward_maturity: BlockDistance); + builder_method!(max_future_block_time_offset: Duration); + builder_method!(version: SemVer); builder_method!(target_block_spacing: Duration); builder_method!(coin_decimals: u8); + builder_method!(max_block_header_size: usize); + builder_method!(max_block_size_with_standard_txs: usize); + builder_method!(max_block_size_with_smart_contracts: usize); builder_method!(net_upgrades: NetUpgrades); /// Set the genesis block to be the unit test version diff --git a/common/src/chain/config/mod.rs b/common/src/chain/config/mod.rs index d68953dd6f..c4c3569053 100644 --- a/common/src/chain/config/mod.rs +++ b/common/src/chain/config/mod.rs @@ -19,27 +19,25 @@ pub mod emission_schedule; pub use builder::Builder; pub use emission_schedule::{EmissionSchedule, EmissionScheduleTabular, Mlt}; -use std::{collections::BTreeMap, time::Duration}; - use hex::FromHex; -use serde::{Deserialize, Serialize}; - -use crate::primitives::Idable; -use crate::{ - chain::{ - block::{timestamp::BlockTimestamp, Block, ConsensusData}, - signature::inputsig::InputWitness, - transaction::{Destination, Transaction}, - upgrades::NetUpgrades, - OutputPurpose, PoWChainConfig, UpgradeVersion, - }, - primitives::{ - id::{Id, H256}, - semver::SemVer, - Amount, BlockHeight, - }, -}; +use crate::chain::block::timestamp::BlockTimestamp; +use crate::chain::block::Block; +use crate::chain::block::ConsensusData; +use crate::chain::signature::inputsig::InputWitness; +use crate::chain::transaction::Destination; +use crate::chain::transaction::Transaction; +use crate::chain::upgrades::NetUpgrades; +use crate::chain::OutputPurpose; +use crate::chain::{PoWChainConfig, UpgradeVersion}; +use crate::primitives::id::{Id, H256}; +use crate::primitives::Amount; +use crate::primitives::BlockDistance; +use crate::primitives::{semver::SemVer, BlockHeight}; +use std::collections::BTreeMap; +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); pub const VERSION: SemVer = SemVer::new(0, 1, 0); @@ -54,8 +52,6 @@ pub const VERSION: SemVer = SemVer::new(0, 1, 0); strum::Display, strum::EnumVariantNames, strum::EnumString, - Serialize, - Deserialize, )] #[strum(serialize_all = "kebab-case")] pub enum ChainType { @@ -66,7 +62,7 @@ pub enum ChainType { } impl ChainType { - const fn address_prefix(&self) -> &'static str { + const fn default_address_prefix(&self) -> &'static str { match self { ChainType::Mainnet => "mtc", ChainType::Testnet => "tmt", @@ -75,12 +71,12 @@ impl ChainType { } } - pub const fn magic_bytes(&self) -> &'static [u8; 4] { + pub const fn default_magic_bytes(&self) -> [u8; 4] { match self { - ChainType::Mainnet => &[0x1a, 0x64, 0xe5, 0xf1], - ChainType::Testnet => &[0x2b, 0x7e, 0x19, 0xf6], - ChainType::Regtest => &[0xaa, 0xbb, 0xcc, 0xdd], - ChainType::Signet => &[0xf3, 0xf7, 0x7b, 0x45], + ChainType::Mainnet => [0x1a, 0x64, 0xe5, 0xf1], + ChainType::Testnet => [0x2b, 0x7e, 0x19, 0xf6], + ChainType::Regtest => [0xaa, 0xbb, 0xcc, 0xdd], + ChainType::Signet => [0xf3, 0xf7, 0x7b, 0x45], } } } @@ -88,12 +84,23 @@ impl ChainType { #[derive(Debug, Clone)] pub struct ChainConfig { chain_type: ChainType, + address_prefix: String, + rpc_port: u16, + p2p_port: u16, height_checkpoint_data: BTreeMap>, net_upgrades: NetUpgrades, + magic_bytes: [u8; 4], genesis_block: Block, - pub target_block_spacing: Duration, + genesis_block_id: Id, + blockreward_maturity: BlockDistance, + max_future_block_time_offset: Duration, + version: SemVer, + target_block_spacing: Duration, coin_decimals: u8, emission_schedule: EmissionSchedule, + max_block_header_size: usize, + max_block_size_with_standard_txs: usize, + max_block_size_with_smart_contracts: usize, } impl ChainConfig { @@ -102,11 +109,11 @@ impl ChainConfig { } pub fn address_prefix(&self) -> &str { - &self.chain_type.address_prefix() + &self.address_prefix } pub fn genesis_block_id(&self) -> Id { - self.genesis_block.get_id() + self.genesis_block_id.clone() } pub fn genesis_block(&self) -> &Block { @@ -114,13 +121,17 @@ impl ChainConfig { } pub fn magic_bytes(&self) -> &[u8; 4] { - &self.chain_type.magic_bytes() + &self.magic_bytes } pub fn magic_bytes_as_u32(&self) -> u32 { u32::from_le_bytes(*self.magic_bytes()) } + pub fn version(&self) -> &SemVer { + &self.version + } + pub fn chain_type(&self) -> &ChainType { &self.chain_type } @@ -129,6 +140,14 @@ impl ChainConfig { &self.net_upgrades } + pub fn p2p_port(&self) -> u16 { + self.p2p_port + } + + pub fn rpc_port(&self) -> u16 { + self.rpc_port + } + pub fn height_checkpoints(&self) -> &BTreeMap> { &self.height_checkpoint_data } @@ -145,16 +164,43 @@ impl ChainConfig { self.coin_decimals } + pub fn max_future_block_time_offset(&self) -> &Duration { + &self.max_future_block_time_offset + } + pub fn block_subsidy_at_height(&self, height: &BlockHeight) -> Amount { self.emission_schedule().subsidy(*height).to_amount_atoms() } + pub fn max_block_header_size(&self) -> usize { + self.max_block_header_size + } + + pub fn max_block_size_from_txs(&self) -> usize { + self.max_block_size_with_standard_txs + } + + pub fn max_block_size_from_smart_contracts(&self) -> usize { + self.max_block_size_with_smart_contracts + } + // TODO: this should be part of net-upgrades. There should be no canonical definition of PoW for any chain config pub const fn get_proof_of_work_config(&self) -> PoWChainConfig { PoWChainConfig::new(self.chain_type) } + + pub const fn blockreward_maturity(&self) -> &BlockDistance { + &self.blockreward_maturity + } } +// If block time is 2 minutes (which is my goal eventually), then 500 is equivalent to 100 in bitcoin's 10 minutes. +const MAINNET_BLOCKREWARD_MATURITY: BlockDistance = BlockDistance::new(500); +// DSA allows us to have blocks up to 1mb +const MAX_BLOCK_HEADER_SIZE: usize = 1024; +const MAX_BLOCK_TXS_SIZE: usize = 524_288; +const MAX_BLOCK_CONTRACTS_SIZE: usize = 524_288; + fn create_mainnet_genesis() -> Block { use crate::chain::transaction::{TxInput, TxOutput}; @@ -260,4 +306,12 @@ mod tests { assert_eq!(&chain_type.to_string(), chain_type_str); } } + + #[test] + fn different_magic_bytes() { + let config1 = Builder::new(ChainType::Regtest).build(); + let config2 = Builder::new(ChainType::Regtest).magic_bytes([1, 2, 3, 4]).build(); + + assert_ne!(config1.magic_bytes(), config2.magic_bytes()); + } } diff --git a/common/src/primitives/height.rs b/common/src/primitives/height.rs index 84d89b1639..6f248528aa 100644 --- a/common/src/primitives/height.rs +++ b/common/src/primitives/height.rs @@ -13,12 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{ - fmt, - ops::{Add, Sub}, -}; - -use serde::{Deserialize, Serialize}; +use std::fmt; +use std::ops::{Add, Sub}; use serialization::{Decode, Encode}; @@ -166,9 +162,7 @@ impl BlockHeight { ///////////////////////////// -#[derive( - Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Encode, Decode, Serialize, Deserialize, -)] +#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Encode, Decode)] pub struct BlockDistance(DistanceIntType); impl BlockDistance { diff --git a/common/src/primitives/semver.rs b/common/src/primitives/semver.rs index 94b6eb8199..0c31a8ab6d 100644 --- a/common/src/primitives/semver.rs +++ b/common/src/primitives/semver.rs @@ -15,11 +15,9 @@ // // Author(s): A. Altonen -use serde::{Deserialize, Serialize}; - use serialization::{Decode, Encode}; -#[derive(Debug, PartialEq, Eq, Encode, Decode, Copy, Clone, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Encode, Decode, Copy, Clone)] pub struct SemVer { pub major: u8, pub minor: u8, @@ -27,7 +25,7 @@ pub struct SemVer { } impl SemVer { - pub const fn new(major: u8, minor: u8, patch: u16) -> Self { + pub fn new(major: u8, minor: u8, patch: u16) -> Self { Self { major, minor, diff --git a/node/mintlayer.toml b/node/mintlayer.toml deleted file mode 100644 index 218e87cc6c..0000000000 --- a/node/mintlayer.toml +++ /dev/null @@ -1,17 +0,0 @@ -chain_type = "Mainnet" - -[chainstate] -max_block_header_size = 1024 -max_block_size_from_txs = 524288 -max_block_size_from_smart_contracts = 524288 -blockreward_maturity = 500 - -[chainstate.max_future_block_time_offset] -secs = 3600 -nanos = 0 - -[p2p] -address = "/ip6/::1/tcp/3031" - -[rpc] -address = "127.0.0.1:3030" diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index c4a96f9003..b7d3e2693c 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -14,7 +14,9 @@ // limitations under the License. // // Author(s): A. Altonen + use crate::{ + config::P2pConfig, error::{ConversionError, P2pError}, net::{ConnectivityService, NetworkingService, PubSubService, SyncingCodecService}, }; @@ -153,7 +155,7 @@ where /// This function starts the networking backend and individual manager objects. pub async fn new( chain_config: Arc, - config: Config, + p2p_config: P2pConfig, consensus_handle: subsystem::Handle>, ) -> crate::Result where @@ -161,7 +163,7 @@ where <::Address as FromStr>::Err: Debug, { let (conn, pubsub, sync) = T::start( - config.address.parse::().map_err(|_| { + p2p_config.address.parse::().map_err(|_| { P2pError::ConversionError(ConversionError::InvalidAddress(config.address.clone())) })?, &[], @@ -231,7 +233,7 @@ pub type P2pHandle = subsystem::Handle>; pub async fn make_p2p( chain_config: Arc, - config: Config, + p2p_config: P2pConfig, consensus_handle: subsystem::Handle>, ) -> crate::Result> where @@ -245,6 +247,6 @@ where <::PeerId as FromStr>::Err: Debug, { Ok(P2pInterface { - p2p: P2P::new(chain_config, config, consensus_handle).await?, + p2p: P2P::new(chain_config, p2p_config, consensus_handle).await?, }) } diff --git a/p2p/src/net/libp2p/behaviour.rs b/p2p/src/net/libp2p/behaviour.rs index 785a23ff3f..b88f6a8087 100644 --- a/p2p/src/net/libp2p/behaviour.rs +++ b/p2p/src/net/libp2p/behaviour.rs @@ -28,7 +28,7 @@ use crate::{ }, }, }; -use common::chain::{config::VERSION, ChainConfig}; +use common::chain::config::ChainConfig; use libp2p::{ core::PeerId, gossipsub::{self, Gossipsub, GossipsubConfigBuilder, MessageAuthenticity, ValidationMode}, @@ -105,11 +105,12 @@ impl Libp2pBehaviour { .build() .expect("configuration to be valid"); + let version = config.version(); let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", - VERSION.major, - VERSION.minor, - VERSION.patch, + version.major, + version.minor, + version.patch, config.magic_bytes_as_u32(), ); let mut req_cfg = RequestResponseConfig::default(); diff --git a/p2p/src/net/libp2p/tests/mod.rs b/p2p/src/net/libp2p/tests/mod.rs index 9ce3afca10..be5644971b 100644 --- a/p2p/src/net/libp2p/tests/mod.rs +++ b/p2p/src/net/libp2p/tests/mod.rs @@ -20,7 +20,6 @@ use crate::net::{ libp2p::sync::*, libp2p::{backend::Backend, behaviour, types}, }; -use common::chain::{config::VERSION, ChainConfig}; use futures::prelude::*; use libp2p::{ core::{muxing::StreamMuxerBox, transport::Boxed, upgrade, PeerId}, @@ -58,7 +57,7 @@ mod ping; #[allow(dead_code)] pub async fn make_libp2p( - chain_config: ChainConfig, + config: common::chain::ChainConfig, addr: Multiaddr, topics: &[net::types::PubSubTopic], relay_mdns: bool, @@ -92,12 +91,13 @@ pub async fn make_libp2p( .build() .expect("configuration to be valid"); - let magic = chain_config.magic_bytes(); + let version = config.version(); + let magic = config.magic_bytes(); let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", - VERSION.major, - VERSION.minor, - VERSION.patch, + version.major, + version.minor, + version.patch, ((magic[0] as u32) << 24) | ((magic[1] as u32) << 16) | ((magic[2] as u32) << 8) @@ -157,7 +157,7 @@ pub async fn make_libp2p( #[allow(dead_code)] pub async fn make_libp2p_with_ping( - chain_config: ChainConfig, + config: common::chain::ChainConfig, addr: Multiaddr, topics: &[net::types::PubSubTopic], ping: libp2p_ping::Behaviour, @@ -192,12 +192,13 @@ pub async fn make_libp2p_with_ping( .build() .expect("configuration to be valid"); - let magic = chain_config.magic_bytes(); + let version = config.version(); + let magic = config.magic_bytes(); let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", - VERSION.major, - VERSION.minor, - VERSION.patch, + version.major, + version.minor, + version.patch, ((magic[0] as u32) << 24) | ((magic[1] as u32) << 16) | ((magic[2] as u32) << 8) @@ -300,12 +301,13 @@ pub fn make_transport_and_keys() -> (Boxed<(PeerId, StreamMuxerBox)>, PeerId, id #[allow(dead_code)] pub fn make_identify(config: ChainConfig, id_keys: identity::Keypair) -> Identify { + let version = config.version(); let magic = config.magic_bytes(); let protocol = format!( "/mintlayer/{}.{}.{}-{:x}", - VERSION.major, - VERSION.minor, - VERSION.patch, + version.major, + version.minor, + version.patch, ((magic[0] as u32) << 24) | ((magic[1] as u32) << 16) | ((magic[2] as u32) << 8) diff --git a/p2p/src/swarm/mod.rs b/p2p/src/swarm/mod.rs index 7af699ba37..c41ccdd55b 100644 --- a/p2p/src/swarm/mod.rs +++ b/p2p/src/swarm/mod.rs @@ -27,10 +27,7 @@ use crate::{ event, net::{self, ConnectivityService, NetworkingService}, }; -use common::{ - chain::{config::VERSION, ChainConfig}, - primitives::semver, -}; +use common::{chain::ChainConfig, primitives::semver}; use futures::FutureExt; use logging::log; use std::{collections::HashMap, fmt::Debug, str::FromStr, sync::Arc, time::Duration}; @@ -159,7 +156,7 @@ where /// /// Make sure that local and remote peer have the same software version fn validate_version(&self, version: &semver::SemVer) -> bool { - version == &VERSION + version == self.config.version() } /// Handle connection established event @@ -171,15 +168,18 @@ where log::debug!("{}", info); ensure!( - &info.magic_bytes == self.config.magic_bytes(), + info.magic_bytes == *self.config.magic_bytes(), P2pError::ProtocolError(ProtocolError::DifferentNetwork( - self.config.magic_bytes().to_owned(), + *self.config.magic_bytes(), info.magic_bytes, )) ); ensure!( self.validate_version(&info.version), - P2pError::ProtocolError(ProtocolError::InvalidVersion(VERSION, info.version)) + P2pError::ProtocolError(ProtocolError::InvalidVersion( + *self.config.version(), + info.version + )) ); ensure!( self.validate_supported_protocols(&info.protocols), diff --git a/p2p/src/sync/tests/mod.rs b/p2p/src/sync/tests/mod.rs index 4663a8b11f..0ce77a7154 100644 --- a/p2p/src/sync/tests/mod.rs +++ b/p2p/src/sync/tests/mod.rs @@ -14,6 +14,7 @@ // limitations under the License. // // Author(s): A. Altonen + use super::*; use crate::{ event::{PubSubControlEvent, SwarmEvent, SyncControlEvent}, @@ -49,12 +50,19 @@ where let (tx_pubsub, rx_pubsub) = mpsc::channel(16); let (tx_swarm, rx_swarm) = mpsc::channel(16); let storage = chainstate_storage::Store::new_empty().unwrap(); - let cfg = Arc::new(common::chain::config::create_unit_test_config()); - let config = ChainstateConfig::new(); + let chain_config = Arc::new(common::chain::config::create_unit_test_config()); + let chainstate_config = ChainstateConfig::new(); let mut man = subsystem::Manager::new("TODO"); let handle = man.add_subsystem( "consensus", - make_chainstate(cfg, config, storage, None, Default::default()).unwrap(), + make_chainstate( + chain_config, + chainstate_config, + storage, + None, + Default::default(), + ) + .unwrap(), ); tokio::spawn(async move { man.main().await }); diff --git a/p2p/test-utils/src/lib.rs b/p2p/test-utils/src/lib.rs index 9c7c1d87bc..34aba53e83 100644 --- a/p2p/test-utils/src/lib.rs +++ b/p2p/test-utils/src/lib.rs @@ -18,8 +18,7 @@ #![allow(clippy::unwrap_used)] use chainstate::{ - chainstate_interface::ChainstateInterface, make_chainstate, BlockSource, - Config as ChainstateConfig, + chainstate_interface::ChainstateInterface, make_chainstate, BlockSource, ChainstateConfig, }; use common::{ chain::{ @@ -141,14 +140,14 @@ fn anyonecanspend_address() -> Destination { } pub async fn start_chainstate( - config: Arc, + chain_config: Arc, ) -> subsystem::Handle> { let storage = chainstate_storage::Store::new_empty().unwrap(); let mut man = subsystem::Manager::new("TODO"); let handle = man.add_subsystem( "chainstate", make_chainstate( - config, + chain_config, ChainstateConfig::new(), storage, None, diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 2e26b9f4e9..54c77bf534 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -56,8 +56,8 @@ impl Builder { } /// New builder pre-populated with RPC info methods - pub fn new(config: Config) -> Self { - Self::new_empty(config.address).register(RpcInfo.into_rpc()) + pub fn new(rpc_config: RpcConfig) -> Self { + Self::new_empty(rpc_config.address).register(RpcInfo.into_rpc()) } /// Add methods handlers to the RPC server @@ -131,10 +131,10 @@ mod tests { #[tokio::test] async fn rpc_server() -> anyhow::Result<()> { - let config = Config { + let rpc_config = RpcConfig { address: "127.0.0.1:3030".parse().unwrap(), }; - let rpc = Builder::new(config).register(SubsystemRpcImpl.into_rpc()).build().await?; + let rpc = Builder::new(rpc_config).register(SubsystemRpcImpl.into_rpc()).build().await?; let url = format!("http://{}", rpc.address()); let client = HttpClientBuilder::default().build(url)?; From 01ed6dfc24a6ea69df1452f1b5bc6b2a34b63fda Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 13 Jul 2022 21:51:28 +0200 Subject: [PATCH 16/30] Fix compilation everywhere --- chainstate/src/config.rs | 6 +- .../src/detail/block_index_history_iter.rs | 2 +- chainstate/src/detail/chainstateref.rs | 2 +- common/src/chain/config/builder.rs | 3 +- common/src/chain/config/mod.rs | 7 +-- node/src/config.rs | 60 +++++++++---------- node/src/lib.rs | 2 +- node/src/main.rs | 23 +++---- node/src/options.rs | 28 ++++----- node/src/runner.rs | 31 ++++++---- node/tests/cli.rs | 46 +++++++------- p2p/src/lib.rs | 4 +- p2p/src/net/libp2p/tests/mod.rs | 2 +- p2p/src/sync/tests/mod.rs | 2 +- 14 files changed, 107 insertions(+), 111 deletions(-) diff --git a/chainstate/src/config.rs b/chainstate/src/config.rs index 89f66ddccb..a77cf51557 100644 --- a/chainstate/src/config.rs +++ b/chainstate/src/config.rs @@ -13,19 +13,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::time::Duration; - use serde::{Deserialize, Serialize}; -use common::primitives::BlockDistance; - /// The chainstate subsystem configuration. #[derive(Serialize, Deserialize, Debug)] pub struct ChainstateConfig { // TODO: FIXME! } -impl Config { +impl ChainstateConfig { /// Creates a new chainstate configuration isntance. pub fn new() -> Self { todo!(); diff --git a/chainstate/src/detail/block_index_history_iter.rs b/chainstate/src/detail/block_index_history_iter.rs index 405a3058aa..f16cc98176 100644 --- a/chainstate/src/detail/block_index_history_iter.rs +++ b/chainstate/src/detail/block_index_history_iter.rs @@ -83,7 +83,7 @@ mod tests { fn history_iteration() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); - let chainstte_config = Config::new(); + let chainstte_config = ChainstateConfig::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = Chainstate::new( chain_config.clone(), diff --git a/chainstate/src/detail/chainstateref.rs b/chainstate/src/detail/chainstateref.rs index ecdbcc6711..6cb294182d 100644 --- a/chainstate/src/detail/chainstateref.rs +++ b/chainstate/src/detail/chainstateref.rs @@ -109,7 +109,7 @@ impl<'a, S: BlockchainStorageRead, O: OrphanBlocks> ChainstateRef<'a, S, O> { pub fn new_ro( chain_config: &'a ChainConfig, - chainstete_config: &'a ChainstateConfig, + chainstate_config: &'a ChainstateConfig, db_tx: S, orphan_blocks: O, time_getter: &'a TimeGetterFn, diff --git a/common/src/chain/config/builder.rs b/common/src/chain/config/builder.rs index 3bbd5a5f2f..1f4962c725 100644 --- a/common/src/chain/config/builder.rs +++ b/common/src/chain/config/builder.rs @@ -114,7 +114,7 @@ impl Builder { max_block_header_size: super::MAX_BLOCK_HEADER_SIZE, max_block_size_with_standard_txs: super::MAX_BLOCK_TXS_SIZE, max_block_size_with_smart_contracts: super::MAX_BLOCK_CONTRACTS_SIZE, - max_future_block_time_offset: super::DEFAULT_MAX_FUTURE_BLOCK_TIME_OFFSET + max_future_block_time_offset: super::DEFAULT_MAX_FUTURE_BLOCK_TIME_OFFSET, target_block_spacing: super::DEFAULT_TARGET_BLOCK_SPACING, p2p_port: 8978, rpc_port: 15234, @@ -182,6 +182,7 @@ impl Builder { target_block_spacing, p2p_port, rpc_port, + genesis_block_id: genesis_block.get_id(), genesis_block, height_checkpoint_data: BTreeMap::new(), emission_schedule, diff --git a/common/src/chain/config/mod.rs b/common/src/chain/config/mod.rs index c4c3569053..61c33b8b94 100644 --- a/common/src/chain/config/mod.rs +++ b/common/src/chain/config/mod.rs @@ -39,7 +39,6 @@ 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); -pub const VERSION: SemVer = SemVer::new(0, 1, 0); #[derive( Debug, @@ -71,7 +70,7 @@ impl ChainType { } } - pub const fn default_magic_bytes(&self) -> [u8; 4] { + const fn default_magic_bytes(&self) -> [u8; 4] { match self { ChainType::Mainnet => [0x1a, 0x64, 0xe5, 0xf1], ChainType::Testnet => [0x2b, 0x7e, 0x19, 0xf6], @@ -104,10 +103,6 @@ pub struct ChainConfig { } impl ChainConfig { - pub fn new(chain_type: ChainType) -> Self { - Builder::new(chain_type).build() - } - pub fn address_prefix(&self) -> &str { &self.address_prefix } diff --git a/node/src/config.rs b/node/src/config.rs index 5894d8cd1e..a8d60c1cc0 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -21,7 +21,6 @@ use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; use chainstate::ChainstateConfig; -use common::chain::config::ChainType; use p2p::config::P2pConfig; use rpc::RpcConfig; @@ -29,23 +28,20 @@ use crate::RunOptions; /// The node configuration. #[derive(Serialize, Deserialize, Debug)] -pub struct Config { - pub chain_type: ChainType, - +pub struct NodeConfig { // Subsystems configurations. pub chainstate: ChainstateConfig, pub p2p: P2pConfig, pub rpc: RpcConfig, } -impl Config { +impl NodeConfig { /// Creates a new `Config` instance for the specified chain type. - pub fn new(chain_type: ChainType) -> Result { - let chainstate = chainstate::Config::new(); - let p2p = p2p::Config::new(); - let rpc = rpc::Config::new()?; + pub fn new() -> Result { + let chainstate = ChainstateConfig::new(); + let p2p = P2pConfig::new(); + let rpc = RpcConfig::new()?; Ok(Self { - chain_type, chainstate, p2p, rpc, @@ -56,28 +52,30 @@ impl Config { /// parameters. pub fn read(options: RunOptions) -> Result { let config = fs::read_to_string(&options.config_path).context("Failed to read config")?; - let mut config: Config = toml::from_str(&config).context("Failed to deserialize config")?; - - // Chainstate options. - if let Some(max_size) = options.max_block_header_size { - config.chainstate.max_block_header_size = max_size; - } - if let Some(max_size) = options.max_block_size_from_txs { - config.chainstate.max_block_size_from_txs = max_size; - } - if let Some(max_size) = options.max_block_size_from_smart_contracts { - config.chainstate.max_block_size_from_smart_contracts = max_size; - } - - // P2p options. - if let Some(address) = options.p2p_addr { - config.p2p.address = address; - } + let mut config: NodeConfig = + toml::from_str(&config).context("Failed to deserialize config")?; - // Rpc options. - if let Some(address) = options.rpc_addr { - config.rpc.address = address; - } + todo!(); + // // Chainstate options. + // if let Some(max_size) = options.max_block_header_size { + // config.chainstate.max_block_header_size = max_size; + // } + // if let Some(max_size) = options.max_block_size_from_txs { + // config.chainstate.max_block_size_from_txs = max_size; + // } + // if let Some(max_size) = options.max_block_size_from_smart_contracts { + // config.chainstate.max_block_size_from_smart_contracts = max_size; + // } + // + // // P2p options. + // if let Some(address) = options.p2p_addr { + // config.p2p.address = address; + // } + // + // // Rpc options. + // if let Some(address) = options.rpc_addr { + // config.rpc.address = address; + // } Ok(config) } diff --git a/node/src/lib.rs b/node/src/lib.rs index 058659f362..b64d55c710 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -21,7 +21,7 @@ mod runner; pub type Error = anyhow::Error; -pub use config::Config; +pub use config::NodeConfig; pub use options::{Command, Options, RunOptions}; pub use runner::{initialize, run}; diff --git a/node/src/main.rs b/node/src/main.rs index c82d5890a0..00425577e1 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -17,11 +17,10 @@ use std::fs; -use anyhow::{anyhow, Context, Result}; +use anyhow::{Context, Result}; -use common::chain::{config::ChainType, ChainConfig}; use logging::log; -use node::{Command, Config, Options}; +use node::{Command, NodeConfig, Options}; async fn run() -> Result<()> { let opts = Options::from_args(std::env::args_os()); @@ -29,24 +28,18 @@ async fn run() -> Result<()> { log::trace!("Command line options: {opts:?}"); match opts.command { - Command::CreateConfig { path, net } => { - let config = Config::new(net)?; + Command::CreateConfig { path } => { + let config = NodeConfig::new()?; let config = toml::to_string(&config).context("Failed to serialize config")?; log::trace!("Saving config to {path:?}\n: {config:#?}"); fs::write(path, config).context("Failed to write config")?; Ok(()) } Command::Run(options) => { - let config = Config::read(options).context("Failed to initialize config")?; - if config.chain_type != ChainType::Mainnet && config.chain_type != ChainType::Regtest { - return Err(anyhow!( - "Chain type '{:?}' not yet supported", - config.chain_type - )); - } - let chain_config = ChainConfig::new(config.chain_type); - log::trace!("Starting with the following config\n: {config:#?}"); - node::run(chain_config, config).await + let chain_type = options.net; + let node_config = NodeConfig::read(options).context("Failed to initialize config")?; + log::trace!("Starting with the following config\n: {node_config:#?}"); + node::run(chain_type, node_config).await } } } diff --git a/node/src/options.rs b/node/src/options.rs index c27dd5f77f..20cc289ffb 100644 --- a/node/src/options.rs +++ b/node/src/options.rs @@ -36,35 +36,33 @@ pub struct Options { #[derive(Subcommand, Debug)] pub enum Command { - Run(RunOptions), /// Create a configuration file. CreateConfig { /// The path where config will be created. - #[clap(short, long, default_value = "./mintlayer.toml")] + // TODO: Use a system-specific location by default such as `%APPDATA%` on Windows and + // `~/Library/Application Support` on Mac. + #[clap(short, long, default_value = "./.mintlayer/mintlayer.toml")] path: PathBuf, - /// Blockchain type. - #[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")] - net: ChainType, }, + Run(RunOptions), } #[derive(Args, Debug)] pub struct RunOptions { /// The path to the configuration file. - #[clap(short, long, default_value = "./mintlayer.toml")] + // TODO: Use a system-specific location by default such as `%APPDATA%` on Windows and + // `~/Library/Application Support` on Mac. + #[clap(short, long, default_value = "./.mintlayer/mintlayer.toml")] pub config_path: PathBuf, - /// Maximum header size. - #[clap(long)] - pub max_block_header_size: Option, - /// Maximum transactions size in a block. - #[clap(long)] - pub max_block_size_from_txs: Option, - /// Maximum smart contracts size in a block. - #[clap(long)] - pub max_block_size_from_smart_contracts: Option, + + /// Blockchain type. + #[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")] + pub net: ChainType, + /// Address to bind P2P to. #[clap(long, value_name = "ADDR")] pub p2p_addr: Option, + /// Address to bind RPC to. #[clap(long, value_name = "ADDR")] pub rpc_addr: Option, diff --git a/node/src/runner.rs b/node/src/runner.rs index f089ca1a41..0b3efcfaf1 100644 --- a/node/src/runner.rs +++ b/node/src/runner.rs @@ -15,21 +15,32 @@ //! Node initialisation routine. -use crate::config::Config; +use crate::config::NodeConfig; use chainstate::rpc::ChainstateRpcServer; -use common::chain::config::ChainConfig; +use common::chain::config::ChainType; use p2p::rpc::P2pRpcServer; use std::sync::Arc; +#[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_config: ChainConfig, - config: Config, + chain_type: ChainType, + node_config: NodeConfig, ) -> anyhow::Result { // Initialize storage. let storage = chainstate_storage::Store::new_empty()?; - let chain_config = Arc::new(chain_config); + // 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 @@ -41,7 +52,7 @@ pub async fn initialize( "chainstate", chainstate::make_chainstate( Arc::clone(&chain_config), - config.chainstate, + node_config.chainstate, storage.clone(), None, Default::default(), @@ -53,7 +64,7 @@ pub async fn initialize( "p2p", p2p::make_p2p::( Arc::clone(&chain_config), - config.p2p, + node_config.p2p, chainstate.clone(), ) .await @@ -63,7 +74,7 @@ pub async fn initialize( // RPC subsystem let _rpc = manager.add_subsystem( "rpc", - rpc::Builder::new(config.rpc) + rpc::Builder::new(node_config.rpc) .register(chainstate.clone().into_rpc()) .register(NodeRpc::new(manager.make_shutdown_trigger()).into_rpc()) .register(p2p.clone().into_rpc()) @@ -75,8 +86,8 @@ pub async fn initialize( } /// Initialize and run the node -pub async fn run(chain_config: ChainConfig, config: Config) -> anyhow::Result<()> { - let manager = initialize(chain_config, config).await?; +pub async fn run(chain_type: ChainType, node_config: NodeConfig) -> anyhow::Result<()> { + let manager = initialize(chain_type, node_config).await?; #[allow(clippy::unit_arg)] Ok(manager.main().await) diff --git a/node/tests/cli.rs b/node/tests/cli.rs index 036fdce30a..46c4ca8c6f 100644 --- a/node/tests/cli.rs +++ b/node/tests/cli.rs @@ -17,7 +17,7 @@ use std::path::Path; use assert_cmd::Command; -use node::{Config, RunOptions}; +use node::{NodeConfig, RunOptions}; const BIN_NAME: &str = env!("CARGO_BIN_EXE_node"); @@ -46,25 +46,27 @@ fn create_config() { .arg(config_path) .assert() .success(); - let run_options = RunOptions { - config_path: config_path.into(), - max_block_header_size: Some(max_block_header_size), - max_block_size_from_txs: Some(max_block_size_from_txs), - max_block_size_from_smart_contracts: Some(max_block_size_from_smart_contracts), - p2p_addr: None, - rpc_addr: None, - }; - let config = Config::read(run_options).unwrap(); - assert_eq!( - config.chainstate.max_block_header_size, - max_block_header_size - ); - assert_eq!( - config.chainstate.max_block_size_from_txs, - max_block_size_from_txs - ); - assert_eq!( - config.chainstate.max_block_size_from_smart_contracts, - max_block_size_from_smart_contracts - ); + // let run_options = RunOptions { + // config_path: config_path.into(), + // max_block_header_size: Some(max_block_header_size), + // max_block_size_from_txs: Some(max_block_size_from_txs), + // max_block_size_from_smart_contracts: Some(max_block_size_from_smart_contracts), + // p2p_addr: None, + // rpc_addr: None, + // }; + // let config = NodeConfig::read(run_options).unwrap(); + todo!(); + todo!(); + // assert_eq!( + // config.chainstate.max_block_header_size, + // max_block_header_size + // ); + // assert_eq!( + // config.chainstate.max_block_size_from_txs, + // max_block_size_from_txs + // ); + // assert_eq!( + // config.chainstate.max_block_size_from_smart_contracts, + // max_block_size_from_smart_contracts + // ); } diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index b7d3e2693c..d438caa188 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -164,7 +164,9 @@ where { let (conn, pubsub, sync) = T::start( p2p_config.address.parse::().map_err(|_| { - P2pError::ConversionError(ConversionError::InvalidAddress(config.address.clone())) + P2pError::ConversionError(ConversionError::InvalidAddress( + p2p_config.address.clone(), + )) })?, &[], Arc::clone(&chain_config), diff --git a/p2p/src/net/libp2p/tests/mod.rs b/p2p/src/net/libp2p/tests/mod.rs index be5644971b..5c4f1c1b3f 100644 --- a/p2p/src/net/libp2p/tests/mod.rs +++ b/p2p/src/net/libp2p/tests/mod.rs @@ -300,7 +300,7 @@ pub fn make_transport_and_keys() -> (Boxed<(PeerId, StreamMuxerBox)>, PeerId, id } #[allow(dead_code)] -pub fn make_identify(config: ChainConfig, id_keys: identity::Keypair) -> Identify { +pub fn make_identify(config: common::chain::ChainConfig, id_keys: identity::Keypair) -> Identify { let version = config.version(); let magic = config.magic_bytes(); let protocol = format!( diff --git a/p2p/src/sync/tests/mod.rs b/p2p/src/sync/tests/mod.rs index 0ce77a7154..d937572170 100644 --- a/p2p/src/sync/tests/mod.rs +++ b/p2p/src/sync/tests/mod.rs @@ -20,7 +20,7 @@ use crate::{ event::{PubSubControlEvent, SwarmEvent, SyncControlEvent}, net::{libp2p::Libp2pService, types::ConnectivityEvent, ConnectivityService}, }; -use chainstate::{make_chainstate, Config as ChainstateConfig}; +use chainstate::{make_chainstate, ChainstateConfig}; use libp2p::PeerId; #[cfg(test)] From ffcf85a19fd211a0a0039f03878db4fce1c6335e Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 13 Jul 2022 22:48:24 +0200 Subject: [PATCH 17/30] Expand the chainstate config --- chainstate/src/config.rs | 11 +++-- chainstate/src/detail/mod.rs | 10 ++-- chainstate/src/detail/orphan_blocks/pool.rs | 52 +++++++-------------- node/src/config.rs | 38 +++++++-------- node/src/options.rs | 8 ++++ 5 files changed, 54 insertions(+), 65 deletions(-) diff --git a/chainstate/src/config.rs b/chainstate/src/config.rs index a77cf51557..00a11a0718 100644 --- a/chainstate/src/config.rs +++ b/chainstate/src/config.rs @@ -18,13 +18,18 @@ use serde::{Deserialize, Serialize}; /// The chainstate subsystem configuration. #[derive(Serialize, Deserialize, Debug)] pub struct ChainstateConfig { - // TODO: FIXME! + /// The number of maximum attempts to process a block. + pub max_db_commit_attempts: usize, + /// The maximum capacity of the orphan blocks pool. + pub max_orphan_blocks: usize, } impl ChainstateConfig { /// Creates a new chainstate configuration isntance. pub fn new() -> Self { - todo!(); - Self {} + Self { + max_db_commit_attempts: 10, + max_orphan_blocks: 512, + } } } diff --git a/chainstate/src/detail/mod.rs b/chainstate/src/detail/mod.rs index 0a4b68e1c1..22051a9c3d 100644 --- a/chainstate/src/detail/mod.rs +++ b/chainstate/src/detail/mod.rs @@ -147,11 +147,12 @@ impl Chainstate { custom_orphan_error_hook: Option>, time_getter: TimeGetter, ) -> Result { + let orphan_blocks = OrphanBlocksPool::new(chainstate_config.max_orphan_blocks); let cons = Self { chain_config, chainstate_config, chainstate_storage, - orphan_blocks: OrphanBlocksPool::new_default(), + orphan_blocks, custom_orphan_error_hook, events_controller: EventsController::new(), time_getter, @@ -194,13 +195,10 @@ impl Chainstate { block_source: BlockSource, attempt_number: usize, ) -> Result, BlockError> { - // TODO: move to a configuration object that loads from command line arguments - const MAX_DB_COMMIT_COUNT: usize = 10; - - if attempt_number >= MAX_DB_COMMIT_COUNT { + if attempt_number >= self.chainstate_config.max_db_commit_attempts { Err(BlockError::DatabaseCommitError( block.get_id(), - MAX_DB_COMMIT_COUNT, + self.chainstate_config.max_db_commit_attempts, db_error, )) } else { diff --git a/chainstate/src/detail/orphan_blocks/pool.rs b/chainstate/src/detail/orphan_blocks/pool.rs index 921fb834c0..98cd94e85a 100644 --- a/chainstate/src/detail/orphan_blocks/pool.rs +++ b/chainstate/src/detail/orphan_blocks/pool.rs @@ -15,14 +15,12 @@ // // Author(s): S. Afach +use std::{collections::BTreeMap, sync::Arc}; + use super::{OrphanBlocksRef, OrphanBlocksRefMut}; use common::chain::block::Block; use common::primitives::{Id, Idable}; use crypto::random::SliceRandom; -use std::collections::BTreeMap; -use std::sync::Arc; - -pub const DEFAULT_MAX_ORPHAN_BLOCKS: usize = 512; // FIXME: The Arc here is unnecessary: https://github.com/mintlayer/mintlayer-core/issues/164 pub struct OrphanBlocksPool { @@ -38,17 +36,7 @@ pub enum OrphanAddError { } impl OrphanBlocksPool { - pub fn new_default() -> Self { - OrphanBlocksPool { - orphan_ids: Vec::new(), - orphan_by_id: BTreeMap::new(), - orphan_by_prev_id: BTreeMap::new(), - max_orphans: DEFAULT_MAX_ORPHAN_BLOCKS, - } - } - - #[allow(dead_code)] - pub fn new_custom(max_orphans: usize) -> Self { + pub fn new(max_orphans: usize) -> Self { OrphanBlocksPool { orphan_ids: Vec::new(), orphan_by_id: BTreeMap::new(), @@ -208,10 +196,11 @@ impl OrphanBlocksPool { mod tests { use super::*; use checkers::*; - use common::chain::block::Block; - use common::primitives::Id; + use common::{chain::block::Block, primitives::Id}; use helpers::*; + const MAX_ORPHAN_BLOCKS: usize = 512; + mod helpers { use super::*; use common::chain::block::timestamp::BlockTimestamp; @@ -323,24 +312,17 @@ mod tests { } } - #[test] - fn test_pool_default() { - let orphans_pool = OrphanBlocksPool::new_default(); - assert_eq!(orphans_pool.max_orphans, DEFAULT_MAX_ORPHAN_BLOCKS); - check_empty_pool(&orphans_pool); - } - #[test] fn test_pool_custom() { let max_orphans = 3; - let orphans_pool = OrphanBlocksPool::new_custom(max_orphans); + let orphans_pool = OrphanBlocksPool::new(max_orphans); assert_eq!(orphans_pool.max_orphans, max_orphans); check_empty_pool(&orphans_pool); } #[test] fn test_add_one_block_and_clear() { - let mut orphans_pool = OrphanBlocksPool::new_default(); + let mut orphans_pool = OrphanBlocksPool::new(MAX_ORPHAN_BLOCKS); // add a random block let block = gen_random_block(); @@ -357,7 +339,7 @@ mod tests { #[test] fn test_add_blocks_and_clear() { - let mut orphans_pool = OrphanBlocksPool::new_default(); + let mut orphans_pool = OrphanBlocksPool::new(MAX_ORPHAN_BLOCKS); // add a random block let block = gen_random_block(); @@ -406,7 +388,7 @@ mod tests { #[test] fn test_add_block_exceeds_max() { let max_orphans = 3; - let mut orphans_pool = OrphanBlocksPool::new_custom(max_orphans); + let mut orphans_pool = OrphanBlocksPool::new(max_orphans); let blocks = gen_random_blocks(max_orphans as u32 + 2); blocks.into_iter().for_each(|block| { @@ -418,7 +400,7 @@ mod tests { #[test] fn test_add_block_repeated() { - let mut orphans_pool = OrphanBlocksPool::new_default(); + let mut orphans_pool = OrphanBlocksPool::new(MAX_ORPHAN_BLOCKS); let blocks = gen_random_blocks(50); blocks.iter().for_each(|block| { @@ -437,7 +419,7 @@ mod tests { #[test] fn test_pool_drop_block() { - let mut orphans_pool = OrphanBlocksPool::new_default(); + let mut orphans_pool = OrphanBlocksPool::new(MAX_ORPHAN_BLOCKS); let blocks = gen_random_blocks(5); blocks.iter().for_each(|block| { @@ -461,7 +443,7 @@ mod tests { #[test] fn test_deepest_child_in_chain() { - let mut orphans_pool = OrphanBlocksPool::new_default(); + let mut orphans_pool = OrphanBlocksPool::new(MAX_ORPHAN_BLOCKS); // In `orphans_by_prev_id`: // [ @@ -516,7 +498,7 @@ mod tests { #[test] fn test_deepest_child_common_parent() { - let mut orphans_pool = OrphanBlocksPool::new_default(); + let mut orphans_pool = OrphanBlocksPool::new(MAX_ORPHAN_BLOCKS); // In `orphans_by_prev_id`: // [ // ( a, (b,c,d,e,f) ), @@ -574,7 +556,7 @@ mod tests { #[test] fn test_prune() { - let mut orphans_pool = OrphanBlocksPool::new_custom(12); + let mut orphans_pool = OrphanBlocksPool::new(12); // in `orphans_by_prev_id`: // [ // ( a, (b,c,d,e) ) @@ -646,7 +628,7 @@ mod tests { #[test] fn test_simple_take_all_children_of() { - let mut orphans_pool = OrphanBlocksPool::new_custom(20); + let mut orphans_pool = OrphanBlocksPool::new(20); let count = 9; // in `orphans_by_prev_id`: @@ -688,7 +670,7 @@ mod tests { #[test] fn test_mix_chain_take_all_children_of() { - let mut orphans_pool = OrphanBlocksPool::new_custom(20); + let mut orphans_pool = OrphanBlocksPool::new(20); let count = 9; // in `orphans_by_prev_id`: diff --git a/node/src/config.rs b/node/src/config.rs index a8d60c1cc0..2ace643991 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -55,27 +55,23 @@ impl NodeConfig { let mut config: NodeConfig = toml::from_str(&config).context("Failed to deserialize config")?; - todo!(); - // // Chainstate options. - // if let Some(max_size) = options.max_block_header_size { - // config.chainstate.max_block_header_size = max_size; - // } - // if let Some(max_size) = options.max_block_size_from_txs { - // config.chainstate.max_block_size_from_txs = max_size; - // } - // if let Some(max_size) = options.max_block_size_from_smart_contracts { - // config.chainstate.max_block_size_from_smart_contracts = max_size; - // } - // - // // P2p options. - // if let Some(address) = options.p2p_addr { - // config.p2p.address = address; - // } - // - // // Rpc options. - // if let Some(address) = options.rpc_addr { - // config.rpc.address = address; - // } + // Chainstate options. + if let Some(attempts) = options.max_db_commit_attempts { + config.chainstate.max_db_commit_attempts = attempts; + } + if let Some(max_orphans) = options.max_orphan_blocks { + config.chainstate.max_orphan_blocks = max_orphans; + } + + // P2p options. + if let Some(address) = options.p2p_addr { + config.p2p.address = address; + } + + // Rpc options. + if let Some(address) = options.rpc_addr { + config.rpc.address = address; + } Ok(config) } diff --git a/node/src/options.rs b/node/src/options.rs index 20cc289ffb..8f3eb9a84d 100644 --- a/node/src/options.rs +++ b/node/src/options.rs @@ -59,6 +59,14 @@ pub struct RunOptions { #[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")] pub net: ChainType, + /// Blockchain type. + #[clap(long)] + pub max_db_commit_attempts: Option, + + /// The maximum capacity of the orphan blocks pool. + #[clap(long)] + pub max_orphan_blocks: Option, + /// Address to bind P2P to. #[clap(long, value_name = "ADDR")] pub p2p_addr: Option, From bceecb38b9faa22cea4d3c2119063d51cf009335 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 13 Jul 2022 23:16:07 +0200 Subject: [PATCH 18/30] Expand the p2p config --- chainstate/src/detail/chainstateref.rs | 6 +++--- node/src/config.rs | 6 ++++++ node/src/options.rs | 8 ++++++++ node/tests/cli.rs | 2 ++ p2p/src/config.rs | 6 ++++++ p2p/src/lib.rs | 13 ++++++------- p2p/src/swarm/mod.rs | 25 +++++++++++++++---------- p2p/src/swarm/tests/mod.rs | 4 +++- 8 files changed, 49 insertions(+), 21 deletions(-) diff --git a/chainstate/src/detail/chainstateref.rs b/chainstate/src/detail/chainstateref.rs index 6cb294182d..f29ada65ed 100644 --- a/chainstate/src/detail/chainstateref.rs +++ b/chainstate/src/detail/chainstateref.rs @@ -44,7 +44,7 @@ use super::{ pub(crate) struct ChainstateRef<'a, S, O> { chain_config: &'a ChainConfig, - chainstate_config: &'a ChainstateConfig, + _chainstate_config: &'a ChainstateConfig, db_tx: S, orphan_blocks: O, time_getter: &'a TimeGetterFn, @@ -100,7 +100,7 @@ impl<'a, S: BlockchainStorageRead, O: OrphanBlocks> ChainstateRef<'a, S, O> { ) -> ChainstateRef<'a, S, O> { ChainstateRef { chain_config, - chainstate_config, + _chainstate_config: chainstate_config, db_tx, orphan_blocks, time_getter, @@ -116,7 +116,7 @@ impl<'a, S: BlockchainStorageRead, O: OrphanBlocks> ChainstateRef<'a, S, O> { ) -> ChainstateRef<'a, S, O> { ChainstateRef { chain_config, - chainstate_config, + _chainstate_config: chainstate_config, db_tx, orphan_blocks, time_getter, diff --git a/node/src/config.rs b/node/src/config.rs index 2ace643991..a54e6970d3 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -67,6 +67,12 @@ impl NodeConfig { if let Some(address) = options.p2p_addr { config.p2p.address = address; } + if let Some(threshold) = options.p2p_ban_threshold { + config.p2p.ban_threshold = threshold; + } + if let Some(timeout) = options.p2p_timeout { + config.p2p.timeout = timeout; + } // Rpc options. if let Some(address) = options.rpc_addr { diff --git a/node/src/options.rs b/node/src/options.rs index 8f3eb9a84d..a068ec8560 100644 --- a/node/src/options.rs +++ b/node/src/options.rs @@ -71,6 +71,14 @@ pub struct RunOptions { #[clap(long, value_name = "ADDR")] pub p2p_addr: Option, + /// The p2p score threshold after which a peer is baned. + #[clap(long)] + pub p2p_ban_threshold: Option, + + /// The p2p timeout value in seconds. + #[clap(long)] + pub p2p_timeout: Option, + /// Address to bind RPC to. #[clap(long, value_name = "ADDR")] pub rpc_addr: Option, diff --git a/node/tests/cli.rs b/node/tests/cli.rs index 46c4ca8c6f..fe4d354598 100644 --- a/node/tests/cli.rs +++ b/node/tests/cli.rs @@ -33,6 +33,8 @@ fn no_args() { Command::new(BIN_NAME).assert().failure(); } +// TODO: config with default values. + #[test] fn create_config() { let config_path = concat!(env!("CARGO_TARGET_TMPDIR"), "/test_mintlayer.toml"); diff --git a/p2p/src/config.rs b/p2p/src/config.rs index c07fcde8ad..05efa11434 100644 --- a/p2p/src/config.rs +++ b/p2p/src/config.rs @@ -20,6 +20,10 @@ use serde::{Deserialize, Serialize}; pub struct P2pConfig { /// Address to bind P2P to. pub address: String, + /// The score threshold after which a peer is baned. + pub ban_threshold: u32, + /// The timeout value in seconds. + pub timeout: u64, } impl P2pConfig { @@ -27,6 +31,8 @@ impl P2pConfig { pub fn new() -> Self { Self { address: "/ip6/::1/tcp/3031".into(), + ban_threshold: 100, + timeout: 10, } } } diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index 1e3ad42e5e..2d77c785e0 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -42,9 +42,6 @@ pub type Result = core::result::Result; // TODO: figure out proper channel sizes const CHANNEL_SIZE: usize = 64; -// TODO: this should come from a config -const TIMEOUT: Duration = Duration::from_secs(10); - pub struct P2pInterface { p2p: P2P, } @@ -162,6 +159,7 @@ where ::Address: FromStr, <::Address as FromStr>::Err: Debug, { + let p2p_config = Arc::new(p2p_config); let (conn, pubsub, sync) = T::start( p2p_config.address.parse::().map_err(|_| { P2pError::ConversionError(ConversionError::InvalidAddress( @@ -170,7 +168,7 @@ where })?, &[], Arc::clone(&chain_config), - TIMEOUT, + Duration::from_secs(p2p_config.timeout), ) .await?; @@ -182,9 +180,10 @@ where let swarm_config = Arc::clone(&chain_config); tokio::spawn(async move { - if let Err(e) = swarm::PeerManager::::new(swarm_config, conn, rx_swarm, tx_p2p_sync) - .run() - .await + if let Err(e) = + swarm::PeerManager::::new(swarm_config, p2p_config, conn, rx_swarm, tx_p2p_sync) + .run() + .await { log::error!("PeerManager failed: {:?}", e); } diff --git a/p2p/src/swarm/mod.rs b/p2p/src/swarm/mod.rs index b7295624df..5b0cedac16 100644 --- a/p2p/src/swarm/mod.rs +++ b/p2p/src/swarm/mod.rs @@ -26,6 +26,7 @@ use crate::{ error::{P2pError, PeerError, ProtocolError}, event, net::{self, ConnectivityService, NetworkingService}, + P2pConfig, }; use chainstate::ban_score::BanScore; use common::{chain::ChainConfig, primitives::semver}; @@ -47,8 +48,11 @@ pub struct PeerManager where T: NetworkingService, { - /// Chain config - config: Arc, + /// Chain configuration. + chain_config: Arc, + + /// P2p configuration. + p2p_config: Arc, /// Handle for sending/receiving connectivity events handle: T::ConnectivityHandle, @@ -77,13 +81,15 @@ where <::Address as FromStr>::Err: Debug, { pub fn new( - config: Arc, + chain_config: Arc, + p2p_config: Arc, handle: T::ConnectivityHandle, rx_swarm: mpsc::Receiver>, tx_sync: mpsc::Sender>, ) -> Self { Self { - config, + chain_config, + p2p_config, handle, rx_swarm, tx_sync, @@ -163,7 +169,7 @@ where /// /// Make sure that local and remote peer have the same software version fn validate_version(&self, version: &semver::SemVer) -> bool { - version == self.config.version() + version == self.chain_config.version() } /// Handle connection established event @@ -175,16 +181,16 @@ where log::debug!("{}", info); ensure!( - info.magic_bytes == *self.config.magic_bytes(), + info.magic_bytes == *self.chain_config.magic_bytes(), P2pError::ProtocolError(ProtocolError::DifferentNetwork( - *self.config.magic_bytes(), + *self.chain_config.magic_bytes(), info.magic_bytes, )) ); ensure!( self.validate_version(&info.version), P2pError::ProtocolError(ProtocolError::InvalidVersion( - *self.config.version(), + *self.chain_config.version(), info.version )) ); @@ -279,8 +285,7 @@ where score }; - // TODO: from config - if score >= 100 { + if score >= self.p2p_config.ban_threshold { self.peerdb.ban_peer(&peer_id); return self.handle.ban_peer(peer_id).await; } diff --git a/p2p/src/swarm/tests/mod.rs b/p2p/src/swarm/tests/mod.rs index 2ee6700025..363b49d73d 100644 --- a/p2p/src/swarm/tests/mod.rs +++ b/p2p/src/swarm/tests/mod.rs @@ -20,6 +20,7 @@ mod tmp; use crate::{ net::{ConnectivityService, NetworkingService}, swarm::PeerManager, + P2pConfig, }; use std::{fmt::Debug, str::FromStr, sync::Arc}; @@ -50,5 +51,6 @@ where } }); - PeerManager::::new(Arc::clone(&config), conn, rx, tx_sync) + let p2p_config = Arc::new(P2pConfig::new()); + PeerManager::::new(Arc::clone(&config), p2p_config, conn, rx, tx_sync) } From 353a4c53014e4eccb2eb960991bdfb649040dbce Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 13 Jul 2022 23:36:52 +0200 Subject: [PATCH 19/30] Add comand line tests --- node/tests/cli.rs | 103 +++++++++++++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 33 deletions(-) diff --git a/node/tests/cli.rs b/node/tests/cli.rs index fe4d354598..d08eac3aab 100644 --- a/node/tests/cli.rs +++ b/node/tests/cli.rs @@ -13,18 +13,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::path::Path; +use std::{net::SocketAddr, path::Path, str::FromStr}; use assert_cmd::Command; +use common::chain::config::ChainType; use node::{NodeConfig, RunOptions}; const BIN_NAME: &str = env!("CARGO_BIN_EXE_node"); +const CONFIG_PATH: &str = concat!(env!("CARGO_TARGET_TMPDIR"), "/test_mintlayer.toml"); // This test is only needed because the node name ix hardcoded here, so if the name is changed we // get an error that is easy to understand. #[test] -fn path_is_correct() { +fn node_path_is_correct() { assert!(Path::new(BIN_NAME).is_file()); } @@ -33,42 +35,77 @@ fn no_args() { Command::new(BIN_NAME).assert().failure(); } -// TODO: config with default values. - #[test] -fn create_config() { - let config_path = concat!(env!("CARGO_TARGET_TMPDIR"), "/test_mintlayer.toml"); - let max_block_header_size = 100; - let max_block_size_from_txs = 200; - let max_block_size_from_smart_contracts = 300; +fn create_default_config() { + Command::new(BIN_NAME) + .arg("create-config") + .arg("--path") + .arg(CONFIG_PATH) + .assert() + .success(); + let options = RunOptions { + config_path: CONFIG_PATH.into(), + net: ChainType::Mainnet, + max_db_commit_attempts: None, + max_orphan_blocks: None, + p2p_addr: None, + p2p_ban_threshold: None, + p2p_timeout: None, + rpc_addr: None, + }; + let config = NodeConfig::read(options).unwrap(); + + assert_eq!(config.chainstate.max_db_commit_attempts, 10); + assert_eq!(config.chainstate.max_orphan_blocks, 512); + + assert_eq!(config.p2p.address, "/ip6/::1/tcp/3031"); + assert_eq!(config.p2p.ban_threshold, 100); + assert_eq!(config.p2p.timeout, 10); + assert_eq!( + config.rpc.address, + SocketAddr::from_str("127.0.0.1:3030").unwrap() + ); +} + +// Check that the config fields are overwritten by the run options. +#[test] +fn read_config_override_values() { Command::new(BIN_NAME) .arg("create-config") .arg("--path") - .arg(config_path) + .arg(CONFIG_PATH) .assert() .success(); - // let run_options = RunOptions { - // config_path: config_path.into(), - // max_block_header_size: Some(max_block_header_size), - // max_block_size_from_txs: Some(max_block_size_from_txs), - // max_block_size_from_smart_contracts: Some(max_block_size_from_smart_contracts), - // p2p_addr: None, - // rpc_addr: None, - // }; - // let config = NodeConfig::read(run_options).unwrap(); - todo!(); - todo!(); - // assert_eq!( - // config.chainstate.max_block_header_size, - // max_block_header_size - // ); - // assert_eq!( - // config.chainstate.max_block_size_from_txs, - // max_block_size_from_txs - // ); - // assert_eq!( - // config.chainstate.max_block_size_from_smart_contracts, - // max_block_size_from_smart_contracts - // ); + + let max_db_commit_attempts = 1; + let max_orphan_blocks = 2; + let p2p_addr = "address"; + let p2p_ban_threshold = 3; + let p2p_timeout = 10000; + let rpc_addr = SocketAddr::from_str("127.0.0.1:5432").unwrap(); + + let options = RunOptions { + config_path: CONFIG_PATH.into(), + 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()), + p2p_ban_threshold: Some(p2p_ban_threshold), + p2p_timeout: Some(p2p_timeout), + rpc_addr: Some(rpc_addr), + }; + let config = NodeConfig::read(options).unwrap(); + + assert_eq!( + config.chainstate.max_db_commit_attempts, + max_db_commit_attempts + ); + assert_eq!(config.chainstate.max_orphan_blocks, max_orphan_blocks); + + assert_eq!(config.p2p.address, p2p_addr); + assert_eq!(config.p2p.ban_threshold, p2p_ban_threshold); + assert_eq!(config.p2p.timeout, p2p_timeout); + + assert_eq!(config.rpc.address, rpc_addr); } From fb77d5ad0e52919faf2ae674a326a36c14fe1391 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 13 Jul 2022 23:41:53 +0200 Subject: [PATCH 20/30] Fix the rpc example --- rpc/examples/simple_server.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rpc/examples/simple_server.rs b/rpc/examples/simple_server.rs index c6f64f7a29..7e8aafd364 100644 --- a/rpc/examples/simple_server.rs +++ b/rpc/examples/simple_server.rs @@ -78,9 +78,10 @@ async fn main() -> anyhow::Result<()> { let mut app = subsystem::Manager::new("rpc-example"); app.install_signal_handlers(); let some_subsystem = app.add_subsystem("some_subsys", SomeSubsystem(0)); + let rpc_config = rpc::RpcConfig::new()?; let _rpc_subsystem = app.add_subsystem( "rpc", - rpc::Builder::new("127.0.0.1:3030".parse().expect("address parse error")) + rpc::Builder::new(rpc_config) .register(some_subsystem.clone().into_rpc()) .build() .await?, From c86991e2d4781c7a9fbe9c35c5dac693dc028d17 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 13 Jul 2022 23:55:29 +0200 Subject: [PATCH 21/30] Fix test node --- Cargo.lock | 1 + test/Cargo.toml | 1 + test/src/bin/test_node.rs | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index d7b7cceb13..80e00586c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2209,6 +2209,7 @@ dependencies = [ name = "mintlayer-test" version = "0.1.0" dependencies = [ + "common", "libtest-mimic", "node", "thiserror", diff --git a/test/Cargo.toml b/test/Cargo.toml index 4d97a914df..96468d744a 100644 --- a/test/Cargo.toml +++ b/test/Cargo.toml @@ -7,6 +7,7 @@ license = "MIT" [dependencies] node = { path = "../node" } +common = { path = "../common" } tokio = { version = "1.19", features = ['full'] } diff --git a/test/src/bin/test_node.rs b/test/src/bin/test_node.rs index c0bfe1faec..be06f6c12e 100644 --- a/test/src/bin/test_node.rs +++ b/test/src/bin/test_node.rs @@ -19,5 +19,7 @@ use std::env; async fn main() -> Result<(), node::Error> { let opts = node::Options::from_args(env::args_os()); node::init_logging(&opts); - node::run(opts).await + + let config = node::NodeConfig::new()?; + node::run(common::chain::config::ChainType, config).await } From d92e2347aecf0552311b1ac375c82d67d623ecf7 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Thu, 14 Jul 2022 09:35:46 +0200 Subject: [PATCH 22/30] Rvert/fix test node initialization --- node/src/main.rs | 30 ++++-------------------------- node/src/runner.rs | 39 ++++++++++++++++++++++++++++++--------- test/src/bin/test_node.rs | 4 +--- 3 files changed, 35 insertions(+), 38 deletions(-) diff --git a/node/src/main.rs b/node/src/main.rs index 00425577e1..b78568482a 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -15,33 +15,11 @@ //! Top-level node binary -use std::fs; - -use anyhow::{Context, Result}; - -use logging::log; -use node::{Command, NodeConfig, Options}; - -async fn run() -> Result<()> { - let opts = Options::from_args(std::env::args_os()); +async fn run() -> anyhow::Result<()> { + let opts = node::Options::from_args(std::env::args_os()); logging::init_logging(opts.log_path.as_ref()); - log::trace!("Command line options: {opts:?}"); - - match opts.command { - Command::CreateConfig { path } => { - let config = NodeConfig::new()?; - let config = toml::to_string(&config).context("Failed to serialize config")?; - log::trace!("Saving config to {path:?}\n: {config:#?}"); - fs::write(path, config).context("Failed to write config")?; - Ok(()) - } - Command::Run(options) => { - let chain_type = options.net; - let node_config = NodeConfig::read(options).context("Failed to initialize config")?; - log::trace!("Starting with the following config\n: {node_config:#?}"); - node::run(chain_type, node_config).await - } - } + logging::log::trace!("Command line options: {opts:?}"); + node::run(opts).await } #[tokio::main] diff --git a/node/src/runner.rs b/node/src/runner.rs index 0b3efcfaf1..cced2fcb7b 100644 --- a/node/src/runner.rs +++ b/node/src/runner.rs @@ -15,11 +15,19 @@ //! Node initialisation routine. -use crate::config::NodeConfig; +use std::{fs, sync::Arc}; + +use anyhow::{Context, Result}; + use chainstate::rpc::ChainstateRpcServer; use common::chain::config::ChainType; +use logging::log; use p2p::rpc::P2pRpcServer; -use std::sync::Arc; + +use crate::{ + config::NodeConfig, + options::{Command, Options}, +}; #[derive(Debug, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, thiserror::Error)] enum Error { @@ -31,7 +39,7 @@ enum Error { pub async fn initialize( chain_type: ChainType, node_config: NodeConfig, -) -> anyhow::Result { +) -> Result { // Initialize storage. let storage = chainstate_storage::Store::new_empty()?; @@ -85,12 +93,25 @@ pub async fn initialize( Ok(manager) } -/// Initialize and run the node -pub async fn run(chain_type: ChainType, node_config: NodeConfig) -> anyhow::Result<()> { - let manager = initialize(chain_type, node_config).await?; - - #[allow(clippy::unit_arg)] - Ok(manager.main().await) +/// Processes options and potentially runs the node. +pub async fn run(options: Options) -> Result<()> { + match options.command { + Command::CreateConfig { path } => { + let config = NodeConfig::new()?; + let config = toml::to_string(&config).context("Failed to serialize config")?; + log::trace!("Saving config to {path:?}\n: {config:#?}"); + fs::write(path, config).context("Failed to write config")?; + Ok(()) + } + Command::Run(options) => { + let chain_type = options.net; + let node_config = NodeConfig::read(options).context("Failed to initialize config")?; + log::trace!("Starting with the following config\n: {node_config:#?}"); + let manager = initialize(chain_type, node_config).await?; + #[allow(clippy::unit_arg)] + Ok(manager.main().await) + } + } } #[rpc::rpc(server, namespace = "node")] diff --git a/test/src/bin/test_node.rs b/test/src/bin/test_node.rs index be06f6c12e..c0bfe1faec 100644 --- a/test/src/bin/test_node.rs +++ b/test/src/bin/test_node.rs @@ -19,7 +19,5 @@ use std::env; async fn main() -> Result<(), node::Error> { let opts = node::Options::from_args(env::args_os()); node::init_logging(&opts); - - let config = node::NodeConfig::new()?; - node::run(common::chain::config::ChainType, config).await + node::run(opts).await } From 8165b6bde4e5901d46cf07eed540be9bc0bcce42 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Thu, 14 Jul 2022 11:55:28 +0200 Subject: [PATCH 23/30] Use run command to start node in the functional tests --- test/functional/test_framework/test_node.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 324455431e..eeeea654f1 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -104,6 +104,7 @@ def __init__(self, i, datadir, *, chain, rpchost, timewait, timeout_factor, bitc # spam debug.log. self.args = [ self.binary, + "run" "--net=regtest", "--rpc-addr={}".format(rpc_addr), "--p2p-addr={}".format(p2p_addr), From 06147c5187abe6402d1f6eb4049e3b54c077c361 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Thu, 14 Jul 2022 13:00:46 +0200 Subject: [PATCH 24/30] Add config to the functional tests --- node/src/config.rs | 3 ++- test/functional/test_framework/test_config.toml | 11 +++++++++++ test/functional/test_framework/test_node.py | 5 ++++- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 test/functional/test_framework/test_config.toml diff --git a/node/src/config.rs b/node/src/config.rs index a54e6970d3..37e44aa79d 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -51,7 +51,8 @@ impl NodeConfig { /// Reads a configuration from the path specified in options and overrides the provided /// parameters. pub fn read(options: RunOptions) -> Result { - let config = fs::read_to_string(&options.config_path).context("Failed to read config")?; + let config = fs::read_to_string(&options.config_path) + .with_context(|| format!("Failed to read '{:?}' config", options.config_path))?; let mut config: NodeConfig = toml::from_str(&config).context("Failed to deserialize config")?; diff --git a/test/functional/test_framework/test_config.toml b/test/functional/test_framework/test_config.toml new file mode 100644 index 0000000000..4789a35dcf --- /dev/null +++ b/test/functional/test_framework/test_config.toml @@ -0,0 +1,11 @@ +[chainstate] +max_db_commit_attempts = 10 +max_orphan_blocks = 512 + +[p2p] +address = "/ip6/::1/tcp/3031" +ban_threshold = 100 +timeout = 10 + +[rpc] +address = "127.0.0.1:3030" diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index eeeea654f1..dd9eb07ad7 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -99,12 +99,15 @@ def __init__(self, i, datadir, *, chain, rpchost, timewait, timeout_factor, bitc rpc_addr = self.init_rpc_url.split("http://")[-1].split('@')[-1] p2p_addr = p2p_url(self.index) + config_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_config.toml") + # Configuration for logging is set as command-line args rather than in the bitcoin.conf file. # This means that starting a bitcoind using the temp dir to debug a failed test won't # spam debug.log. self.args = [ self.binary, - "run" + "run", + "--config-path={}".format(config_path), "--net=regtest", "--rpc-addr={}".format(rpc_addr), "--p2p-addr={}".format(p2p_addr), From 839481c877d2ffe4deb0a5f2f3ed6f939476d3d1 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Thu, 14 Jul 2022 14:09:03 +0200 Subject: [PATCH 25/30] Remove ports from the chain config --- common/src/chain/config/builder.rs | 10 ---------- common/src/chain/config/mod.rs | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/common/src/chain/config/builder.rs b/common/src/chain/config/builder.rs index 1f4962c725..a0b7f71952 100644 --- a/common/src/chain/config/builder.rs +++ b/common/src/chain/config/builder.rs @@ -85,8 +85,6 @@ impl GenesisBlockInit { pub struct Builder { chain_type: ChainType, address_prefix: String, - rpc_port: u16, - p2p_port: u16, magic_bytes: [u8; 4], blockreward_maturity: BlockDistance, max_future_block_time_offset: Duration, @@ -116,8 +114,6 @@ impl Builder { max_block_size_with_smart_contracts: super::MAX_BLOCK_CONTRACTS_SIZE, max_future_block_time_offset: super::DEFAULT_MAX_FUTURE_BLOCK_TIME_OFFSET, target_block_spacing: super::DEFAULT_TARGET_BLOCK_SPACING, - p2p_port: 8978, - rpc_port: 15234, genesis_block: chain_type.default_genesis_init(), emission_schedule: EmissionScheduleInit::Mainnet, net_upgrades: chain_type.default_net_upgrades(), @@ -145,8 +141,6 @@ impl Builder { max_block_size_with_smart_contracts, max_future_block_time_offset, target_block_spacing, - p2p_port, - rpc_port, genesis_block, emission_schedule, net_upgrades, @@ -180,8 +174,6 @@ impl Builder { max_block_size_with_smart_contracts, max_future_block_time_offset, target_block_spacing, - p2p_port, - rpc_port, genesis_block_id: genesis_block.get_id(), genesis_block, height_checkpoint_data: BTreeMap::new(), @@ -207,8 +199,6 @@ macro_rules! builder_method { impl Builder { builder_method!(chain_type: ChainType); builder_method!(address_prefix: String); - builder_method!(rpc_port: u16); - builder_method!(p2p_port: u16); builder_method!(magic_bytes: [u8; 4]); builder_method!(blockreward_maturity: BlockDistance); builder_method!(max_future_block_time_offset: Duration); diff --git a/common/src/chain/config/mod.rs b/common/src/chain/config/mod.rs index 61c33b8b94..86ec3605d7 100644 --- a/common/src/chain/config/mod.rs +++ b/common/src/chain/config/mod.rs @@ -84,8 +84,6 @@ impl ChainType { pub struct ChainConfig { chain_type: ChainType, address_prefix: String, - rpc_port: u16, - p2p_port: u16, height_checkpoint_data: BTreeMap>, net_upgrades: NetUpgrades, magic_bytes: [u8; 4], @@ -135,14 +133,6 @@ impl ChainConfig { &self.net_upgrades } - pub fn p2p_port(&self) -> u16 { - self.p2p_port - } - - pub fn rpc_port(&self) -> u16 { - self.rpc_port - } - pub fn height_checkpoints(&self) -> &BTreeMap> { &self.height_checkpoint_data } From 80a8d9e7f234dc3f8329c977dc4d88e6f1292477 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Thu, 14 Jul 2022 22:33:09 +0200 Subject: [PATCH 26/30] Rename p2p config parameters --- node/src/config.rs | 6 +++--- node/src/options.rs | 2 +- node/tests/cli.rs | 12 ++++++------ p2p/src/config.rs | 10 +++++----- p2p/src/lib.rs | 6 +++--- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/node/src/config.rs b/node/src/config.rs index 37e44aa79d..143522f70f 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -66,13 +66,13 @@ impl NodeConfig { // P2p options. if let Some(address) = options.p2p_addr { - config.p2p.address = address; + config.p2p.bind_address = address; } if let Some(threshold) = options.p2p_ban_threshold { config.p2p.ban_threshold = threshold; } - if let Some(timeout) = options.p2p_timeout { - config.p2p.timeout = timeout; + if let Some(timeout) = options.p2p_outbound_connection_timeout { + config.p2p.outbound_connection_timeout = timeout; } // Rpc options. diff --git a/node/src/options.rs b/node/src/options.rs index a068ec8560..cf54ac6206 100644 --- a/node/src/options.rs +++ b/node/src/options.rs @@ -77,7 +77,7 @@ pub struct RunOptions { /// The p2p timeout value in seconds. #[clap(long)] - pub p2p_timeout: Option, + pub p2p_outbound_connection_timeout: Option, /// Address to bind RPC to. #[clap(long, value_name = "ADDR")] diff --git a/node/tests/cli.rs b/node/tests/cli.rs index d08eac3aab..9aafd04187 100644 --- a/node/tests/cli.rs +++ b/node/tests/cli.rs @@ -50,7 +50,7 @@ fn create_default_config() { max_orphan_blocks: None, p2p_addr: None, p2p_ban_threshold: None, - p2p_timeout: None, + p2p_outbound_connection_timeout: None, rpc_addr: None, }; let config = NodeConfig::read(options).unwrap(); @@ -58,9 +58,9 @@ fn create_default_config() { assert_eq!(config.chainstate.max_db_commit_attempts, 10); assert_eq!(config.chainstate.max_orphan_blocks, 512); - assert_eq!(config.p2p.address, "/ip6/::1/tcp/3031"); + assert_eq!(config.p2p.bind_address, "/ip6/::1/tcp/3031"); assert_eq!(config.p2p.ban_threshold, 100); - assert_eq!(config.p2p.timeout, 10); + assert_eq!(config.p2p.outbound_connection_timeout, 10); assert_eq!( config.rpc.address, @@ -92,7 +92,7 @@ fn read_config_override_values() { max_orphan_blocks: Some(max_orphan_blocks), p2p_addr: Some(p2p_addr.into()), p2p_ban_threshold: Some(p2p_ban_threshold), - p2p_timeout: Some(p2p_timeout), + p2p_outbound_connection_timeout: Some(p2p_timeout), rpc_addr: Some(rpc_addr), }; let config = NodeConfig::read(options).unwrap(); @@ -103,9 +103,9 @@ fn read_config_override_values() { ); assert_eq!(config.chainstate.max_orphan_blocks, max_orphan_blocks); - assert_eq!(config.p2p.address, p2p_addr); + assert_eq!(config.p2p.bind_address, p2p_addr); assert_eq!(config.p2p.ban_threshold, p2p_ban_threshold); - assert_eq!(config.p2p.timeout, p2p_timeout); + assert_eq!(config.p2p.outbound_connection_timeout, p2p_timeout); assert_eq!(config.rpc.address, rpc_addr); } diff --git a/p2p/src/config.rs b/p2p/src/config.rs index 05efa11434..994869d84e 100644 --- a/p2p/src/config.rs +++ b/p2p/src/config.rs @@ -19,20 +19,20 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] pub struct P2pConfig { /// Address to bind P2P to. - pub address: String, + pub bind_address: String, /// The score threshold after which a peer is baned. pub ban_threshold: u32, - /// The timeout value in seconds. - pub timeout: u64, + /// The outbound connection timeout value in seconds. + pub outbound_connection_timeout: u64, } impl P2pConfig { /// Creates a new p2p configuration instance. pub fn new() -> Self { Self { - address: "/ip6/::1/tcp/3031".into(), + bind_address: "/ip6/::1/tcp/3031".into(), ban_threshold: 100, - timeout: 10, + outbound_connection_timeout: 10, } } } diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index 2d77c785e0..8819e567ef 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -161,14 +161,14 @@ where { let p2p_config = Arc::new(p2p_config); let (conn, pubsub, sync) = T::start( - p2p_config.address.parse::().map_err(|_| { + p2p_config.bind_address.parse::().map_err(|_| { P2pError::ConversionError(ConversionError::InvalidAddress( - p2p_config.address.clone(), + p2p_config.bind_address.clone(), )) })?, &[], Arc::clone(&chain_config), - Duration::from_secs(p2p_config.timeout), + Duration::from_secs(p2p_config.outbound_connection_timeout), ) .await?; From aa99255886cc9e472ae0b0fd2bb68d0a5f0a6826 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Fri, 15 Jul 2022 09:33:45 +0200 Subject: [PATCH 27/30] Update functional tests config --- test/functional/test_framework/test_config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/test_framework/test_config.toml b/test/functional/test_framework/test_config.toml index 4789a35dcf..dce012057b 100644 --- a/test/functional/test_framework/test_config.toml +++ b/test/functional/test_framework/test_config.toml @@ -3,7 +3,7 @@ max_db_commit_attempts = 10 max_orphan_blocks = 512 [p2p] -address = "/ip6/::1/tcp/3031" +bind_address = "/ip6/::1/tcp/3031" ban_threshold = 100 timeout = 10 From aeaa5b4b23713f8a35ccea1348eb6a8a2b7c0f36 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Fri, 15 Jul 2022 11:04:01 +0200 Subject: [PATCH 28/30] Node config initialization refactoring --- node/src/config.rs | 87 ++++++++++++------- node/src/runner.rs | 5 +- node/tests/cli.rs | 4 +- .../test_framework/test_config.toml | 2 +- 4 files changed, 63 insertions(+), 35 deletions(-) diff --git a/node/src/config.rs b/node/src/config.rs index 143522f70f..295f20ec78 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -50,36 +50,65 @@ impl NodeConfig { /// Reads a configuration from the path specified in options and overrides the provided /// parameters. - pub fn read(options: RunOptions) -> Result { + pub fn read(options: &RunOptions) -> Result { let config = fs::read_to_string(&options.config_path) .with_context(|| format!("Failed to read '{:?}' config", options.config_path))?; - let mut config: NodeConfig = - toml::from_str(&config).context("Failed to deserialize config")?; - - // Chainstate options. - if let Some(attempts) = options.max_db_commit_attempts { - config.chainstate.max_db_commit_attempts = attempts; - } - if let Some(max_orphans) = options.max_orphan_blocks { - config.chainstate.max_orphan_blocks = max_orphans; - } - - // P2p options. - if let Some(address) = options.p2p_addr { - config.p2p.bind_address = address; - } - if let Some(threshold) = options.p2p_ban_threshold { - config.p2p.ban_threshold = threshold; - } - if let Some(timeout) = options.p2p_outbound_connection_timeout { - config.p2p.outbound_connection_timeout = timeout; - } - - // Rpc options. - if let Some(address) = options.rpc_addr { - config.rpc.address = address; - } - - Ok(config) + let NodeConfig { + chainstate, + p2p, + rpc, + } = toml::from_str(&config).context("Failed to deserialize config")?; + + let chainstate = chainstate_config(chainstate, options); + let p2p = p2p_config(p2p, options); + let rpc = rpc_config(rpc, options); + + Ok(Self { + chainstate, + p2p, + rpc, + }) + } +} + +fn chainstate_config(config: ChainstateConfig, options: &RunOptions) -> ChainstateConfig { + let ChainstateConfig { + max_db_commit_attempts, + max_orphan_blocks, + } = config; + + let max_db_commit_attempts = options.max_db_commit_attempts.unwrap_or(max_db_commit_attempts); + let max_orphan_blocks = options.max_orphan_blocks.unwrap_or(max_orphan_blocks); + + ChainstateConfig { + max_db_commit_attempts, + max_orphan_blocks, + } +} + +fn p2p_config(config: P2pConfig, options: &RunOptions) -> P2pConfig { + let P2pConfig { + bind_address, + ban_threshold, + outbound_connection_timeout, + } = config; + + let bind_address = options.p2p_addr.clone().unwrap_or(bind_address); + let ban_threshold = options.p2p_ban_threshold.unwrap_or(ban_threshold); + let outbound_connection_timeout = + options.p2p_outbound_connection_timeout.unwrap_or(outbound_connection_timeout); + + P2pConfig { + bind_address, + ban_threshold, + outbound_connection_timeout, } } + +fn rpc_config(config: RpcConfig, options: &RunOptions) -> RpcConfig { + let RpcConfig { address } = config; + + let address = options.rpc_addr.unwrap_or(address); + + RpcConfig { address } +} diff --git a/node/src/runner.rs b/node/src/runner.rs index cced2fcb7b..9b39f4c304 100644 --- a/node/src/runner.rs +++ b/node/src/runner.rs @@ -104,10 +104,9 @@ pub async fn run(options: Options) -> Result<()> { Ok(()) } Command::Run(options) => { - let chain_type = options.net; - let node_config = NodeConfig::read(options).context("Failed to initialize config")?; + let node_config = NodeConfig::read(&options).context("Failed to initialize config")?; log::trace!("Starting with the following config\n: {node_config:#?}"); - let manager = initialize(chain_type, node_config).await?; + let manager = initialize(options.net, node_config).await?; #[allow(clippy::unit_arg)] Ok(manager.main().await) } diff --git a/node/tests/cli.rs b/node/tests/cli.rs index 9aafd04187..dd72278dcc 100644 --- a/node/tests/cli.rs +++ b/node/tests/cli.rs @@ -53,7 +53,7 @@ fn create_default_config() { p2p_outbound_connection_timeout: None, rpc_addr: None, }; - let config = NodeConfig::read(options).unwrap(); + let config = NodeConfig::read(&options).unwrap(); assert_eq!(config.chainstate.max_db_commit_attempts, 10); assert_eq!(config.chainstate.max_orphan_blocks, 512); @@ -95,7 +95,7 @@ fn read_config_override_values() { p2p_outbound_connection_timeout: Some(p2p_timeout), rpc_addr: Some(rpc_addr), }; - let config = NodeConfig::read(options).unwrap(); + let config = NodeConfig::read(&options).unwrap(); assert_eq!( config.chainstate.max_db_commit_attempts, diff --git a/test/functional/test_framework/test_config.toml b/test/functional/test_framework/test_config.toml index dce012057b..9bf1103013 100644 --- a/test/functional/test_framework/test_config.toml +++ b/test/functional/test_framework/test_config.toml @@ -5,7 +5,7 @@ max_orphan_blocks = 512 [p2p] bind_address = "/ip6/::1/tcp/3031" ban_threshold = 100 -timeout = 10 +outbound_connection_timeout = 10 [rpc] address = "127.0.0.1:3030" From e204cbc4c52b38cc620e3d4af70b4ac670007f57 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Fri, 15 Jul 2022 12:25:16 +0200 Subject: [PATCH 29/30] Apply review comments --- node/src/config.rs | 8 ++++---- node/tests/cli.rs | 4 ++-- p2p/src/config.rs | 2 +- rpc/src/config.rs | 4 ++-- rpc/src/lib.rs | 4 ++-- test/functional/test_framework/test_config.toml | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/node/src/config.rs b/node/src/config.rs index 295f20ec78..5be15e3d88 100644 --- a/node/src/config.rs +++ b/node/src/config.rs @@ -57,7 +57,7 @@ impl NodeConfig { chainstate, p2p, rpc, - } = toml::from_str(&config).context("Failed to deserialize config")?; + } = toml::from_str(&config).context("Failed to parse config")?; let chainstate = chainstate_config(chainstate, options); let p2p = p2p_config(p2p, options); @@ -106,9 +106,9 @@ fn p2p_config(config: P2pConfig, options: &RunOptions) -> P2pConfig { } fn rpc_config(config: RpcConfig, options: &RunOptions) -> RpcConfig { - let RpcConfig { address } = config; + let RpcConfig { bind_address } = config; - let address = options.rpc_addr.unwrap_or(address); + let bind_address = options.rpc_addr.unwrap_or(bind_address); - RpcConfig { address } + RpcConfig { bind_address } } diff --git a/node/tests/cli.rs b/node/tests/cli.rs index dd72278dcc..23722b1adc 100644 --- a/node/tests/cli.rs +++ b/node/tests/cli.rs @@ -63,7 +63,7 @@ fn create_default_config() { assert_eq!(config.p2p.outbound_connection_timeout, 10); assert_eq!( - config.rpc.address, + config.rpc.bind_address, SocketAddr::from_str("127.0.0.1:3030").unwrap() ); } @@ -107,5 +107,5 @@ fn read_config_override_values() { assert_eq!(config.p2p.ban_threshold, p2p_ban_threshold); assert_eq!(config.p2p.outbound_connection_timeout, p2p_timeout); - assert_eq!(config.rpc.address, rpc_addr); + assert_eq!(config.rpc.bind_address, rpc_addr); } diff --git a/p2p/src/config.rs b/p2p/src/config.rs index 994869d84e..1bdb790a33 100644 --- a/p2p/src/config.rs +++ b/p2p/src/config.rs @@ -20,7 +20,7 @@ use serde::{Deserialize, Serialize}; pub struct P2pConfig { /// Address to bind P2P to. pub bind_address: String, - /// The score threshold after which a peer is baned. + /// The score threshold after which a peer is banned. pub ban_threshold: u32, /// The outbound connection timeout value in seconds. pub outbound_connection_timeout: u64, diff --git a/rpc/src/config.rs b/rpc/src/config.rs index 5aa3019c55..25712bada2 100644 --- a/rpc/src/config.rs +++ b/rpc/src/config.rs @@ -22,14 +22,14 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] pub struct RpcConfig { /// Address to bind RPC to. - pub address: SocketAddr, + pub bind_address: SocketAddr, } impl RpcConfig { /// Creates a new rpc configuration instance. pub fn new() -> Result { Ok(Self { - address: SocketAddr::from_str("127.0.0.1:3030")?, + bind_address: SocketAddr::from_str("127.0.0.1:3030")?, }) } } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 54c77bf534..b05faad420 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -57,7 +57,7 @@ impl Builder { /// New builder pre-populated with RPC info methods pub fn new(rpc_config: RpcConfig) -> Self { - Self::new_empty(rpc_config.address).register(RpcInfo.into_rpc()) + Self::new_empty(rpc_config.bind_address).register(RpcInfo.into_rpc()) } /// Add methods handlers to the RPC server @@ -132,7 +132,7 @@ mod tests { #[tokio::test] async fn rpc_server() -> anyhow::Result<()> { let rpc_config = RpcConfig { - address: "127.0.0.1:3030".parse().unwrap(), + bind_address: "127.0.0.1:3030".parse().unwrap(), }; let rpc = Builder::new(rpc_config).register(SubsystemRpcImpl.into_rpc()).build().await?; diff --git a/test/functional/test_framework/test_config.toml b/test/functional/test_framework/test_config.toml index 9bf1103013..d257248586 100644 --- a/test/functional/test_framework/test_config.toml +++ b/test/functional/test_framework/test_config.toml @@ -8,4 +8,4 @@ ban_threshold = 100 outbound_connection_timeout = 10 [rpc] -address = "127.0.0.1:3030" +bind_address = "127.0.0.1:3030" From 809e9e71c4674fe87e1324a4e7e40ce0bd1f9be5 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Mon, 18 Jul 2022 11:52:01 +0200 Subject: [PATCH 30/30] Apply review comments (typos and better description) --- chainstate/src/detail/block_index_history_iter.rs | 4 ++-- node/src/options.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/chainstate/src/detail/block_index_history_iter.rs b/chainstate/src/detail/block_index_history_iter.rs index f16cc98176..4ac1b52103 100644 --- a/chainstate/src/detail/block_index_history_iter.rs +++ b/chainstate/src/detail/block_index_history_iter.rs @@ -83,11 +83,11 @@ mod tests { fn history_iteration() { common::concurrency::model(|| { let chain_config = Arc::new(create_unit_test_config()); - let chainstte_config = ChainstateConfig::new(); + let chainstate_config = ChainstateConfig::new(); let storage = Store::new_empty().unwrap(); let mut chainstate = Chainstate::new( chain_config.clone(), - chainstte_config, + chainstate_config, storage, None, Default::default(), diff --git a/node/src/options.rs b/node/src/options.rs index cf54ac6206..0524099f70 100644 --- a/node/src/options.rs +++ b/node/src/options.rs @@ -59,11 +59,11 @@ pub struct RunOptions { #[clap(long, possible_values = ChainType::VARIANTS, default_value = "mainnet")] pub net: ChainType, - /// Blockchain type. + /// The number of maximum attempts to process a block. #[clap(long)] pub max_db_commit_attempts: Option, - /// The maximum capacity of the orphan blocks pool. + /// The maximum capacity of the orphan blocks pool in blocks. #[clap(long)] pub max_orphan_blocks: Option,