@@ -14,6 +14,9 @@ use scroll_codec::{decoding::payload::PayloadData, Codec, CodecError, DecodingEr
1414use scroll_db:: { Database , DatabaseReadOperations , L1MessageKey } ;
1515use tokio:: sync:: mpsc:: { UnboundedReceiver , UnboundedSender } ;
1616
17+ mod cache;
18+ use cache:: { PreFetchCache , DEFAULT_CACHE_SIZE , DEFAULT_CACHE_TTL , DEFAULT_PREFETCH_COUNT } ;
19+
1720mod data_source;
1821
1922mod error;
@@ -108,6 +111,8 @@ pub struct DerivationPipelineWorker<P> {
108111 futures : FuturesOrdered < DerivationPipelineFuture > ,
109112 /// A reference to the database.
110113 database : Arc < Database > ,
114+ /// A cache for pre-fetching derivation pipeline data from the database.
115+ cache : PreFetchCache ,
111116 /// A L1 provider.
112117 l1_provider : P ,
113118 /// The L1 message queue index at which the V2 L1 message queue was enabled.
@@ -118,22 +123,30 @@ pub struct DerivationPipelineWorker<P> {
118123
119124impl < P > DerivationPipelineWorker < P > {
120125 /// Returns a new instance of the [`DerivationPipeline`].
121- pub fn new (
126+ pub async fn new (
122127 l1_provider : P ,
123128 database : Arc < Database > ,
124129 l1_v2_message_queue_start_index : u64 ,
125130 batch_receiver : UnboundedReceiver < Arc < BatchDerivationRequest > > ,
126131 result_sender : UnboundedSender < BatchDerivationResult > ,
127- ) -> Self {
128- Self {
132+ ) -> Result < Self , DerivationPipelineError > {
133+ let cache = PreFetchCache :: new (
134+ database. clone ( ) ,
135+ DEFAULT_CACHE_SIZE ,
136+ DEFAULT_CACHE_TTL ,
137+ DEFAULT_PREFETCH_COUNT ,
138+ )
139+ . await ?;
140+ Ok ( Self {
129141 batch_receiver,
130142 result_sender,
131143 futures : FuturesOrdered :: new ( ) ,
132144 database,
145+ cache,
133146 l1_provider,
134147 l1_v2_message_queue_start_index,
135148 metrics : DerivationPipelineMetrics :: default ( ) ,
136- }
149+ } )
137150 }
138151}
139152
@@ -158,7 +171,9 @@ where
158171 l1_v2_message_queue_start_index,
159172 batch_receiver,
160173 result_sender,
161- ) ;
174+ )
175+ . await
176+ . expect ( "Failed to create derivation pipeline worker" ) ;
162177
163178 worker. run ( ) . await ;
164179 } ) ;
@@ -207,6 +222,7 @@ where
207222
208223 fn derivation_future ( & self , request : Arc < BatchDerivationRequest > ) -> DerivationPipelineFuture {
209224 let db = self . database . clone ( ) ;
225+ let cache = self . cache . clone ( ) ;
210226 let metrics = self . metrics . clone ( ) ;
211227 let provider = self . l1_provider . clone ( ) ;
212228 let l1_v2_message_queue_start_index = self . l1_v2_message_queue_start_index ;
@@ -228,7 +244,7 @@ where
228244
229245 // derive the attributes and attach the corresponding batch info.
230246 let result =
231- derive ( batch, target_status, provider, db , l1_v2_message_queue_start_index)
247+ derive ( batch, target_status, provider, cache , l1_v2_message_queue_start_index)
232248 . await
233249 . map_err ( |err| ( request. clone ( ) , err) ) ?;
234250
@@ -286,11 +302,11 @@ type DerivationPipelineFuture = Pin<
286302
287303/// Returns a [`BatchDerivationResult`] from the [`BatchCommitData`] by deriving the payload
288304/// attributes for each L2 block in the batch.
289- pub async fn derive < L1P : L1Provider + Sync + Send , DB : DatabaseReadOperations > (
305+ pub async fn derive < L1P : L1Provider + Sync + Send > (
290306 batch : BatchCommitData ,
291307 target_status : BatchStatus ,
292308 l1_provider : L1P ,
293- db : DB ,
309+ cache : PreFetchCache ,
294310 l1_v2_message_queue_start_index : u64 ,
295311) -> Result < BatchDerivationResult , DerivationPipelineError > {
296312 // fetch the blob then decode the input batch.
@@ -323,14 +339,7 @@ pub async fn derive<L1P: L1Provider + Sync + Send, DB: DatabaseReadOperations>(
323339 let blocks = decoded. data . into_l2_blocks ( ) ;
324340 let mut attributes = Vec :: with_capacity ( blocks. len ( ) ) ;
325341
326- let start = blocks. first ( ) . map ( |b| b. context . number ) ;
327- let block_data = if let Some ( start) = start {
328- db. get_n_l2_block_data_hint ( start, blocks. len ( ) ) . await ?
329- } else {
330- vec ! [ ]
331- } ;
332-
333- for ( i, mut block) in blocks. into_iter ( ) . enumerate ( ) {
342+ for mut block in blocks {
334343 // query the appropriate amount of l1 messages.
335344 let mut txs = Vec :: with_capacity ( block. context . num_transactions as usize ) ;
336345 for _ in 0 ..block. context . num_l1_messages {
@@ -369,7 +378,10 @@ pub async fn derive<L1P: L1Provider + Sync + Send, DB: DatabaseReadOperations>(
369378 } ,
370379 transactions : Some ( txs) ,
371380 no_tx_pool : true ,
372- block_data_hint : block_data. get ( i) . cloned ( ) . unwrap_or_else ( BlockDataHint :: none) ,
381+ block_data_hint : cache
382+ . get ( block. context . number )
383+ . await ?
384+ . unwrap_or_else ( BlockDataHint :: none) ,
373385 gas_limit : Some ( block. context . gas_limit ) ,
374386 } ,
375387 } ;
@@ -446,7 +458,7 @@ async fn iter_l1_messages_from_payload<L1P: L1Provider>(
446458#[ cfg( test) ]
447459mod tests {
448460 use super :: * ;
449- use std:: sync:: Arc ;
461+ use std:: { sync:: Arc , time :: Duration } ;
450462
451463 use alloy_eips:: Decodable2718 ;
452464 use alloy_primitives:: { address, b256, bytes, U256 } ;
@@ -643,10 +655,12 @@ mod tests {
643655 for message in l1_messages {
644656 db. insert_l1_message ( message) . await ?;
645657 }
658+ let cache = PreFetchCache :: new ( db. clone ( ) , 100 , Duration :: from_secs ( 60 ) , 10 ) . await ?;
646659
647660 let l1_provider = MockL1Provider { db : db. clone ( ) , blobs : HashMap :: new ( ) } ;
648661
649- let result = derive ( batch_data, BatchStatus :: Committed , l1_provider, db, u64:: MAX ) . await ?;
662+ let result =
663+ derive ( batch_data, BatchStatus :: Committed , l1_provider, cache, u64:: MAX ) . await ?;
650664 let attribute = result
651665 . attributes
652666 . iter ( )
@@ -745,10 +759,11 @@ mod tests {
745759 }
746760
747761 let l1_provider = MockL1Provider { db : db. clone ( ) , blobs : HashMap :: new ( ) } ;
762+ let cache = PreFetchCache :: new ( db. clone ( ) , 100 , Duration :: from_secs ( 60 ) , 10 ) . await ?;
748763
749764 // derive attributes and extract l1 messages.
750765 let attributes =
751- derive ( batch_data, BatchStatus :: Committed , l1_provider, db , u64:: MAX ) . await ?;
766+ derive ( batch_data, BatchStatus :: Committed , l1_provider, cache , u64:: MAX ) . await ?;
752767 let derived_l1_messages: Vec < _ > = attributes
753768 . attributes
754769 . into_iter ( )
@@ -800,10 +815,11 @@ mod tests {
800815 }
801816
802817 let l1_provider = MockL1Provider { db : db. clone ( ) , blobs : HashMap :: new ( ) } ;
818+ let cache = PreFetchCache :: new ( db. clone ( ) , 100 , Duration :: from_secs ( 60 ) , 10 ) . await ?;
803819
804820 // derive attributes and extract l1 messages.
805821 let attributes =
806- derive ( batch_data, BatchStatus :: Committed , l1_provider, db , u64:: MAX ) . await ?;
822+ derive ( batch_data, BatchStatus :: Committed , l1_provider, cache , u64:: MAX ) . await ?;
807823 let derived_l1_messages: Vec < _ > = attributes
808824 . attributes
809825 . into_iter ( )
@@ -916,8 +932,9 @@ mod tests {
916932 blob_path
917933 ) ] ) ,
918934 } ;
935+ let cache = PreFetchCache :: new ( db. clone ( ) , 100 , Duration :: from_secs ( 60 ) , 10 ) . await ?;
919936
920- let attributes = derive ( batch_data, BatchStatus :: Committed , l1_provider, db , u64:: MAX ) . await ?;
937+ let attributes = derive ( batch_data, BatchStatus :: Committed , l1_provider, cache , u64:: MAX ) . await ?;
921938
922939 let attribute = attributes. attributes . last ( ) . unwrap ( ) ;
923940 let expected = ScrollPayloadAttributes {
0 commit comments