LCOV - code coverage report
Current view: top level - flamenco/features - fd_features.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 52 86 60.5 %
Date: 2026-02-13 06:06:24 Functions: 6 7 85.7 %

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

Generated by: LCOV version 1.14