Address review comments:

1. use was_executed to correctly identify transactions requires cost adjustment;
2. add function to specifically handle executino cost adjustment without have to copy accounts
This commit is contained in:
Tao Zhu 2022-04-10 17:18:58 -05:00 committed by Tao Zhu
parent 29ca21ed78
commit 094da35b91
2 changed files with 84 additions and 19 deletions

View File

@ -188,7 +188,7 @@ impl QosService {
// Only transactions that the qos service included have to be
// checked for remove or update/commit
if qos_inclusion_result.is_ok() {
if execution_result.was_executed_successfully() {
if execution_result.was_executed() {
cost_tracker.update_execution_cost(tx_cost, None);
} else {
cost_tracker.remove(tx_cost);

View File

@ -101,16 +101,14 @@ impl CostTracker {
actual_execution_units: Option<u64>,
) {
if let Some(actual_execution_units) = actual_execution_units {
let mut adjustment =
TransactionCost::new_with_capacity(estimated_tx_cost.writable_accounts.len());
adjustment
.writable_accounts
.extend(&estimated_tx_cost.writable_accounts);
adjustment.execution_cost = estimated_tx_cost
.execution_cost
.saturating_sub(actual_execution_units);
adjustment.is_simple_vote = estimated_tx_cost.is_simple_vote;
self.sub_transaction_cost(&adjustment);
let estimated_execution_units = estimated_tx_cost.execution_cost;
if actual_execution_units == estimated_execution_units {
return;
}
let adjustment =
i128::from(actual_execution_units) - i128::from(estimated_execution_units);
self.adjust_transaction_execution_cost(estimated_tx_cost, adjustment);
}
}
@ -235,7 +233,7 @@ impl CostTracker {
self.transaction_count = self.transaction_count.saturating_add(1);
}
fn sub_transaction_cost(&mut self, tx_cost: &TransactionCost) {
fn remove_transaction_cost(&mut self, tx_cost: &TransactionCost) {
let cost = tx_cost.sum();
for account_key in tx_cost.writable_accounts.iter() {
let account_cost = self
@ -251,11 +249,24 @@ impl CostTracker {
self.account_data_size = self
.account_data_size
.saturating_sub(tx_cost.account_data_size);
self.transaction_count = self.transaction_count.saturating_sub(1);
}
fn remove_transaction_cost(&mut self, tx_cost: &TransactionCost) {
self.sub_transaction_cost(tx_cost);
self.transaction_count = self.transaction_count.saturating_sub(1);
fn adjust_transaction_execution_cost(&mut self, tx_cost: &TransactionCost, adjustment: i128) {
for account_key in tx_cost.writable_accounts.iter() {
let account_cost = self
.cost_by_writable_accounts
.entry(*account_key)
.or_insert(0);
*account_cost = u64::try_from(i128::from(*account_cost).saturating_add(adjustment))
.unwrap_or(*account_cost);
}
self.block_cost = u64::try_from(i128::from(self.block_cost).saturating_add(adjustment))
.unwrap_or(self.block_cost);
if tx_cost.is_simple_vote {
self.vote_cost = u64::try_from(i128::from(self.vote_cost).saturating_add(adjustment))
.unwrap_or(self.vote_cost);
}
}
}
@ -633,10 +644,6 @@ mod tests {
#[test]
fn test_cost_tracker_try_add_is_atomic() {
let (mint_keypair, start_hash) = test_setup();
// build two mocking vote transactions with diff accounts
let (_tx1, _tx_cost1) = build_simple_vote_transaction(&mint_keypair, &start_hash);
let acct1 = Pubkey::new_unique();
let acct2 = Pubkey::new_unique();
let acct3 = Pubkey::new_unique();
@ -703,4 +710,62 @@ mod tests {
assert_eq!(acct2, costliest_account);
}
}
#[test]
fn test_adjust_transaction_execution_cost() {
let acct1 = Pubkey::new_unique();
let acct2 = Pubkey::new_unique();
let acct3 = Pubkey::new_unique();
let cost = 100;
let account_max = cost * 2;
let block_max = account_max * 3; // for three accts
let mut testee = CostTracker::new(account_max, block_max, block_max, None);
let tx_cost = TransactionCost {
writable_accounts: vec![acct1, acct2, acct3],
execution_cost: cost,
..TransactionCost::default()
};
let mut expected_block_cost = tx_cost.sum();
let expected_tx_count = 1;
assert!(testee.try_add(&tx_cost).is_ok());
assert_eq!(expected_block_cost, testee.block_cost());
assert_eq!(expected_tx_count, testee.transaction_count());
testee
.cost_by_writable_accounts
.iter()
.for_each(|(_key, units)| {
assert_eq!(expected_block_cost, *units);
});
// adjust up
{
let adjustment: i128 = 50;
testee.adjust_transaction_execution_cost(&tx_cost, adjustment);
expected_block_cost += 50;
assert_eq!(expected_block_cost, testee.block_cost());
assert_eq!(expected_tx_count, testee.transaction_count());
testee
.cost_by_writable_accounts
.iter()
.for_each(|(_key, units)| {
assert_eq!(expected_block_cost, *units);
});
}
// adjust down
{
let adjustment: i128 = -50;
testee.adjust_transaction_execution_cost(&tx_cost, adjustment);
expected_block_cost -= 50;
assert_eq!(expected_block_cost, testee.block_cost());
assert_eq!(expected_tx_count, testee.transaction_count());
testee
.cost_by_writable_accounts
.iter()
.for_each(|(_key, units)| {
assert_eq!(expected_block_cost, *units);
});
}
}
}