LCOV - code coverage report
Current view: top level - discof/backup - fd_ssmanifest_writer.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 111 0.0 %
Date: 2026-11-11 12:40:43 Functions: 0 5 0.0 %

          Line data    Source code
       1             : #include "fd_ssmanifest_writer.h"
       2             : #include "../../flamenco/runtime/fd_system_ids.h"
       3             : #include "../../flamenco/runtime/program/vote/fd_vote_state_versioned.h"
       4             : #include "../../ballet/bls/fd_bls.h"
       5             : 
       6             : #define SORT_NAME        sort_epoch_vote_by_node
       7           0 : #define SORT_KEY_T       fd_ssmanifest_epoch_vote_t
       8           0 : #define SORT_BEFORE(a,b) (0>memcmp( (a).node.uc, (b).node.uc, sizeof(fd_pubkey_t) ))
       9             : #include "../../util/tmpl/fd_sort.c"
      10             : 
      11           0 : #define STATE_BLOCKHASH_QUEUE        1
      12           0 : #define STATE_HASHES                 2
      13           0 : #define STATE_HARD_FORKS             3
      14           0 : #define STATE_COUNTERS               4
      15           0 : #define STATE_VOTE_ACCOUNTS          5
      16           0 : #define STATE_STAKE_DELEGATION       6
      17           0 : #define STATE_STAKE_EPOCH            7
      18           0 : #define STATE_STAKE_HISTORY          8
      19           0 : #define STATE_BANK_TRAILER           9
      20           0 : #define STATE_ACCOUNT_STORAGE_ENTRY 10
      21           0 : #define STATE_BANK_HASH_INFO        11
      22           0 : #define STATE_EPOCH_STAKES          12
      23           0 : #define STATE_EPOCH_STAKES_STAKES   13
      24           0 : #define STATE_EPOCH_STAKES_EPOCH    14
      25           0 : #define STATE_EPOCH_TOTAL_STAKE     15
      26           0 : #define STATE_NODE_VOTE_ACCOUNTS    16
      27           0 : #define STATE_AUTH_VOTER            17
      28           0 : #define STATE_LTHASH                18
      29           0 : #define STATE_BLOCK_ID              19
      30           0 : #define STATE_DONE                  20
      31           0 : #define STATE_INIT STATE_BLOCKHASH_QUEUE
      32             : 
      33             : /* Epoch stakes entries are keyed max(E-3,0)..E+1, as agave retains.
      34             :    Key E+1 is the t-1 set with credits, E the t-2 set, E-1..E-3 the
      35             :    t-3..t-5 sets. */
      36             : 
      37             : static inline ulong
      38             : epoch_stakes_key( fd_bank_t const * bank,
      39           0 :                   ulong             epoch_idx ) {
      40           0 :   ulong epoch = bank->f.epoch;
      41           0 :   return ( epoch>3UL ? epoch-3UL : 0UL ) + epoch_idx;
      42           0 : }
      43             : 
      44             : static inline int
      45             : epoch_stakes_iter_kind( fd_bank_t const * bank,
      46           0 :                         ulong             epoch_idx ) {
      47           0 :   return (int)( bank->f.epoch + 2UL - epoch_stakes_key( bank, epoch_idx ) );
      48           0 : }
      49             : 
      50             : static fd_epoch_credits_t const *
      51             : find_epoch_credits( fd_bank_t *          bank,
      52           0 :                     fd_pubkey_t const * pubkey ) {
      53           0 :   ulong                      epoch_credits_len;
      54           0 :   fd_epoch_credits_t const * epoch_credits_arr = fd_epoch_credits_store_peek( fd_bank_epoch_credits( bank ), bank->epoch_credits_fork_id, &epoch_credits_len );
      55           0 :   for( ulong i=0UL; i<epoch_credits_len; i++ ) {
      56           0 :     fd_epoch_credits_t const * epoch_credits = &epoch_credits_arr[ i ];
      57           0 :     if( fd_memeq( epoch_credits->pubkey, pubkey, sizeof(fd_pubkey_t) ) ) return epoch_credits;
      58           0 :   }
      59           0 :   return NULL;
      60           0 : }
      61             : 
      62             : /* Size estimate */
      63             : 
      64             : #define ENCODE_FN     static ulong manifest_estimate( fd_ssmanifest_writer_t * enc )
      65           0 : #define PREP          ulong sz = 0UL;
      66           0 : #define PUSH_VAL(t,n) do { sz += sizeof(t); (void)(n); } while(0)
      67           0 : #define RET_EXPR      sz
      68             : #include "fd_ssmanifest_encoder.c"
      69             : 
      70             : fd_ssmanifest_writer_t *
      71             : fd_ssmanifest_writer_init( fd_ssmanifest_writer_t * enc,
      72             :                            fd_bank_t *              bank,
      73             :                            fd_pubkey_t const *      leader,
      74             :                            fd_accdb_t *             accdb,
      75             :                            fd_accdb_fork_id_t       accdb_fork_id,
      76           0 :                            uchar *                  acc_data ) {
      77           0 :   enc->state       = STATE_BLOCKHASH_QUEUE;
      78           0 :   enc->bank        = bank;
      79           0 :   enc->leader      = *leader;
      80           0 :   enc->epoch_idx   = 0;
      81           0 :   enc->epoch_cnt   = 0;
      82           0 :   enc->vote_cnt    = 0;
      83           0 :   enc->vote_idx    = 0;
      84           0 :   enc->total_stake = 0UL;
      85             : 
      86           0 :   fd_vote_stakes_t * vote_stakes = fd_bank_vote_stakes( bank );
      87           0 :   ushort             fork_id     = bank->vote_stakes_fork_id;
      88           0 :   ulong              epoch_cnt   = fd_ulong_min( bank->f.epoch, 3UL ) + 2UL;
      89           0 :   for( ulong epoch_idx=0UL; epoch_idx<epoch_cnt; epoch_idx++ ) {
      90           0 :     fd_ssmanifest_epoch_map_t * map = &enc->epoch_map[ epoch_idx ];
      91           0 :     ulong epoch_key = epoch_stakes_key( bank, epoch_idx );
      92           0 :     int   iter_kind = epoch_stakes_iter_kind( bank, epoch_idx );
      93             : 
      94             :     /* Agave only reads the maps of the previous, current and next
      95             :        epoch.  Older sets keep empty maps. */
      96           0 :     map->vote_cnt = 0UL;
      97           0 :     map->node_cnt = 0UL;
      98           0 :     if( iter_kind>FD_VOTE_STAKES_ITER_T_3 ) continue;
      99             : 
     100           0 :     for( fd_vote_stakes_iter_t * iter = fd_vote_stakes_iter_init( vote_stakes, fork_id, iter_kind, enc->vote_stakes_iter_mem );
     101           0 :          !fd_vote_stakes_iter_done( vote_stakes, fork_id, iter_kind, iter );
     102           0 :          fd_vote_stakes_iter_next( vote_stakes, fork_id, iter_kind, iter ) ) {
     103           0 :       fd_ssmanifest_epoch_vote_t * ele = &map->vote[ map->vote_cnt ];
     104           0 :       fd_vote_stakes_ele_t vs_ele[1];
     105           0 :       fd_vote_stakes_iter_ele( vote_stakes, fork_id, iter_kind, iter, vs_ele );
     106           0 :       ele->vote  = vs_ele->pubkey;
     107           0 :       ele->node  = vs_ele->node_account;
     108           0 :       ele->stake = vs_ele->stake;
     109             : 
     110           0 :       ulong lamports;
     111           0 :       int   executable;
     112           0 :       uchar owner[ 32UL ];
     113           0 :       ulong data_len;
     114           0 :       fd_accdb_read_one_nocache( accdb, accdb_fork_id, ele->vote.uc, &lamports, &executable, owner, acc_data, &data_len );
     115           0 :       if( FD_UNLIKELY( !lamports ||
     116           0 :                        !fd_vsv_is_correct_size_owner_and_init( owner, acc_data, data_len ) ||
     117           0 :                        fd_vote_account_authorized_voter( acc_data, data_len, epoch_key, &ele->voter ) ) ) {
     118           0 :         continue;
     119           0 :       }
     120           0 :       map->vote_cnt++;
     121           0 :     }
     122             : 
     123           0 :     sort_epoch_vote_by_node_inplace( map->vote, map->vote_cnt );
     124           0 :     for( ulong i=0UL; i<map->vote_cnt; i++ ) {
     125           0 :       int new_node = ( i==0UL ) || !fd_memeq( map->vote[ i ].node.uc, map->vote[ i-1UL ].node.uc, sizeof(fd_pubkey_t) );
     126           0 :       if( new_node ) {
     127           0 :         map->node_cnt++;
     128           0 :       }
     129           0 :     }
     130           0 :   }
     131             : 
     132           0 :   enc->serialized_sz = 0UL;
     133           0 :   for(;;) {
     134           0 :     ulong chunk = manifest_estimate( enc );
     135           0 :     if( FD_UNLIKELY( !chunk ) ) break;
     136           0 :     enc->serialized_sz += chunk;
     137           0 :   }
     138           0 :   return enc;
     139           0 : }
     140             : 
     141             : /* Actual encoder */
     142             : 
     143             : __attribute__((cold,noreturn))
     144             : static void fail( fd_ssmanifest_writer_t const * enc,
     145             :                   ulong buf_sz,
     146           0 :                   ulong line_nr ) {
     147           0 :   FD_LOG_ERR(( "buffer overflow (state=%u, buf_sz=%lu, line_nr=%lu)", enc->state, buf_sz, line_nr ));
     148           0 : }
     149             : 
     150             : #define ENCODE_FN                                                         \
     151             :   ulong                                                                   \
     152             :   fd_snap_manifest_serialize( fd_ssmanifest_writer_t * enc,               \
     153             :                               uchar out_buf[ FD_SSMANIFEST_BUF_MIN ],     \
     154             :                               ulong buf_sz )
     155             : #define PREP                                                              \
     156           0 :   uchar * p  = out_buf;                                                   \
     157           0 :   uchar * p1 = out_buf+buf_sz;
     158             : #define PUSH_VAL( t, n )                                                  \
     159           0 :   FD_STORE( t, __extension__({                                            \
     160           0 :     /* compile time bounds check elide */                                 \
     161           0 :     if( FD_UNLIKELY( p+sizeof(t) > p1 ) ) fail( enc, buf_sz, __LINE__ );  \
     162           0 :     uchar * ret = p;                                                      \
     163           0 :     p += sizeof(t);                                                       \
     164           0 :     ret;                                                                  \
     165           0 :   }), (n) )
     166           0 : #define RET_EXPR (ulong)( p - out_buf )
     167             : #include "fd_ssmanifest_encoder.c"

Generated by: LCOV version 1.14