diff --git a/crates/protocol/src/batch/core.rs b/crates/protocol/src/batch/core.rs index 72bf3810b..ca4a71dac 100644 --- a/crates/protocol/src/batch/core.rs +++ b/crates/protocol/src/batch/core.rs @@ -62,7 +62,7 @@ impl Batch { Self::Span(sb) => { out.put_u8(BatchType::Span as u8); let raw_span_batch = - RawSpanBatch::try_from(sb).map_err(BatchEncodingError::SpanBatchError)?; + sb.to_raw_span_batch().map_err(BatchEncodingError::SpanBatchError)?; raw_span_batch.encode(out).map_err(BatchEncodingError::SpanBatchError)?; } } diff --git a/crates/protocol/src/batch/raw.rs b/crates/protocol/src/batch/raw.rs index 55ff6017a..7a95b2636 100644 --- a/crates/protocol/src/batch/raw.rs +++ b/crates/protocol/src/batch/raw.rs @@ -17,35 +17,6 @@ pub struct RawSpanBatch { pub payload: SpanBatchPayload, } -impl TryFrom<&SpanBatch> for RawSpanBatch { - type Error = SpanBatchError; - - fn try_from(value: &SpanBatch) -> Result { - if value.batches.is_empty() { - return Err(SpanBatchError::EmptySpanBatch); - } - - // These should never error since we check for an empty batch above. - let span_start = value.batches.first().ok_or(SpanBatchError::EmptySpanBatch)?; - let span_end = value.batches.last().ok_or(SpanBatchError::EmptySpanBatch)?; - - Ok(Self { - prefix: SpanBatchPrefix { - rel_timestamp: span_start.timestamp - value.genesis_timestamp, - l1_origin_num: span_end.epoch_num, - parent_check: value.parent_check, - l1_origin_check: value.l1_origin_check, - }, - payload: SpanBatchPayload { - block_count: value.batches.len() as u64, - origin_bits: value.origin_bits.clone(), - block_tx_counts: value.block_tx_counts.clone(), - txs: value.txs.clone(), - }, - }) - } -} - impl RawSpanBatch { /// Returns the batch type pub const fn get_batch_type(&self) -> BatchType { @@ -130,7 +101,7 @@ mod test { #[test] fn test_try_from_span_batch_empty_batches_errors() { let span_batch = SpanBatch::default(); - let raw_span_batch = RawSpanBatch::try_from(&span_batch).unwrap_err(); + let raw_span_batch = span_batch.to_raw_span_batch().unwrap_err(); assert_eq!(raw_span_batch, SpanBatchError::EmptySpanBatch); } @@ -154,7 +125,7 @@ mod test { l1_origin_check, }; let expected_payload = SpanBatchPayload { block_count: 2, ..Default::default() }; - let raw_span_batch = RawSpanBatch::try_from(&span_batch).unwrap(); + let raw_span_batch = span_batch.to_raw_span_batch().unwrap(); assert_eq!(raw_span_batch.prefix, expected_prefix); assert_eq!(raw_span_batch.payload, expected_payload); } diff --git a/crates/protocol/src/batch/span.rs b/crates/protocol/src/batch/span.rs index a4ab51e29..1ec7ebcf1 100644 --- a/crates/protocol/src/batch/span.rs +++ b/crates/protocol/src/batch/span.rs @@ -8,8 +8,9 @@ use op_alloy_genesis::RollupConfig; use tracing::{info, warn}; use crate::{ - BatchValidationProvider, BatchValidity, BlockInfo, L2BlockInfo, SingleBatch, SpanBatchBits, - SpanBatchElement, SpanBatchError, SpanBatchTransactions, + BatchValidationProvider, BatchValidity, BlockInfo, L2BlockInfo, RawSpanBatch, SingleBatch, + SpanBatchBits, SpanBatchElement, SpanBatchError, SpanBatchPayload, SpanBatchPrefix, + SpanBatchTransactions, }; /// The span batch contains the input to build a span of L2 blocks in derived form. @@ -73,6 +74,32 @@ impl SpanBatch { &self.batches[self.batches.len() - 1 - n] } + /// Constructs a [RawSpanBatch] from the [SpanBatch]. + pub fn to_raw_span_batch(&self) -> Result { + if self.batches.is_empty() { + return Err(SpanBatchError::EmptySpanBatch); + } + + // These should never error since we check for an empty batch above. + let span_start = self.batches.first().ok_or(SpanBatchError::EmptySpanBatch)?; + let span_end = self.batches.last().ok_or(SpanBatchError::EmptySpanBatch)?; + + Ok(RawSpanBatch { + prefix: SpanBatchPrefix { + rel_timestamp: span_start.timestamp - self.genesis_timestamp, + l1_origin_num: span_end.epoch_num, + parent_check: self.parent_check, + l1_origin_check: self.l1_origin_check, + }, + payload: SpanBatchPayload { + block_count: self.batches.len() as u64, + origin_bits: self.origin_bits.clone(), + block_tx_counts: self.block_tx_counts.clone(), + txs: self.txs.clone(), + }, + }) + } + /// Converts all [SpanBatchElement]s after the L2 safe head to [SingleBatch]es. The resulting /// [SingleBatch]es do not contain a parent hash, as it is populated by the Batch Queue /// stage.