-
Notifications
You must be signed in to change notification settings - Fork 4
feat: chain orchestrator #185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
c1e5cc2
bbe0e8f
4032fa5
39802e2
c84dc0d
ea3140c
a28a5b2
fa6952c
43cc2be
5dfc813
a50558d
19458f7
4578d49
e6248f5
626e29b
7a6ebfc
7d35185
74fd7b8
fe75ed5
f3bab0d
56a0ff3
1320f14
0fa87fe
cecbd03
af4bac9
7df1a59
fa51172
e86446d
9cdbdf3
01a10cf
2f851b1
9f88b5d
9a3339a
000ade7
00d18f2
2beb7e0
add9933
e3d5453
4383231
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
[codespell] | ||
skip = .git,target,Cargo.toml,Cargo.lock | ||
skip = .git,target,Cargo.toml,Cargo.lock,docker-compose | ||
ignore-words-list = crate |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
use super::{ChainOrchestratorError, ChainOrchestratorEvent}; | ||
use std::{ | ||
fmt, | ||
future::Future, | ||
pin::Pin, | ||
task::{Context, Poll}, | ||
}; | ||
|
||
/// A future that resolves to a `Result<ChainOrchestratorEvent, ChainOrchestratorError>`. | ||
pub(super) type PendingChainOrchestratorFuture = Pin< | ||
Box<dyn Future<Output = Result<Option<ChainOrchestratorEvent>, ChainOrchestratorError>> + Send>, | ||
>; | ||
|
||
/// A type that represents a future that is being executed by the chain orchestrator. | ||
pub(super) enum ChainOrchestratorFuture { | ||
HandleReorg(PendingChainOrchestratorFuture), | ||
HandleFinalized(PendingChainOrchestratorFuture), | ||
HandleBatchCommit(PendingChainOrchestratorFuture), | ||
HandleBatchFinalization(PendingChainOrchestratorFuture), | ||
HandleL1Message(PendingChainOrchestratorFuture), | ||
HandleDerivedBlock(PendingChainOrchestratorFuture), | ||
HandleL2Block(PendingChainOrchestratorFuture), | ||
} | ||
|
||
impl ChainOrchestratorFuture { | ||
/// Polls the future to completion. | ||
pub(super) fn poll( | ||
&mut self, | ||
cx: &mut Context<'_>, | ||
) -> Poll<Result<Option<ChainOrchestratorEvent>, ChainOrchestratorError>> { | ||
match self { | ||
Self::HandleReorg(fut) | | ||
Self::HandleFinalized(fut) | | ||
Self::HandleBatchCommit(fut) | | ||
Self::HandleBatchFinalization(fut) | | ||
Self::HandleL1Message(fut) | | ||
Self::HandleDerivedBlock(fut) | | ||
Self::HandleL2Block(fut) => fut.as_mut().poll(cx), | ||
} | ||
} | ||
} | ||
|
||
// We implement the Debug trait for ChainOrchestratorFuture to provide a human-readable | ||
// representation of the enum variants. | ||
impl fmt::Debug for ChainOrchestratorFuture { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
match self { | ||
Self::HandleReorg(_) => write!(f, "HandleReorg"), | ||
Self::HandleFinalized(_) => write!(f, "HandleFinalized"), | ||
Self::HandleBatchCommit(_) => write!(f, "HandleBatchCommit"), | ||
Self::HandleBatchFinalization(_) => write!(f, "HandleBatchFinalization"), | ||
Self::HandleL1Message(_) => write!(f, "HandleL1Message"), | ||
Self::HandleDerivedBlock(_) => write!(f, "HandleDerivedBlock"), | ||
Self::HandleL2Block(_) => write!(f, "HandleL2Block"), | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use alloy_json_rpc::RpcError; | ||
use alloy_primitives::B256; | ||
use alloy_transport::TransportErrorKind; | ||
use scroll_db::{DatabaseError, L1MessageStart}; | ||
|
||
/// A type that represents an error that occurred in the chain orchestrator. | ||
#[derive(Debug, thiserror::Error)] | ||
pub enum ChainOrchestratorError { | ||
/// An error occurred while interacting with the database. | ||
#[error("database error occurred: {0}")] | ||
DatabaseError(#[from] DatabaseError), | ||
/// An error occurred while trying to fetch the L2 block from the database. | ||
#[error("L2 block not found - block number: {0}")] | ||
L2BlockNotFoundInDatabase(u64), | ||
/// An error occurred while trying to fetch the L2 block from the L2 client. | ||
#[error("L2 block not found in L2 client - block number: {0}")] | ||
L2BlockNotFoundInL2Client(u64), | ||
/// A fork was received from the peer that is associated with a reorg of the safe chain. | ||
#[error("L2 safe block reorg detected")] | ||
L2SafeBlockReorgDetected, | ||
/// A block contains invalid L1 messages. | ||
#[error("Block contains invalid L1 message. Expected: {expected:?}, Actual: {actual:?}")] | ||
L1MessageMismatch { | ||
/// The expected L1 messages hash. | ||
expected: B256, | ||
/// The actual L1 messages hash. | ||
actual: B256, | ||
}, | ||
/// An L1 message was not found in the database. | ||
#[error("L1 message not found at {0}")] | ||
L1MessageNotFound(L1MessageStart), | ||
/// An inconsistency was detected when trying to consolidate the chain. | ||
#[error("Chain inconsistency detected")] | ||
ChainInconsistency, | ||
/// The peer did not provide the requested block header. | ||
#[error("A peer did not provide the requested block header")] | ||
MissingBlockHeader { | ||
/// The hash of the block header that was requested. | ||
hash: B256, | ||
}, | ||
/// An error occurred while making a network request. | ||
#[error("Network request error: {0}")] | ||
NetworkRequestError(#[from] reth_network_p2p::error::RequestError), | ||
/// An error occurred while making a JSON-RPC request to the Execution Node (EN). | ||
#[error("An error occurred while making a JSON-RPC request to the EN: {0}")] | ||
RpcError(#[from] RpcError<TransportErrorKind>), | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
use alloy_consensus::Header; | ||
use alloy_primitives::{Signature, B256}; | ||
use reth_network_peers::PeerId; | ||
use reth_scroll_primitives::ScrollBlock; | ||
use rollup_node_primitives::{BatchInfo, BlockInfo, ChainImport, L2BlockInfoWithL1Messages}; | ||
|
||
/// An event emitted by the `ChainOrchestrator`. | ||
#[derive(Debug, Clone, PartialEq, Eq)] | ||
pub enum ChainOrchestratorEvent { | ||
/// A new block has been received from the network but we have insufficient data to process it | ||
/// due to being in optimistic mode. | ||
InsufficientDataForReceivedBlock(B256), | ||
/// The block that we have received is already known. | ||
BlockAlreadyKnown(B256, PeerId), | ||
/// A fork of the chain that is older than the current chain has been received. | ||
OldForkReceived { | ||
/// The headers of the old fork. | ||
headers: Vec<Header>, | ||
/// The peer that provided the old fork. | ||
peer_id: PeerId, | ||
/// The signature of the old fork. | ||
signature: Signature, | ||
}, | ||
/// The chain should be optimistically synced to the provided block. | ||
OptimisticSync(ScrollBlock), | ||
/// The chain has been extended, returning the new blocks. | ||
ChainExtended(ChainImport), | ||
/// The chain has reorged, returning the new chain and the peer that provided them. | ||
ChainReorged(ChainImport), | ||
/// A `BatchCommit` event has been indexed returning the batch info and the L2 block info to | ||
/// revert to due to a batch revert. | ||
Comment on lines
+30
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand this comment |
||
BatchCommitIndexed { | ||
/// The batch info. | ||
batch_info: BatchInfo, | ||
/// The L1 block number in which the batch was committed. | ||
l1_block_number: u64, | ||
/// The safe L2 block info. | ||
safe_head: Option<BlockInfo>, | ||
}, | ||
/// A batch has been finalized returning the batch hash and new an optional finalized | ||
/// L2 block. | ||
BatchFinalized(B256, Option<BlockInfo>), | ||
/// An L1 block has been finalized returning the L1 block number and an optional | ||
/// finalized L2 block. | ||
L1BlockFinalized(u64, Option<BlockInfo>), | ||
/// A `L1Message` event has been committed returning the message queue index. | ||
L1MessageCommitted(u64), | ||
/// The chain has been unwound, returning the L1 block number of the new L1 head, | ||
/// the L1 message queue index of the new L1 head, and optionally the L2 head and safe block | ||
/// info if the unwind resulted in a new L2 head or safe block. | ||
ChainUnwound { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure what does this mean? Is it a reorg? |
||
/// The L1 block number of the new L1 head. | ||
l1_block_number: u64, | ||
/// The L1 message queue index of the new L1 head. | ||
queue_index: Option<u64>, | ||
/// The L2 head block info. | ||
l2_head_block_info: Option<BlockInfo>, | ||
/// The L2 safe block info. | ||
l2_safe_block_info: Option<BlockInfo>, | ||
}, | ||
/// An L2 block has been committed returning the [`L2BlockInfoWithL1Messages`] and an | ||
/// optional [`BatchInfo`] if the block is associated with a committed batch. | ||
L2ChainCommitted(L2BlockInfoWithL1Messages, Option<BatchInfo>, bool), | ||
/// An L2 consolidated block has been committed returning the [`L2BlockInfoWithL1Messages`]. | ||
L2ConsolidatedBlockCommitted(L2BlockInfoWithL1Messages), | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming on the events seems a bit inconsistent after just reading the event names and description in this file.