diff --git a/Cargo.lock b/Cargo.lock index 2badeff6e55..31ed1c9b068 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1442,6 +1442,7 @@ dependencies = [ "bit-vec", "bytes 1.4.0", "ckb-channel", + "ckb-constant", "ckb-error", "ckb-fixed-hash", "ckb-hash", @@ -1454,6 +1455,7 @@ dependencies = [ "molecule", "numext-fixed-uint", "once_cell", + "paste", "proptest", ] diff --git a/chain/src/tests/load_code_with_snapshot.rs b/chain/src/tests/load_code_with_snapshot.rs index ee698c534b3..206339e38a3 100644 --- a/chain/src/tests/load_code_with_snapshot.rs +++ b/chain/src/tests/load_code_with_snapshot.rs @@ -8,8 +8,10 @@ use ckb_types::prelude::*; use ckb_types::{ bytes::Bytes, core::{ - capacity_bytes, hardfork::HardForkSwitch, BlockBuilder, Capacity, EpochNumberWithFraction, - ScriptHashType, TransactionBuilder, TransactionView, + capacity_bytes, + hardfork::{HardForks, CKB2021, CKB2023}, + BlockBuilder, Capacity, EpochNumberWithFraction, ScriptHashType, TransactionBuilder, + TransactionView, }, packed::{self, CellDep, CellInput, CellOutputBuilder, OutPoint, Script}, utilities::DIFF_TWO, @@ -235,11 +237,14 @@ fn _test_load_code_with_snapshot_after_hardfork(script_type: ScriptHashType) { .dao(dao) .build(); - let hardfork_switch = HardForkSwitch::new_mirana() - .as_builder() - .rfc_0032(0) - .build() - .unwrap(); + let hardfork_switch = HardForks { + ckb2021: CKB2021::new_mirana() + .as_builder() + .rfc_0032(0) + .build() + .unwrap(), + ckb2023: CKB2023::new_builder().build().unwrap(), + }; let consensus = ConsensusBuilder::default() .cellbase_maturity(EpochNumberWithFraction::new(0, 0, 1)) .genesis_block(genesis_block) diff --git a/resource/specs/dev.toml b/resource/specs/dev.toml index 6e5609bb623..0f5b32a817f 100644 --- a/resource/specs/dev.toml +++ b/resource/specs/dev.toml @@ -96,13 +96,7 @@ genesis_epoch_length = 1000 permanent_difficulty_in_dummy = true [params.hardfork] -rfc_0028 = 0 -rfc_0029 = 0 -rfc_0030 = 0 -rfc_0031 = 0 -rfc_0032 = 0 -rfc_0036 = 0 -rfc_0038 = 0 + [pow] func = "Dummy" diff --git a/resource/specs/staging.toml b/resource/specs/staging.toml index a4de2981728..85aeca4027a 100644 --- a/resource/specs/staging.toml +++ b/resource/specs/staging.toml @@ -94,13 +94,7 @@ epoch_duration_target = 14400 genesis_epoch_length = 1000 [params.hardfork] -rfc_0028 = 0 -rfc_0029 = 0 -rfc_0030 = 0 -rfc_0031 = 0 -rfc_0032 = 0 -rfc_0036 = 0 -rfc_0038 = 0 + [pow] func = "Eaglesong" diff --git a/rpc/README.md b/rpc/README.md index fe976772fdc..da10cfc19c9 100644 --- a/rpc/README.md +++ b/rpc/README.md @@ -137,7 +137,7 @@ The crate `ckb-rpc`'s minimum supported rustc version is 1.67.1. * [Type `EstimateCycles`](#type-estimatecycles) * [Type `FeeRateStatics`](#type-feeratestatics) * [Type `H256`](#type-h256) - * [Type `HardForkFeature`](#type-hardforkfeature) + * [Type `HardForks`](#type-hardforks) * [Type `Header`](#type-header) * [Type `HeaderView`](#type-headerview) * [Type `IndexerCell`](#type-indexercell) @@ -1647,15 +1647,18 @@ Response "dao_type_hash": null, "epoch_duration_target": "0x3840", "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" } - ], + "hardfork_features": { + "ckb2021": [ + { "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" } + ], + "ckb2023": [] + }, "id": "main", "initial_primary_epoch_reward": "0x71afd498d000", "max_block_bytes": "0x91c08", @@ -5607,7 +5610,7 @@ Consensus defines various parameters that influence chain consensus * `permanent_difficulty_in_dummy`: `boolean` - Keep difficulty be permanent if the pow is dummy -* `hardfork_features`: `Array<` [`HardForkFeature`](#type-hardforkfeature) `>` - Hardfork features +* `hardfork_features`: [`HardForks`](#type-hardforks) - Hardfork features ### Type `Cycle` @@ -5801,17 +5804,10 @@ The fee_rate statistics information, includes mean and median, unit: shannons pe The 256-bit binary data encoded as a 0x-prefixed hex string in JSON. -### Type `HardForkFeature` - -The information about one hardfork feature. - -#### Fields - -`HardForkFeature` is a JSON object with the following fields. +### Type `HardForks` -* `rfc`: `string` - The related RFC ID. +Returns a list of hardfork features from a hardfork switch. -* `epoch_number`: [`EpochNumber`](#type-epochnumber) `|` `null` - The first epoch when the feature is enabled, `null` indicates that the RFC has never been enabled. ### Type `Header` diff --git a/rpc/src/module/chain.rs b/rpc/src/module/chain.rs index 26ac83029ef..c4be4e284bb 100644 --- a/rpc/src/module/chain.rs +++ b/rpc/src/module/chain.rs @@ -1333,15 +1333,18 @@ pub trait ChainRpc { /// "dao_type_hash": null, /// "epoch_duration_target": "0x3840", /// "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" } - /// ], + /// "hardfork_features": { + /// "ckb2021": [ + /// { "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" } + /// ], + /// "ckb2023": [] + /// }, /// "id": "main", /// "initial_primary_epoch_reward": "0x71afd498d000", /// "max_block_bytes": "0x91c08", diff --git a/script/fuzz/fuzz_targets/syscall_exec.rs b/script/fuzz/fuzz_targets/syscall_exec.rs index abf25524601..de08f868211 100644 --- a/script/fuzz/fuzz_targets/syscall_exec.rs +++ b/script/fuzz/fuzz_targets/syscall_exec.rs @@ -8,7 +8,6 @@ use ckb_types::{ core::{ capacity_bytes, cell::{CellMetaBuilder, ResolvedTransaction}, - hardfork::HardForkSwitch, Capacity, HeaderView, ScriptHashType, TransactionBuilder, TransactionInfo, }, packed::{ diff --git a/script/fuzz/fuzz_targets/transaction_scripts_verifier_data1.rs b/script/fuzz/fuzz_targets/transaction_scripts_verifier_data1.rs index b9221e15afe..bbce77e9557 100644 --- a/script/fuzz/fuzz_targets/transaction_scripts_verifier_data1.rs +++ b/script/fuzz/fuzz_targets/transaction_scripts_verifier_data1.rs @@ -9,7 +9,6 @@ use ckb_types::{ core::{ capacity_bytes, cell::{CellMetaBuilder, ResolvedTransaction}, - hardfork::HardForkSwitch, Capacity, HeaderView, ScriptHashType, TransactionBuilder, TransactionInfo, }, h256, diff --git a/spec/src/consensus.rs b/spec/src/consensus.rs index 6cf3f790f4a..5315c136c13 100644 --- a/spec/src/consensus.rs +++ b/spec/src/consensus.rs @@ -25,7 +25,7 @@ use ckb_types::{ bytes::Bytes, constants::{BLOCK_VERSION, TX_VERSION}, core::{ - hardfork::HardForkSwitch, BlockBuilder, BlockNumber, BlockView, Capacity, Cycle, EpochExt, + hardfork::HardForks, BlockBuilder, BlockNumber, BlockView, Capacity, Cycle, EpochExt, EpochNumber, EpochNumberWithFraction, HeaderView, Ratio, TransactionBuilder, TransactionView, Version, }, @@ -282,7 +282,7 @@ impl ConsensusBuilder { primary_epoch_reward_halving_interval: DEFAULT_PRIMARY_EPOCH_REWARD_HALVING_INTERVAL, permanent_difficulty_in_dummy: false, - hardfork_switch: HardForkSwitch::new_mirana(), + hardfork_switch: HardForks::new_mirana(), deployments: HashMap::new(), versionbits_caches: VersionbitsCache::default(), }, @@ -468,7 +468,7 @@ impl ConsensusBuilder { } /// Sets a hard fork switch for the new Consensus. - pub fn hardfork_switch(mut self, hardfork_switch: HardForkSwitch) -> Self { + pub fn hardfork_switch(mut self, hardfork_switch: HardForks) -> Self { self.inner.hardfork_switch = hardfork_switch; self } @@ -554,7 +554,7 @@ pub struct Consensus { /// Keep difficulty be permanent if the pow is dummy pub permanent_difficulty_in_dummy: bool, /// A switch to select hard fork features base on the epoch number. - pub hardfork_switch: HardForkSwitch, + pub hardfork_switch: HardForks, /// Soft fork deployments pub deployments: HashMap, /// Soft fork state cache @@ -951,7 +951,7 @@ impl Consensus { } /// Returns the hardfork switch. - pub fn hardfork_switch(&self) -> &HardForkSwitch { + pub fn hardfork_switch(&self) -> &HardForks { &self.hardfork_switch } @@ -1062,9 +1062,7 @@ impl From for ckb_jsonrpc_types::Consensus { .primary_epoch_reward_halving_interval .into(), permanent_difficulty_in_dummy: consensus.permanent_difficulty_in_dummy, - hardfork_features: ckb_jsonrpc_types::HardForkFeature::load_list_from_switch( - &consensus.hardfork_switch, - ), + hardfork_features: ckb_jsonrpc_types::HardForks::new(&consensus.hardfork_switch), } } } diff --git a/spec/src/hardfork.rs b/spec/src/hardfork.rs index d887e3a19a1..82d6be61b7d 100644 --- a/spec/src/hardfork.rs +++ b/spec/src/hardfork.rs @@ -2,7 +2,7 @@ use ckb_constant::hardfork::{mainnet, testnet}; use ckb_types::core::{ - hardfork::{HardForkSwitch, HardForkSwitchBuilder}, + hardfork::{CKB2021Builder, HardForks, CKB2021, CKB2023}, EpochNumber, }; use serde::{Deserialize, Serialize}; @@ -10,124 +10,77 @@ use serde::{Deserialize, Serialize}; /// Hard forks parameters for spec. #[derive(Default, Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] #[serde(deny_unknown_fields)] -pub struct HardForkConfig { - /// Use input cell committing block timestamp as the start time for the relative timestamp in `since`. - /// - /// Ref: [CKB RFC 0028](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0028-change-since-relative-timestamp/0028-change-since-relative-timestamp.md) - #[serde(skip_serializing_if = "Option::is_none")] - pub rfc_0028: Option, - /// Allow Multiple Cell Dep Matches When There Is No Ambiguity. - /// - /// Ref: [CKB RFC 0029](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0029-allow-script-multiple-matches-on-identical-code/0029-allow-script-multiple-matches-on-identical-code.md) - #[serde(skip_serializing_if = "Option::is_none")] - pub rfc_0029: Option, - /// Ensure That Index Is Less Than Length In the Input Since Field Using Epoch With Fraction. - /// - /// Ref: [CKB RFC 0030](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0030-ensure-index-less-than-length-in-since/0030-ensure-index-less-than-length-in-since.md) - #[serde(skip_serializing_if = "Option::is_none")] - pub rfc_0030: Option, - /// Add a variable length field in the block: reuse `uncles_hash` in the header as `extra_hash`. - /// - /// Ref: [CKB RFC 0031](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0031-variable-length-header-field/0031-variable-length-header-field.md) - #[serde(skip_serializing_if = "Option::is_none")] - pub rfc_0031: Option, - /// CKB VM Version Selection. - /// - /// This feature include 4 parts: - /// - CKB VM Version Selection. - /// - CKB VM version 1. - /// - CKB VM Syscalls 2. - /// - P2P protocol upgrade. - /// - /// Ref: - /// - [CKB RFC 0032](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0032-ckb-vm-version-selection/0032-ckb-vm-version-selection.md) - /// - [CKB RFC 0033](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0033-ckb-vm-version-1/0033-ckb-vm-version-1.md) - /// - [CKB RFC 0034](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0034-vm-syscalls-2/0034-vm-syscalls-2.md) - /// - [CKB RFC 0035](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0035-ckb2021-p2p-protocol-upgrade/0035-ckb2021-p2p-protocol-upgrade.md) - #[serde(skip_serializing_if = "Option::is_none")] - pub rfc_0032: Option, - /// Remove Header Deps Immature Rule. - /// - /// Ref: [CKB RFC 0036](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0036-remove-header-deps-immature-rule/0036-remove-header-deps-immature-rule.md) - #[serde(skip_serializing_if = "Option::is_none")] - pub rfc_0036: Option, - // TODO ckb2021 update the description and the rfc link - /// Disallow over the max dep expansion limit. - /// - /// Ref: CKB RFC 0038 - #[serde(skip_serializing_if = "Option::is_none")] - pub rfc_0038: Option, -} +pub struct HardForkConfig {} -macro_rules! check_default { - ($config:ident, $feature:ident, $expected:expr) => { - if $config.$feature.is_some() { - let errmsg = format!( - "Found the hard fork feature parameter \"{}\" is the chain specification file. - Don't set any hard fork parameters for \"mainnet\" or \"testnet\".", - stringify!($feature), - ); - return Err(errmsg); - } else { - $expected - } - }; -} +// macro_rules! check_default { +// ($config:ident, $feature:ident, $expected:expr) => { +// if $config.$feature.is_some() { +// let errmsg = format!( +// "Found the hard fork feature parameter \"{}\" is the chain specification file. +// Don't set any hard fork parameters for \"mainnet\" or \"testnet\".", +// stringify!($feature), +// ); +// return Err(errmsg); +// } else { +// $expected +// } +// }; +// } impl HardForkConfig { /// If all parameters which have been set are correct for mainnet, then /// sets all `None` to default values, otherwise, return an `Err`. - pub fn complete_mainnet(&self) -> Result { - let mut b = HardForkSwitch::new_builder(); - b = self.update_builder_via_edition( - b, + 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, )?; - b.build() + + Ok(HardForks { + ckb2021: ckb2021.build()?, + ckb2023: CKB2023::new_builder().build()?, + }) } /// If all parameters which have been set are correct for testnet, then /// sets all `None` to default values, otherwise, return an `Err`. - pub fn complete_testnet(&self) -> Result { - let mut b = HardForkSwitch::new_builder(); - b = self.update_builder_via_edition( - b, + 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, )?; - b.build() + + Ok(HardForks { + ckb2021: ckb2021.build()?, + ckb2023: CKB2023::new_builder().build()?, + }) } - fn update_builder_via_edition( + fn update_2021( &self, - builder: HardForkSwitchBuilder, + builder: CKB2021Builder, ckb2021: EpochNumber, rfc_0028_start: EpochNumber, - ) -> Result { + ) -> Result { let builder = builder - .rfc_0028(check_default!(self, rfc_0028, rfc_0028_start)) - .rfc_0029(check_default!(self, rfc_0029, ckb2021)) - .rfc_0030(check_default!(self, rfc_0030, ckb2021)) - .rfc_0031(check_default!(self, rfc_0031, ckb2021)) - .rfc_0032(check_default!(self, rfc_0032, ckb2021)) - .rfc_0036(check_default!(self, rfc_0036, ckb2021)) - .rfc_0038(check_default!(self, rfc_0038, ckb2021)); + .rfc_0028(rfc_0028_start) + .rfc_0029(ckb2021) + .rfc_0030(ckb2021) + .rfc_0031(ckb2021) + .rfc_0032(ckb2021) + .rfc_0036(ckb2021) + .rfc_0038(ckb2021); Ok(builder) } /// Converts to a hard fork switch. /// /// Enable features which are set to `None` at the user provided epoch. - pub fn complete_with_default(&self, default: EpochNumber) -> Result { - HardForkSwitch::new_builder() - .rfc_0028(self.rfc_0028.unwrap_or(default)) - .rfc_0029(self.rfc_0029.unwrap_or(default)) - .rfc_0030(self.rfc_0030.unwrap_or(default)) - .rfc_0031(self.rfc_0031.unwrap_or(default)) - .rfc_0032(self.rfc_0032.unwrap_or(default)) - .rfc_0036(self.rfc_0036.unwrap_or(default)) - .rfc_0038(self.rfc_0038.unwrap_or(default)) - .build() + pub fn complete_with_default(&self, _default: EpochNumber) -> Result { + Ok(HardForks::new_mirana()) } } diff --git a/spec/src/lib.rs b/spec/src/lib.rs index cd69fea49db..647e49a83a0 100644 --- a/spec/src/lib.rs +++ b/spec/src/lib.rs @@ -28,8 +28,8 @@ use ckb_resource::{ use ckb_types::{ bytes::Bytes, core::{ - capacity_bytes, hardfork::HardForkSwitch, BlockBuilder, BlockNumber, BlockView, Capacity, - Cycle, EpochNumber, EpochNumberWithFraction, Ratio, ScriptHashType, TransactionBuilder, + capacity_bytes, hardfork::HardForks, BlockBuilder, BlockNumber, BlockView, Capacity, Cycle, + EpochNumber, EpochNumberWithFraction, Ratio, ScriptHashType, TransactionBuilder, TransactionView, }, h256, packed, @@ -494,7 +494,7 @@ impl ChainSpec { /// /// Verify the parameters for mainnet and testnet, because all start epoch numbers /// for mainnet and testnet are fixed. - fn build_hardfork_switch(&self) -> Result> { + fn build_hardfork_switch(&self) -> Result> { let config = self.params.hardfork.as_ref().cloned().unwrap_or_default(); match self.name.as_str() { mainnet::CHAIN_SPEC_NAME => config.complete_mainnet(), diff --git a/util/constant/src/hardfork/mainnet.rs b/util/constant/src/hardfork/mainnet.rs index c5ae4578967..df7fc333935 100644 --- a/util/constant/src/hardfork/mainnet.rs +++ b/util/constant/src/hardfork/mainnet.rs @@ -6,3 +6,6 @@ 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; + +/// 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 9855e57a9b7..362df34df33 100644 --- a/util/constant/src/hardfork/testnet.rs +++ b/util/constant/src/hardfork/testnet.rs @@ -6,3 +6,6 @@ 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; + +/// hardcode ckb2023 epoch +pub const CKB2023_START_EPOCH: u64 = u64::MAX; diff --git a/util/jsonrpc-types/src/blockchain.rs b/util/jsonrpc-types/src/blockchain.rs index d7aabab741c..e020ea6a602 100644 --- a/util/jsonrpc-types/src/blockchain.rs +++ b/util/jsonrpc-types/src/blockchain.rs @@ -1369,7 +1369,31 @@ pub struct Consensus { /// Keep difficulty be permanent if the pow is dummy pub permanent_difficulty_in_dummy: bool, /// Hardfork features - pub hardfork_features: Vec, + pub hardfork_features: HardForks, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct HardForks { + pub ckb2021: Vec, + pub ckb2023: Vec, +} + +impl HardForks { + /// Returns a list of hardfork features from a hardfork switch. + pub fn new(hardforks: &core::hardfork::HardForks) -> Self { + HardForks { + ckb2021: vec![ + HardForkFeature::new("0028", convert(hardforks.ckb2021.rfc_0028())), + HardForkFeature::new("0029", convert(hardforks.ckb2021.rfc_0029())), + HardForkFeature::new("0030", convert(hardforks.ckb2021.rfc_0030())), + HardForkFeature::new("0031", convert(hardforks.ckb2021.rfc_0031())), + HardForkFeature::new("0032", convert(hardforks.ckb2021.rfc_0032())), + HardForkFeature::new("0036", convert(hardforks.ckb2021.rfc_0036())), + HardForkFeature::new("0038", convert(hardforks.ckb2021.rfc_0038())), + ], + ckb2023: vec![], + } + } } /// The information about one hardfork feature. @@ -1397,19 +1421,6 @@ impl HardForkFeature { epoch_number, } } - - /// Returns a list of hardfork features from a hardfork switch. - pub fn load_list_from_switch(switch: &core::hardfork::HardForkSwitch) -> Vec { - vec![ - Self::new("0028", convert(switch.rfc_0028())), - Self::new("0029", convert(switch.rfc_0029())), - Self::new("0030", convert(switch.rfc_0030())), - Self::new("0031", convert(switch.rfc_0031())), - Self::new("0032", convert(switch.rfc_0032())), - Self::new("0036", convert(switch.rfc_0036())), - Self::new("0038", convert(switch.rfc_0038())), - ] - } } /// The fee_rate statistics information, includes mean and median, unit: shannons per kilo-weight diff --git a/util/jsonrpc-types/src/lib.rs b/util/jsonrpc-types/src/lib.rs index 9595e822c19..87059506007 100644 --- a/util/jsonrpc-types/src/lib.rs +++ b/util/jsonrpc-types/src/lib.rs @@ -27,10 +27,10 @@ pub use self::block_template::{ pub use self::blockchain::{ Block, BlockEconomicState, BlockFilter, BlockIssuance, BlockResponse, BlockView, BlockWithCyclesResponse, CellDep, CellInput, CellOutput, Consensus, DepType, EpochView, - FeeRateStatics, HardForkFeature, Header, HeaderView, MerkleProof, MinerReward, OutPoint, - ProposalWindow, Script, ScriptHashType, Status, Transaction, TransactionAndWitnessProof, - TransactionProof, TransactionView, TransactionWithStatusResponse, TxStatus, UncleBlock, - UncleBlockView, + FeeRateStatics, HardForkFeature, HardForks, Header, HeaderView, MerkleProof, MinerReward, + OutPoint, ProposalWindow, Script, ScriptHashType, Status, Transaction, + TransactionAndWitnessProof, TransactionProof, TransactionView, TransactionWithStatusResponse, + TxStatus, UncleBlock, UncleBlockView, }; pub use self::bytes::JsonBytes; pub use self::cell::{CellData, CellInfo, CellWithStatus}; diff --git a/util/types/Cargo.toml b/util/types/Cargo.toml index 30f37c84274..bdbe06ae67a 100644 --- a/util/types/Cargo.toml +++ b/util/types/Cargo.toml @@ -17,6 +17,7 @@ merkle-cbt = "0.3" ckb-occupied-capacity = { path = "../occupied-capacity", version = "= 0.110.0-pre" } ckb-hash = { path = "../hash", version = "= 0.110.0-pre" } ckb-channel = { path = "../channel", version = "= 0.110.0-pre" } +ckb-constant = { path = "../constant", version = "= 0.110.0-pre" } bit-vec = "0.6.3" ckb-error = { path = "../../error", version = "= 0.110.0-pre" } ckb-rational = { path = "../rational", version = "= 0.110.0-pre" } @@ -24,6 +25,7 @@ once_cell = "1.8.0" derive_more = { version = "0.99.0", default-features=false, features = ["display"] } ckb-merkle-mountain-range = "0.5.2" golomb-coded-set = "0.2.0" +paste = "1.0" [dev-dependencies] proptest = "1.0" diff --git a/util/types/src/core/hardfork.rs b/util/types/src/core/hardfork/ckb2021.rs similarity index 58% rename from util/types/src/core/hardfork.rs rename to util/types/src/core/hardfork/ckb2021.rs index d8dc14da685..0a1ecf39f07 100644 --- a/util/types/src/core/hardfork.rs +++ b/util/types/src/core/hardfork/ckb2021.rs @@ -1,99 +1,15 @@ -//! Hard forks related types. - use crate::core::EpochNumber; - -// Defines all methods for a feature. -macro_rules! define_methods { - ($feature:ident, $name_getter:ident, - $name_if_enabled:ident, $name_disable:ident, $rfc_name:literal) => { - define_methods!( - $feature, - $name_getter, - $name_if_enabled, - $name_disable, - concat!( - "Return the first epoch number when the [", - $rfc_name, - "](struct.HardForkSwitchBuilder.html#structfield.", - stringify!($feature), - ") is enabled." - ), - concat!( - "An alias for the method [", - stringify!($feature), - "(&self)](#method.", - stringify!($feature), - ") to let the code to be more readable." - ), - concat!( - "If the [", - $rfc_name, - "](struct.HardForkSwitchBuilder.html#structfield.", - stringify!($feature), - ") is enabled at the provided epoch." - ), - concat!( - "Set the first epoch number of the [", - $rfc_name, - "](struct.HardForkSwitchBuilder.html#structfield.", - stringify!($feature), - ")." - ), - concat!( - "Never enable the [", - $rfc_name, - "](struct.HardForkSwitchBuilder.html#structfield.", - stringify!($feature), - ")." - ) - ); - }; - ($feature:ident, $name_getter_alias:ident, - $name_if_enabled:ident, $name_disable:ident, - $comment_getter:expr,$comment_getter_alias:expr, $comment_if_enabled:expr, - $comment_setter:expr, $comment_disable:expr) => { - impl HardForkSwitch { - #[doc = $comment_getter] - #[inline] - pub fn $feature(&self) -> EpochNumber { - self.$feature - } - #[doc = $comment_getter_alias] - #[inline] - pub fn $name_getter_alias(&self) -> EpochNumber { - self.$feature - } - #[doc = $comment_if_enabled] - #[inline] - pub fn $name_if_enabled(&self, epoch_number: EpochNumber) -> bool { - epoch_number >= self.$feature - } - } - impl HardForkSwitchBuilder { - #[doc = $comment_setter] - #[inline] - pub fn $feature(mut self, epoch_number: EpochNumber) -> Self { - self.$feature = Some(epoch_number); - self - } - #[doc = $comment_disable] - #[inline] - pub fn $name_disable(mut self) -> Self { - self.$feature = Some(EpochNumber::MAX); - self - } - } - }; -} +use ckb_constant::hardfork; +use paste::paste; /// A switch to select hard fork features base on the epoch number. /// /// For safety, all fields are private and not allowed to update. -/// This structure can only be constructed by [`HardForkSwitchBuilder`]. +/// This structure can only be constructed by [`CKB2021Builder`]. /// -/// [`HardForkSwitchBuilder`]: struct.HardForkSwitchBuilder.html +/// [`CKB2021Builder`]: struct.CKB2021Builder.html #[derive(Debug, Clone)] -pub struct HardForkSwitch { +pub struct CKB2021 { rfc_0028: EpochNumber, rfc_0029: EpochNumber, rfc_0030: EpochNumber, @@ -103,11 +19,11 @@ pub struct HardForkSwitch { rfc_0038: EpochNumber, } -/// Builder for [`HardForkSwitch`]. +/// Builder for [`CKB2021`]. /// -/// [`HardForkSwitch`]: struct.HardForkSwitch.html +/// [`CKB2021`]: struct.CKB2021.html #[derive(Debug, Clone, Default)] -pub struct HardForkSwitchBuilder { +pub struct CKB2021Builder { /// Use input cell committing block timestamp as the start time for the relative timestamp in `since`. /// /// Ref: [CKB RFC 0028](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0028-change-since-relative-timestamp/0028-change-since-relative-timestamp.md) @@ -149,14 +65,14 @@ pub struct HardForkSwitchBuilder { pub rfc_0038: Option, } -impl HardForkSwitch { +impl CKB2021 { /// Creates a new builder to build an instance. - pub fn new_builder() -> HardForkSwitchBuilder { + pub fn new_builder() -> CKB2021Builder { Default::default() } /// Creates a new builder based on the current instance. - pub fn as_builder(&self) -> HardForkSwitchBuilder { + pub fn as_builder(&self) -> CKB2021Builder { Self::new_builder() .rfc_0028(self.rfc_0028()) .rfc_0029(self.rfc_0029()) @@ -171,7 +87,7 @@ impl HardForkSwitch { pub fn new_mirana() -> Self { // Use a builder to ensure all features are set manually. Self::new_builder() - .rfc_0028(5414) + .rfc_0028(hardfork::mainnet::RFC0028_START_EPOCH) .rfc_0029(0) .rfc_0030(0) .rfc_0031(0) @@ -196,6 +112,7 @@ impl HardForkSwitch { } define_methods!( + CKB2021, rfc_0028, block_ts_as_relative_since_start, is_block_ts_as_relative_since_start_enabled, @@ -203,6 +120,7 @@ define_methods!( "RFC PR 0028" ); define_methods!( + CKB2021, rfc_0029, allow_multiple_matches_on_identical_data, is_allow_multiple_matches_on_identical_data_enabled, @@ -210,6 +128,7 @@ define_methods!( "RFC PR 0029" ); define_methods!( + CKB2021, rfc_0030, check_length_in_epoch_since, is_check_length_in_epoch_since_enabled, @@ -217,6 +136,7 @@ define_methods!( "RFC PR 0030" ); define_methods!( + CKB2021, rfc_0031, reuse_uncles_hash_as_extra_hash, is_reuse_uncles_hash_as_extra_hash_enabled, @@ -224,6 +144,7 @@ define_methods!( "RFC PR 0031" ); define_methods!( + CKB2021, rfc_0032, vm_version_1_and_syscalls_2, is_vm_version_1_and_syscalls_2_enabled, @@ -231,6 +152,7 @@ define_methods!( "RFC PR 0032" ); define_methods!( + CKB2021, rfc_0036, remove_header_deps_immature_rule, is_remove_header_deps_immature_rule_enabled, @@ -238,6 +160,7 @@ define_methods!( "RFC PR 0036" ); define_methods!( + CKB2021, rfc_0038, disallow_over_max_dep_expansion_limit, is_disallow_over_max_dep_expansion_limit_enabled, @@ -245,30 +168,23 @@ define_methods!( "RFC PR 0038" ); -impl HardForkSwitchBuilder { - /// Build a new [`HardForkSwitch`]. +impl CKB2021Builder { + /// Build a new [`CKB2021`]. /// /// Returns an error if failed at any check, for example, there maybe are some features depend /// on others. /// - /// [`HardForkSwitch`]: struct.HardForkSwitch.html - pub fn build(self) -> Result { - macro_rules! try_find { - ($feature:ident) => { - self.$feature.ok_or_else(|| { - concat!("The feature ", stringify!($feature), " isn't configured.").to_owned() - })? - }; - } - let rfc_0028 = try_find!(rfc_0028); - let rfc_0029 = try_find!(rfc_0029); - let rfc_0030 = try_find!(rfc_0030); - let rfc_0031 = try_find!(rfc_0031); - let rfc_0032 = try_find!(rfc_0032); - let rfc_0036 = try_find!(rfc_0036); - let rfc_0038 = try_find!(rfc_0038); + /// [`CKB2021`]: struct.CKB2021.html + pub fn build(self) -> Result { + let rfc_0028 = try_find!(self, rfc_0028); + let rfc_0029 = try_find!(self, rfc_0029); + let rfc_0030 = try_find!(self, rfc_0030); + let rfc_0031 = try_find!(self, rfc_0031); + let rfc_0032 = try_find!(self, rfc_0032); + let rfc_0036 = try_find!(self, rfc_0036); + let rfc_0038 = try_find!(self, rfc_0038); - Ok(HardForkSwitch { + Ok(CKB2021 { rfc_0028, rfc_0029, rfc_0030, diff --git a/util/types/src/core/hardfork/ckb2023.rs b/util/types/src/core/hardfork/ckb2023.rs new file mode 100644 index 00000000000..94fc61bed4e --- /dev/null +++ b/util/types/src/core/hardfork/ckb2023.rs @@ -0,0 +1,41 @@ +// use crate::core::EpochNumber; +// use paste::paste; + +/// A switch to select hard fork features base on the epoch number. +/// +/// For safety, all fields are private and not allowed to update. +/// This structure can only be constructed by [`CKB2023Builder`]. +/// +/// [`CKB2023Builder`]: struct.CKB2023Builder.html +#[derive(Debug, Clone)] +pub struct CKB2023 {} + +/// Builder for [`CKB2023`]. +/// +/// [`CKB2023`]: struct.CKB2023.html +#[derive(Debug, Clone, Default)] +pub struct CKB2023Builder {} + +impl CKB2023 { + /// Creates a new builder to build an instance. + pub fn new_builder() -> CKB2023Builder { + Default::default() + } + + /// Creates a new builder based on the current instance. + pub fn as_builder(&self) -> CKB2023Builder { + Self::new_builder() + } +} + +impl CKB2023Builder { + /// Build a new [`CKB2023`]. + /// + /// Returns an error if failed at any check, for example, there maybe are some features depend + /// on others. + /// + /// [`CKB2023`]: struct.CKB2023.html + pub fn build(self) -> Result { + Ok(CKB2023 {}) + } +} diff --git a/util/types/src/core/hardfork/helper.rs b/util/types/src/core/hardfork/helper.rs new file mode 100644 index 00000000000..10aeefbeaa5 --- /dev/null +++ b/util/types/src/core/hardfork/helper.rs @@ -0,0 +1,47 @@ +macro_rules! define_methods { + ($name_struct:ident, $feature:ident, $name_getter:ident, + $name_if_enabled:ident, $name_disable:ident, $rfc_name:literal) => { + paste! { + impl $name_struct { + #[doc = "Return the first epoch number when the [" $rfc_name "](struct." $name_struct "Builder.html#structfield." $feature ") is enabled."] + #[inline] + pub fn $feature(&self) -> EpochNumber { + self.$feature + } + #[doc = "An alias for the method [" $feature "(&self)](#method." $feature ") to let the code to be more readable."] + #[inline] + pub fn $name_getter(&self) -> EpochNumber { + self.$feature + } + #[doc = "If the [" $rfc_name "](struct." $name_struct "Builder.html#structfield." $feature ") is enabled at the provided epoch."] + #[inline] + pub fn $name_if_enabled(&self, epoch_number: EpochNumber) -> bool { + epoch_number >= self.$feature + } + } + + impl [< $name_struct Builder >] { + #[doc = "Set the first epoch number of the [" $rfc_name "](struct." $name_struct "Builder.html#structfield." $feature ")."] + #[inline] + pub fn $feature(mut self, epoch_number: EpochNumber) -> Self { + self.$feature = Some(epoch_number); + self + } + #[doc = "Never enable the [" $rfc_name "](struct." $name_struct "Builder.html#structfield." $feature ")."] + #[inline] + pub fn $name_disable(mut self) -> Self { + self.$feature = Some(EpochNumber::MAX); + self + } + } + } + } +} + +macro_rules! try_find { + ($self:ident, $feature:ident) => { + $self.$feature.ok_or_else(|| { + concat!("The feature ", stringify!($feature), " isn't configured.").to_owned() + })? + }; +} diff --git a/util/types/src/core/hardfork/mod.rs b/util/types/src/core/hardfork/mod.rs new file mode 100644 index 00000000000..916fe41f444 --- /dev/null +++ b/util/types/src/core/hardfork/mod.rs @@ -0,0 +1,22 @@ +#[macro_use] +pub(crate) mod helper; +mod ckb2021; +mod ckb2023; + +pub use ckb2021::{CKB2021Builder, CKB2021}; +pub use ckb2023::{CKB2023Builder, CKB2023}; + +#[derive(Debug, Clone)] +pub struct HardForks { + pub ckb2021: CKB2021, + pub ckb2023: CKB2023, +} + +impl HardForks { + pub fn new_mirana() -> HardForks { + HardForks { + ckb2021: CKB2021::new_mirana(), + ckb2023: CKB2023 {}, + } + } +} diff --git a/verification/src/tests/transaction_verifier.rs b/verification/src/tests/transaction_verifier.rs index 7c8d00d81a0..60cb947cae3 100644 --- a/verification/src/tests/transaction_verifier.rs +++ b/verification/src/tests/transaction_verifier.rs @@ -13,7 +13,7 @@ use ckb_types::{ core::{ capacity_bytes, cell::{CellMetaBuilder, ResolvedTransaction}, - hardfork::HardForkSwitch, + hardfork::HardForks, BlockNumber, Capacity, EpochNumber, EpochNumberWithFraction, HeaderView, TransactionBuilder, TransactionInfo, TransactionView, }, @@ -545,7 +545,7 @@ fn test_fraction_epoch_since_verify_v2021() { }; { // Test CKB v2021 - let hardfork_switch = HardForkSwitch::new_mirana(); + let hardfork_switch = HardForks::new_mirana(); let consensus = ConsensusBuilder::default() .median_time_block_count(MOCK_MEDIAN_TIME_COUNT) .hardfork_switch(hardfork_switch) diff --git a/verification/src/transaction_verifier.rs b/verification/src/transaction_verifier.rs index 0acab87d310..a59c22181ae 100644 --- a/verification/src/transaction_verifier.rs +++ b/verification/src/transaction_verifier.rs @@ -728,6 +728,7 @@ impl<'a, DL: HeaderProvider> SinceVerifier<'a, DL> { let epoch_number = self.tx_env.epoch_number(proposal_window); let hardfork_switch = self.consensus.hardfork_switch(); let base_timestamp = if hardfork_switch + .ckb2021 .is_block_ts_as_relative_since_start_enabled(epoch_number) { self.data_loader