Skip to content

Commit

Permalink
[cli] implement genesis cmd (#1828)
Browse files Browse the repository at this point in the history
* [cli] implement genesis cmd

* nursery support custom chain
  • Loading branch information
jolestar authored Jun 6, 2024
1 parent 27aed78 commit 41cef59
Show file tree
Hide file tree
Showing 17 changed files with 196 additions and 117 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

14 changes: 7 additions & 7 deletions crates/rooch-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,20 @@ pub fn get_rooch_config_dir() -> Result<PathBuf, anyhow::Error> {
}

pub static R_OPT_NET_HELP: &str = r#"Chain Network
Builtin network: dev,test,main
Custom network format: chain_name:chain_id
Builtin network: local,dev,test,main
Custom network format: chain_id
Such as:
my_chain:123 will init a new chain with id `123`.
Custom network first start should also set the `genesis-config` option.
Use rooch_generator command to generate a genesis config."#;
The Custom network need to use `rooch genesis init` command to init the genesis config first."#;

#[derive(Clone, Debug, Parser, Default, Serialize, Deserialize)]
pub struct RoochOpt {
#[serde(skip_serializing_if = "Option::is_none")]
#[clap(long = "data-dir", short = 'd')]
/// Path to data dir, this dir is base dir, the final data_dir is base_dir/chain_network_name
/// If not set, the default data dir is $HOME/.rooch
/// If set to `TMP`, the service will start with a temporary data store.
pub base_data_dir: Option<PathBuf>,

/// If local chainid, start the service with a temporary data store.
/// All data will be deleted when the service is stopped.
#[serde(skip_serializing_if = "Option::is_none")]
#[clap(long, short = 'n', help = R_OPT_NET_HELP)]
pub chain_id: Option<RoochChainID>,
Expand Down Expand Up @@ -180,10 +178,12 @@ impl RoochOpt {
pub fn new_with_default(
base_data_dir: Option<PathBuf>,
chain_id: Option<RoochChainID>,
genesis_config: Option<String>,
) -> Result<Self> {
let mut opt = RoochOpt {
base_data_dir,
chain_id,
genesis_config,
..Default::default()
};
opt.init()?;
Expand Down
48 changes: 22 additions & 26 deletions crates/rooch-rpc-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::server::rooch_server::RoochServer;
use crate::service::aggregate_service::AggregateService;
use crate::service::rpc_logger::RpcLogger;
use crate::service::rpc_service::RpcService;
use anyhow::{bail, ensure, Error, Result};
use anyhow::{ensure, Error, Result};
use coerce::actor::scheduler::timer::Timer;
use coerce::actor::{system::ActorSystem, IntoActor};
use hyper::header::HeaderValue;
Expand Down Expand Up @@ -36,9 +36,9 @@ use rooch_relayer::actor::relayer::RelayerActor;
use rooch_rpc_api::api::RoochRpcModule;
use rooch_sequencer::actor::sequencer::SequencerActor;
use rooch_sequencer::proxy::SequencerProxy;
use rooch_types::address::{BitcoinAddress, RoochAddress};
use rooch_types::address::RoochAddress;
use rooch_types::error::{GenesisError, RoochError};
use rooch_types::rooch_network::{BuiltinChainID, RoochChainID, RoochNetwork};
use rooch_types::rooch_network::BuiltinChainID;
use serde_json::json;
use std::env;
use std::fmt::Debug;
Expand Down Expand Up @@ -163,9 +163,6 @@ pub async fn run_start_server(opt: RoochOpt, server_opt: ServerOpt) -> Result<Se
let _ = tracing_subscriber::fmt::try_init();

let config = ServerConfig::new_with_port(opt.port());

let chain_id = opt.chain_id.clone().unwrap_or_default();

let actor_system = ActorSystem::global_system();

//Init store
Expand All @@ -189,28 +186,27 @@ pub async fn run_start_server(opt: RoochOpt, server_opt: ServerOpt) -> Result<Se

let sequencer_keypair = server_opt.sequencer_keypair.unwrap();
let sequencer_account = sequencer_keypair.public().rooch_address()?;
let sequencer_bitcoin_address = sequencer_keypair.public().bitcoin_address()?;

let data_import_flag = opt.data_import_flag;
if let RoochChainID::Builtin(builtin_chain_id) = chain_id {
let mut network: RoochNetwork = builtin_chain_id.into();
let sequencer_account: BitcoinAddress = sequencer_keypair.public().bitcoin_address()?;
match builtin_chain_id {
// local chain can use any sequencer account
BuiltinChainID::Local | BuiltinChainID::Dev => {
network.set_sequencer_account(sequencer_account);
}
_ => {
ensure!(network.genesis_config.sequencer_account == sequencer_account, "Sequencer({:?}) in genesis config is not equal to sequencer({:?}) in cli config", network.genesis_config.sequencer_account, sequencer_account);
}
}
let genesis = RoochGenesis::build(network)?;
if root.is_genesis() {
root = genesis.init_genesis(&rooch_db)?;
} else {
genesis.check_genesis(moveos_store.get_config_store())?;
}
} else if root.is_genesis() {
bail!("Custom chain_id is not supported auto genesis, please use `rooch genesis` to init genesis. ");
let mut network = opt.network();
if network.chain_id == BuiltinChainID::Local.chain_id() {
// local chain use current active account as sequencer account
network.set_sequencer_account(sequencer_bitcoin_address);
} else {
ensure!(
network.genesis_config.sequencer_account == sequencer_bitcoin_address,
"Sequencer({:?}) in genesis config is not equal to sequencer({:?}) in cli config",
network.genesis_config.sequencer_account,
sequencer_bitcoin_address
);
}

let genesis = RoochGenesis::build(network)?;
if root.is_genesis() {
root = genesis.init_genesis(&rooch_db)?;
} else {
genesis.check_genesis(moveos_store.get_config_store())?;
}

let executor_actor =
Expand Down
1 change: 1 addition & 0 deletions crates/rooch-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ serde = { workspace = true }
serde_bytes = { workspace = true }
serde_json = { workspace = true }
serde_with = { workspace = true }
serde_yaml = { workspace = true }
derive_more = { workspace = true }
eyre = { workspace = true }
fastcrypto = { workspace = true, features = ["copy_key"] }
Expand Down
38 changes: 38 additions & 0 deletions crates/rooch-types/src/genesis_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,44 @@ pub struct GenesisConfig {
pub stdlib_version: StdlibVersion,
}

impl GenesisConfig {
pub fn new(
bitcoin_network: u8,
bitcoin_block_height: u64,
timestamp: u64,
sequencer_account: BitcoinAddress,
genesis_objects: Vec<GenesisObject>,
stdlib_version: StdlibVersion,
) -> Self {
Self {
bitcoin_network,
bitcoin_block_height,
timestamp,
sequencer_account,
genesis_objects,
stdlib_version,
}
}

pub fn load<P>(path: P) -> anyhow::Result<Self>
where
P: AsRef<std::path::Path>,
{
let content = std::fs::read_to_string(path)?;
let config: GenesisConfig = serde_yaml::from_str(&content)?;
Ok(config)
}

pub fn save<P>(&self, path: P) -> anyhow::Result<()>
where
P: AsRef<std::path::Path>,
{
let content = serde_yaml::to_string(self)?;
std::fs::write(path, content)?;
Ok(())
}
}

pub static G_LOCAL_CONFIG: Lazy<GenesisConfig> = Lazy::new(|| GenesisConfig {
bitcoin_network: crate::bitcoin::network::Network::Regtest.to_num(),
bitcoin_block_height: 0,
Expand Down
4 changes: 1 addition & 3 deletions crates/rooch/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@ rooch-rpc-server = { workspace = true }
rooch-rpc-client = { workspace = true }
rooch-integration-test-runner = { workspace = true }
rooch-indexer = { workspace = true }
rooch-db = { workspace = true }

framework-release = { workspace = true }

[features]
dashboard = []
45 changes: 45 additions & 0 deletions crates/rooch/src/commands/genesis/commands/init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use clap::Parser;
use rooch_config::{RoochOpt, R_OPT_NET_HELP};
use rooch_db::RoochDB;
use rooch_genesis::RoochGenesis;
use rooch_types::{error::RoochResult, rooch_network::RoochChainID};
use std::path::PathBuf;

/// Init genesis statedb
#[derive(Debug, Parser)]
pub struct InitCommand {
#[clap(long = "data-dir", short = 'd')]
/// Path to data dir, this dir is base dir, the final data_dir is base_dir/chain_network_name
pub base_data_dir: Option<PathBuf>,

/// If local chainid, start the service with a temporary data store.
/// All data will be deleted when the service is stopped.
#[clap(long, short = 'n', help = R_OPT_NET_HELP)]
pub chain_id: Option<RoochChainID>,

#[clap(long)]
/// The genesis config file path for custom chain network.
/// If the file path equals to builtin chain network name(local/dev/test/main), will use builtin genesis config.
pub genesis_config: Option<String>,
}

impl InitCommand {
pub async fn execute(self) -> RoochResult<()> {
let opt =
RoochOpt::new_with_default(self.base_data_dir, self.chain_id, self.genesis_config)?;
let store_config = opt.store_config();
let rooch_db = RoochDB::init(store_config)?;
let network = opt.network();
let genesis = RoochGenesis::build(network)?;
let root = genesis.init_genesis(&rooch_db)?;
println!(
"Genesis statedb initialized at {:?} successfully, state_root: {:?}",
opt.base().data_dir(),
root.state_root()
);
Ok(())
}
}
4 changes: 4 additions & 0 deletions crates/rooch/src/commands/genesis/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

pub mod init;
32 changes: 32 additions & 0 deletions crates/rooch/src/commands/genesis/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use self::commands::init::InitCommand;
use crate::cli_types::CommandAction;
use async_trait::async_trait;
use clap::Parser;
use rooch_types::error::RoochResult;

pub mod commands;

/// Statedb Commands
#[derive(Parser)]
pub struct Genesis {
#[clap(subcommand)]
cmd: GenesisCommand,
}

#[async_trait]
impl CommandAction<String> for Genesis {
async fn execute(self) -> RoochResult<String> {
match self.cmd {
GenesisCommand::Init(init) => init.execute().await.map(|_| "".to_string()),
}
}
}

#[derive(clap::Subcommand)]
#[clap(name = "genesis")]
pub enum GenesisCommand {
Init(InitCommand),
}
2 changes: 1 addition & 1 deletion crates/rooch/src/commands/indexer/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn init_indexer(
chain_id: Option<RoochChainID>,
) -> Result<(IndexerStore, IndexerReader)> {
// Reconstruct RoochOpt
let opt = RoochOpt::new_with_default(base_data_dir, chain_id)?;
let opt = RoochOpt::new_with_default(base_data_dir, chain_id, None)?;

let store_config = opt.store_config();

Expand Down
1 change: 1 addition & 0 deletions crates/rooch/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod abi;
pub mod account;
pub mod env;
pub mod event;
pub mod genesis;
pub mod indexer;
pub mod init;
pub mod move_cli;
Expand Down
23 changes: 11 additions & 12 deletions crates/rooch/src/commands/statedb/commands/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@

use crate::cli_types::WalletContextOptions;
use crate::commands::statedb::commands::{
init_statedb, BATCH_SIZE, GLOBAL_STATE_TYPE_FIELD, GLOBAL_STATE_TYPE_OBJECT,
GLOBAL_STATE_TYPE_ROOT,
BATCH_SIZE, GLOBAL_STATE_TYPE_FIELD, GLOBAL_STATE_TYPE_OBJECT, GLOBAL_STATE_TYPE_ROOT,
};
use anyhow::Result;
use clap::Parser;
Expand All @@ -13,7 +12,8 @@ use moveos_store::MoveOSStore;
use moveos_types::h256::H256;
use moveos_types::moveos_std::object::ObjectID;
use moveos_types::state_resolver::StatelessResolver;
use rooch_config::R_OPT_NET_HELP;
use rooch_config::{RoochOpt, R_OPT_NET_HELP};
use rooch_db::RoochDB;
use rooch_types::bitcoin::ord::InscriptionStore;
use rooch_types::bitcoin::utxo::BitcoinUTXOStore;
use rooch_types::error::{RoochError, RoochResult};
Expand Down Expand Up @@ -157,12 +157,11 @@ pub struct ExportCommand {

impl ExportCommand {
pub async fn execute(self) -> RoochResult<()> {
let mut _context = self.context_options.build()?;
// let client = context.get_client().await?;

println!("Start statedb export task, batch_size: {:?}", BATCH_SIZE);
let (root, moveos_store) = init_statedb(self.base_data_dir.clone(), self.chain_id.clone())?;
println!("root object: {:?}", root);
let opt = RoochOpt::new_with_default(self.base_data_dir, self.chain_id, None)?;
let rooch_db = RoochDB::init(opt.store_config())?;

println!("root object: {:?}", rooch_db.root);

let mut _start_time = SystemTime::now();
let file_name = self.output.display().to_string();
Expand All @@ -173,12 +172,12 @@ impl ExportCommand {
})?;
let root_state_root = self
.state_root
.unwrap_or(H256::from(root.state_root.into_bytes()));
.unwrap_or(H256::from(rooch_db.root.state_root.into_bytes()));

let mode = ExportMode::try_from(self.mode.unwrap_or(ExportMode::Genesis.to_num()))?;
match mode {
ExportMode::Genesis => {
Self::export_genesis(&moveos_store, root_state_root, &mut writer)?;
Self::export_genesis(&rooch_db.moveos_store, root_state_root, &mut writer)?;
}
ExportMode::Full => {
todo!()
Expand All @@ -187,13 +186,13 @@ impl ExportCommand {
todo!()
}
ExportMode::Indexer => {
Self::export_indexer(&moveos_store, root_state_root, &mut writer)?;
Self::export_indexer(&rooch_db.moveos_store, root_state_root, &mut writer)?;
}
ExportMode::Object => {
let obj_id = self
.object_id
.expect("Object id should exist in object mode");
Self::export_object(&moveos_store, root_state_root, obj_id, &mut writer)?;
Self::export_object(&rooch_db.moveos_store, root_state_root, obj_id, &mut writer)?;
}
}

Expand Down
Loading

0 comments on commit 41cef59

Please sign in to comment.