diff --git a/fuzz/fixture/src/feature_set.rs b/fuzz/fixture/src/feature_set.rs index 36cdb78..26e3e6f 100644 --- a/fuzz/fixture/src/feature_set.rs +++ b/fuzz/fixture/src/feature_set.rs @@ -1,11 +1,23 @@ //! Runtime feature set. -use {super::proto::FeatureSet as ProtoFeatureSet, solana_sdk::feature_set::FeatureSet}; +use { + super::proto::FeatureSet as ProtoFeatureSet, + solana_sdk::{feature_set::FeatureSet, pubkey::Pubkey}, +}; + +// Omit "test features" (they have the same u64 ID). +pub static OMITTED_FEATURES: &[Pubkey] = &[ + solana_sdk::feature_set::disable_sbpf_v1_execution::id(), + solana_sdk::feature_set::reenable_sbpf_v1_execution::id(), +]; impl From for FeatureSet { fn from(value: ProtoFeatureSet) -> Self { let mut feature_set = Self::default(); - let inactive = std::mem::take(&mut feature_set.inactive); + let mut inactive = std::mem::take(&mut feature_set.inactive); + OMITTED_FEATURES.iter().for_each(|f| { + inactive.remove(f); + }); value.features.iter().for_each(|int_id| { let discriminator = int_id.to_le_bytes(); @@ -26,9 +38,13 @@ impl From for ProtoFeatureSet { let features = value .active .keys() - .map(|feature_id| { + .filter_map(|feature_id| { + if OMITTED_FEATURES.contains(feature_id) { + return None; + } let discriminator = &feature_id.to_bytes()[0..8]; - u64::from_le_bytes(discriminator.try_into().unwrap()) + let int_id = u64::from_le_bytes(discriminator.try_into().unwrap()); + Some(int_id) }) .collect(); diff --git a/harness/src/lib.rs b/harness/src/lib.rs index ee003ff..e150e66 100644 --- a/harness/src/lib.rs +++ b/harness/src/lib.rs @@ -79,9 +79,21 @@ impl Default for Mollusk { solana_runtime::message_processor=debug,\ solana_runtime::system_instruction_processor=trace", ); + #[cfg(feature = "fuzz")] + let feature_set = { + // Omit "test features" (they have the same u64 ID). + let mut fs = FeatureSet::all_enabled(); + fs.active + .remove(&solana_sdk::feature_set::disable_sbpf_v1_execution::id()); + fs.active + .remove(&solana_sdk::feature_set::reenable_sbpf_v1_execution::id()); + fs + }; + #[cfg(not(feature = "fuzz"))] + let feature_set = FeatureSet::all_enabled(); Self { compute_budget: ComputeBudget::default(), - feature_set: FeatureSet::all_enabled(), + feature_set, fee_structure: FeeStructure::default(), program_cache: ProgramCache::default(), sysvars: Sysvars::default(), diff --git a/harness/tests/dump_fixture.rs b/harness/tests/dump_fixture.rs index 413bf1b..8d3db8a 100644 --- a/harness/tests/dump_fixture.rs +++ b/harness/tests/dump_fixture.rs @@ -3,7 +3,10 @@ use { mollusk_svm::{result::Check, Mollusk}, mollusk_svm_fuzz_fixture::Fixture, - solana_sdk::{account::AccountSharedData, pubkey::Pubkey, system_instruction, system_program}, + solana_sdk::{ + account::AccountSharedData, feature_set::FeatureSet, pubkey::Pubkey, system_instruction, + system_program, + }, std::path::Path, }; @@ -59,6 +62,14 @@ fn clear() { } } +fn compare_feature_sets(from_fixture: &FeatureSet, from_mollusk: &FeatureSet) { + assert_eq!(from_fixture.active.len(), from_mollusk.active.len()); + assert_eq!(from_fixture.inactive.len(), from_mollusk.inactive.len()); + for f in from_fixture.active.keys() { + assert!(from_mollusk.active.get(&f).is_some()); + } +} + #[test] fn test_dump() { clear(); @@ -100,7 +111,8 @@ fn test_dump() { let blob_fixture_path = find_fixture(&FileType::Blob).unwrap(); let blob_fixture = Fixture::load_from_blob_file(&blob_fixture_path); assert_eq!(blob_fixture.input.compute_budget, mollusk.compute_budget); - assert_eq!(blob_fixture.input.feature_set, mollusk.feature_set); + // Feature set matches, but it can't guarantee sorting. + compare_feature_sets(&blob_fixture.input.feature_set, &mollusk.feature_set); assert_eq!(blob_fixture.input.sysvars.clock, mollusk.sysvars.clock); assert_eq!(blob_fixture.input.sysvars.rent, mollusk.sysvars.rent); assert_eq!(blob_fixture.input.program_id, instruction.program_id); @@ -115,7 +127,8 @@ fn test_dump() { let json_fixture_path = find_fixture(&FileType::Json).unwrap(); let json_fixture = Fixture::load_from_json_file(&json_fixture_path); assert_eq!(json_fixture.input.compute_budget, mollusk.compute_budget); - assert_eq!(json_fixture.input.feature_set, mollusk.feature_set); + // Feature set matches, but it can't guarantee sorting. + compare_feature_sets(&json_fixture.input.feature_set, &mollusk.feature_set); assert_eq!(json_fixture.input.sysvars.clock, mollusk.sysvars.clock); assert_eq!(json_fixture.input.sysvars.rent, mollusk.sysvars.rent); assert_eq!(json_fixture.input.program_id, instruction.program_id);