34
34
solana_rpc_client:: { nonblocking, rpc_client:: RpcClient } ,
35
35
solana_rpc_client_api:: request:: MAX_MULTIPLE_ACCOUNTS ,
36
36
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 ,
39
41
} ,
40
42
solana_sdk:: {
41
43
account:: { Account , AccountSharedData , ReadableAccount , WritableAccount } ,
44
46
commitment_config:: CommitmentConfig ,
45
47
epoch_schedule:: EpochSchedule ,
46
48
exit:: Exit ,
49
+ feature_set:: FeatureSet ,
47
50
fee_calculator:: FeeRateGovernor ,
48
51
instruction:: { AccountMeta , Instruction } ,
49
52
message:: Message ,
@@ -829,7 +832,7 @@ impl TestValidator {
829
832
) ;
830
833
}
831
834
832
- let mut genesis_config = create_genesis_config_with_leader_ex (
835
+ let mut genesis_config = create_genesis_config_with_leader_ex_no_features (
833
836
mint_lamports,
834
837
& mint_address,
835
838
& validator_identity. pubkey ( ) ,
@@ -852,23 +855,21 @@ impl TestValidator {
852
855
genesis_config. ticks_per_slot = ticks_per_slot;
853
856
}
854
857
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)
865
863
} else {
866
864
warn ! (
867
865
"Feature {:?} set for deactivation is not a known Feature public key" ,
868
- deactivate_feature_pk
869
- ) ;
866
+ feature ,
867
+ )
870
868
}
871
869
}
870
+ for feature in feature_set {
871
+ genesis_utils:: activate_feature ( & mut genesis_config, feature) ;
872
+ }
872
873
873
874
let ledger_path = match & config. ledger_path {
874
875
None => create_new_tmp_ledger ! ( & genesis_config) . 0 ,
@@ -1193,7 +1194,7 @@ impl Drop for TestValidator {
1193
1194
1194
1195
#[ cfg( test) ]
1195
1196
mod test {
1196
- use super :: * ;
1197
+ use { super :: * , solana_sdk :: feature :: Feature } ;
1197
1198
1198
1199
#[ test]
1199
1200
fn get_health ( ) {
@@ -1217,4 +1218,86 @@ mod test {
1217
1218
// `start()` blows up when run within tokio
1218
1219
let ( _test_validator, _payer) = TestValidatorGenesis :: default ( ) . start ( ) ;
1219
1220
}
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
+ }
1220
1303
}
0 commit comments