diff --git a/crates/derive/src/types/batch/span_batch/batch.rs b/crates/derive/src/types/batch/span_batch/batch.rs index a4b45860..f68f3b32 100644 --- a/crates/derive/src/types/batch/span_batch/batch.rs +++ b/crates/derive/src/types/batch/span_batch/batch.rs @@ -4,8 +4,8 @@ use super::{SpanBatchError, SpanBatchTransactions}; use crate::{ traits::L2ChainProvider, types::{ - BatchValidity, BlockInfo, L2BlockInfo, RawSpanBatch, RollupConfig, SingleBatch, - SpanBatchBits, SpanBatchElement, SpanBatchPayload, SpanBatchPrefix, + BatchValidity, BlockInfo, L2BlockInfo, RollupConfig, SingleBatch, SpanBatchBits, + SpanBatchElement, }, }; use alloc::vec::Vec; @@ -316,36 +316,6 @@ impl SpanBatch { BatchValidity::Accept } - /// Converts the span batch to a raw span batch. - pub fn to_raw_span_batch( - &self, - _origin_changed_bit: u8, - genesis_timestamp: u64, - _chain_id: u64, - ) -> Result { - if self.batches.is_empty() { - return Err(SpanBatchError::EmptySpanBatch); - } - - 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 - 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. diff --git a/crates/derive/src/types/batch/span_batch/raw.rs b/crates/derive/src/types/batch/span_batch/raw.rs index e1ca81d7..9b8d6677 100644 --- a/crates/derive/src/types/batch/span_batch/raw.rs +++ b/crates/derive/src/types/batch/span_batch/raw.rs @@ -18,6 +18,35 @@ pub struct RawSpanBatch { pub payload: SpanBatchPayload, } +impl TryFrom 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(RawSpanBatch { + 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 fn get_batch_type(&self) -> BatchType { @@ -105,8 +134,41 @@ impl RawSpanBatch { #[cfg(test)] mod test { extern crate std; - use super::RawSpanBatch; - use alloc::vec::Vec; + use super::{RawSpanBatch, SpanBatch, SpanBatchElement}; + use alloc::{vec, vec::Vec}; + use alloy_primitives::FixedBytes; + + #[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(); + assert_eq!(raw_span_batch, super::SpanBatchError::EmptySpanBatch); + } + + #[test] + fn test_try_from_span_batch_succeeds() { + let parent_check = FixedBytes::from([2u8; 20]); + let l1_origin_check = FixedBytes::from([3u8; 20]); + let first = SpanBatchElement { epoch_num: 100, timestamp: 400, transactions: Vec::new() }; + let last = SpanBatchElement { epoch_num: 200, timestamp: 500, transactions: Vec::new() }; + let span_batch = SpanBatch { + batches: vec![first, last], + genesis_timestamp: 300, + parent_check, + l1_origin_check, + ..Default::default() + }; + let expected_prefix = super::SpanBatchPrefix { + rel_timestamp: 100, + l1_origin_num: 200, + parent_check, + l1_origin_check, + }; + let expected_payload = super::SpanBatchPayload { block_count: 2, ..Default::default() }; + let raw_span_batch = RawSpanBatch::try_from(span_batch).unwrap(); + assert_eq!(raw_span_batch.prefix, expected_prefix); + assert_eq!(raw_span_batch.payload, expected_payload); + } #[test] fn test_decode_encode_raw_span_batch() {