Line data Source code
1 : #include "fd_runtime_init.h" 2 : #include "fd_runtime_err.h" 3 : #include <stdio.h> 4 : #include "../types/fd_types.h" 5 : #include "context/fd_exec_slot_ctx.h" 6 : #include "../../ballet/lthash/fd_lthash.h" 7 : #include "fd_system_ids.h" 8 : 9 : /* fd_feature_restore loads a feature from the accounts database and 10 : updates the bank's feature activation state, given a feature account 11 : address. */ 12 : 13 : static void 14 : fd_feature_restore( fd_features_t * features, 15 : fd_exec_slot_ctx_t * slot_ctx, 16 : fd_feature_id_t const * id, 17 : uchar const acct[ static 32 ], 18 0 : fd_spad_t * runtime_spad ) { 19 : 20 : /* Skip reverted features */ 21 0 : if( FD_UNLIKELY( id->reverted ) ) { 22 0 : return; 23 0 : } 24 : 25 0 : FD_TXN_ACCOUNT_DECL( acct_rec ); 26 0 : int err = fd_txn_account_init_from_funk_readonly( acct_rec, 27 0 : (fd_pubkey_t *)acct, 28 0 : slot_ctx->funk, 29 0 : slot_ctx->funk_txn ); 30 0 : if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) { 31 0 : return; 32 0 : } 33 : 34 : /* Skip accounts that are not owned by the feature program 35 : https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L42-L44 */ 36 0 : if( FD_UNLIKELY( memcmp( acct_rec->vt->get_owner( acct_rec ), fd_solana_feature_program_id.key, sizeof(fd_pubkey_t) ) ) ) { 37 0 : return; 38 0 : } 39 : 40 : /* Account data size must be >= FD_FEATURE_SIZEOF (9 bytes) 41 : https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L45-L47 */ 42 0 : if( FD_UNLIKELY( acct_rec->vt->get_data_len( acct_rec )<FD_FEATURE_SIZEOF ) ) { 43 0 : return; 44 0 : } 45 : 46 : /* Deserialize the feature account data 47 : https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L48-L50 */ 48 0 : FD_SPAD_FRAME_BEGIN( runtime_spad ) { 49 0 : int decode_err; 50 0 : fd_feature_t * feature = fd_bincode_decode_spad( 51 0 : feature, runtime_spad, 52 0 : acct_rec->vt->get_data( acct_rec ), 53 0 : acct_rec->vt->get_data_len( acct_rec ), 54 0 : &decode_err ); 55 0 : if( FD_UNLIKELY( decode_err ) ) { 56 0 : return; 57 0 : } 58 : 59 0 : if( feature->has_activated_at ) { 60 0 : FD_LOG_INFO(( "Feature %s activated at %lu", FD_BASE58_ENC_32_ALLOCA( acct ), feature->activated_at )); 61 0 : fd_features_set( features, id, feature->activated_at ); 62 0 : } else { 63 0 : FD_LOG_DEBUG(( "Feature %s not activated at %lu", FD_BASE58_ENC_32_ALLOCA( acct ), feature->activated_at )); 64 0 : } 65 : /* No need to call destroy, since we are using fd_spad allocator. */ 66 0 : } FD_SPAD_FRAME_END; 67 0 : } 68 : 69 : void 70 0 : fd_features_restore( fd_exec_slot_ctx_t * slot_ctx, fd_spad_t * runtime_spad ) { 71 0 : fd_features_t * features = fd_bank_features_modify( slot_ctx->bank ); 72 : 73 0 : for( fd_feature_id_t const * id = fd_feature_iter_init(); 74 0 : !fd_feature_iter_done( id ); 75 0 : id = fd_feature_iter_next( id ) ) { 76 0 : fd_feature_restore( features, slot_ctx, id, id->id.key, runtime_spad ); 77 0 : } 78 0 : }