Skip to content

Commit

Permalink
feat(client): l1<>l2 messaging crate (madara-alliance#220)
Browse files Browse the repository at this point in the history
Co-authored-by: 0xevolve <Artevolve@yahoo.com>
  • Loading branch information
azurwastaken and EvolveArt authored Aug 20, 2024
1 parent aa1b888 commit 954f64a
Show file tree
Hide file tree
Showing 11 changed files with 828 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Next release

- feat: Added l1->l2 messaging
- test: add unitests primitives
- tests: add tests for the rpcs endpoints
- fix: pending contract storage not stored properly
Expand Down
100 changes: 96 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

127 changes: 127 additions & 0 deletions crates/client/db/src/l1_db.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use rocksdb::WriteOptions;
use serde::{Deserialize, Serialize};
use starknet_api::core::Nonce;

use crate::error::DbError;
use crate::{Column, DatabaseExt, DeoxysBackend, DeoxysStorageError};

type Result<T, E = DeoxysStorageError> = std::result::Result<T, E>;

pub const LAST_SYNCED_L1_EVENT_BLOCK: &[u8] = b"LAST_SYNCED_L1_EVENT_BLOCK";

/// Struct to store block number and event_index where L1->L2 Message occured
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct LastSyncedEventBlock {
pub block_number: u64,
pub event_index: u64,
}

impl LastSyncedEventBlock {
/// Create a new LastSyncedBlock with block number and event index
pub fn new(block_number: u64, event_index: u64) -> Self {
LastSyncedEventBlock { block_number, event_index }
}
}

/// We add method in DeoxysBackend to be able to handle L1->L2 messaging related data
impl DeoxysBackend {
/// Retrieves the last stored L1 block data that contains a message from the database.
///
/// This function attempts to fetch the data of the last messaging-related block from the database.
/// If a block is found, it is retrieved, deserialized, and returned.
/// Otherwise, a `LastSyncedEventBlock` instance with the `block_number` and `event_index` set to 0 is returned.
///
/// # Returns
///
/// - `Ok(Some(LastSyncedEventBlock))` - If the last synced L1 block with a messaging event is found
/// and successfully deserialized.
/// - `Ok(Some(LastSyncedEventBlock::new(0, 0)))` - If no such block exists in the database.
/// - `Err(e)` - If there is an error accessing the database or deserializing the block.
///
/// # Errors
///
/// This function returns an error if:
/// - There is a failure in interacting with the database.
/// - The block's deserialization fails.
///
/// # Example
///
/// let last_synced_event_block = match backend.messaging_last_synced_l1_block_with_event() {
/// Ok(Some(blk)) => blk,
/// Ok(None) => unreachable!("Should never be None"),
/// Err(e) => {
/// tracing::error!("⟠ Madara Messaging DB unavailable: {:?}", e);
/// return Err(e.into());
/// }
/// };
///
/// # Panics
///
/// This function does not panic.
pub fn messaging_last_synced_l1_block_with_event(&self) -> Result<Option<LastSyncedEventBlock>> {
let messaging_column = self.db.get_column(Column::L1Messaging);
let Some(res) = self.db.get_cf(&messaging_column, LAST_SYNCED_L1_EVENT_BLOCK)? else {
return Ok(Some(LastSyncedEventBlock::new(0, 0)));
};
let res = bincode::deserialize(&res)?;
Ok(Some(res))
}

/// This function inserts a new block into the messaging column.
///
/// This function retrieves the messaging column and inserts a `LastSyncedEventBlock`
/// into it.
///
/// # Arguments
///
/// - `last_synced_event_block`: The `LastSyncedEventBlock` instance representing the most recent
/// synced L1 block with a messaging event.
///
/// # Returns
///
/// - `Ok(())` if the data is correctly inserted into the database.
/// - `Err(e)` if there is an error accessing the database or serializing the data.
///
/// # Errors
///
/// This function returns an error if:
/// - There is a failure in interacting with the database.
/// - The block's serialization fails.
///
/// # Example
///
/// let block_sent = LastSyncedEventBlock::new(l1_block_number.unwrap(), event_index.unwrap());
/// backend.messaging_update_last_synced_l1_block_with_event(block_sent)?;
///
/// # Panics
///
/// This function does not panic.
pub fn messaging_update_last_synced_l1_block_with_event(
&self,
last_synced_event_block: LastSyncedEventBlock,
) -> Result<(), DbError> {
let messaging_column = self.db.get_column(Column::L1Messaging);
let mut writeopts = WriteOptions::default(); // todo move that in db
writeopts.disable_wal(true);
self.db.put_cf_opt(
&messaging_column,
LAST_SYNCED_L1_EVENT_BLOCK,
bincode::serialize(&last_synced_event_block)?,
&writeopts,
)?;
Ok(())
}

pub fn has_l1_messaging_nonce(&self, nonce: Nonce) -> Result<bool> {
let nonce_column = self.db.get_column(Column::L1MessagingNonce);
Ok(self.db.get_pinned_cf(&nonce_column, bincode::serialize(&nonce)?)?.is_some())
}

pub fn set_l1_messaging_nonce(&self, nonce: Nonce) -> Result<(), DbError> {
let nonce_column = self.db.get_column(Column::L1MessagingNonce);
let mut writeopts = WriteOptions::default();
writeopts.disable_wal(true);
self.db.put_cf_opt(&nonce_column, bincode::serialize(&nonce)?, /* empty value */ [], &writeopts)?;
Ok(())
}
}
8 changes: 8 additions & 0 deletions crates/client/db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub mod class_db;
pub mod contract_db;
pub mod db_block_id;
pub mod db_metrics;
pub mod l1_db;
pub mod storage_updates;

pub use error::{DeoxysStorageError, TrieType};
Expand Down Expand Up @@ -164,6 +165,9 @@ pub enum Column {
BonsaiClassesTrie,
BonsaiClassesFlat,
BonsaiClassesLog,

L1Messaging,
L1MessagingNonce,
}

impl fmt::Debug for Column {
Expand Down Expand Up @@ -207,6 +211,8 @@ impl Column {
BonsaiClassesTrie,
BonsaiClassesFlat,
BonsaiClassesLog,
L1Messaging,
L1MessagingNonce,
PendingContractToClassHashes,
PendingContractToNonces,
PendingContractStorage,
Expand Down Expand Up @@ -242,6 +248,8 @@ impl Column {
ContractToNonces => "contract_to_nonces",
ContractClassHashes => "contract_class_hashes",
ContractStorage => "contract_storage",
L1Messaging => "l1_messaging",
L1MessagingNonce => "l1_messaging_nonce",
PendingContractToClassHashes => "pending_contract_to_class_hashes",
PendingContractToNonces => "pending_contract_to_nonces",
PendingContractStorage => "pending_contract_storage",
Expand Down
4 changes: 4 additions & 0 deletions crates/client/eth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ starknet_api = { workspace = true }
alloy = { workspace = true, features = ["node-bindings"] }
anyhow = "1.0.75"
bitvec = { workspace = true }
blockifier = { workspace = true }
bytes = "1.6.0"
futures = { workspace = true, default-features = true }
log = { workspace = true }
serde = { workspace = true, default-features = true }
Expand All @@ -41,6 +43,7 @@ tokio = { workspace = true, features = [
"test-util",
"signal",
] }
tracing = "0.1.40"
url = { workspace = true }

[dev-dependencies]
Expand All @@ -49,3 +52,4 @@ once_cell = { workspace = true }
tempfile = { workspace = true }
dotenv = { workspace = true }
prometheus = { workspace = true }
tracing-test = "0.2.5"
Loading

0 comments on commit 954f64a

Please sign in to comment.