@@ -205,6 +205,7 @@ fd_txncache_insert_txn( fd_txncache_t * tc,
205205 ulong txnhash_offset = blockcache -> shmem -> txnhash_offset ;
206206 memcpy ( txnpage -> txns [ txn_idx ]-> txnhash , txnhash + txnhash_offset , 20UL );
207207 txnpage -> txns [ txn_idx ]-> fork_id = fork_id ;
208+ txnpage -> txns [ txn_idx ]-> generation = tc -> blockcache_pool [ fork_id .val ].shmem -> generation ;
208209 FD_COMPILER_MFENCE ();
209210
210211 ulong txn_bucket = FD_LOAD ( ulong , txnhash + txnhash_offset )%tc -> shmem -> txn_per_slot_max ;
@@ -231,6 +232,7 @@ fd_txncache_attach_child( fd_txncache_t * tc,
231232 blockcache_t * fork = & tc -> blockcache_pool [ idx ];
232233 fd_txncache_fork_id_t fork_id = { .val = (ushort )idx };
233234
235+ fork -> shmem -> generation = tc -> shmem -> blockcache_generation ++ ;
234236 fork -> shmem -> child_id = (fd_txncache_fork_id_t ){ .val = USHORT_MAX };
235237
236238 if ( FD_LIKELY ( parent_fork_id .val == USHORT_MAX ) ) {
@@ -390,6 +392,13 @@ blockhash_on_fork( fd_txncache_t * tc,
390392 return NULL ;
391393}
392394
395+ static void
396+ fd_txncache_purge_stale ( fd_txncache_t * tc ) {
397+ (void )tc ;
398+ FD_LOG_ERR (( "txncache full, purging stale transactions" ));
399+ // TODO: Implement eviction of any txn with generation!=fork->generation
400+ }
401+
393402void
394403fd_txncache_insert ( fd_txncache_t * tc ,
395404 fd_txncache_fork_id_t fork_id ,
@@ -408,7 +417,14 @@ fd_txncache_insert( fd_txncache_t * tc,
408417
409418 for (;;) {
410419 fd_txncache_txnpage_t * txnpage = fd_txncache_ensure_txnpage ( tc , blockcache );
411- FD_TEST ( txnpage );
420+ if ( FD_UNLIKELY ( !txnpage ) ) {
421+ /* Because of sizing invariants when creating the structure, it is
422+ not typically possible to fill it, unless there are stale
423+ transactions from minority forks that were purged floating
424+ around, in which case we can purge them here and try again. */
425+ fd_txncache_purge_stale ( tc );
426+ continue ;
427+ }
412428
413429 int success = fd_txncache_insert_txn ( tc , blockcache , txnpage , fork_id , txnhash );
414430 if ( FD_LIKELY ( success ) ) break ;
@@ -441,7 +457,7 @@ fd_txncache_query( fd_txncache_t * tc,
441457 for ( uint head = blockcache -> heads [ head_hash ]; head != UINT_MAX ; head = tc -> txnpages [ head /FD_TXNCACHE_TXNS_PER_PAGE ].txns [ head %FD_TXNCACHE_TXNS_PER_PAGE ]-> blockcache_next ) {
442458 fd_txncache_single_txn_t * txn = tc -> txnpages [ head /FD_TXNCACHE_TXNS_PER_PAGE ].txns [ head %FD_TXNCACHE_TXNS_PER_PAGE ];
443459
444- int descends = txn -> fork_id .val == fork_id .val || descends_set_test ( fork -> descends , txn -> fork_id .val );
460+ int descends = ( txn -> fork_id .val == fork_id .val || descends_set_test ( fork -> descends , txn -> fork_id .val )) && fork -> shmem -> generation == txn -> generation ;
445461 if ( FD_LIKELY ( descends && !memcmp ( txnhash + txnhash_offset , txn -> txnhash , 20UL ) ) ) {
446462 found = 1 ;
447463 break ;
0 commit comments