diff --git a/Cargo.lock b/Cargo.lock index f0b9b94d14..b150ca37d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -384,6 +384,7 @@ dependencies = [ name = "ckb-bin" version = "0.23.0-pre" dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "ckb-app-config 0.23.0-pre", "ckb-build-info 0.23.0-pre", "ckb-chain 0.23.0-pre", diff --git a/ckb-bin/Cargo.toml b/ckb-bin/Cargo.toml index 3d6591a38d..e5c3b52d69 100644 --- a/ckb-bin/Cargo.toml +++ b/ckb-bin/Cargo.toml @@ -35,3 +35,4 @@ ckb-build-info = { path = "../util/build-info" } ckb-verification = { path = "../verification" } faster-hex = "0.4" ckb-db = { path = "../db" } +base64 = "0.10.1" diff --git a/ckb-bin/src/subcommand/init.rs b/ckb-bin/src/subcommand/init.rs index 4d6d0b06fd..0926f2a3ce 100644 --- a/ckb-bin/src/subcommand/init.rs +++ b/ckb-bin/src/subcommand/init.rs @@ -1,4 +1,5 @@ use std::fs; +use std::io::{self, Read}; use std::path::PathBuf; use crate::helper::prompt; @@ -166,15 +167,6 @@ pub fn init(args: InitArgs) -> Result<(), ExitCode> { } }; - let context = TemplateContext { - spec: &args.chain, - rpc_port: &args.rpc_port, - p2p_port: &args.p2p_port, - log_to_file: args.log_to_file, - log_to_stdout: args.log_to_stdout, - block_assembler: &block_assembler, - }; - println!( "{} CKB directory in {}", if !exported { @@ -185,15 +177,49 @@ pub fn init(args: InitArgs) -> Result<(), ExitCode> { args.root_dir.display() ); - println!("create {}", CKB_CONFIG_FILE_NAME); - Resource::bundled_ckb_config().export(&context, &args.root_dir)?; - println!("create {}", MINER_CONFIG_FILE_NAME); - Resource::bundled_miner_config().export(&context, &args.root_dir)?; + let mut context = TemplateContext { + spec: &args.chain, + rpc_port: &args.rpc_port, + p2p_port: &args.p2p_port, + log_to_file: args.log_to_file, + log_to_stdout: args.log_to_stdout, + block_assembler: &block_assembler, + spec_source: "bundled", + }; - if args.chain == DEFAULT_SPEC { + if let Some(spec_file) = args.import_spec { + context.spec_source = "file"; + + let specs_dir = args.root_dir.join("specs"); + fs::create_dir_all(&specs_dir)?; + let target_file = specs_dir.join(format!("{}.toml", args.chain)); + + if spec_file == "-" { + println!("create specs/{}.toml from stdin", args.chain); + let mut encoded_content = String::new(); + io::stdin().read_to_string(&mut encoded_content)?; + let spec_content = base64::decode_config( + &encoded_content.trim(), + base64::STANDARD.decode_allow_trailing_bits(true), + ) + .map_err(|err| { + eprintln!("stdin must be encoded in base64: {}", err); + ExitCode::Failure + })?; + fs::write(target_file, spec_content)?; + } else { + println!("cp {} specs/{}.toml", spec_file, args.chain); + fs::copy(spec_file, target_file)?; + } + } else if args.chain == DEFAULT_SPEC { println!("create {}", SPEC_DEV_FILE_NAME); Resource::bundled(SPEC_DEV_FILE_NAME.to_string()).export(&context, &args.root_dir)?; } + println!("create {}", CKB_CONFIG_FILE_NAME); + Resource::bundled_ckb_config().export(&context, &args.root_dir)?; + println!("create {}", MINER_CONFIG_FILE_NAME); + Resource::bundled_miner_config().export(&context, &args.root_dir)?; + Ok(()) } diff --git a/error/src/lib.rs b/error/src/lib.rs index 5ee2c3a7ff..31c239acaf 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -13,6 +13,7 @@ use std::fmt::{self, Display}; pub enum ErrorKind { OutPoint, Transaction, + SubmitTransaction, Script, Header, Block, diff --git a/resource/ckb-miner.toml b/resource/ckb-miner.toml index 704e19f0bc..82f05d4022 100644 --- a/resource/ckb-miner.toml +++ b/resource/ckb-miner.toml @@ -11,8 +11,8 @@ data_dir = "data" # - { file = "specs/dev.toml" } # - { bundled = "specs/testnet.toml" } spec = { file = "specs/dev.toml" } # {{ -# testnet => spec = { bundled = "specs/testnet.toml" } -# staging => spec = { bundled = "specs/staging.toml" } +# testnet => spec = { {spec_source} = "specs/testnet.toml" } +# staging => spec = { {spec_source} = "specs/staging.toml" } # integration => spec = { file = "specs/integration.toml" } # }} diff --git a/resource/ckb.toml b/resource/ckb.toml index 9d948507c0..dac54db67a 100644 --- a/resource/ckb.toml +++ b/resource/ckb.toml @@ -11,8 +11,8 @@ data_dir = "data" # - { file = "specs/dev.toml" } # - { bundled = "specs/testnet.toml" } spec = { file = "specs/dev.toml" } # {{ -# testnet => spec = { bundled = "specs/testnet.toml" } -# staging => spec = { bundled = "specs/staging.toml" } +# testnet => spec = { {spec_source} = "specs/testnet.toml" } +# staging => spec = { {spec_source} = "specs/staging.toml" } # integration => spec = { file = "specs/integration.toml" } # }} diff --git a/resource/src/lib.rs b/resource/src/lib.rs index dc81c2df0a..4787b1a291 100644 --- a/resource/src/lib.rs +++ b/resource/src/lib.rs @@ -228,6 +228,7 @@ mod tests { log_to_file: true, log_to_stdout: true, block_assembler: "", + spec_source: "bundled", }; Resource::bundled_ckb_config() .export(&context, root_dir.path()) diff --git a/resource/src/template.rs b/resource/src/template.rs index caa92ba23c..13953b3657 100644 --- a/resource/src/template.rs +++ b/resource/src/template.rs @@ -13,6 +13,7 @@ pub struct Template(T); pub struct TemplateContext<'a> { pub spec: &'a str, + pub spec_source: &'a str, pub rpc_port: &'a str, pub p2p_port: &'a str, pub log_to_file: bool, @@ -38,6 +39,7 @@ fn writeln(w: &mut W, s: &str, context: &TemplateContext) -> io::R .replace("{log_to_file}", &format!("{}", context.log_to_file)) .replace("{log_to_stdout}", &format!("{}", context.log_to_stdout)) .replace("{block_assembler}", context.block_assembler) + .replace("{spec_source}", context.spec_source) ) } diff --git a/spec/src/lib.rs b/spec/src/lib.rs index 271fd56a3f..d38a3a2555 100644 --- a/spec/src/lib.rs +++ b/spec/src/lib.rs @@ -147,7 +147,6 @@ impl Default for SatoshiGift { #[derive(Debug)] pub enum SpecLoadError { FileNotFound, - ChainNameNotAllowed(String), GenesisMismatch { expect: H256, actual: H256 }, } @@ -156,10 +155,6 @@ impl SpecLoadError { Box::new(SpecLoadError::FileNotFound) } - fn chain_name_not_allowed(name: String) -> Box { - Box::new(SpecLoadError::ChainNameNotAllowed(name)) - } - fn genesis_mismatch(expect: H256, actual: H256) -> Box { Box::new(SpecLoadError::GenesisMismatch { expect, actual }) } @@ -171,11 +166,6 @@ impl fmt::Display for SpecLoadError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { SpecLoadError::FileNotFound => write!(f, "ChainSpec: file not found"), - SpecLoadError::ChainNameNotAllowed(name) => write!( - f, - "ChainSpec: name not allowed, expect ckb_dev, actual {}", - name - ), SpecLoadError::GenesisMismatch { expect, actual } => write!( f, "ChainSpec: genesis hash mismatch, expect {:#x}, actual {:#x}", @@ -192,10 +182,6 @@ impl ChainSpec { } let config_bytes = resource.get()?; let mut spec: ChainSpec = toml::from_slice(&config_bytes)?; - if !(resource.is_bundled() || spec.name == "ckb_dev" || spec.name == "ckb_integration_test") - { - return Err(SpecLoadError::chain_name_not_allowed(spec.name.clone())); - } if let Some(parent) = resource.parent() { for r in spec.genesis.system_cells.iter_mut() { diff --git a/tx-pool/src/error.rs b/tx-pool/src/error.rs index 5f32df99f6..e70975933d 100644 --- a/tx-pool/src/error.rs +++ b/tx-pool/src/error.rs @@ -10,7 +10,7 @@ pub enum SubmitTxError { impl From for Error { fn from(error: SubmitTxError) -> Self { - error.context(ErrorKind::Transaction).into() + error.context(ErrorKind::SubmitTransaction).into() } } diff --git a/util/app-config/src/app_config.rs b/util/app-config/src/app_config.rs index 772b436b3e..6335d877c8 100644 --- a/util/app-config/src/app_config.rs +++ b/util/app-config/src/app_config.rs @@ -260,6 +260,7 @@ mod tests { log_to_file: true, log_to_stdout: true, block_assembler: "", + spec_source: "bundled", }; { Resource::bundled_ckb_config() @@ -306,6 +307,7 @@ mod tests { log_to_file: false, log_to_stdout: true, block_assembler: "", + spec_source: "bundled", }; { Resource::bundled_ckb_config() @@ -341,6 +343,7 @@ mod tests { log_to_file: true, log_to_stdout: true, block_assembler: "", + spec_source: "bundled", }; { Resource::bundled_ckb_config() @@ -387,6 +390,7 @@ mod tests { log_to_file: true, log_to_stdout: true, block_assembler: "", + spec_source: "bundled", }; { Resource::bundled_ckb_config() @@ -431,6 +435,7 @@ mod tests { log_to_file: true, log_to_stdout: true, block_assembler: "", + spec_source: "bundled", }; { Resource::bundled_ckb_config() diff --git a/util/app-config/src/args.rs b/util/app-config/src/args.rs index d8d51bc48b..b00feb2e4b 100644 --- a/util/app-config/src/args.rs +++ b/util/app-config/src/args.rs @@ -57,6 +57,7 @@ pub struct InitArgs { pub block_assembler_args: Vec, pub block_assembler_hash_type: ScriptHashType, pub block_assembler_message: Option, + pub import_spec: Option, } pub struct ResetDataArgs { diff --git a/util/app-config/src/cli.rs b/util/app-config/src/cli.rs index 03ef6c30e1..8f2db18509 100644 --- a/util/app-config/src/cli.rs +++ b/util/app-config/src/cli.rs @@ -24,6 +24,7 @@ pub const ARG_DATA: &str = "data"; pub const ARG_LIST_CHAINS: &str = "list-chains"; pub const ARG_INTERACTIVE: &str = "interactive"; pub const ARG_CHAIN: &str = "chain"; +pub const ARG_IMPORT_SPEC: &str = "import-spec"; pub const ARG_P2P_PORT: &str = "p2p-port"; pub const ARG_RPC_PORT: &str = "rpc-port"; pub const ARG_FORCE: &str = "force"; @@ -301,6 +302,15 @@ fn init() -> App<'static, 'static> { .default_value(DEFAULT_SPEC) .help("Initializes CKB direcotry for "), ) + .arg( + Arg::with_name(ARG_IMPORT_SPEC) + .long(ARG_IMPORT_SPEC) + .takes_value(true) + .help( + "Uses the specifiec file as chain spec. Specially, \ + The dash \"-\" denotes importing the spec from stdin encoded in base64", + ), + ) .arg( Arg::with_name(ARG_LOG_TO) .long(ARG_LOG_TO) diff --git a/util/app-config/src/lib.rs b/util/app-config/src/lib.rs index 22ab8444fa..4b3c574a63 100644 --- a/util/app-config/src/lib.rs +++ b/util/app-config/src/lib.rs @@ -226,6 +226,8 @@ impl Setup { .unwrap(); let block_assembler_message = matches.value_of(cli::ARG_BA_MESSAGE).map(str::to_string); + let import_spec = matches.value_of(cli::ARG_IMPORT_SPEC).map(str::to_string); + Ok(InitArgs { interactive, root_dir, @@ -240,6 +242,7 @@ impl Setup { block_assembler_args, block_assembler_hash_type, block_assembler_message, + import_spec, }) }