From a740f7494c76a32254778436697a5408817a747e Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Thu, 19 Mar 2026 12:47:49 +0200 Subject: [PATCH 1/6] feat: added one meta field with trait --- storage/src/indexer/meta_cells.rs | 41 ++++++++ storage/src/indexer/mod.rs | 121 +++++++++++++++++++++++- storage/src/indexer/read_once.rs | 31 +----- storage/src/indexer/write_atomic.rs | 21 +--- storage/src/indexer/write_non_atomic.rs | 26 +---- 5 files changed, 171 insertions(+), 69 deletions(-) create mode 100644 storage/src/indexer/meta_cells.rs diff --git a/storage/src/indexer/meta_cells.rs b/storage/src/indexer/meta_cells.rs new file mode 100644 index 00000000..b9c7eb94 --- /dev/null +++ b/storage/src/indexer/meta_cells.rs @@ -0,0 +1,41 @@ +use borsh::{BorshDeserialize, BorshSerialize}; + +use crate::{ + error::DbError, + indexer::{CF_META_NAME, DB_META_LAST_BLOCK_IN_DB_KEY, DbResult, SimpleStorableCell}, +}; + +#[derive(Debug)] +pub struct LastBlockCell(pub u64); + +impl BorshSerialize for LastBlockCell { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + u64::serialize(&self.0, writer) + } +} + +impl BorshDeserialize for LastBlockCell { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + u64::deserialize_reader(reader).map(|val| LastBlockCell(val)) + } +} + +impl SimpleStorableCell for LastBlockCell { + const CELL_NAME: &'static str = DB_META_LAST_BLOCK_IN_DB_KEY; + const CF_NAME: &'static str = CF_META_NAME; + + fn key_constructor() -> DbResult> { + borsh::to_vec(&Self::CELL_NAME).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self.0).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize last block id".to_owned())) + }) + } +} diff --git a/storage/src/indexer/mod.rs b/storage/src/indexer/mod.rs index c5d47c1f..340fb515 100644 --- a/storage/src/indexer/mod.rs +++ b/storage/src/indexer/mod.rs @@ -1,13 +1,15 @@ use std::{path::Path, sync::Arc}; +use borsh::{BorshDeserialize, BorshSerialize}; use common::block::Block; use nssa::V02State; use rocksdb::{ - BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options, + BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options, WriteBatch, }; use crate::error::DbError; +pub mod meta_cells; pub mod read_multiple; pub mod read_once; pub mod write_atomic; @@ -61,6 +63,97 @@ pub struct RocksDBIO { pub db: DBWithThreadMode, } +pub trait SimpleStorableCell: BorshSerialize + BorshDeserialize { + const CF_NAME: &'static str; + const CELL_NAME: &'static str; + + fn key_constructor() -> DbResult>; + fn value_constructor(&self) -> DbResult>; + + fn column_ref(db: &RocksDBIO) -> Arc> { + db.db + .cf_handle(Self::CF_NAME) + .expect(format!("Column family {:?} must be present", Self::CF_NAME).as_str()) + } + + fn get(db: &RocksDBIO) -> DbResult { + let cf_ref = Self::column_ref(db); + let res = db + .db + .get_cf(&cf_ref, Self::key_constructor()?) + .map_err(|rerr| { + DbError::rocksdb_cast_message( + rerr, + Some(format!("Failed to read {:?}", Self::CELL_NAME)), + ) + })?; + + if let Some(data) = res { + Ok(borsh::from_slice::(&data).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to deserialize {:?}", Self::CELL_NAME)), + ) + })?) + } else { + Err(DbError::db_interaction_error(format!( + "{:?} not found", + Self::CELL_NAME + ))) + } + } + + fn get_opt(db: &RocksDBIO) -> DbResult> { + let cf_ref = Self::column_ref(db); + let res = db + .db + .get_cf(&cf_ref, Self::key_constructor()?) + .map_err(|rerr| { + DbError::rocksdb_cast_message( + rerr, + Some(format!("Failed to read {:?}", Self::CELL_NAME)), + ) + })?; + + res.map(|data| { + borsh::from_slice::(&data).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to deserialize {:?}", Self::CELL_NAME)), + ) + }) + }) + .transpose() + } + + fn put(&self, db: &RocksDBIO) -> DbResult<()> { + let cf_meta = db.meta_column(); + db.db + .put_cf( + &cf_meta, + Self::key_constructor()?, + self.value_constructor()?, + ) + .map_err(|rerr| { + DbError::rocksdb_cast_message( + rerr, + Some(format!("Failed to write {:?}", Self::CELL_NAME)), + ) + })?; + Ok(()) + } + + fn put_batch(&self, db: &RocksDBIO, write_batch: &mut WriteBatch) -> DbResult<()> { + let cf_meta = db.meta_column(); + write_batch.put_cf( + &cf_meta, + Self::key_constructor()?, + self.value_constructor()?, + ); + Ok(()) + } +} + impl RocksDBIO { pub fn open_or_create( path: &Path, @@ -158,6 +251,32 @@ impl RocksDBIO { .expect("Account meta column should exist") } + // Generics + + #[allow(unused)] + fn get(&self) -> DbResult { + T::get(&self) + } + + #[allow(unused)] + fn get_opt(&self) -> DbResult> { + T::get_opt(&self) + } + + #[allow(unused)] + fn put(&self, cell: T) -> DbResult<()> { + cell.put(&self) + } + + #[allow(unused)] + fn put_batch( + &self, + cell: T, + write_batch: &mut WriteBatch, + ) -> DbResult<()> { + cell.put_batch(&self, write_batch) + } + // State pub fn calculate_state_for_id(&self, block_id: u64) -> DbResult { diff --git a/storage/src/indexer/read_once.rs b/storage/src/indexer/read_once.rs index f966f349..eb5fc697 100644 --- a/storage/src/indexer/read_once.rs +++ b/storage/src/indexer/read_once.rs @@ -1,8 +1,8 @@ use super::{ - Block, DB_META_FIRST_BLOCK_IN_DB_KEY, DB_META_FIRST_BLOCK_SET_KEY, - DB_META_LAST_BLOCK_IN_DB_KEY, DB_META_LAST_BREAKPOINT_ID, + Block, DB_META_FIRST_BLOCK_IN_DB_KEY, DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, DbError, DbResult, RocksDBIO, V02State, }; +use crate::indexer::meta_cells::LastBlockCell; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] impl RocksDBIO { @@ -38,32 +38,7 @@ impl RocksDBIO { } pub fn get_meta_last_block_in_db(&self) -> DbResult { - let cf_meta = self.meta_column(); - let res = self - .db - .get_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_BLOCK_IN_DB_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LAST_BLOCK_IN_DB_KEY".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - if let Some(data) = res { - Ok(borsh::from_slice::(&data).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to deserialize last block".to_owned()), - ) - })?) - } else { - Err(DbError::db_interaction_error( - "Last block not found".to_owned(), - )) - } + self.get::().map(|cell| cell.0) } pub fn get_meta_last_observed_l1_lib_header_in_db(&self) -> DbResult> { diff --git a/storage/src/indexer/write_atomic.rs b/storage/src/indexer/write_atomic.rs index 161d763a..82dfba7c 100644 --- a/storage/src/indexer/write_atomic.rs +++ b/storage/src/indexer/write_atomic.rs @@ -4,9 +4,10 @@ use rocksdb::WriteBatch; use super::{ Arc, BREAKPOINT_INTERVAL, Block, BoundColumnFamily, DB_META_FIRST_BLOCK_IN_DB_KEY, - DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BLOCK_IN_DB_KEY, DB_META_LAST_BREAKPOINT_ID, + DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, DbError, DbResult, RocksDBIO, }; +use crate::indexer::meta_cells::LastBlockCell; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] impl RocksDBIO { @@ -163,23 +164,7 @@ impl RocksDBIO { block_id: u64, write_batch: &mut WriteBatch, ) -> DbResult<()> { - let cf_meta = self.meta_column(); - write_batch.put_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_BLOCK_IN_DB_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LAST_BLOCK_IN_DB_KEY".to_owned()), - ) - })?, - borsh::to_vec(&block_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize last block id".to_owned()), - ) - })?, - ); - Ok(()) + self.put_batch(LastBlockCell(block_id), write_batch) } pub fn put_meta_last_observed_l1_lib_header_in_db_batch( diff --git a/storage/src/indexer/write_non_atomic.rs b/storage/src/indexer/write_non_atomic.rs index 84fc7de5..c674095a 100644 --- a/storage/src/indexer/write_non_atomic.rs +++ b/storage/src/indexer/write_non_atomic.rs @@ -1,33 +1,15 @@ use super::{ - BREAKPOINT_INTERVAL, DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BLOCK_IN_DB_KEY, - DB_META_LAST_BREAKPOINT_ID, DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, DbError, - DbResult, RocksDBIO, V02State, + BREAKPOINT_INTERVAL, DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, + DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, DbError, DbResult, RocksDBIO, V02State, }; +use crate::indexer::meta_cells::LastBlockCell; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] impl RocksDBIO { // Meta pub fn put_meta_last_block_in_db(&self, block_id: u64) -> DbResult<()> { - let cf_meta = self.meta_column(); - self.db - .put_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_BLOCK_IN_DB_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LAST_BLOCK_IN_DB_KEY".to_owned()), - ) - })?, - borsh::to_vec(&block_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize last block id".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - Ok(()) + self.put(LastBlockCell(block_id)) } pub fn put_meta_last_observed_l1_lib_header_in_db( From 927f6de9bcf2b0e037bc937126895a56a9da4606 Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Wed, 25 Mar 2026 16:14:33 +0200 Subject: [PATCH 2/6] fix: structural update --- storage/src/indexer/mod.rs | 151 ++---------------- storage/src/indexer/read_once.rs | 9 +- storage/src/indexer/write_atomic.rs | 10 +- storage/src/indexer/write_non_atomic.rs | 9 +- storage/src/lib.rs | 66 ++++++++ storage/src/sequencer.rs | 129 ++++----------- .../src/storable_cell/cells/meta_indexer.rs | 1 + .../src/storable_cell/cells/meta_sequencer.rs | 1 + .../cells/meta_shared.rs} | 4 +- storage/src/storable_cell/cells/mod.rs | 3 + storage/src/storable_cell/mod.rs | 91 +++++++++++ 11 files changed, 221 insertions(+), 253 deletions(-) create mode 100644 storage/src/storable_cell/cells/meta_indexer.rs create mode 100644 storage/src/storable_cell/cells/meta_sequencer.rs rename storage/src/{indexer/meta_cells.rs => storable_cell/cells/meta_shared.rs} (90%) create mode 100644 storage/src/storable_cell/cells/mod.rs create mode 100644 storage/src/storable_cell/mod.rs diff --git a/storage/src/indexer/mod.rs b/storage/src/indexer/mod.rs index 7bc7c85c..9fa5ebde 100644 --- a/storage/src/indexer/mod.rs +++ b/storage/src/indexer/mod.rs @@ -1,159 +1,26 @@ use std::{path::Path, sync::Arc}; -use borsh::{BorshDeserialize, BorshSerialize}; use common::block::Block; use nssa::V03State; use rocksdb::{ BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options, WriteBatch, }; -use crate::error::DbError; +use crate::{ + BREAKPOINT_INTERVAL, CF_ACC_META, CF_ACC_TO_TX, CF_BLOCK_NAME, CF_BREAKPOINT_NAME, + CF_HASH_TO_ID, CF_META_NAME, CF_TX_TO_ID, DbResult, error::DbError, + storable_cell::SimpleStorableCell, +}; -pub mod meta_cells; pub mod read_multiple; pub mod read_once; pub mod write_atomic; pub mod write_non_atomic; -/// Maximal size of stored blocks in base. -/// -/// Used to control db size. -/// -/// Currently effectively unbounded. -pub const BUFF_SIZE_ROCKSDB: usize = usize::MAX; - -/// Size of stored blocks cache in memory. -/// -/// Keeping small to not run out of memory. -pub const CACHE_SIZE: usize = 1000; - -/// Key base for storing metainformation about id of first block in db. -pub const DB_META_FIRST_BLOCK_IN_DB_KEY: &str = "first_block_in_db"; -/// Key base for storing metainformation about id of last current block in db. -pub const DB_META_LAST_BLOCK_IN_DB_KEY: &str = "last_block_in_db"; -/// Key base for storing metainformation about id of last observed L1 lib header in db. -pub const DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY: &str = - "last_observed_l1_lib_header_in_db"; -/// Key base for storing metainformation which describe if first block has been set. -pub const DB_META_FIRST_BLOCK_SET_KEY: &str = "first_block_set"; -/// Key base for storing metainformation about the last breakpoint. -pub const DB_META_LAST_BREAKPOINT_ID: &str = "last_breakpoint_id"; - -/// Interval between state breakpoints. -pub const BREAKPOINT_INTERVAL: u8 = 100; - -/// Name of block column family. -pub const CF_BLOCK_NAME: &str = "cf_block"; -/// Name of meta column family. -pub const CF_META_NAME: &str = "cf_meta"; -/// Name of breakpoint column family. -pub const CF_BREAKPOINT_NAME: &str = "cf_breakpoint"; -/// Name of hash to id map column family. -pub const CF_HASH_TO_ID: &str = "cf_hash_to_id"; -/// Name of tx hash to id map column family. -pub const CF_TX_TO_ID: &str = "cf_tx_to_id"; -/// Name of account meta column family. -pub const CF_ACC_META: &str = "cf_acc_meta"; -/// Name of account id to tx hash map column family. -pub const CF_ACC_TO_TX: &str = "cf_acc_to_tx"; - -pub type DbResult = Result; - pub struct RocksDBIO { pub db: DBWithThreadMode, } -pub trait SimpleStorableCell: BorshSerialize + BorshDeserialize { - const CF_NAME: &'static str; - const CELL_NAME: &'static str; - - fn key_constructor() -> DbResult>; - fn value_constructor(&self) -> DbResult>; - - fn column_ref(db: &RocksDBIO) -> Arc> { - db.db - .cf_handle(Self::CF_NAME) - .unwrap_or_else(|| panic!("Column family {:?} must be present", Self::CF_NAME)) - } - - fn get(db: &RocksDBIO) -> DbResult { - let cf_ref = Self::column_ref(db); - let res = db - .db - .get_cf(&cf_ref, Self::key_constructor()?) - .map_err(|rerr| { - DbError::rocksdb_cast_message( - rerr, - Some(format!("Failed to read {:?}", Self::CELL_NAME)), - ) - })?; - - if let Some(data) = res { - Ok(borsh::from_slice::(&data).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to deserialize {:?}", Self::CELL_NAME)), - ) - })?) - } else { - Err(DbError::db_interaction_error(format!( - "{:?} not found", - Self::CELL_NAME - ))) - } - } - - fn get_opt(db: &RocksDBIO) -> DbResult> { - let cf_ref = Self::column_ref(db); - let res = db - .db - .get_cf(&cf_ref, Self::key_constructor()?) - .map_err(|rerr| { - DbError::rocksdb_cast_message( - rerr, - Some(format!("Failed to read {:?}", Self::CELL_NAME)), - ) - })?; - - res.map(|data| { - borsh::from_slice::(&data).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to deserialize {:?}", Self::CELL_NAME)), - ) - }) - }) - .transpose() - } - - fn put(&self, db: &RocksDBIO) -> DbResult<()> { - let cf_meta = db.meta_column(); - db.db - .put_cf( - &cf_meta, - Self::key_constructor()?, - self.value_constructor()?, - ) - .map_err(|rerr| { - DbError::rocksdb_cast_message( - rerr, - Some(format!("Failed to write {:?}", Self::CELL_NAME)), - ) - })?; - Ok(()) - } - - fn put_batch(&self, db: &RocksDBIO, write_batch: &mut WriteBatch) -> DbResult<()> { - let cf_meta = db.meta_column(); - write_batch.put_cf( - &cf_meta, - Self::key_constructor()?, - self.value_constructor()?, - ); - Ok(()) - } -} - impl RocksDBIO { pub fn open_or_create( path: &Path, @@ -254,16 +121,16 @@ impl RocksDBIO { // Generics fn get(&self) -> DbResult { - T::get(self) + T::get(&self.db) } #[expect(unused, reason = "Unused")] fn get_opt(&self) -> DbResult> { - T::get_opt(self) + T::get_opt(&self.db) } fn put(&self, cell: &T) -> DbResult<()> { - cell.put(self) + cell.put(&self.db) } fn put_batch( @@ -271,7 +138,7 @@ impl RocksDBIO { cell: &T, write_batch: &mut WriteBatch, ) -> DbResult<()> { - cell.put_batch(self, write_batch) + cell.put_batch(&self.db, write_batch) } // State diff --git a/storage/src/indexer/read_once.rs b/storage/src/indexer/read_once.rs index eb1499ba..a4ff5877 100644 --- a/storage/src/indexer/read_once.rs +++ b/storage/src/indexer/read_once.rs @@ -1,8 +1,9 @@ -use super::{ - Block, DB_META_FIRST_BLOCK_IN_DB_KEY, DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, - DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, DbError, DbResult, RocksDBIO, V03State, +use super::{Block, DbError, DbResult, RocksDBIO, V03State}; +use crate::{ + DB_META_FIRST_BLOCK_IN_DB_KEY, DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, + DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, + storable_cell::cells::meta_shared::LastBlockCell, }; -use crate::indexer::meta_cells::LastBlockCell; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] impl RocksDBIO { diff --git a/storage/src/indexer/write_atomic.rs b/storage/src/indexer/write_atomic.rs index 7e81d4b6..3274eb8e 100644 --- a/storage/src/indexer/write_atomic.rs +++ b/storage/src/indexer/write_atomic.rs @@ -2,12 +2,12 @@ use std::collections::HashMap; use rocksdb::WriteBatch; -use super::{ - Arc, BREAKPOINT_INTERVAL, Block, BoundColumnFamily, DB_META_FIRST_BLOCK_IN_DB_KEY, - DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, - DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, DbError, DbResult, RocksDBIO, +use super::{Arc, BREAKPOINT_INTERVAL, Block, BoundColumnFamily, DbError, DbResult, RocksDBIO}; +use crate::{ + DB_META_FIRST_BLOCK_IN_DB_KEY, DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, + DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, + storable_cell::cells::meta_shared::LastBlockCell, }; -use crate::indexer::meta_cells::LastBlockCell; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] impl RocksDBIO { diff --git a/storage/src/indexer/write_non_atomic.rs b/storage/src/indexer/write_non_atomic.rs index fc93b68c..f44cda7d 100644 --- a/storage/src/indexer/write_non_atomic.rs +++ b/storage/src/indexer/write_non_atomic.rs @@ -1,8 +1,9 @@ -use super::{ - BREAKPOINT_INTERVAL, DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, - DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, DbError, DbResult, RocksDBIO, V03State, +use super::{BREAKPOINT_INTERVAL, DbError, DbResult, RocksDBIO, V03State}; +use crate::{ + DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, + DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, + storable_cell::cells::meta_shared::LastBlockCell, }; -use crate::indexer::meta_cells::LastBlockCell; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] impl RocksDBIO { diff --git a/storage/src/lib.rs b/storage/src/lib.rs index 05c4a374..b1126626 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -1,3 +1,69 @@ +use crate::error::DbError; + pub mod error; pub mod indexer; pub mod sequencer; +pub mod storable_cell; + +pub type DbResult = Result; + +// General + +/// Maximal size of stored blocks in base. +/// +/// Used to control db size. +/// +/// Currently effectively unbounded. +pub const BUFF_SIZE_ROCKSDB: usize = usize::MAX; + +/// Size of stored blocks cache in memory. +/// +/// Keeping small to not run out of memory. +pub const CACHE_SIZE: usize = 1000; + +/// Key base for storing metainformation which describe if first block has been set. +pub const DB_META_FIRST_BLOCK_SET_KEY: &str = "first_block_set"; +/// Key base for storing metainformation about id of first block in db. +pub const DB_META_FIRST_BLOCK_IN_DB_KEY: &str = "first_block_in_db"; +/// Key base for storing metainformation about id of last current block in db. +pub const DB_META_LAST_BLOCK_IN_DB_KEY: &str = "last_block_in_db"; + +/// Interval between state breakpoints. +pub const BREAKPOINT_INTERVAL: u8 = 100; + +/// Name of block column family. +pub const CF_BLOCK_NAME: &str = "cf_block"; +/// Name of meta column family. +pub const CF_META_NAME: &str = "cf_meta"; + +// Indexer-specific + +/// Key base for storing metainformation about id of last observed L1 lib header in db. +pub const DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY: &str = + "last_observed_l1_lib_header_in_db"; +/// Key base for storing metainformation about the last breakpoint. +pub const DB_META_LAST_BREAKPOINT_ID: &str = "last_breakpoint_id"; + +/// Name of breakpoint column family. +pub const CF_BREAKPOINT_NAME: &str = "cf_breakpoint"; +/// Name of hash to id map column family. +pub const CF_HASH_TO_ID: &str = "cf_hash_to_id"; +/// Name of tx hash to id map column family. +pub const CF_TX_TO_ID: &str = "cf_tx_to_id"; +/// Name of account meta column family. +pub const CF_ACC_META: &str = "cf_acc_meta"; +/// Name of account id to tx hash map column family. +pub const CF_ACC_TO_TX: &str = "cf_acc_to_tx"; + +// Sequencer-specific + +/// Key base for storing metainformation about the last finalized block on Bedrock. +pub const DB_META_LAST_FINALIZED_BLOCK_ID: &str = "last_finalized_block_id"; +/// Key base for storing metainformation about the latest block meta. +pub const DB_META_LATEST_BLOCK_META_KEY: &str = "latest_block_meta"; + +/// Key base for storing the NSSA state. +pub const DB_NSSA_STATE_KEY: &str = "nssa_state"; + +/// Name of state column family. +pub const CF_NSSA_STATE_NAME: &str = "cf_nssa_state"; diff --git a/storage/src/sequencer.rs b/storage/src/sequencer.rs index 17d0e73e..f04785e5 100644 --- a/storage/src/sequencer.rs +++ b/storage/src/sequencer.rs @@ -6,40 +6,13 @@ use rocksdb::{ BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options, WriteBatch, }; -use crate::error::DbError; - -/// Maximal size of stored blocks in base. -/// -/// Used to control db size. -/// -/// Currently effectively unbounded. -pub const BUFF_SIZE_ROCKSDB: usize = usize::MAX; - -/// Size of stored blocks cache in memory. -/// -/// Keeping small to not run out of memory. -pub const CACHE_SIZE: usize = 1000; - -/// Key base for storing metainformation about id of first block in db. -pub const DB_META_FIRST_BLOCK_IN_DB_KEY: &str = "first_block_in_db"; -/// Key base for storing metainformation about id of last current block in db. -pub const DB_META_LAST_BLOCK_IN_DB_KEY: &str = "last_block_in_db"; -/// Key base for storing metainformation which describe if first block has been set. -pub const DB_META_FIRST_BLOCK_SET_KEY: &str = "first_block_set"; -/// Key base for storing metainformation about the last finalized block on Bedrock. -pub const DB_META_LAST_FINALIZED_BLOCK_ID: &str = "last_finalized_block_id"; -/// Key base for storing metainformation about the latest block meta. -pub const DB_META_LATEST_BLOCK_META_KEY: &str = "latest_block_meta"; - -/// Key base for storing the NSSA state. -pub const DB_NSSA_STATE_KEY: &str = "nssa_state"; - -/// Name of block column family. -pub const CF_BLOCK_NAME: &str = "cf_block"; -/// Name of meta column family. -pub const CF_META_NAME: &str = "cf_meta"; -/// Name of state column family. -pub const CF_NSSA_STATE_NAME: &str = "cf_nssa_state"; +use crate::{ + CF_BLOCK_NAME, CF_META_NAME, CF_NSSA_STATE_NAME, DB_META_FIRST_BLOCK_IN_DB_KEY, + DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_FINALIZED_BLOCK_ID, DB_META_LATEST_BLOCK_META_KEY, + DB_NSSA_STATE_KEY, + error::DbError, + storable_cell::{SimpleStorableCell, cells::meta_shared::LastBlockCell}, +}; pub type DbResult = Result; @@ -119,6 +92,29 @@ impl RocksDBIO { self.db.cf_handle(CF_NSSA_STATE_NAME).unwrap() } + // Generics + + fn get(&self) -> DbResult { + T::get(&self.db) + } + + #[expect(unused, reason = "Unused")] + fn get_opt(&self) -> DbResult> { + T::get_opt(&self.db) + } + + fn put(&self, cell: &T) -> DbResult<()> { + cell.put(&self.db) + } + + fn put_batch( + &self, + cell: &T, + write_batch: &mut WriteBatch, + ) -> DbResult<()> { + cell.put_batch(&self.db, write_batch) + } + pub fn get_meta_first_block_in_db(&self) -> DbResult { let cf_meta = self.meta_column(); let res = self @@ -149,32 +145,7 @@ impl RocksDBIO { } pub fn get_meta_last_block_in_db(&self) -> DbResult { - let cf_meta = self.meta_column(); - let res = self - .db - .get_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_BLOCK_IN_DB_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LAST_BLOCK_IN_DB_KEY".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - if let Some(data) = res { - Ok(borsh::from_slice::(&data).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to deserialize last block".to_owned()), - ) - })?) - } else { - Err(DbError::db_interaction_error( - "Last block not found".to_owned(), - )) - } + self.get::().map(|cell| cell.0) } pub fn get_meta_is_first_block_set(&self) -> DbResult { @@ -246,25 +217,7 @@ impl RocksDBIO { } pub fn put_meta_last_block_in_db(&self, block_id: u64) -> DbResult<()> { - let cf_meta = self.meta_column(); - self.db - .put_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_BLOCK_IN_DB_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LAST_BLOCK_IN_DB_KEY".to_owned()), - ) - })?, - borsh::to_vec(&block_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize last block id".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - Ok(()) + self.put(&LastBlockCell(block_id)) } fn put_meta_last_block_in_db_batch( @@ -272,23 +225,7 @@ impl RocksDBIO { block_id: u64, batch: &mut WriteBatch, ) -> DbResult<()> { - let cf_meta = self.meta_column(); - batch.put_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_BLOCK_IN_DB_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LAST_BLOCK_IN_DB_KEY".to_owned()), - ) - })?, - borsh::to_vec(&block_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize last block id".to_owned()), - ) - })?, - ); - Ok(()) + self.put_batch(&LastBlockCell(block_id), batch) } pub fn put_meta_last_finalized_block_id(&self, block_id: Option) -> DbResult<()> { diff --git a/storage/src/storable_cell/cells/meta_indexer.rs b/storage/src/storable_cell/cells/meta_indexer.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/storage/src/storable_cell/cells/meta_indexer.rs @@ -0,0 +1 @@ + diff --git a/storage/src/storable_cell/cells/meta_sequencer.rs b/storage/src/storable_cell/cells/meta_sequencer.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/storage/src/storable_cell/cells/meta_sequencer.rs @@ -0,0 +1 @@ + diff --git a/storage/src/indexer/meta_cells.rs b/storage/src/storable_cell/cells/meta_shared.rs similarity index 90% rename from storage/src/indexer/meta_cells.rs rename to storage/src/storable_cell/cells/meta_shared.rs index 216866a3..4b88a385 100644 --- a/storage/src/indexer/meta_cells.rs +++ b/storage/src/storable_cell/cells/meta_shared.rs @@ -1,8 +1,8 @@ use borsh::{BorshDeserialize, BorshSerialize}; use crate::{ - error::DbError, - indexer::{CF_META_NAME, DB_META_LAST_BLOCK_IN_DB_KEY, DbResult, SimpleStorableCell}, + CF_META_NAME, DB_META_LAST_BLOCK_IN_DB_KEY, DbResult, error::DbError, + storable_cell::SimpleStorableCell, }; #[derive(Debug)] diff --git a/storage/src/storable_cell/cells/mod.rs b/storage/src/storable_cell/cells/mod.rs new file mode 100644 index 00000000..914befa1 --- /dev/null +++ b/storage/src/storable_cell/cells/mod.rs @@ -0,0 +1,3 @@ +pub mod meta_indexer; +pub mod meta_sequencer; +pub mod meta_shared; diff --git a/storage/src/storable_cell/mod.rs b/storage/src/storable_cell/mod.rs new file mode 100644 index 00000000..06912829 --- /dev/null +++ b/storage/src/storable_cell/mod.rs @@ -0,0 +1,91 @@ +use std::sync::Arc; + +use borsh::{BorshDeserialize, BorshSerialize}; +use rocksdb::{BoundColumnFamily, DBWithThreadMode, MultiThreaded, WriteBatch}; + +use crate::{DbResult, error::DbError}; + +pub mod cells; + +pub trait SimpleStorableCell: BorshSerialize + BorshDeserialize { + const CF_NAME: &'static str; + const CELL_NAME: &'static str; + + fn key_constructor() -> DbResult>; + fn value_constructor(&self) -> DbResult>; + + fn column_ref(db: &DBWithThreadMode) -> Arc> { + db.cf_handle(Self::CF_NAME) + .unwrap_or_else(|| panic!("Column family {:?} must be present", Self::CF_NAME)) + } + + fn get(db: &DBWithThreadMode) -> DbResult { + let cf_ref = Self::column_ref(db); + let res = db + .get_cf(&cf_ref, Self::key_constructor()?) + .map_err(|rerr| { + DbError::rocksdb_cast_message( + rerr, + Some(format!("Failed to read {:?}", Self::CELL_NAME)), + ) + })?; + + if let Some(data) = res { + Ok(borsh::from_slice::(&data).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to deserialize {:?}", Self::CELL_NAME)), + ) + })?) + } else { + Err(DbError::db_interaction_error(format!( + "{:?} not found", + Self::CELL_NAME + ))) + } + } + + fn get_opt(db: &DBWithThreadMode) -> DbResult> { + let cf_ref = Self::column_ref(db); + let res = db + .get_cf(&cf_ref, Self::key_constructor()?) + .map_err(|rerr| { + DbError::rocksdb_cast_message( + rerr, + Some(format!("Failed to read {:?}", Self::CELL_NAME)), + ) + })?; + + res.map(|data| { + borsh::from_slice::(&data).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to deserialize {:?}", Self::CELL_NAME)), + ) + }) + }) + .transpose() + } + + fn put(&self, db: &DBWithThreadMode) -> DbResult<()> { + let cf_ref = Self::column_ref(db); + db.put_cf(&cf_ref, Self::key_constructor()?, self.value_constructor()?) + .map_err(|rerr| { + DbError::rocksdb_cast_message( + rerr, + Some(format!("Failed to write {:?}", Self::CELL_NAME)), + ) + })?; + Ok(()) + } + + fn put_batch( + &self, + db: &DBWithThreadMode, + write_batch: &mut WriteBatch, + ) -> DbResult<()> { + let cf_ref = Self::column_ref(db); + write_batch.put_cf(&cf_ref, Self::key_constructor()?, self.value_constructor()?); + Ok(()) + } +} From 392f9cf1798152f4eaaf09710a51a11d34829b74 Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Thu, 26 Mar 2026 13:10:31 +0200 Subject: [PATCH 3/6] feat: various cells --- storage/src/indexer/mod.rs | 23 +- storage/src/indexer/read_once.rs | 226 ++------------ storage/src/indexer/write_atomic.rs | 133 +++----- storage/src/indexer/write_non_atomic.rs | 89 +----- storage/src/lib.rs | 4 +- storage/src/sequencer.rs | 265 +++------------- .../src/storable_cell/cells/meta_indexer.rs | 286 ++++++++++++++++++ .../src/storable_cell/cells/meta_sequencer.rs | 181 +++++++++++ .../src/storable_cell/cells/meta_shared.rs | 140 ++++++++- storage/src/storable_cell/mod.rs | 47 ++- 10 files changed, 767 insertions(+), 627 deletions(-) diff --git a/storage/src/indexer/mod.rs b/storage/src/indexer/mod.rs index 9fa5ebde..f91c40d8 100644 --- a/storage/src/indexer/mod.rs +++ b/storage/src/indexer/mod.rs @@ -8,8 +8,9 @@ use rocksdb::{ use crate::{ BREAKPOINT_INTERVAL, CF_ACC_META, CF_ACC_TO_TX, CF_BLOCK_NAME, CF_BREAKPOINT_NAME, - CF_HASH_TO_ID, CF_META_NAME, CF_TX_TO_ID, DbResult, error::DbError, - storable_cell::SimpleStorableCell, + CF_HASH_TO_ID, CF_META_NAME, CF_TX_TO_ID, DbResult, + error::DbError, + storable_cell::{SimpleReadableCell, SimpleWritableCell}, }; pub mod read_multiple; @@ -120,25 +121,25 @@ impl RocksDBIO { // Generics - fn get(&self) -> DbResult { - T::get(&self.db) + fn get(&self, params: T::KeyParams) -> DbResult { + T::get(&self.db, params) } - #[expect(unused, reason = "Unused")] - fn get_opt(&self) -> DbResult> { - T::get_opt(&self.db) + fn get_opt(&self, params: T::KeyParams) -> DbResult> { + T::get_opt(&self.db, params) } - fn put(&self, cell: &T) -> DbResult<()> { - cell.put(&self.db) + fn put(&self, cell: &T, params: T::KeyParams) -> DbResult<()> { + cell.put(&self.db, params) } - fn put_batch( + fn put_batch( &self, cell: &T, + params: T::KeyParams, write_batch: &mut WriteBatch, ) -> DbResult<()> { - cell.put_batch(&self.db, write_batch) + cell.put_batch(&self.db, params, write_batch) } // State diff --git a/storage/src/indexer/read_once.rs b/storage/src/indexer/read_once.rs index a4ff5877..a7cedd58 100644 --- a/storage/src/indexer/read_once.rs +++ b/storage/src/indexer/read_once.rs @@ -1,8 +1,10 @@ -use super::{Block, DbError, DbResult, RocksDBIO, V03State}; -use crate::{ - DB_META_FIRST_BLOCK_IN_DB_KEY, DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, - DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, - storable_cell::cells::meta_shared::LastBlockCell, +use super::{Block, DbResult, RocksDBIO, V03State}; +use crate::storable_cell::cells::{ + meta_indexer::{ + AccNumTxCell, BlockHashToBlockIdMapCell, BreakpointCellOwned, LastBreakpointIdCell, + LastObservedL1LibHeaderCell, TxHashToBlockIdMapCell, + }, + meta_shared::{BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell}, }; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] @@ -10,239 +12,55 @@ impl RocksDBIO { // Meta pub fn get_meta_first_block_in_db(&self) -> DbResult { - let cf_meta = self.meta_column(); - let res = self - .db - .get_cf( - &cf_meta, - borsh::to_vec(&DB_META_FIRST_BLOCK_IN_DB_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_FIRST_BLOCK_IN_DB_KEY".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - if let Some(data) = res { - Ok(borsh::from_slice::(&data).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to deserialize first block".to_owned()), - ) - })?) - } else { - Err(DbError::db_interaction_error( - "First block not found".to_owned(), - )) - } + self.get::(()).map(|cell| cell.0) } pub fn get_meta_last_block_in_db(&self) -> DbResult { - self.get::().map(|cell| cell.0) + self.get::(()).map(|cell| cell.0) } pub fn get_meta_last_observed_l1_lib_header_in_db(&self) -> DbResult> { - let cf_meta = self.meta_column(); - let res = self - .db - .get_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY).map_err( - |err| { - DbError::borsh_cast_message( - err, - Some( - "Failed to serialize DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY" - .to_owned(), - ), - ) - }, - )?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - res.map(|data| { - borsh::from_slice::<[u8; 32]>(&data).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to deserialize last l1 lib header".to_owned()), - ) - }) - }) - .transpose() + self.get_opt::(()) + .map(|opt| opt.map(|val| val.0)) } pub fn get_meta_is_first_block_set(&self) -> DbResult { - let cf_meta = self.meta_column(); - let res = self - .db - .get_cf( - &cf_meta, - borsh::to_vec(&DB_META_FIRST_BLOCK_SET_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_FIRST_BLOCK_SET_KEY".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - Ok(res.is_some()) + Ok(self.get_opt::(())?.is_some()) } pub fn get_meta_last_breakpoint_id(&self) -> DbResult { - let cf_meta = self.meta_column(); - let res = self - .db - .get_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_BREAKPOINT_ID).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LAST_BREAKPOINT_ID".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - if let Some(data) = res { - Ok(borsh::from_slice::(&data).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to deserialize last breakpoint id".to_owned()), - ) - })?) - } else { - Err(DbError::db_interaction_error( - "Last breakpoint id not found".to_owned(), - )) - } + self.get::(()).map(|cell| cell.0) } // Block pub fn get_block(&self, block_id: u64) -> DbResult> { - let cf_block = self.block_column(); - let res = self - .db - .get_cf( - &cf_block, - borsh::to_vec(&block_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize block id".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - if let Some(data) = res { - Ok(Some(borsh::from_slice::(&data).map_err(|serr| { - DbError::borsh_cast_message( - serr, - Some("Failed to deserialize block data".to_owned()), - ) - })?)) - } else { - Ok(None) - } + self.get_opt::(block_id) + .map(|opt| opt.map(|val| val.0)) } // State pub fn get_breakpoint(&self, br_id: u64) -> DbResult { - let cf_br = self.breakpoint_column(); - let res = self - .db - .get_cf( - &cf_br, - borsh::to_vec(&br_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize breakpoint id".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - if let Some(data) = res { - Ok(borsh::from_slice::(&data).map_err(|serr| { - DbError::borsh_cast_message( - serr, - Some("Failed to deserialize breakpoint data".to_owned()), - ) - })?) - } else { - Err(DbError::db_interaction_error( - "Breakpoint on this id not found".to_owned(), - )) - } + self.get::(br_id).map(|cell| cell.0) } // Mappings pub fn get_block_id_by_hash(&self, hash: [u8; 32]) -> DbResult> { - let cf_hti = self.hash_to_id_column(); - let res = self - .db - .get_cf( - &cf_hti, - borsh::to_vec(&hash).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize block hash".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - if let Some(data) = res { - Ok(Some(borsh::from_slice::(&data).map_err(|serr| { - DbError::borsh_cast_message(serr, Some("Failed to deserialize block id".to_owned())) - })?)) - } else { - Ok(None) - } + self.get_opt::(hash) + .map(|opt| opt.map(|cell| cell.0)) } pub fn get_block_id_by_tx_hash(&self, tx_hash: [u8; 32]) -> DbResult> { - let cf_tti = self.tx_hash_to_id_column(); - let res = self - .db - .get_cf( - &cf_tti, - borsh::to_vec(&tx_hash).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize transaction hash".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - if let Some(data) = res { - Ok(Some(borsh::from_slice::(&data).map_err(|serr| { - DbError::borsh_cast_message(serr, Some("Failed to deserialize block id".to_owned())) - })?)) - } else { - Ok(None) - } + self.get_opt::(tx_hash) + .map(|opt| opt.map(|cell| cell.0)) } // Accounts meta pub(crate) fn get_acc_meta_num_tx(&self, acc_id: [u8; 32]) -> DbResult> { - let cf_ameta = self.account_meta_column(); - let res = self.db.get_cf(&cf_ameta, acc_id).map_err(|rerr| { - DbError::rocksdb_cast_message(rerr, Some("Failed to read from acc meta cf".to_owned())) - })?; - - res.map(|data| { - borsh::from_slice::(&data).map_err(|serr| { - DbError::borsh_cast_message(serr, Some("Failed to deserialize num tx".to_owned())) - }) - }) - .transpose() + self.get_opt::(acc_id) + .map(|opt| opt.map(|cell| cell.0)) } } diff --git a/storage/src/indexer/write_atomic.rs b/storage/src/indexer/write_atomic.rs index 3274eb8e..cff8284a 100644 --- a/storage/src/indexer/write_atomic.rs +++ b/storage/src/indexer/write_atomic.rs @@ -2,11 +2,16 @@ use std::collections::HashMap; use rocksdb::WriteBatch; -use super::{Arc, BREAKPOINT_INTERVAL, Block, BoundColumnFamily, DbError, DbResult, RocksDBIO}; +use super::{BREAKPOINT_INTERVAL, Block, DbError, DbResult, RocksDBIO}; use crate::{ - DB_META_FIRST_BLOCK_IN_DB_KEY, DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, - DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, - storable_cell::cells::meta_shared::LastBlockCell, + DB_META_FIRST_BLOCK_IN_DB_KEY, + storable_cell::cells::{ + meta_indexer::{ + AccNumTxCell, BlockHashToBlockIdMapCell, LastBreakpointIdCell, + LastObservedL1LibHeaderCell, TxHashToBlockIdMapCell, + }, + meta_shared::{FirstBlockSetCell, LastBlockCell}, + }, }; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] @@ -19,22 +24,27 @@ impl RocksDBIO { num_tx: u64, write_batch: &mut WriteBatch, ) -> DbResult<()> { - let cf_ameta = self.account_meta_column(); + self.put_batch(&AccNumTxCell(num_tx), acc_id, write_batch) + } - write_batch.put_cf( - &cf_ameta, - borsh::to_vec(&acc_id).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize account id".to_owned())) - })?, - borsh::to_vec(&num_tx).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize acc metadata".to_owned()), - ) - })?, - ); + // Mappings - Ok(()) + pub fn put_block_id_by_hash_batch( + &self, + hash: [u8; 32], + block_id: u64, + write_batch: &mut WriteBatch, + ) -> DbResult<()> { + self.put_batch(&BlockHashToBlockIdMapCell(block_id), hash, write_batch) + } + + pub fn put_block_id_by_tx_hash_batch( + &self, + tx_hash: [u8; 32], + block_id: u64, + write_batch: &mut WriteBatch, + ) -> DbResult<()> { + self.put_batch(&TxHashToBlockIdMapCell(block_id), tx_hash, write_batch) } // Account @@ -164,7 +174,7 @@ impl RocksDBIO { block_id: u64, write_batch: &mut WriteBatch, ) -> DbResult<()> { - self.put_batch(&LastBlockCell(block_id), write_batch) + self.put_batch(&LastBlockCell(block_id), (), write_batch) } pub fn put_meta_last_observed_l1_lib_header_in_db_batch( @@ -172,26 +182,7 @@ impl RocksDBIO { l1_lib_header: [u8; 32], write_batch: &mut WriteBatch, ) -> DbResult<()> { - let cf_meta = self.meta_column(); - write_batch.put_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some( - "Failed to serialize DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY" - .to_owned(), - ), - ) - })?, - borsh::to_vec(&l1_lib_header).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize last l1 block header".to_owned()), - ) - })?, - ); - Ok(()) + self.put_batch(&LastObservedL1LibHeaderCell(l1_lib_header), (), write_batch) } pub fn put_meta_last_breakpoint_id_batch( @@ -199,46 +190,17 @@ impl RocksDBIO { br_id: u64, write_batch: &mut WriteBatch, ) -> DbResult<()> { - let cf_meta = self.meta_column(); - write_batch.put_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_BREAKPOINT_ID).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LAST_BREAKPOINT_ID".to_owned()), - ) - })?, - borsh::to_vec(&br_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize last block id".to_owned()), - ) - })?, - ); - Ok(()) + self.put_batch(&LastBreakpointIdCell(br_id), (), write_batch) } pub fn put_meta_is_first_block_set_batch(&self, write_batch: &mut WriteBatch) -> DbResult<()> { - let cf_meta = self.meta_column(); - write_batch.put_cf( - &cf_meta, - borsh::to_vec(&DB_META_FIRST_BLOCK_SET_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_FIRST_BLOCK_SET_KEY".to_owned()), - ) - })?, - [1_u8; 1], - ); - Ok(()) + self.put_batch(&FirstBlockSetCell(true), (), write_batch) } // Block pub fn put_block(&self, block: &Block, l1_lib_header: [u8; 32]) -> DbResult<()> { let cf_block = self.block_column(); - let cf_hti = self.hash_to_id_column(); - let cf_tti: Arc> = self.tx_hash_to_id_column(); let last_curr_block = self.get_meta_last_block_in_db()?; let mut write_batch = WriteBatch::default(); @@ -257,33 +219,22 @@ impl RocksDBIO { self.put_meta_last_observed_l1_lib_header_in_db_batch(l1_lib_header, &mut write_batch)?; } - write_batch.put_cf( - &cf_hti, - borsh::to_vec(&block.header.hash).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize block hash".to_owned())) - })?, - borsh::to_vec(&block.header.block_id).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize block id".to_owned())) - })?, - ); + self.put_block_id_by_hash_batch( + block.header.hash.into(), + block.header.block_id, + &mut write_batch, + )?; let mut acc_to_tx_map: HashMap<[u8; 32], Vec<[u8; 32]>> = HashMap::new(); for tx in &block.body.transactions { let tx_hash = tx.hash(); - write_batch.put_cf( - &cf_tti, - borsh::to_vec(&tx_hash).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize tx hash".to_owned())) - })?, - borsh::to_vec(&block.header.block_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize block id".to_owned()), - ) - })?, - ); + self.put_block_id_by_tx_hash_batch( + tx_hash.into(), + block.header.block_id, + &mut write_batch, + )?; let acc_ids = tx .affected_public_account_ids() diff --git a/storage/src/indexer/write_non_atomic.rs b/storage/src/indexer/write_non_atomic.rs index f44cda7d..96d133e4 100644 --- a/storage/src/indexer/write_non_atomic.rs +++ b/storage/src/indexer/write_non_atomic.rs @@ -1,8 +1,7 @@ use super::{BREAKPOINT_INTERVAL, DbError, DbResult, RocksDBIO, V03State}; -use crate::{ - DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BREAKPOINT_ID, - DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, - storable_cell::cells::meta_shared::LastBlockCell, +use crate::storable_cell::cells::{ + meta_indexer::{BreakpointCellRef, LastBreakpointIdCell, LastObservedL1LibHeaderCell}, + meta_shared::{FirstBlockSetCell, LastBlockCell}, }; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] @@ -10,100 +9,28 @@ impl RocksDBIO { // Meta pub fn put_meta_last_block_in_db(&self, block_id: u64) -> DbResult<()> { - self.put(&LastBlockCell(block_id)) + self.put(&LastBlockCell(block_id), ()) } pub fn put_meta_last_observed_l1_lib_header_in_db( &self, l1_lib_header: [u8; 32], ) -> DbResult<()> { - let cf_meta = self.meta_column(); - self.db - .put_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY).map_err( - |err| { - DbError::borsh_cast_message( - err, - Some( - "Failed to serialize DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY" - .to_owned(), - ), - ) - }, - )?, - borsh::to_vec(&l1_lib_header).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize last l1 block header".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - Ok(()) + self.put(&LastObservedL1LibHeaderCell(l1_lib_header), ()) } pub fn put_meta_last_breakpoint_id(&self, br_id: u64) -> DbResult<()> { - let cf_meta = self.meta_column(); - self.db - .put_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_BREAKPOINT_ID).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LAST_BREAKPOINT_ID".to_owned()), - ) - })?, - borsh::to_vec(&br_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize last block id".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - Ok(()) + self.put(&LastBreakpointIdCell(br_id), ()) } pub fn put_meta_is_first_block_set(&self) -> DbResult<()> { - let cf_meta = self.meta_column(); - self.db - .put_cf( - &cf_meta, - borsh::to_vec(&DB_META_FIRST_BLOCK_SET_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_FIRST_BLOCK_SET_KEY".to_owned()), - ) - })?, - [1_u8; 1], - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - Ok(()) + self.put(&FirstBlockSetCell(true), ()) } // State pub fn put_breakpoint(&self, br_id: u64, breakpoint: &V03State) -> DbResult<()> { - let cf_br = self.breakpoint_column(); - - self.db - .put_cf( - &cf_br, - borsh::to_vec(&br_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize breakpoint id".to_owned()), - ) - })?, - borsh::to_vec(breakpoint).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize breakpoint data".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None)) + self.put(&BreakpointCellRef(breakpoint), br_id) } pub fn put_next_breakpoint(&self) -> DbResult<()> { diff --git a/storage/src/lib.rs b/storage/src/lib.rs index b1126626..9aa17356 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -5,8 +5,6 @@ pub mod indexer; pub mod sequencer; pub mod storable_cell; -pub type DbResult = Result; - // General /// Maximal size of stored blocks in base. @@ -67,3 +65,5 @@ pub const DB_NSSA_STATE_KEY: &str = "nssa_state"; /// Name of state column family. pub const CF_NSSA_STATE_NAME: &str = "cf_nssa_state"; + +pub type DbResult = Result; diff --git a/storage/src/sequencer.rs b/storage/src/sequencer.rs index f04785e5..c3424fb7 100644 --- a/storage/src/sequencer.rs +++ b/storage/src/sequencer.rs @@ -8,10 +8,17 @@ use rocksdb::{ use crate::{ CF_BLOCK_NAME, CF_META_NAME, CF_NSSA_STATE_NAME, DB_META_FIRST_BLOCK_IN_DB_KEY, - DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_FINALIZED_BLOCK_ID, DB_META_LATEST_BLOCK_META_KEY, - DB_NSSA_STATE_KEY, error::DbError, - storable_cell::{SimpleStorableCell, cells::meta_shared::LastBlockCell}, + storable_cell::{ + SimpleReadableCell, SimpleWritableCell, + cells::{ + meta_sequencer::{ + LastFinalizedBlockIdCell, LatestBlockMetaCellOwned, LatestBlockMetaCellRef, + NSSAStateCellOwned, NSSAStateCellRef, + }, + meta_shared::{BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell}, + }, + }, }; pub type DbResult = Result; @@ -80,108 +87,65 @@ impl RocksDBIO { .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None)) } + // Columns + pub fn meta_column(&self) -> Arc> { - self.db.cf_handle(CF_META_NAME).unwrap() + self.db + .cf_handle(CF_META_NAME) + .expect("Meta column should exist") } pub fn block_column(&self) -> Arc> { - self.db.cf_handle(CF_BLOCK_NAME).unwrap() + self.db + .cf_handle(CF_BLOCK_NAME) + .expect("Block column should exist") } pub fn nssa_state_column(&self) -> Arc> { - self.db.cf_handle(CF_NSSA_STATE_NAME).unwrap() + self.db + .cf_handle(CF_NSSA_STATE_NAME) + .expect("State should exist") } // Generics - fn get(&self) -> DbResult { - T::get(&self.db) + fn get(&self, params: T::KeyParams) -> DbResult { + T::get(&self.db, params) } - #[expect(unused, reason = "Unused")] - fn get_opt(&self) -> DbResult> { - T::get_opt(&self.db) + fn get_opt(&self, params: T::KeyParams) -> DbResult> { + T::get_opt(&self.db, params) } - fn put(&self, cell: &T) -> DbResult<()> { - cell.put(&self.db) + fn put(&self, cell: &T, params: T::KeyParams) -> DbResult<()> { + cell.put(&self.db, params) } - fn put_batch( + fn put_batch( &self, cell: &T, + params: T::KeyParams, write_batch: &mut WriteBatch, ) -> DbResult<()> { - cell.put_batch(&self.db, write_batch) + cell.put_batch(&self.db, params, write_batch) } - pub fn get_meta_first_block_in_db(&self) -> DbResult { - let cf_meta = self.meta_column(); - let res = self - .db - .get_cf( - &cf_meta, - borsh::to_vec(&DB_META_FIRST_BLOCK_IN_DB_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_FIRST_BLOCK_IN_DB_KEY".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; + // Meta - if let Some(data) = res { - Ok(borsh::from_slice::(&data).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to deserialize first block".to_owned()), - ) - })?) - } else { - Err(DbError::db_interaction_error( - "First block not found".to_owned(), - )) - } + pub fn get_meta_first_block_in_db(&self) -> DbResult { + self.get::(()).map(|cell| cell.0) } pub fn get_meta_last_block_in_db(&self) -> DbResult { - self.get::().map(|cell| cell.0) + self.get::(()).map(|cell| cell.0) } pub fn get_meta_is_first_block_set(&self) -> DbResult { - let cf_meta = self.meta_column(); - let res = self - .db - .get_cf( - &cf_meta, - borsh::to_vec(&DB_META_FIRST_BLOCK_SET_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_FIRST_BLOCK_SET_KEY".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - Ok(res.is_some()) + Ok(self.get_opt::(())?.is_some()) } pub fn put_nssa_state_in_db(&self, state: &V03State, batch: &mut WriteBatch) -> DbResult<()> { - let cf_nssa_state = self.nssa_state_column(); - batch.put_cf( - &cf_nssa_state, - borsh::to_vec(&DB_NSSA_STATE_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_NSSA_STATE_KEY".to_owned()), - ) - })?, - borsh::to_vec(state).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize NSSA state".to_owned())) - })?, - ); - - Ok(()) + self.put_batch(&NSSAStateCellRef(state), (), batch) } pub fn put_meta_first_block_in_db(&self, block: &Block, msg_id: MantleMsgId) -> DbResult<()> { @@ -217,7 +181,7 @@ impl RocksDBIO { } pub fn put_meta_last_block_in_db(&self, block_id: u64) -> DbResult<()> { - self.put(&LastBlockCell(block_id)) + self.put(&LastBlockCell(block_id), ()) } fn put_meta_last_block_in_db_batch( @@ -225,68 +189,19 @@ impl RocksDBIO { block_id: u64, batch: &mut WriteBatch, ) -> DbResult<()> { - self.put_batch(&LastBlockCell(block_id), batch) + self.put_batch(&LastBlockCell(block_id), (), batch) } pub fn put_meta_last_finalized_block_id(&self, block_id: Option) -> DbResult<()> { - let cf_meta = self.meta_column(); - self.db - .put_cf( - &cf_meta, - borsh::to_vec(&DB_META_LAST_FINALIZED_BLOCK_ID).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LAST_FINALIZED_BLOCK_ID".to_owned()), - ) - })?, - borsh::to_vec(&block_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize last block id".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - Ok(()) + self.put(&LastFinalizedBlockIdCell(block_id), ()) } pub fn put_meta_is_first_block_set(&self) -> DbResult<()> { - let cf_meta = self.meta_column(); - self.db - .put_cf( - &cf_meta, - borsh::to_vec(&DB_META_FIRST_BLOCK_SET_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_FIRST_BLOCK_SET_KEY".to_owned()), - ) - })?, - [1_u8; 1], - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - Ok(()) + self.put(&FirstBlockSetCell(true), ()) } fn put_meta_latest_block_meta(&self, block_meta: &BlockMeta) -> DbResult<()> { - let cf_meta = self.meta_column(); - self.db - .put_cf( - &cf_meta, - borsh::to_vec(&DB_META_LATEST_BLOCK_META_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LATEST_BLOCK_META_KEY".to_owned()), - ) - })?, - borsh::to_vec(&block_meta).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize latest block meta".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - Ok(()) + self.put(&LatestBlockMetaCellRef(block_meta), ()) } fn put_meta_latest_block_meta_batch( @@ -294,52 +209,11 @@ impl RocksDBIO { block_meta: &BlockMeta, batch: &mut WriteBatch, ) -> DbResult<()> { - let cf_meta = self.meta_column(); - batch.put_cf( - &cf_meta, - borsh::to_vec(&DB_META_LATEST_BLOCK_META_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LATEST_BLOCK_META_KEY".to_owned()), - ) - })?, - borsh::to_vec(&block_meta).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize latest block meta".to_owned()), - ) - })?, - ); - Ok(()) + self.put_batch(&LatestBlockMetaCellRef(block_meta), (), batch) } pub fn latest_block_meta(&self) -> DbResult { - let cf_meta = self.meta_column(); - let res = self - .db - .get_cf( - &cf_meta, - borsh::to_vec(&DB_META_LATEST_BLOCK_META_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize DB_META_LATEST_BLOCK_META_KEY".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - if let Some(data) = res { - Ok(borsh::from_slice::(&data).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to deserialize latest block meta".to_owned()), - ) - })?) - } else { - Err(DbError::db_interaction_error( - "Latest block meta not found".to_owned(), - )) - } + self.get::(()).map(|val| val.0) } pub fn put_block( @@ -380,59 +254,12 @@ impl RocksDBIO { } pub fn get_block(&self, block_id: u64) -> DbResult> { - let cf_block = self.block_column(); - let res = self - .db - .get_cf( - &cf_block, - borsh::to_vec(&block_id).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize block id".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - if let Some(data) = res { - Ok(Some(borsh::from_slice::(&data).map_err(|serr| { - DbError::borsh_cast_message( - serr, - Some("Failed to deserialize block data".to_owned()), - ) - })?)) - } else { - Ok(None) - } + self.get_opt::(block_id) + .map(|opt| opt.map(|val| val.0)) } pub fn get_nssa_state(&self) -> DbResult { - let cf_nssa_state = self.nssa_state_column(); - let res = self - .db - .get_cf( - &cf_nssa_state, - borsh::to_vec(&DB_NSSA_STATE_KEY).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize block id".to_owned()), - ) - })?, - ) - .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; - - if let Some(data) = res { - Ok(borsh::from_slice::(&data).map_err(|serr| { - DbError::borsh_cast_message( - serr, - Some("Failed to deserialize block data".to_owned()), - ) - })?) - } else { - Err(DbError::db_interaction_error( - "NSSA state not found".to_owned(), - )) - } + self.get::(()).map(|val| val.0) } pub fn delete_block(&self, block_id: u64) -> DbResult<()> { diff --git a/storage/src/storable_cell/cells/meta_indexer.rs b/storage/src/storable_cell/cells/meta_indexer.rs index 8b137891..7322ba8f 100644 --- a/storage/src/storable_cell/cells/meta_indexer.rs +++ b/storage/src/storable_cell/cells/meta_indexer.rs @@ -1 +1,287 @@ +use borsh::{BorshDeserialize, BorshSerialize}; +use nssa::V03State; +use crate::{ + CF_ACC_META, CF_BREAKPOINT_NAME, CF_HASH_TO_ID, CF_META_NAME, CF_TX_TO_ID, + DB_META_LAST_BREAKPOINT_ID, DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, DbResult, + error::DbError, + storable_cell::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, +}; + +#[derive(Debug)] +pub struct LastObservedL1LibHeaderCell(pub [u8; 32]); + +impl BorshSerialize for LastObservedL1LibHeaderCell { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + <[u8; 32]>::serialize(&self.0, writer) + } +} + +impl BorshDeserialize for LastObservedL1LibHeaderCell { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + <[u8; 32]>::deserialize_reader(reader).map(LastObservedL1LibHeaderCell) + } +} + +impl SimpleStorableCell for LastObservedL1LibHeaderCell { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY; + const CF_NAME: &'static str = CF_META_NAME; + + fn key_constructor(_params: Self::KeyParams) -> DbResult> { + borsh::to_vec(&Self::CELL_NAME).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message( + err, + Some("Failed to serialize last observed l1 header".to_owned()), + ) + }) + } +} + +impl SimpleReadableCell for LastObservedL1LibHeaderCell {} + +impl SimpleWritableCell for LastObservedL1LibHeaderCell {} + +#[derive(Debug)] +pub struct LastBreakpointIdCell(pub u64); + +impl BorshSerialize for LastBreakpointIdCell { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + u64::serialize(&self.0, writer) + } +} + +impl BorshDeserialize for LastBreakpointIdCell { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + u64::deserialize_reader(reader).map(LastBreakpointIdCell) + } +} + +impl SimpleStorableCell for LastBreakpointIdCell { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_LAST_BREAKPOINT_ID; + const CF_NAME: &'static str = CF_META_NAME; + + fn key_constructor(_params: Self::KeyParams) -> DbResult> { + borsh::to_vec(&Self::CELL_NAME).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message( + err, + Some("Failed to serialize last breakpoint id".to_owned()), + ) + }) + } +} + +impl SimpleReadableCell for LastBreakpointIdCell {} + +impl SimpleWritableCell for LastBreakpointIdCell {} + +pub struct BreakpointCellOwned(pub V03State); + +impl BorshDeserialize for BreakpointCellOwned { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + V03State::deserialize_reader(reader).map(BreakpointCellOwned) + } +} + +impl SimpleStorableCell for BreakpointCellOwned { + type KeyParams = u64; + + const CELL_NAME: &'static str = "breakpoint"; + const CF_NAME: &'static str = CF_BREAKPOINT_NAME; + + fn key_constructor(params: Self::KeyParams) -> DbResult> { + borsh::to_vec(¶ms).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self.0).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize breakpoint".to_owned())) + }) + } +} + +impl SimpleReadableCell for BreakpointCellOwned {} + +pub struct BreakpointCellRef<'state>(pub &'state V03State); + +impl BorshSerialize for BreakpointCellRef<'_> { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + V03State::serialize(self.0, writer) + } +} + +impl SimpleStorableCell for BreakpointCellRef<'_> { + type KeyParams = u64; + + const CELL_NAME: &'static str = "breakpoint"; + const CF_NAME: &'static str = CF_BREAKPOINT_NAME; + + fn key_constructor(params: Self::KeyParams) -> DbResult> { + borsh::to_vec(¶ms).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize breakpoint".to_owned())) + }) + } +} + +impl SimpleWritableCell for BreakpointCellRef<'_> {} + +#[derive(Debug)] +pub struct BlockHashToBlockIdMapCell(pub u64); + +impl BorshSerialize for BlockHashToBlockIdMapCell { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + u64::serialize(&self.0, writer) + } +} + +impl BorshDeserialize for BlockHashToBlockIdMapCell { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + u64::deserialize_reader(reader).map(BlockHashToBlockIdMapCell) + } +} + +impl SimpleStorableCell for BlockHashToBlockIdMapCell { + type KeyParams = [u8; 32]; + + const CELL_NAME: &'static str = "block hash"; + const CF_NAME: &'static str = CF_HASH_TO_ID; + + fn key_constructor(params: Self::KeyParams) -> DbResult> { + borsh::to_vec(¶ms).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize block id".to_owned())) + }) + } +} + +impl SimpleReadableCell for BlockHashToBlockIdMapCell {} + +impl SimpleWritableCell for BlockHashToBlockIdMapCell {} + +#[derive(Debug)] +pub struct TxHashToBlockIdMapCell(pub u64); + +impl BorshSerialize for TxHashToBlockIdMapCell { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + u64::serialize(&self.0, writer) + } +} + +impl BorshDeserialize for TxHashToBlockIdMapCell { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + u64::deserialize_reader(reader).map(TxHashToBlockIdMapCell) + } +} + +impl SimpleStorableCell for TxHashToBlockIdMapCell { + type KeyParams = [u8; 32]; + + const CELL_NAME: &'static str = "tx hash"; + const CF_NAME: &'static str = CF_TX_TO_ID; + + fn key_constructor(params: Self::KeyParams) -> DbResult> { + borsh::to_vec(¶ms).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize block id".to_owned())) + }) + } +} + +impl SimpleReadableCell for TxHashToBlockIdMapCell {} + +impl SimpleWritableCell for TxHashToBlockIdMapCell {} + +#[derive(Debug)] +pub struct AccNumTxCell(pub u64); + +impl BorshSerialize for AccNumTxCell { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + u64::serialize(&self.0, writer) + } +} + +impl BorshDeserialize for AccNumTxCell { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + u64::deserialize_reader(reader).map(AccNumTxCell) + } +} + +impl SimpleStorableCell for AccNumTxCell { + type KeyParams = [u8; 32]; + + const CELL_NAME: &'static str = "acc id"; + const CF_NAME: &'static str = CF_ACC_META; + + fn key_constructor(params: Self::KeyParams) -> DbResult> { + borsh::to_vec(¶ms).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message( + err, + Some("Failed to serialize number of transactions".to_owned()), + ) + }) + } +} + +impl SimpleReadableCell for AccNumTxCell {} + +impl SimpleWritableCell for AccNumTxCell {} diff --git a/storage/src/storable_cell/cells/meta_sequencer.rs b/storage/src/storable_cell/cells/meta_sequencer.rs index 8b137891..9c564fd5 100644 --- a/storage/src/storable_cell/cells/meta_sequencer.rs +++ b/storage/src/storable_cell/cells/meta_sequencer.rs @@ -1 +1,182 @@ +use borsh::{BorshDeserialize, BorshSerialize}; +use common::block::BlockMeta; +use nssa::V03State; +use crate::{ + CF_META_NAME, CF_NSSA_STATE_NAME, DB_META_LAST_FINALIZED_BLOCK_ID, + DB_META_LATEST_BLOCK_META_KEY, DB_NSSA_STATE_KEY, DbResult, + error::DbError, + storable_cell::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, +}; + +pub struct NSSAStateCellOwned(pub V03State); + +impl BorshDeserialize for NSSAStateCellOwned { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + V03State::deserialize_reader(reader).map(NSSAStateCellOwned) + } +} + +impl SimpleStorableCell for NSSAStateCellOwned { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_NSSA_STATE_KEY; + const CF_NAME: &'static str = CF_NSSA_STATE_NAME; + + fn key_constructor(_params: Self::KeyParams) -> DbResult> { + borsh::to_vec(&Self::CELL_NAME).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self.0).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize last state".to_owned())) + }) + } +} + +impl SimpleReadableCell for NSSAStateCellOwned {} + +pub struct NSSAStateCellRef<'state>(pub &'state V03State); + +impl BorshSerialize for NSSAStateCellRef<'_> { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + V03State::serialize(self.0, writer) + } +} + +impl SimpleStorableCell for NSSAStateCellRef<'_> { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_NSSA_STATE_KEY; + const CF_NAME: &'static str = CF_NSSA_STATE_NAME; + + fn key_constructor(_params: Self::KeyParams) -> DbResult> { + borsh::to_vec(&Self::CELL_NAME).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize last state".to_owned())) + }) + } +} + +impl SimpleWritableCell for NSSAStateCellRef<'_> {} + +#[derive(Debug)] +pub struct LastFinalizedBlockIdCell(pub Option); + +impl BorshSerialize for LastFinalizedBlockIdCell { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + Option::::serialize(&self.0, writer) + } +} + +impl BorshDeserialize for LastFinalizedBlockIdCell { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + Option::::deserialize_reader(reader).map(LastFinalizedBlockIdCell) + } +} + +impl SimpleStorableCell for LastFinalizedBlockIdCell { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_LAST_FINALIZED_BLOCK_ID; + const CF_NAME: &'static str = CF_META_NAME; + + fn key_constructor(_params: Self::KeyParams) -> DbResult> { + borsh::to_vec(&Self::CELL_NAME).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message( + err, + Some("Failed to serialize last finalized block id".to_owned()), + ) + }) + } +} + +impl SimpleReadableCell for LastFinalizedBlockIdCell {} + +impl SimpleWritableCell for LastFinalizedBlockIdCell {} + +pub struct LatestBlockMetaCellOwned(pub BlockMeta); + +impl BorshDeserialize for LatestBlockMetaCellOwned { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + BlockMeta::deserialize_reader(reader).map(LatestBlockMetaCellOwned) + } +} + +impl SimpleStorableCell for LatestBlockMetaCellOwned { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_LATEST_BLOCK_META_KEY; + const CF_NAME: &'static str = CF_META_NAME; + + fn key_constructor(_params: Self::KeyParams) -> DbResult> { + borsh::to_vec(&Self::CELL_NAME).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self.0).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize last block meta".to_owned())) + }) + } +} + +impl SimpleReadableCell for LatestBlockMetaCellOwned {} + +pub struct LatestBlockMetaCellRef<'blockmeta>(pub &'blockmeta BlockMeta); + +impl BorshSerialize for LatestBlockMetaCellRef<'_> { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + BlockMeta::serialize(self.0, writer) + } +} + +impl SimpleStorableCell for LatestBlockMetaCellRef<'_> { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_LATEST_BLOCK_META_KEY; + const CF_NAME: &'static str = CF_META_NAME; + + fn key_constructor(_params: Self::KeyParams) -> DbResult> { + borsh::to_vec(&Self::CELL_NAME).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize last block meta".to_owned())) + }) + } +} + +impl SimpleWritableCell for LatestBlockMetaCellRef<'_> {} diff --git a/storage/src/storable_cell/cells/meta_shared.rs b/storage/src/storable_cell/cells/meta_shared.rs index 4b88a385..21ca74fc 100644 --- a/storage/src/storable_cell/cells/meta_shared.rs +++ b/storage/src/storable_cell/cells/meta_shared.rs @@ -1,8 +1,11 @@ use borsh::{BorshDeserialize, BorshSerialize}; +use common::block::Block; use crate::{ - CF_META_NAME, DB_META_LAST_BLOCK_IN_DB_KEY, DbResult, error::DbError, - storable_cell::SimpleStorableCell, + CF_BLOCK_NAME, CF_META_NAME, DB_META_FIRST_BLOCK_IN_DB_KEY, DB_META_FIRST_BLOCK_SET_KEY, + DB_META_LAST_BLOCK_IN_DB_KEY, DbResult, + error::DbError, + storable_cell::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, }; #[derive(Debug)] @@ -21,10 +24,12 @@ impl BorshDeserialize for LastBlockCell { } impl SimpleStorableCell for LastBlockCell { + type KeyParams = (); + const CELL_NAME: &'static str = DB_META_LAST_BLOCK_IN_DB_KEY; const CF_NAME: &'static str = CF_META_NAME; - fn key_constructor() -> DbResult> { + fn key_constructor(_params: Self::KeyParams) -> DbResult> { borsh::to_vec(&Self::CELL_NAME).map_err(|err| { DbError::borsh_cast_message( err, @@ -34,8 +39,135 @@ impl SimpleStorableCell for LastBlockCell { } fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self.0).map_err(|err| { + borsh::to_vec(&self).map_err(|err| { DbError::borsh_cast_message(err, Some("Failed to serialize last block id".to_owned())) }) } } + +impl SimpleReadableCell for LastBlockCell {} + +impl SimpleWritableCell for LastBlockCell {} + +#[derive(Debug)] +pub struct FirstBlockSetCell(pub bool); + +impl BorshSerialize for FirstBlockSetCell { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + bool::serialize(&self.0, writer) + } +} + +impl BorshDeserialize for FirstBlockSetCell { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + bool::deserialize_reader(reader).map(FirstBlockSetCell) + } +} + +impl SimpleStorableCell for FirstBlockSetCell { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_FIRST_BLOCK_SET_KEY; + const CF_NAME: &'static str = CF_META_NAME; + + fn key_constructor(_params: Self::KeyParams) -> DbResult> { + borsh::to_vec(&Self::CELL_NAME).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message( + err, + Some("Failed to serialize first block set flag".to_owned()), + ) + }) + } +} + +impl SimpleReadableCell for FirstBlockSetCell {} + +impl SimpleWritableCell for FirstBlockSetCell {} + +#[derive(Debug)] +pub struct FirstBlockCell(pub u64); + +impl BorshSerialize for FirstBlockCell { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + u64::serialize(&self.0, writer) + } +} + +impl BorshDeserialize for FirstBlockCell { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + u64::deserialize_reader(reader).map(FirstBlockCell) + } +} + +impl SimpleStorableCell for FirstBlockCell { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_FIRST_BLOCK_IN_DB_KEY; + const CF_NAME: &'static str = CF_META_NAME; + + fn key_constructor(_params: Self::KeyParams) -> DbResult> { + borsh::to_vec(&Self::CELL_NAME).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize first block id".to_owned())) + }) + } +} + +impl SimpleReadableCell for FirstBlockCell {} + +#[derive(Debug)] +pub struct BlockCell(pub Block); + +impl BorshSerialize for BlockCell { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + Block::serialize(&self.0, writer) + } +} + +impl BorshDeserialize for BlockCell { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + Block::deserialize_reader(reader).map(BlockCell) + } +} + +impl SimpleStorableCell for BlockCell { + type KeyParams = u64; + + const CELL_NAME: &'static str = "block"; + const CF_NAME: &'static str = CF_BLOCK_NAME; + + fn key_constructor(params: Self::KeyParams) -> DbResult> { + // ToDo: Replace with increasing ordering serialization + borsh::to_vec(¶ms).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } + + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize block".to_owned())) + }) + } +} + +impl SimpleReadableCell for BlockCell {} diff --git a/storage/src/storable_cell/mod.rs b/storage/src/storable_cell/mod.rs index 06912829..8aa8b779 100644 --- a/storage/src/storable_cell/mod.rs +++ b/storage/src/storable_cell/mod.rs @@ -7,22 +7,25 @@ use crate::{DbResult, error::DbError}; pub mod cells; -pub trait SimpleStorableCell: BorshSerialize + BorshDeserialize { +pub trait SimpleStorableCell { const CF_NAME: &'static str; const CELL_NAME: &'static str; + type KeyParams; - fn key_constructor() -> DbResult>; + fn key_constructor(params: Self::KeyParams) -> DbResult>; fn value_constructor(&self) -> DbResult>; fn column_ref(db: &DBWithThreadMode) -> Arc> { db.cf_handle(Self::CF_NAME) .unwrap_or_else(|| panic!("Column family {:?} must be present", Self::CF_NAME)) } +} - fn get(db: &DBWithThreadMode) -> DbResult { +pub trait SimpleReadableCell: SimpleStorableCell + BorshDeserialize { + fn get(db: &DBWithThreadMode, params: Self::KeyParams) -> DbResult { let cf_ref = Self::column_ref(db); let res = db - .get_cf(&cf_ref, Self::key_constructor()?) + .get_cf(&cf_ref, Self::key_constructor(params)?) .map_err(|rerr| { DbError::rocksdb_cast_message( rerr, @@ -45,10 +48,13 @@ pub trait SimpleStorableCell: BorshSerialize + BorshDeserialize { } } - fn get_opt(db: &DBWithThreadMode) -> DbResult> { + fn get_opt( + db: &DBWithThreadMode, + params: Self::KeyParams, + ) -> DbResult> { let cf_ref = Self::column_ref(db); let res = db - .get_cf(&cf_ref, Self::key_constructor()?) + .get_cf(&cf_ref, Self::key_constructor(params)?) .map_err(|rerr| { DbError::rocksdb_cast_message( rerr, @@ -66,26 +72,37 @@ pub trait SimpleStorableCell: BorshSerialize + BorshDeserialize { }) .transpose() } +} - fn put(&self, db: &DBWithThreadMode) -> DbResult<()> { +pub trait SimpleWritableCell: SimpleStorableCell + BorshSerialize { + fn put(&self, db: &DBWithThreadMode, params: Self::KeyParams) -> DbResult<()> { let cf_ref = Self::column_ref(db); - db.put_cf(&cf_ref, Self::key_constructor()?, self.value_constructor()?) - .map_err(|rerr| { - DbError::rocksdb_cast_message( - rerr, - Some(format!("Failed to write {:?}", Self::CELL_NAME)), - ) - })?; + db.put_cf( + &cf_ref, + Self::key_constructor(params)?, + self.value_constructor()?, + ) + .map_err(|rerr| { + DbError::rocksdb_cast_message( + rerr, + Some(format!("Failed to write {:?}", Self::CELL_NAME)), + ) + })?; Ok(()) } fn put_batch( &self, db: &DBWithThreadMode, + params: Self::KeyParams, write_batch: &mut WriteBatch, ) -> DbResult<()> { let cf_ref = Self::column_ref(db); - write_batch.put_cf(&cf_ref, Self::key_constructor()?, self.value_constructor()?); + write_batch.put_cf( + &cf_ref, + Self::key_constructor(params)?, + self.value_constructor()?, + ); Ok(()) } } From f59bcde78acdb084cf76350f202fee8a485fe1de Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Tue, 31 Mar 2026 09:08:40 +0300 Subject: [PATCH 4/6] fix: suggestions fix --- .../indexer_cells.rs} | 223 ++++++------------ storage/src/indexer/mod.rs | 30 ++- storage/src/indexer/read_once.rs | 8 +- storage/src/indexer/write_atomic.rs | 10 +- storage/src/indexer/write_non_atomic.rs | 8 +- storage/src/lib.rs | 37 +-- .../src/{sequencer.rs => sequencer/mod.rs} | 27 ++- storage/src/sequencer/sequencer_cells.rs | 96 ++++++++ .../src/storable_cell/cells/meta_sequencer.rs | 182 -------------- .../src/storable_cell/cells/meta_shared.rs | 173 -------------- storage/src/storable_cell/cells/mod.rs | 4 +- .../src/storable_cell/cells/shared_cells.rs | 89 +++++++ storage/src/storable_cell/mod.rs | 44 ++-- 13 files changed, 343 insertions(+), 588 deletions(-) rename storage/src/{storable_cell/cells/meta_indexer.rs => indexer/indexer_cells.rs} (50%) rename storage/src/{sequencer.rs => sequencer/mod.rs} (93%) create mode 100644 storage/src/sequencer/sequencer_cells.rs delete mode 100644 storage/src/storable_cell/cells/meta_sequencer.rs delete mode 100644 storage/src/storable_cell/cells/meta_shared.rs create mode 100644 storage/src/storable_cell/cells/shared_cells.rs diff --git a/storage/src/storable_cell/cells/meta_indexer.rs b/storage/src/indexer/indexer_cells.rs similarity index 50% rename from storage/src/storable_cell/cells/meta_indexer.rs rename to storage/src/indexer/indexer_cells.rs index 7322ba8f..144f56b9 100644 --- a/storage/src/storable_cell/cells/meta_indexer.rs +++ b/storage/src/indexer/indexer_cells.rs @@ -2,42 +2,29 @@ use borsh::{BorshDeserialize, BorshSerialize}; use nssa::V03State; use crate::{ - CF_ACC_META, CF_BREAKPOINT_NAME, CF_HASH_TO_ID, CF_META_NAME, CF_TX_TO_ID, - DB_META_LAST_BREAKPOINT_ID, DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, DbResult, + CF_META_NAME, DbResult, error::DbError, + indexer::{ + ACC_NUM_CELL_NAME, BLOCK_HASH_CELL_NAME, BREAKPOINT_CELL_NAME, CF_ACC_META, + CF_BREAKPOINT_NAME, CF_HASH_TO_ID, CF_TX_TO_ID, DB_META_LAST_BREAKPOINT_ID, + DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, TX_HASH_CELL_NAME, + }, storable_cell::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, }; -#[derive(Debug)] +#[derive(Debug, BorshSerialize, BorshDeserialize)] pub struct LastObservedL1LibHeaderCell(pub [u8; 32]); -impl BorshSerialize for LastObservedL1LibHeaderCell { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - <[u8; 32]>::serialize(&self.0, writer) - } -} - -impl BorshDeserialize for LastObservedL1LibHeaderCell { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - <[u8; 32]>::deserialize_reader(reader).map(LastObservedL1LibHeaderCell) - } -} - impl SimpleStorableCell for LastObservedL1LibHeaderCell { type KeyParams = (); const CELL_NAME: &'static str = DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY; const CF_NAME: &'static str = CF_META_NAME; +} - fn key_constructor(_params: Self::KeyParams) -> DbResult> { - borsh::to_vec(&Self::CELL_NAME).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } +impl SimpleReadableCell for LastObservedL1LibHeaderCell {} +impl SimpleWritableCell for LastObservedL1LibHeaderCell { fn value_constructor(&self) -> DbResult> { borsh::to_vec(&self).map_err(|err| { DbError::borsh_cast_message( @@ -48,40 +35,19 @@ impl SimpleStorableCell for LastObservedL1LibHeaderCell { } } -impl SimpleReadableCell for LastObservedL1LibHeaderCell {} - -impl SimpleWritableCell for LastObservedL1LibHeaderCell {} - -#[derive(Debug)] +#[derive(Debug, BorshSerialize, BorshDeserialize)] pub struct LastBreakpointIdCell(pub u64); -impl BorshSerialize for LastBreakpointIdCell { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - u64::serialize(&self.0, writer) - } -} - -impl BorshDeserialize for LastBreakpointIdCell { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - u64::deserialize_reader(reader).map(LastBreakpointIdCell) - } -} - impl SimpleStorableCell for LastBreakpointIdCell { type KeyParams = (); const CELL_NAME: &'static str = DB_META_LAST_BREAKPOINT_ID; const CF_NAME: &'static str = CF_META_NAME; +} - fn key_constructor(_params: Self::KeyParams) -> DbResult> { - borsh::to_vec(&Self::CELL_NAME).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } +impl SimpleReadableCell for LastBreakpointIdCell {} +impl SimpleWritableCell for LastBreakpointIdCell { fn value_constructor(&self) -> DbResult> { borsh::to_vec(&self).map_err(|err| { DbError::borsh_cast_message( @@ -92,65 +58,53 @@ impl SimpleStorableCell for LastBreakpointIdCell { } } -impl SimpleReadableCell for LastBreakpointIdCell {} - -impl SimpleWritableCell for LastBreakpointIdCell {} - +#[derive(BorshDeserialize)] pub struct BreakpointCellOwned(pub V03State); -impl BorshDeserialize for BreakpointCellOwned { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - V03State::deserialize_reader(reader).map(BreakpointCellOwned) - } -} - impl SimpleStorableCell for BreakpointCellOwned { type KeyParams = u64; - const CELL_NAME: &'static str = "breakpoint"; + const CELL_NAME: &'static str = BREAKPOINT_CELL_NAME; const CF_NAME: &'static str = CF_BREAKPOINT_NAME; fn key_constructor(params: Self::KeyParams) -> DbResult> { borsh::to_vec(¶ms).map_err(|err| { DbError::borsh_cast_message( err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + Some(format!( + "Failed to serialize {:?} key params", + Self::CELL_NAME + )), ) }) } - - fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self.0).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize breakpoint".to_owned())) - }) - } } impl SimpleReadableCell for BreakpointCellOwned {} +#[derive(BorshSerialize)] pub struct BreakpointCellRef<'state>(pub &'state V03State); -impl BorshSerialize for BreakpointCellRef<'_> { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - V03State::serialize(self.0, writer) - } -} - impl SimpleStorableCell for BreakpointCellRef<'_> { type KeyParams = u64; - const CELL_NAME: &'static str = "breakpoint"; + const CELL_NAME: &'static str = BREAKPOINT_CELL_NAME; const CF_NAME: &'static str = CF_BREAKPOINT_NAME; fn key_constructor(params: Self::KeyParams) -> DbResult> { borsh::to_vec(¶ms).map_err(|err| { DbError::borsh_cast_message( err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + Some(format!( + "Failed to serialize {:?} key params", + Self::CELL_NAME + )), ) }) } +} +impl SimpleWritableCell for BreakpointCellRef<'_> { fn value_constructor(&self) -> DbResult> { borsh::to_vec(&self).map_err(|err| { DbError::borsh_cast_message(err, Some("Failed to serialize breakpoint".to_owned())) @@ -158,79 +112,31 @@ impl SimpleStorableCell for BreakpointCellRef<'_> { } } -impl SimpleWritableCell for BreakpointCellRef<'_> {} - -#[derive(Debug)] +#[derive(Debug, BorshSerialize, BorshDeserialize)] pub struct BlockHashToBlockIdMapCell(pub u64); -impl BorshSerialize for BlockHashToBlockIdMapCell { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - u64::serialize(&self.0, writer) - } -} - -impl BorshDeserialize for BlockHashToBlockIdMapCell { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - u64::deserialize_reader(reader).map(BlockHashToBlockIdMapCell) - } -} - impl SimpleStorableCell for BlockHashToBlockIdMapCell { type KeyParams = [u8; 32]; - const CELL_NAME: &'static str = "block hash"; + const CELL_NAME: &'static str = BLOCK_HASH_CELL_NAME; const CF_NAME: &'static str = CF_HASH_TO_ID; fn key_constructor(params: Self::KeyParams) -> DbResult> { borsh::to_vec(¶ms).map_err(|err| { DbError::borsh_cast_message( err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + Some(format!( + "Failed to serialize {:?} key params", + Self::CELL_NAME + )), ) }) } - - fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize block id".to_owned())) - }) - } } impl SimpleReadableCell for BlockHashToBlockIdMapCell {} -impl SimpleWritableCell for BlockHashToBlockIdMapCell {} - -#[derive(Debug)] -pub struct TxHashToBlockIdMapCell(pub u64); - -impl BorshSerialize for TxHashToBlockIdMapCell { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - u64::serialize(&self.0, writer) - } -} - -impl BorshDeserialize for TxHashToBlockIdMapCell { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - u64::deserialize_reader(reader).map(TxHashToBlockIdMapCell) - } -} - -impl SimpleStorableCell for TxHashToBlockIdMapCell { - type KeyParams = [u8; 32]; - - const CELL_NAME: &'static str = "tx hash"; - const CF_NAME: &'static str = CF_TX_TO_ID; - - fn key_constructor(params: Self::KeyParams) -> DbResult> { - borsh::to_vec(¶ms).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } - +impl SimpleWritableCell for BlockHashToBlockIdMapCell { fn value_constructor(&self) -> DbResult> { borsh::to_vec(&self).map_err(|err| { DbError::borsh_cast_message(err, Some("Failed to serialize block id".to_owned())) @@ -238,40 +144,63 @@ impl SimpleStorableCell for TxHashToBlockIdMapCell { } } +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct TxHashToBlockIdMapCell(pub u64); + +impl SimpleStorableCell for TxHashToBlockIdMapCell { + type KeyParams = [u8; 32]; + + const CELL_NAME: &'static str = TX_HASH_CELL_NAME; + const CF_NAME: &'static str = CF_TX_TO_ID; + + fn key_constructor(params: Self::KeyParams) -> DbResult> { + borsh::to_vec(¶ms).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!( + "Failed to serialize {:?} key params", + Self::CELL_NAME + )), + ) + }) + } +} + impl SimpleReadableCell for TxHashToBlockIdMapCell {} -impl SimpleWritableCell for TxHashToBlockIdMapCell {} +impl SimpleWritableCell for TxHashToBlockIdMapCell { + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize block id".to_owned())) + }) + } +} -#[derive(Debug)] +#[derive(Debug, BorshSerialize, BorshDeserialize)] pub struct AccNumTxCell(pub u64); -impl BorshSerialize for AccNumTxCell { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - u64::serialize(&self.0, writer) - } -} - -impl BorshDeserialize for AccNumTxCell { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - u64::deserialize_reader(reader).map(AccNumTxCell) - } -} - impl SimpleStorableCell for AccNumTxCell { type KeyParams = [u8; 32]; - const CELL_NAME: &'static str = "acc id"; + const CELL_NAME: &'static str = ACC_NUM_CELL_NAME; const CF_NAME: &'static str = CF_ACC_META; fn key_constructor(params: Self::KeyParams) -> DbResult> { borsh::to_vec(¶ms).map_err(|err| { DbError::borsh_cast_message( err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + Some(format!( + "Failed to serialize {:?} key params", + Self::CELL_NAME + )), ) }) } +} +impl SimpleReadableCell for AccNumTxCell {} + +impl SimpleWritableCell for AccNumTxCell { fn value_constructor(&self) -> DbResult> { borsh::to_vec(&self).map_err(|err| { DbError::borsh_cast_message( @@ -281,7 +210,3 @@ impl SimpleStorableCell for AccNumTxCell { }) } } - -impl SimpleReadableCell for AccNumTxCell {} - -impl SimpleWritableCell for AccNumTxCell {} diff --git a/storage/src/indexer/mod.rs b/storage/src/indexer/mod.rs index f91c40d8..7d4bce09 100644 --- a/storage/src/indexer/mod.rs +++ b/storage/src/indexer/mod.rs @@ -7,17 +7,43 @@ use rocksdb::{ }; use crate::{ - BREAKPOINT_INTERVAL, CF_ACC_META, CF_ACC_TO_TX, CF_BLOCK_NAME, CF_BREAKPOINT_NAME, - CF_HASH_TO_ID, CF_META_NAME, CF_TX_TO_ID, DbResult, + BREAKPOINT_INTERVAL, CF_BLOCK_NAME, CF_META_NAME, DbResult, error::DbError, storable_cell::{SimpleReadableCell, SimpleWritableCell}, }; +pub mod indexer_cells; pub mod read_multiple; pub mod read_once; pub mod write_atomic; pub mod write_non_atomic; +/// Key base for storing metainformation about id of last observed L1 lib header in db. +pub const DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY: &str = + "last_observed_l1_lib_header_in_db"; +/// Key base for storing metainformation about the last breakpoint. +pub const DB_META_LAST_BREAKPOINT_ID: &str = "last_breakpoint_id"; + +/// Cell name for a breakpoint. +pub const BREAKPOINT_CELL_NAME: &str = "breakpoint"; +/// Cell name for a block hash to block id map. +pub const BLOCK_HASH_CELL_NAME: &str = "block hash"; +/// Cell name for a tx hash to block id map. +pub const TX_HASH_CELL_NAME: &str = "tx hash"; +/// Cell name for a account number of transactions. +pub const ACC_NUM_CELL_NAME: &str = "acc id"; + +/// Name of breakpoint column family. +pub const CF_BREAKPOINT_NAME: &str = "cf_breakpoint"; +/// Name of hash to id map column family. +pub const CF_HASH_TO_ID: &str = "cf_hash_to_id"; +/// Name of tx hash to id map column family. +pub const CF_TX_TO_ID: &str = "cf_tx_to_id"; +/// Name of account meta column family. +pub const CF_ACC_META: &str = "cf_acc_meta"; +/// Name of account id to tx hash map column family. +pub const CF_ACC_TO_TX: &str = "cf_acc_to_tx"; + pub struct RocksDBIO { pub db: DBWithThreadMode, } diff --git a/storage/src/indexer/read_once.rs b/storage/src/indexer/read_once.rs index a7cedd58..a652b8e9 100644 --- a/storage/src/indexer/read_once.rs +++ b/storage/src/indexer/read_once.rs @@ -1,10 +1,12 @@ use super::{Block, DbResult, RocksDBIO, V03State}; -use crate::storable_cell::cells::{ - meta_indexer::{ +use crate::{ + indexer::indexer_cells::{ AccNumTxCell, BlockHashToBlockIdMapCell, BreakpointCellOwned, LastBreakpointIdCell, LastObservedL1LibHeaderCell, TxHashToBlockIdMapCell, }, - meta_shared::{BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell}, + storable_cell::cells::shared_cells::{ + BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell, + }, }; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] diff --git a/storage/src/indexer/write_atomic.rs b/storage/src/indexer/write_atomic.rs index cff8284a..e1145131 100644 --- a/storage/src/indexer/write_atomic.rs +++ b/storage/src/indexer/write_atomic.rs @@ -5,13 +5,11 @@ use rocksdb::WriteBatch; use super::{BREAKPOINT_INTERVAL, Block, DbError, DbResult, RocksDBIO}; use crate::{ DB_META_FIRST_BLOCK_IN_DB_KEY, - storable_cell::cells::{ - meta_indexer::{ - AccNumTxCell, BlockHashToBlockIdMapCell, LastBreakpointIdCell, - LastObservedL1LibHeaderCell, TxHashToBlockIdMapCell, - }, - meta_shared::{FirstBlockSetCell, LastBlockCell}, + indexer::indexer_cells::{ + AccNumTxCell, BlockHashToBlockIdMapCell, LastBreakpointIdCell, LastObservedL1LibHeaderCell, + TxHashToBlockIdMapCell, }, + storable_cell::cells::shared_cells::{FirstBlockSetCell, LastBlockCell}, }; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] diff --git a/storage/src/indexer/write_non_atomic.rs b/storage/src/indexer/write_non_atomic.rs index 96d133e4..d5a862f4 100644 --- a/storage/src/indexer/write_non_atomic.rs +++ b/storage/src/indexer/write_non_atomic.rs @@ -1,7 +1,9 @@ use super::{BREAKPOINT_INTERVAL, DbError, DbResult, RocksDBIO, V03State}; -use crate::storable_cell::cells::{ - meta_indexer::{BreakpointCellRef, LastBreakpointIdCell, LastObservedL1LibHeaderCell}, - meta_shared::{FirstBlockSetCell, LastBlockCell}, +use crate::{ + indexer::indexer_cells::{ + BreakpointCellRef, LastBreakpointIdCell, LastObservedL1LibHeaderCell, + }, + storable_cell::cells::shared_cells::{FirstBlockSetCell, LastBlockCell}, }; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] diff --git a/storage/src/lib.rs b/storage/src/lib.rs index 9aa17356..5d9f8705 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -5,8 +5,6 @@ pub mod indexer; pub mod sequencer; pub mod storable_cell; -// General - /// Maximal size of stored blocks in base. /// /// Used to control db size. @@ -26,6 +24,9 @@ pub const DB_META_FIRST_BLOCK_IN_DB_KEY: &str = "first_block_in_db"; /// Key base for storing metainformation about id of last current block in db. pub const DB_META_LAST_BLOCK_IN_DB_KEY: &str = "last_block_in_db"; +/// Cell name for a block. +pub const BLOCK_CELL_NAME: &str = "block"; + /// Interval between state breakpoints. pub const BREAKPOINT_INTERVAL: u8 = 100; @@ -34,36 +35,4 @@ pub const CF_BLOCK_NAME: &str = "cf_block"; /// Name of meta column family. pub const CF_META_NAME: &str = "cf_meta"; -// Indexer-specific - -/// Key base for storing metainformation about id of last observed L1 lib header in db. -pub const DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY: &str = - "last_observed_l1_lib_header_in_db"; -/// Key base for storing metainformation about the last breakpoint. -pub const DB_META_LAST_BREAKPOINT_ID: &str = "last_breakpoint_id"; - -/// Name of breakpoint column family. -pub const CF_BREAKPOINT_NAME: &str = "cf_breakpoint"; -/// Name of hash to id map column family. -pub const CF_HASH_TO_ID: &str = "cf_hash_to_id"; -/// Name of tx hash to id map column family. -pub const CF_TX_TO_ID: &str = "cf_tx_to_id"; -/// Name of account meta column family. -pub const CF_ACC_META: &str = "cf_acc_meta"; -/// Name of account id to tx hash map column family. -pub const CF_ACC_TO_TX: &str = "cf_acc_to_tx"; - -// Sequencer-specific - -/// Key base for storing metainformation about the last finalized block on Bedrock. -pub const DB_META_LAST_FINALIZED_BLOCK_ID: &str = "last_finalized_block_id"; -/// Key base for storing metainformation about the latest block meta. -pub const DB_META_LATEST_BLOCK_META_KEY: &str = "latest_block_meta"; - -/// Key base for storing the NSSA state. -pub const DB_NSSA_STATE_KEY: &str = "nssa_state"; - -/// Name of state column family. -pub const CF_NSSA_STATE_NAME: &str = "cf_nssa_state"; - pub type DbResult = Result; diff --git a/storage/src/sequencer.rs b/storage/src/sequencer/mod.rs similarity index 93% rename from storage/src/sequencer.rs rename to storage/src/sequencer/mod.rs index c3424fb7..fcd81702 100644 --- a/storage/src/sequencer.rs +++ b/storage/src/sequencer/mod.rs @@ -7,21 +7,30 @@ use rocksdb::{ }; use crate::{ - CF_BLOCK_NAME, CF_META_NAME, CF_NSSA_STATE_NAME, DB_META_FIRST_BLOCK_IN_DB_KEY, + CF_BLOCK_NAME, CF_META_NAME, DB_META_FIRST_BLOCK_IN_DB_KEY, DbResult, error::DbError, + sequencer::sequencer_cells::{ + LastFinalizedBlockIdCell, LatestBlockMetaCellOwned, LatestBlockMetaCellRef, + NSSAStateCellOwned, NSSAStateCellRef, + }, storable_cell::{ SimpleReadableCell, SimpleWritableCell, - cells::{ - meta_sequencer::{ - LastFinalizedBlockIdCell, LatestBlockMetaCellOwned, LatestBlockMetaCellRef, - NSSAStateCellOwned, NSSAStateCellRef, - }, - meta_shared::{BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell}, - }, + cells::shared_cells::{BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell}, }, }; -pub type DbResult = Result; +pub mod sequencer_cells; + +/// Key base for storing metainformation about the last finalized block on Bedrock. +pub const DB_META_LAST_FINALIZED_BLOCK_ID: &str = "last_finalized_block_id"; +/// Key base for storing metainformation about the latest block meta. +pub const DB_META_LATEST_BLOCK_META_KEY: &str = "latest_block_meta"; + +/// Key base for storing the NSSA state. +pub const DB_NSSA_STATE_KEY: &str = "nssa_state"; + +/// Name of state column family. +pub const CF_NSSA_STATE_NAME: &str = "cf_nssa_state"; pub struct RocksDBIO { pub db: DBWithThreadMode, diff --git a/storage/src/sequencer/sequencer_cells.rs b/storage/src/sequencer/sequencer_cells.rs new file mode 100644 index 00000000..7fa0b48a --- /dev/null +++ b/storage/src/sequencer/sequencer_cells.rs @@ -0,0 +1,96 @@ +use borsh::{BorshDeserialize, BorshSerialize}; +use common::block::BlockMeta; +use nssa::V03State; + +use crate::{ + CF_META_NAME, DbResult, + error::DbError, + sequencer::{ + CF_NSSA_STATE_NAME, DB_META_LAST_FINALIZED_BLOCK_ID, DB_META_LATEST_BLOCK_META_KEY, + DB_NSSA_STATE_KEY, + }, + storable_cell::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, +}; + +#[derive(BorshDeserialize)] +pub struct NSSAStateCellOwned(pub V03State); + +impl SimpleStorableCell for NSSAStateCellOwned { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_NSSA_STATE_KEY; + const CF_NAME: &'static str = CF_NSSA_STATE_NAME; +} + +impl SimpleReadableCell for NSSAStateCellOwned {} + +#[derive(BorshSerialize)] +pub struct NSSAStateCellRef<'state>(pub &'state V03State); + +impl SimpleStorableCell for NSSAStateCellRef<'_> { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_NSSA_STATE_KEY; + const CF_NAME: &'static str = CF_NSSA_STATE_NAME; +} + +impl SimpleWritableCell for NSSAStateCellRef<'_> { + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize last state".to_owned())) + }) + } +} + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct LastFinalizedBlockIdCell(pub Option); + +impl SimpleStorableCell for LastFinalizedBlockIdCell { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_LAST_FINALIZED_BLOCK_ID; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleReadableCell for LastFinalizedBlockIdCell {} + +impl SimpleWritableCell for LastFinalizedBlockIdCell { + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message( + err, + Some("Failed to serialize last finalized block id".to_owned()), + ) + }) + } +} + +#[derive(BorshDeserialize)] +pub struct LatestBlockMetaCellOwned(pub BlockMeta); + +impl SimpleStorableCell for LatestBlockMetaCellOwned { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_LATEST_BLOCK_META_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleReadableCell for LatestBlockMetaCellOwned {} + +#[derive(BorshSerialize)] +pub struct LatestBlockMetaCellRef<'blockmeta>(pub &'blockmeta BlockMeta); + +impl SimpleStorableCell for LatestBlockMetaCellRef<'_> { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_LATEST_BLOCK_META_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleWritableCell for LatestBlockMetaCellRef<'_> { + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize last block meta".to_owned())) + }) + } +} diff --git a/storage/src/storable_cell/cells/meta_sequencer.rs b/storage/src/storable_cell/cells/meta_sequencer.rs deleted file mode 100644 index 9c564fd5..00000000 --- a/storage/src/storable_cell/cells/meta_sequencer.rs +++ /dev/null @@ -1,182 +0,0 @@ -use borsh::{BorshDeserialize, BorshSerialize}; -use common::block::BlockMeta; -use nssa::V03State; - -use crate::{ - CF_META_NAME, CF_NSSA_STATE_NAME, DB_META_LAST_FINALIZED_BLOCK_ID, - DB_META_LATEST_BLOCK_META_KEY, DB_NSSA_STATE_KEY, DbResult, - error::DbError, - storable_cell::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, -}; - -pub struct NSSAStateCellOwned(pub V03State); - -impl BorshDeserialize for NSSAStateCellOwned { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - V03State::deserialize_reader(reader).map(NSSAStateCellOwned) - } -} - -impl SimpleStorableCell for NSSAStateCellOwned { - type KeyParams = (); - - const CELL_NAME: &'static str = DB_NSSA_STATE_KEY; - const CF_NAME: &'static str = CF_NSSA_STATE_NAME; - - fn key_constructor(_params: Self::KeyParams) -> DbResult> { - borsh::to_vec(&Self::CELL_NAME).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } - - fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self.0).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize last state".to_owned())) - }) - } -} - -impl SimpleReadableCell for NSSAStateCellOwned {} - -pub struct NSSAStateCellRef<'state>(pub &'state V03State); - -impl BorshSerialize for NSSAStateCellRef<'_> { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - V03State::serialize(self.0, writer) - } -} - -impl SimpleStorableCell for NSSAStateCellRef<'_> { - type KeyParams = (); - - const CELL_NAME: &'static str = DB_NSSA_STATE_KEY; - const CF_NAME: &'static str = CF_NSSA_STATE_NAME; - - fn key_constructor(_params: Self::KeyParams) -> DbResult> { - borsh::to_vec(&Self::CELL_NAME).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } - - fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize last state".to_owned())) - }) - } -} - -impl SimpleWritableCell for NSSAStateCellRef<'_> {} - -#[derive(Debug)] -pub struct LastFinalizedBlockIdCell(pub Option); - -impl BorshSerialize for LastFinalizedBlockIdCell { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - Option::::serialize(&self.0, writer) - } -} - -impl BorshDeserialize for LastFinalizedBlockIdCell { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - Option::::deserialize_reader(reader).map(LastFinalizedBlockIdCell) - } -} - -impl SimpleStorableCell for LastFinalizedBlockIdCell { - type KeyParams = (); - - const CELL_NAME: &'static str = DB_META_LAST_FINALIZED_BLOCK_ID; - const CF_NAME: &'static str = CF_META_NAME; - - fn key_constructor(_params: Self::KeyParams) -> DbResult> { - borsh::to_vec(&Self::CELL_NAME).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } - - fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize last finalized block id".to_owned()), - ) - }) - } -} - -impl SimpleReadableCell for LastFinalizedBlockIdCell {} - -impl SimpleWritableCell for LastFinalizedBlockIdCell {} - -pub struct LatestBlockMetaCellOwned(pub BlockMeta); - -impl BorshDeserialize for LatestBlockMetaCellOwned { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - BlockMeta::deserialize_reader(reader).map(LatestBlockMetaCellOwned) - } -} - -impl SimpleStorableCell for LatestBlockMetaCellOwned { - type KeyParams = (); - - const CELL_NAME: &'static str = DB_META_LATEST_BLOCK_META_KEY; - const CF_NAME: &'static str = CF_META_NAME; - - fn key_constructor(_params: Self::KeyParams) -> DbResult> { - borsh::to_vec(&Self::CELL_NAME).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } - - fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self.0).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize last block meta".to_owned())) - }) - } -} - -impl SimpleReadableCell for LatestBlockMetaCellOwned {} - -pub struct LatestBlockMetaCellRef<'blockmeta>(pub &'blockmeta BlockMeta); - -impl BorshSerialize for LatestBlockMetaCellRef<'_> { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - BlockMeta::serialize(self.0, writer) - } -} - -impl SimpleStorableCell for LatestBlockMetaCellRef<'_> { - type KeyParams = (); - - const CELL_NAME: &'static str = DB_META_LATEST_BLOCK_META_KEY; - const CF_NAME: &'static str = CF_META_NAME; - - fn key_constructor(_params: Self::KeyParams) -> DbResult> { - borsh::to_vec(&Self::CELL_NAME).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } - - fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize last block meta".to_owned())) - }) - } -} - -impl SimpleWritableCell for LatestBlockMetaCellRef<'_> {} diff --git a/storage/src/storable_cell/cells/meta_shared.rs b/storage/src/storable_cell/cells/meta_shared.rs deleted file mode 100644 index 21ca74fc..00000000 --- a/storage/src/storable_cell/cells/meta_shared.rs +++ /dev/null @@ -1,173 +0,0 @@ -use borsh::{BorshDeserialize, BorshSerialize}; -use common::block::Block; - -use crate::{ - CF_BLOCK_NAME, CF_META_NAME, DB_META_FIRST_BLOCK_IN_DB_KEY, DB_META_FIRST_BLOCK_SET_KEY, - DB_META_LAST_BLOCK_IN_DB_KEY, DbResult, - error::DbError, - storable_cell::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, -}; - -#[derive(Debug)] -pub struct LastBlockCell(pub u64); - -impl BorshSerialize for LastBlockCell { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - u64::serialize(&self.0, writer) - } -} - -impl BorshDeserialize for LastBlockCell { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - u64::deserialize_reader(reader).map(LastBlockCell) - } -} - -impl SimpleStorableCell for LastBlockCell { - type KeyParams = (); - - const CELL_NAME: &'static str = DB_META_LAST_BLOCK_IN_DB_KEY; - const CF_NAME: &'static str = CF_META_NAME; - - fn key_constructor(_params: Self::KeyParams) -> DbResult> { - borsh::to_vec(&Self::CELL_NAME).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } - - fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize last block id".to_owned())) - }) - } -} - -impl SimpleReadableCell for LastBlockCell {} - -impl SimpleWritableCell for LastBlockCell {} - -#[derive(Debug)] -pub struct FirstBlockSetCell(pub bool); - -impl BorshSerialize for FirstBlockSetCell { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - bool::serialize(&self.0, writer) - } -} - -impl BorshDeserialize for FirstBlockSetCell { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - bool::deserialize_reader(reader).map(FirstBlockSetCell) - } -} - -impl SimpleStorableCell for FirstBlockSetCell { - type KeyParams = (); - - const CELL_NAME: &'static str = DB_META_FIRST_BLOCK_SET_KEY; - const CF_NAME: &'static str = CF_META_NAME; - - fn key_constructor(_params: Self::KeyParams) -> DbResult> { - borsh::to_vec(&Self::CELL_NAME).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } - - fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self).map_err(|err| { - DbError::borsh_cast_message( - err, - Some("Failed to serialize first block set flag".to_owned()), - ) - }) - } -} - -impl SimpleReadableCell for FirstBlockSetCell {} - -impl SimpleWritableCell for FirstBlockSetCell {} - -#[derive(Debug)] -pub struct FirstBlockCell(pub u64); - -impl BorshSerialize for FirstBlockCell { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - u64::serialize(&self.0, writer) - } -} - -impl BorshDeserialize for FirstBlockCell { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - u64::deserialize_reader(reader).map(FirstBlockCell) - } -} - -impl SimpleStorableCell for FirstBlockCell { - type KeyParams = (); - - const CELL_NAME: &'static str = DB_META_FIRST_BLOCK_IN_DB_KEY; - const CF_NAME: &'static str = CF_META_NAME; - - fn key_constructor(_params: Self::KeyParams) -> DbResult> { - borsh::to_vec(&Self::CELL_NAME).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } - - fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize first block id".to_owned())) - }) - } -} - -impl SimpleReadableCell for FirstBlockCell {} - -#[derive(Debug)] -pub struct BlockCell(pub Block); - -impl BorshSerialize for BlockCell { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - Block::serialize(&self.0, writer) - } -} - -impl BorshDeserialize for BlockCell { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - Block::deserialize_reader(reader).map(BlockCell) - } -} - -impl SimpleStorableCell for BlockCell { - type KeyParams = u64; - - const CELL_NAME: &'static str = "block"; - const CF_NAME: &'static str = CF_BLOCK_NAME; - - fn key_constructor(params: Self::KeyParams) -> DbResult> { - // ToDo: Replace with increasing ordering serialization - borsh::to_vec(¶ms).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), - ) - }) - } - - fn value_constructor(&self) -> DbResult> { - borsh::to_vec(&self).map_err(|err| { - DbError::borsh_cast_message(err, Some("Failed to serialize block".to_owned())) - }) - } -} - -impl SimpleReadableCell for BlockCell {} diff --git a/storage/src/storable_cell/cells/mod.rs b/storage/src/storable_cell/cells/mod.rs index 914befa1..a464144b 100644 --- a/storage/src/storable_cell/cells/mod.rs +++ b/storage/src/storable_cell/cells/mod.rs @@ -1,3 +1 @@ -pub mod meta_indexer; -pub mod meta_sequencer; -pub mod meta_shared; +pub mod shared_cells; diff --git a/storage/src/storable_cell/cells/shared_cells.rs b/storage/src/storable_cell/cells/shared_cells.rs new file mode 100644 index 00000000..6dc434c2 --- /dev/null +++ b/storage/src/storable_cell/cells/shared_cells.rs @@ -0,0 +1,89 @@ +use borsh::{BorshDeserialize, BorshSerialize}; +use common::block::Block; + +use crate::{ + BLOCK_CELL_NAME, CF_BLOCK_NAME, CF_META_NAME, DB_META_FIRST_BLOCK_IN_DB_KEY, + DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BLOCK_IN_DB_KEY, DbResult, + error::DbError, + storable_cell::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, +}; + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct LastBlockCell(pub u64); + +impl SimpleStorableCell for LastBlockCell { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_LAST_BLOCK_IN_DB_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleReadableCell for LastBlockCell {} + +impl SimpleWritableCell for LastBlockCell { + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message(err, Some("Failed to serialize last block id".to_owned())) + }) + } +} + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct FirstBlockSetCell(pub bool); + +impl SimpleStorableCell for FirstBlockSetCell { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_FIRST_BLOCK_SET_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleReadableCell for FirstBlockSetCell {} + +impl SimpleWritableCell for FirstBlockSetCell { + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message( + err, + Some("Failed to serialize first block set flag".to_owned()), + ) + }) + } +} + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct FirstBlockCell(pub u64); + +impl SimpleStorableCell for FirstBlockCell { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_FIRST_BLOCK_IN_DB_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleReadableCell for FirstBlockCell {} + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct BlockCell(pub Block); + +impl SimpleStorableCell for BlockCell { + type KeyParams = u64; + + const CELL_NAME: &'static str = BLOCK_CELL_NAME; + const CF_NAME: &'static str = CF_BLOCK_NAME; + + fn key_constructor(params: Self::KeyParams) -> DbResult> { + // ToDo: Replace with increasing ordering serialization + borsh::to_vec(¶ms).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!( + "Failed to serialize {:?} key params", + Self::CELL_NAME + )), + ) + }) + } +} + +impl SimpleReadableCell for BlockCell {} diff --git a/storage/src/storable_cell/mod.rs b/storage/src/storable_cell/mod.rs index 8aa8b779..8322b6ae 100644 --- a/storage/src/storable_cell/mod.rs +++ b/storage/src/storable_cell/mod.rs @@ -12,8 +12,14 @@ pub trait SimpleStorableCell { const CELL_NAME: &'static str; type KeyParams; - fn key_constructor(params: Self::KeyParams) -> DbResult>; - fn value_constructor(&self) -> DbResult>; + fn key_constructor(_params: Self::KeyParams) -> DbResult> { + borsh::to_vec(&Self::CELL_NAME).map_err(|err| { + DbError::borsh_cast_message( + err, + Some(format!("Failed to serialize {:?}", Self::CELL_NAME)), + ) + }) + } fn column_ref(db: &DBWithThreadMode) -> Arc> { db.cf_handle(Self::CF_NAME) @@ -23,29 +29,17 @@ pub trait SimpleStorableCell { pub trait SimpleReadableCell: SimpleStorableCell + BorshDeserialize { fn get(db: &DBWithThreadMode, params: Self::KeyParams) -> DbResult { - let cf_ref = Self::column_ref(db); - let res = db - .get_cf(&cf_ref, Self::key_constructor(params)?) - .map_err(|rerr| { - DbError::rocksdb_cast_message( - rerr, - Some(format!("Failed to read {:?}", Self::CELL_NAME)), - ) - })?; + let res = Self::get_opt(db, params)?; - if let Some(data) = res { - Ok(borsh::from_slice::(&data).map_err(|err| { - DbError::borsh_cast_message( - err, - Some(format!("Failed to deserialize {:?}", Self::CELL_NAME)), - ) - })?) - } else { - Err(DbError::db_interaction_error(format!( - "{:?} not found", - Self::CELL_NAME - ))) - } + res.map_or_else( + || { + Err(DbError::db_interaction_error(format!( + "{:?} not found", + Self::CELL_NAME + ))) + }, + |data| Ok(data), + ) } fn get_opt( @@ -75,6 +69,8 @@ pub trait SimpleReadableCell: SimpleStorableCell + BorshDeserialize { } pub trait SimpleWritableCell: SimpleStorableCell + BorshSerialize { + fn value_constructor(&self) -> DbResult>; + fn put(&self, db: &DBWithThreadMode, params: Self::KeyParams) -> DbResult<()> { let cf_ref = Self::column_ref(db); db.put_cf( From 40f8750278f353c580a80b160261905ee66a49a9 Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Wed, 1 Apr 2026 08:53:45 +0300 Subject: [PATCH 5/6] fix: suggestions 2 --- storage/src/indexer/indexer_cells.rs | 18 ++++++++++++ storage/src/indexer/mod.rs | 37 +++++------------------- storage/src/indexer/read_once.rs | 1 + storage/src/indexer/write_atomic.rs | 2 +- storage/src/indexer/write_non_atomic.rs | 1 + storage/src/lib.rs | 33 ++++++++++++++++++++- storage/src/sequencer/mod.rs | 36 ++++++----------------- storage/src/sequencer/sequencer_cells.rs | 36 +++++++++++++++++++++++ storage/src/storable_cell/mod.rs | 10 +------ 9 files changed, 107 insertions(+), 67 deletions(-) diff --git a/storage/src/indexer/indexer_cells.rs b/storage/src/indexer/indexer_cells.rs index 144f56b9..57766252 100644 --- a/storage/src/indexer/indexer_cells.rs +++ b/storage/src/indexer/indexer_cells.rs @@ -210,3 +210,21 @@ impl SimpleWritableCell for AccNumTxCell { }) } } + +#[cfg(test)] +mod uniform_tests { + use crate::{ + indexer::indexer_cells::{BreakpointCellOwned, BreakpointCellRef}, + storable_cell::SimpleStorableCell as _, + }; + + #[test] + fn breakpoint_ref_and_owned_is_aligned() { + assert_eq!(BreakpointCellRef::CELL_NAME, BreakpointCellOwned::CELL_NAME); + assert_eq!(BreakpointCellRef::CF_NAME, BreakpointCellOwned::CF_NAME); + assert_eq!( + BreakpointCellRef::key_constructor(1000).unwrap(), + BreakpointCellOwned::key_constructor(1000).unwrap() + ); + } +} diff --git a/storage/src/indexer/mod.rs b/storage/src/indexer/mod.rs index 7d4bce09..d3e91c89 100644 --- a/storage/src/indexer/mod.rs +++ b/storage/src/indexer/mod.rs @@ -3,14 +3,10 @@ use std::{path::Path, sync::Arc}; use common::block::Block; use nssa::V03State; use rocksdb::{ - BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options, WriteBatch, + BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options, }; -use crate::{ - BREAKPOINT_INTERVAL, CF_BLOCK_NAME, CF_META_NAME, DbResult, - error::DbError, - storable_cell::{SimpleReadableCell, SimpleWritableCell}, -}; +use crate::{BREAKPOINT_INTERVAL, CF_BLOCK_NAME, CF_META_NAME, DBIO, DbResult, error::DbError}; pub mod indexer_cells; pub mod read_multiple; @@ -48,6 +44,12 @@ pub struct RocksDBIO { pub db: DBWithThreadMode, } +impl DBIO for RocksDBIO { + fn db(&self) -> &DBWithThreadMode { + &self.db + } +} + impl RocksDBIO { pub fn open_or_create( path: &Path, @@ -145,29 +147,6 @@ impl RocksDBIO { .expect("Account meta column should exist") } - // Generics - - fn get(&self, params: T::KeyParams) -> DbResult { - T::get(&self.db, params) - } - - fn get_opt(&self, params: T::KeyParams) -> DbResult> { - T::get_opt(&self.db, params) - } - - fn put(&self, cell: &T, params: T::KeyParams) -> DbResult<()> { - cell.put(&self.db, params) - } - - fn put_batch( - &self, - cell: &T, - params: T::KeyParams, - write_batch: &mut WriteBatch, - ) -> DbResult<()> { - cell.put_batch(&self.db, params, write_batch) - } - // State pub fn calculate_state_for_id(&self, block_id: u64) -> DbResult { diff --git a/storage/src/indexer/read_once.rs b/storage/src/indexer/read_once.rs index a652b8e9..bf084c84 100644 --- a/storage/src/indexer/read_once.rs +++ b/storage/src/indexer/read_once.rs @@ -1,5 +1,6 @@ use super::{Block, DbResult, RocksDBIO, V03State}; use crate::{ + DBIO as _, indexer::indexer_cells::{ AccNumTxCell, BlockHashToBlockIdMapCell, BreakpointCellOwned, LastBreakpointIdCell, LastObservedL1LibHeaderCell, TxHashToBlockIdMapCell, diff --git a/storage/src/indexer/write_atomic.rs b/storage/src/indexer/write_atomic.rs index e1145131..b8ea4751 100644 --- a/storage/src/indexer/write_atomic.rs +++ b/storage/src/indexer/write_atomic.rs @@ -4,7 +4,7 @@ use rocksdb::WriteBatch; use super::{BREAKPOINT_INTERVAL, Block, DbError, DbResult, RocksDBIO}; use crate::{ - DB_META_FIRST_BLOCK_IN_DB_KEY, + DB_META_FIRST_BLOCK_IN_DB_KEY, DBIO as _, indexer::indexer_cells::{ AccNumTxCell, BlockHashToBlockIdMapCell, LastBreakpointIdCell, LastObservedL1LibHeaderCell, TxHashToBlockIdMapCell, diff --git a/storage/src/indexer/write_non_atomic.rs b/storage/src/indexer/write_non_atomic.rs index d5a862f4..a250dcc7 100644 --- a/storage/src/indexer/write_non_atomic.rs +++ b/storage/src/indexer/write_non_atomic.rs @@ -1,5 +1,6 @@ use super::{BREAKPOINT_INTERVAL, DbError, DbResult, RocksDBIO, V03State}; use crate::{ + DBIO as _, indexer::indexer_cells::{ BreakpointCellRef, LastBreakpointIdCell, LastObservedL1LibHeaderCell, }, diff --git a/storage/src/lib.rs b/storage/src/lib.rs index 5d9f8705..182b8991 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -1,4 +1,9 @@ -use crate::error::DbError; +use rocksdb::{DBWithThreadMode, MultiThreaded, WriteBatch}; + +use crate::{ + error::DbError, + storable_cell::{SimpleReadableCell, SimpleWritableCell}, +}; pub mod error; pub mod indexer; @@ -36,3 +41,29 @@ pub const CF_BLOCK_NAME: &str = "cf_block"; pub const CF_META_NAME: &str = "cf_meta"; pub type DbResult = Result; + +/// Minimal requirements for DB IO. +pub trait DBIO { + fn db(&self) -> &DBWithThreadMode; + + fn get(&self, params: T::KeyParams) -> DbResult { + T::get(self.db(), params) + } + + fn get_opt(&self, params: T::KeyParams) -> DbResult> { + T::get_opt(self.db(), params) + } + + fn put(&self, cell: &T, params: T::KeyParams) -> DbResult<()> { + cell.put(self.db(), params) + } + + fn put_batch( + &self, + cell: &T, + params: T::KeyParams, + write_batch: &mut WriteBatch, + ) -> DbResult<()> { + cell.put_batch(self.db(), params, write_batch) + } +} diff --git a/storage/src/sequencer/mod.rs b/storage/src/sequencer/mod.rs index fcd81702..140008b5 100644 --- a/storage/src/sequencer/mod.rs +++ b/storage/src/sequencer/mod.rs @@ -7,15 +7,14 @@ use rocksdb::{ }; use crate::{ - CF_BLOCK_NAME, CF_META_NAME, DB_META_FIRST_BLOCK_IN_DB_KEY, DbResult, + CF_BLOCK_NAME, CF_META_NAME, DB_META_FIRST_BLOCK_IN_DB_KEY, DBIO, DbResult, error::DbError, sequencer::sequencer_cells::{ LastFinalizedBlockIdCell, LatestBlockMetaCellOwned, LatestBlockMetaCellRef, NSSAStateCellOwned, NSSAStateCellRef, }, - storable_cell::{ - SimpleReadableCell, SimpleWritableCell, - cells::shared_cells::{BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell}, + storable_cell::cells::shared_cells::{ + BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell, }, }; @@ -36,6 +35,12 @@ pub struct RocksDBIO { pub db: DBWithThreadMode, } +impl DBIO for RocksDBIO { + fn db(&self) -> &DBWithThreadMode { + &self.db + } +} + impl RocksDBIO { pub fn open_or_create( path: &Path, @@ -116,29 +121,6 @@ impl RocksDBIO { .expect("State should exist") } - // Generics - - fn get(&self, params: T::KeyParams) -> DbResult { - T::get(&self.db, params) - } - - fn get_opt(&self, params: T::KeyParams) -> DbResult> { - T::get_opt(&self.db, params) - } - - fn put(&self, cell: &T, params: T::KeyParams) -> DbResult<()> { - cell.put(&self.db, params) - } - - fn put_batch( - &self, - cell: &T, - params: T::KeyParams, - write_batch: &mut WriteBatch, - ) -> DbResult<()> { - cell.put_batch(&self.db, params, write_batch) - } - // Meta pub fn get_meta_first_block_in_db(&self) -> DbResult { diff --git a/storage/src/sequencer/sequencer_cells.rs b/storage/src/sequencer/sequencer_cells.rs index 7fa0b48a..386cd953 100644 --- a/storage/src/sequencer/sequencer_cells.rs +++ b/storage/src/sequencer/sequencer_cells.rs @@ -94,3 +94,39 @@ impl SimpleWritableCell for LatestBlockMetaCellRef<'_> { }) } } + +#[cfg(test)] +mod uniform_tests { + use crate::{ + sequencer::sequencer_cells::{ + LatestBlockMetaCellOwned, LatestBlockMetaCellRef, NSSAStateCellOwned, NSSAStateCellRef, + }, + storable_cell::SimpleStorableCell as _, + }; + + #[test] + fn state_ref_and_owned_is_aligned() { + assert_eq!(NSSAStateCellRef::CELL_NAME, NSSAStateCellOwned::CELL_NAME); + assert_eq!(NSSAStateCellRef::CF_NAME, NSSAStateCellOwned::CF_NAME); + assert_eq!( + NSSAStateCellRef::key_constructor(()).unwrap(), + NSSAStateCellOwned::key_constructor(()).unwrap() + ); + } + + #[test] + fn block_meta_ref_and_owned_is_aligned() { + assert_eq!( + LatestBlockMetaCellRef::CELL_NAME, + LatestBlockMetaCellOwned::CELL_NAME + ); + assert_eq!( + LatestBlockMetaCellRef::CF_NAME, + LatestBlockMetaCellOwned::CF_NAME + ); + assert_eq!( + LatestBlockMetaCellRef::key_constructor(()).unwrap(), + LatestBlockMetaCellOwned::key_constructor(()).unwrap() + ); + } +} diff --git a/storage/src/storable_cell/mod.rs b/storage/src/storable_cell/mod.rs index 8322b6ae..5a00e3a6 100644 --- a/storage/src/storable_cell/mod.rs +++ b/storage/src/storable_cell/mod.rs @@ -31,15 +31,7 @@ pub trait SimpleReadableCell: SimpleStorableCell + BorshDeserialize { fn get(db: &DBWithThreadMode, params: Self::KeyParams) -> DbResult { let res = Self::get_opt(db, params)?; - res.map_or_else( - || { - Err(DbError::db_interaction_error(format!( - "{:?} not found", - Self::CELL_NAME - ))) - }, - |data| Ok(data), - ) + res.ok_or_else(|| DbError::db_interaction_error(format!("{:?} not found", Self::CELL_NAME))) } fn get_opt( From a2904c130c1a7e93369afb4fdcba90c862b89081 Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Thu, 2 Apr 2026 17:45:49 +0300 Subject: [PATCH 6/6] fix: suggestion fix 3 --- storage/src/{storable_cell => cells}/mod.rs | 2 +- storage/src/{storable_cell => }/cells/shared_cells.rs | 2 +- storage/src/indexer/indexer_cells.rs | 4 ++-- storage/src/indexer/read_once.rs | 4 +--- storage/src/indexer/write_atomic.rs | 2 +- storage/src/indexer/write_non_atomic.rs | 2 +- storage/src/lib.rs | 4 ++-- storage/src/sequencer/mod.rs | 4 +--- storage/src/sequencer/sequencer_cells.rs | 4 ++-- storage/src/storable_cell/cells/mod.rs | 1 - 10 files changed, 12 insertions(+), 17 deletions(-) rename storage/src/{storable_cell => cells}/mod.rs (99%) rename storage/src/{storable_cell => }/cells/shared_cells.rs (96%) delete mode 100644 storage/src/storable_cell/cells/mod.rs diff --git a/storage/src/storable_cell/mod.rs b/storage/src/cells/mod.rs similarity index 99% rename from storage/src/storable_cell/mod.rs rename to storage/src/cells/mod.rs index 5a00e3a6..76c1ff8c 100644 --- a/storage/src/storable_cell/mod.rs +++ b/storage/src/cells/mod.rs @@ -5,7 +5,7 @@ use rocksdb::{BoundColumnFamily, DBWithThreadMode, MultiThreaded, WriteBatch}; use crate::{DbResult, error::DbError}; -pub mod cells; +pub mod shared_cells; pub trait SimpleStorableCell { const CF_NAME: &'static str; diff --git a/storage/src/storable_cell/cells/shared_cells.rs b/storage/src/cells/shared_cells.rs similarity index 96% rename from storage/src/storable_cell/cells/shared_cells.rs rename to storage/src/cells/shared_cells.rs index 6dc434c2..2a76edf3 100644 --- a/storage/src/storable_cell/cells/shared_cells.rs +++ b/storage/src/cells/shared_cells.rs @@ -4,8 +4,8 @@ use common::block::Block; use crate::{ BLOCK_CELL_NAME, CF_BLOCK_NAME, CF_META_NAME, DB_META_FIRST_BLOCK_IN_DB_KEY, DB_META_FIRST_BLOCK_SET_KEY, DB_META_LAST_BLOCK_IN_DB_KEY, DbResult, + cells::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, error::DbError, - storable_cell::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, }; #[derive(Debug, BorshSerialize, BorshDeserialize)] diff --git a/storage/src/indexer/indexer_cells.rs b/storage/src/indexer/indexer_cells.rs index 57766252..76a2c035 100644 --- a/storage/src/indexer/indexer_cells.rs +++ b/storage/src/indexer/indexer_cells.rs @@ -3,13 +3,13 @@ use nssa::V03State; use crate::{ CF_META_NAME, DbResult, + cells::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, error::DbError, indexer::{ ACC_NUM_CELL_NAME, BLOCK_HASH_CELL_NAME, BREAKPOINT_CELL_NAME, CF_ACC_META, CF_BREAKPOINT_NAME, CF_HASH_TO_ID, CF_TX_TO_ID, DB_META_LAST_BREAKPOINT_ID, DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, TX_HASH_CELL_NAME, }, - storable_cell::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, }; #[derive(Debug, BorshSerialize, BorshDeserialize)] @@ -214,8 +214,8 @@ impl SimpleWritableCell for AccNumTxCell { #[cfg(test)] mod uniform_tests { use crate::{ + cells::SimpleStorableCell as _, indexer::indexer_cells::{BreakpointCellOwned, BreakpointCellRef}, - storable_cell::SimpleStorableCell as _, }; #[test] diff --git a/storage/src/indexer/read_once.rs b/storage/src/indexer/read_once.rs index bf084c84..b1ae0ada 100644 --- a/storage/src/indexer/read_once.rs +++ b/storage/src/indexer/read_once.rs @@ -1,13 +1,11 @@ use super::{Block, DbResult, RocksDBIO, V03State}; use crate::{ DBIO as _, + cells::shared_cells::{BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell}, indexer::indexer_cells::{ AccNumTxCell, BlockHashToBlockIdMapCell, BreakpointCellOwned, LastBreakpointIdCell, LastObservedL1LibHeaderCell, TxHashToBlockIdMapCell, }, - storable_cell::cells::shared_cells::{ - BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell, - }, }; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] diff --git a/storage/src/indexer/write_atomic.rs b/storage/src/indexer/write_atomic.rs index b8ea4751..9b661f3b 100644 --- a/storage/src/indexer/write_atomic.rs +++ b/storage/src/indexer/write_atomic.rs @@ -5,11 +5,11 @@ use rocksdb::WriteBatch; use super::{BREAKPOINT_INTERVAL, Block, DbError, DbResult, RocksDBIO}; use crate::{ DB_META_FIRST_BLOCK_IN_DB_KEY, DBIO as _, + cells::shared_cells::{FirstBlockSetCell, LastBlockCell}, indexer::indexer_cells::{ AccNumTxCell, BlockHashToBlockIdMapCell, LastBreakpointIdCell, LastObservedL1LibHeaderCell, TxHashToBlockIdMapCell, }, - storable_cell::cells::shared_cells::{FirstBlockSetCell, LastBlockCell}, }; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] diff --git a/storage/src/indexer/write_non_atomic.rs b/storage/src/indexer/write_non_atomic.rs index a250dcc7..62b466a2 100644 --- a/storage/src/indexer/write_non_atomic.rs +++ b/storage/src/indexer/write_non_atomic.rs @@ -1,10 +1,10 @@ use super::{BREAKPOINT_INTERVAL, DbError, DbResult, RocksDBIO, V03State}; use crate::{ DBIO as _, + cells::shared_cells::{FirstBlockSetCell, LastBlockCell}, indexer::indexer_cells::{ BreakpointCellRef, LastBreakpointIdCell, LastObservedL1LibHeaderCell, }, - storable_cell::cells::shared_cells::{FirstBlockSetCell, LastBlockCell}, }; #[expect(clippy::multiple_inherent_impl, reason = "Readability")] diff --git a/storage/src/lib.rs b/storage/src/lib.rs index 182b8991..2edb0ee3 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -1,14 +1,14 @@ use rocksdb::{DBWithThreadMode, MultiThreaded, WriteBatch}; use crate::{ + cells::{SimpleReadableCell, SimpleWritableCell}, error::DbError, - storable_cell::{SimpleReadableCell, SimpleWritableCell}, }; +pub mod cells; pub mod error; pub mod indexer; pub mod sequencer; -pub mod storable_cell; /// Maximal size of stored blocks in base. /// diff --git a/storage/src/sequencer/mod.rs b/storage/src/sequencer/mod.rs index 140008b5..508f6c29 100644 --- a/storage/src/sequencer/mod.rs +++ b/storage/src/sequencer/mod.rs @@ -8,14 +8,12 @@ use rocksdb::{ use crate::{ CF_BLOCK_NAME, CF_META_NAME, DB_META_FIRST_BLOCK_IN_DB_KEY, DBIO, DbResult, + cells::shared_cells::{BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell}, error::DbError, sequencer::sequencer_cells::{ LastFinalizedBlockIdCell, LatestBlockMetaCellOwned, LatestBlockMetaCellRef, NSSAStateCellOwned, NSSAStateCellRef, }, - storable_cell::cells::shared_cells::{ - BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell, - }, }; pub mod sequencer_cells; diff --git a/storage/src/sequencer/sequencer_cells.rs b/storage/src/sequencer/sequencer_cells.rs index 386cd953..0ad092d7 100644 --- a/storage/src/sequencer/sequencer_cells.rs +++ b/storage/src/sequencer/sequencer_cells.rs @@ -4,12 +4,12 @@ use nssa::V03State; use crate::{ CF_META_NAME, DbResult, + cells::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, error::DbError, sequencer::{ CF_NSSA_STATE_NAME, DB_META_LAST_FINALIZED_BLOCK_ID, DB_META_LATEST_BLOCK_META_KEY, DB_NSSA_STATE_KEY, }, - storable_cell::{SimpleReadableCell, SimpleStorableCell, SimpleWritableCell}, }; #[derive(BorshDeserialize)] @@ -98,10 +98,10 @@ impl SimpleWritableCell for LatestBlockMetaCellRef<'_> { #[cfg(test)] mod uniform_tests { use crate::{ + cells::SimpleStorableCell as _, sequencer::sequencer_cells::{ LatestBlockMetaCellOwned, LatestBlockMetaCellRef, NSSAStateCellOwned, NSSAStateCellRef, }, - storable_cell::SimpleStorableCell as _, }; #[test] diff --git a/storage/src/storable_cell/cells/mod.rs b/storage/src/storable_cell/cells/mod.rs deleted file mode 100644 index a464144b..00000000 --- a/storage/src/storable_cell/cells/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod shared_cells;