This repository has been archived by the owner on Jan 13, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
cost model could double count builtin instruction cost #32422
Merged
tao-stones
merged 1 commit into
solana-labs:master
from
tao-stones:cost-model-could-double-count-builtin-cost
Jul 17, 2023
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,9 +9,11 @@ use { | |
crate::{block_cost_limits::*, transaction_cost::TransactionCost}, | ||
log::*, | ||
solana_program_runtime::compute_budget::{ | ||
ComputeBudget, DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, | ||
ComputeBudget, DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_COMPUTE_UNIT_LIMIT, | ||
}, | ||
solana_sdk::{ | ||
borsh::try_from_slice_unchecked, | ||
compute_budget::{self, ComputeBudgetInstruction}, | ||
feature_set::{ | ||
add_set_tx_loaded_accounts_data_size_instruction, | ||
include_loaded_accounts_data_size_in_fee_calculation, | ||
|
@@ -92,16 +94,27 @@ impl CostModel { | |
let mut bpf_costs = 0u64; | ||
let mut loaded_accounts_data_size_cost = 0u64; | ||
let mut data_bytes_len_total = 0u64; | ||
let mut compute_unit_limit_is_set = false; | ||
|
||
for (program_id, instruction) in transaction.message().program_instructions_iter() { | ||
// to keep the same behavior, look for builtin first | ||
if let Some(builtin_cost) = BUILT_IN_INSTRUCTION_COSTS.get(program_id) { | ||
builtin_costs = builtin_costs.saturating_add(*builtin_cost); | ||
} else { | ||
bpf_costs = bpf_costs.saturating_add(DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT.into()); | ||
bpf_costs = bpf_costs | ||
.saturating_add(u64::from(DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT)) | ||
.min(u64::from(MAX_COMPUTE_UNIT_LIMIT)); | ||
tao-stones marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
data_bytes_len_total = | ||
data_bytes_len_total.saturating_add(instruction.data.len() as u64); | ||
|
||
if compute_budget::check_id(program_id) { | ||
if let Ok(ComputeBudgetInstruction::SetComputeUnitLimit(_)) = | ||
try_from_slice_unchecked(&instruction.data) | ||
Comment on lines
+112
to
+113
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this feels dirty, but is a quick fix. |
||
{ | ||
compute_unit_limit_is_set = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. have to explicitly check if |
||
} | ||
} | ||
} | ||
|
||
// calculate bpf cost based on compute budget instructions | ||
|
@@ -126,10 +139,15 @@ impl CostModel { | |
// by `bank`, therefore it should be considered as no execution cost by cost model. | ||
match result { | ||
Ok(_) => { | ||
// if tx contained user-space instructions and a more accurate estimate available correct it | ||
if bpf_costs > 0 { | ||
// if tx contained user-space instructions and a more accurate estimate available correct it, | ||
// where "user-space instructions" must be specifically checked by | ||
// 'compute_unit_limit_is_set' flag, because compute_budget does not distinguish | ||
// builtin and bpf instructions when calculating default compute-unit-limit. (see | ||
// compute_budget.rs test `test_process_mixed_instructions_without_compute_budget`) | ||
if bpf_costs > 0 && compute_unit_limit_is_set { | ||
bpf_costs = compute_budget.compute_unit_limit | ||
} | ||
|
||
if feature_set | ||
.is_active(&include_loaded_accounts_data_size_in_fee_calculation::id()) | ||
{ | ||
|
@@ -210,7 +228,7 @@ mod tests { | |
solana_sdk::{ | ||
compute_budget::{self, ComputeBudgetInstruction}, | ||
hash::Hash, | ||
instruction::CompiledInstruction, | ||
instruction::{CompiledInstruction, Instruction}, | ||
message::Message, | ||
signature::{Keypair, Signer}, | ||
system_instruction::{self}, | ||
|
@@ -675,4 +693,31 @@ mod tests { | |
CostModel::calculate_loaded_accounts_data_size_cost(&compute_budget) | ||
); | ||
} | ||
|
||
#[test] | ||
fn test_transaction_cost_with_mix_instruction_without_compute_budget() { | ||
let (mint_keypair, start_hash) = test_setup(); | ||
|
||
let transaction = | ||
SanitizedTransaction::from_transaction_for_tests(Transaction::new_signed_with_payer( | ||
&[ | ||
Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]), | ||
system_instruction::transfer(&mint_keypair.pubkey(), &Pubkey::new_unique(), 2), | ||
], | ||
Some(&mint_keypair.pubkey()), | ||
&[&mint_keypair], | ||
start_hash, | ||
)); | ||
// transaction has one builtin instruction, and one bpf instruction, no ComputeBudget::compute_unit_limit | ||
let expected_builtin_cost = *BUILT_IN_INSTRUCTION_COSTS | ||
.get(&solana_system_program::id()) | ||
.unwrap(); | ||
let expected_bpf_cost = DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT; | ||
tao-stones marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
let mut tx_cost = TransactionCost::default(); | ||
CostModel::get_transaction_cost(&mut tx_cost, &transaction, &FeatureSet::all_enabled()); | ||
|
||
assert_eq!(expected_builtin_cost, tx_cost.builtins_execution_cost); | ||
assert_eq!(expected_bpf_cost as u64, tx_cost.bpf_execution_cost); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably don't need to do this every time, right? just do it after the loop