kona_derive/errors/
pipeline.rsuse crate::errors::BuilderError;
use alloc::string::String;
use alloy_primitives::B256;
use op_alloy_genesis::system::SystemConfigUpdateError;
use op_alloy_protocol::{DepositError, SpanBatchError};
#[macro_export]
macro_rules! ensure {
($cond:expr, $err:expr) => {
if !($cond) {
return Err($err);
}
};
}
#[derive(derive_more::Display, Debug, PartialEq, Eq)]
pub enum PipelineErrorKind {
#[display("Temporary error: {_0}")]
Temporary(PipelineError),
#[display("Critical error: {_0}")]
Critical(PipelineError),
#[display("Pipeline reset: {_0}")]
Reset(ResetError),
}
impl From<ResetError> for PipelineErrorKind {
fn from(err: ResetError) -> Self {
Self::Reset(err)
}
}
impl core::error::Error for PipelineErrorKind {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self {
Self::Temporary(err) => Some(err),
Self::Critical(err) => Some(err),
Self::Reset(err) => Some(err),
}
}
}
#[derive(derive_more::Display, Debug, PartialEq, Eq)]
pub enum PipelineError {
#[display("EOF")]
Eof,
#[display("Not enough data")]
NotEnoughData,
#[display("The channel provider is empty")]
ChannelProviderEmpty,
#[display("Channel already built")]
ChannelAlreadyBuilt,
#[display("Channel not found in channel provider")]
ChannelNotFound,
#[display("The channel reader has no channel available")]
ChannelReaderEmpty,
#[display("The batch queue has no batches available")]
BatchQueueEmpty,
#[display("Missing L1 origin from previous stage")]
MissingOrigin,
#[display("L1 Retrieval missing data")]
MissingL1Data,
#[display("Invalid batch type passed to stage")]
InvalidBatchType,
#[display("Invalid batch validity")]
InvalidBatchValidity,
#[display("Error updating system config: {_0}")]
SystemConfigUpdate(SystemConfigUpdateError),
#[display("Attributes builder error: {_0}")]
AttributesBuilder(BuilderError),
#[display("Decode error: {_0}")]
BadEncoding(PipelineEncodingError),
#[display("Data source exhausted")]
EndOfSource,
#[display("Blob provider error: {_0}")]
Provider(String),
}
impl From<BuilderError> for PipelineError {
fn from(err: BuilderError) -> Self {
Self::AttributesBuilder(err)
}
}
impl From<PipelineEncodingError> for PipelineError {
fn from(err: PipelineEncodingError) -> Self {
Self::BadEncoding(err)
}
}
impl core::error::Error for PipelineError {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self {
Self::AttributesBuilder(err) => Some(err),
Self::BadEncoding(err) => Some(err),
_ => None,
}
}
}
impl PipelineError {
pub const fn crit(self) -> PipelineErrorKind {
PipelineErrorKind::Critical(self)
}
pub const fn temp(self) -> PipelineErrorKind {
PipelineErrorKind::Temporary(self)
}
}
#[derive(derive_more::Display, Clone, Debug, Eq, PartialEq)]
pub enum ResetError {
#[display("Bad parent hash: expected {_0}, got {_1}")]
BadParentHash(B256, B256),
#[display("Bad timestamp: expected {_0}, got {_1}")]
BadTimestamp(u64, u64),
#[display("L1 origin mismatch. Expected {_0:?}, got {_1:?}")]
L1OriginMismatch(u64, u64),
#[display("L1 reorg detected: expected {_0}, got {_1}")]
ReorgDetected(B256, B256),
#[display("Attributes builder error: {_0}")]
AttributesBuilder(BuilderError),
#[display("Holocene activation reset")]
HoloceneActivation,
}
impl From<BuilderError> for ResetError {
fn from(err: BuilderError) -> Self {
Self::AttributesBuilder(err)
}
}
impl core::error::Error for ResetError {}
impl ResetError {
pub const fn reset(self) -> PipelineErrorKind {
PipelineErrorKind::Reset(self)
}
}
#[derive(derive_more::Display, Debug, PartialEq, Eq)]
pub enum PipelineEncodingError {
#[display("Empty buffer")]
EmptyBuffer,
#[display("Error decoding deposit: {_0}")]
DepositError(DepositError),
#[display("RLP error: {_0}")]
AlloyRlpError(alloy_rlp::Error),
#[display("{_0}")]
SpanBatchError(SpanBatchError),
}
impl core::error::Error for PipelineEncodingError {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self {
Self::DepositError(err) => Some(err),
Self::SpanBatchError(err) => Some(err),
_ => None,
}
}
}
impl From<SpanBatchError> for PipelineEncodingError {
fn from(err: SpanBatchError) -> Self {
Self::SpanBatchError(err)
}
}
impl From<DepositError> for PipelineEncodingError {
fn from(err: DepositError) -> Self {
Self::DepositError(err)
}
}
#[cfg(test)]
mod tests {
use super::*;
use core::error::Error;
#[test]
fn test_pipeline_error_kind_source() {
let err = PipelineErrorKind::Temporary(PipelineError::Eof);
assert!(err.source().is_some());
let err = PipelineErrorKind::Critical(PipelineError::Eof);
assert!(err.source().is_some());
let err = PipelineErrorKind::Reset(ResetError::BadParentHash(
Default::default(),
Default::default(),
));
assert!(err.source().is_some());
}
#[test]
fn test_pipeline_error_source() {
let err = PipelineError::AttributesBuilder(BuilderError::BlockMismatch(
Default::default(),
Default::default(),
));
assert!(err.source().is_some());
let encoding_err = PipelineEncodingError::EmptyBuffer;
let err: PipelineError = encoding_err.into();
assert!(err.source().is_some());
let err = PipelineError::Eof;
assert!(err.source().is_none());
}
#[test]
fn test_pipeline_encoding_error_source() {
let err = PipelineEncodingError::DepositError(DepositError::UnexpectedTopicsLen(0));
assert!(err.source().is_some());
let err = SpanBatchError::TooBigSpanBatchSize;
let err: PipelineEncodingError = err.into();
assert!(err.source().is_some());
let err = PipelineEncodingError::EmptyBuffer;
assert!(err.source().is_none());
}
#[test]
fn test_reset_error_kinds() {
let reset_errors = [
ResetError::BadParentHash(Default::default(), Default::default()),
ResetError::BadTimestamp(0, 0),
ResetError::L1OriginMismatch(0, 0),
ResetError::ReorgDetected(Default::default(), Default::default()),
ResetError::AttributesBuilder(BuilderError::BlockMismatch(
Default::default(),
Default::default(),
)),
ResetError::HoloceneActivation,
];
for error in reset_errors.into_iter() {
let expected = PipelineErrorKind::Reset(error.clone());
assert_eq!(error.reset(), expected);
}
}
}