Skip to content

Commit

Permalink
feat(cli): split sub-command run to init and run
Browse files Browse the repository at this point in the history
  • Loading branch information
yangby-cryptape committed Sep 4, 2023
1 parent c86f065 commit a4221eb
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 121 deletions.
44 changes: 44 additions & 0 deletions core/cli/src/args/init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use clap::Parser;

use common_config_parser::types::{spec::ChainSpec, Config};
use common_version::Version;

use crate::{
error::{Error, Result},
utils,
};

#[derive(Parser, Debug)]
#[command(about = "Initialize new axon data directory")]
pub struct InitArgs {
#[arg(
short = 'c',
long = "config",
value_name = "CONFIG_FILE",
help = "File path of client configurations."
)]
pub config: Config,
#[arg(
short = 's',
long = "chain-spec",
value_name = "CHAIN_SPEC_FILE",
help = "File path of chain spec."
)]
pub spec: ChainSpec,
}

impl InitArgs {
pub(crate) fn execute(self, kernel_version: Version) -> Result<()> {
let Self { config, spec } = self;
let genesis = spec.genesis.build_rich_block();

utils::check_version(
&config.data_path_for_version(),
&kernel_version,
utils::latest_compatible_version(),
)?;
utils::register_log(&config);

core_run::init(config, spec, genesis).map_err(Error::Running)
}
}
1 change: 1 addition & 0 deletions core/cli/src/args/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub(crate) mod init;
pub(crate) mod run;
21 changes: 6 additions & 15 deletions core/cli/src/args/run.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use clap::Parser;

use common_config_parser::types::{spec::ChainSpec, Config};
use common_config_parser::types::Config;
use common_version::Version;
use core_run::{Axon, KeyProvider};
use core_run::KeyProvider;

use crate::{
error::{Error, Result},
utils,
};

#[derive(Parser, Debug)]
#[command(about = "Run axon process")]
#[command(about = "Run axon service")]
pub struct RunArgs {
#[arg(
short = 'c',
Expand All @@ -19,13 +19,6 @@ pub struct RunArgs {
help = "File path of client configurations."
)]
pub config: Config,
#[arg(
short = 's',
long = "chain-spec",
value_name = "CHAIN_SPEC_FILE",
help = "File path of chain spec."
)]
pub spec: ChainSpec,
}

impl RunArgs {
Expand All @@ -35,8 +28,7 @@ impl RunArgs {
kernel_version: Version,
key_provider: Option<K>,
) -> Result<()> {
let Self { config, spec } = self;
let genesis = spec.genesis.build_rich_block();
let Self { config } = self;

utils::check_version(
&config.data_path_for_version(),
Expand All @@ -45,8 +37,7 @@ impl RunArgs {
)?;
utils::register_log(&config);

Axon::new(application_version.to_string(), config, spec, genesis)
.run(key_provider)
.map_err(Error::Running)
let version = application_version.to_string();
core_run::run(version, config, key_provider).map_err(Error::Running)
}
}
4 changes: 3 additions & 1 deletion core/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mod args;
mod error;
pub(crate) mod utils;

pub use args::run::RunArgs;
pub use args::{init::InitArgs, run::RunArgs};
pub use error::{CheckingVersionError, Error, Result};

use clap::{CommandFactory as _, FromArgMatches as _, Parser, Subcommand};
Expand All @@ -19,6 +19,7 @@ struct Cli {

#[derive(Subcommand, Debug)]
enum Commands {
Init(InitArgs),
Run(RunArgs),
}

Expand Down Expand Up @@ -57,6 +58,7 @@ impl AxonCli {
inner: cli,
} = self;
match cli.command {
Commands::Init(args) => args.execute(kernel_version),
Commands::Run(args) => args.execute(application_version, kernel_version, key_provider),
}
}
Expand Down
25 changes: 18 additions & 7 deletions core/db/src/rocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,22 @@ pub struct RocksAdapter {
}

impl RocksAdapter {
/// Create a new RocksDB or load an already existed RocksDB.
pub fn new<P: AsRef<Path>>(path: P, config: ConfigRocksDB) -> ProtocolResult<Self> {
if !path.as_ref().is_dir() {
Self::open_internal(path, config, true)
}

/// Open an already existed RocksDB, or return error if it doesn't exist.
pub fn open<P: AsRef<Path>>(path: P, config: ConfigRocksDB) -> ProtocolResult<Self> {
Self::open_internal(path, config, false)
}

fn open_internal<P: AsRef<Path>>(
path: P,
config: ConfigRocksDB,
allow_missing: bool,
) -> ProtocolResult<Self> {
if allow_missing && !path.as_ref().is_dir() {
fs::create_dir_all(&path).map_err(RocksDBError::CreateDB)?;
}

Expand Down Expand Up @@ -66,15 +80,12 @@ impl RocksAdapter {
(opts, cf_descriptors)
};

opts.create_if_missing(true);
if allow_missing {
opts.create_if_missing(true);
}
opts.create_missing_column_families(true);
opts.set_max_open_files(config.max_open_files);

// let tmp_db = DB::list_cf(&opts, path).map_err(RocksDBError::from)?;
// if tmp_db.len() != cf_descriptors.len() {
// opts.create_missing_column_families(true);
// }

let db =
DB::open_cf_descriptors(&opts, path, cf_descriptors).map_err(RocksDBError::from)?;

Expand Down
2 changes: 1 addition & 1 deletion core/run/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ rlp = "0.5"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
tempfile = "3.6"
toml = "0.7"

common-apm = { path = "../../common/apm" }
Expand All @@ -38,6 +37,7 @@ jemallocator = { version = "0.5", features = ["profiling", "stats", "unprefixed_

[dev-dependencies]
clap = "4.3"
tempfile = "3.6"

[features]
jemalloc = ["dep:jemallocator", "dep:jemalloc-ctl", "dep:common-memory-tracker"]
8 changes: 7 additions & 1 deletion core/run/src/components/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,15 @@ impl DatabaseGroup {
pub(crate) fn new<P: AsRef<Path>>(
config: &ConfigRocksDB,
rocksdb_path: P,
is_first_run: bool,
triedb_cache_size: usize,
) -> ProtocolResult<Self> {
let adapter = Arc::new(RocksAdapter::new(rocksdb_path, config.clone())?);
let adapter_inner = if is_first_run {
RocksAdapter::new(rocksdb_path, config.clone())
} else {
RocksAdapter::open(rocksdb_path, config.clone())
}?;
let adapter = Arc::new(adapter_inner);
let inner_db = adapter.inner_db();
let trie_db = Arc::new(RocksTrieDB::new_evm(adapter.inner_db(), triedb_cache_size));
let storage = Arc::new(ImplStorage::new(adapter, config.cache_size));
Expand Down
159 changes: 63 additions & 96 deletions core/run/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{collections::HashMap, sync::Arc, time::Duration};

use common_apm::metrics::mempool::{MEMPOOL_CO_QUEUE_LEN, MEMPOOL_LEN_GAUGE};
use common_config_parser::types::spec::{ChainSpec, InitialAccount};
use common_config_parser::types::{Config, ConfigMempool, ConfigRocksDB};
use common_config_parser::types::{Config, ConfigMempool};
use common_crypto::{BlsPrivateKey, BlsPublicKey, Secp256k1, Secp256k1PrivateKey, ToPublicKey};

use protocol::tokio::{
Expand Down Expand Up @@ -48,71 +48,65 @@ use components::{
pub use error::MainError;
use key_provider::KeyP;

#[derive(Debug)]
pub struct Axon {
version: String,
config: Config,
spec: ChainSpec,
genesis: RichBlock,
}

impl Axon {
pub fn new(version: String, config: Config, spec: ChainSpec, genesis: RichBlock) -> Axon {
Axon {
version,
config,
spec,
genesis,
}
pub fn init(config: Config, spec: ChainSpec, genesis: RichBlock) -> ProtocolResult<()> {
let path_rocksdb = config.data_path_for_rocksdb();
if path_rocksdb.exists() {
let msg = format!("Data directory {} already exists.", path_rocksdb.display());
return Err(MainError::Other(msg).into());
}

pub fn run<K: KeyProvider>(self, key_provider: Option<K>) -> ProtocolResult<()> {
let Self {
version,
config,
spec,
genesis,
} = self;

let rt = RuntimeBuilder::new_multi_thread()
.enable_all()
.build()
.expect("new tokio runtime");

rt.block_on(async move {
let db_group = DatabaseGroup::new(
&config.rocksdb,
config.data_path_for_rocksdb(),
config.executor.triedb_cache_size,
)?;
if let Some(loaded_genesis) = db_group.storage().try_load_genesis().await? {
log::info!("Check genesis block.");
let genesis = execute_genesis_temporarily(
genesis,
spec,
&config.rocksdb,
config.executor.triedb_cache_size,
)
.await?;
if genesis.block != loaded_genesis {
let err_msg = format!(
"The user provided genesis (hash: {:#x}) is NOT \
the same as the genesis in storage (hash: {:#x})",
genesis.block.hash(),
loaded_genesis.hash()
);
return Err(MainError::Other(err_msg).into());
}
} else {
log::info!("Initialize genesis block.");
let _genesis = execute_genesis(genesis, spec, &db_group).await?;
}
start(version, config, key_provider, &db_group).await
})?;
rt.shutdown_timeout(std::time::Duration::from_secs(1));
let rt = RuntimeBuilder::new_multi_thread()
.enable_all()
.build()
.expect("new tokio runtime");

rt.block_on(async move {
log::info!("Load databases.");
let db_group = DatabaseGroup::new(
&config.rocksdb,
path_rocksdb,
true,
config.executor.triedb_cache_size,
)?;
log::info!("Initialize genesis block.");
execute_genesis(genesis, spec, &db_group).await
})?;

Ok(())
Ok(())
}

pub fn run<K: KeyProvider>(
version: String,
config: Config,
key_provider: Option<K>,
) -> ProtocolResult<()> {
let path_rocksdb = config.data_path_for_rocksdb();
if !path_rocksdb.exists() {
let msg = format!(
"Data directory {} doesn't exist, please initialize it before run.",
path_rocksdb.display()
);
return Err(MainError::Other(msg).into());
}
let rt = RuntimeBuilder::new_multi_thread()
.enable_all()
.build()
.expect("new tokio runtime");

rt.block_on(async move {
log::info!("Load databases.");
let db_group = DatabaseGroup::new(
&config.rocksdb,
path_rocksdb,
false,
config.executor.triedb_cache_size,
)?;
log::info!("Start all services.");
start(version, config, key_provider, &db_group).await
})?;
rt.shutdown_timeout(std::time::Duration::from_secs(1));

Ok(())
}

async fn start<K: KeyProvider>(
Expand Down Expand Up @@ -164,16 +158,14 @@ async fn start<K: KeyProvider>(
let txs_wal = Arc::new(SignedTxsWAL::new(txs_wal_path));

// Init system contract
if current_block.header.number != 0 {
let mut backend = AxonExecutorApplyAdapter::from_root(
current_block.header.state_root,
Arc::clone(&trie_db),
Arc::clone(&storage),
Proposal::new_without_state_root(&current_block.header).into(),
)?;
let mut backend = AxonExecutorApplyAdapter::from_root(
current_block.header.state_root,
Arc::clone(&trie_db),
Arc::clone(&storage),
Proposal::new_without_state_root(&current_block.header).into(),
)?;

system_contract::init(inner_db, &mut backend);
}
system_contract::init(inner_db, &mut backend);

// Init mempool and recover signed transactions with the current block number
let current_stxs = txs_wal.load_by_number(current_block.header.number + 1);
Expand Down Expand Up @@ -451,31 +443,6 @@ async fn execute_genesis(
Ok(partial_genesis)
}

async fn execute_genesis_temporarily(
mut partial_genesis: RichBlock,
spec: ChainSpec,
config: &ConfigRocksDB,
triedb_cache_size: usize,
) -> ProtocolResult<RichBlock> {
let tmp_dir = tempfile::tempdir().map_err(|err| {
let err_msg = format!("failed to create temporary directory since {err:?}");
MainError::Other(err_msg)
})?;
let path_block = tmp_dir.path().join("block");

let db_group = DatabaseGroup::new(config, path_block, triedb_cache_size)?;

let resp = execute_transactions(&partial_genesis, &db_group, &spec.accounts)?;

partial_genesis.block.header.state_root = resp.state_root;
partial_genesis.block.header.receipts_root = resp.receipt_root;

log::info!("The genesis block is executed {:?}", partial_genesis.block);
log::info!("Response for genesis is {:?}", resp);

Ok(partial_genesis)
}

fn execute_transactions(
rich: &RichBlock,
db_group: &DatabaseGroup,
Expand Down
Loading

0 comments on commit a4221eb

Please sign in to comment.