Skip to content

Commit ba234ed

Browse files
authored
Merge branch 'main' into feat/verify-contiguous-attributes
2 parents b8c703a + d6f9818 commit ba234ed

File tree

14 files changed

+90
-60
lines changed

14 files changed

+90
-60
lines changed

crates/chain-orchestrator/src/error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use alloy_json_rpc::RpcError;
22
use alloy_primitives::B256;
33
use alloy_transport::TransportErrorKind;
4-
use scroll_db::{DatabaseError, L1MessageStart};
4+
use scroll_db::{DatabaseError, L1MessageKey};
55

66
/// A type that represents an error that occurred in the chain orchestrator.
77
#[derive(Debug, thiserror::Error)]
@@ -28,7 +28,7 @@ pub enum ChainOrchestratorError {
2828
},
2929
/// An L1 message was not found in the database.
3030
#[error("L1 message not found at {0}")]
31-
L1MessageNotFound(L1MessageStart),
31+
L1MessageNotFound(L1MessageKey),
3232
/// A gap was detected in the L1 message queue: the previous message before index {0} is
3333
/// missing.
3434
#[error("L1 message queue gap detected at index {0}, previous L1 message not found")]

crates/chain-orchestrator/src/lib.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use scroll_alloy_hardforks::ScrollHardforks;
1919
use scroll_alloy_network::Scroll;
2020
use scroll_db::{
2121
Database, DatabaseError, DatabaseReadOperations, DatabaseTransactionProvider,
22-
DatabaseWriteOperations, L1MessageStart, UnwindResult,
22+
DatabaseWriteOperations, L1MessageKey, UnwindResult,
2323
};
2424
use scroll_network::NewBlockWithPeer;
2525
use std::{
@@ -838,7 +838,7 @@ async fn compute_l1_message_queue_hash(
838838
})
839839
.await?
840840
.map(|m| m.queue_hash)
841-
.ok_or(DatabaseError::L1MessageNotFound(L1MessageStart::Index(index)))?
841+
.ok_or(DatabaseError::L1MessageNotFound(L1MessageKey::QueueIndex(index)))?
842842
.unwrap_or_default()
843843
.to_vec();
844844
input.append(&mut l1_message.tx_hash().to_vec());
@@ -1078,7 +1078,9 @@ async fn validate_l1_messages(
10781078
let l1_message_stream = Retry::default()
10791079
.retry("get_l1_messages", || async {
10801080
let messages = tx
1081-
.get_l1_messages(l1_message_hashes.first().map(|tx| L1MessageStart::Hash(*tx)))
1081+
.get_l1_messages(
1082+
l1_message_hashes.first().map(|tx| L1MessageKey::TransactionHash(*tx)),
1083+
)
10821084
.await?;
10831085
Ok::<_, ChainOrchestratorError>(messages)
10841086
})
@@ -1093,7 +1095,9 @@ async fn validate_l1_messages(
10931095
.await
10941096
.map(|m| m.map(|msg| msg.transaction.tx_hash()))
10951097
.transpose()?
1096-
.ok_or(ChainOrchestratorError::L1MessageNotFound(L1MessageStart::Hash(message_hash)))?;
1098+
.ok_or(ChainOrchestratorError::L1MessageNotFound(L1MessageKey::TransactionHash(
1099+
message_hash,
1100+
)))?;
10971101

10981102
// If the received and expected L1 messages do not match return an error.
10991103
if message_hash != expected_hash {

crates/database/db/src/error.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::L1MessageStart;
1+
use super::L1MessageKey;
22
use sea_orm::sqlx::Error as SqlxError;
33

44
/// The error type for database operations.
@@ -17,6 +17,6 @@ pub enum DatabaseError {
1717
#[error("failed to serde metadata value: {0}")]
1818
MetadataSerdeError(#[from] serde_json::Error),
1919
/// The L1 message was not found in database.
20-
#[error("L1 message at index [{0}] not found in database")]
21-
L1MessageNotFound(L1MessageStart),
20+
#[error("L1 message at key [{0}] not found in database")]
21+
L1MessageNotFound(L1MessageKey),
2222
}

crates/database/db/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ mod models;
1515
pub use models::*;
1616

1717
mod operations;
18-
pub use operations::{
19-
DatabaseReadOperations, DatabaseWriteOperations, L1MessageStart, UnwindResult,
20-
};
18+
pub use operations::{DatabaseReadOperations, DatabaseWriteOperations, L1MessageKey, UnwindResult};
2119

2220
mod transaction;
2321
pub use transaction::{DatabaseTransactionProvider, TXMut, TX};

crates/database/db/src/operations.rs

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -531,18 +531,34 @@ pub trait DatabaseReadOperations: ReadConnectionProvider + Sync {
531531
/// `start` point.
532532
async fn get_l1_messages<'a>(
533533
&'a self,
534-
start: Option<L1MessageStart>,
534+
start: Option<L1MessageKey>,
535535
) -> Result<impl Stream<Item = Result<L1MessageEnvelope, DatabaseError>> + 'a, DatabaseError>
536536
{
537537
let queue_index = match start {
538-
Some(L1MessageStart::Index(i)) => i,
539-
Some(L1MessageStart::Hash(ref h)) => {
538+
Some(L1MessageKey::QueueIndex(i)) => i,
539+
Some(L1MessageKey::TransactionHash(ref h)) => {
540540
// Lookup message by hash
541541
let record = models::l1_message::Entity::find()
542542
.filter(models::l1_message::Column::Hash.eq(h.to_vec()))
543543
.one(self.get_connection())
544544
.await?
545-
.ok_or_else(|| DatabaseError::L1MessageNotFound(L1MessageStart::Hash(*h)))?;
545+
.ok_or_else(|| {
546+
DatabaseError::L1MessageNotFound(L1MessageKey::TransactionHash(*h))
547+
})?;
548+
549+
record.queue_index as u64
550+
}
551+
Some(L1MessageKey::QueueHash(ref h)) => {
552+
// Lookup message by queue hash
553+
let record = models::l1_message::Entity::find()
554+
.filter(
555+
Condition::all()
556+
.add(models::l1_message::Column::QueueHash.is_not_null())
557+
.add(models::l1_message::Column::QueueHash.eq(h.to_vec())),
558+
)
559+
.one(self.get_connection())
560+
.await?
561+
.ok_or_else(|| DatabaseError::L1MessageNotFound(L1MessageKey::QueueHash(*h)))?;
546562

547563
record.queue_index as u64
548564
}
@@ -691,36 +707,43 @@ pub trait DatabaseReadOperations: ReadConnectionProvider + Sync {
691707
}
692708
}
693709

694-
/// This type defines the start of an L1 message stream.
710+
/// A key for an L1 message stored in the database.
695711
///
696-
/// It can either be an index, which is the queue index of the first message to return, or a hash,
697-
/// which is the hash of the first message to return.
712+
/// It can either be the queue index, queue hash or the transaction hash.
698713
#[derive(Debug, Clone, PartialEq, Eq)]
699-
pub enum L1MessageStart {
700-
/// Start from the provided queue index.
701-
Index(u64),
702-
/// Start from the provided queue hash.
703-
Hash(B256),
714+
pub enum L1MessageKey {
715+
/// The queue index of the message.
716+
QueueIndex(u64),
717+
/// The queue hash of the message.
718+
QueueHash(B256),
719+
/// The transaction hash of the message.
720+
TransactionHash(B256),
704721
}
705722

706-
impl fmt::Display for L1MessageStart {
707-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
708-
match self {
709-
Self::Index(index) => write!(f, "Index({index})"),
710-
Self::Hash(hash) => write!(f, "Hash({hash:#x})"),
711-
}
723+
impl L1MessageKey {
724+
/// Create a new [`L1MessageKey`] from a queue index.
725+
pub const fn from_queue_index(index: u64) -> Self {
726+
Self::QueueIndex(index)
727+
}
728+
729+
/// Create a new [`L1MessageKey`] from a queue hash.
730+
pub const fn from_queue_hash(hash: B256) -> Self {
731+
Self::QueueHash(hash)
712732
}
713-
}
714733

715-
impl From<u64> for L1MessageStart {
716-
fn from(value: u64) -> Self {
717-
Self::Index(value)
734+
/// Create a new [`L1MessageKey`] from a transaction hash.
735+
pub const fn from_transaction_hash(hash: B256) -> Self {
736+
Self::TransactionHash(hash)
718737
}
719738
}
720739

721-
impl From<B256> for L1MessageStart {
722-
fn from(value: B256) -> Self {
723-
Self::Hash(value)
740+
impl fmt::Display for L1MessageKey {
741+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
742+
match self {
743+
Self::QueueIndex(index) => write!(f, "QueueIndex({index})"),
744+
Self::QueueHash(hash) => write!(f, "QueueHash({hash:#x})"),
745+
Self::TransactionHash(hash) => write!(f, "TransactionHash({hash:#x})"),
746+
}
724747
}
725748
}
726749

crates/derivation-pipeline/src/lib.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use rollup_node_primitives::{
3030
use rollup_node_providers::{BlockDataProvider, L1Provider};
3131
use scroll_alloy_rpc_types_engine::{BlockDataHint, ScrollPayloadAttributes};
3232
use scroll_codec::{decoding::payload::PayloadData, Codec};
33-
use scroll_db::{Database, DatabaseReadOperations, DatabaseTransactionProvider};
33+
use scroll_db::{Database, DatabaseReadOperations, DatabaseTransactionProvider, L1MessageKey};
3434
use tokio::time::Interval;
3535

3636
/// A future that resolves to a vec of [`WithFullL2Meta<ScrollPayloadAttributes>`].
@@ -403,25 +403,31 @@ async fn iter_l1_messages_from_payload<L1P: L1Provider>(
403403
let total_l1_messages = data.blocks.iter().map(|b| b.context.num_l1_messages as u64).sum();
404404

405405
let messages = if let Some(index) = data.queue_index_start() {
406-
provider.get_n_messages(index.into(), total_l1_messages).await.map_err(Into::into)?
406+
provider
407+
.get_n_messages(L1MessageKey::from_queue_index(index), total_l1_messages)
408+
.await
409+
.map_err(Into::into)?
407410
} else if let Some(hash) = data.prev_l1_message_queue_hash() {
408411
// If the message queue hash is zero then we should use the V2 L1 message queue start
409412
// index. We must apply this branch logic because we do not have a L1
410413
// message associated with a queue hash of ZERO (we only compute a queue
411414
// hash for the first L1 message of the V2 contract).
412415
if hash == &B256::ZERO {
413416
provider
414-
.get_n_messages(l1_v2_message_queue_start_index.into(), total_l1_messages)
417+
.get_n_messages(
418+
L1MessageKey::from_queue_index(l1_v2_message_queue_start_index),
419+
total_l1_messages,
420+
)
415421
.await
416422
.map_err(Into::into)?
417423
} else {
418424
let mut messages = provider
419-
.get_n_messages((*hash).into(), total_l1_messages + 1)
425+
.get_n_messages(L1MessageKey::from_queue_hash(*hash), total_l1_messages + 1)
420426
.await
421427
.map_err(Into::into)?;
422428
// we skip the first l1 message, as we are interested in the one starting after
423429
// prev_l1_message_queue_hash.
424-
messages.pop();
430+
messages.remove(0);
425431
messages
426432
}
427433
} else {

crates/manager/src/manager/event.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use reth_scroll_primitives::ScrollBlock;
33
use rollup_node_chain_orchestrator::ChainOrchestratorEvent;
44
use rollup_node_signer::SignerEvent;
55
use rollup_node_watcher::L1Notification;
6-
use scroll_db::L1MessageStart;
6+
use scroll_db::L1MessageKey;
77
use scroll_engine::ConsolidationOutcome;
88
use scroll_network::NewBlockWithPeer;
99

@@ -33,8 +33,8 @@ pub enum RollupManagerEvent {
3333
},
3434
/// A block has been received containing an L1 message that is not in the database.
3535
L1MessageMissingInDatabase {
36-
/// The L1 message start index or hash.
37-
start: L1MessageStart,
36+
/// The L1 message key.
37+
key: L1MessageKey,
3838
},
3939
/// An event was received from the L1 watcher.
4040
L1NotificationEvent(L1Notification),

crates/manager/src/manager/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ where
435435

436436
if let Some(event_sender) = self.event_sender.as_ref() {
437437
event_sender.notify(RollupManagerEvent::L1MessageMissingInDatabase {
438-
start: start.clone(),
438+
key: start.clone(),
439439
});
440440
}
441441
}

crates/node/tests/e2e.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use rollup_node_sequencer::L1MessageInclusionMode;
3737
use rollup_node_watcher::L1Notification;
3838
use scroll_alloy_consensus::TxL1Message;
3939
use scroll_alloy_rpc_types::Transaction as ScrollAlloyTransaction;
40-
use scroll_db::{test_utils::setup_test_db, L1MessageStart};
40+
use scroll_db::{test_utils::setup_test_db, L1MessageKey};
4141
use scroll_network::NewBlockWithPeer;
4242
use scroll_wire::{ScrollWireConfig, ScrollWireProtocolHandler};
4343
use std::{
@@ -1719,7 +1719,7 @@ async fn can_reject_l2_block_with_unknown_l1_message() -> eyre::Result<()> {
17191719
wait_for_event_5s(
17201720
&mut node1_rnm_events,
17211721
RollupManagerEvent::L1MessageMissingInDatabase {
1722-
start: L1MessageStart::Hash(b256!(
1722+
key: L1MessageKey::TransactionHash(b256!(
17231723
"0x0a2f8e75392ab51a26a2af835042c614eb141cd934fe1bdd4934c10f2fe17e98"
17241724
)),
17251725
},

crates/node/tests/sync.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ async fn test_should_consolidate_after_optimistic_sync() -> eyre::Result<()> {
423423
// message.
424424
wait_n_events(
425425
&mut follower_events,
426-
|e| matches!(e, RollupManagerEvent::L1MessageMissingInDatabase { start: _ }),
426+
|e| matches!(e, RollupManagerEvent::L1MessageMissingInDatabase { key: _ }),
427427
1,
428428
)
429429
.await;
@@ -599,7 +599,7 @@ async fn test_consolidation() -> eyre::Result<()> {
599599
// Assert that the follower node rejects the new block as it hasn't received the L1 message.
600600
wait_n_events(
601601
&mut follower_events,
602-
|e| matches!(e, RollupManagerEvent::L1MessageMissingInDatabase { start: _ }),
602+
|e| matches!(e, RollupManagerEvent::L1MessageMissingInDatabase { key: _ }),
603603
1,
604604
)
605605
.await;

0 commit comments

Comments
 (0)