diff --git a/chain/src/chain.rs b/chain/src/chain.rs index c1915ed48e..8008eff1a8 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -1,6 +1,7 @@ //! CKB chain service. #![allow(missing_docs)] +use crate::forkchanges::ForkChanges; use ckb_channel::{self as channel, select, Sender}; use ckb_error::{Error, InternalErrorKind}; use ckb_logger::Level::Trace; @@ -19,11 +20,10 @@ use ckb_types::{ resolve_transaction, BlockCellProvider, HeaderChecker, OverlayCellProvider, ResolvedTransaction, }, - hardfork::HardForks, service::Request, BlockExt, BlockNumber, BlockView, Cycle, HeaderView, }, - packed::{Byte32, ProposalShortId}, + packed::Byte32, utilities::merkle_mountain_range::ChainRootMMR, U256, }; @@ -33,7 +33,7 @@ use ckb_verification_contextual::{ContextualBlockVerifier, VerifyContext}; use ckb_verification_traits::{Switch, Verifier}; #[cfg(debug_assertions)] use is_sorted::IsSorted; -use std::collections::{HashSet, VecDeque}; +use std::collections::HashSet; use std::sync::Arc; use std::time::Instant; use std::{cmp, thread}; @@ -102,85 +102,6 @@ impl ChainController { } } -/// The struct represent fork -#[derive(Debug, Default)] -pub struct ForkChanges { - /// Blocks attached to index after forks - pub(crate) attached_blocks: VecDeque, - /// Blocks detached from index after forks - pub(crate) detached_blocks: VecDeque, - /// HashSet with proposal_id detached to index after forks - pub(crate) detached_proposal_id: HashSet, - /// to be updated exts - pub(crate) dirty_exts: VecDeque, -} - -impl ForkChanges { - /// blocks attached to index after forks - pub fn attached_blocks(&self) -> &VecDeque { - &self.attached_blocks - } - - /// blocks detached from index after forks - pub fn detached_blocks(&self) -> &VecDeque { - &self.detached_blocks - } - - /// proposal_id detached to index after forks - pub fn detached_proposal_id(&self) -> &HashSet { - &self.detached_proposal_id - } - - /// are there any block should be detached - pub fn has_detached(&self) -> bool { - !self.detached_blocks.is_empty() - } - - /// cached verified attached block num - pub fn verified_len(&self) -> usize { - self.attached_blocks.len() - self.dirty_exts.len() - } - - /// assertion for make sure attached_blocks and detached_blocks are sorted - #[cfg(debug_assertions)] - pub fn is_sorted(&self) -> bool { - IsSorted::is_sorted_by_key(&mut self.attached_blocks().iter(), |blk| { - blk.header().number() - }) && IsSorted::is_sorted_by_key(&mut self.detached_blocks().iter(), |blk| { - blk.header().number() - }) - } - - pub fn during_hardfork(&self, hardfork_switch: &HardForks) -> bool { - let hardfork_during_detach = - self.check_if_hardfork_during_blocks(hardfork_switch, &self.detached_blocks); - let hardfork_during_attach = - self.check_if_hardfork_during_blocks(hardfork_switch, &self.attached_blocks); - - hardfork_during_detach || hardfork_during_attach - } - - fn check_if_hardfork_during_blocks( - &self, - hardfork: &HardForks, - blocks: &VecDeque, - ) -> bool { - if blocks.is_empty() { - false - } else { - // This method assumes that the input blocks are sorted and unique. - let rfc_0049 = hardfork.ckb2023.rfc_0049(); - let epoch_first = blocks.front().unwrap().epoch().number(); - let epoch_next = blocks - .back() - .unwrap() - .epoch() - .minimum_epoch_number_after_n_blocks(1); - epoch_first < rfc_0049 && rfc_0049 <= epoch_next - } - } -} - pub(crate) struct GlobalIndex { pub(crate) number: BlockNumber, pub(crate) hash: Byte32, diff --git a/chain/src/forkchanges.rs b/chain/src/forkchanges.rs new file mode 100644 index 0000000000..01e3415c67 --- /dev/null +++ b/chain/src/forkchanges.rs @@ -0,0 +1,84 @@ +use ckb_rust_unstable_port::IsSorted; +use ckb_types::core::hardfork::HardForks; +use ckb_types::core::{BlockExt, BlockView}; +use ckb_types::packed::ProposalShortId; +use std::collections::{HashSet, VecDeque}; + +/// The struct represent fork +#[derive(Debug, Default)] +pub struct ForkChanges { + /// Blocks attached to index after forks + pub(crate) attached_blocks: VecDeque, + /// Blocks detached from index after forks + pub(crate) detached_blocks: VecDeque, + /// HashSet with proposal_id detached to index after forks + pub(crate) detached_proposal_id: HashSet, + /// to be updated exts + pub(crate) dirty_exts: VecDeque, +} + +impl ForkChanges { + /// blocks attached to index after forks + pub fn attached_blocks(&self) -> &VecDeque { + &self.attached_blocks + } + + /// blocks detached from index after forks + pub fn detached_blocks(&self) -> &VecDeque { + &self.detached_blocks + } + + /// proposal_id detached to index after forks + pub fn detached_proposal_id(&self) -> &HashSet { + &self.detached_proposal_id + } + + /// are there any block should be detached + pub fn has_detached(&self) -> bool { + !self.detached_blocks.is_empty() + } + + /// cached verified attached block num + pub fn verified_len(&self) -> usize { + self.attached_blocks.len() - self.dirty_exts.len() + } + + /// assertion for make sure attached_blocks and detached_blocks are sorted + #[cfg(debug_assertions)] + pub fn is_sorted(&self) -> bool { + IsSorted::is_sorted_by_key(&mut self.attached_blocks().iter(), |blk| { + blk.header().number() + }) && IsSorted::is_sorted_by_key(&mut self.detached_blocks().iter(), |blk| { + blk.header().number() + }) + } + + pub fn during_hardfork(&self, hardfork_switch: &HardForks) -> bool { + let hardfork_during_detach = + self.check_if_hardfork_during_blocks(hardfork_switch, &self.detached_blocks); + let hardfork_during_attach = + self.check_if_hardfork_during_blocks(hardfork_switch, &self.attached_blocks); + + hardfork_during_detach || hardfork_during_attach + } + + fn check_if_hardfork_during_blocks( + &self, + hardfork: &HardForks, + blocks: &VecDeque, + ) -> bool { + if blocks.is_empty() { + false + } else { + // This method assumes that the input blocks are sorted and unique. + let rfc_0049 = hardfork.ckb2023.rfc_0049(); + let epoch_first = blocks.front().unwrap().epoch().number(); + let epoch_next = blocks + .back() + .unwrap() + .epoch() + .minimum_epoch_number_after_n_blocks(1); + epoch_first < rfc_0049 && rfc_0049 <= epoch_next + } + } +} diff --git a/chain/src/lib.rs b/chain/src/lib.rs index 5898633b83..6885da60b9 100644 --- a/chain/src/lib.rs +++ b/chain/src/lib.rs @@ -7,5 +7,6 @@ //! [`ChainController`]: chain/struct.ChainController.html pub mod chain; +mod forkchanges; #[cfg(test)] mod tests; diff --git a/chain/src/tests/find_fork.rs b/chain/src/tests/find_fork.rs index eb1f4208a8..270ea47662 100644 --- a/chain/src/tests/find_fork.rs +++ b/chain/src/tests/find_fork.rs @@ -1,4 +1,5 @@ -use crate::chain::{ChainService, ForkChanges}; +use crate::chain::ChainService; +use crate::forkchanges::ForkChanges; use ckb_chain_spec::consensus::{Consensus, ProposalWindow}; use ckb_shared::SharedBuilder; use ckb_store::ChainStore; @@ -495,7 +496,7 @@ fn test_fork_proposal_table() { assert_eq!( &vec![ packed::ProposalShortId::new([0u8, 0, 0, 0, 0, 0, 0, 0, 0, 3]), - packed::ProposalShortId::new([1u8, 0, 0, 0, 0, 0, 0, 0, 0, 4]) + packed::ProposalShortId::new([1u8, 0, 0, 0, 0, 0, 0, 0, 0, 4]), ] .into_iter() .collect::>(),