ckb_traits/
header_provider.rs

1use ckb_types::{
2    core::{BlockNumber, EpochNumberWithFraction, HeaderView},
3    packed::Byte32,
4};
5
6/// Trait for header storage
7pub trait HeaderProvider {
8    /// Get the header of the given block hash
9    fn get_header(&self, hash: &Byte32) -> Option<HeaderView>;
10}
11
12/// A compact representation of header fields, used for header verification and median time calculation
13pub struct HeaderFields {
14    /// Block hash
15    pub hash: Byte32,
16    /// Block number
17    pub number: BlockNumber,
18    /// Block epoch
19    pub epoch: EpochNumberWithFraction,
20    /// Block timestamp
21    pub timestamp: u64,
22    /// Block parent hash
23    pub parent_hash: Byte32,
24}
25
26/// Trait for header fields storage
27pub trait HeaderFieldsProvider {
28    /// Get the header fields of the given block hash
29    fn get_header_fields(&self, hash: &Byte32) -> Option<HeaderFields>;
30
31    /// Get past block median time, **including the timestamp of the given one**
32    fn block_median_time(&self, block_hash: &Byte32, median_block_count: usize) -> u64 {
33        let mut timestamps: Vec<u64> = Vec::with_capacity(median_block_count);
34        let mut block_hash = block_hash.clone();
35        for _ in 0..median_block_count {
36            let header_fields = self
37                .get_header_fields(&block_hash)
38                .expect("parent header exist");
39            timestamps.push(header_fields.timestamp);
40            block_hash = header_fields.parent_hash;
41
42            if header_fields.number == 0 {
43                break;
44            }
45        }
46
47        // return greater one if count is even.
48        timestamps.sort_unstable();
49        timestamps[timestamps.len() >> 1]
50    }
51}