diff --git a/core/benches/banking_stage.rs b/core/benches/banking_stage.rs index 5ce40bcdc43e09..919701491c96f1 100644 --- a/core/benches/banking_stage.rs +++ b/core/benches/banking_stage.rs @@ -9,7 +9,7 @@ use rand::{thread_rng, Rng}; use rayon::prelude::*; use solana_core::banking_stage::{BankingStage, BankingStageStats}; use solana_core::cost_model::CostModel; -use solana_core::cost_tracker::CostTracker; +use solana_core::cost_tracker::{CostTracker, CostTrackerStats}; use solana_gossip::cluster_info::ClusterInfo; use solana_gossip::cluster_info::Node; use solana_ledger::blockstore_processor::process_entries; @@ -97,6 +97,7 @@ fn bench_consume_buffered(bencher: &mut Bencher) { &Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new( CostModel::new(std::u64::MAX, std::u64::MAX), ))))), + &mut CostTrackerStats::default(), ); }); diff --git a/core/src/banking_stage.rs b/core/src/banking_stage.rs index 8eb6f58f37fb41..020dfe45a8929f 100644 --- a/core/src/banking_stage.rs +++ b/core/src/banking_stage.rs @@ -1,7 +1,9 @@ //! The `banking_stage` processes Transaction messages. It is intended to be used //! to contruct a software pipeline. The stage uses all available CPU cores and //! can do its processing in parallel with signature verification on the GPU. -use crate::{cost_tracker::CostTracker, packet_hasher::PacketHasher}; +use crate::{ + cost_tracker::CostTracker, cost_tracker::CostTrackerStats, packet_hasher::PacketHasher, +}; use crossbeam_channel::{Receiver as CrossbeamReceiver, RecvTimeoutError}; use itertools::Itertools; use lru::LruCache; @@ -425,12 +427,16 @@ impl BankingStage { cost_tracker: &Arc>, bank: Arc, banking_stage_stats: &BankingStageStats, + cost_tracker_stats: &mut CostTrackerStats, ) { if !bank.feature_set.is_active(&feature_set::cost_model::id()) { return; } - cost_tracker.write().unwrap().reset_if_new_bank(bank.slot()); + cost_tracker + .write() + .unwrap() + .reset_if_new_bank(bank.slot(), cost_tracker_stats); banking_stage_stats .reset_cost_tracker_count .fetch_add(1, Ordering::Relaxed); @@ -448,6 +454,7 @@ impl BankingStage { banking_stage_stats: &BankingStageStats, recorder: &TransactionRecorder, cost_tracker: &Arc>, + cost_tracker_stats: &mut CostTrackerStats, ) { let mut rebuffered_packets_len = 0; let mut new_tx_count = 0; @@ -467,6 +474,7 @@ impl BankingStage { *next_leader, cost_tracker, banking_stage_stats, + cost_tracker_stats, ); Self::update_buffered_packets_with_new_unprocessed( original_unprocessed_indexes, @@ -479,6 +487,7 @@ impl BankingStage { cost_tracker, bank.clone(), banking_stage_stats, + cost_tracker_stats, ); let (processed, verified_txs_len, new_unprocessed_indexes) = Self::process_packets_transactions( @@ -491,6 +500,7 @@ impl BankingStage { gossip_vote_sender, banking_stage_stats, cost_tracker, + cost_tracker_stats, ); if processed < verified_txs_len || !Bank::should_bank_still_be_processing_txs( @@ -595,6 +605,7 @@ impl BankingStage { recorder: &TransactionRecorder, data_budget: &DataBudget, cost_tracker: &Arc>, + cost_tracker_stats: &mut CostTrackerStats, ) -> BufferedPacketsDecision { let bank_start; let ( @@ -610,6 +621,7 @@ impl BankingStage { cost_tracker, bank.clone(), banking_stage_stats, + cost_tracker_stats, ); }; ( @@ -643,6 +655,7 @@ impl BankingStage { banking_stage_stats, recorder, cost_tracker, + cost_tracker_stats, ); } BufferedPacketsDecision::Forward => { @@ -728,6 +741,7 @@ impl BankingStage { let socket = UdpSocket::bind("0.0.0.0:0").unwrap(); let mut buffered_packets = VecDeque::with_capacity(batch_limit); let banking_stage_stats = BankingStageStats::new(id); + let mut cost_tracker_stats = CostTrackerStats::default(); loop { while !buffered_packets.is_empty() { let decision = Self::process_buffered_packets( @@ -743,6 +757,7 @@ impl BankingStage { &recorder, data_budget, cost_tracker, + &mut cost_tracker_stats, ); if matches!(decision, BufferedPacketsDecision::Hold) || matches!(decision, BufferedPacketsDecision::ForwardAndHold) @@ -778,6 +793,7 @@ impl BankingStage { duplicates, &recorder, cost_tracker, + &mut cost_tracker_stats, ) { Ok(()) | Err(RecvTimeoutError::Timeout) => (), Err(RecvTimeoutError::Disconnected) => break, @@ -1121,6 +1137,7 @@ impl BankingStage { banking_stage_stats: &BankingStageStats, cost_model_enabled: bool, demote_program_write_locks: bool, + cost_tracker_stats: &mut CostTrackerStats, ) -> (Vec>, Vec, Vec) { let mut retryable_transaction_packet_indexes: Vec = vec![]; @@ -1154,7 +1171,11 @@ impl BankingStage { // into current bank if cost_model_enabled && cost_tracker_readonly - .would_transaction_fit(&tx, demote_program_write_locks) + .would_transaction_fit( + &tx, + demote_program_write_locks, + cost_tracker_stats, + ) .is_err() { debug!("transaction {:?} would exceed limit", tx); @@ -1242,6 +1263,7 @@ impl BankingStage { gossip_vote_sender: &ReplayVoteSender, banking_stage_stats: &BankingStageStats, cost_tracker: &Arc>, + cost_tracker_stats: &mut CostTrackerStats, ) -> (usize, usize, Vec) { let cost_model_enabled = bank.feature_set.is_active(&feature_set::cost_model::id()); @@ -1256,6 +1278,7 @@ impl BankingStage { banking_stage_stats, cost_model_enabled, bank.demote_program_write_locks(), + cost_tracker_stats, ); packet_conversion_time.stop(); inc_new_counter_info!("banking_stage-packet_conversion", 1); @@ -1293,10 +1316,11 @@ impl BankingStage { if cost_model_enabled { transactions.iter().enumerate().for_each(|(index, tx)| { if unprocessed_tx_indexes.iter().all(|&i| i != index) { - cost_tracker - .write() - .unwrap() - .add_transaction_cost(tx.transaction(), bank.demote_program_write_locks()); + cost_tracker.write().unwrap().add_transaction_cost( + tx.transaction(), + bank.demote_program_write_locks(), + cost_tracker_stats, + ); } }); } @@ -1344,6 +1368,7 @@ impl BankingStage { next_leader: Option, cost_tracker: &Arc>, banking_stage_stats: &BankingStageStats, + cost_tracker_stats: &mut CostTrackerStats, ) -> Vec { // Check if we are the next leader. If so, let's not filter the packets // as we'll filter it again while processing the packets. @@ -1367,6 +1392,7 @@ impl BankingStage { banking_stage_stats, cost_model_enabled, bank.demote_program_write_locks(), + cost_tracker_stats, ); unprocessed_packet_conversion_time.stop(); @@ -1428,6 +1454,7 @@ impl BankingStage { duplicates: &Arc, PacketHasher)>>, recorder: &TransactionRecorder, cost_tracker: &Arc>, + cost_tracker_stats: &mut CostTrackerStats, ) -> Result<(), RecvTimeoutError> { let mut recv_time = Measure::start("process_packets_recv"); let mms = verified_receiver.recv_timeout(recv_timeout)?; @@ -1468,7 +1495,12 @@ impl BankingStage { continue; } let (bank, bank_creation_time) = bank_start.unwrap(); - Self::reset_cost_tracker_if_new_bank(cost_tracker, bank.clone(), banking_stage_stats); + Self::reset_cost_tracker_if_new_bank( + cost_tracker, + bank.clone(), + banking_stage_stats, + cost_tracker_stats, + ); let (processed, verified_txs_len, unprocessed_indexes) = Self::process_packets_transactions( @@ -1481,6 +1513,7 @@ impl BankingStage { gossip_vote_sender, banking_stage_stats, cost_tracker, + cost_tracker_stats, ); new_tx_count += processed; @@ -1514,6 +1547,7 @@ impl BankingStage { next_leader, cost_tracker, banking_stage_stats, + cost_tracker_stats, ); Self::push_unprocessed( buffered_packets, @@ -1740,7 +1774,7 @@ mod tests { tpu_vote_receiver, gossip_verified_vote_receiver, None, - gossip_vote_sender, + vote_forward_sender, Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new( CostModel::default(), ))))), @@ -1791,7 +1825,7 @@ mod tests { tpu_vote_receiver, verified_gossip_vote_receiver, None, - gossip_vote_sender, + vote_forward_sender, Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new( CostModel::default(), ))))), @@ -2847,6 +2881,7 @@ mod tests { &Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new( CostModel::default(), ))))), + &mut CostTrackerStats::default(), ); assert_eq!(buffered_packets[0].1.len(), num_conflicting_transactions); // When the poh recorder has a bank, should process all non conflicting buffered packets. @@ -2866,6 +2901,7 @@ mod tests { &Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new( CostModel::default(), ))))), + &mut CostTrackerStats::default(), ); if num_expected_unprocessed == 0 { assert!(buffered_packets.is_empty()) @@ -2934,6 +2970,7 @@ mod tests { &Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new( CostModel::default(), ))))), + &mut CostTrackerStats::default(), ); // Check everything is correct. All indexes after `interrupted_iteration` @@ -3182,21 +3219,31 @@ mod tests { make_test_packets(vec![transfer_tx.clone(), transfer_tx.clone()], vote_indexes); let mut votes_only = false; - let (txs, tx_packet_index) = BankingStage::transactions_from_packets( + let (txs, tx_packet_index, _) = BankingStage::transactions_from_packets( &packets, &packet_indexes, false, votes_only, + &Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new(CostModel::default()))))), + &BankingStageStats::default(), + false, + false, + &mut CostTrackerStats::default(), ); assert_eq!(2, txs.len()); assert_eq!(vec![0, 1], tx_packet_index); votes_only = true; - let (txs, tx_packet_index) = BankingStage::transactions_from_packets( + let (txs, tx_packet_index, _) = BankingStage::transactions_from_packets( &packets, &packet_indexes, false, votes_only, + &Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new(CostModel::default()))))), + &BankingStageStats::default(), + false, + false, + &mut CostTrackerStats::default(), ); assert_eq!(0, txs.len()); assert_eq!(0, tx_packet_index.len()); @@ -3211,21 +3258,31 @@ mod tests { ); let mut votes_only = false; - let (txs, tx_packet_index) = BankingStage::transactions_from_packets( + let (txs, tx_packet_index, _) = BankingStage::transactions_from_packets( &packets, &packet_indexes, false, votes_only, + &Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new(CostModel::default()))))), + &BankingStageStats::default(), + false, + false, + &mut CostTrackerStats::default(), ); assert_eq!(3, txs.len()); assert_eq!(vec![0, 1, 2], tx_packet_index); votes_only = true; - let (txs, tx_packet_index) = BankingStage::transactions_from_packets( + let (txs, tx_packet_index, _) = BankingStage::transactions_from_packets( &packets, &packet_indexes, false, votes_only, + &Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new(CostModel::default()))))), + &BankingStageStats::default(), + false, + false, + &mut CostTrackerStats::default(), ); assert_eq!(2, txs.len()); assert_eq!(vec![0, 2], tx_packet_index); @@ -3240,21 +3297,31 @@ mod tests { ); let mut votes_only = false; - let (txs, tx_packet_index) = BankingStage::transactions_from_packets( + let (txs, tx_packet_index, _) = BankingStage::transactions_from_packets( &packets, &packet_indexes, false, votes_only, + &Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new(CostModel::default()))))), + &BankingStageStats::default(), + false, + false, + &mut CostTrackerStats::default(), ); assert_eq!(3, txs.len()); assert_eq!(vec![0, 1, 2], tx_packet_index); votes_only = true; - let (txs, tx_packet_index) = BankingStage::transactions_from_packets( + let (txs, tx_packet_index, _) = BankingStage::transactions_from_packets( &packets, &packet_indexes, false, votes_only, + &Arc::new(RwLock::new(CostTracker::new(Arc::new(RwLock::new(CostModel::default()))))), + &BankingStageStats::default(), + false, + false, + &mut CostTrackerStats::default(), ); assert_eq!(3, txs.len()); assert_eq!(vec![0, 1, 2], tx_packet_index); diff --git a/core/src/cost_model.rs b/core/src/cost_model.rs index 282064e8008a9f..b53340b8fbc19f 100644 --- a/core/src/cost_model.rs +++ b/core/src/cost_model.rs @@ -159,11 +159,7 @@ impl CostModel { transaction.signatures.len() as u64 * SIGNATURE_COST } - fn get_write_lock_cost( - &mut self, - transaction: &Transaction, - demote_program_write_locks: bool, - ) { + fn get_write_lock_cost(&mut self, transaction: &Transaction, demote_program_write_locks: bool) { let message = transaction.message(); message.account_keys.iter().enumerate().for_each(|(i, k)| { let is_writable = message.is_writable(i, demote_program_write_locks); @@ -177,13 +173,9 @@ impl CostModel { fn get_data_bytes_cost(&self, transaction: &Transaction) -> u64 { let mut data_bytes_cost: u64 = 0; - transaction - .message() - .instructions - .iter() - .for_each(|ix| { - data_bytes_cost += ix.data.len() as u64 / DATA_BYTES_UNITS; - }); + transaction.message().instructions.iter().for_each(|ix| { + data_bytes_cost += ix.data.len() as u64 / DATA_BYTES_UNITS; + }); data_bytes_cost } diff --git a/core/src/cost_tracker.rs b/core/src/cost_tracker.rs index b8309185e28be3..0243697a800225 100644 --- a/core/src/cost_tracker.rs +++ b/core/src/cost_tracker.rs @@ -13,6 +13,76 @@ use std::{ const WRITABLE_ACCOUNTS_PER_BLOCK: usize = 512; +// cist tracker stats reset for each bank +#[derive(Debug, Default)] +pub struct CostTrackerStats { + transaction_cost_histogram: histogram::Histogram, + writable_accounts_cost_histogram: histogram::Histogram, + block_cost: u64, + bank_slot: u64, +} + +impl CostTrackerStats { + pub fn new(bank_slot: Slot) -> Self { + CostTrackerStats { + bank_slot, + ..CostTrackerStats::default() + } + } + + fn report(&self) { + datapoint_info!( + "cost_tracker_stats", + ( + "transaction_cost_unit_min", + self.transaction_cost_histogram.minimum().unwrap_or(0), + i64 + ), + ( + "transaction_cost_unit_max", + self.transaction_cost_histogram.maximum().unwrap_or(0), + i64 + ), + ( + "transaction_cost_unit_mean", + self.transaction_cost_histogram.mean().unwrap_or(0), + i64 + ), + ( + "transaction_cost_unit_2nd_std", + self.transaction_cost_histogram + .percentile(95.0) + .unwrap_or(0), + i64 + ), + ( + "writable_accounts_cost_min", + self.writable_accounts_cost_histogram.minimum().unwrap_or(0), + i64 + ), + ( + "writable_accounts_cost_max", + self.writable_accounts_cost_histogram.maximum().unwrap_or(0), + i64 + ), + ( + "writable_accounts_cost_mean", + self.writable_accounts_cost_histogram.mean().unwrap_or(0), + i64 + ), + ( + "writable_accounts_cost_2nd_std", + self.writable_accounts_cost_histogram + .percentile(95.0) + .unwrap_or(0), + i64 + ), + ("block_cost", self.block_cost, i64), + ("bank_slot", self.bank_slot, i64), + ); + } +} + #[derive(Debug)] pub struct CostTracker { cost_model: Arc>, @@ -47,16 +117,18 @@ impl CostTracker { &self, transaction: &Transaction, demote_program_write_locks: bool, + stats: &mut CostTrackerStats, ) -> Result<(), &'static str> { let mut cost_model = self.cost_model.write().unwrap(); let tx_cost = cost_model.calculate_cost(transaction, demote_program_write_locks); - self.would_fit(&tx_cost.writable_accounts, &tx_cost.sum()) + self.would_fit(&tx_cost.writable_accounts, &tx_cost.sum(), stats) } pub fn add_transaction_cost( &mut self, transaction: &Transaction, demote_program_write_locks: bool, + stats: &mut CostTrackerStats, ) { let mut cost_model = self.cost_model.write().unwrap(); let tx_cost = cost_model.calculate_cost(transaction, demote_program_write_locks); @@ -68,25 +140,42 @@ impl CostTracker { .or_insert(0) += cost; } self.block_cost += cost; + + stats.block_cost += cost; } - pub fn reset_if_new_bank(&mut self, slot: Slot) { + pub fn reset_if_new_bank(&mut self, slot: Slot, stats: &mut CostTrackerStats) { if slot != self.current_bank_slot { + stats.bank_slot = self.current_bank_slot; + stats.report(); + *stats = CostTrackerStats::default(); + self.current_bank_slot = slot; self.cost_by_writable_accounts.clear(); self.block_cost = 0; } } - pub fn try_add(&mut self, transaction_cost: &TransactionCost) -> Result { + pub fn try_add( + &mut self, + transaction_cost: &TransactionCost, + stats: &mut CostTrackerStats, + ) -> Result { let cost = transaction_cost.sum(); - self.would_fit(&transaction_cost.writable_accounts, &cost)?; + self.would_fit(&transaction_cost.writable_accounts, &cost, stats)?; self.add_transaction(&transaction_cost.writable_accounts, &cost); Ok(self.block_cost) } - fn would_fit(&self, keys: &[Pubkey], cost: &u64) -> Result<(), &'static str> { + fn would_fit( + &self, + keys: &[Pubkey], + cost: &u64, + stats: &mut CostTrackerStats, + ) -> Result<(), &'static str> { + stats.transaction_cost_histogram.increment(*cost).unwrap(); + // check against the total package cost if self.block_cost + cost > self.block_cost_limit { return Err("would exceed block cost limit"); @@ -101,6 +190,11 @@ impl CostTracker { for account_key in keys.iter() { match self.cost_by_writable_accounts.get(&account_key) { Some(chained_cost) => { + stats + .writable_accounts_cost_histogram + .increment(*chained_cost) + .unwrap(); + if chained_cost + cost > self.account_cost_limit { return Err("would exceed account cost limit"); } else { @@ -210,7 +304,9 @@ mod tests { // build testee to have capacity for one simple transaction let mut testee = CostTracker::new(Arc::new(RwLock::new(CostModel::new(cost, cost)))); - assert!(testee.would_fit(&keys, &cost).is_ok()); + assert!(testee + .would_fit(&keys, &cost, &mut CostTrackerStats::default()) + .is_ok()); testee.add_transaction(&keys, &cost); assert_eq!(cost, testee.block_cost); } @@ -228,11 +324,15 @@ mod tests { cost1 + cost2, )))); { - assert!(testee.would_fit(&keys1, &cost1).is_ok()); + assert!(testee + .would_fit(&keys1, &cost1, &mut CostTrackerStats::default()) + .is_ok()); testee.add_transaction(&keys1, &cost1); } { - assert!(testee.would_fit(&keys2, &cost2).is_ok()); + assert!(testee + .would_fit(&keys2, &cost2, &mut CostTrackerStats::default()) + .is_ok()); testee.add_transaction(&keys2, &cost2); } assert_eq!(cost1 + cost2, testee.block_cost); @@ -253,11 +353,15 @@ mod tests { cost1 + cost2, )))); { - assert!(testee.would_fit(&keys1, &cost1).is_ok()); + assert!(testee + .would_fit(&keys1, &cost1, &mut CostTrackerStats::default()) + .is_ok()); testee.add_transaction(&keys1, &cost1); } { - assert!(testee.would_fit(&keys2, &cost2).is_ok()); + assert!(testee + .would_fit(&keys2, &cost2, &mut CostTrackerStats::default()) + .is_ok()); testee.add_transaction(&keys2, &cost2); } assert_eq!(cost1 + cost2, testee.block_cost); @@ -278,12 +382,16 @@ mod tests { )))); // should have room for first transaction { - assert!(testee.would_fit(&keys1, &cost1).is_ok()); + assert!(testee + .would_fit(&keys1, &cost1, &mut CostTrackerStats::default()) + .is_ok()); testee.add_transaction(&keys1, &cost1); } // but no more sapce on the same chain (same signer account) { - assert!(testee.would_fit(&keys2, &cost2).is_err()); + assert!(testee + .would_fit(&keys2, &cost2, &mut CostTrackerStats::default()) + .is_err()); } } @@ -302,12 +410,16 @@ mod tests { )))); // should have room for first transaction { - assert!(testee.would_fit(&keys1, &cost1).is_ok()); + assert!(testee + .would_fit(&keys1, &cost1, &mut CostTrackerStats::default()) + .is_ok()); testee.add_transaction(&keys1, &cost1); } // but no more room for package as whole { - assert!(testee.would_fit(&keys2, &cost2).is_err()); + assert!(testee + .would_fit(&keys2, &cost2, &mut CostTrackerStats::default()) + .is_err()); } } @@ -325,24 +437,30 @@ mod tests { )))); // should have room for first transaction { - assert!(testee.would_fit(&keys1, &cost1).is_ok()); + assert!(testee + .would_fit(&keys1, &cost1, &mut CostTrackerStats::default()) + .is_ok()); testee.add_transaction(&keys1, &cost1); assert_eq!(1, testee.cost_by_writable_accounts.len()); assert_eq!(cost1, testee.block_cost); } // but no more sapce on the same chain (same signer account) { - assert!(testee.would_fit(&keys2, &cost2).is_err()); + assert!(testee + .would_fit(&keys2, &cost2, &mut CostTrackerStats::default()) + .is_err()); } // reset the tracker { - testee.reset_if_new_bank(100); + testee.reset_if_new_bank(100, &mut CostTrackerStats::default()); assert_eq!(0, testee.cost_by_writable_accounts.len()); assert_eq!(0, testee.block_cost); } //now the second transaction can be added { - assert!(testee.would_fit(&keys2, &cost2).is_ok()); + assert!(testee + .would_fit(&keys2, &cost2, &mut CostTrackerStats::default()) + .is_ok()); } } @@ -371,7 +489,9 @@ mod tests { execution_cost: cost, ..TransactionCost::default() }; - assert!(testee.try_add(&tx_cost).is_ok()); + assert!(testee + .try_add(&tx_cost, &mut CostTrackerStats::default()) + .is_ok()); let stat = testee.get_stats(); assert_eq!(cost, stat.total_cost); assert_eq!(3, stat.number_of_accounts); @@ -389,7 +509,9 @@ mod tests { execution_cost: cost, ..TransactionCost::default() }; - assert!(testee.try_add(&tx_cost).is_ok()); + assert!(testee + .try_add(&tx_cost, &mut CostTrackerStats::default()) + .is_ok()); let stat = testee.get_stats(); assert_eq!(cost * 2, stat.total_cost); assert_eq!(3, stat.number_of_accounts); @@ -409,7 +531,9 @@ mod tests { execution_cost: cost, ..TransactionCost::default() }; - assert!(testee.try_add(&tx_cost).is_err()); + assert!(testee + .try_add(&tx_cost, &mut CostTrackerStats::default()) + .is_err()); let stat = testee.get_stats(); assert_eq!(cost * 2, stat.total_cost); assert_eq!(3, stat.number_of_accounts); diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index 1fd2f47deaeb6f..daace4c0e3f6ef 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -15,7 +15,7 @@ use solana_clap_utils::{ }, }; use solana_core::cost_model::CostModel; -use solana_core::cost_tracker::CostTracker; +use solana_core::cost_tracker::{CostTracker, CostTrackerStats}; use solana_ledger::entry::Entry; use solana_ledger::{ ancestor_iterator::AncestorIterator, @@ -744,6 +744,7 @@ fn compute_slot_cost(blockstore: &Blockstore, slot: Slot) -> Result<(), String> cost_model.initialize_cost_table(&blockstore.read_program_costs().unwrap()); let cost_model = Arc::new(RwLock::new(cost_model)); let mut cost_tracker = CostTracker::new(cost_model.clone()); + let mut cost_tracker_stats = CostTrackerStats::default(); for entry in &entries { transactions += entry.transactions.len(); @@ -751,7 +752,10 @@ fn compute_slot_cost(blockstore: &Blockstore, slot: Slot) -> Result<(), String> for transaction in &entry.transactions { programs += transaction.message().instructions.len(); let tx_cost = cost_model.calculate_cost(transaction, true); - if cost_tracker.try_add(tx_cost).is_err() { + if cost_tracker + .try_add(tx_cost, &mut cost_tracker_stats) + .is_err() + { println!( "Slot: {}, CostModel rejected transaction {:?}, stats {:?}!", slot, diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index a1c2edbed696e4..4f42601875a096 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -3068,7 +3068,7 @@ dependencies = [ [[package]] name = "solana-compute-budget-program" -version = "1.7.13" +version = "1.7.14" dependencies = [ "solana-sdk", ]