LCOV - code coverage report
Current view: top level - flamenco/features - fd_features.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 86 91 94.5 %
Date: 2026-05-22 08:05:30 Functions: 7 7 100.0 %

          Line data    Source code
       1             : #include "fd_features.h"
       2             : #include "../runtime/fd_bank.h"
       3             : #include "../runtime/fd_system_ids.h"
       4             : #include "../runtime/sysvar/fd_sysvar_epoch_schedule.h"
       5             : #include "../accdb/fd_accdb_sync.h"
       6             : 
       7             : FD_STATIC_ASSERT( sizeof  ( fd_feature_t                  )==9UL, layout );
       8             : FD_STATIC_ASSERT( offsetof( fd_feature_t, is_active       )==0UL, layout );
       9             : FD_STATIC_ASSERT( offsetof( fd_feature_t, activation_slot )==1UL, layout );
      10             : 
      11             : fd_feature_t *
      12             : fd_feature_decode( fd_feature_t * feature,
      13             :                    uchar const *  data,
      14          48 :                    ulong          data_sz ) {
      15          48 :   if( FD_UNLIKELY( data_sz < sizeof(fd_feature_t) ) ) return NULL;
      16          45 :   *feature = FD_LOAD( fd_feature_t, data );
      17          45 :   if( FD_UNLIKELY( feature->is_active>1 ) ) return NULL;
      18          45 :   return feature;
      19          45 : }
      20             : 
      21             : void
      22          15 : fd_features_enable_all( fd_features_t * f ) {
      23          15 :   for( fd_feature_id_t const * id = fd_feature_iter_init();
      24        4125 :        !fd_feature_iter_done( id );
      25        4110 :        id = fd_feature_iter_next( id ) ) {
      26        4110 :     fd_features_set( f, id, 0UL );
      27        4110 :   }
      28          15 : }
      29             : 
      30             : void
      31        7314 : fd_features_disable_all( fd_features_t * f ) {
      32        7314 :   for( fd_feature_id_t const * id = fd_feature_iter_init();
      33     2011350 :        !fd_feature_iter_done( id );
      34     2004036 :        id = fd_feature_iter_next( id ) ) {
      35     2004036 :     fd_features_set( f, id, FD_FEATURE_DISABLED );
      36     2004036 :   }
      37        7314 : }
      38             : 
      39             : void
      40        3519 : fd_features_enable_cleaned_up( fd_features_t * f ) {
      41        3519 :   for( fd_feature_id_t const * id = fd_feature_iter_init();
      42      967725 :        !fd_feature_iter_done( id );
      43      964206 :        id = fd_feature_iter_next( id ) ) {
      44      964206 :     if( FD_LIKELY( id->cleaned_up ) ) {
      45      696762 :       fd_features_set( f, id, 0UL );
      46      696762 :     } else {
      47      267444 :       fd_features_set( f, id, FD_FEATURE_DISABLED );
      48      267444 :     }
      49      964206 :   }
      50        3519 : }
      51             : 
      52             : void
      53          21 : fd_features_enable_one_offs( fd_features_t * f, char const * * one_offs, uint one_offs_cnt, ulong slot ) {
      54          21 :   uchar pubkey[32];
      55          81 :   for( uint i=0U; i<one_offs_cnt; i++ ) {
      56          60 :     fd_base58_decode_32( one_offs[i], pubkey );
      57          60 :     for( fd_feature_id_t const * id = fd_feature_iter_init();
      58       14103 :          !fd_feature_iter_done( id );
      59       14100 :          id = fd_feature_iter_next( id ) ) {
      60       14100 :       if( !memcmp( &id->id, pubkey, sizeof(fd_pubkey_t) ) ) {
      61          57 :         fd_features_set( f, id, slot );
      62          57 :         break;
      63          57 :       }
      64       14100 :     }
      65          60 :   }
      66          21 : }
      67             : 
      68             : static void
      69             : fd_feature_restore( fd_bank_t *               bank,
      70             :                     fd_accdb_user_t *         accdb,
      71             :                     fd_funk_txn_xid_t const * xid,
      72             :                     fd_feature_id_t const *   id,
      73       41100 :                     fd_pubkey_t const *       addr ) {
      74             : 
      75       41100 :   fd_features_t *             features       = &bank->f.features;
      76       41100 :   fd_epoch_schedule_t const * epoch_schedule = &bank->f.epoch_schedule;
      77       41100 :   ulong                       slot           = bank->f.slot;
      78             : 
      79       41100 :   fd_features_set( features, id, FD_FEATURE_DISABLED );
      80             : 
      81             :   /* Skip reverted features */
      82       41100 :   if( FD_UNLIKELY( id->reverted ) ) return;
      83             : 
      84       39300 :   fd_accdb_ro_t ro[1];
      85       39300 :   if( FD_UNLIKELY( !fd_accdb_open_ro( accdb, ro, xid, addr ) ) )  {
      86       39258 :     return;
      87       39258 :   }
      88             : 
      89             :   /* Skip accounts that are not owned by the feature program
      90             :      https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L42-L44 */
      91          42 :   if( FD_UNLIKELY( !fd_pubkey_eq( fd_accdb_ref_owner( ro ), &fd_solana_feature_program_id ) ) ) {
      92           6 :     fd_accdb_close_ro( accdb, ro );
      93           6 :     return;
      94           6 :   }
      95             : 
      96             :   /* Account data size must be >= FD_FEATURE_SIZEOF (9 bytes)
      97             :      https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L45-L47 */
      98          36 :   if( FD_UNLIKELY( fd_accdb_ref_data_sz( ro ) < sizeof(fd_feature_t) ) ) {
      99           6 :     fd_accdb_close_ro( accdb, ro );
     100           6 :     return;
     101           6 :   }
     102             : 
     103             :   /* Deserialize the feature account data
     104             :      https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L48-L50 */
     105          30 :   fd_feature_t feature[1];
     106          30 :   if( FD_UNLIKELY( !fd_feature_decode(
     107          30 :       feature,
     108          30 :       fd_accdb_ref_data_const( ro ),
     109          30 :       fd_accdb_ref_data_sz   ( ro ) ) ) ) {
     110           0 :     fd_accdb_close_ro( accdb, ro );
     111           0 :     return;
     112           0 :   }
     113          30 :   fd_accdb_close_ro( accdb, ro );
     114             : 
     115          30 :   FD_BASE58_ENCODE_32_BYTES( addr->uc, addr_b58 );
     116          30 :   if( feature->is_active ) {
     117          27 :     FD_LOG_DEBUG(( "feature %s activated at slot %lu", addr_b58, feature->activation_slot ));
     118          27 :     fd_features_set( features, id, feature->activation_slot );
     119          27 :   } else if( fd_slot_to_epoch( epoch_schedule, slot, NULL )!=fd_slot_to_epoch( epoch_schedule, slot+1UL, NULL ) ) {
     120           3 :     ulong activation_slot = slot+1UL;
     121           3 :     FD_LOG_DEBUG(( "feature %s pending, pre-populating activation at slot %lu", addr_b58, activation_slot ));
     122           3 :     fd_features_set( features, id, activation_slot );
     123           3 :   } else {
     124           0 :     FD_LOG_DEBUG(( "feature %s not activated at slot %lu", addr_b58, feature->activation_slot ));
     125           0 :   }
     126          30 : }
     127             : 
     128             : void
     129             : fd_features_restore( fd_bank_t *               bank,
     130             :                      fd_accdb_user_t *         accdb,
     131         150 :                      fd_funk_txn_xid_t const * xid ) {
     132             : 
     133         150 :   for( fd_feature_id_t const * id = fd_feature_iter_init();
     134       41250 :                                    !fd_feature_iter_done( id );
     135       41100 :                                id = fd_feature_iter_next( id ) ) {
     136       41100 :     fd_feature_restore( bank, accdb, xid, id, &id->id );
     137       41100 :   }
     138         150 : }

Generated by: LCOV version 1.14