fuel_core/service/adapters/
block_importer.rs1use crate::{
2 database::{
3 Database,
4 commit_changes_with_height_update,
5 },
6 service::adapters::{
7 BlockImporterAdapter,
8 ExecutorAdapter,
9 VerifierAdapter,
10 },
11};
12use fuel_core_importer::{
13 Config,
14 Importer,
15 ports::{
16 BlockVerifier,
17 ImporterDatabase,
18 Validator,
19 },
20};
21use fuel_core_storage::{
22 MerkleRoot,
23 Result as StorageResult,
24 StorageAsRef,
25 iter::{
26 IterDirection,
27 IteratorOverTable,
28 },
29 tables::{
30 FuelBlocks,
31 merkle::{
32 DenseMetadataKey,
33 FuelBlockMerkleMetadata,
34 },
35 },
36 transactional::{
37 Changes,
38 StorageChanges,
39 },
40};
41use fuel_core_txpool::ports::{
42 WasmChecker,
43 WasmValidityError,
44};
45use fuel_core_types::{
46 blockchain::{
47 SealedBlock,
48 block::Block,
49 consensus::Consensus,
50 },
51 fuel_tx::Bytes32,
52 fuel_types::{
53 BlockHeight,
54 ChainId,
55 },
56 services::executor::{
57 Result as ExecutorResult,
58 UncommittedValidationResult,
59 },
60};
61use itertools::Itertools;
62use std::sync::Arc;
63
64impl BlockImporterAdapter {
65 pub fn new(
66 chain_id: ChainId,
67 config: Config,
68 database: Database,
69 executor: ExecutorAdapter,
70 verifier: VerifierAdapter,
71 ) -> Self {
72 let importer = Importer::new(chain_id, config, database, executor, verifier);
73 Self {
74 block_importer: Arc::new(importer),
75 }
76 }
77
78 pub async fn execute_and_commit(
79 &self,
80 sealed_block: SealedBlock,
81 ) -> anyhow::Result<()> {
82 self.block_importer.execute_and_commit(sealed_block).await?;
83 Ok(())
84 }
85}
86
87impl BlockVerifier for VerifierAdapter {
88 fn verify_block_fields(
89 &self,
90 consensus: &Consensus,
91 block: &Block,
92 ) -> anyhow::Result<()> {
93 self.block_verifier.verify_block_fields(consensus, block)
94 }
95}
96
97impl ImporterDatabase for Database {
98 fn latest_block_height(&self) -> StorageResult<Option<BlockHeight>> {
99 self.iter_all_keys::<FuelBlocks>(Some(IterDirection::Reverse))
100 .next()
101 .transpose()
102 }
103
104 fn latest_block_root(&self) -> StorageResult<Option<MerkleRoot>> {
105 Ok(self
106 .storage_as_ref::<FuelBlockMerkleMetadata>()
107 .get(&DenseMetadataKey::Latest)?
108 .map(|cow| *cow.root()))
109 }
110
111 fn commit_changes(&mut self, changes: StorageChanges) -> StorageResult<()> {
112 commit_changes_with_height_update(self, changes, |iter| {
113 iter.iter_all_keys::<FuelBlocks>(Some(IterDirection::Reverse))
114 .try_collect()
115 })
116 }
117}
118
119impl Validator for ExecutorAdapter {
120 fn validate(
121 &self,
122 block: &Block,
123 ) -> ExecutorResult<UncommittedValidationResult<Changes>> {
124 self.executor.validate(block)
125 }
126}
127
128#[cfg(feature = "wasm-executor")]
129impl WasmChecker for ExecutorAdapter {
130 fn validate_uploaded_wasm(
131 &self,
132 wasm_root: &Bytes32,
133 ) -> Result<(), WasmValidityError> {
134 self.executor
135 .validate_uploaded_wasm(wasm_root)
136 .map_err(|err| match err {
137 fuel_core_upgradable_executor::error::UpgradableError::InvalidWasm(_) => {
138 WasmValidityError::NotValid
139 }
140 _ => WasmValidityError::NotFound,
141 })
142 }
143}
144
145#[cfg(not(feature = "wasm-executor"))]
146impl WasmChecker for ExecutorAdapter {
147 fn validate_uploaded_wasm(
148 &self,
149 _wasm_root: &Bytes32,
150 ) -> Result<(), WasmValidityError> {
151 Err(WasmValidityError::NotEnabled)
152 }
153}