1use std::{path::Path, sync::Arc};
2
3use crate::api::StoreEngineRollup;
4use crate::error::RollupStoreError;
5use crate::store_db::in_memory::Store as InMemoryStore;
6#[cfg(feature = "sql")]
7use crate::store_db::sql::SQLStore;
8use ethrex_common::{
9 H256,
10 types::{
11 AccountUpdate, Blob, BlobsBundle, BlockNumber, Fork, balance_diff::BalanceDiff,
12 batch::Batch, fee_config::FeeConfig,
13 },
14};
15use ethrex_l2_common::prover::{ProverInputData, ProverOutput, ProverType};
16use tracing::info;
17
18#[derive(Debug, Clone)]
19pub struct Store {
20 engine: Arc<dyn StoreEngineRollup>,
21}
22
23impl Default for Store {
24 fn default() -> Self {
25 Self {
26 engine: Arc::new(InMemoryStore::new()),
27 }
28 }
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum EngineType {
33 InMemory,
34 #[cfg(feature = "sql")]
35 SQL,
36}
37
38impl Store {
39 pub fn new(_path: &Path, engine_type: EngineType) -> Result<Self, RollupStoreError> {
40 info!("Starting l2 storage engine ({engine_type:?})");
41 let store = match engine_type {
42 EngineType::InMemory => Self {
43 engine: Arc::new(InMemoryStore::new()),
44 },
45 #[cfg(feature = "sql")]
46 EngineType::SQL => Self {
47 engine: Arc::new(SQLStore::new(_path)?),
48 },
49 };
50 info!("Started l2 store engine");
51 Ok(store)
52 }
53
54 pub async fn init(&self) -> Result<(), RollupStoreError> {
55 self.seal_batch(Batch {
57 number: 0,
58 first_block: 0,
59 last_block: 0,
60 state_root: H256::zero(),
61 l1_in_messages_rolling_hash: H256::zero(),
62 l2_in_message_rolling_hashes: Vec::new(),
63 l1_out_message_hashes: Vec::new(),
64 non_privileged_transactions: 0,
65 balance_diffs: Vec::new(),
66 blobs_bundle: BlobsBundle::empty(),
67 commit_tx: None,
68 verify_tx: None,
69 })
70 .await?;
71 if self.get_latest_verified_batch_proof().await.is_err() {
73 self.set_latest_verified_batch_proof(0, 0).await?;
74 };
75 if self.get_latest_sent_to_aligned().await.is_err() {
77 self.set_latest_sent_to_aligned(0).await?;
78 };
79 Ok(())
80 }
81
82 pub async fn get_block_numbers_by_batch(
84 &self,
85 batch_number: u64,
86 ) -> Result<Option<Vec<BlockNumber>>, RollupStoreError> {
87 self.engine.get_block_numbers_by_batch(batch_number).await
88 }
89
90 pub async fn get_batch_number_by_block(
91 &self,
92 block_number: BlockNumber,
93 ) -> Result<Option<u64>, RollupStoreError> {
94 self.engine.get_batch_number_by_block(block_number).await
95 }
96
97 pub async fn get_l1_out_message_hashes_by_batch(
98 &self,
99 batch_number: u64,
100 ) -> Result<Option<Vec<H256>>, RollupStoreError> {
101 self.engine
102 .get_l1_out_message_hashes_by_batch(batch_number)
103 .await
104 }
105
106 pub async fn get_balance_diffs_by_batch(
107 &self,
108 batch_number: u64,
109 ) -> Result<Option<Vec<BalanceDiff>>, RollupStoreError> {
110 self.engine.get_balance_diffs_by_batch(batch_number).await
111 }
112
113 pub async fn get_l1_in_messages_rolling_hash_by_batch_number(
114 &self,
115 batch_number: u64,
116 ) -> Result<Option<H256>, RollupStoreError> {
117 self.engine
118 .get_l1_in_messages_rolling_hash_by_batch_number(batch_number)
119 .await
120 }
121
122 pub async fn get_l2_in_message_rolling_hashes_by_batch(
123 &self,
124 batch_number: u64,
125 ) -> Result<Option<Vec<(u64, H256)>>, RollupStoreError> {
126 self.engine
127 .get_l2_in_message_rolling_hashes_by_batch(batch_number)
128 .await
129 }
130
131 pub async fn get_state_root_by_batch(
132 &self,
133 batch_number: u64,
134 ) -> Result<Option<H256>, RollupStoreError> {
135 self.engine
136 .get_state_root_by_batch_number(batch_number)
137 .await
138 }
139
140 pub async fn get_blobs_by_batch(
141 &self,
142 batch_number: u64,
143 ) -> Result<Option<Vec<Blob>>, RollupStoreError> {
144 self.engine
145 .get_blob_bundle_by_batch_number(batch_number)
146 .await
147 }
148
149 pub async fn get_commit_tx_by_batch(
150 &self,
151 batch_number: u64,
152 ) -> Result<Option<H256>, RollupStoreError> {
153 self.engine.get_commit_tx_by_batch(batch_number).await
154 }
155
156 pub async fn store_commit_tx_by_batch(
157 &self,
158 batch_number: u64,
159 commit_tx: H256,
160 ) -> Result<(), RollupStoreError> {
161 self.engine
162 .store_commit_tx_by_batch(batch_number, commit_tx)
163 .await
164 }
165
166 pub async fn get_verify_tx_by_batch(
167 &self,
168 batch_number: u64,
169 ) -> Result<Option<H256>, RollupStoreError> {
170 self.engine.get_verify_tx_by_batch(batch_number).await
171 }
172
173 pub async fn store_verify_tx_by_batch(
174 &self,
175 batch_number: u64,
176 verify_tx: H256,
177 ) -> Result<(), RollupStoreError> {
178 self.engine
179 .store_verify_tx_by_batch(batch_number, verify_tx)
180 .await
181 }
182
183 pub async fn get_batch_number(&self) -> Result<Option<u64>, RollupStoreError> {
184 self.engine.get_last_batch_number().await
185 }
186
187 pub async fn get_batch(
188 &self,
189 batch_number: u64,
190 fork: Fork,
191 ) -> Result<Option<Batch>, RollupStoreError> {
192 let Some(blocks) = self.get_block_numbers_by_batch(batch_number).await? else {
193 return Ok(None);
194 };
195
196 let first_block = *blocks.first().ok_or(RollupStoreError::Custom(
197 "Failed while trying to retrieve the first block of a known batch. This is a bug."
198 .to_owned(),
199 ))?;
200 let last_block = *blocks.last().ok_or(RollupStoreError::Custom(
201 "Failed while trying to retrieve the last block of a known batch. This is a bug."
202 .to_owned(),
203 ))?;
204
205 let state_root =
206 self.get_state_root_by_batch(batch_number)
207 .await?
208 .ok_or(RollupStoreError::Custom(
209 "Failed while trying to retrieve the state root of a known batch. This is a bug."
210 .to_owned(),
211 ))?;
212
213 let blobs_bundle = BlobsBundle::create_from_blobs(
214 &self
217 .get_blobs_by_batch(batch_number)
218 .await?
219 .unwrap_or_default(),
220 if fork <= Fork::Prague { None } else { Some(1) },
221 ).map_err(|e| {
222 RollupStoreError::Custom(format!("Failed to create blobs bundle from blob while getting batch from database: {e}. This is a bug"))
223 })?;
224
225 let l1_out_message_hashes = self
226 .get_l1_out_message_hashes_by_batch(batch_number)
227 .await?
228 .unwrap_or_default();
229
230 let balance_diffs = self
231 .get_balance_diffs_by_batch(batch_number)
232 .await?
233 .unwrap_or_default();
234
235 let l1_in_messages_rolling_hash = self
236 .get_l1_in_messages_rolling_hash_by_batch_number(batch_number)
237 .await?.ok_or(RollupStoreError::Custom(
238 "Failed while trying to retrieve the deposit logs hash of a known batch. This is a bug."
239 .to_owned(),
240 ))?;
241
242 let non_privileged_transactions = self
243 .engine
244 .get_non_privileged_transactions_by_batch(batch_number)
245 .await?
246 .ok_or(RollupStoreError::Custom(
247 "Failed while trying to retrieve the non-privileged transactions count of a known batch. This is a bug."
248 .to_owned(),
249 ))?;
250
251 let l2_in_message_rolling_hashes = self
252 .get_l2_in_message_rolling_hashes_by_batch(batch_number)
253 .await?
254 .ok_or(RollupStoreError::Custom(
255 "Failed while trying to retrieve the L2 in messages rolling hashes of a known batch. This is a bug."
256 .to_owned(),
257 ))?;
258
259 let commit_tx = self.get_commit_tx_by_batch(batch_number).await?;
260
261 let verify_tx = self.get_verify_tx_by_batch(batch_number).await?;
262
263 Ok(Some(Batch {
264 number: batch_number,
265 first_block,
266 last_block,
267 state_root,
268 blobs_bundle,
269 l1_out_message_hashes,
270 l1_in_messages_rolling_hash,
271 l2_in_message_rolling_hashes,
272 non_privileged_transactions,
273 balance_diffs,
274 commit_tx,
275 verify_tx,
276 }))
277 }
278
279 pub async fn seal_batch(&self, batch: Batch) -> Result<(), RollupStoreError> {
280 self.engine.seal_batch(batch).await
281 }
282
283 pub async fn seal_batch_with_prover_input(
285 &self,
286 batch: Batch,
287 prover_version: &str,
288 prover_input: ProverInputData,
289 ) -> Result<(), RollupStoreError> {
290 self.engine
291 .seal_batch_with_prover_input(batch, prover_version, prover_input)
292 .await
293 }
294
295 pub async fn update_operations_count(
296 &self,
297 transaction_inc: u64,
298 privileged_tx_inc: u64,
299 messages_inc: u64,
300 ) -> Result<(), RollupStoreError> {
301 self.engine
302 .update_operations_count(transaction_inc, privileged_tx_inc, messages_inc)
303 .await
304 }
305
306 pub async fn get_operations_count(&self) -> Result<[u64; 3], RollupStoreError> {
307 self.engine.get_operations_count().await
308 }
309
310 pub async fn contains_batch(&self, batch_number: &u64) -> Result<bool, RollupStoreError> {
312 self.engine.contains_batch(batch_number).await
313 }
314
315 pub async fn store_signature_by_block(
319 &self,
320 block_hash: H256,
321 signature: ethereum_types::Signature,
322 ) -> Result<(), RollupStoreError> {
323 self.engine
324 .store_signature_by_block(block_hash, signature)
325 .await
326 }
327
328 pub async fn get_signature_by_block(
332 &self,
333 block_hash: H256,
334 ) -> Result<Option<ethereum_types::Signature>, RollupStoreError> {
335 self.engine.get_signature_by_block(block_hash).await
336 }
337
338 pub async fn store_signature_by_batch(
343 &self,
344 batch_number: u64,
345 signature: ethereum_types::Signature,
346 ) -> Result<(), RollupStoreError> {
347 self.engine
348 .store_signature_by_batch(batch_number, signature)
349 .await
350 }
351
352 pub async fn get_signature_by_batch(
356 &self,
357 batch_number: u64,
358 ) -> Result<Option<ethereum_types::Signature>, RollupStoreError> {
359 self.engine.get_signature_by_batch(batch_number).await
360 }
361
362 pub async fn get_latest_verified_batch_proof(&self) -> Result<(u64, u64), RollupStoreError> {
364 self.engine.get_latest_verified_batch_proof().await
365 }
366
367 pub async fn set_latest_verified_batch_proof(
369 &self,
370 batch_number: u64,
371 verified_at: u64,
372 ) -> Result<(), RollupStoreError> {
373 self.engine
374 .set_latest_verified_batch_proof(batch_number, verified_at)
375 .await
376 }
377
378 pub async fn get_latest_sent_to_aligned(&self) -> Result<u64, RollupStoreError> {
380 self.engine.get_latest_sent_to_aligned().await
381 }
382
383 pub async fn set_latest_sent_to_aligned(
385 &self,
386 batch_number: u64,
387 ) -> Result<(), RollupStoreError> {
388 self.engine.set_latest_sent_to_aligned(batch_number).await
389 }
390
391 pub async fn get_account_updates_by_block_number(
393 &self,
394 block_number: BlockNumber,
395 ) -> Result<Option<Vec<AccountUpdate>>, RollupStoreError> {
396 self.engine
397 .get_account_updates_by_block_number(block_number)
398 .await
399 }
400
401 pub async fn store_account_updates_by_block_number(
403 &self,
404 block_number: BlockNumber,
405 account_updates: Vec<AccountUpdate>,
406 ) -> Result<(), RollupStoreError> {
407 self.engine
408 .store_account_updates_by_block_number(block_number, account_updates)
409 .await
410 }
411
412 pub async fn store_proof_by_batch_and_type(
413 &self,
414 batch_number: u64,
415 proof_type: ProverType,
416 proof: ProverOutput,
417 ) -> Result<(), RollupStoreError> {
418 self.engine
419 .store_proof_by_batch_and_type(batch_number, proof_type, proof)
420 .await
421 }
422
423 pub async fn get_proof_by_batch_and_type(
424 &self,
425 batch_number: u64,
426 proof_type: ProverType,
427 ) -> Result<Option<ProverOutput>, RollupStoreError> {
428 self.engine
429 .get_proof_by_batch_and_type(batch_number, proof_type)
430 .await
431 }
432
433 pub async fn revert_to_batch(&self, batch_number: u64) -> Result<(), RollupStoreError> {
435 self.engine.revert_to_batch(batch_number).await
436 }
437
438 pub async fn delete_proof_by_batch_and_type(
439 &self,
440 batch_number: u64,
441 proof_type: ProverType,
442 ) -> Result<(), RollupStoreError> {
443 self.engine
444 .delete_proof_by_batch_and_type(batch_number, proof_type)
445 .await
446 }
447
448 pub async fn store_prover_input_by_batch_and_version(
449 &self,
450 batch_number: u64,
451 prover_version: &str,
452 prover_input: ProverInputData,
453 ) -> Result<(), RollupStoreError> {
454 self.engine
455 .store_prover_input_by_batch_and_version(batch_number, prover_version, prover_input)
456 .await
457 }
458
459 pub async fn get_prover_input_by_batch_and_version(
460 &self,
461 batch_number: u64,
462 prover_version: &str,
463 ) -> Result<Option<ProverInputData>, RollupStoreError> {
464 self.engine
465 .get_prover_input_by_batch_and_version(batch_number, prover_version)
466 .await
467 }
468
469 pub async fn store_fee_config_by_block(
470 &self,
471 block_number: BlockNumber,
472 fee_config: FeeConfig,
473 ) -> Result<(), RollupStoreError> {
474 self.engine
475 .store_fee_config_by_block(block_number, fee_config)
476 .await
477 }
478 pub async fn get_fee_config_by_block(
479 &self,
480 block_number: BlockNumber,
481 ) -> Result<Option<FeeConfig>, RollupStoreError> {
482 self.engine.get_fee_config_by_block(block_number).await
483 }
484}