ckb_traits/
epoch_provider.rs

1use ckb_types::{
2    core::{BlockExt, BlockNumber, EpochExt, HeaderView},
3    packed,
4};
5
6/// Trait for epoch storage.
7pub trait EpochProvider {
8    /// Get corresponding `EpochExt` by block header
9    fn get_epoch_ext(&self, block_header: &HeaderView) -> Option<EpochExt>;
10    /// Get block header hash by block number
11    fn get_block_hash(&self, number: BlockNumber) -> Option<packed::Byte32>;
12    /// Get block ext by block header hash
13    fn get_block_ext(&self, block_hash: &packed::Byte32) -> Option<BlockExt>;
14    /// Get header by block header hash
15    fn get_block_header(&self, hash: &packed::Byte32) -> Option<HeaderView>;
16
17    /// Get corresponding epoch progress information by block header
18    fn get_block_epoch(&self, header: &HeaderView) -> Option<BlockEpoch> {
19        self.get_epoch_ext(header).map(|epoch| {
20            if header.number() != epoch.start_number() + epoch.length() - 1 {
21                BlockEpoch::NonTailBlock { epoch }
22            } else {
23                let last_block_hash_in_previous_epoch = if epoch.is_genesis() {
24                    self.get_block_hash(0).expect("genesis block stored")
25                } else {
26                    epoch.last_block_hash_in_previous_epoch()
27                };
28                let epoch_uncles_count = self
29                    .get_block_ext(&header.hash())
30                    .expect("stored block ext")
31                    .total_uncles_count
32                    - self
33                        .get_block_ext(&last_block_hash_in_previous_epoch)
34                        .expect("stored block ext")
35                        .total_uncles_count;
36                let epoch_duration_in_milliseconds = header.timestamp()
37                    - self
38                        .get_block_header(&last_block_hash_in_previous_epoch)
39                        .expect("stored block header")
40                        .timestamp();
41
42                BlockEpoch::TailBlock {
43                    epoch,
44                    epoch_uncles_count,
45                    epoch_duration_in_milliseconds,
46                }
47            }
48        })
49    }
50}
51
52/// Progress of block's corresponding epoch
53pub enum BlockEpoch {
54    /// Block is the tail block of epoch, provides extra statistics for next epoch generating or verifying
55    TailBlock {
56        /// epoch information
57        epoch: EpochExt,
58        /// epoch uncles count
59        epoch_uncles_count: u64,
60        /// epoch duration
61        epoch_duration_in_milliseconds: u64,
62    },
63    /// Non tail block of epoch
64    NonTailBlock {
65        /// epoch information
66        epoch: EpochExt,
67    },
68}
69
70impl BlockEpoch {
71    /// Return block's corresponding epoch information
72    pub fn epoch(self) -> EpochExt {
73        match self {
74            Self::TailBlock {
75                epoch,
76                epoch_uncles_count: _,
77                epoch_duration_in_milliseconds: _,
78            } => epoch,
79            Self::NonTailBlock { epoch } => epoch,
80        }
81    }
82}