1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
pub mod config;
#[cfg(test)]
mod tests;
use crate::block_verifier::config::Config;
use anyhow::ensure;
use fuel_core_poa::ports::{
Database as PoAVerifierDatabase,
RelayerPort,
};
use fuel_core_types::{
blockchain::{
block::Block,
consensus::Consensus,
header::BlockHeader,
primitives::{
BlockHeight,
DaBlockHeight,
},
SealedBlockHeader,
},
fuel_types::Bytes32,
tai64::Tai64,
};
pub struct Verifier<D, R> {
config: Config,
database: D,
relayer: R,
}
impl<D, R> Verifier<D, R> {
pub fn new(config: Config, database: D, relayer: R) -> Self {
Self {
config,
database,
relayer,
}
}
}
impl<D, R> Verifier<D, R>
where
D: PoAVerifierDatabase,
R: RelayerPort,
{
pub fn verify_block_fields(
&self,
consensus: &Consensus,
block: &Block,
) -> anyhow::Result<()> {
match consensus {
Consensus::Genesis(_) => {
let expected_genesis_height = self
.config
.chain_config
.initial_state
.as_ref()
.map(|config| config.height.unwrap_or_else(|| 0u32.into()))
.unwrap_or_else(|| 0u32.into());
verify_genesis_block_fields(expected_genesis_height, block.header())
}
Consensus::PoA(_) => fuel_core_poa::verifier::verify_block_fields(
&self.config.poa,
&self.database,
block,
),
}
}
pub fn verify_consensus(&self, header: &SealedBlockHeader) -> bool {
let SealedBlockHeader {
entity: header,
consensus,
} = header;
match consensus {
Consensus::Genesis(_) => true,
Consensus::PoA(consensus) => fuel_core_poa::verifier::verify_consensus(
&self.config.chain_config.consensus,
header,
consensus,
),
}
}
pub async fn await_da_height(&self, da_height: &DaBlockHeight) -> anyhow::Result<()> {
tokio::time::timeout(
self.config.relayer.max_wait_time,
self.relayer
.await_until_if_in_range(da_height, &self.config.relayer.max_da_lag),
)
.await?
}
}
fn verify_genesis_block_fields(
expected_genesis_height: BlockHeight,
header: &BlockHeader,
) -> anyhow::Result<()> {
let actual_genesis_height = *header.height();
ensure!(
header.prev_root() == &Bytes32::zeroed(),
"The genesis previous root should be zeroed"
);
ensure!(
header.time() == Tai64::UNIX_EPOCH,
"The genesis time should be unix epoch time"
);
ensure!(
header.da_height == Default::default(),
"The genesis `da_height` is not as expected"
);
ensure!(
expected_genesis_height == actual_genesis_height,
"The genesis height is not as expected"
);
Ok(())
}