From 1f7aaa372e84f8318b1f4598cb574d7d10b7eb77 Mon Sep 17 00:00:00 2001 From: two-heart <12869538+two-heart@users.noreply.github.com> Date: Thu, 12 Dec 2024 22:50:34 +0100 Subject: [PATCH] scratch layout fixes --- src/app/fdctl/run/tiles/fd_dedup.c | 2 +- src/app/fdctl/run/tiles/fd_net.c | 2 +- src/app/fdctl/run/tiles/fd_replay.c | 46 +++++++++---------- src/app/fdctl/run/tiles/fd_store_int.c | 4 +- src/choreo/eqvoc/fd_eqvoc.c | 6 +-- src/disco/quic/fd_quic_tile.c | 8 ++-- src/disco/quic/fd_tpu_reasm.c | 8 ++-- src/disco/stem/fd_stem.c | 5 +- src/flamenco/gossip/fd_gossip.c | 4 +- .../runtime/tests/fd_exec_instr_test.c | 21 ++++++--- 10 files changed, 57 insertions(+), 49 deletions(-) diff --git a/src/app/fdctl/run/tiles/fd_dedup.c b/src/app/fdctl/run/tiles/fd_dedup.c index 3890d56c65..0f5019d011 100644 --- a/src/app/fdctl/run/tiles/fd_dedup.c +++ b/src/app/fdctl/run/tiles/fd_dedup.c @@ -242,7 +242,7 @@ unprivileged_init( fd_topo_t * topo, FD_SCRATCH_ALLOC_INIT( l, scratch ); fd_dedup_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof( fd_dedup_ctx_t ), sizeof( fd_dedup_ctx_t ) ); - fd_tcache_t * tcache = fd_tcache_join( fd_tcache_new( FD_SCRATCH_ALLOC_APPEND( l, FD_TCACHE_ALIGN, fd_tcache_footprint( tile->dedup.tcache_depth, 0) ), tile->dedup.tcache_depth, 0 ) ); + fd_tcache_t * tcache = fd_tcache_join( fd_tcache_new( FD_SCRATCH_ALLOC_APPEND( l, fd_tcache_align(), fd_tcache_footprint( tile->dedup.tcache_depth, 0) ), tile->dedup.tcache_depth, 0 ) ); if( FD_UNLIKELY( !tcache ) ) FD_LOG_ERR(( "fd_tcache_new failed" )); ctx->tcache_depth = fd_tcache_depth ( tcache ); diff --git a/src/app/fdctl/run/tiles/fd_net.c b/src/app/fdctl/run/tiles/fd_net.c index 7c437b9648..2e9135ed01 100644 --- a/src/app/fdctl/run/tiles/fd_net.c +++ b/src/app/fdctl/run/tiles/fd_net.c @@ -128,7 +128,7 @@ scratch_footprint( fd_topo_tile_t const * tile ) { l = FD_LAYOUT_APPEND( l, fd_xsk_align(), fd_xsk_footprint( FD_NET_MTU, tile->net.xdp_rx_queue_size, tile->net.xdp_rx_queue_size, tile->net.xdp_tx_queue_size, tile->net.xdp_tx_queue_size ) ); l = FD_LAYOUT_APPEND( l, fd_xsk_aio_align(), fd_xsk_aio_footprint( tile->net.xdp_tx_queue_size, tile->net.xdp_aio_depth ) ); } - l = FD_LAYOUT_APPEND( l, fd_ip_align(), fd_ip_footprint( 0U, 0U ) ); + l = FD_LAYOUT_APPEND( l, fd_ip_align(), fd_ip_footprint( 0UL, 0UL ) ); return FD_LAYOUT_FINI( l, scratch_align() ); } diff --git a/src/app/fdctl/run/tiles/fd_replay.c b/src/app/fdctl/run/tiles/fd_replay.c index cb90d63b32..901b4f1143 100644 --- a/src/app/fdctl/run/tiles/fd_replay.c +++ b/src/app/fdctl/run/tiles/fd_replay.c @@ -575,22 +575,22 @@ blockstore_publish( fd_replay_tile_ctx_t * ctx, ulong smr ) { } static void -txncache_publish( fd_replay_tile_ctx_t * ctx, +txncache_publish( fd_replay_tile_ctx_t * ctx, fd_funk_txn_t * txn_map, fd_funk_txn_t * root_txn, uchar is_funk_constipated ) { - - /* For the status cache, we stop rooting until the status cache has been + + /* For the status cache, we stop rooting until the status cache has been written out to the current snapshot. We also need to iterate up the funk transaction tree to figure out what slots should be constipated. As a note, when funk is constipated we don't want to iterate all the way up to the root because then we will register previously registered slots - that are in the constipated root. This introduces an edge case where - we will never register the slots that in the original constipated txn. + that are in the constipated root. This introduces an edge case where + we will never register the slots that in the original constipated txn. This currently gets handled in a hacky way by first tracking the first call to is_funk_constipated. This gets set to 1 as soon as funk gets - constipated. By setting this, we are able to register the slot that + constipated. By setting this, we are able to register the slot that corresponds to the constipated root. */ if( FD_UNLIKELY( !ctx->slot_ctx->status_cache ) ) { @@ -627,15 +627,15 @@ snapshot_state_update( fd_replay_tile_ctx_t * ctx, ulong smr, uchar is_constipat /* We are ready for a snapshot if either we are on or just passed a snapshot interval and no snapshot is currently in progress. This is to handle the - case where the snapshot interval falls on a skipped slot. - + case where the snapshot interval falls on a skipped slot. + We are ready to create a snapshot if: 1. The node is caught up to the network. 2. There is currently no snapshot in progress 3. The current slot is at the snapshot interval OR The current slot has passed a snapshot interval - If a snapshot is ready to be created we will constipate funk and the + If a snapshot is ready to be created we will constipate funk and the status cache. This will also notify the status cache via the funk constipation fseq. */ @@ -664,9 +664,9 @@ snapshot_state_update( fd_replay_tile_ctx_t * ctx, ulong smr, uchar is_constipat ulong updated_fseq = 0UL; - /* TODO: We need a better check if the smr fell on an epoch boundary due to + /* TODO: We need a better check if the smr fell on an epoch boundary due to skipped slots. We just don't want to make a snapshot on an epoch boundary */ - if( (is_full_snapshot_ready || is_inc_snapshot_ready) && + if( (is_full_snapshot_ready || is_inc_snapshot_ready) && !fd_runtime_is_epoch_boundary( epoch_bank, smr, smr-1UL ) ) { /* Constipate the status cache when a snapshot is ready to be created. */ if( is_full_snapshot_ready ) { @@ -688,11 +688,11 @@ funk_and_txncache_publish( fd_replay_tile_ctx_t * ctx, ulong smr ) { /* When we are trying to root for an smr that we want a snapshot for, we need to constipate funk as well as the txncache. The snapshot tile will notify - the replay tile that funk is ready to be unconstipated via the + the replay tile that funk is ready to be unconstipated via the is_funk_constipated fseq. Txncache constipation will be handled differently. All operations on the status cache are bounded by a rw lock making - operation atomic. The status cache will internally track if it is in a - constipated state. The snapshot tile will be directly responsible for + operation atomic. The status cache will internally track if it is in a + constipated state. The snapshot tile will be directly responsible for unconstipating the txncache. */ fd_blockstore_start_read( ctx->blockstore ); @@ -709,13 +709,13 @@ funk_and_txncache_publish( fd_replay_tile_ctx_t * ctx, ulong smr ) { /* Once all of the banking tiles have finished executing, grab a write lock on funk and publish the transaction. - + The publishing mechanism for funk and the status cache will change if constipation is enabled. If constipation is enabled, constipate the current transaction into the constipated root. This means we will treat the oldest ancestor as the new root of the transaction tree. All slots that are "rooted" in the constipated state will be published - into the constipated root. When constipation is disabled, flush the backed + into the constipated root. When constipation is disabled, flush the backed up transactions into the root. There is some unfortunate behavior we have to consider here with @@ -724,9 +724,9 @@ funk_and_txncache_publish( fd_replay_tile_ctx_t * ctx, ulong smr ) { corresponds to the constipated root. However, during the first pass when we are constipated, we also need to register the constipated root into the txn cache. If we don't then the constipated root slot will never be - included in the status cache. TODO: There is probably a better way to - hhandle this. - + included in the status cache. TODO: There is probably a better way to + hhandle this. + Constipation can be activated for a variety of reasons including snapshot creation and epoch account hash generation. TODO: Currently epoch account hash generation is unimplemented but the @@ -736,12 +736,12 @@ funk_and_txncache_publish( fd_replay_tile_ctx_t * ctx, ulong smr ) { fd_tpool_wait( ctx->tpool, i+1 ); } fd_funk_start_write( ctx->funk ); - + uchar is_funk_constipated = fd_fseq_query( ctx->is_funk_constipated ) != 0; txncache_publish( ctx, txn_map, root_txn, is_funk_constipated ); - /* Now try to publish into funk, this is handled differently based on if + /* Now try to publish into funk, this is handled differently based on if funk is constipated. */ if( !is_funk_constipated ) { @@ -751,11 +751,11 @@ funk_and_txncache_publish( fd_replay_tile_ctx_t * ctx, ulong smr ) { if( FD_UNLIKELY( !rc ) ) { FD_LOG_ERR(( "failed to funk publish slot %lu", smr )); } - + } else { FD_LOG_WARNING(( "Publishing slot=%lu while constipated", smr )); - /* At this point, first collapse the current transaction that should be + /* At this point, first collapse the current transaction that should be published into the oldest child transaction. */ fd_funk_txn_t * txn = root_txn; diff --git a/src/app/fdctl/run/tiles/fd_store_int.c b/src/app/fdctl/run/tiles/fd_store_int.c index eaa273adbb..7dacbb3681 100644 --- a/src/app/fdctl/run/tiles/fd_store_int.c +++ b/src/app/fdctl/run/tiles/fd_store_int.c @@ -546,7 +546,7 @@ privileged_init( fd_topo_t * topo, FD_SCRATCH_ALLOC_INIT( l, scratch ); fd_store_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_store_tile_ctx_t), sizeof(fd_store_tile_ctx_t) ); - FD_SCRATCH_ALLOC_FINI( l, sizeof(fd_store_tile_ctx_t) ); + FD_SCRATCH_ALLOC_FINI( l, scratch_align() ); if( FD_UNLIKELY( !strcmp( tile->store_int.identity_key_path, "" ) ) ) FD_LOG_ERR(( "identity_key_path not set" )); @@ -777,7 +777,7 @@ populate_allowed_seccomp( fd_topo_t const * topo, void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id ); FD_SCRATCH_ALLOC_INIT( l, scratch ); fd_store_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_store_tile_ctx_t), sizeof(fd_store_tile_ctx_t) ); - FD_SCRATCH_ALLOC_FINI( l, alignof(fd_store_tile_ctx_t) ); + FD_SCRATCH_ALLOC_FINI( l, scratch_align() ); populate_sock_filter_policy_store_int( out_cnt, out, (uint)fd_log_private_logfile_fd(), (uint)ctx->blockstore_fd ); return sock_filter_policy_store_int_instr_cnt; diff --git a/src/choreo/eqvoc/fd_eqvoc.c b/src/choreo/eqvoc/fd_eqvoc.c index a0e7bff2bd..956fd26231 100644 --- a/src/choreo/eqvoc/fd_eqvoc.c +++ b/src/choreo/eqvoc/fd_eqvoc.c @@ -51,9 +51,9 @@ fd_eqvoc_join( void * sheqvoc ) { } FD_SCRATCH_ALLOC_INIT( l, sheqvoc ); - fd_eqvoc_t * eqvoc = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_eqvoc_t), sizeof(fd_eqvoc_t) ); - void * fec_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_eqvoc_fec_pool_align(), fd_eqvoc_fec_pool_footprint( eqvoc->fec_max ) ); - void * fec_map = FD_SCRATCH_ALLOC_APPEND( l, fd_eqvoc_fec_map_align(), fd_eqvoc_fec_map_footprint( eqvoc->fec_max ) ); + fd_eqvoc_t * eqvoc = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_eqvoc_t), sizeof(fd_eqvoc_t) ); + void * fec_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_eqvoc_fec_pool_align(), fd_eqvoc_fec_pool_footprint( eqvoc->fec_max ) ); + void * fec_map = FD_SCRATCH_ALLOC_APPEND( l, fd_eqvoc_fec_map_align(), fd_eqvoc_fec_map_footprint( eqvoc->fec_max ) ); void * proof_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_eqvoc_proof_pool_align(), fd_eqvoc_proof_pool_footprint( eqvoc->proof_max ) ); void * proof_map = FD_SCRATCH_ALLOC_APPEND( l, fd_eqvoc_proof_map_align(), fd_eqvoc_proof_map_footprint( eqvoc->proof_max ) ); void * sha512 = FD_SCRATCH_ALLOC_APPEND( l, fd_sha512_align(), fd_sha512_footprint() ); diff --git a/src/disco/quic/fd_quic_tile.c b/src/disco/quic/fd_quic_tile.c index d9ffdd1b38..cd3a898b26 100644 --- a/src/disco/quic/fd_quic_tile.c +++ b/src/disco/quic/fd_quic_tile.c @@ -52,14 +52,14 @@ scratch_align( void ) { FD_FN_PURE static inline ulong scratch_footprint( fd_topo_tile_t const * tile ) { - ulong depth = tile->quic.out_depth; + ulong out_depth = tile->quic.out_depth; ulong reasm_max = tile->quic.reasm_cnt; fd_quic_limits_t limits = quic_limits( tile ); /* May FD_LOG_ERR */ ulong l = FD_LAYOUT_INIT; - l = FD_LAYOUT_APPEND( l, alignof( fd_quic_ctx_t ), sizeof( fd_quic_ctx_t ) ); - l = FD_LAYOUT_APPEND( l, fd_quic_align(), fd_quic_footprint( &limits ) ); - l = FD_LAYOUT_APPEND( l, fd_tpu_reasm_align(), fd_tpu_reasm_footprint( depth, reasm_max ) ); + l = FD_LAYOUT_APPEND( l, alignof( fd_quic_ctx_t ), sizeof( fd_quic_ctx_t ) ); + l = FD_LAYOUT_APPEND( l, fd_quic_align(), fd_quic_footprint( &limits ) ); + l = FD_LAYOUT_APPEND( l, fd_tpu_reasm_align(), fd_tpu_reasm_footprint( out_depth, reasm_max ) ); return FD_LAYOUT_FINI( l, scratch_align() ); } diff --git a/src/disco/quic/fd_tpu_reasm.c b/src/disco/quic/fd_tpu_reasm.c index ae8b7dbe76..5788e0d3f2 100644 --- a/src/disco/quic/fd_tpu_reasm.c +++ b/src/disco/quic/fd_tpu_reasm.c @@ -20,11 +20,11 @@ fd_tpu_reasm_footprint( ulong depth, ulong slot_cnt = depth+burst; ulong chain_cnt = fd_tpu_reasm_map_chain_cnt_est( slot_cnt ); return FD_LAYOUT_FINI( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_INIT, - FD_TPU_REASM_ALIGN, sizeof(fd_tpu_reasm_t) ), /* hdr */ + fd_tpu_reasm_align(), sizeof(fd_tpu_reasm_t) ), /* hdr */ alignof(uint), depth *sizeof(uint) ), /* pub_slots */ alignof(fd_tpu_reasm_slot_t), slot_cnt*sizeof(fd_tpu_reasm_slot_t) ), /* slots */ fd_tpu_reasm_map_align(), fd_tpu_reasm_map_footprint( chain_cnt ) ), /* map */ - FD_TPU_REASM_ALIGN ); + fd_tpu_reasm_align() ); } @@ -53,11 +53,11 @@ fd_tpu_reasm_new( void * shmem, ulong chain_cnt = fd_tpu_reasm_map_chain_cnt_est( slot_cnt ); FD_SCRATCH_ALLOC_INIT( l, shmem ); - fd_tpu_reasm_t * reasm = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_tpu_reasm_t), sizeof(fd_tpu_reasm_t) ); + fd_tpu_reasm_t * reasm = FD_SCRATCH_ALLOC_APPEND( l, fd_tpu_reasm_align(), sizeof(fd_tpu_reasm_t) ); ulong * pub_slots = FD_SCRATCH_ALLOC_APPEND( l, alignof(uint), depth*sizeof(uint) ); fd_tpu_reasm_slot_t * slots = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_tpu_reasm_slot_t), slot_cnt*sizeof(fd_tpu_reasm_slot_t) ); void * map_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_tpu_reasm_map_align(), fd_tpu_reasm_map_footprint( chain_cnt ) ); - FD_SCRATCH_ALLOC_FINI( l, alignof(fd_tpu_reasm_t) ); + FD_SCRATCH_ALLOC_FINI( l, fd_tpu_reasm_align() ); fd_memset( reasm, 0, sizeof(fd_tpu_reasm_t) ); fd_memset( slots, 0, burst*sizeof(fd_tpu_reasm_slot_t) ); diff --git a/src/disco/stem/fd_stem.c b/src/disco/stem/fd_stem.c index b72888790e..a4b1360211 100644 --- a/src/disco/stem/fd_stem.c +++ b/src/disco/stem/fd_stem.c @@ -191,7 +191,8 @@ STEM_(scratch_footprint)( ulong in_cnt, l = FD_LAYOUT_APPEND( l, alignof(ulong *), cons_cnt*sizeof(ulong *) ); /* cons_slow */ l = FD_LAYOUT_APPEND( l, alignof(ulong), cons_cnt*sizeof(ulong) ); /* cons_out */ l = FD_LAYOUT_APPEND( l, alignof(ulong), cons_cnt*sizeof(ulong) ); /* cons_seq */ - l = FD_LAYOUT_APPEND( l, alignof(ushort), (in_cnt+cons_cnt+1UL)*sizeof(ushort) ); /* event_map */ + const ulong event_cnt = in_cnt + 1UL + cons_cnt; + l = FD_LAYOUT_APPEND( l, alignof(ushort), event_cnt*sizeof(ushort) ); /* event_map */ return FD_LAYOUT_FINI( l, STEM_(scratch_align)() ); } @@ -301,7 +302,7 @@ STEM_(run1)( ulong in_cnt, cons_fseq = (ulong const **)FD_SCRATCH_ALLOC_APPEND( l, alignof(ulong const *), cons_cnt*sizeof(ulong const *) ); cons_slow = (ulong **) FD_SCRATCH_ALLOC_APPEND( l, alignof(ulong *), cons_cnt*sizeof(ulong *) ); - cons_out = (ulong *) FD_SCRATCH_ALLOC_APPEND( l, alignof(ulong), cons_cnt*sizeof(ulong *) ); + cons_out = (ulong *) FD_SCRATCH_ALLOC_APPEND( l, alignof(ulong), cons_cnt*sizeof(ulong) ); cons_seq = (ulong *) FD_SCRATCH_ALLOC_APPEND( l, alignof(ulong), cons_cnt*sizeof(ulong) ); if( FD_UNLIKELY( !!cons_cnt && !_cons_fseq ) ) FD_LOG_ERR(( "NULL cons_fseq" )); diff --git a/src/flamenco/gossip/fd_gossip.c b/src/flamenco/gossip/fd_gossip.c index e9adca5fc3..fb7197fc29 100644 --- a/src/flamenco/gossip/fd_gossip.c +++ b/src/flamenco/gossip/fd_gossip.c @@ -354,7 +354,7 @@ fd_gossip_footprint( void ) { l = FD_LAYOUT_APPEND( l, fd_stats_table_align(), fd_stats_table_footprint(FD_STATS_KEY_MAX) ); l = FD_LAYOUT_APPEND( l, fd_weights_table_align(), fd_weights_table_footprint(MAX_STAKE_WEIGHTS) ); l = FD_LAYOUT_APPEND( l, fd_push_states_pool_align(), fd_push_states_pool_footprint(FD_PUSH_LIST_MAX) ); - l = FD_LAYOUT_FINI(l, fd_gossip_align()); + l = FD_LAYOUT_FINI( l, fd_gossip_align() ); return l; } @@ -394,7 +394,7 @@ fd_gossip_new ( void * shmem, ulong seed ) { shm = FD_SCRATCH_ALLOC_APPEND(l, fd_push_states_pool_align(), fd_push_states_pool_footprint(FD_PUSH_LIST_MAX)); glob->push_states_pool = fd_push_states_pool_join( fd_push_states_pool_new( shm, FD_PUSH_LIST_MAX ) ); - ulong scratch_top = FD_SCRATCH_ALLOC_FINI(l, 1UL); + ulong scratch_top = FD_SCRATCH_ALLOC_FINI( l, fd_gossip_align() ); if ( scratch_top > (ulong)shmem + fd_gossip_footprint() ) { FD_LOG_ERR(("Not enough space allocated for gossip")); } diff --git a/src/flamenco/runtime/tests/fd_exec_instr_test.c b/src/flamenco/runtime/tests/fd_exec_instr_test.c index 783485bb90..8b8014a706 100644 --- a/src/flamenco/runtime/tests/fd_exec_instr_test.c +++ b/src/flamenco/runtime/tests/fd_exec_instr_test.c @@ -75,9 +75,9 @@ fd_exec_instr_test_runner_align( void ) { ulong fd_exec_instr_test_runner_footprint( void ) { ulong l = FD_LAYOUT_INIT; - l = FD_LAYOUT_APPEND( l, alignof(fd_exec_instr_test_runner_t), sizeof(fd_exec_instr_test_runner_t) ); - l = FD_LAYOUT_APPEND( l, fd_funk_align(), fd_funk_footprint() ); - return l; + l = FD_LAYOUT_APPEND( l, fd_exec_instr_test_runner_align(), sizeof(fd_exec_instr_test_runner_t) ); + l = FD_LAYOUT_APPEND( l, fd_funk_align(), fd_funk_footprint() ); + return FD_LAYOUT_FINI( l, fd_exec_instr_test_runner_align() ); } fd_exec_instr_test_runner_t * @@ -85,9 +85,9 @@ fd_exec_instr_test_runner_new( void * mem, void * spad_mem, ulong wksp_tag ) { FD_SCRATCH_ALLOC_INIT( l, mem ); - void * runner_mem = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_instr_test_runner_t), sizeof(fd_exec_instr_test_runner_t) ); - void * funk_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_funk_align(), fd_funk_footprint() ); - FD_SCRATCH_ALLOC_FINI( l, alignof(fd_exec_instr_test_runner_t) ); + void * runner_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_exec_instr_test_runner_align(), sizeof(fd_exec_instr_test_runner_t) ); + void * funk_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_funk_align(), fd_funk_footprint() ); + FD_SCRATCH_ALLOC_FINI( l, fd_exec_instr_test_runner_align() ); ulong txn_max = 4+fd_tile_cnt(); ulong rec_max = 1024UL; @@ -670,7 +670,7 @@ _txn_context_create_and_exec( fd_exec_instr_test_runner_t * runner, epoch_bank->rent = *slot_ctx->sysvar_cache->val_rent; } - /* Provde default slot hashes of size 1 if not provided */ + /* Provide default slot hashes of size 1 if not provided */ if( !slot_ctx->sysvar_cache->has_slot_hashes ) { fd_slot_hash_t * slot_hashes = deq_fd_slot_hash_t_alloc( fd_scratch_virtual(), 1 ); fd_slot_hash_t * dummy_elem = deq_fd_slot_hash_t_push_tail_nocopy( slot_hashes ); @@ -1678,6 +1678,13 @@ fd_exec_vm_syscall_test_run( fd_exec_instr_test_runner_t * runner, ctx->txn_ctx->instr_trace[0].instr_info = (fd_instr_info_t *)ctx->instr; ctx->txn_ctx->instr_trace[0].stack_height = 1; + if (is_cpi) { + ctx->txn_ctx->instr_info_cnt = 1; + } + + ctx->txn_ctx->instr_trace[0].instr_info = (fd_instr_info_t *)ctx->instr; + ctx->txn_ctx->instr_trace[0].stack_height = 1; + /* Capture outputs */ ulong output_end = (ulong)output_buf + output_bufsz; FD_SCRATCH_ALLOC_INIT( l, output_buf );