LCOV - code coverage report
Current view: top level - flamenco/features - fd_features.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 88 93 94.6 %
Date: 2026-07-04 05:35:33 Functions: 7 7 100.0 %

          Line data    Source code
       1             : #include "fd_features.h"
       2             : #include "../runtime/fd_system_ids.h"
       3             : #include "../runtime/sysvar/fd_sysvar_epoch_schedule.h"
       4             : 
       5             : FD_STATIC_ASSERT( sizeof  ( fd_feature_t                  )==9UL, layout );
       6             : FD_STATIC_ASSERT( offsetof( fd_feature_t, is_active       )==0UL, layout );
       7             : FD_STATIC_ASSERT( offsetof( fd_feature_t, activation_slot )==1UL, layout );
       8             : 
       9             : fd_feature_t *
      10             : fd_feature_decode( fd_feature_t * feature,
      11             :                    uchar const *  data,
      12         372 :                    ulong          data_sz ) {
      13         372 :   if( FD_UNLIKELY( data_sz < sizeof(fd_feature_t) ) ) return NULL;
      14         369 :   *feature = FD_LOAD( fd_feature_t, data );
      15         369 :   if( FD_UNLIKELY( feature->is_active>1 ) ) return NULL;
      16         369 :   return feature;
      17         369 : }
      18             : 
      19             : void
      20          15 : fd_features_enable_all( fd_features_t * f ) {
      21          15 :   for( fd_feature_id_t const * id = fd_feature_iter_init();
      22        4170 :        !fd_feature_iter_done( id );
      23        4155 :        id = fd_feature_iter_next( id ) ) {
      24        4155 :     fd_features_set( f, id, 0UL );
      25        4155 :   }
      26          15 : }
      27             : 
      28             : void
      29        6924 : fd_features_disable_all( fd_features_t * f ) {
      30        6924 :   for( fd_feature_id_t const * id = fd_feature_iter_init();
      31     1924872 :        !fd_feature_iter_done( id );
      32     1917948 :        id = fd_feature_iter_next( id ) ) {
      33     1917948 :     fd_features_set( f, id, FD_FEATURE_DISABLED );
      34     1917948 :   }
      35        6924 : }
      36             : 
      37             : void
      38        3747 : fd_features_enable_cleaned_up( fd_features_t * f ) {
      39        3747 :   for( fd_feature_id_t const * id = fd_feature_iter_init();
      40     1041666 :        !fd_feature_iter_done( id );
      41     1037919 :        id = fd_feature_iter_next( id ) ) {
      42     1037919 :     if( FD_LIKELY( id->cleaned_up ) ) {
      43      771882 :       fd_features_set( f, id, 0UL );
      44      771882 :     } else {
      45      266037 :       fd_features_set( f, id, FD_FEATURE_DISABLED );
      46      266037 :     }
      47     1037919 :   }
      48        3747 : }
      49             : 
      50             : void
      51          18 : fd_features_enable_one_offs( fd_features_t * f, char const * * one_offs, uint one_offs_cnt, ulong slot ) {
      52          18 :   uchar pubkey[32];
      53          72 :   for( uint i=0U; i<one_offs_cnt; i++ ) {
      54          54 :     fd_base58_decode_32( one_offs[i], pubkey );
      55          54 :     for( fd_feature_id_t const * id = fd_feature_iter_init();
      56       13230 :          !fd_feature_iter_done( id );
      57       13230 :          id = fd_feature_iter_next( id ) ) {
      58       13230 :       if( !memcmp( &id->id, pubkey, sizeof(fd_pubkey_t) ) ) {
      59          54 :         fd_features_set( f, id, slot );
      60          54 :         break;
      61          54 :       }
      62       13230 :     }
      63          54 :   }
      64          18 : }
      65             : 
      66             : static void
      67             : fd_feature_restore( fd_bank_t *             bank,
      68             :                     fd_accdb_t *            accdb,
      69             :                     fd_feature_id_t const * id,
      70       69804 :                     fd_pubkey_t const *     addr ) {
      71             : 
      72       69804 :   fd_features_t *             features       = &bank->f.features;
      73       69804 :   fd_epoch_schedule_t const * epoch_schedule = &bank->f.epoch_schedule;
      74       69804 :   ulong                       slot           = bank->f.slot;
      75             : 
      76       69804 :   if( FD_UNLIKELY( id->cleaned_up ) ) {
      77       51912 :     fd_features_set( features, id, 0UL );
      78       51912 :     return;
      79       51912 :   }
      80             : 
      81       17892 :   fd_features_set( features, id, FD_FEATURE_DISABLED );
      82             : 
      83             :   /* Skip reverted features */
      84       17892 :   if( FD_UNLIKELY( id->reverted ) ) return;
      85             : 
      86       13860 :   fd_acc_t acc = fd_accdb_read_one( accdb, bank->accdb_fork_id, addr->uc );
      87       13860 :   if( FD_UNLIKELY( !acc.lamports ) ) {
      88       13602 :     fd_accdb_unread_one( accdb, &acc );
      89       13602 :     return;
      90       13602 :   }
      91             : 
      92             :   /* Skip accounts that are not owned by the feature program
      93             :      https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L42-L44 */
      94         258 :   if( FD_UNLIKELY( memcmp( acc.owner, fd_solana_feature_program_id.uc, 32UL ) ) ) {
      95           6 :     fd_accdb_unread_one( accdb, &acc );
      96           6 :     return;
      97           6 :   }
      98             : 
      99             :   /* Account data size must be >= FD_FEATURE_SIZEOF (9 bytes)
     100             :      https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L45-L47 */
     101         252 :   if( FD_UNLIKELY( acc.data_len<sizeof(fd_feature_t) ) ) {
     102           6 :     fd_accdb_unread_one( accdb, &acc );
     103           6 :     return;
     104           6 :   }
     105             : 
     106             :   /* Deserialize the feature account data
     107             :      https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L48-L50 */
     108         246 :   fd_feature_t feature[1];
     109         246 :   if( FD_UNLIKELY( !fd_feature_decode( feature, acc.data, acc.data_len ) ) ) {
     110           0 :     fd_accdb_unread_one( accdb, &acc );
     111           0 :     return;
     112           0 :   }
     113         246 :   fd_accdb_unread_one( accdb, &acc );
     114             : 
     115         246 :   FD_BASE58_ENCODE_32_BYTES( addr->uc, addr_b58 );
     116         246 :   if( feature->is_active ) {
     117         243 :     FD_LOG_DEBUG(( "feature %s activated at slot %lu", addr_b58, feature->activation_slot ));
     118         243 :     fd_features_set( features, id, feature->activation_slot );
     119         243 :   } 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         246 : }
     127             : 
     128             : void
     129             : fd_features_restore( fd_bank_t *  bank,
     130         252 :                      fd_accdb_t * accdb ) {
     131         252 :   for( fd_feature_id_t const * id = fd_feature_iter_init();
     132       70056 :                                    !fd_feature_iter_done( id );
     133       69804 :                                id = fd_feature_iter_next( id ) ) {
     134       69804 :     fd_feature_restore( bank, accdb, id, &id->id );
     135       69804 :   }
     136         252 : }

Generated by: LCOV version 1.14