3434 solana_rpc_client:: { nonblocking, rpc_client:: RpcClient } ,
3535 solana_rpc_client_api:: request:: MAX_MULTIPLE_ACCOUNTS ,
3636 solana_runtime:: {
37- bank_forks:: BankForks , genesis_utils:: create_genesis_config_with_leader_ex,
38- runtime_config:: RuntimeConfig , snapshot_config:: SnapshotConfig ,
37+ bank_forks:: BankForks ,
38+ genesis_utils:: { self , create_genesis_config_with_leader_ex_no_features} ,
39+ runtime_config:: RuntimeConfig ,
40+ snapshot_config:: SnapshotConfig ,
3941 } ,
4042 solana_sdk:: {
4143 account:: { Account , AccountSharedData , ReadableAccount , WritableAccount } ,
4446 commitment_config:: CommitmentConfig ,
4547 epoch_schedule:: EpochSchedule ,
4648 exit:: Exit ,
49+ feature_set:: FeatureSet ,
4750 fee_calculator:: FeeRateGovernor ,
4851 instruction:: { AccountMeta , Instruction } ,
4952 message:: Message ,
@@ -829,7 +832,7 @@ impl TestValidator {
829832 ) ;
830833 }
831834
832- let mut genesis_config = create_genesis_config_with_leader_ex (
835+ let mut genesis_config = create_genesis_config_with_leader_ex_no_features (
833836 mint_lamports,
834837 & mint_address,
835838 & validator_identity. pubkey ( ) ,
@@ -852,23 +855,21 @@ impl TestValidator {
852855 genesis_config. ticks_per_slot = ticks_per_slot;
853856 }
854857
855- // Remove features tagged to deactivate
856- for deactivate_feature_pk in & config. deactivate_feature_set {
857- if FEATURE_NAMES . contains_key ( deactivate_feature_pk) {
858- match genesis_config. accounts . remove ( deactivate_feature_pk) {
859- Some ( _) => info ! ( "Feature for {:?} deactivated" , deactivate_feature_pk) ,
860- None => warn ! (
861- "Feature {:?} set for deactivation not found in genesis_config account list, ignored." ,
862- deactivate_feature_pk
863- ) ,
864- }
858+ // Only activate features which are not explicitly deactivated.
859+ let mut feature_set = FeatureSet :: default ( ) . inactive ;
860+ for feature in & config. deactivate_feature_set {
861+ if feature_set. remove ( feature) {
862+ info ! ( "Feature for {:?} deactivated" , feature)
865863 } else {
866864 warn ! (
867865 "Feature {:?} set for deactivation is not a known Feature public key" ,
868- deactivate_feature_pk
869- ) ;
866+ feature ,
867+ )
870868 }
871869 }
870+ for feature in feature_set {
871+ genesis_utils:: activate_feature ( & mut genesis_config, feature) ;
872+ }
872873
873874 let ledger_path = match & config. ledger_path {
874875 None => create_new_tmp_ledger ! ( & genesis_config) . 0 ,
@@ -1193,7 +1194,7 @@ impl Drop for TestValidator {
11931194
11941195#[ cfg( test) ]
11951196mod test {
1196- use super :: * ;
1197+ use { super :: * , solana_sdk :: feature :: Feature } ;
11971198
11981199 #[ test]
11991200 fn get_health ( ) {
@@ -1217,4 +1218,86 @@ mod test {
12171218 // `start()` blows up when run within tokio
12181219 let ( _test_validator, _payer) = TestValidatorGenesis :: default ( ) . start ( ) ;
12191220 }
1221+
1222+ #[ tokio:: test]
1223+ async fn test_deactivate_features ( ) {
1224+ let mut control = FeatureSet :: default ( ) . inactive ;
1225+ let mut deactivate_features = Vec :: new ( ) ;
1226+ [
1227+ solana_sdk:: feature_set:: deprecate_rewards_sysvar:: id ( ) ,
1228+ solana_sdk:: feature_set:: disable_fees_sysvar:: id ( ) ,
1229+ ]
1230+ . into_iter ( )
1231+ . for_each ( |feature| {
1232+ control. remove ( & feature) ;
1233+ deactivate_features. push ( feature) ;
1234+ } ) ;
1235+
1236+ // Convert to `Vec` so we can get a slice.
1237+ let control: Vec < Pubkey > = control. into_iter ( ) . collect ( ) ;
1238+
1239+ let ( test_validator, _payer) = TestValidatorGenesis :: default ( )
1240+ . deactivate_features ( & deactivate_features)
1241+ . start_async ( )
1242+ . await ;
1243+
1244+ let rpc_client = test_validator. get_async_rpc_client ( ) ;
1245+
1246+ // Our deactivated features should be inactive.
1247+ let inactive_feature_accounts = rpc_client
1248+ . get_multiple_accounts ( & deactivate_features)
1249+ . await
1250+ . unwrap ( ) ;
1251+ for f in inactive_feature_accounts {
1252+ assert ! ( f. is_none( ) ) ;
1253+ }
1254+
1255+ // Everything else should be active.
1256+ for chunk in control. chunks ( 100 ) {
1257+ let active_feature_accounts = rpc_client. get_multiple_accounts ( chunk) . await . unwrap ( ) ;
1258+ for f in active_feature_accounts {
1259+ let account = f. unwrap ( ) ; // Should be `Some`.
1260+ let feature_state: Feature = bincode:: deserialize ( account. data ( ) ) . unwrap ( ) ;
1261+ assert ! ( feature_state. activated_at. is_some( ) ) ;
1262+ }
1263+ }
1264+ }
1265+
1266+ #[ tokio:: test]
1267+ async fn test_override_feature_account ( ) {
1268+ let with_deactivate_flag = solana_sdk:: feature_set:: deprecate_rewards_sysvar:: id ( ) ;
1269+ let without_deactivate_flag = solana_sdk:: feature_set:: disable_fees_sysvar:: id ( ) ;
1270+
1271+ let owner = Pubkey :: new_unique ( ) ;
1272+ let account = || AccountSharedData :: new ( 100_000 , 0 , & owner) ;
1273+
1274+ let ( test_validator, _payer) = TestValidatorGenesis :: default ( )
1275+ . deactivate_features ( & [ with_deactivate_flag] ) // Just deactivate one feature.
1276+ . add_accounts ( [
1277+ ( with_deactivate_flag, account ( ) ) , // But add both accounts.
1278+ ( without_deactivate_flag, account ( ) ) ,
1279+ ] )
1280+ . start_async ( )
1281+ . await ;
1282+
1283+ let rpc_client = test_validator. get_async_rpc_client ( ) ;
1284+
1285+ let our_accounts = rpc_client
1286+ . get_multiple_accounts ( & [ with_deactivate_flag, without_deactivate_flag] )
1287+ . await
1288+ . unwrap ( ) ;
1289+
1290+ // The first one, where we provided `--deactivate-feature`, should be
1291+ // the account we provided.
1292+ let overriden_account = our_accounts[ 0 ] . as_ref ( ) . unwrap ( ) ;
1293+ assert_eq ! ( overriden_account. lamports, 100_000 ) ;
1294+ assert_eq ! ( overriden_account. data. len( ) , 0 ) ;
1295+ assert_eq ! ( overriden_account. owner, owner) ;
1296+
1297+ // The second one should be a feature account.
1298+ let feature_account = our_accounts[ 1 ] . as_ref ( ) . unwrap ( ) ;
1299+ assert_eq ! ( feature_account. owner, solana_sdk:: feature:: id( ) ) ;
1300+ let feature_state: Feature = bincode:: deserialize ( feature_account. data ( ) ) . unwrap ( ) ;
1301+ assert ! ( feature_state. activated_at. is_some( ) ) ;
1302+ }
12201303}
0 commit comments