1+ use super :: bundler:: { Bundle , BundlePoller } ;
2+ use super :: oauth:: Authenticator ;
3+ use super :: tx_poller:: TxPoller ;
4+ use crate :: config:: { BuilderConfig , WalletlessProvider } ;
5+ use alloy:: providers:: Provider ;
16use alloy:: {
27 consensus:: { SidecarBuilder , SidecarCoder , TxEnvelope } ,
38 eips:: eip2718:: Decodable2718 ,
@@ -10,19 +15,13 @@ use tokio::{sync::mpsc, task::JoinHandle};
1015use tracing:: Instrument ;
1116use zenith_types:: { encode_txns, Alloy2718Coder } ;
1217
13- use super :: bundler:: { Bundle , BundlePoller } ;
14- use super :: oauth:: Authenticator ;
15- use super :: tx_poller:: TxPoller ;
16- use crate :: config:: BuilderConfig ;
17-
1818/// Ethereum's slot time in seconds.
1919pub const ETHEREUM_SLOT_TIME : u64 = 12 ;
2020
2121#[ derive( Debug , Default , Clone ) ]
2222/// A block in progress.
2323pub struct InProgressBlock {
2424 transactions : Vec < TxEnvelope > ,
25-
2625 raw_encoding : OnceLock < Bytes > ,
2726 hash : OnceLock < B256 > ,
2827}
@@ -57,15 +56,22 @@ impl InProgressBlock {
5756
5857 /// Ingest a transaction into the in-progress block. Fails
5958 pub fn ingest_tx ( & mut self , tx : & TxEnvelope ) {
60- tracing:: info !( hash = %tx. tx_hash( ) , "ingesting tx" ) ;
59+ tracing:: trace !( hash = %tx. tx_hash( ) , "ingesting tx" ) ;
6160 self . unseal ( ) ;
6261 self . transactions . push ( tx. clone ( ) ) ;
6362 }
6463
64+ /// Remove a transaction from the in-progress block.
65+ pub fn remove_tx ( & mut self , tx : & TxEnvelope ) {
66+ tracing:: trace!( hash = %tx. tx_hash( ) , "removing tx" ) ;
67+ self . unseal ( ) ;
68+ self . transactions . retain ( |t| t. tx_hash ( ) != tx. tx_hash ( ) ) ;
69+ }
70+
6571 /// Ingest a bundle into the in-progress block.
6672 /// Ignores Signed Orders for now.
6773 pub fn ingest_bundle ( & mut self , bundle : Bundle ) {
68- tracing:: info !( bundle = %bundle. id, "ingesting bundle" ) ;
74+ tracing:: trace !( bundle = %bundle. id, "ingesting bundle" ) ;
6975
7076 let txs = bundle
7177 . bundle
@@ -113,26 +119,32 @@ impl InProgressBlock {
113119/// BlockBuilder is a task that periodically builds a block then sends it for signing and submission.
114120pub struct BlockBuilder {
115121 pub config : BuilderConfig ,
122+ pub ru_provider : WalletlessProvider ,
116123 pub tx_poller : TxPoller ,
117124 pub bundle_poller : BundlePoller ,
118125}
119126
120127impl BlockBuilder {
121128 // create a new block builder with the given config.
122- pub fn new ( config : & BuilderConfig , authenticator : Authenticator ) -> Self {
129+ pub fn new (
130+ config : & BuilderConfig ,
131+ authenticator : Authenticator ,
132+ ru_provider : WalletlessProvider ,
133+ ) -> Self {
123134 Self {
124135 config : config. clone ( ) ,
136+ ru_provider,
125137 tx_poller : TxPoller :: new ( config) ,
126138 bundle_poller : BundlePoller :: new ( config, authenticator) ,
127139 }
128140 }
129141
130142 async fn get_transactions ( & mut self , in_progress : & mut InProgressBlock ) {
131- tracing:: info !( "query transactions from cache" ) ;
143+ tracing:: trace !( "query transactions from cache" ) ;
132144 let txns = self . tx_poller . check_tx_cache ( ) . await ;
133145 match txns {
134146 Ok ( txns) => {
135- tracing:: info !( "got transactions response" ) ;
147+ tracing:: trace !( "got transactions response" ) ;
136148 for txn in txns. into_iter ( ) {
137149 in_progress. ingest_tx ( & txn) ;
138150 }
@@ -145,11 +157,11 @@ impl BlockBuilder {
145157 }
146158
147159 async fn _get_bundles ( & mut self , in_progress : & mut InProgressBlock ) {
148- tracing:: info !( "query bundles from cache" ) ;
160+ tracing:: trace !( "query bundles from cache" ) ;
149161 let bundles = self . bundle_poller . check_bundle_cache ( ) . await ;
150162 match bundles {
151163 Ok ( bundles) => {
152- tracing:: info !( "got bundles response" ) ;
164+ tracing:: trace !( "got bundles response" ) ;
153165 for bundle in bundles {
154166 in_progress. ingest_bundle ( bundle) ;
155167 }
@@ -161,15 +173,36 @@ impl BlockBuilder {
161173 self . bundle_poller . evict ( ) ;
162174 }
163175
176+ async fn filter_transactions ( & self , in_progress : & mut InProgressBlock ) {
177+ // query the rollup node to see which transaction(s) have been included
178+ let mut confirmed_transactions = Vec :: new ( ) ;
179+ for transaction in in_progress. transactions . iter ( ) {
180+ let tx = self
181+ . ru_provider
182+ . get_transaction_by_hash ( * transaction. tx_hash ( ) )
183+ . await
184+ . expect ( "failed to get receipt" ) ;
185+ if tx. is_some ( ) {
186+ confirmed_transactions. push ( transaction. clone ( ) ) ;
187+ }
188+ }
189+ tracing:: trace!( confirmed = confirmed_transactions. len( ) , "found confirmed transactions" ) ;
190+
191+ // remove already-confirmed transactions
192+ for transaction in confirmed_transactions {
193+ in_progress. remove_tx ( & transaction) ;
194+ }
195+ }
196+
164197 // calculate the duration in seconds until the beginning of the next block slot.
165- fn secs_to_next_slot ( & mut self ) -> u64 {
198+ fn secs_to_next_slot ( & self ) -> u64 {
166199 let curr_timestamp: u64 = SystemTime :: now ( ) . duration_since ( UNIX_EPOCH ) . unwrap ( ) . as_secs ( ) ;
167200 let current_slot_time = ( curr_timestamp - self . config . chain_offset ) % ETHEREUM_SLOT_TIME ;
168201 ( ETHEREUM_SLOT_TIME - current_slot_time) % ETHEREUM_SLOT_TIME
169202 }
170203
171204 // add a buffer to the beginning of the block slot.
172- fn secs_to_next_target ( & mut self ) -> u64 {
205+ fn secs_to_next_target ( & self ) -> u64 {
173206 self . secs_to_next_slot ( ) + self . config . target_slot_time
174207 }
175208
@@ -190,16 +223,19 @@ impl BlockBuilder {
190223 // TODO: Implement bundle ingestion #later
191224 // self.get_bundles(&mut in_progress).await;
192225
226+ // Filter confirmed transactions from the block
227+ self . filter_transactions ( & mut in_progress) . await ;
228+
193229 // submit the block if it has transactions
194230 if !in_progress. is_empty ( ) {
195- tracing:: info !( txns = in_progress. len( ) , "sending block to submit task" ) ;
231+ tracing:: debug !( txns = in_progress. len( ) , "sending block to submit task" ) ;
196232 let in_progress_block = std:: mem:: take ( & mut in_progress) ;
197233 if outbound. send ( in_progress_block) . is_err ( ) {
198- tracing:: debug !( "downstream task gone" ) ;
234+ tracing:: error !( "downstream task gone" ) ;
199235 break ;
200236 }
201237 } else {
202- tracing:: info !( "no transactions, skipping block submission" ) ;
238+ tracing:: debug !( "no transactions, skipping block submission" ) ;
203239 }
204240 }
205241 }
0 commit comments