ckb_verification/
header_verifier.rs1use crate::{
2 ALLOWED_FUTURE_BLOCKTIME, EpochError, NumberError, PowError, TimestampError, UnknownParentError,
3};
4use ckb_chain_spec::consensus::Consensus;
5use ckb_error::Error;
6use ckb_pow::PowEngine;
7use ckb_systemtime::unix_time_as_millis;
8use ckb_traits::HeaderFieldsProvider;
9use ckb_types::core::{BlockNumber, EpochNumberWithFraction, HeaderView};
10use ckb_verification_traits::Verifier;
11
12pub struct HeaderVerifier<'a, DL> {
16 data_loader: &'a DL,
17 consensus: &'a Consensus,
18}
19
20impl<'a, DL: HeaderFieldsProvider> HeaderVerifier<'a, DL> {
21 pub fn new(data_loader: &'a DL, consensus: &'a Consensus) -> Self {
23 HeaderVerifier {
24 consensus,
25 data_loader,
26 }
27 }
28}
29
30impl<'a, DL: HeaderFieldsProvider> Verifier for HeaderVerifier<'a, DL> {
31 type Target = HeaderView;
32 fn verify(&self, header: &Self::Target) -> Result<(), Error> {
33 PowVerifier::new(header, self.consensus.pow_engine().as_ref()).verify()?;
35 let parent_fields = self
36 .data_loader
37 .get_header_fields(&header.parent_hash())
38 .ok_or_else(|| UnknownParentError {
39 parent_hash: header.parent_hash(),
40 })?;
41 NumberVerifier::new(parent_fields.number, header).verify()?;
42 EpochVerifier::new(parent_fields.epoch, header).verify()?;
43 TimestampVerifier::new(
44 self.data_loader,
45 header,
46 self.consensus.median_time_block_count(),
47 )
48 .verify()?;
49 Ok(())
50 }
51}
52
53pub struct TimestampVerifier<'a, DL> {
54 header: &'a HeaderView,
55 data_loader: &'a DL,
56 median_block_count: usize,
57 now: u64,
58}
59
60impl<'a, DL: HeaderFieldsProvider> TimestampVerifier<'a, DL> {
61 pub fn new(data_loader: &'a DL, header: &'a HeaderView, median_block_count: usize) -> Self {
62 TimestampVerifier {
63 data_loader,
64 header,
65 median_block_count,
66 now: unix_time_as_millis(),
67 }
68 }
69
70 pub fn verify(&self) -> Result<(), Error> {
71 if self.header.is_genesis() {
73 return Ok(());
74 }
75
76 let min = self.data_loader.block_median_time(
77 &self.header.data().raw().parent_hash(),
78 self.median_block_count,
79 );
80 if self.header.timestamp() <= min {
81 return Err(TimestampError::BlockTimeTooOld {
82 min,
83 actual: self.header.timestamp(),
84 }
85 .into());
86 }
87 let max = self.now + ALLOWED_FUTURE_BLOCKTIME;
88 if self.header.timestamp() > max {
89 return Err(TimestampError::BlockTimeTooNew {
90 max,
91 actual: self.header.timestamp(),
92 }
93 .into());
94 }
95 Ok(())
96 }
97}
98
99pub struct NumberVerifier<'a> {
102 parent: BlockNumber,
103 header: &'a HeaderView,
104}
105
106impl<'a> NumberVerifier<'a> {
107 pub fn new(parent: BlockNumber, header: &'a HeaderView) -> Self {
108 NumberVerifier { parent, header }
109 }
110
111 pub fn verify(&self) -> Result<(), Error> {
112 if self.header.number() != self.parent + 1 {
113 return Err(NumberError {
114 expected: self.parent + 1,
115 actual: self.header.number(),
116 }
117 .into());
118 }
119 Ok(())
120 }
121}
122
123pub struct EpochVerifier<'a> {
124 parent: EpochNumberWithFraction,
125 header: &'a HeaderView,
126}
127
128impl<'a> EpochVerifier<'a> {
129 pub fn new(parent: EpochNumberWithFraction, header: &'a HeaderView) -> Self {
130 EpochVerifier { parent, header }
131 }
132
133 pub fn verify(&self) -> Result<(), Error> {
134 if !self.header.epoch().is_well_formed() {
135 return Err(EpochError::Malformed {
136 value: self.header.epoch(),
137 }
138 .into());
139 }
140 if !self.parent.is_genesis() && !self.header.epoch().is_successor_of(self.parent) {
141 return Err(EpochError::NonContinuous {
142 current: self.header.epoch(),
143 parent: self.parent,
144 }
145 .into());
146 }
147 Ok(())
148 }
149}
150
151pub struct PowVerifier<'a> {
152 header: &'a HeaderView,
153 pow: &'a dyn PowEngine,
154}
155
156impl<'a> PowVerifier<'a> {
157 pub fn new(header: &'a HeaderView, pow: &'a dyn PowEngine) -> Self {
158 PowVerifier { header, pow }
159 }
160
161 pub fn verify(&self) -> Result<(), Error> {
162 if self.pow.verify(&self.header.data()) {
163 Ok(())
164 } else {
165 Err(PowError::InvalidNonce.into())
166 }
167 }
168}