Demote write locks on transaction program ids (#19593)
* Add feature * Demote write lock on program ids * Fixup bpf tests * Update MappedMessage::is_writable * Comma nit * Review comments
This commit is contained in:
@ -1049,6 +1049,7 @@ impl BankingStage {
|
||||
libsecp256k1_fail_on_bad_count: bool,
|
||||
cost_tracker: &Arc<RwLock<CostTracker>>,
|
||||
banking_stage_stats: &BankingStageStats,
|
||||
demote_program_write_locks: bool,
|
||||
) -> (Vec<SanitizedTransaction>, Vec<usize>, Vec<usize>) {
|
||||
let mut retryable_transaction_packet_indexes: Vec<usize> = vec![];
|
||||
|
||||
@ -1082,7 +1083,8 @@ impl BankingStage {
|
||||
verified_transactions_with_packet_indexes
|
||||
.into_iter()
|
||||
.filter_map(|(tx, tx_index)| {
|
||||
let result = cost_tracker_readonly.would_transaction_fit(&tx);
|
||||
let result = cost_tracker_readonly
|
||||
.would_transaction_fit(&tx, demote_program_write_locks);
|
||||
if result.is_err() {
|
||||
debug!("transaction {:?} would exceed limit: {:?}", tx, result);
|
||||
retryable_transaction_packet_indexes.push(tx_index);
|
||||
@ -1165,6 +1167,7 @@ impl BankingStage {
|
||||
bank.libsecp256k1_fail_on_bad_count(),
|
||||
cost_tracker,
|
||||
banking_stage_stats,
|
||||
bank.demote_program_write_locks(),
|
||||
);
|
||||
packet_conversion_time.stop();
|
||||
inc_new_counter_info!("banking_stage-packet_conversion", 1);
|
||||
@ -1201,7 +1204,10 @@ impl BankingStage {
|
||||
let mut cost_tracking_time = Measure::start("cost_tracking_time");
|
||||
transactions.iter().enumerate().for_each(|(index, tx)| {
|
||||
if unprocessed_tx_indexes.iter().all(|&i| i != index) {
|
||||
cost_tracker.write().unwrap().add_transaction_cost(tx);
|
||||
cost_tracker
|
||||
.write()
|
||||
.unwrap()
|
||||
.add_transaction_cost(tx, bank.demote_program_write_locks());
|
||||
}
|
||||
});
|
||||
cost_tracking_time.stop();
|
||||
@ -1268,6 +1274,7 @@ impl BankingStage {
|
||||
bank.libsecp256k1_fail_on_bad_count(),
|
||||
cost_tracker,
|
||||
banking_stage_stats,
|
||||
bank.demote_program_write_locks(),
|
||||
);
|
||||
unprocessed_packet_conversion_time.stop();
|
||||
|
||||
|
@ -113,7 +113,11 @@ impl CostModel {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn calculate_cost(&mut self, transaction: &SanitizedTransaction) -> &TransactionCost {
|
||||
pub fn calculate_cost(
|
||||
&mut self,
|
||||
transaction: &SanitizedTransaction,
|
||||
demote_program_write_locks: bool,
|
||||
) -> &TransactionCost {
|
||||
self.transaction_cost.reset();
|
||||
|
||||
// calculate transaction exeution cost
|
||||
@ -122,7 +126,7 @@ impl CostModel {
|
||||
// calculate account access cost
|
||||
let message = transaction.message();
|
||||
message.account_keys_iter().enumerate().for_each(|(i, k)| {
|
||||
let is_writable = message.is_writable(i);
|
||||
let is_writable = message.is_writable(i, demote_program_write_locks);
|
||||
|
||||
if is_writable {
|
||||
self.transaction_cost.writable_accounts.push(*k);
|
||||
@ -353,7 +357,7 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
let mut cost_model = CostModel::default();
|
||||
let tx_cost = cost_model.calculate_cost(&tx);
|
||||
let tx_cost = cost_model.calculate_cost(&tx, /*demote_program_write_locks=*/ true);
|
||||
assert_eq!(2 + 2, tx_cost.writable_accounts.len());
|
||||
assert_eq!(signer1.pubkey(), tx_cost.writable_accounts[0]);
|
||||
assert_eq!(signer2.pubkey(), tx_cost.writable_accounts[1]);
|
||||
@ -395,7 +399,7 @@ mod tests {
|
||||
cost_model
|
||||
.upsert_instruction_cost(&system_program::id(), expected_execution_cost)
|
||||
.unwrap();
|
||||
let tx_cost = cost_model.calculate_cost(&tx);
|
||||
let tx_cost = cost_model.calculate_cost(&tx, /*demote_program_write_locks=*/ true);
|
||||
assert_eq!(expected_account_cost, tx_cost.account_access_cost);
|
||||
assert_eq!(expected_execution_cost, tx_cost.execution_cost);
|
||||
assert_eq!(2, tx_cost.writable_accounts.len());
|
||||
@ -465,7 +469,8 @@ mod tests {
|
||||
} else {
|
||||
thread::spawn(move || {
|
||||
let mut cost_model = cost_model.write().unwrap();
|
||||
let tx_cost = cost_model.calculate_cost(&tx);
|
||||
let tx_cost = cost_model
|
||||
.calculate_cost(&tx, /*demote_program_write_locks=*/ true);
|
||||
assert_eq!(3, tx_cost.writable_accounts.len());
|
||||
assert_eq!(expected_account_cost, tx_cost.account_access_cost);
|
||||
})
|
||||
|
@ -46,18 +46,23 @@ impl CostTracker {
|
||||
pub fn would_transaction_fit(
|
||||
&self,
|
||||
transaction: &SanitizedTransaction,
|
||||
demote_program_write_locks: bool,
|
||||
) -> Result<(), CostModelError> {
|
||||
let mut cost_model = self.cost_model.write().unwrap();
|
||||
let tx_cost = cost_model.calculate_cost(transaction);
|
||||
let tx_cost = cost_model.calculate_cost(transaction, demote_program_write_locks);
|
||||
self.would_fit(
|
||||
&tx_cost.writable_accounts,
|
||||
&(tx_cost.account_access_cost + tx_cost.execution_cost),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn add_transaction_cost(&mut self, transaction: &SanitizedTransaction) {
|
||||
pub fn add_transaction_cost(
|
||||
&mut self,
|
||||
transaction: &SanitizedTransaction,
|
||||
demote_program_write_locks: bool,
|
||||
) {
|
||||
let mut cost_model = self.cost_model.write().unwrap();
|
||||
let tx_cost = cost_model.calculate_cost(transaction);
|
||||
let tx_cost = cost_model.calculate_cost(transaction, demote_program_write_locks);
|
||||
let cost = tx_cost.account_access_cost + tx_cost.execution_cost;
|
||||
for account_key in tx_cost.writable_accounts.iter() {
|
||||
*self
|
||||
|
Reference in New Issue
Block a user