Skip to content

Commit

Permalink
use new feature gate for cu depletion (#3994)
Browse files Browse the repository at this point in the history
(cherry picked from commit 11467d9)

# Conflicts:
#	programs/bpf_loader/src/lib.rs
#	programs/sbf/tests/programs.rs
#	sdk/feature-set/src/lib.rs
  • Loading branch information
jstarry authored and mergify[bot] committed Dec 11, 2024
1 parent 9e4dd59 commit e403be4
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 0 deletions.
21 changes: 21 additions & 0 deletions programs/bpf_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,27 @@ pub fn execute<'a, 'b: 'a>(
Err(Box::new(error) as Box<dyn std::error::Error>)
}
ProgramResult::Err(mut error) => {
<<<<<<< HEAD
=======
if invoke_context
.get_feature_set()
.is_active(&solana_feature_set::deplete_cu_meter_on_vm_failure::id())
&& !matches!(error, EbpfError::SyscallError(_))
{
// when an exception is thrown during the execution of a
// Basic Block (e.g., a null memory dereference or other
// faults), determining the exact number of CUs consumed
// up to the point of failure requires additional effort
// and is unnecessary since these cases are rare.
//
// In order to simplify CU tracking, simply consume all
// remaining compute units so that the block cost
// tracker uses the full requested compute unit cost for
// this failed transaction.
invoke_context.consume(invoke_context.get_remaining());
}

>>>>>>> 11467d9221 (use new feature gate for cu depletion (#3994))
if direct_mapping {
if let EbpfError::AccessViolation(
AccessType::Store,
Expand Down
131 changes: 131 additions & 0 deletions programs/sbf/tests/programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4603,6 +4603,137 @@ fn test_cpi_invalid_account_info_pointers() {

#[test]
#[cfg(feature = "sbf_rust")]
<<<<<<< HEAD
=======
fn test_deplete_cost_meter_with_access_violation() {
solana_logger::setup();
let GenesisConfigInfo {
genesis_config,
mint_keypair,
..
} = create_genesis_config(100_123_456_789);

for deplete_cu_meter_on_vm_failure in [false, true] {
let mut bank = Bank::new_for_tests(&genesis_config);
let feature_set = Arc::make_mut(&mut bank.feature_set);
// by default test banks have all features enabled, so we only need to
// disable when needed
if !deplete_cu_meter_on_vm_failure {
feature_set.deactivate(&feature_set::deplete_cu_meter_on_vm_failure::id());
}
let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
let mut bank_client = BankClient::new_shared(bank.clone());
let authority_keypair = Keypair::new();
let (bank, invoke_program_id) = load_upgradeable_program_and_advance_slot(
&mut bank_client,
bank_forks.as_ref(),
&mint_keypair,
&authority_keypair,
"solana_sbf_rust_invoke",
);

let account_keypair = Keypair::new();
let mint_pubkey = mint_keypair.pubkey();
let account_metas = vec![
AccountMeta::new(mint_pubkey, true),
AccountMeta::new(account_keypair.pubkey(), false),
AccountMeta::new_readonly(invoke_program_id, false),
];

let mut instruction_data = vec![TEST_WRITE_ACCOUNT, 2];
instruction_data.extend_from_slice(3usize.to_le_bytes().as_ref());
instruction_data.push(42);

let instruction = Instruction::new_with_bytes(
invoke_program_id,
&instruction_data,
account_metas.clone(),
);

let compute_unit_limit = 10_000u32;
let message = Message::new(
&[
ComputeBudgetInstruction::set_compute_unit_limit(compute_unit_limit),
instruction,
],
Some(&mint_keypair.pubkey()),
);
let tx = Transaction::new(&[&mint_keypair], message, bank.last_blockhash());

let result = load_execute_and_commit_transaction(&bank, tx).unwrap();

assert_eq!(
result.status.unwrap_err(),
TransactionError::InstructionError(1, InstructionError::ReadonlyDataModified)
);

if deplete_cu_meter_on_vm_failure {
assert_eq!(result.executed_units, u64::from(compute_unit_limit));
} else {
assert!(result.executed_units < u64::from(compute_unit_limit));
}
}
}

#[test]
#[cfg(feature = "sbf_rust")]
fn test_program_sbf_deplete_cost_meter_with_divide_by_zero() {
solana_logger::setup();

let GenesisConfigInfo {
genesis_config,
mint_keypair,
..
} = create_genesis_config(50);

for deplete_cu_meter_on_vm_failure in [false, true] {
let mut bank = Bank::new_for_tests(&genesis_config);
let feature_set = Arc::make_mut(&mut bank.feature_set);
// by default test banks have all features enabled, so we only need to
// disable when needed
if !deplete_cu_meter_on_vm_failure {
feature_set.deactivate(&feature_set::deplete_cu_meter_on_vm_failure::id());
}
let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
let mut bank_client = BankClient::new_shared(bank.clone());
let authority_keypair = Keypair::new();
let (bank, program_id) = load_upgradeable_program_and_advance_slot(
&mut bank_client,
bank_forks.as_ref(),
&mint_keypair,
&authority_keypair,
"solana_sbf_rust_divide_by_zero",
);

let instruction = Instruction::new_with_bytes(program_id, &[], vec![]);
let compute_unit_limit = 10_000;
let message = Message::new(
&[
ComputeBudgetInstruction::set_compute_unit_limit(compute_unit_limit),
instruction,
],
Some(&mint_keypair.pubkey()),
);
let tx = Transaction::new(&[&mint_keypair], message, bank.last_blockhash());

let result = load_execute_and_commit_transaction(&bank, tx).unwrap();

assert_eq!(
result.status.unwrap_err(),
TransactionError::InstructionError(1, InstructionError::ProgramFailedToComplete)
);

if deplete_cu_meter_on_vm_failure {
assert_eq!(result.executed_units, u64::from(compute_unit_limit));
} else {
assert!(result.executed_units < u64::from(compute_unit_limit));
}
}
}

#[test]
#[cfg(feature = "sbf_rust")]
>>>>>>> 11467d9221 (use new feature gate for cu depletion (#3994))
fn test_deny_executable_write() {
solana_logger::setup();

Expand Down
16 changes: 16 additions & 0 deletions sdk/feature-set/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,17 @@ pub mod migrate_stake_program_to_core_bpf {
solana_pubkey::declare_id!("6M4oQ6eXneVhtLoiAr4yRYQY43eVLjrKbiDZDJc892yk");
}

<<<<<<< HEAD
=======
pub mod deplete_cu_meter_on_vm_failure {
solana_pubkey::declare_id!("B7H2caeia4ZFcpE3QcgMqbiWiBtWrdBRBSJ1DY6Ktxbq");
}

pub mod reserve_minimal_cus_for_builtin_instructions {
solana_pubkey::declare_id!("C9oAhLxDBm3ssWtJx1yBGzPY55r2rArHmN1pbQn6HogH");
}

>>>>>>> 11467d9221 (use new feature gate for cu depletion (#3994))
lazy_static! {
/// Map of feature identifiers to user-visible description
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
Expand Down Expand Up @@ -1096,6 +1107,11 @@ lazy_static! {
(disable_account_loader_special_case::id(), "Disable account loader special case #3513"),
(enable_secp256r1_precompile::id(), "Enable secp256r1 precompile SIMD-0075"),
(migrate_stake_program_to_core_bpf::id(), "Migrate Stake program to Core BPF SIMD-0196 #3655"),
<<<<<<< HEAD
=======
(deplete_cu_meter_on_vm_failure::id(), "Deplete compute meter for vm errors SIMD-0182 #3993"),
(reserve_minimal_cus_for_builtin_instructions::id(), "Reserve minimal CUs for builtin instructions SIMD-170 #2562"),
>>>>>>> 11467d9221 (use new feature gate for cu depletion (#3994))
/*************** ADD NEW FEATURES HERE ***************/
]
.iter()
Expand Down

0 comments on commit e403be4

Please sign in to comment.