fuel_core_consensus_module/
block_verifier.rs1use crate::block_verifier::config::Config;
5use anyhow::ensure;
6use fuel_core_poa::ports::Database as PoAVerifierDatabase;
7use fuel_core_storage::transactional::AtomicView;
8use fuel_core_types::{
9 blockchain::{
10 block::Block,
11 consensus::Consensus,
12 header::BlockHeader,
13 primitives::DaBlockHeight,
14 SealedBlockHeader,
15 },
16 fuel_types::{
17 BlockHeight,
18 Bytes32,
19 },
20 tai64::Tai64,
21};
22
23pub mod config;
24
25#[cfg(test)]
26mod tests;
27
28pub struct Verifier<V> {
30 config: Config,
31 view_provider: V,
32}
33
34impl<V> Verifier<V> {
35 pub fn new(config: Config, view_provider: V) -> Self {
37 Self {
38 config,
39 view_provider,
40 }
41 }
42}
43
44impl<V> Verifier<V>
45where
46 V: AtomicView,
47 V::LatestView: PoAVerifierDatabase,
48{
49 pub fn verify_block_fields(
53 &self,
54 consensus: &Consensus,
55 block: &Block,
56 ) -> anyhow::Result<()> {
57 match consensus {
58 Consensus::Genesis(_) => {
59 let expected_genesis_height = self.config.block_height;
60 let expected_genesis_da_height = self.config.da_block_height;
61 verify_genesis_block_fields(
62 expected_genesis_height,
63 expected_genesis_da_height,
64 block.header(),
65 )
66 }
67 Consensus::PoA(_) => {
68 let view = self.view_provider.latest_view()?;
69 fuel_core_poa::verifier::verify_block_fields(&view, block)
70 }
71 _ => Err(anyhow::anyhow!("Unsupported consensus: {:?}", consensus)),
72 }
73 }
74
75 pub fn verify_consensus(&self, header: &SealedBlockHeader) -> bool {
77 let SealedBlockHeader {
78 entity: header,
79 consensus,
80 } = header;
81 match consensus {
82 Consensus::Genesis(_) => true,
83 Consensus::PoA(consensus) => fuel_core_poa::verifier::verify_consensus(
84 &self.config.consensus,
85 header,
86 consensus,
87 ),
88 _ => false,
89 }
90 }
91}
92
93fn verify_genesis_block_fields(
94 expected_genesis_height: BlockHeight,
95 expected_genesis_da_height: DaBlockHeight,
96 header: &BlockHeader,
97) -> anyhow::Result<()> {
98 let actual_genesis_height = *header.height();
99
100 ensure!(
101 header.prev_root() == &Bytes32::zeroed(),
102 "The genesis previous root should be zeroed"
103 );
104 ensure!(
105 header.time() == Tai64::UNIX_EPOCH,
106 "The genesis time should be unix epoch time"
107 );
108 ensure!(
109 header.da_height == expected_genesis_da_height,
110 "The genesis `da_height` is not as expected"
111 );
112 ensure!(
113 expected_genesis_height == actual_genesis_height,
114 "The genesis height is not as expected"
115 );
116 Ok(())
117}