From 1c45ea4b0ec30a28077d7a7f1b1d84a37c0b6de7 Mon Sep 17 00:00:00 2001 From: driftluo Date: Thu, 2 Nov 2023 11:30:42 +0800 Subject: [PATCH] fix: fix vm version select --- ckb-bin/src/subcommand/export.rs | 3 +- ckb-bin/src/subcommand/import.rs | 3 +- ckb-bin/src/subcommand/migrate.rs | 2 +- ckb-bin/src/subcommand/replay.rs | 8 +- ckb-bin/src/subcommand/stats.rs | 3 +- rpc/README.md | 12 +-- rpc/src/module/chain.rs | 12 +-- script/src/verify.rs | 17 +++- .../tests/ckb_latest/features_since_v2019.rs | 90 ----------------- .../tests/ckb_latest/features_since_v2021.rs | 96 ++++++++++++++++++- script/src/verify/tests/utils.rs | 11 ++- spec/src/hardfork.rs | 27 +----- util/constant/src/hardfork/mainnet.rs | 5 +- util/constant/src/hardfork/testnet.rs | 5 +- util/launcher/src/lib.rs | 2 +- util/launcher/src/migrate.rs | 4 +- util/launcher/src/migrations/mod.rs | 2 + .../migrations/set_2019_block_cycle_zero.rs | 90 +++++++++++++++++ util/launcher/src/shared_builder.rs | 22 +++-- util/launcher/src/tests.rs | 8 +- util/types/src/core/hardfork/ckb2021.rs | 14 +-- 21 files changed, 272 insertions(+), 164 deletions(-) create mode 100644 util/launcher/src/migrations/set_2019_block_cycle_zero.rs diff --git a/ckb-bin/src/subcommand/export.rs b/ckb-bin/src/subcommand/export.rs index 4ec13245be..5bebd4a41f 100644 --- a/ckb-bin/src/subcommand/export.rs +++ b/ckb-bin/src/subcommand/export.rs @@ -10,8 +10,9 @@ pub fn export(args: ExportArgs, async_handle: Handle) -> Result<(), ExitCode> { &args.config.db, None, async_handle, + args.consensus, )?; - let (shared, _) = builder.consensus(args.consensus).build()?; + let (shared, _) = builder.build()?; Export::new(shared, args.target).execute().map_err(|err| { eprintln!("Export error: {err:?}"); ExitCode::Failure diff --git a/ckb-bin/src/subcommand/import.rs b/ckb-bin/src/subcommand/import.rs index 574da91d49..800d1ed5bd 100644 --- a/ckb-bin/src/subcommand/import.rs +++ b/ckb-bin/src/subcommand/import.rs @@ -11,8 +11,9 @@ pub fn import(args: ImportArgs, async_handle: Handle) -> Result<(), ExitCode> { &args.config.db, None, async_handle, + args.consensus, )?; - let (shared, mut pack) = builder.consensus(args.consensus).build()?; + let (shared, mut pack) = builder.build()?; let chain_service = ChainService::new(shared, pack.take_proposal_table()); let chain_controller = chain_service.start::<&str>(Some("ImportChainService")); diff --git a/ckb-bin/src/subcommand/migrate.rs b/ckb-bin/src/subcommand/migrate.rs index 3be1aef0cf..f6c0a86254 100644 --- a/ckb-bin/src/subcommand/migrate.rs +++ b/ckb-bin/src/subcommand/migrate.rs @@ -6,7 +6,7 @@ use std::cmp::Ordering; use crate::helper::prompt; pub fn migrate(args: MigrateArgs) -> Result<(), ExitCode> { - let migrate = Migrate::new(&args.config.db.path); + let migrate = Migrate::new(&args.config.db.path, args.consensus.hardfork_switch); { let read_only_db = migrate.open_read_only_db().map_err(|e| { diff --git a/ckb-bin/src/subcommand/replay.rs b/ckb-bin/src/subcommand/replay.rs index 592924dd73..94114c6cdb 100644 --- a/ckb-bin/src/subcommand/replay.rs +++ b/ckb-bin/src/subcommand/replay.rs @@ -18,9 +18,9 @@ pub fn replay(args: ReplayArgs, async_handle: Handle) -> Result<(), ExitCode> { &args.config.db, None, async_handle.clone(), + args.consensus.clone(), )?; let (shared, _) = shared_builder - .consensus(args.consensus.clone()) .tx_pool_config(args.config.tx_pool.clone()) .build()?; @@ -45,11 +45,9 @@ pub fn replay(args: ReplayArgs, async_handle: Handle) -> Result<(), ExitCode> { &tmp_db_config, None, async_handle, + args.consensus, )?; - let (tmp_shared, mut pack) = shared_builder - .consensus(args.consensus) - .tx_pool_config(args.config.tx_pool) - .build()?; + let (tmp_shared, mut pack) = shared_builder.tx_pool_config(args.config.tx_pool).build()?; let chain = ChainService::new(tmp_shared, pack.take_proposal_table()); if let Some((from, to)) = args.profile { diff --git a/ckb-bin/src/subcommand/stats.rs b/ckb-bin/src/subcommand/stats.rs index 50583f742a..e71725c51d 100644 --- a/ckb-bin/src/subcommand/stats.rs +++ b/ckb-bin/src/subcommand/stats.rs @@ -33,8 +33,9 @@ impl Statics { &args.config.db, None, async_handle, + args.consensus, )?; - let (shared, _) = shared_builder.consensus(args.consensus).build()?; + let (shared, _) = shared_builder.build()?; let tip_number = shared.snapshot().tip_number(); diff --git a/rpc/README.md b/rpc/README.md index e50b65674f..6aa51ce8f4 100644 --- a/rpc/README.md +++ b/rpc/README.md @@ -1659,12 +1659,12 @@ Response "genesis_hash": "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed", "hardfork_features": [ { "rfc": "0028", "epoch_number": "0x1526" }, - { "rfc": "0029", "epoch_number": "0x0" }, - { "rfc": "0030", "epoch_number": "0x0" }, - { "rfc": "0031", "epoch_number": "0x0" }, - { "rfc": "0032", "epoch_number": "0x0" }, - { "rfc": "0036", "epoch_number": "0x0" }, - { "rfc": "0038", "epoch_number": "0x0" }, + { "rfc": "0029", "epoch_number": "0x1526" }, + { "rfc": "0030", "epoch_number": "0x1526" }, + { "rfc": "0031", "epoch_number": "0x1526" }, + { "rfc": "0032", "epoch_number": "0x1526" }, + { "rfc": "0036", "epoch_number": "0x1526" }, + { "rfc": "0038", "epoch_number": "0x1526" }, { "rfc": "0048", "epoch_number": null }, { "rfc": "0049", "epoch_number": null } ], diff --git a/rpc/src/module/chain.rs b/rpc/src/module/chain.rs index 6a013be67c..0a52368b4c 100644 --- a/rpc/src/module/chain.rs +++ b/rpc/src/module/chain.rs @@ -1341,12 +1341,12 @@ pub trait ChainRpc { /// "genesis_hash": "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed", /// "hardfork_features": [ /// { "rfc": "0028", "epoch_number": "0x1526" }, - /// { "rfc": "0029", "epoch_number": "0x0" }, - /// { "rfc": "0030", "epoch_number": "0x0" }, - /// { "rfc": "0031", "epoch_number": "0x0" }, - /// { "rfc": "0032", "epoch_number": "0x0" }, - /// { "rfc": "0036", "epoch_number": "0x0" }, - /// { "rfc": "0038", "epoch_number": "0x0" }, + /// { "rfc": "0029", "epoch_number": "0x1526" }, + /// { "rfc": "0030", "epoch_number": "0x1526" }, + /// { "rfc": "0031", "epoch_number": "0x1526" }, + /// { "rfc": "0032", "epoch_number": "0x1526" }, + /// { "rfc": "0036", "epoch_number": "0x1526" }, + /// { "rfc": "0038", "epoch_number": "0x1526" }, /// { "rfc": "0048", "epoch_number": null }, /// { "rfc": "0049", "epoch_number": null } /// ], diff --git a/script/src/verify.rs b/script/src/verify.rs index 8f8c406c7e..bdb8b8d588 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -536,6 +536,18 @@ impl bool { + // If the proposal window is allowed to prejudge on the vm version, + // it will cause proposal tx to start a new vm in the blocks before hardfork, + // destroying the assumption that the transaction execution only uses the old vm + // before hardfork, leading to unexpected network splits. + let epoch_number = self.tx_env.epoch_number_without_proposal_window(); + let hardfork_switch = self.consensus.hardfork_switch(); + hardfork_switch + .ckb2021 + .is_vm_version_1_and_syscalls_2_enabled(epoch_number) + } + fn is_vm_version_2_and_syscalls_3_enabled(&self) -> bool { // If the proposal window is allowed to prejudge on the vm version, // it will cause proposal tx to start a new vm in the blocks before hardfork, @@ -551,6 +563,7 @@ impl Result { let is_vm_version_2_and_syscalls_3_enabled = self.is_vm_version_2_and_syscalls_3_enabled(); + let is_vm_version_1_and_syscalls_2_enabled = self.is_vm_version_1_and_syscalls_2_enabled(); let script_hash_type = ScriptHashType::try_from(script.hash_type()) .map_err(|err| ScriptError::InvalidScriptHashType(err.to_string()))?; match script_hash_type { @@ -566,8 +579,10 @@ impl { if is_vm_version_2_and_syscalls_3_enabled { Ok(ScriptVersion::V2) - } else { + } else if is_vm_version_1_and_syscalls_2_enabled { Ok(ScriptVersion::V1) + } else { + Ok(ScriptVersion::V0) } } } diff --git a/script/src/verify/tests/ckb_latest/features_since_v2019.rs b/script/src/verify/tests/ckb_latest/features_since_v2019.rs index 516df11492..77d224c0ae 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2019.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2019.rs @@ -190,96 +190,6 @@ fn check_signature_referenced_via_type_hash() { assert!(result.is_ok()); } -#[test] -fn check_signature_referenced_via_type_hash_ok_with_multiple_matches() { - let script_version = SCRIPT_VERSION; - - let mut file = open_cell_always_success(); - let mut buffer = Vec::new(); - file.read_to_end(&mut buffer).unwrap(); - let data = Bytes::from(buffer); - - let (privkey, pubkey) = random_keypair(); - let mut args = b"foobar".to_vec(); - - let signature = sign_args(&args, &privkey); - args.extend(&to_hex_pubkey(&pubkey)); - args.extend(&to_hex_signature(&signature)); - - let dep_out_point = OutPoint::new(h256!("0x123").pack(), 8); - let cell_dep = CellDep::new_builder() - .out_point(dep_out_point.clone()) - .build(); - let output = CellOutputBuilder::default() - .capacity(Capacity::bytes(data.len()).unwrap().pack()) - .type_( - Some( - Script::new_builder() - .code_hash(h256!("0x123456abcd90").pack()) - .hash_type(ScriptHashType::Data.into()) - .build(), - ) - .pack(), - ) - .build(); - let type_hash = output.type_().to_opt().as_ref().unwrap().calc_script_hash(); - let dep_cell = CellMetaBuilder::from_cell_output(output, data.clone()) - .transaction_info(default_transaction_info()) - .out_point(dep_out_point) - .build(); - - let dep_out_point2 = OutPoint::new(h256!("0x1234").pack(), 8); - let cell_dep2 = CellDep::new_builder() - .out_point(dep_out_point2.clone()) - .build(); - let output2 = CellOutputBuilder::default() - .capacity(Capacity::bytes(data.len()).unwrap().pack()) - .type_( - Some( - Script::new_builder() - .code_hash(h256!("0x123456abcd90").pack()) - .hash_type(ScriptHashType::Data.into()) - .build(), - ) - .pack(), - ) - .build(); - let dep_cell2 = CellMetaBuilder::from_cell_output(output2, data) - .transaction_info(default_transaction_info()) - .out_point(dep_out_point2) - .build(); - - let script = Script::new_builder() - .args(Bytes::from(args).pack()) - .code_hash(type_hash) - .hash_type(ScriptHashType::Type.into()) - .build(); - let input = CellInput::new(OutPoint::null(), 0); - - let transaction = TransactionBuilder::default() - .input(input) - .cell_dep(cell_dep) - .cell_dep(cell_dep2) - .build(); - - let output = CellOutputBuilder::default() - .capacity(capacity_bytes!(100).pack()) - .lock(script) - .build(); - let dummy_cell = create_dummy_cell(output); - - let rtx = ResolvedTransaction { - transaction, - resolved_cell_deps: vec![dep_cell, dep_cell2], - resolved_inputs: vec![dummy_cell], - resolved_dep_groups: vec![], - }; - - let verifier = TransactionScriptsVerifierWithEnv::new(); - let result = verifier.verify_without_limit(script_version, &rtx); - assert_eq!(result.unwrap(), 539); -} - #[test] fn check_invalid_signature() { let script_version = SCRIPT_VERSION; diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index 423a67bd15..9570c326ae 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -10,7 +10,7 @@ use ckb_vm::Error as VmError; use proptest::{prelude::*, prop_assert_eq, proptest}; use rand::distributions::Uniform; use rand::{thread_rng, Rng}; -use std::collections::VecDeque; +use std::{collections::VecDeque, io::Read}; use super::SCRIPT_VERSION; use crate::syscalls::SOURCE_GROUP_FLAG; @@ -1694,3 +1694,97 @@ fn exec_slice() { let res = Ok(2); test_exec(0b0000, 1, 2, 1, from, res); } + +#[test] +fn check_signature_referenced_via_type_hash_ok_with_multiple_matches() { + let script_version = SCRIPT_VERSION; + if script_version < ScriptVersion::V1 { + // This transaction is restricted by rfc_0029 and not supported in the 2019 version + return; + } + + let mut file = open_cell_always_success(); + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer).unwrap(); + let data = Bytes::from(buffer); + + let (privkey, pubkey) = random_keypair(); + let mut args = b"foobar".to_vec(); + + let signature = sign_args(&args, &privkey); + args.extend(&to_hex_pubkey(&pubkey)); + args.extend(&to_hex_signature(&signature)); + + let dep_out_point = OutPoint::new(h256!("0x123").pack(), 8); + let cell_dep = CellDep::new_builder() + .out_point(dep_out_point.clone()) + .build(); + let output = CellOutputBuilder::default() + .capacity(Capacity::bytes(data.len()).unwrap().pack()) + .type_( + Some( + Script::new_builder() + .code_hash(h256!("0x123456abcd90").pack()) + .hash_type(ScriptHashType::Data.into()) + .build(), + ) + .pack(), + ) + .build(); + let type_hash = output.type_().to_opt().as_ref().unwrap().calc_script_hash(); + let dep_cell = CellMetaBuilder::from_cell_output(output, data.clone()) + .transaction_info(default_transaction_info()) + .out_point(dep_out_point) + .build(); + + let dep_out_point2 = OutPoint::new(h256!("0x1234").pack(), 8); + let cell_dep2 = CellDep::new_builder() + .out_point(dep_out_point2.clone()) + .build(); + let output2 = CellOutputBuilder::default() + .capacity(Capacity::bytes(data.len()).unwrap().pack()) + .type_( + Some( + Script::new_builder() + .code_hash(h256!("0x123456abcd90").pack()) + .hash_type(ScriptHashType::Data.into()) + .build(), + ) + .pack(), + ) + .build(); + let dep_cell2 = CellMetaBuilder::from_cell_output(output2, data) + .transaction_info(default_transaction_info()) + .out_point(dep_out_point2) + .build(); + + let script = Script::new_builder() + .args(Bytes::from(args).pack()) + .code_hash(type_hash) + .hash_type(ScriptHashType::Type.into()) + .build(); + let input = CellInput::new(OutPoint::null(), 0); + + let transaction = TransactionBuilder::default() + .input(input) + .cell_dep(cell_dep) + .cell_dep(cell_dep2) + .build(); + + let output = CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(script) + .build(); + let dummy_cell = create_dummy_cell(output); + + let rtx = ResolvedTransaction { + transaction, + resolved_cell_deps: vec![dep_cell, dep_cell2], + resolved_inputs: vec![dummy_cell], + resolved_dep_groups: vec![], + }; + + let verifier = TransactionScriptsVerifierWithEnv::new(); + let result = verifier.verify_without_limit(script_version, &rtx); + assert_eq!(result.unwrap(), 539); +} diff --git a/script/src/verify/tests/utils.rs b/script/src/verify/tests/utils.rs index d206de1f37..8eaffcd64d 100644 --- a/script/src/verify/tests/utils.rs +++ b/script/src/verify/tests/utils.rs @@ -126,6 +126,7 @@ pub(crate) struct TransactionScriptsVerifierWithEnv { // Ref: https://doc.rust-lang.org/reference/destructors.html store: Arc, consensus: Arc, + version_1_enabled_at: EpochNumber, version_2_enabled_at: EpochNumber, _tmp_dir: TempDir, } @@ -135,10 +136,15 @@ impl TransactionScriptsVerifierWithEnv { let tmp_dir = TempDir::new().unwrap(); let db = RocksDB::open_in(&tmp_dir, COLUMNS); let store = Arc::new(ChainDB::new(db, Default::default())); + let version_1_enabled_at = 5; let version_2_enabled_at = 10; let hardfork_switch = HardForks { - ckb2021: CKB2021::new_mirana(), + ckb2021: CKB2021::new_mirana() + .as_builder() + .rfc_0032(version_1_enabled_at) + .build() + .unwrap(), ckb2023: CKB2023::new_mirana() .as_builder() .rfc_0049(version_2_enabled_at) @@ -152,6 +158,7 @@ impl TransactionScriptsVerifierWithEnv { ); Self { store, + version_1_enabled_at, version_2_enabled_at, consensus, _tmp_dir: tmp_dir, @@ -237,7 +244,7 @@ impl TransactionScriptsVerifierWithEnv { let data_loader = self.store.as_data_loader(); let epoch = match version { ScriptVersion::V0 => EpochNumberWithFraction::new(0, 0, 1), - ScriptVersion::V1 => EpochNumberWithFraction::new(0, 0, 1), + ScriptVersion::V1 => EpochNumberWithFraction::new(self.version_1_enabled_at, 0, 1), ScriptVersion::V2 => EpochNumberWithFraction::new(self.version_2_enabled_at, 0, 1), }; let header = HeaderView::new_advanced_builder() diff --git a/spec/src/hardfork.rs b/spec/src/hardfork.rs index 2c1f411a2f..ce2c13cc81 100644 --- a/spec/src/hardfork.rs +++ b/spec/src/hardfork.rs @@ -20,11 +20,7 @@ impl HardForkConfig { /// sets all `None` to default values, otherwise, return an `Err`. pub fn complete_mainnet(&self) -> Result { let mut ckb2021 = CKB2021::new_builder(); - ckb2021 = self.update_2021( - ckb2021, - mainnet::CKB2021_START_EPOCH, - mainnet::RFC0028_START_EPOCH, - )?; + ckb2021 = self.update_2021(ckb2021, mainnet::CKB2021_START_EPOCH)?; Ok(HardForks { ckb2021: ckb2021.build()?, @@ -36,11 +32,7 @@ impl HardForkConfig { /// sets all `None` to default values, otherwise, return an `Err`. pub fn complete_testnet(&self) -> Result { let mut ckb2021 = CKB2021::new_builder(); - ckb2021 = self.update_2021( - ckb2021, - testnet::CKB2021_START_EPOCH, - testnet::RFC0028_START_EPOCH, - )?; + ckb2021 = self.update_2021(ckb2021, testnet::CKB2021_START_EPOCH)?; let mut ckb2023 = CKB2023::new_builder(); ckb2023 = self.update_2023(ckb2023, testnet::CKB2023_START_EPOCH)?; @@ -54,10 +46,9 @@ impl HardForkConfig { &self, builder: CKB2021Builder, ckb2021: EpochNumber, - rfc_0028_start: EpochNumber, ) -> Result { let builder = builder - .rfc_0028(rfc_0028_start) + .rfc_0028(ckb2021) .rfc_0029(ckb2021) .rfc_0030(ckb2021) .rfc_0031(ckb2021) @@ -80,12 +71,7 @@ impl HardForkConfig { /// /// Enable features which are set to `None` at the dev default config. pub fn complete_with_dev_default(&self) -> Result { - let mut ckb2021 = CKB2021::new_builder(); - ckb2021 = self.update_2021( - ckb2021, - testnet::CKB2021_START_EPOCH, - testnet::RFC0028_START_EPOCH, - )?; + let ckb2021 = CKB2021::new_dev_default(); let ckb2023 = if let Some(epoch) = self.ckb2023 { CKB2023::new_with_specified(epoch) @@ -93,9 +79,6 @@ impl HardForkConfig { CKB2023::new_dev_default() }; - Ok(HardForks { - ckb2021: ckb2021.build()?, - ckb2023, - }) + Ok(HardForks { ckb2021, ckb2023 }) } } diff --git a/util/constant/src/hardfork/mainnet.rs b/util/constant/src/hardfork/mainnet.rs index df7fc33393..4f1a35c12d 100644 --- a/util/constant/src/hardfork/mainnet.rs +++ b/util/constant/src/hardfork/mainnet.rs @@ -1,11 +1,8 @@ /// The Chain Specification name. pub const CHAIN_SPEC_NAME: &str = "ckb"; -/// hardcode rfc0028 epoch -pub const RFC0028_START_EPOCH: u64 = 5414; /// First epoch number for CKB v2021, at about 2022/05/10 1:00 UTC -// pub const CKB2021_START_EPOCH: u64 = 5414; -pub const CKB2021_START_EPOCH: u64 = 0; +pub const CKB2021_START_EPOCH: u64 = 5414; /// hardcode ckb2023 epoch pub const CKB2023_START_EPOCH: u64 = u64::MAX; diff --git a/util/constant/src/hardfork/testnet.rs b/util/constant/src/hardfork/testnet.rs index 362df34df3..dbc94cb46b 100644 --- a/util/constant/src/hardfork/testnet.rs +++ b/util/constant/src/hardfork/testnet.rs @@ -1,11 +1,8 @@ /// The Chain Specification name. pub const CHAIN_SPEC_NAME: &str = "ckb_testnet"; -/// hardcode rfc0028 epoch -pub const RFC0028_START_EPOCH: u64 = 3113; /// First epoch number for CKB v2021, at about 2021/10/24 3:15 UTC. -// pub const CKB2021_START_EPOCH: u64 = 3113; -pub const CKB2021_START_EPOCH: u64 = 0; +pub const CKB2021_START_EPOCH: u64 = 3113; /// hardcode ckb2023 epoch pub const CKB2023_START_EPOCH: u64 = u64::MAX; diff --git a/util/launcher/src/lib.rs b/util/launcher/src/lib.rs index ad56947f35..5ceda92478 100644 --- a/util/launcher/src/lib.rs +++ b/util/launcher/src/lib.rs @@ -204,10 +204,10 @@ impl Launcher { &self.args.config.db, Some(self.args.config.ancient.clone()), self.async_handle.clone(), + self.args.consensus.clone(), )?; let (shared, pack) = shared_builder - .consensus(self.args.consensus.clone()) .tx_pool_config(self.args.config.tx_pool.clone()) .notify_config(self.args.config.notify.clone()) .store_config(self.args.config.store) diff --git a/util/launcher/src/migrate.rs b/util/launcher/src/migrate.rs index 99d6a65b7e..f338003b41 100644 --- a/util/launcher/src/migrate.rs +++ b/util/launcher/src/migrate.rs @@ -5,6 +5,7 @@ use ckb_db::{ReadOnlyDB, RocksDB}; use ckb_db_migration::{DefaultMigration, Migrations}; use ckb_db_schema::{COLUMNS, COLUMN_META}; use ckb_error::Error; +use ckb_types::core::hardfork::HardForks; use std::cmp::Ordering; use std::path::PathBuf; @@ -18,7 +19,7 @@ pub struct Migrate { impl Migrate { /// Construct new migrate - pub fn new>(path: P) -> Self { + pub fn new>(path: P, hardforks: HardForks) -> Self { let mut migrations = Migrations::default(); migrations.add_migration(Box::new(DefaultMigration::new(INIT_DB_VERSION))); migrations.add_migration(Box::new(migrations::ChangeMoleculeTableToStruct)); // since v0.35.0 @@ -29,6 +30,7 @@ impl Migrate { migrations.add_migration(Box::new(migrations::AddChainRootMMR)); // TODO(light-client) update the comment: which version? migrations.add_migration(Box::new(migrations::AddBlockFilterColumnFamily)); // since v0.105.0 migrations.add_migration(Box::new(migrations::AddBlockFilterHash)); // since v0.108.0 + migrations.add_migration(Box::new(migrations::BlockExt2019ToZero::new(hardforks))); // since v0.111.1 Migrate { migrations, diff --git a/util/launcher/src/migrations/mod.rs b/util/launcher/src/migrations/mod.rs index 37e6136371..bc6b1e4338 100644 --- a/util/launcher/src/migrations/mod.rs +++ b/util/launcher/src/migrations/mod.rs @@ -5,6 +5,7 @@ mod add_chain_root_mmr; mod add_extra_data_hash; mod add_number_hash_mapping; mod cell; +mod set_2019_block_cycle_zero; mod table_to_struct; pub use add_block_extension_cf::AddBlockExtensionColumnFamily; @@ -14,4 +15,5 @@ pub use add_chain_root_mmr::AddChainRootMMR; pub use add_extra_data_hash::AddExtraDataHash; pub use add_number_hash_mapping::AddNumberHashMapping; pub use cell::CellMigration; +pub use set_2019_block_cycle_zero::BlockExt2019ToZero; pub use table_to_struct::ChangeMoleculeTableToStruct; diff --git a/util/launcher/src/migrations/set_2019_block_cycle_zero.rs b/util/launcher/src/migrations/set_2019_block_cycle_zero.rs new file mode 100644 index 0000000000..48291aae06 --- /dev/null +++ b/util/launcher/src/migrations/set_2019_block_cycle_zero.rs @@ -0,0 +1,90 @@ +use ckb_app_config::StoreConfig; +use ckb_db_migration::{Migration, ProgressBar, ProgressStyle}; +use ckb_db_schema::COLUMN_EPOCH; +use ckb_store::{ChainDB, ChainStore}; +use ckb_types::{ + core::hardfork::HardForks, + packed, + prelude::{Entity, FromSliceShouldBeOk, Pack, Reader}, +}; + +const VERSION: &str = "20231101000000"; +pub struct BlockExt2019ToZero { + hardforks: HardForks, +} + +impl BlockExt2019ToZero { + pub fn new(hardforks: HardForks) -> Self { + BlockExt2019ToZero { hardforks } + } +} + +impl Migration for BlockExt2019ToZero { + fn migrate( + &self, + db: ckb_db::RocksDB, + pb: std::sync::Arc ProgressBar + Send + Sync>, + ) -> Result { + let chain_db = ChainDB::new(db, StoreConfig::default()); + let limit_epoch = self.hardforks.ckb2021.rfc_0032(); + + if limit_epoch == 0 { + return Ok(chain_db.into_inner()); + } + + let epoch_number: packed::Uint64 = limit_epoch.pack(); + if let Some(epoch_hash) = chain_db.get(COLUMN_EPOCH, epoch_number.as_slice()) { + let epoch_ext = chain_db + .get_epoch_ext( + &packed::Byte32Reader::from_slice_should_be_ok(epoch_hash.as_ref()).to_entity(), + ) + .expect("db must have epoch ext"); + let mut header = chain_db + .get_block_header(&epoch_ext.last_block_hash_in_previous_epoch()) + .expect("db must have header"); + + let pb = ::std::sync::Arc::clone(&pb); + let pbi = pb(header.number() + 1); + pbi.set_style( + ProgressStyle::default_bar() + .template( + "{prefix:.bold.dim} {spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta}) {msg}", + ) + .progress_chars("#>-"), + ); + pbi.set_position(0); + pbi.enable_steady_tick(5000); + + loop { + let db_txn = chain_db.begin_transaction(); + for _ in 0..10000 { + let hash = header.hash(); + + let mut old_block_ext = db_txn.get_block_ext(&hash).unwrap(); + old_block_ext.cycles = None; + db_txn.insert_block_ext(&hash, &old_block_ext)?; + + header = db_txn + .get_block_header(&header.parent_hash()) + .expect("db must have header"); + + pbi.inc(1); + + if header.is_genesis() { + break; + } + } + db_txn.commit()?; + + if header.is_genesis() { + break; + } + } + } + + Ok(chain_db.into_inner()) + } + fn version(&self) -> &str { + VERSION + } +} diff --git a/util/launcher/src/shared_builder.rs b/util/launcher/src/shared_builder.rs index e1ad368a24..7f98c6ff98 100644 --- a/util/launcher/src/shared_builder.rs +++ b/util/launcher/src/shared_builder.rs @@ -26,6 +26,7 @@ use ckb_tx_pool::{ error::Reject, service::TxVerificationResult, TokioRwLock, TxEntry, TxPool, TxPoolServiceBuilder, }; +use ckb_types::core::hardfork::HardForks; use ckb_types::core::EpochExt; use ckb_types::core::HeaderView; use ckb_verification::cache::init_cache; @@ -40,7 +41,7 @@ use tempfile::TempDir; pub struct SharedBuilder { db: RocksDB, ancient_path: Option, - consensus: Option, + consensus: Consensus, tx_pool_config: Option, store_config: Option, block_assembler_config: Option, @@ -52,8 +53,9 @@ pub fn open_or_create_db( bin_name: &str, root_dir: &Path, config: &DBConfig, + hardforks: HardForks, ) -> Result { - let migrate = Migrate::new(&config.path); + let migrate = Migrate::new(&config.path, hardforks); let read_only_db = migrate.open_read_only_db().map_err(|e| { eprintln!("migrate error {e}"); @@ -121,13 +123,19 @@ impl SharedBuilder { db_config: &DBConfig, ancient: Option, async_handle: Handle, + consensus: Consensus, ) -> Result { - let db = open_or_create_db(bin_name, root_dir, db_config)?; + let db = open_or_create_db( + bin_name, + root_dir, + db_config, + consensus.hardfork_switch.clone(), + )?; Ok(SharedBuilder { db, ancient_path: ancient, - consensus: None, + consensus, tx_pool_config: None, notify_config: None, store_config: None, @@ -172,7 +180,7 @@ impl SharedBuilder { RUNTIME_HANDLE.with(|runtime| SharedBuilder { db, ancient_path: None, - consensus: None, + consensus: Consensus::default(), tx_pool_config: None, notify_config: None, store_config: None, @@ -185,7 +193,7 @@ impl SharedBuilder { impl SharedBuilder { /// TODO(doc): @quake pub fn consensus(mut self, value: Consensus) -> Self { - self.consensus = Some(value); + self.consensus = value; self } @@ -318,7 +326,7 @@ impl SharedBuilder { let tx_pool_config = tx_pool_config.unwrap_or_default(); let notify_config = notify_config.unwrap_or_default(); let store_config = store_config.unwrap_or_default(); - let consensus = Arc::new(consensus.unwrap_or_default()); + let consensus = Arc::new(consensus); let notify_controller = start_notify_service(notify_config, async_handle.clone()); diff --git a/util/launcher/src/tests.rs b/util/launcher/src/tests.rs index ba68c542d6..73ec9da409 100644 --- a/util/launcher/src/tests.rs +++ b/util/launcher/src/tests.rs @@ -9,7 +9,9 @@ use ckb_db_schema::{ }; use ckb_systemtime::unix_time_as_millis; use ckb_types::{ - core::{capacity_bytes, BlockBuilder, BlockExt, Capacity, TransactionBuilder}, + core::{ + capacity_bytes, hardfork::HardForks, BlockBuilder, BlockExt, Capacity, TransactionBuilder, + }, packed::{self, Bytes}, prelude::*, utilities::DIFF_TWO, @@ -149,13 +151,13 @@ fn test_mock_migration() { drop(db_txn); drop(db); - let mg = Migrate::new(tmp_dir.as_ref().to_path_buf()); + let mg = Migrate::new(tmp_dir.as_ref().to_path_buf(), HardForks::new_mirana()); let db = mg.open_bulk_load_db().unwrap().unwrap(); mg.migrate(db).unwrap(); - let mg2 = Migrate::new(tmp_dir.as_ref().to_path_buf()); + let mg2 = Migrate::new(tmp_dir.as_ref().to_path_buf(), HardForks::new_mirana()); let rdb = mg2.open_read_only_db().unwrap().unwrap(); diff --git a/util/types/src/core/hardfork/ckb2021.rs b/util/types/src/core/hardfork/ckb2021.rs index ffe10d3e95..1b2ea50073 100644 --- a/util/types/src/core/hardfork/ckb2021.rs +++ b/util/types/src/core/hardfork/ckb2021.rs @@ -87,13 +87,13 @@ impl CKB2021 { pub fn new_mirana() -> Self { // Use a builder to ensure all features are set manually. Self::new_builder() - .rfc_0028(hardfork::mainnet::RFC0028_START_EPOCH) - .rfc_0029(0) - .rfc_0030(0) - .rfc_0031(0) - .rfc_0032(0) - .rfc_0036(0) - .rfc_0038(0) + .rfc_0028(hardfork::mainnet::CKB2021_START_EPOCH) + .rfc_0029(hardfork::mainnet::CKB2021_START_EPOCH) + .rfc_0030(hardfork::mainnet::CKB2021_START_EPOCH) + .rfc_0031(hardfork::mainnet::CKB2021_START_EPOCH) + .rfc_0032(hardfork::mainnet::CKB2021_START_EPOCH) + .rfc_0036(hardfork::mainnet::CKB2021_START_EPOCH) + .rfc_0038(hardfork::mainnet::CKB2021_START_EPOCH) .build() .unwrap() }