LCOV - code coverage report
Current view: top level - discof/backup - fd_ssmanifest_encoder.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 319 330 96.7 %
Date: 2026-11-12 04:25:03 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /* Serialize a chunk of values.
       2             :    Each call may only produce up to FD_SSMANIFEST_BUF_MIN bytes worth of
       3             :    serialized data.  Therefore, we split the serializer into multiple
       4             :    states. */
       5             : 
       6        1296 : ENCODE_FN {
       7        1296 :   fd_bank_t const * bank = enc->bank;
       8             : 
       9        1296 :   PREP
      10             : 
      11        1296 :   switch( enc->state ) {
      12          24 :   case STATE_BLOCKHASH_QUEUE: {
      13          12 :     fd_blockhashes_t const *    bhq   = &bank->f.block_hash_queue;
      14          12 :     fd_blockhash_info_t const * deq   = bhq->d.deque;
      15          12 :     ulong                       total = fd_blockhash_deq_cnt( deq );
      16             : 
      17             :     /* Write the newest FD_BLOCKHASHES_MAX entries by count, each at its
      18             :        own absolute hash_index. with skipped indices it can keep an
      19             :        entry older than max_age. */
      20          24 :     ulong cnt     = fd_ulong_min( total, FD_BLOCKHASHES_MAX );
      21          12 :     ulong to_skip = total - cnt;
      22             : 
      23          12 :     fd_blockhash_info_t const * last = fd_blockhashes_peek_last( bhq );
      24          24 :     PUSH_VAL( ulong, last ? last->hash_index : 0UL ); /* last hash index */
      25          24 :     PUSH_VAL( uchar, !!last );
      26          24 :     if( last ) PUSH_VAL( fd_hash_t, last->hash );
      27             : 
      28          24 :     PUSH_VAL( ulong, cnt );
      29         120 :     for( ulong i=to_skip; i<total; i++ ) {
      30          96 :       fd_blockhash_info_t const * ele = fd_blockhash_deq_peek_index_const( deq, i );
      31          96 :       PUSH_VAL( fd_hash_t, ele->hash );
      32          96 :       PUSH_VAL( ulong,     ele->lamports_per_signature );
      33          96 :       PUSH_VAL( ulong,     ele->hash_index );
      34          96 :       PUSH_VAL( ulong,     0UL ); /* timestamp, ignored */
      35          48 :     }
      36          24 :     PUSH_VAL( ulong, FD_BLOCKHASHES_MAX-1UL ); /* max_age */
      37          24 :     enc->state = STATE_HASHES;
      38          12 :     break;
      39          12 :   }
      40          24 :   case STATE_HASHES: {
      41          24 :     PUSH_VAL( ulong,     0UL ); /* ancestors */
      42          24 :     PUSH_VAL( fd_hash_t, bank->f.bank_hash      );
      43          24 :     PUSH_VAL( fd_hash_t, bank->f.prev_bank_hash );
      44          24 :     PUSH_VAL( ulong,     bank->f.parent_slot    );
      45          24 :     enc->state = STATE_HARD_FORKS;
      46          12 :     break;
      47          12 :   }
      48          24 :   case STATE_HARD_FORKS: {
      49          24 :     PUSH_VAL( ulong, bank->f.hard_fork_cnt );
      50          24 :     for( ulong i=0UL; i<bank->f.hard_fork_cnt; i++ ) {
      51           0 :       PUSH_VAL( ulong, bank->f.hard_forks[ i ].slot );
      52           0 :       PUSH_VAL( ulong, bank->f.hard_forks[ i ].cnt  );
      53           0 :     }
      54          24 :     enc->state = STATE_COUNTERS;
      55          12 :     break;
      56          12 :   }
      57          24 :   case STATE_COUNTERS: {
      58          24 :     PUSH_VAL( ulong,  bank->f.parent_txn_count + bank->f.txn_count                );
      59          24 :     PUSH_VAL( ulong,  bank->f.max_tick_height                                     );
      60          24 :     PUSH_VAL( ulong,  bank->f.signature_count                                     );
      61          24 :     PUSH_VAL( ulong,  bank->f.capitalization                                      );
      62          24 :     PUSH_VAL( ulong,  bank->f.max_tick_height                                     );
      63          24 :     PUSH_VAL( uchar,  0 ); /* hashes_per_tick: None */
      64          24 :     PUSH_VAL( ulong,  bank->f.ticks_per_slot                                      );
      65          24 :     PUSH_VAL( fd_w_u128_t, (fd_w_u128_t){ .ud = bank->f.slot_params.ns_per_slot } );
      66          24 :     PUSH_VAL( ulong,  bank->f.genesis_creation_time                               );
      67          24 :     PUSH_VAL( double, bank->f.slot_params.slots_per_year                          );
      68          24 :     PUSH_VAL( ulong,  0UL ); /* accounts_data_len, unused */
      69          24 :     PUSH_VAL( ulong,  bank->f.slot                                                );
      70          24 :     PUSH_VAL( ulong,  bank->f.epoch                                               );
      71          24 :     PUSH_VAL( ulong,  bank->f.block_height                                        );
      72          24 :     PUSH_VAL( fd_pubkey_t, enc->leader );
      73          24 :     PUSH_VAL( ulong, 0UL ); /* unused_collector_fees */
      74          24 :     PUSH_VAL( ulong, 0UL ); /* unused_fee_calculator */
      75             : 
      76          12 :     fd_fee_rate_governor_t const * frg = &bank->f.fee_rate_governor;
      77          24 :     PUSH_VAL( ulong, frg->target_lamports_per_signature );
      78          24 :     PUSH_VAL( ulong, frg->target_signatures_per_slot    );
      79          24 :     PUSH_VAL( ulong, frg->min_lamports_per_signature    );
      80          24 :     PUSH_VAL( ulong, frg->max_lamports_per_signature    );
      81          24 :     PUSH_VAL( uchar, frg->burn_percent                  );
      82          24 :     PUSH_VAL( ulong, 0UL );
      83          24 :     PUSH_VAL( ulong, bank->f.epoch );
      84             : 
      85          12 :     fd_epoch_schedule_t const * es = &bank->f.epoch_schedule;
      86          12 :     fd_rent_t const * rent = &bank->f.rent;
      87          24 :     PUSH_VAL( ulong,  es->slots_per_epoch                );
      88          24 :     PUSH_VAL( ulong,  es->leader_schedule_slot_offset    );
      89          24 :     PUSH_VAL( uchar,  es->warmup                         );
      90          24 :     PUSH_VAL( ulong,  es->first_normal_epoch             );
      91          24 :     PUSH_VAL( ulong,  es->first_normal_slot              );
      92          24 :     PUSH_VAL( double, bank->f.slot_params.slots_per_year );
      93          24 :     PUSH_VAL( ulong,  rent->lamports_per_uint8_year      );
      94          24 :     PUSH_VAL( double, rent->exemption_threshold          );
      95          24 :     PUSH_VAL( uchar,  rent->burn_percent                 );
      96          24 :     PUSH_VAL( ulong,  es->slots_per_epoch                );
      97          24 :     PUSH_VAL( ulong,  es->leader_schedule_slot_offset    );
      98          24 :     PUSH_VAL( uchar,  es->warmup                         );
      99          24 :     PUSH_VAL( ulong,  es->first_normal_epoch             );
     100          24 :     PUSH_VAL( ulong,  es->first_normal_slot              );
     101             : 
     102          12 :     fd_inflation_t const * inf = &bank->f.inflation;
     103          24 :     PUSH_VAL( double, inf->initial        );
     104          24 :     PUSH_VAL( double, inf->terminal       );
     105          24 :     PUSH_VAL( double, inf->taper          );
     106          24 :     PUSH_VAL( double, inf->foundation     );
     107          24 :     PUSH_VAL( double, inf->foundation_term );
     108          24 :     PUSH_VAL( double, inf->unused          );
     109             : 
     110          24 :     enc->state = STATE_VOTE_ACCOUNTS;
     111          12 :     break;
     112          12 :   }
     113          24 :   case STATE_VOTE_ACCOUNTS: {
     114          24 :     PUSH_VAL( ulong, 0UL ); /* zero vote_accounts */
     115          24 :     PUSH_VAL( ulong, 0UL ); /* zero stake delegations */
     116          24 :     PUSH_VAL( ulong, 0UL ); /* unused */
     117          24 :     PUSH_VAL( ulong, bank->f.epoch );
     118          24 :     enc->state = STATE_STAKE_HISTORY;
     119          12 :     break;
     120          12 :   }
     121           0 :   case STATE_STAKE_DELEGATION: { FD_LOG_ERR(( "TODO")); }
     122           0 :   case STATE_STAKE_EPOCH: { FD_LOG_ERR(( "TODO")); }
     123          24 :   case STATE_STAKE_HISTORY: {
     124          24 :     PUSH_VAL( ulong, 0UL ); /* zero stake history entries */
     125          24 :     enc->state = STATE_BANK_TRAILER;
     126          12 :     break;
     127          12 :   }
     128          24 :   case STATE_BANK_TRAILER: {
     129          24 :     PUSH_VAL( ulong, 0UL ); /* unused_accounts.unused1 */
     130          24 :     PUSH_VAL( ulong, 0UL ); /* unused_accounts.unused2 */
     131          24 :     PUSH_VAL( ulong, 0UL ); /* unused_accounts.unused3 */
     132          24 :     PUSH_VAL( ulong, 0UL ); /* unused_epoch_stakes */
     133          24 :     PUSH_VAL( uchar, 0   ); /* is_delta */
     134          24 :     PUSH_VAL( ulong, 0UL ); /* zero account_storage_entries */
     135          24 :     enc->state = STATE_BANK_HASH_INFO;
     136          12 :     break;
     137          12 :   }
     138           0 :   case STATE_ACCOUNT_STORAGE_ENTRY: { FD_LOG_ERR(( "TODO")); }
     139          24 :   case STATE_BANK_HASH_INFO: {
     140             :     /* AccountsDbFields */
     141          24 :     PUSH_VAL( ulong, 0UL          ); /* write_version, unused */
     142          24 :     PUSH_VAL( ulong, bank->f.slot ); /* slot */
     143          24 :     PUSH_VAL( fd_hash_t, (fd_hash_t){0} ); /* unused_accounts_delta_hash */
     144          24 :     PUSH_VAL( fd_hash_t, (fd_hash_t){0} ); /* unused_accounts_hash */
     145          24 :     PUSH_VAL( ulong, 0UL ); /* num_updated_accounts, unused */
     146          24 :     PUSH_VAL( ulong, 0UL ); /* num_removed_accounts, unused */
     147          24 :     PUSH_VAL( ulong, 0UL ); /* num_lamports_stored, unused */
     148          24 :     PUSH_VAL( ulong, 0UL ); /* total_data_len, unused */
     149          24 :     PUSH_VAL( ulong, 0UL ); /* num_executable_accounts, unused */
     150          24 :     PUSH_VAL( ulong, 0UL ); /* historical_roots, unused */
     151          24 :     PUSH_VAL( ulong, 0UL ); /* historical_roots_with_hash, unused */
     152             :     /* ExtraFieldsToSerialize */
     153          24 :     PUSH_VAL( ulong, bank->f.rbh_lamports_per_sig );
     154          24 :     PUSH_VAL( uchar, 0 ); /* unused_incremental_snapshot_persistence */
     155          24 :     PUSH_VAL( uchar, 0 ); /* unused_epoch_accounts_hash */
     156             : 
     157          12 :     ulong epoch = bank->f.epoch;
     158          12 :     ulong epoch_cnt = fd_ulong_min( epoch, 3UL ) + 2UL; /* keys max(E-3,0)..E+1, as agave retains */
     159          24 :     PUSH_VAL( ulong, epoch_cnt );
     160          12 :     enc->epoch_cnt = (uchar)epoch_cnt;
     161          12 :     enc->epoch_idx = 0;
     162          24 :     enc->state = STATE_EPOCH_STAKES;
     163          12 :     break;
     164          12 :   }
     165         120 :   case STATE_EPOCH_STAKES: {
     166          60 :     ulong epoch_key = epoch_stakes_key      ( bank, enc->epoch_idx );
     167          60 :     int   iter_kind = epoch_stakes_iter_kind( bank, enc->epoch_idx );
     168          60 :     fd_vote_stakes_t * vote_stakes = fd_bank_vote_stakes( bank );
     169          60 :     ushort             fork_id     = bank->vote_stakes_fork_id;
     170             : 
     171          60 :     uint vote_cnt = 0U;
     172          60 :     for( fd_vote_stakes_iter_t * iter = fd_vote_stakes_iter_init( vote_stakes, fork_id, iter_kind, enc->vote_stakes_iter_mem );
     173         552 :          !fd_vote_stakes_iter_done( vote_stakes, fork_id, iter_kind, iter );
     174         432 :          fd_vote_stakes_iter_next( vote_stakes, fork_id, iter_kind, iter ) ) vote_cnt++;
     175          60 :     fd_vote_stakes_iter_init( vote_stakes, fork_id, iter_kind, enc->vote_stakes_iter_mem );
     176          60 :     enc->vote_cnt    = vote_cnt;
     177          60 :     enc->vote_idx    = 0;
     178          60 :     enc->total_stake = 0UL;
     179             : 
     180         120 :     PUSH_VAL( ulong, epoch_key );
     181         120 :     PUSH_VAL( uint,  0U ); /* variant = 0 (VersionedEpochStakes::Current) */
     182         120 :     PUSH_VAL( ulong, (ulong)vote_cnt );
     183             : 
     184         120 :     enc->state = (vote_cnt > 0U) ? STATE_EPOCH_STAKES_STAKES : STATE_EPOCH_STAKES_EPOCH;
     185          60 :     break;
     186          60 :   }
     187         432 :   case STATE_EPOCH_STAKES_STAKES: {
     188         432 :     int iter_kind = epoch_stakes_iter_kind( bank, enc->epoch_idx );
     189             : 
     190         432 :     ulong       ec_cnt            = 0UL;
     191         432 :     fd_epoch_credits_t const * ec = NULL;
     192             : 
     193         432 :     fd_vote_stakes_t * vote_stakes = fd_bank_vote_stakes( bank );
     194         432 :     ushort             fork_id     = bank->vote_stakes_fork_id;
     195             : 
     196         432 :     fd_vote_stakes_iter_t * iter = fd_type_pun( enc->vote_stakes_iter_mem );
     197         432 :     FD_TEST( !fd_vote_stakes_iter_done( vote_stakes, fork_id, iter_kind, iter ) );
     198         432 :     fd_vote_stakes_ele_t ele[1];
     199         432 :     fd_vote_stakes_iter_ele( vote_stakes, fork_id, iter_kind, iter, ele );
     200             : 
     201         432 :     if( iter_kind==FD_VOTE_STAKES_ITER_T_1 ) {
     202          72 :       ec = find_epoch_credits( enc->bank, &ele->pubkey );
     203          72 :       FD_TEST( ec );
     204          72 :       ec_cnt = ec->cnt;
     205          72 :     }
     206             : 
     207             :     /* SIMD-0232 collectors.  t-3..t-5 collectors are never consulted on
     208             :        reload; encoded as zero. */
     209         432 :     fd_pubkey_t inflation_collector = {0};
     210         432 :     fd_pubkey_t block_collector     = {0};
     211         432 :     if( FD_LIKELY( iter_kind==FD_VOTE_STAKES_ITER_T_1 || iter_kind==FD_VOTE_STAKES_ITER_T_2 ) ) {
     212         144 :       inflation_collector = ele->inflation_collector;
     213         144 :       block_collector     = ele->block_collector;
     214         144 :     }
     215             : 
     216             :     /* A zeroed key means no BLS key is registered (serialized as None) */
     217         432 :     static uchar const no_bls_key[ FD_BLS_PUB_COMPRESSED_SZ ] = {0};
     218         432 :     int has_bls      = !fd_memeq( ele->bls_key, no_bls_key, FD_BLS_PUB_COMPRESSED_SZ );
     219         432 :     int has_location = ele->location.x || ele->location.y || ele->location.z;
     220             : 
     221         432 :     enc->total_stake += ele->stake;
     222             : 
     223         432 :     FD_TEST( ec_cnt<=FD_EPOCH_CREDITS_MAX );
     224             : 
     225         432 :     ulong data_length = fd_ulong_if( has_location, FD_VOTE_STATE_V5_SZ, 186UL + fd_ulong_if( !!has_bls, FD_BLS_PUB_COMPRESSED_SZ, 0UL ) + 24UL * ec_cnt );
     226             : 
     227             :     /* Vote account key + stake */
     228         432 :     PUSH_VAL( fd_pubkey_t, ele->pubkey );
     229         432 :     PUSH_VAL( ulong,       ele->stake  );
     230             : 
     231             :     /* AccountSharedData: lamports, data_length */
     232         432 :     PUSH_VAL( ulong, 0UL         );
     233         432 :     PUSH_VAL( ulong, data_length );
     234             : 
     235         432 :     if( has_location ) {
     236          72 :       ulong epoch_key = epoch_stakes_key( bank, enc->epoch_idx );
     237          72 :       ulong ec_skip   = fd_ulong_sat_sub( ec_cnt, FD_VOTE_STATE_V5_ACCUMULATED_LAMPORTS_MAX );
     238          72 :       fd_vote_state_v5_t v5 = {
     239          72 :         .node_pubkey                             = ele->node_account,
     240          72 :         .inflation_rewards_collector             = inflation_collector,
     241          72 :         .block_revenue_collector                 = block_collector,
     242          72 :         .inflation_rewards_commission_bps_len    = 1,
     243          72 :         .block_revenue_commission_bps_len        = 1,
     244          72 :         .pending_delegator_rewards               = ele->pending_delegator_rewards,
     245          72 :         .location                                = ele->location,
     246          72 :         .inflation_rewards_commission_bps_epochs = { epoch_key },
     247          72 :         .inflation_rewards_commission_bps        = { ele->commission },
     248          72 :         .block_revenue_commission_bps_epochs     = { epoch_key },
     249          72 :         .block_revenue_commission_bps            = { ele->block_revenue_commission_bps },
     250          72 :         .latest_vote                             = ULONG_MAX,
     251          72 :         .root_slot                               = ULONG_MAX,
     252          72 :         .accumulated_lamports_len                = (uint)( ec_cnt-ec_skip ),
     253          72 :         .rank_epoch                              = ULONG_MAX,
     254          72 :         .rank                                    = USHORT_MAX
     255          72 :       };
     256          72 :       memcpy( v5.bls_pubkey_compressed, ele->bls_key, FD_BLS_PUB_COMPRESSED_SZ );
     257         144 :       for( ulong j=ec_skip; j<ec_cnt; j++ ) {
     258          72 :         v5.accumulated_lamports[ j-ec_skip ] = (fd_vote_epoch_credits_t){ (ulong)ec->epoch[j],
     259          72 :                                                                           ec->base_credits + (ulong)ec->credits_delta[j],
     260          72 :                                                                           ec->base_credits + (ulong)ec->prev_credits_delta[j] };
     261          72 :       }
     262          72 :       typedef struct { uchar b[ FD_VOTE_STATE_V5_SZ-sizeof(uint)-sizeof(fd_vote_state_v5_t) ]; } v5_tail_t;
     263          72 :       PUSH_VAL( uint,               fd_vote_state_versioned_enum_v5 );
     264          72 :       PUSH_VAL( fd_vote_state_v5_t, v5                              );
     265          72 :       PUSH_VAL( v5_tail_t,          (v5_tail_t){0}                  );
     266         360 :     } else {
     267             :       /* VoteStateV4 */
     268         360 :       PUSH_VAL( uint,       3U           ); /* variant = V4 */
     269         360 :       PUSH_VAL( fd_pubkey_t, ele->node_account ); /* node_pubkey */
     270         360 :       PUSH_VAL( fd_pubkey_t, (fd_pubkey_t){0} ); /* authorized_withdrawer */
     271         360 :       PUSH_VAL( fd_pubkey_t, inflation_collector ); /* inflation_rewards_collector */
     272         360 :       PUSH_VAL( fd_pubkey_t, block_collector     ); /* block_revenue_collector */
     273         360 :       PUSH_VAL( ushort, ele->commission ); /* inflation_rewards_commission_bps */
     274         360 :       PUSH_VAL( ushort, ele->block_revenue_commission_bps ); /* block_revenue_commission_bps */
     275         360 :       PUSH_VAL( ulong,  ele->pending_delegator_rewards    ); /* pending_delegator_rewards */
     276         360 :       if( has_bls ) {
     277           0 :         typedef struct { uchar b[ FD_BLS_PUB_COMPRESSED_SZ ]; } bls_key_compressed_t;
     278           0 :         PUSH_VAL( uchar, 1        ); /* bls_pubkey_compressed = Some */
     279           0 :         PUSH_VAL( bls_key_compressed_t, *(bls_key_compressed_t const *)ele->bls_key );
     280         360 :       } else {
     281         360 :         PUSH_VAL( uchar, 0        ); /* bls_pubkey_compressed = None */
     282         180 :       }
     283         360 :       PUSH_VAL( ulong,  0UL      ); /* votes_length = 0 */
     284         360 :       PUSH_VAL( uchar,  0        ); /* root_slot = None */
     285         360 :       PUSH_VAL( ulong,  0UL      ); /* authorized_voters_length = 0 */
     286             : 
     287             :       /* Epoch credits */
     288         360 :       PUSH_VAL( ulong, ec_cnt );
     289         504 :       for( ulong j=0UL; j<ec_cnt; j++ ) {
     290         144 :         PUSH_VAL( ulong, (ulong)ec->epoch[j] );
     291         144 :         PUSH_VAL( ulong, ec->base_credits + (ulong)ec->credits_delta[j] );
     292         144 :         PUSH_VAL( ulong, ec->base_credits + (ulong)ec->prev_credits_delta[j] );
     293          72 :       }
     294             : 
     295         360 :       PUSH_VAL( ulong, 0UL ); /* last_timestamp_slot */
     296         360 :       PUSH_VAL( ulong, 0UL ); /* last_timestamp_timestamp */
     297         180 :     }
     298             : 
     299             :     /* AccountSharedData trailer */
     300         432 :     PUSH_VAL( fd_pubkey_t, fd_solana_vote_program_id ); /* owner */
     301         432 :     PUSH_VAL( uchar,       1                         ); /* executable */
     302         432 :     PUSH_VAL( ulong,       0UL                       ); /* rent_epoch */
     303             : 
     304         216 :     enc->vote_idx++;
     305         216 :     fd_vote_stakes_iter_next( vote_stakes, fork_id, iter_kind, iter );
     306         432 :     if( enc->vote_idx >= enc->vote_cnt ) enc->state = STATE_EPOCH_STAKES_EPOCH;
     307         216 :     break;
     308         216 :   }
     309         120 :   case STATE_EPOCH_STAKES_EPOCH: {
     310          60 :     ulong epoch_key = epoch_stakes_key( bank, enc->epoch_idx );
     311             : 
     312         120 :     PUSH_VAL( ulong, 0UL       ); /* stake_delegations_length = 0 */
     313         120 :     PUSH_VAL( ulong, 0UL       ); /* unused */
     314         120 :     PUSH_VAL( ulong, epoch_key ); /* epoch */
     315         120 :     PUSH_VAL( ulong, 0UL       ); /* stake_history_length = 0 */
     316         120 :     enc->state = STATE_EPOCH_TOTAL_STAKE;
     317          60 :     break;
     318          60 :   }
     319         120 :   case STATE_EPOCH_TOTAL_STAKE: {
     320          60 :     int iter_kind = epoch_stakes_iter_kind( bank, enc->epoch_idx );
     321         120 :     ulong total_stake = (iter_kind==FD_VOTE_STAKES_ITER_T_1) ? bank->f.total_epoch_stake : enc->total_stake;
     322         120 :     PUSH_VAL( ulong, total_stake );
     323         120 :     enc->state = STATE_NODE_VOTE_ACCOUNTS;
     324          60 :     break;
     325          60 :   }
     326         120 :   case STATE_NODE_VOTE_ACCOUNTS: {
     327             :     /* node_id_to_vote_accounts: HashMap<node, (Vec<vote>, total_stake)> */
     328          60 :     fd_ssmanifest_epoch_map_t const * map = &enc->epoch_map[ enc->epoch_idx ];
     329         120 :     PUSH_VAL( ulong, map->node_cnt );
     330         336 :     for( ulong i=0UL; i<map->vote_cnt; ) {
     331         216 :       fd_pubkey_t const * node = &map->vote[ i ].node;
     332         216 :       ulong j = i;
     333         216 :       ulong total_stake = 0UL;
     334         456 :       for( ; j<map->vote_cnt && fd_memeq( map->vote[ j ].node.uc, node->uc, sizeof(fd_pubkey_t) ); j++ ) {
     335         240 :         total_stake += map->vote[ j ].stake;
     336         240 :       }
     337         216 :       PUSH_VAL( fd_pubkey_t, *node );
     338         216 :       PUSH_VAL( ulong,       j-i   );
     339         456 :       for( ulong k=i; k<j; k++ ) {
     340         240 :         PUSH_VAL( fd_pubkey_t, map->vote[ k ].vote );
     341         120 :       }
     342         216 :       PUSH_VAL( ulong, total_stake );
     343         216 :       i = j;
     344         216 :     }
     345         120 :     enc->state = STATE_AUTH_VOTER;
     346          60 :     break;
     347          60 :   }
     348         120 :   case STATE_AUTH_VOTER: {
     349             :     /* epoch_authorized_voters: HashMap<vote, voter> */
     350          60 :     fd_ssmanifest_epoch_map_t const * map = &enc->epoch_map[ enc->epoch_idx ];
     351         120 :     PUSH_VAL( ulong, map->vote_cnt );
     352         360 :     for( ulong i=0UL; i<map->vote_cnt; i++ ) {
     353         240 :       PUSH_VAL( fd_pubkey_t, map->vote[ i ].vote  );
     354         240 :       PUSH_VAL( fd_pubkey_t, map->vote[ i ].voter );
     355         120 :     }
     356          60 :     enc->epoch_idx++;
     357         120 :     enc->state = (enc->epoch_idx < enc->epoch_cnt) ? STATE_EPOCH_STAKES : STATE_LTHASH;
     358          60 :     break;
     359          60 :   }
     360          24 :   case STATE_LTHASH: {
     361          24 :     PUSH_VAL( uchar, 1 );
     362          24 :     PUSH_VAL( fd_lthash_value_t, bank->f.lthash );
     363          24 :     enc->state = STATE_BLOCK_ID;
     364          12 :     break;
     365          12 :   }
     366          24 :   case STATE_BLOCK_ID: {
     367          12 :     int has_block_id = !fd_hash_check_zero( &bank->f.block_id );
     368          24 :     PUSH_VAL( uchar, (uchar)has_block_id );
     369          24 :     if( has_block_id ) PUSH_VAL( fd_hash_t, bank->f.block_id );
     370          24 :     enc->state = STATE_DONE;
     371          12 :     break;
     372          12 :   }
     373          24 :   case STATE_DONE:
     374          24 :     enc->state = STATE_INIT; /* ready for the next pass */
     375          24 :     return 0UL;
     376           0 :   default:
     377           0 :     FD_LOG_CRIT(( "invalid state reached (%u)", enc->state ));
     378        1296 :   }
     379             : 
     380        1272 :   return RET_EXPR;
     381        1296 : }
     382             : 
     383             : #undef PREP
     384             : #undef ENCODE_FN
     385             : #undef PUSH_VAL
     386             : #undef RET_EXPR

Generated by: LCOV version 1.14