ckb_traits/
epoch_provider.rs1use ckb_types::{
2 core::{BlockExt, BlockNumber, EpochExt, HeaderView},
3 packed,
4};
5
6pub trait EpochProvider {
8 fn get_epoch_ext(&self, block_header: &HeaderView) -> Option<EpochExt>;
10 fn get_block_hash(&self, number: BlockNumber) -> Option<packed::Byte32>;
12 fn get_block_ext(&self, block_hash: &packed::Byte32) -> Option<BlockExt>;
14 fn get_block_header(&self, hash: &packed::Byte32) -> Option<HeaderView>;
16
17 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
52pub enum BlockEpoch {
54 TailBlock {
56 epoch: EpochExt,
58 epoch_uncles_count: u64,
60 epoch_duration_in_milliseconds: u64,
62 },
63 NonTailBlock {
65 epoch: EpochExt,
67 },
68}
69
70impl BlockEpoch {
71 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}