From 4d75c5ce2c120f0210437a7f40df32dfa9fe1a1f Mon Sep 17 00:00:00 2001 From: Boyu Yang Date: Fri, 21 May 2021 18:27:54 +0800 Subject: [PATCH] feat(hardfork): use block timestamp of input cells as relative since start timestamp --- spec/src/hardfork.rs | 7 +++++- test/template/specs/integration.toml | 1 + util/types/src/core/hardfork.rs | 29 +++++++++++++++++++++--- verification/src/transaction_verifier.rs | 18 +++++++++++++-- 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/spec/src/hardfork.rs b/spec/src/hardfork.rs index 5b87e59374..091e298969 100644 --- a/spec/src/hardfork.rs +++ b/spec/src/hardfork.rs @@ -13,6 +13,8 @@ use serde::{Deserialize, Serialize}; pub struct HardForkConfig { // TODO ckb2021 Update all rfc numbers and fix all links, after all proposals are merged. /// Ref: [CKB RFC xxxx](https://github.com/nervosnetwork/rfcs/tree/master/rfcs/xxxx-rfc-title) + pub rfc_pr_0221: Option, + /// Ref: [CKB RFC xxxx](https://github.com/nervosnetwork/rfcs/tree/master/rfcs/xxxx-rfc-title) pub rfc_pr_0223: Option, } @@ -56,7 +58,9 @@ impl HardForkConfig { builder: HardForkSwitchBuilder, ckb2021: EpochNumber, ) -> Result { - let builder = builder.rfc_pr_0223(check_default!(self, rfc_pr_0223, ckb2021)); + let builder = builder + .rfc_pr_0221(check_default!(self, rfc_pr_0221, ckb2021)) + .rfc_pr_0223(check_default!(self, rfc_pr_0223, ckb2021)); Ok(builder) } @@ -65,6 +69,7 @@ impl HardForkConfig { /// 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_pr_0221(self.rfc_pr_0221.unwrap_or(default)) .rfc_pr_0223(self.rfc_pr_0223.unwrap_or(default)) .build() } diff --git a/test/template/specs/integration.toml b/test/template/specs/integration.toml index 9403f3b97e..15b3abf35c 100644 --- a/test/template/specs/integration.toml +++ b/test/template/specs/integration.toml @@ -69,6 +69,7 @@ epoch_duration_target = 14400 genesis_epoch_length = 1000 [params.hardfork] +rfc_pr_0221 = 9_223_372_036_854_775_807 rfc_pr_0223 = 9_223_372_036_854_775_807 [pow] diff --git a/util/types/src/core/hardfork.rs b/util/types/src/core/hardfork.rs index ea36749497..64631e4294 100644 --- a/util/types/src/core/hardfork.rs +++ b/util/types/src/core/hardfork.rs @@ -94,6 +94,7 @@ macro_rules! define_methods { /// [`HardForkSwitchBuilder`]: struct.HardForkSwitchBuilder.html #[derive(Debug, Clone)] pub struct HardForkSwitch { + rfc_pr_0221: EpochNumber, rfc_pr_0223: EpochNumber, } @@ -103,6 +104,11 @@ pub struct HardForkSwitch { #[derive(Debug, Clone, Default)] pub struct HardForkSwitchBuilder { // TODO ckb2021 Update all rfc numbers and fix all links, after all proposals are merged. + /// Use the input cell creation block timestamp as start time in the + /// "relative since timestamp". + /// + /// Ref: [CKB RFC xxxx](https://github.com/nervosnetwork/rfcs/tree/master/rfcs/xxxx-rfc-title) + pub rfc_pr_0221: Option, /// In the "since epoch", the index should be less than length and /// the length should be greater than zero. /// @@ -118,16 +124,29 @@ impl HardForkSwitch { /// Creates a new builder based on the current instance. pub fn as_builder(&self) -> HardForkSwitchBuilder { - Self::new_builder().rfc_pr_0223(self.rfc_pr_0223()) + Self::new_builder() + .rfc_pr_0221(self.rfc_pr_0221()) + .rfc_pr_0223(self.rfc_pr_0223()) } /// Creates a new instance that all hard fork features are disabled forever. pub fn new_without_any_enabled() -> Self { // Use a builder to ensure all features are set manually. - Self::new_builder().disable_rfc_pr_0223().build().unwrap() + Self::new_builder() + .disable_rfc_pr_0221() + .disable_rfc_pr_0223() + .build() + .unwrap() } } +define_methods!( + rfc_pr_0221, + block_ts_as_relative_since_start, + is_block_ts_as_relative_since_start_enabled, + disable_rfc_pr_0221, + "RFC PR 0221" +); define_methods!( rfc_pr_0223, check_length_in_epoch_since, @@ -151,7 +170,11 @@ impl HardForkSwitchBuilder { })?; }; } + let rfc_pr_0221 = try_find!(rfc_pr_0221); let rfc_pr_0223 = try_find!(rfc_pr_0223); - Ok(HardForkSwitch { rfc_pr_0223 }) + Ok(HardForkSwitch { + rfc_pr_0221, + rfc_pr_0223, + }) } } diff --git a/verification/src/transaction_verifier.rs b/verification/src/transaction_verifier.rs index 3413ad08e8..5d1d57dfdb 100644 --- a/verification/src/transaction_verifier.rs +++ b/verification/src/transaction_verifier.rs @@ -574,6 +574,11 @@ impl<'a, DL: HeaderProvider> SinceVerifier<'a, DL> { self.block_median_time(&parent_hash) } + fn parent_block_time(&self, block_hash: &Byte32) -> u64 { + let (timestamp, _, _) = self.data_loader.timestamp_and_parent(block_hash); + timestamp + } + fn block_median_time(&self, block_hash: &Byte32) -> u64 { if let Some(median_time) = self.median_timestamps_cache.borrow().peek(block_hash) { return *median_time; @@ -666,10 +671,19 @@ impl<'a, DL: HeaderProvider> SinceVerifier<'a, DL> { // parent of current block. // pass_median_time(input_cell's block) starts with cell_block_number - 1, // which is the parent of input_cell's block + let proposal_window = self.consensus.tx_proposal_window(); let parent_hash = self.tx_env.parent_hash(); - let cell_median_timestamp = self.parent_median_time(&info.block_hash); + let epoch_number = self.tx_env.epoch_number(proposal_window); + let hardfork_switch = self.consensus.hardfork_switch(); + let base_timestamp = if hardfork_switch + .is_block_ts_as_relative_since_start_enabled(epoch_number) + { + self.parent_median_time(&info.block_hash) + } else { + self.parent_block_time(&info.block_hash) + }; let current_median_time = self.block_median_time(&parent_hash); - if current_median_time < cell_median_timestamp + timestamp { + if current_median_time < base_timestamp + timestamp { return Err((TransactionError::Immature { index }).into()); } }