diff --git a/src/disco/gui/fd_gui.c b/src/disco/gui/fd_gui.c index 7ed440baec..65d9899e5c 100644 --- a/src/disco/gui/fd_gui.c +++ b/src/disco/gui/fd_gui.c @@ -1732,6 +1732,7 @@ fd_gui_microblock_execution_begin( fd_gui_t * gui, txn_entry->flags |= (uchar)FD_GUI_TXN_FLAGS_STARTED; txn_entry->flags |= (uchar)fd_uint_if(txn_payload->flags & FD_TXN_P_FLAGS_IS_SIMPLE_VOTE, FD_GUI_TXN_FLAGS_IS_SIMPLE_VOTE, 0U); txn_entry->flags |= (uchar)fd_uint_if((txn_payload->flags & FD_TXN_P_FLAGS_BUNDLE) || (txn_payload->flags & FD_TXN_P_FLAGS_INITIALIZER_BUNDLE), FD_GUI_TXN_FLAGS_FROM_BUNDLE, 0U); + txn_entry->flags |= (uchar)fd_uint_if(txn_payload->flags & FD_TXN_P_FLAGS_SCHEDULED_WHILE_LEADER, FD_GUI_TXN_FLAGS_SCHEDULED_WHILE_LEADER, 0U); } /* At the moment, bank publishes at most 1 transaction per microblock, diff --git a/src/disco/gui/fd_gui.h b/src/disco/gui/fd_gui.h index bb6412d69f..204cd0266b 100644 --- a/src/disco/gui/fd_gui.h +++ b/src/disco/gui/fd_gui.h @@ -58,6 +58,7 @@ #define FD_GUI_TXN_FLAGS_IS_SIMPLE_VOTE ( 4U) #define FD_GUI_TXN_FLAGS_FROM_BUNDLE ( 8U) #define FD_GUI_TXN_FLAGS_LANDED_IN_BLOCK (16U) +#define FD_GUI_TXN_FLAGS_SCHEDULED_WHILE_LEADER (32U) struct fd_gui_gossip_peer { fd_pubkey_t pubkey[ 1 ]; diff --git a/src/disco/gui/fd_gui_printf.c b/src/disco/gui/fd_gui_printf.c index 51d2e3388e..f7c5a9117d 100644 --- a/src/disco/gui/fd_gui_printf.c +++ b/src/disco/gui/fd_gui_printf.c @@ -1267,6 +1267,9 @@ fd_gui_printf_slot_transactions_request( fd_gui_t * gui, jsonp_open_array( gui, "txn_landed" ); for( ulong i=0UL; itxs[ (slot->txs.start_offset + i)%FD_GUI_TXN_HISTORY_SZ ]->flags & FD_GUI_TXN_FLAGS_LANDED_IN_BLOCK ); jsonp_close_array( gui ); + jsonp_open_array( gui, "txn_arrived_in_slot" ); + for( ulong i=0UL; itxs[ (slot->txs.start_offset + i)%FD_GUI_TXN_HISTORY_SZ ]->flags & FD_GUI_TXN_FLAGS_SCHEDULED_WHILE_LEADER ); + jsonp_close_array( gui ); jsonp_close_object( gui ); } else { jsonp_null( gui, "compute_units" ); diff --git a/src/disco/pack/fd_pack.c b/src/disco/pack/fd_pack.c index 8b98b01b8a..0317d8d67b 100644 --- a/src/disco/pack/fd_pack.c +++ b/src/disco/pack/fd_pack.c @@ -51,6 +51,12 @@ struct fd_pack_private_ord_txn { expiration priority queue. */ ulong expq_idx; + /* arrival_slot: The slot during which this transaction first arrived + to pack, if this validator was a leader at the time. Otherwise, + this is ULONG_MAX. This is used by monitoring tools to gauge if a + transaction.arrived in the same slot it was scheduled. */ + ulong arrival_leader_slot; + /* We want rewards*compute_est to fit in a ulong so that r1/c1 < r2/c2 can be computed as r1*c2 < r2*c1, with the product fitting in a ulong. compute_est has a small natural limit of mid-20 bits. rewards doesn't have @@ -551,6 +557,7 @@ struct fd_pack_private { /* compressed_slot_number: a number in (FD_PACK_SKIP_CNT, USHORT_MAX] that advances each time we start packing for a new slot. */ ushort compressed_slot_number; + ulong leader_slot; /* bitset_avail: a stack of which bits are not currently reserved and can be used to represent an account address. @@ -1149,9 +1156,11 @@ populate_bitsets( fd_pack_t * pack, int fd_pack_insert_txn_fini( fd_pack_t * pack, fd_txn_e_t * txne, + ulong leader_slot, ulong expires_at ) { fd_pack_ord_txn_t * ord = (fd_pack_ord_txn_t *)txne; + ord->arrival_leader_slot = leader_slot; fd_txn_t * txn = TXN(txne->txnp); uchar * payload = txne->txnp->payload; @@ -1626,6 +1635,7 @@ fd_pack_schedule_impl( fd_pack_t * pack, # endif fd_pack_ord_txn_t * cur = treap_rev_iter_ele( _cur, pool ); + cur->txn->flags &= fd_uint_if(cur->arrival_leader_slot == pack->leader_slot, cur->txn->flags | FD_TXN_P_FLAGS_SCHEDULED_WHILE_LEADER, cur->txn->flags & ~(FD_TXN_P_FLAGS_SCHEDULED_WHILE_LEADER)); min_cus = fd_ulong_min( min_cus, cur->compute_est ); min_bytes = fd_ulong_min( min_bytes, cur->txn->payload_sz ); @@ -2044,6 +2054,8 @@ fd_pack_try_schedule_bundle( fd_pack_t * pack, while( !(doesnt_fit | has_conflict) & !treap_rev_iter_done( _cur ) ) { fd_pack_ord_txn_t * cur = treap_rev_iter_ele( _cur, pool ); + cur->txn->flags &= fd_uint_if(cur->arrival_leader_slot == pack->leader_slot, cur->txn->flags | FD_TXN_P_FLAGS_SCHEDULED_WHILE_LEADER, cur->txn->flags & ~(FD_TXN_P_FLAGS_SCHEDULED_WHILE_LEADER)); + ulong this_bundle_idx = RC_TO_REL_BUNDLE_IDX( cur->rewards, cur->compute_est ); if( FD_UNLIKELY( this_bundle_idx!=bundle_idx ) ) break; @@ -2403,6 +2415,11 @@ fd_pack_expire_before( fd_pack_t * pack, return deleted_cnt; } +void +fd_pack_start_block( fd_pack_t * pack, ulong leader_slot ) { + pack->leader_slot = leader_slot; +} + void fd_pack_end_block( fd_pack_t * pack ) { /* rounded division */ @@ -2412,6 +2429,7 @@ fd_pack_end_block( fd_pack_t * pack ) { fd_histf_sample( pack->rebated_cus_per_block, pack->cumulative_rebated_cus ); fd_histf_sample( pack->scheduled_cus_per_block, pack->cumulative_rebated_cus + pack->cumulative_block_cost ); + pack->leader_slot = ULONG_MAX; pack->microblock_cnt = 0UL; pack->data_bytes_consumed = 0UL; pack->cumulative_block_cost = 0UL; @@ -2493,6 +2511,7 @@ release_tree( treap_t * treap, void fd_pack_clear_all( fd_pack_t * pack ) { pack->pending_txn_cnt = 0UL; + pack->leader_slot = ULONG_MAX; pack->microblock_cnt = 0UL; pack->cumulative_block_cost = 0UL; pack->cumulative_vote_cost = 0UL; diff --git a/src/disco/pack/fd_pack.h b/src/disco/pack/fd_pack.h index c9569d1c7c..7c73dd42d6 100644 --- a/src/disco/pack/fd_pack.h +++ b/src/disco/pack/fd_pack.h @@ -70,12 +70,13 @@ /* ---- End consensus-critical constants */ -#define FD_TXN_P_FLAGS_IS_SIMPLE_VOTE ( 1U) -#define FD_TXN_P_FLAGS_BUNDLE ( 2U) -#define FD_TXN_P_FLAGS_INITIALIZER_BUNDLE ( 4U) -#define FD_TXN_P_FLAGS_SANITIZE_SUCCESS ( 8U) -#define FD_TXN_P_FLAGS_EXECUTE_SUCCESS (16U) -#define FD_TXN_P_FLAGS_FEES_ONLY (32U) +#define FD_TXN_P_FLAGS_IS_SIMPLE_VOTE ( 1U) +#define FD_TXN_P_FLAGS_BUNDLE ( 2U) +#define FD_TXN_P_FLAGS_INITIALIZER_BUNDLE ( 4U) +#define FD_TXN_P_FLAGS_SANITIZE_SUCCESS ( 8U) +#define FD_TXN_P_FLAGS_EXECUTE_SUCCESS (16U) +#define FD_TXN_P_FLAGS_FEES_ONLY (32U) +#define FD_TXN_P_FLAGS_SCHEDULED_WHILE_LEADER (64U) #define FD_TXN_P_FLAGS_RESULT_MASK (0xFF000000U) @@ -346,9 +347,9 @@ FD_STATIC_ASSERT( FD_PACK_INSERT_ACCEPT_VOTE_REPLACEtxnp->blockhash_slot; long insert_duration = -fd_tickcount(); - int result = fd_pack_insert_txn_fini( ctx->pack, spot, blockhash_slot ); + int result = fd_pack_insert_txn_fini( ctx->pack, spot, ctx->leader_slot, blockhash_slot ); insert_duration += fd_tickcount(); ctx->insert_result[ result + FD_PACK_INSERT_RETVAL_OFF ]++; fd_histf_sample( ctx->insert_duration, (ulong)insert_duration ); @@ -972,7 +972,7 @@ after_frag( fd_pack_ctx_t * ctx, } else { ulong blockhash_slot = sig; long insert_duration = -fd_tickcount(); - int result = fd_pack_insert_txn_fini( ctx->pack, ctx->cur_spot, blockhash_slot ); + int result = fd_pack_insert_txn_fini( ctx->pack, ctx->cur_spot, ctx->leader_slot, blockhash_slot ); insert_duration += fd_tickcount(); ctx->insert_result[ result + FD_PACK_INSERT_RETVAL_OFF ]++; fd_histf_sample( ctx->insert_duration, (ulong)insert_duration ); diff --git a/src/disco/pack/test_pack.c b/src/disco/pack/test_pack.c index 3bc059deb3..960072fe44 100644 --- a/src/disco/pack/test_pack.c +++ b/src/disco/pack/test_pack.c @@ -224,7 +224,7 @@ insert( ulong i, fd_memcpy( slot->txnp->payload, payload_scratch[ i ], payload_sz[ i ] ); fd_memcpy( TXN(slot->txnp), txn, fd_txn_footprint( txn->instr_cnt, txn->addr_table_lookup_cnt ) ); - return fd_pack_insert_txn_fini( pack, slot, i ); + return fd_pack_insert_txn_fini( pack, slot, 0UL, i ); } static void @@ -588,7 +588,7 @@ performance_test2( void ) { fd_memcpy( slot->txnp->payload, payload_scratch[ i ], payload_sz[ i ] ); fd_memcpy( TXN(slot->txnp), txn, fd_txn_footprint( txn->instr_cnt, txn->addr_table_lookup_cnt ) ); - fd_pack_insert_txn_fini( pack, slot, 0UL ); + fd_pack_insert_txn_fini( pack, slot, 0UL, 0UL ); } ulong scheduled = 0UL; for( ulong i=0UL; i<1024UL/MAX_TXN_PER_MICROBLOCK+1UL; i++ ) { @@ -677,7 +677,7 @@ void performance_test( int extra_bench ) { fd_memcpy( slot->txnp->payload, payload_scratch[ j&1 ], payload_sz[ j&1 ] ); fd_memcpy( TXN(slot->txnp), txn, fd_txn_footprint( txn->instr_cnt, txn->addr_table_lookup_cnt ) ); - fd_pack_insert_txn_fini( pack, slot, 0UL ); + fd_pack_insert_txn_fini( pack, slot, 0UL, 0UL ); } if( FD_LIKELY( iter>=WARMUP ) ) insert += fd_log_wallclock( ); @@ -722,7 +722,7 @@ void performance_test( int extra_bench ) { fd_memcpy( slot->txnp->payload, payload_scratch[ j&1 ], payload_sz[ j&1 ] ); fd_memcpy( TXN(slot->txnp), txn, fd_txn_footprint( txn->instr_cnt, txn->addr_table_lookup_cnt ) ); - fd_pack_insert_txn_fini( pack, slot, 0UL ); + fd_pack_insert_txn_fini( pack, slot, 0UL, 0UL ); } FD_TEST( fd_pack_avail_txn_cnt( pack )==heap_sz ); @@ -750,7 +750,7 @@ void performance_test( int extra_bench ) { fd_memcpy( slot->txnp->payload, payload_scratch[ j&1 ], payload_sz[ j&1 ] ); fd_memcpy( TXN(slot->txnp), txn, fd_txn_footprint( txn->instr_cnt, txn->addr_table_lookup_cnt ) ); - fd_pack_insert_txn_fini( pack, slot, 0UL ); + fd_pack_insert_txn_fini( pack, slot, 0UL, 0UL ); } FD_TEST( fd_pack_avail_txn_cnt( pack )==heap_sz ); @@ -823,7 +823,7 @@ void performance_end_block( void ) { fd_memcpy( slot->txnp->payload, payload_scratch[ 0UL ], payload_sz[ 0UL ] ); fd_memcpy( TXN(slot->txnp), txn, fd_txn_footprint( txn->instr_cnt, txn->addr_table_lookup_cnt ) ); - fd_pack_insert_txn_fini( pack, slot, 0UL ); + fd_pack_insert_txn_fini( pack, slot, 0UL, 0UL ); } while( fd_pack_avail_txn_cnt( pack )>0UL ) { FD_TEST( fd_pack_schedule_next_microblock( pack, 5000000UL, 0.0f, 0UL, ALL, outcome.results ) ); @@ -856,7 +856,7 @@ void heap_overflow_test( void ) { fd_memcpy( slot->txnp->payload, payload_scratch[ j ], payload_sz[ j ] ); fd_memcpy( TXN(slot->txnp), txn, fd_txn_footprint( txn->instr_cnt, txn->addr_table_lookup_cnt ) ); - fd_pack_insert_txn_fini( pack, slot, 0UL ); + fd_pack_insert_txn_fini( pack, slot, 0UL, 0UL ); } FD_TEST( fd_pack_avail_txn_cnt( pack )==1024UL ); @@ -872,7 +872,7 @@ void heap_overflow_test( void ) { fd_memcpy( slot->txnp->payload, payload_scratch[ j ], payload_sz[ j ] ); fd_memcpy( TXN(slot->txnp), txn, fd_txn_footprint( txn->instr_cnt, txn->addr_table_lookup_cnt ) ); - fd_pack_insert_txn_fini( pack, slot, 0UL ); + fd_pack_insert_txn_fini( pack, slot, 0UL, 0UL ); } FD_TEST( fd_pack_avail_txn_cnt( pack )==1024UL );