diff --git a/evm-utils/evm-rpc/src/lib.rs b/evm-utils/evm-rpc/src/lib.rs index 3a1fb35cd9..5ca1e93f77 100644 --- a/evm-utils/evm-rpc/src/lib.rs +++ b/evm-utils/evm-rpc/src/lib.rs @@ -641,6 +641,7 @@ pub mod trace { state_root: H256, unsigned_tx_fix: bool, clear_logs_on_error: bool, + accept_zero_gas_price_with_native_fee: bool, burn_gas_price: u64, ) -> BoxFuture>), Error>>; } diff --git a/rpc/src/evm_rpc_impl/mod.rs b/rpc/src/evm_rpc_impl/mod.rs index cce3ea49d9..af6ac8a197 100644 --- a/rpc/src/evm_rpc_impl/mod.rs +++ b/rpc/src/evm_rpc_impl/mod.rs @@ -763,6 +763,7 @@ impl TraceERPC for TraceErpcImpl { state_root: H256, unsigned_tx_fix: bool, clear_logs_on_error: bool, + accept_zero_gas_price_with_native_fee: bool, burn_gas_price: u64, ) -> BoxFuture>), Error>> { fn simulate_transaction( @@ -977,7 +978,7 @@ impl TraceERPC for TraceErpcImpl { evm_state.clone(), evm_state::ChainContext::new(last_hashes), evm_config, - evm_state::executor::FeatureSet::new(unsigned_tx_fix, clear_logs_on_error), + evm_state::executor::FeatureSet::new(unsigned_tx_fix, clear_logs_on_error, accept_zero_gas_price_with_native_fee), ); debug!("running on executor = {:?}", executor); let meta_keys = meta_keys diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 922ab2080a..2d8dd19cce 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -6888,6 +6888,10 @@ impl Bank { self.reset_all_sysvar_balances(); } + if new_feature_activations.contains(&feature_set::velas::lock_gas_station::id()) { + self.lock_gas_station_account(&solana_sdk::evm_gas_station::EVM_GAS_STATION_SOURCE_KEY); + } + if !debug_do_not_add_builtins { let apply_transitions_for_new_features = !init_finish_or_warp; self.apply_builtin_program_feature_transitions( @@ -7023,6 +7027,18 @@ impl Bank { } } + fn lock_gas_station_account(&mut self, source_address: &Pubkey) { + if let Some(source_acc) = self.get_account_with_fixed_root(source_address) { + if source_acc.executable() + && self + .get_account_with_fixed_root(&solana_sdk::evm_gas_station::id()) + .is_none() + { + self.store_account(&solana_sdk::evm_gas_station::id(), &source_acc); + } + } + } + fn replace_program_account( &mut self, old_address: &Pubkey, @@ -7273,6 +7289,7 @@ pub(crate) mod tests { clock::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT}, compute_budget::ComputeBudgetInstruction, epoch_schedule::MINIMUM_SLOTS_PER_EPOCH, + evm_gas_station, feature::Feature, feature_set::reject_empty_instruction_without_program, genesis_config::create_genesis_config, @@ -8698,6 +8715,64 @@ pub(crate) mod tests { assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 432_000)]); } + #[test] + fn test_lock_gas_station_feature_activation() { + let leader_pubkey = solana_sdk::pubkey::new_rand(); + let leader_lamports = 3; + let mut genesis_config = + create_genesis_config_with_leader(5, &leader_pubkey, leader_lamports).genesis_config; + genesis_config + .accounts + .remove(&feature_set::velas::lock_gas_station::id()); + let gas_station_source = Account::create( + 9999, + vec![0u8, 1, 2, 3], + bpf_loader::id(), + true, + Epoch::default(), + ); + genesis_config.accounts.insert( + evm_gas_station::EVM_GAS_STATION_SOURCE_KEY, + gas_station_source.clone(), + ); + + const SLOTS_PER_EPOCH: u64 = MINIMUM_SLOTS_PER_EPOCH as u64; + genesis_config.epoch_schedule = EpochSchedule::new(SLOTS_PER_EPOCH); + + let mut bank = Bank::new_for_tests(&genesis_config); + assert_eq!(DEFAULT_SLOTS_PER_EPOCH, 432_000); + assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32); + assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 0)); + assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 432_000)]); + assert!(bank + .feature_set + .inactive + .contains(&feature_set::velas::lock_gas_station::id())); + + bank = Bank::new_from_parent(&Arc::new(bank), &Pubkey::default(), 31); + assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32); + assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 31)); + + println!("Activating feature lock_gas_station"); + + let feature = Feature::default(); + assert_eq!(feature.activated_at, None); + bank.store_account( + &feature_set::velas::lock_gas_station::id(), + &feature::create_account(&feature, 42), + ); + + bank = new_from_parent(&Arc::new(bank)); + + let locked_acc = bank.get_account(&evm_gas_station::id()).unwrap(); + assert_eq!(locked_acc.data().to_vec(), gas_station_source.data); + assert!(locked_acc.executable()); + assert!(bank + .feature_set + .active + .contains_key(&feature_set::velas::lock_gas_station::id())); + } + #[test] fn test_rent_eager_across_epoch_with_gap_under_multi_epoch_cycle() { let leader_pubkey = solana_sdk::pubkey::new_rand(); diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index dfe9084e87..1098bed03c 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -73,3 +73,4 @@ extern crate serde_derive; #[macro_use] extern crate solana_frozen_abi_macro; +extern crate core; diff --git a/sdk/program/src/evm_gas_station.rs b/sdk/program/src/evm_gas_station.rs new file mode 100644 index 0000000000..5b291cb2fd --- /dev/null +++ b/sdk/program/src/evm_gas_station.rs @@ -0,0 +1,5 @@ +use crate::pubkey::Pubkey; +crate::declare_id!("EvmGasStation111111111111111111111111111111"); + +// TODO: set key +pub const EVM_GAS_STATION_SOURCE_KEY: Pubkey = Pubkey::new_from_array([9; 32]); \ No newline at end of file diff --git a/sdk/program/src/lib.rs b/sdk/program/src/lib.rs index b01dd83760..d09868769d 100644 --- a/sdk/program/src/lib.rs +++ b/sdk/program/src/lib.rs @@ -19,6 +19,7 @@ pub mod ed25519_program; pub mod entrypoint; pub mod entrypoint_deprecated; pub mod epoch_schedule; +pub mod evm_gas_station; pub mod evm_state; pub mod feature; pub mod fee_calculator; diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs index 5edb2365c2..140930a95b 100644 --- a/sdk/src/feature_set.rs +++ b/sdk/src/feature_set.rs @@ -433,6 +433,10 @@ pub mod velas { pub mod clear_logs_on_native_error { solana_sdk::declare_id!("BVF8r9JP1is4YworaZsiEk6fCSTiDxvD59Eo9kFyc85F"); } + + pub mod lock_gas_station { + solana_sdk::declare_id!("BVF8r9JP1is4YworaZsiEk6fCSTiDxvD59Eo9kFyc851"); // TODO: set key + } } lazy_static! { /// Map of feature identifiers to user-visible description @@ -547,6 +551,7 @@ lazy_static! { (velas::evm_instruction_borsh_serialization::id(), "Support for Borsh serialization for EVM instructions."), (velas::accept_zero_gas_price_with_native_fee::id(), "Accept evm transactions with native fee and zero gas price."), (velas::clear_logs_on_native_error::id(), "Clear evm logs from receipt if native transaction is failed."), + (velas::lock_gas_station::id(), "Lock gas station code."), /*************** ADD NEW FEATURES HERE ***************/ ] ).collect();