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