@@ -27,7 +27,7 @@ use monad_chain_config::{
2727 ChainConfig , MockChainConfig ,
2828} ;
2929use monad_consensus_types:: {
30- block:: { BlockPolicyError , ProposedExecutionInputs } ,
30+ block:: { BlockPolicyError , ConsensusBlockHeader , ProposedExecutionInputs } ,
3131 payload:: RoundSignature ,
3232} ;
3333use monad_crypto:: certificate_signature:: {
@@ -41,7 +41,7 @@ use monad_system_calls::{SystemTransactionGenerator, SYSTEM_SENDER_ETH_ADDRESS};
4141use monad_types:: { Epoch , NodeId , Round , SeqNum } ;
4242use monad_validator:: signature_collection:: SignatureCollection ;
4343use rayon:: iter:: { IntoParallelIterator , ParallelIterator } ;
44- use tracing:: { debug, info, warn} ;
44+ use tracing:: { debug, error , info, warn} ;
4545
4646pub use self :: transaction:: max_eip2718_encoded_length;
4747use self :: { pending:: PendingTxMap , tracked:: TrackedTxMap , transaction:: ValidEthTransaction } ;
7070 pending : PendingTxMap ,
7171 tracked : TrackedTxMap < ST , SCT , SBT , CCT , CRT > ,
7272
73+ last_commit : Option < ConsensusBlockHeader < ST , SCT , EthExecutionProtocol > > ,
74+
7375 chain_id : u64 ,
7476 chain_revision : CRT ,
7577 execution_revision : MonadExecutionRevision ,
98100 pending : PendingTxMap :: default ( ) ,
99101 tracked : TrackedTxMap :: new ( soft_tx_expiry, hard_tx_expiry) ,
100102
103+ last_commit : None ,
104+
101105 chain_id,
102106 chain_revision,
103107 execution_revision,
@@ -136,7 +140,7 @@ where
136140 return ;
137141 }
138142
139- let Some ( last_commit) = self . tracked . last_commit ( ) else {
143+ let Some ( last_commit) = self . last_commit . as_ref ( ) else {
140144 event_tracker. drop_all ( txs. into_iter ( ) , EthTxPoolDropReason :: PoolNotReady ) ;
141145 return ;
142146 } ;
@@ -202,7 +206,7 @@ where
202206
203207 let Some ( tx) = self
204208 . tracked
205- . try_insert_tx ( event_tracker, tx)
209+ . try_insert_tx ( event_tracker, last_commit , tx)
206210 . unwrap_or_else ( |tx| {
207211 self . pending
208212 . try_insert_tx ( event_tracker, tx, last_commit_base_fee)
@@ -216,6 +220,7 @@ where
216220
217221 if !self . tracked . try_promote_pending (
218222 event_tracker,
223+ last_commit,
219224 block_policy,
220225 state_backend,
221226 & mut self . pending ,
@@ -235,8 +240,14 @@ where
235240 block_policy : & EthBlockPolicy < ST , SCT , CCT , CRT > ,
236241 state_backend : & SBT ,
237242 ) {
243+ let Some ( last_commit) = self . last_commit . as_ref ( ) else {
244+ warn ! ( "txpool promote_pending called before last committed block set" ) ;
245+ return ;
246+ } ;
247+
238248 if !self . tracked . try_promote_pending (
239249 event_tracker,
250+ last_commit,
240251 block_policy,
241252 state_backend,
242253 & mut self . pending ,
@@ -323,21 +334,42 @@ where
323334 . map ( |tx| tx. length ( ) as u64 )
324335 . sum ( ) ;
325336
326- let user_transactions = self . tracked . create_proposal (
327- event_tracker,
328- self . chain_id ,
329- proposed_seq_num,
330- base_fee,
331- tx_limit - system_transactions. len ( ) ,
332- proposal_gas_limit,
333- proposal_byte_limit - system_txs_size,
334- block_policy,
335- extending_blocks. iter ( ) . collect ( ) ,
336- state_backend,
337- chain_config,
338- & self . chain_revision ,
339- & self . execution_revision ,
340- ) ?;
337+ let user_transactions = if let Some ( last_commit) = self . last_commit . as_ref ( ) {
338+ let last_commit_seq_num = last_commit. seq_num ;
339+
340+ assert ! (
341+ block_policy. get_last_commit( ) . ge( & last_commit_seq_num) ,
342+ "txpool received block policy with lower committed seq num"
343+ ) ;
344+
345+ if last_commit_seq_num == block_policy. get_last_commit ( ) {
346+ self . tracked . create_proposal (
347+ event_tracker,
348+ self . chain_id ,
349+ proposed_seq_num,
350+ base_fee,
351+ tx_limit - system_transactions. len ( ) ,
352+ proposal_gas_limit,
353+ proposal_byte_limit - system_txs_size,
354+ block_policy,
355+ extending_blocks. iter ( ) . collect ( ) ,
356+ state_backend,
357+ chain_config,
358+ & self . chain_revision ,
359+ & self . execution_revision ,
360+ ) ?
361+ } else {
362+ error ! (
363+ block_policy_last_commit = block_policy. get_last_commit( ) . 0 ,
364+ txpool_last_commit = last_commit_seq_num. 0 ,
365+ "last commit update does not match block policy last commit"
366+ ) ;
367+ Vec :: default ( )
368+ }
369+ } else {
370+ error ! ( "txpool create_proposal called before last committed block set" ) ;
371+ Vec :: default ( )
372+ } ;
341373
342374 let body = EthBlockBody {
343375 transactions : system_transactions
@@ -423,13 +455,22 @@ where
423455 chain_config : & impl ChainConfig < CRT > ,
424456 committed_block : EthValidatedBlock < ST , SCT > ,
425457 ) {
426- let execution_revision = chain_config
427- . get_execution_chain_revision ( committed_block. header ( ) . execution_inputs . timestamp ) ;
458+ {
459+ let seqnum = committed_block. get_seq_num ( ) ;
460+ debug ! ( ?seqnum, "txpool updating committed block" ) ;
461+ }
428462
429- self . tracked
430- . update_committed_block ( event_tracker, committed_block, & mut self . pending ) ;
463+ if let Some ( last_commit) = self . last_commit . as_ref ( ) {
464+ assert_eq ! (
465+ committed_block. get_seq_num( ) ,
466+ last_commit. seq_num + SeqNum ( 1 ) ,
467+ "txpool received out of order committed block"
468+ ) ;
469+ }
470+ self . last_commit = Some ( committed_block. header ( ) . clone ( ) ) ;
431471
432- self . tracked . evict_expired_txs ( event_tracker) ;
472+ let execution_revision = chain_config
473+ . get_execution_chain_revision ( committed_block. header ( ) . execution_inputs . timestamp ) ;
433474
434475 if self . execution_revision != execution_revision {
435476 self . execution_revision = execution_revision;
@@ -438,6 +479,14 @@ where
438479 self . static_validate_all_txs ( event_tracker) ;
439480 }
440481
482+ self . tracked . update_committed_nonce_usages (
483+ event_tracker,
484+ committed_block. nonce_usages ,
485+ & mut self . pending ,
486+ ) ;
487+
488+ self . tracked . evict_expired_txs ( event_tracker) ;
489+
441490 self . update_aggregate_metrics ( event_tracker) ;
442491 }
443492
@@ -447,6 +496,10 @@ where
447496 chain_config : & impl ChainConfig < CRT > ,
448497 last_delay_committed_blocks : Vec < EthValidatedBlock < ST , SCT > > ,
449498 ) {
499+ self . last_commit = last_delay_committed_blocks
500+ . last ( )
501+ . map ( |block| block. header ( ) . clone ( ) ) ;
502+
450503 let execution_revision = chain_config. get_execution_chain_revision (
451504 last_delay_committed_blocks
452505 . last ( )
@@ -455,15 +508,15 @@ where
455508 } ) ,
456509 ) ;
457510
458- self . tracked . reset ( last_delay_committed_blocks) ;
459-
460511 if self . execution_revision != execution_revision {
461512 self . execution_revision = execution_revision;
462513 info ! ( execution_revision =? self . execution_revision, "updating execution revision" ) ;
463514
464515 self . static_validate_all_txs ( event_tracker) ;
465516 }
466517
518+ self . tracked . reset ( ) ;
519+
467520 self . update_aggregate_metrics ( event_tracker) ;
468521 }
469522
@@ -485,7 +538,7 @@ where
485538 pub fn get_forwardable_txs < const MIN_SEQNUM_DIFF : u64 , const MAX_RETRIES : usize > (
486539 & mut self ,
487540 ) -> Option < impl Iterator < Item = & TxEnvelope > > {
488- let last_commit = self . tracked . last_commit ( ) ?;
541+ let last_commit = self . last_commit . as_ref ( ) ?;
489542
490543 let last_commit_seq_num = last_commit. seq_num ;
491544 let last_commit_base_fee = last_commit. execution_inputs . base_fee_per_gas ;
0 commit comments