diff --git a/Cargo.lock b/Cargo.lock index cc81f52..1cc32bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -379,14 +379,14 @@ dependencies = [ [[package]] name = "ckb-bitcoin-spv-verifier" version = "0.1.0" -source = "git+https://github.com/ckb-cell/ckb-bitcoin-spv?rev=a6fce4b#a6fce4b5333967905a6d3859c56babc985ef89e9" +source = "git+https://github.com/ckb-cell/ckb-bitcoin-spv?rev=bfc71d7#bfc71d7daf17e96f34e8e287f45254e512383330" dependencies = [ "bitcoin", "bitcoin_hashes", "ckb-merkle-mountain-range 0.6.0", - "ethereum-types", "log", "molecule", + "primitive-types", ] [[package]] @@ -1126,29 +1126,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ethbloom" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" -dependencies = [ - "crunchy", - "fixed-hash", - "tiny-keccak", -] - -[[package]] -name = "ethereum-types" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" -dependencies = [ - "ethbloom", - "fixed-hash", - "primitive-types", - "uint", -] - [[package]] name = "faster-hex" version = "0.6.1" diff --git a/Cargo.toml b/Cargo.toml index d672d2c..3b7d539 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ ckb-hash = "0.115.0-rc2" [dependencies.ckb-bitcoin-spv-verifier] version = "0.1.0" git = "https://github.com/ckb-cell/ckb-bitcoin-spv" -rev = "a6fce4b" +rev = "bfc71d7" [features] default = ["default-tls"] diff --git a/src/cli/init.rs b/src/cli/init.rs index e2f0b0d..97b445e 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -4,7 +4,7 @@ use std::{collections::HashMap, path::PathBuf}; use bitcoin::blockdata::constants::DIFFCHANGE_INTERVAL; use ckb_bitcoin_spv_verifier::{ - constants::FLAG_DISABLE_DIFFICULTY_CHECK, + constants::{FLAG_CHAIN_TYPE_MAINNET, FLAG_CHAIN_TYPE_SIGNET, FLAG_CHAIN_TYPE_TESTNET}, types::{core::Hash as BitcoinHash, packed, prelude::Pack as VPack}, }; use ckb_jsonrpc_types::TransactionView; @@ -31,7 +31,7 @@ use ckb_types::{ prelude::*, H256, }; -use clap::{Args as ClapArgs, Parser}; +use clap::{Args as ClapArgs, Parser, ValueEnum}; use secp256k1::SecretKey; use crate::{ @@ -78,14 +78,9 @@ pub struct Args { #[clap(flatten)] pub(crate) spv_owner: super::SpvOwner, - /// Disable the on-chain difficulty check. - /// - /// ### Warning - /// - /// For testing purpose only. - /// Do NOT enable this flag in production environment. + /// Bitcoin chain type. #[arg(long)] - pub(crate) disable_difficulty_check: bool, + pub(crate) bitcoin_chain_type: BitcoinChainType, /// Perform all steps without sending. #[arg(long, hide = true)] @@ -104,14 +99,22 @@ pub struct CodeHash { pub(crate) spv_contract_type_hash: Option, } +#[derive(Clone, PartialEq, ValueEnum)] +pub enum BitcoinChainType { + Mainnet, + Testnet, + Signet, +} + impl Args { // TODO Split this method into several smaller methods. pub fn execute(&self) -> Result<()> { log::info!("Try to initialize a Bitcoin SPV instance on CKB"); - if self.disable_difficulty_check && self.ckb.network == NetworkType::Mainnet { - let msg = "For safety, the option `self.disable_difficulty_check` \ - are not allowed on the mainnet"; + if self.bitcoin_chain_type != BitcoinChainType::Mainnet + && self.ckb.network == NetworkType::Mainnet + { + let msg = "The Bitcoin chain type is not mainnet, but the CKB network is mainnet"; return Err(Error::other(msg)); } @@ -182,8 +185,10 @@ impl Args { let type_id_array = calculate_type_id(input0.cell_input(), cells_count); let type_id = BitcoinHash::from_bytes_ref(&type_id_array); let mut flags = 0u8; - if self.disable_difficulty_check { - flags |= FLAG_DISABLE_DIFFICULTY_CHECK; + match self.bitcoin_chain_type { + BitcoinChainType::Mainnet => flags |= FLAG_CHAIN_TYPE_MAINNET, + BitcoinChainType::Testnet => flags |= FLAG_CHAIN_TYPE_TESTNET, + BitcoinChainType::Signet => flags |= FLAG_CHAIN_TYPE_SIGNET, } let args = packed::SpvTypeArgs::new_builder() .type_id(type_id.pack()) diff --git a/src/cli/serve.rs b/src/cli/serve.rs index 2f2e220..c7df5b6 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -181,6 +181,7 @@ impl Args { let (spv_client, spv_update) = storage.generate_spv_client_and_spv_update( spv_tip_height, self.spv_headers_update_limit, + input.info.get_flags()?, )?; let tx_hash = @@ -193,8 +194,11 @@ impl Args { let spv_tip_height = input.curr.client.headers_mmr_root.max_height; - let (spv_client, spv_update) = storage - .generate_spv_client_and_spv_update(spv_tip_height, NonZeroU32::MAX)?; + let (spv_client, spv_update) = storage.generate_spv_client_and_spv_update( + spv_tip_height, + NonZeroU32::MAX, + input.info.get_flags()?, + )?; let tx_hash = self.reorg_spv_cells(&spv_service, input, spv_client, spv_update)?; diff --git a/src/components/ckb_client.rs b/src/components/ckb_client.rs index c8e7074..d5d2f62 100644 --- a/src/components/ckb_client.rs +++ b/src/components/ckb_client.rs @@ -60,6 +60,24 @@ impl SpvInfoCell { 0 } } + + pub(crate) fn get_flags(&self) -> Result { + let script_args = self + .cell + .output + .type_() + .to_opt() + .ok_or_else(|| Error::other("the SPV info cell has no type script"))? + .args(); + let script_args_slice = script_args.as_reader().raw_data(); + let args = packed::SpvTypeArgsReader::from_slice(script_args_slice).map_err(|err| { + let msg = + format!("failed to parse the type script args for the SPV info cell since {err}"); + Error::other(msg) + })?; + let flags: u8 = args.flags().into(); + Ok(flags) + } } pub trait CkbRpcClientExtension { diff --git a/src/components/storage/prelude.rs b/src/components/storage/prelude.rs index 9f5a76c..8aa80c4 100644 --- a/src/components/storage/prelude.rs +++ b/src/components/storage/prelude.rs @@ -153,6 +153,7 @@ pub(crate) trait BitcoinSpvStorage: InternalBitcoinSpvStorage { &self, prev_height: u32, limit: NonZeroU32, + flags: u8, ) -> Result<(SpvClient, packed::SpvUpdate)> { let mut tip_height = self.get_tip_bitcoin_height()?; if tip_height > prev_height.saturating_add(limit.into()) { @@ -200,7 +201,7 @@ pub(crate) trait BitcoinSpvStorage: InternalBitcoinSpvStorage { tip_header.time ); let next_target = - calculate_next_target(curr_target, start_header.time, tip_header.time); + calculate_next_target(curr_target, start_header.time, tip_header.time, flags); log::trace!("calculated new target {next_target:#x}"); let next_bits = next_target.to_compact_lossy(); let next_target: Target = next_bits.into();