2018-06-06 08:58:49 -07:00
|
|
|
//! The `banking_stage` processes Transaction messages. It is intended to be used
|
2022-03-21 16:35:31 -07:00
|
|
|
//! to construct a software pipeline. The stage uses all available CPU cores and
|
2018-06-06 08:58:49 -07:00
|
|
|
//! can do its processing in parallel with signature verification on the GPU.
|
2022-08-09 22:39:01 -07:00
|
|
|
|
2021-12-03 09:00:31 -08:00
|
|
|
use {
|
2023-01-20 10:10:47 -08:00
|
|
|
self::{
|
2023-02-15 08:52:13 -08:00
|
|
|
consumer::Consumer,
|
2023-01-20 10:10:47 -08:00
|
|
|
decision_maker::{BufferedPacketsDecision, DecisionMaker},
|
2023-01-25 12:31:59 -08:00
|
|
|
forwarder::Forwarder,
|
2023-01-20 10:10:47 -08:00
|
|
|
packet_receiver::PacketReceiver,
|
|
|
|
},
|
2022-02-11 00:07:45 -08:00
|
|
|
crate::{
|
2023-01-25 19:02:21 -08:00
|
|
|
banking_stage::committer::Committer,
|
2023-01-25 04:54:38 -08:00
|
|
|
banking_trace::BankingPacketReceiver,
|
2022-10-20 14:10:48 -07:00
|
|
|
latest_unprocessed_votes::{LatestUnprocessedVotes, VoteSource},
|
2023-02-15 08:52:13 -08:00
|
|
|
leader_slot_banking_stage_metrics::LeaderSlotMetricsTracker,
|
2022-02-11 00:07:45 -08:00
|
|
|
qos_service::QosService,
|
2022-06-08 22:25:37 -07:00
|
|
|
tracer_packet_stats::TracerPacketStats,
|
2022-10-20 14:10:48 -07:00
|
|
|
unprocessed_packet_batches::*,
|
2023-02-15 08:52:13 -08:00
|
|
|
unprocessed_transaction_storage::{ThreadType, UnprocessedTransactionStorage},
|
2022-02-11 00:07:45 -08:00
|
|
|
},
|
2023-01-25 04:54:38 -08:00
|
|
|
crossbeam_channel::RecvTimeoutError,
|
2022-01-19 00:13:07 -08:00
|
|
|
histogram::Histogram,
|
2023-01-25 12:31:59 -08:00
|
|
|
solana_client::connection_cache::ConnectionCache,
|
2023-01-20 10:02:29 -08:00
|
|
|
solana_gossip::cluster_info::ClusterInfo,
|
2023-02-15 08:52:13 -08:00
|
|
|
solana_ledger::blockstore_processor::TransactionStatusSender,
|
|
|
|
solana_measure::{measure, measure_us},
|
2023-01-25 12:31:59 -08:00
|
|
|
solana_perf::{data_budget::DataBudget, packet::PACKETS_PER_BATCH},
|
2023-03-06 09:13:28 -08:00
|
|
|
solana_poh::poh_recorder::PohRecorder,
|
2023-03-23 17:05:54 -07:00
|
|
|
solana_runtime::{
|
|
|
|
bank_forks::BankForks, prioritization_fee_cache::PrioritizationFeeCache,
|
|
|
|
vote_sender_types::ReplayVoteSender,
|
|
|
|
},
|
2023-02-15 08:52:13 -08:00
|
|
|
solana_sdk::{feature_set::allow_votes_to_directly_update_vote_state, timing::AtomicInterval},
|
2021-12-03 09:00:31 -08:00
|
|
|
std::{
|
2023-02-15 08:52:13 -08:00
|
|
|
cmp, env,
|
2021-12-03 09:00:31 -08:00
|
|
|
sync::{
|
|
|
|
atomic::{AtomicU64, AtomicUsize, Ordering},
|
2022-07-05 07:29:44 -07:00
|
|
|
Arc, RwLock,
|
2021-12-03 09:00:31 -08:00
|
|
|
},
|
|
|
|
thread::{self, Builder, JoinHandle},
|
|
|
|
time::{Duration, Instant},
|
2019-09-19 10:06:08 -07:00
|
|
|
},
|
2019-05-10 14:28:38 -07:00
|
|
|
};
|
2018-05-14 16:31:13 -07:00
|
|
|
|
2023-01-25 19:02:21 -08:00
|
|
|
pub mod committer;
|
2023-02-15 08:52:13 -08:00
|
|
|
pub mod consumer;
|
2023-01-20 10:10:47 -08:00
|
|
|
mod decision_maker;
|
2023-01-25 12:31:59 -08:00
|
|
|
mod forwarder;
|
2023-01-19 08:52:32 -08:00
|
|
|
mod packet_receiver;
|
|
|
|
|
2023-04-06 10:12:03 -07:00
|
|
|
#[allow(dead_code)]
|
|
|
|
mod thread_aware_account_locks;
|
|
|
|
|
2019-06-28 01:55:24 -07:00
|
|
|
// Fixed thread size seems to be fastest on GCP setup
|
2022-05-15 07:52:47 -07:00
|
|
|
pub const NUM_THREADS: u32 = 6;
|
2019-06-28 01:55:24 -07:00
|
|
|
|
2022-05-15 07:52:47 -07:00
|
|
|
const TOTAL_BUFFERED_PACKETS: usize = 700_000;
|
2018-09-26 05:52:13 -07:00
|
|
|
|
2021-10-07 02:38:23 -07:00
|
|
|
const NUM_VOTE_PROCESSING_THREADS: u32 = 2;
|
|
|
|
const MIN_THREADS_BANKING: u32 = 1;
|
2022-03-02 07:08:08 -08:00
|
|
|
const MIN_TOTAL_THREADS: u32 = NUM_VOTE_PROCESSING_THREADS + MIN_THREADS_BANKING;
|
2021-10-07 02:38:23 -07:00
|
|
|
|
2022-05-18 13:37:47 -07:00
|
|
|
const SLOT_BOUNDARY_CHECK_PERIOD: Duration = Duration::from_millis(10);
|
|
|
|
|
2021-02-12 03:27:37 -08:00
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct BankingStageStats {
|
2021-07-28 18:16:36 -07:00
|
|
|
last_report: AtomicInterval,
|
2021-02-12 03:27:37 -08:00
|
|
|
id: u32,
|
2021-12-16 09:44:10 -08:00
|
|
|
receive_and_buffer_packets_count: AtomicUsize,
|
2021-09-15 13:53:55 -07:00
|
|
|
dropped_packets_count: AtomicUsize,
|
2021-12-22 21:05:10 -08:00
|
|
|
pub(crate) dropped_duplicated_packets_count: AtomicUsize,
|
2021-02-12 03:27:37 -08:00
|
|
|
newly_buffered_packets_count: AtomicUsize,
|
|
|
|
current_buffered_packets_count: AtomicUsize,
|
|
|
|
rebuffered_packets_count: AtomicUsize,
|
|
|
|
consumed_buffered_packets_count: AtomicUsize,
|
2022-06-02 11:14:58 -07:00
|
|
|
forwarded_transaction_count: AtomicUsize,
|
|
|
|
forwarded_vote_count: AtomicUsize,
|
2022-01-19 00:13:07 -08:00
|
|
|
batch_packet_indexes_len: Histogram,
|
2021-04-12 23:28:08 -07:00
|
|
|
|
|
|
|
// Timing
|
|
|
|
consume_buffered_packets_elapsed: AtomicU64,
|
2021-12-16 09:44:10 -08:00
|
|
|
receive_and_buffer_packets_elapsed: AtomicU64,
|
2021-04-12 23:28:08 -07:00
|
|
|
filter_pending_packets_elapsed: AtomicU64,
|
2022-11-14 11:04:21 -08:00
|
|
|
pub(crate) packet_conversion_elapsed: AtomicU64,
|
2021-04-12 23:28:08 -07:00
|
|
|
transaction_processing_elapsed: AtomicU64,
|
2021-02-12 03:27:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl BankingStageStats {
|
|
|
|
pub fn new(id: u32) -> Self {
|
|
|
|
BankingStageStats {
|
|
|
|
id,
|
2022-01-19 00:13:07 -08:00
|
|
|
batch_packet_indexes_len: Histogram::configure()
|
|
|
|
.max_value(PACKETS_PER_BATCH as u64)
|
|
|
|
.build()
|
|
|
|
.unwrap(),
|
2021-02-12 03:27:37 -08:00
|
|
|
..BankingStageStats::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-14 13:52:45 -08:00
|
|
|
fn is_empty(&self) -> bool {
|
2021-12-16 09:44:10 -08:00
|
|
|
0 == self
|
|
|
|
.receive_and_buffer_packets_count
|
|
|
|
.load(Ordering::Relaxed) as u64
|
2021-12-14 13:52:45 -08:00
|
|
|
+ self.dropped_packets_count.load(Ordering::Relaxed) as u64
|
|
|
|
+ self
|
|
|
|
.dropped_duplicated_packets_count
|
|
|
|
.load(Ordering::Relaxed) as u64
|
|
|
|
+ self.newly_buffered_packets_count.load(Ordering::Relaxed) as u64
|
|
|
|
+ self.current_buffered_packets_count.load(Ordering::Relaxed) as u64
|
|
|
|
+ self.rebuffered_packets_count.load(Ordering::Relaxed) as u64
|
|
|
|
+ self.consumed_buffered_packets_count.load(Ordering::Relaxed) as u64
|
|
|
|
+ self
|
|
|
|
.consume_buffered_packets_elapsed
|
|
|
|
.load(Ordering::Relaxed)
|
2021-12-16 09:44:10 -08:00
|
|
|
+ self
|
|
|
|
.receive_and_buffer_packets_elapsed
|
|
|
|
.load(Ordering::Relaxed)
|
2021-12-14 13:52:45 -08:00
|
|
|
+ self.filter_pending_packets_elapsed.load(Ordering::Relaxed)
|
|
|
|
+ self.packet_conversion_elapsed.load(Ordering::Relaxed)
|
|
|
|
+ self.transaction_processing_elapsed.load(Ordering::Relaxed)
|
2022-06-02 11:14:58 -07:00
|
|
|
+ self.forwarded_transaction_count.load(Ordering::Relaxed) as u64
|
|
|
|
+ self.forwarded_vote_count.load(Ordering::Relaxed) as u64
|
2022-01-19 00:13:07 -08:00
|
|
|
+ self.batch_packet_indexes_len.entries()
|
2021-12-14 13:52:45 -08:00
|
|
|
}
|
|
|
|
|
2022-01-19 00:13:07 -08:00
|
|
|
fn report(&mut self, report_interval_ms: u64) {
|
2022-03-21 16:35:31 -07:00
|
|
|
// skip reporting metrics if stats is empty
|
2021-12-14 13:52:45 -08:00
|
|
|
if self.is_empty() {
|
|
|
|
return;
|
|
|
|
}
|
2021-07-28 18:16:36 -07:00
|
|
|
if self.last_report.should_update(report_interval_ms) {
|
2021-02-12 03:27:37 -08:00
|
|
|
datapoint_info!(
|
|
|
|
"banking_stage-loop-stats",
|
|
|
|
("id", self.id as i64, i64),
|
|
|
|
(
|
2021-12-16 09:44:10 -08:00
|
|
|
"receive_and_buffer_packets_count",
|
|
|
|
self.receive_and_buffer_packets_count
|
|
|
|
.swap(0, Ordering::Relaxed) as i64,
|
2021-02-12 03:27:37 -08:00
|
|
|
i64
|
|
|
|
),
|
2021-09-15 13:53:55 -07:00
|
|
|
(
|
|
|
|
"dropped_packets_count",
|
|
|
|
self.dropped_packets_count.swap(0, Ordering::Relaxed) as i64,
|
2021-02-12 03:27:37 -08:00
|
|
|
i64
|
|
|
|
),
|
2021-10-20 19:56:48 -07:00
|
|
|
(
|
|
|
|
"dropped_duplicated_packets_count",
|
|
|
|
self.dropped_duplicated_packets_count
|
|
|
|
.swap(0, Ordering::Relaxed) as i64,
|
|
|
|
i64
|
|
|
|
),
|
2021-02-12 03:27:37 -08:00
|
|
|
(
|
|
|
|
"newly_buffered_packets_count",
|
|
|
|
self.newly_buffered_packets_count.swap(0, Ordering::Relaxed) as i64,
|
|
|
|
i64
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"current_buffered_packets_count",
|
|
|
|
self.current_buffered_packets_count
|
|
|
|
.swap(0, Ordering::Relaxed) as i64,
|
|
|
|
i64
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"rebuffered_packets_count",
|
|
|
|
self.rebuffered_packets_count.swap(0, Ordering::Relaxed) as i64,
|
|
|
|
i64
|
|
|
|
),
|
2021-09-15 07:19:39 -07:00
|
|
|
(
|
|
|
|
"consumed_buffered_packets_count",
|
|
|
|
self.consumed_buffered_packets_count
|
|
|
|
.swap(0, Ordering::Relaxed) as i64,
|
|
|
|
i64
|
|
|
|
),
|
2022-06-02 11:14:58 -07:00
|
|
|
(
|
|
|
|
"forwarded_transaction_count",
|
|
|
|
self.forwarded_transaction_count.swap(0, Ordering::Relaxed) as i64,
|
|
|
|
i64
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"forwarded_vote_count",
|
|
|
|
self.forwarded_vote_count.swap(0, Ordering::Relaxed) as i64,
|
|
|
|
i64
|
|
|
|
),
|
2021-04-12 23:28:08 -07:00
|
|
|
(
|
|
|
|
"consume_buffered_packets_elapsed",
|
|
|
|
self.consume_buffered_packets_elapsed
|
|
|
|
.swap(0, Ordering::Relaxed) as i64,
|
|
|
|
i64
|
|
|
|
),
|
|
|
|
(
|
2021-12-16 09:44:10 -08:00
|
|
|
"receive_and_buffer_packets_elapsed",
|
|
|
|
self.receive_and_buffer_packets_elapsed
|
|
|
|
.swap(0, Ordering::Relaxed) as i64,
|
2021-04-12 23:28:08 -07:00
|
|
|
i64
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"filter_pending_packets_elapsed",
|
|
|
|
self.filter_pending_packets_elapsed
|
|
|
|
.swap(0, Ordering::Relaxed) as i64,
|
|
|
|
i64
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"packet_conversion_elapsed",
|
|
|
|
self.packet_conversion_elapsed.swap(0, Ordering::Relaxed) as i64,
|
|
|
|
i64
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"transaction_processing_elapsed",
|
|
|
|
self.transaction_processing_elapsed
|
|
|
|
.swap(0, Ordering::Relaxed) as i64,
|
|
|
|
i64
|
|
|
|
),
|
2022-01-19 00:13:07 -08:00
|
|
|
(
|
|
|
|
"packet_batch_indices_len_min",
|
|
|
|
self.batch_packet_indexes_len.minimum().unwrap_or(0) as i64,
|
|
|
|
i64
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"packet_batch_indices_len_max",
|
|
|
|
self.batch_packet_indexes_len.maximum().unwrap_or(0) as i64,
|
|
|
|
i64
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"packet_batch_indices_len_mean",
|
|
|
|
self.batch_packet_indexes_len.mean().unwrap_or(0) as i64,
|
|
|
|
i64
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"packet_batch_indices_len_90pct",
|
|
|
|
self.batch_packet_indexes_len.percentile(90.0).unwrap_or(0) as i64,
|
|
|
|
i64
|
|
|
|
)
|
2021-02-12 03:27:37 -08:00
|
|
|
);
|
2022-01-19 00:13:07 -08:00
|
|
|
self.batch_packet_indexes_len.clear();
|
2021-02-12 03:27:37 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-13 08:58:57 -07:00
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct BatchedTransactionDetails {
|
|
|
|
pub costs: BatchedTransactionCostDetails,
|
|
|
|
pub errors: BatchedTransactionErrorDetails,
|
|
|
|
}
|
|
|
|
|
2022-01-14 15:44:18 -08:00
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct BatchedTransactionCostDetails {
|
|
|
|
pub batched_signature_cost: u64,
|
|
|
|
pub batched_write_lock_cost: u64,
|
|
|
|
pub batched_data_bytes_cost: u64,
|
2022-04-19 11:25:47 -07:00
|
|
|
pub batched_builtins_execute_cost: u64,
|
|
|
|
pub batched_bpf_execute_cost: u64,
|
2022-01-14 15:44:18 -08:00
|
|
|
}
|
|
|
|
|
2022-03-13 08:58:57 -07:00
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct BatchedTransactionErrorDetails {
|
|
|
|
pub batched_retried_txs_per_block_limit_count: u64,
|
|
|
|
pub batched_retried_txs_per_vote_limit_count: u64,
|
|
|
|
pub batched_retried_txs_per_account_limit_count: u64,
|
|
|
|
pub batched_retried_txs_per_account_data_block_limit_count: u64,
|
|
|
|
pub batched_dropped_txs_per_account_data_total_limit_count: u64,
|
|
|
|
}
|
|
|
|
|
2018-06-06 08:58:49 -07:00
|
|
|
/// Stores the stage's thread handle and output receiver.
|
2018-05-14 16:31:13 -07:00
|
|
|
pub struct BankingStage {
|
2019-03-03 16:44:06 -08:00
|
|
|
bank_thread_hdls: Vec<JoinHandle<()>>,
|
2018-09-26 05:52:13 -07:00
|
|
|
}
|
|
|
|
|
2021-10-07 02:38:23 -07:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum ForwardOption {
|
|
|
|
NotForward,
|
|
|
|
ForwardTpuVote,
|
|
|
|
ForwardTransaction,
|
|
|
|
}
|
|
|
|
|
2022-09-14 10:40:44 -07:00
|
|
|
#[derive(Debug, Default)]
|
2022-07-05 21:24:58 -07:00
|
|
|
pub struct FilterForwardingResults {
|
2022-09-14 10:40:44 -07:00
|
|
|
pub(crate) total_forwardable_packets: usize,
|
|
|
|
pub(crate) total_tracer_packets_in_buffer: usize,
|
|
|
|
pub(crate) total_forwardable_tracer_packets: usize,
|
2022-09-29 14:33:40 -07:00
|
|
|
pub(crate) total_packet_conversion_us: u64,
|
|
|
|
pub(crate) total_filter_packets_us: u64,
|
2022-06-08 22:25:37 -07:00
|
|
|
}
|
|
|
|
|
2018-05-14 16:31:13 -07:00
|
|
|
impl BankingStage {
|
2018-07-05 14:41:53 -07:00
|
|
|
/// Create the stage using `bank`. Exit when `verified_receiver` is dropped.
|
2022-07-05 21:24:58 -07:00
|
|
|
#[allow(clippy::too_many_arguments)]
|
2018-05-14 16:31:13 -07:00
|
|
|
pub fn new(
|
2020-04-21 12:54:45 -07:00
|
|
|
cluster_info: &Arc<ClusterInfo>,
|
2022-07-05 07:29:44 -07:00
|
|
|
poh_recorder: &Arc<RwLock<PohRecorder>>,
|
2023-01-18 17:04:55 -08:00
|
|
|
non_vote_receiver: BankingPacketReceiver,
|
|
|
|
tpu_vote_receiver: BankingPacketReceiver,
|
|
|
|
gossip_vote_receiver: BankingPacketReceiver,
|
2019-11-20 15:43:10 -08:00
|
|
|
transaction_status_sender: Option<TransactionStatusSender>,
|
2023-01-17 21:14:04 -08:00
|
|
|
replay_vote_sender: ReplayVoteSender,
|
2022-07-11 08:53:18 -07:00
|
|
|
log_messages_bytes_limit: Option<usize>,
|
2022-06-08 04:57:12 -07:00
|
|
|
connection_cache: Arc<ConnectionCache>,
|
2022-07-05 21:24:58 -07:00
|
|
|
bank_forks: Arc<RwLock<BankForks>>,
|
2023-03-23 17:05:54 -07:00
|
|
|
prioritization_fee_cache: &Arc<PrioritizationFeeCache>,
|
2019-03-18 22:08:21 -07:00
|
|
|
) -> Self {
|
|
|
|
Self::new_num_threads(
|
|
|
|
cluster_info,
|
|
|
|
poh_recorder,
|
2023-01-18 17:04:55 -08:00
|
|
|
non_vote_receiver,
|
|
|
|
tpu_vote_receiver,
|
|
|
|
gossip_vote_receiver,
|
2019-06-28 01:55:24 -07:00
|
|
|
Self::num_threads(),
|
2019-11-20 15:43:10 -08:00
|
|
|
transaction_status_sender,
|
2023-01-17 21:14:04 -08:00
|
|
|
replay_vote_sender,
|
2022-07-11 08:53:18 -07:00
|
|
|
log_messages_bytes_limit,
|
2022-06-08 04:57:12 -07:00
|
|
|
connection_cache,
|
2022-07-05 21:24:58 -07:00
|
|
|
bank_forks,
|
2023-03-23 17:05:54 -07:00
|
|
|
prioritization_fee_cache,
|
2019-03-18 22:08:21 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-12-22 21:05:10 -08:00
|
|
|
#[allow(clippy::too_many_arguments)]
|
banking-bench: Add and rearrange options
- Add write-lock-contention option, replacing same_payer
- write-lock-contention also has a same-batch-only value, where
contention happens only inside batches, not between them
- Rename num-threads to batches-per-iteration, which is closer to what
it is actually doing.
- Add num-banking-threads as a new option
- Rename packets-per-chunk to packets-per-batch, because this is closer
to what's happening; and it was previously confusing that num-chunks
had little to do with packets-per-chunk.
Example output for a iterations=100 and a permutation of inputs:
contention,threads,batchsize,batchcount,tps
none, 3,192, 4,65290.30
none, 4,192, 4,77358.06
none, 5,192, 4,86436.65
none, 3, 12,64,43944.57
none, 4, 12,64,65852.15
none, 5, 12,64,70674.37
same-batch-only,3,192, 4,3928.21
same-batch-only,4,192, 4,6460.15
same-batch-only,5,192, 4,7242.85
same-batch-only,3, 12,64,11377.58
same-batch-only,4, 12,64,19582.79
same-batch-only,5, 12,64,24648.45
full, 3,192, 4,3914.26
full, 4,192, 4,2102.99
full, 5,192, 4,3041.87
full, 3, 12,64,11316.17
full, 4, 12,64,2224.99
full, 5, 12,64,5240.32
2022-04-14 06:54:38 -07:00
|
|
|
pub fn new_num_threads(
|
2020-04-21 12:54:45 -07:00
|
|
|
cluster_info: &Arc<ClusterInfo>,
|
2022-07-05 07:29:44 -07:00
|
|
|
poh_recorder: &Arc<RwLock<PohRecorder>>,
|
2023-01-18 17:04:55 -08:00
|
|
|
non_vote_receiver: BankingPacketReceiver,
|
|
|
|
tpu_vote_receiver: BankingPacketReceiver,
|
|
|
|
gossip_vote_receiver: BankingPacketReceiver,
|
2019-03-18 22:08:21 -07:00
|
|
|
num_threads: u32,
|
2019-11-20 15:43:10 -08:00
|
|
|
transaction_status_sender: Option<TransactionStatusSender>,
|
2023-01-17 21:14:04 -08:00
|
|
|
replay_vote_sender: ReplayVoteSender,
|
2022-07-11 08:53:18 -07:00
|
|
|
log_messages_bytes_limit: Option<usize>,
|
2022-06-08 04:57:12 -07:00
|
|
|
connection_cache: Arc<ConnectionCache>,
|
2022-07-05 21:24:58 -07:00
|
|
|
bank_forks: Arc<RwLock<BankForks>>,
|
2023-03-23 17:05:54 -07:00
|
|
|
prioritization_fee_cache: &Arc<PrioritizationFeeCache>,
|
2019-03-03 16:44:06 -08:00
|
|
|
) -> Self {
|
2022-03-02 07:08:08 -08:00
|
|
|
assert!(num_threads >= MIN_TOTAL_THREADS);
|
2018-09-26 05:52:13 -07:00
|
|
|
// Single thread to generate entries from many banks.
|
|
|
|
// This thread talks to poh_service and broadcasts the entries once they have been recorded.
|
2019-03-02 10:25:16 -08:00
|
|
|
// Once an entry has been recorded, its blockhash is registered with the bank.
|
2021-09-21 08:49:41 -07:00
|
|
|
let data_budget = Arc::new(DataBudget::default());
|
2022-05-04 19:50:56 -07:00
|
|
|
let batch_limit =
|
|
|
|
TOTAL_BUFFERED_PACKETS / ((num_threads - NUM_VOTE_PROCESSING_THREADS) as usize);
|
2022-10-20 14:10:48 -07:00
|
|
|
// Keeps track of extraneous vote transactions for the vote threads
|
|
|
|
let latest_unprocessed_votes = Arc::new(LatestUnprocessedVotes::new());
|
|
|
|
let should_split_voting_threads = bank_forks
|
|
|
|
.read()
|
|
|
|
.map(|bank_forks| {
|
|
|
|
let bank = bank_forks.root_bank();
|
|
|
|
bank.feature_set
|
|
|
|
.is_active(&allow_votes_to_directly_update_vote_state::id())
|
|
|
|
})
|
|
|
|
.unwrap_or(false);
|
2018-09-26 05:52:13 -07:00
|
|
|
// Many banks that process transactions in parallel.
|
2019-03-27 04:37:36 -07:00
|
|
|
let bank_thread_hdls: Vec<JoinHandle<()>> = (0..num_threads)
|
2023-02-03 11:35:43 -08:00
|
|
|
.map(|id| {
|
2023-01-18 17:04:55 -08:00
|
|
|
let (packet_receiver, unprocessed_transaction_storage) =
|
2023-02-03 11:35:43 -08:00
|
|
|
match (id, should_split_voting_threads) {
|
2022-10-20 14:10:48 -07:00
|
|
|
(0, false) => (
|
2023-01-18 17:04:55 -08:00
|
|
|
gossip_vote_receiver.clone(),
|
2022-10-20 14:10:48 -07:00
|
|
|
UnprocessedTransactionStorage::new_transaction_storage(
|
|
|
|
UnprocessedPacketBatches::with_capacity(batch_limit),
|
|
|
|
ThreadType::Voting(VoteSource::Gossip),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
(0, true) => (
|
2023-01-18 17:04:55 -08:00
|
|
|
gossip_vote_receiver.clone(),
|
2022-10-20 14:10:48 -07:00
|
|
|
UnprocessedTransactionStorage::new_vote_storage(
|
|
|
|
latest_unprocessed_votes.clone(),
|
|
|
|
VoteSource::Gossip,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
(1, false) => (
|
2023-01-18 17:04:55 -08:00
|
|
|
tpu_vote_receiver.clone(),
|
2022-10-20 14:10:48 -07:00
|
|
|
UnprocessedTransactionStorage::new_transaction_storage(
|
|
|
|
UnprocessedPacketBatches::with_capacity(batch_limit),
|
|
|
|
ThreadType::Voting(VoteSource::Tpu),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
(1, true) => (
|
2023-01-18 17:04:55 -08:00
|
|
|
tpu_vote_receiver.clone(),
|
2022-10-20 14:10:48 -07:00
|
|
|
UnprocessedTransactionStorage::new_vote_storage(
|
|
|
|
latest_unprocessed_votes.clone(),
|
|
|
|
VoteSource::Tpu,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
_ => (
|
2023-01-18 17:04:55 -08:00
|
|
|
non_vote_receiver.clone(),
|
2022-10-20 14:10:48 -07:00
|
|
|
UnprocessedTransactionStorage::new_transaction_storage(
|
|
|
|
UnprocessedPacketBatches::with_capacity(batch_limit),
|
|
|
|
ThreadType::Transactions,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
};
|
2019-04-17 21:07:45 -07:00
|
|
|
|
2023-02-03 11:35:43 -08:00
|
|
|
let mut packet_receiver = PacketReceiver::new(id, packet_receiver);
|
2019-03-03 16:44:06 -08:00
|
|
|
let poh_recorder = poh_recorder.clone();
|
2023-02-01 09:18:40 -08:00
|
|
|
|
2023-02-09 13:22:42 -08:00
|
|
|
let committer = Committer::new(
|
|
|
|
transaction_status_sender.clone(),
|
|
|
|
replay_vote_sender.clone(),
|
2023-03-23 17:05:54 -07:00
|
|
|
prioritization_fee_cache.clone(),
|
2023-02-09 13:22:42 -08:00
|
|
|
);
|
2023-02-01 09:18:40 -08:00
|
|
|
let decision_maker = DecisionMaker::new(cluster_info.id(), poh_recorder.clone());
|
2023-02-02 11:09:08 -08:00
|
|
|
let forwarder = Forwarder::new(
|
|
|
|
poh_recorder.clone(),
|
|
|
|
bank_forks.clone(),
|
|
|
|
cluster_info.clone(),
|
|
|
|
connection_cache.clone(),
|
|
|
|
data_budget.clone(),
|
|
|
|
);
|
2023-03-06 09:13:28 -08:00
|
|
|
let consumer = Consumer::new(
|
|
|
|
committer,
|
2023-03-21 21:19:20 -07:00
|
|
|
poh_recorder.read().unwrap().new_recorder(),
|
2023-03-06 09:13:28 -08:00
|
|
|
QosService::new(id),
|
|
|
|
log_messages_bytes_limit,
|
|
|
|
);
|
2023-02-01 09:18:40 -08:00
|
|
|
|
2018-09-26 05:52:13 -07:00
|
|
|
Builder::new()
|
2023-02-03 11:35:43 -08:00
|
|
|
.name(format!("solBanknStgTx{id:02}"))
|
2018-09-26 05:52:13 -07:00
|
|
|
.spawn(move || {
|
2019-04-09 11:17:15 -07:00
|
|
|
Self::process_loop(
|
2023-02-03 11:35:43 -08:00
|
|
|
&mut packet_receiver,
|
2023-02-01 09:18:40 -08:00
|
|
|
&decision_maker,
|
2023-02-02 11:09:08 -08:00
|
|
|
&forwarder,
|
2023-03-06 09:13:28 -08:00
|
|
|
&consumer,
|
2023-02-03 11:35:43 -08:00
|
|
|
id,
|
2022-10-20 14:10:48 -07:00
|
|
|
unprocessed_transaction_storage,
|
2019-04-09 11:17:15 -07:00
|
|
|
);
|
2018-12-07 19:01:28 -08:00
|
|
|
})
|
|
|
|
.unwrap()
|
|
|
|
})
|
|
|
|
.collect();
|
2019-03-03 16:44:06 -08:00
|
|
|
Self { bank_thread_hdls }
|
|
|
|
}
|
|
|
|
|
2020-08-07 11:21:35 -07:00
|
|
|
#[allow(clippy::too_many_arguments)]
|
2019-05-01 15:13:10 -07:00
|
|
|
fn process_buffered_packets(
|
2023-02-01 09:18:40 -08:00
|
|
|
decision_maker: &DecisionMaker,
|
2023-02-02 11:09:08 -08:00
|
|
|
forwarder: &Forwarder,
|
2023-03-06 09:13:28 -08:00
|
|
|
consumer: &Consumer,
|
2022-10-20 14:10:48 -07:00
|
|
|
unprocessed_transaction_storage: &mut UnprocessedTransactionStorage,
|
2021-02-12 03:27:37 -08:00
|
|
|
banking_stage_stats: &BankingStageStats,
|
2022-02-11 00:07:45 -08:00
|
|
|
slot_metrics_tracker: &mut LeaderSlotMetricsTracker,
|
2022-06-08 22:25:37 -07:00
|
|
|
tracer_packet_stats: &mut TracerPacketStats,
|
2022-05-18 13:37:47 -07:00
|
|
|
) {
|
2022-10-20 14:10:48 -07:00
|
|
|
if unprocessed_transaction_storage.should_not_process() {
|
|
|
|
return;
|
|
|
|
}
|
2023-03-15 19:39:48 -07:00
|
|
|
let (decision, make_decision_time) =
|
|
|
|
measure!(decision_maker.make_consume_or_forward_decision());
|
|
|
|
let metrics_action = slot_metrics_tracker.check_leader_slot_boundary(decision.bank_start());
|
2022-02-16 22:14:32 -08:00
|
|
|
slot_metrics_tracker.increment_make_decision_us(make_decision_time.as_us());
|
2019-07-18 14:54:27 -07:00
|
|
|
|
2019-04-13 23:19:54 -07:00
|
|
|
match decision {
|
2022-12-02 08:07:01 -08:00
|
|
|
BufferedPacketsDecision::Consume(bank_start) => {
|
2022-06-13 15:03:34 -07:00
|
|
|
// Take metrics action before consume packets (potentially resetting the
|
|
|
|
// slot metrics tracker to the next slot) so that we don't count the
|
|
|
|
// packet processing metrics from the next slot towards the metrics
|
|
|
|
// of the previous slot
|
|
|
|
slot_metrics_tracker.apply_action(metrics_action);
|
2022-06-06 18:21:05 -07:00
|
|
|
let (_, consume_buffered_packets_time) = measure!(
|
2023-03-06 09:13:28 -08:00
|
|
|
consumer.consume_buffered_packets(
|
2022-12-02 08:07:01 -08:00
|
|
|
&bank_start,
|
2022-10-20 14:10:48 -07:00
|
|
|
unprocessed_transaction_storage,
|
2022-06-06 18:21:05 -07:00
|
|
|
banking_stage_stats,
|
|
|
|
slot_metrics_tracker,
|
|
|
|
),
|
2022-02-16 22:14:32 -08:00
|
|
|
"consume_buffered_packets",
|
2020-01-02 19:50:43 -08:00
|
|
|
);
|
2022-02-16 22:14:32 -08:00
|
|
|
slot_metrics_tracker
|
|
|
|
.increment_consume_buffered_packets_us(consume_buffered_packets_time.as_us());
|
2019-04-13 23:19:54 -07:00
|
|
|
}
|
|
|
|
BufferedPacketsDecision::Forward => {
|
2023-02-02 11:09:08 -08:00
|
|
|
let ((), forward_us) = measure_us!(forwarder.handle_forwarding(
|
|
|
|
unprocessed_transaction_storage,
|
|
|
|
false,
|
|
|
|
slot_metrics_tracker,
|
|
|
|
banking_stage_stats,
|
|
|
|
tracer_packet_stats,
|
|
|
|
));
|
|
|
|
slot_metrics_tracker.increment_forward_us(forward_us);
|
2022-06-13 15:03:34 -07:00
|
|
|
// Take metrics action after forwarding packets to include forwarded
|
|
|
|
// metrics into current slot
|
|
|
|
slot_metrics_tracker.apply_action(metrics_action);
|
2021-03-03 10:23:05 -08:00
|
|
|
}
|
|
|
|
BufferedPacketsDecision::ForwardAndHold => {
|
2023-02-02 11:09:08 -08:00
|
|
|
let ((), forward_and_hold_us) = measure_us!(forwarder.handle_forwarding(
|
|
|
|
unprocessed_transaction_storage,
|
|
|
|
true,
|
|
|
|
slot_metrics_tracker,
|
|
|
|
banking_stage_stats,
|
|
|
|
tracer_packet_stats,
|
|
|
|
));
|
|
|
|
slot_metrics_tracker.increment_forward_and_hold_us(forward_and_hold_us);
|
2022-06-13 15:03:34 -07:00
|
|
|
// Take metrics action after forwarding packets
|
|
|
|
slot_metrics_tracker.apply_action(metrics_action);
|
2019-04-13 23:19:54 -07:00
|
|
|
}
|
2020-01-02 19:50:43 -08:00
|
|
|
_ => (),
|
2019-03-08 16:48:15 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-17 10:14:21 -07:00
|
|
|
fn process_loop(
|
2023-02-03 11:35:43 -08:00
|
|
|
packet_receiver: &mut PacketReceiver,
|
2023-02-01 09:18:40 -08:00
|
|
|
decision_maker: &DecisionMaker,
|
2023-02-02 11:09:08 -08:00
|
|
|
forwarder: &Forwarder,
|
2023-03-06 09:13:28 -08:00
|
|
|
consumer: &Consumer,
|
2019-05-20 09:15:00 -07:00
|
|
|
id: u32,
|
2022-10-20 14:10:48 -07:00
|
|
|
mut unprocessed_transaction_storage: UnprocessedTransactionStorage,
|
2019-03-03 16:44:06 -08:00
|
|
|
) {
|
2022-01-19 00:13:07 -08:00
|
|
|
let mut banking_stage_stats = BankingStageStats::new(id);
|
2022-06-08 22:25:37 -07:00
|
|
|
let mut tracer_packet_stats = TracerPacketStats::new(id);
|
2022-05-18 13:37:47 -07:00
|
|
|
|
2022-02-11 00:07:45 -08:00
|
|
|
let mut slot_metrics_tracker = LeaderSlotMetricsTracker::new(id);
|
2022-05-18 13:37:47 -07:00
|
|
|
let mut last_metrics_update = Instant::now();
|
|
|
|
|
2019-03-03 16:44:06 -08:00
|
|
|
loop {
|
2022-10-20 14:10:48 -07:00
|
|
|
if !unprocessed_transaction_storage.is_empty()
|
2022-06-13 15:03:34 -07:00
|
|
|
|| last_metrics_update.elapsed() >= SLOT_BOUNDARY_CHECK_PERIOD
|
|
|
|
{
|
2022-06-06 18:21:05 -07:00
|
|
|
let (_, process_buffered_packets_time) = measure!(
|
|
|
|
Self::process_buffered_packets(
|
2023-02-01 09:18:40 -08:00
|
|
|
decision_maker,
|
2023-02-02 11:09:08 -08:00
|
|
|
forwarder,
|
2023-03-06 09:13:28 -08:00
|
|
|
consumer,
|
2022-10-20 14:10:48 -07:00
|
|
|
&mut unprocessed_transaction_storage,
|
2022-06-06 18:21:05 -07:00
|
|
|
&banking_stage_stats,
|
|
|
|
&mut slot_metrics_tracker,
|
2022-06-08 22:25:37 -07:00
|
|
|
&mut tracer_packet_stats,
|
2022-06-06 18:21:05 -07:00
|
|
|
),
|
2022-02-16 22:14:32 -08:00
|
|
|
"process_buffered_packets",
|
2020-01-02 19:50:43 -08:00
|
|
|
);
|
2022-02-16 22:14:32 -08:00
|
|
|
slot_metrics_tracker
|
|
|
|
.increment_process_buffered_packets_us(process_buffered_packets_time.as_us());
|
2022-06-13 15:03:34 -07:00
|
|
|
last_metrics_update = Instant::now();
|
2019-03-08 16:48:15 -08:00
|
|
|
}
|
|
|
|
|
2022-06-08 22:25:37 -07:00
|
|
|
tracer_packet_stats.report(1000);
|
|
|
|
|
2023-02-03 11:35:43 -08:00
|
|
|
match packet_receiver.receive_and_buffer_packets(
|
2023-02-02 07:58:55 -08:00
|
|
|
&mut unprocessed_transaction_storage,
|
|
|
|
&mut banking_stage_stats,
|
|
|
|
&mut tracer_packet_stats,
|
|
|
|
&mut slot_metrics_tracker,
|
|
|
|
) {
|
2021-02-12 03:27:37 -08:00
|
|
|
Ok(()) | Err(RecvTimeoutError::Timeout) => (),
|
2020-01-02 19:50:43 -08:00
|
|
|
Err(RecvTimeoutError::Disconnected) => break,
|
2019-03-03 16:44:06 -08:00
|
|
|
}
|
2021-03-03 10:58:47 -08:00
|
|
|
banking_stage_stats.report(1000);
|
2019-03-03 16:44:06 -08:00
|
|
|
}
|
2018-05-14 16:31:13 -07:00
|
|
|
}
|
|
|
|
|
2018-12-21 13:55:45 -08:00
|
|
|
pub fn num_threads() -> u32 {
|
2019-06-28 01:55:24 -07:00
|
|
|
cmp::max(
|
|
|
|
env::var("SOLANA_BANKING_THREADS")
|
|
|
|
.map(|x| x.parse().unwrap_or(NUM_THREADS))
|
|
|
|
.unwrap_or(NUM_THREADS),
|
2022-03-02 07:08:08 -08:00
|
|
|
MIN_TOTAL_THREADS,
|
2019-06-28 01:55:24 -07:00
|
|
|
)
|
2018-12-21 13:55:45 -08:00
|
|
|
}
|
|
|
|
|
2019-11-13 10:12:09 -08:00
|
|
|
pub fn join(self) -> thread::Result<()> {
|
2018-10-18 22:57:48 -07:00
|
|
|
for bank_thread_hdl in self.bank_thread_hdls {
|
2019-02-13 19:12:14 -08:00
|
|
|
bank_thread_hdl.join()?;
|
2018-09-26 05:52:13 -07:00
|
|
|
}
|
2019-02-13 19:12:14 -08:00
|
|
|
Ok(())
|
2018-07-03 21:14:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-25 15:01:51 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2021-12-03 09:00:31 -08:00
|
|
|
use {
|
|
|
|
super::*,
|
2023-02-15 08:52:13 -08:00
|
|
|
crate::banking_trace::{BankingPacketBatch, BankingTracer},
|
2022-01-11 02:44:46 -08:00
|
|
|
crossbeam_channel::{unbounded, Receiver},
|
2023-02-15 08:52:13 -08:00
|
|
|
itertools::Itertools,
|
|
|
|
solana_entry::entry::{Entry, EntrySlice},
|
2023-01-24 08:57:55 -08:00
|
|
|
solana_gossip::cluster_info::Node,
|
2021-12-03 09:00:31 -08:00
|
|
|
solana_ledger::{
|
2023-02-15 08:52:13 -08:00
|
|
|
blockstore::Blockstore,
|
2023-01-24 08:57:55 -08:00
|
|
|
genesis_utils::{
|
|
|
|
create_genesis_config, create_genesis_config_with_leader, GenesisConfigInfo,
|
|
|
|
},
|
2022-02-03 00:56:36 -08:00
|
|
|
get_tmp_ledger_path_auto_delete,
|
2021-12-03 09:00:31 -08:00
|
|
|
leader_schedule_cache::LeaderScheduleCache,
|
|
|
|
},
|
2023-01-25 12:31:59 -08:00
|
|
|
solana_perf::packet::{to_packet_batches, PacketBatch},
|
2021-12-03 09:00:31 -08:00
|
|
|
solana_poh::{
|
2023-02-15 08:52:13 -08:00
|
|
|
poh_recorder::{
|
|
|
|
create_test_recorder, PohRecorderError, Record, RecordTransactionsSummary,
|
|
|
|
},
|
2021-12-03 09:00:31 -08:00
|
|
|
poh_service::PohService,
|
|
|
|
},
|
2023-01-24 08:57:55 -08:00
|
|
|
solana_runtime::{
|
2023-02-15 08:52:13 -08:00
|
|
|
bank::Bank,
|
2023-01-24 08:57:55 -08:00
|
|
|
bank_forks::BankForks,
|
|
|
|
genesis_utils::{activate_feature, bootstrap_validator_stake_lamports},
|
|
|
|
},
|
2021-12-03 09:00:31 -08:00
|
|
|
solana_sdk::{
|
|
|
|
hash::Hash,
|
|
|
|
poh_config::PohConfig,
|
2023-02-15 08:52:13 -08:00
|
|
|
pubkey::Pubkey,
|
2021-12-03 09:00:31 -08:00
|
|
|
signature::{Keypair, Signer},
|
|
|
|
system_transaction,
|
|
|
|
},
|
2023-01-25 12:31:59 -08:00
|
|
|
solana_streamer::socket::SocketAddrSpace,
|
2022-10-20 14:10:48 -07:00
|
|
|
solana_vote_program::{
|
|
|
|
vote_state::VoteStateUpdate, vote_transaction::new_vote_state_update_transaction,
|
|
|
|
},
|
2021-12-03 09:00:31 -08:00
|
|
|
std::{
|
2022-01-11 02:44:46 -08:00
|
|
|
sync::atomic::{AtomicBool, Ordering},
|
2021-12-03 09:00:31 -08:00
|
|
|
thread::sleep,
|
2021-06-04 08:23:06 -07:00
|
|
|
},
|
2021-03-23 07:10:04 -07:00
|
|
|
};
|
2018-09-25 15:01:51 -07:00
|
|
|
|
2023-01-25 12:31:59 -08:00
|
|
|
pub(crate) fn new_test_cluster_info(keypair: Option<Arc<Keypair>>) -> (Node, ClusterInfo) {
|
2023-01-24 08:57:55 -08:00
|
|
|
let keypair = keypair.unwrap_or_else(|| Arc::new(Keypair::new()));
|
|
|
|
let node = Node::new_localhost_with_pubkey(&keypair.pubkey());
|
|
|
|
let cluster_info =
|
|
|
|
ClusterInfo::new(node.info.clone(), keypair, SocketAddrSpace::Unspecified);
|
|
|
|
(node, cluster_info)
|
2021-07-23 08:25:03 -07:00
|
|
|
}
|
|
|
|
|
2018-09-25 15:01:51 -07:00
|
|
|
#[test]
|
2018-09-26 05:52:13 -07:00
|
|
|
fn test_banking_stage_shutdown1() {
|
2019-11-08 20:56:57 -08:00
|
|
|
let genesis_config = create_genesis_config(2).genesis_config;
|
2022-07-05 21:24:58 -07:00
|
|
|
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
|
|
|
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
|
|
|
let bank = Arc::new(bank_forks.read().unwrap().get(0).unwrap());
|
2023-01-25 04:54:38 -08:00
|
|
|
let banking_tracer = BankingTracer::new_disabled();
|
|
|
|
let (non_vote_sender, non_vote_receiver) = banking_tracer.create_channel_non_vote();
|
|
|
|
let (tpu_vote_sender, tpu_vote_receiver) = banking_tracer.create_channel_tpu_vote();
|
|
|
|
let (gossip_vote_sender, gossip_vote_receiver) =
|
|
|
|
banking_tracer.create_channel_gossip_vote();
|
2022-02-03 00:56:36 -08:00
|
|
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
2019-03-29 20:00:36 -07:00
|
|
|
{
|
2020-01-13 13:13:52 -08:00
|
|
|
let blockstore = Arc::new(
|
2022-02-03 00:56:36 -08:00
|
|
|
Blockstore::open(ledger_path.path())
|
2020-01-13 13:13:52 -08:00
|
|
|
.expect("Expected to be able to open database ledger"),
|
2019-03-29 20:00:36 -07:00
|
|
|
);
|
|
|
|
let (exit, poh_recorder, poh_service, _entry_receiever) =
|
2023-04-19 11:41:18 -07:00
|
|
|
create_test_recorder(&bank, blockstore, None, None);
|
2023-01-24 08:57:55 -08:00
|
|
|
let (_, cluster_info) = new_test_cluster_info(/*keypair:*/ None);
|
2020-04-21 12:54:45 -07:00
|
|
|
let cluster_info = Arc::new(cluster_info);
|
2023-01-17 21:14:04 -08:00
|
|
|
let (replay_vote_sender, _replay_vote_receiver) = unbounded();
|
2021-10-07 02:38:23 -07:00
|
|
|
|
2019-04-17 21:07:45 -07:00
|
|
|
let banking_stage = BankingStage::new(
|
|
|
|
&cluster_info,
|
|
|
|
&poh_recorder,
|
2023-01-18 17:04:55 -08:00
|
|
|
non_vote_receiver,
|
2021-10-07 02:38:23 -07:00
|
|
|
tpu_vote_receiver,
|
2023-01-18 17:04:55 -08:00
|
|
|
gossip_vote_receiver,
|
2019-11-20 15:43:10 -08:00
|
|
|
None,
|
2023-01-17 21:14:04 -08:00
|
|
|
replay_vote_sender,
|
2022-07-11 08:53:18 -07:00
|
|
|
None,
|
2022-06-08 04:57:12 -07:00
|
|
|
Arc::new(ConnectionCache::default()),
|
2022-07-05 21:24:58 -07:00
|
|
|
bank_forks,
|
2023-03-23 17:05:54 -07:00
|
|
|
&Arc::new(PrioritizationFeeCache::new(0u64)),
|
2019-04-17 21:07:45 -07:00
|
|
|
);
|
2023-01-18 17:04:55 -08:00
|
|
|
drop(non_vote_sender);
|
2021-10-07 02:38:23 -07:00
|
|
|
drop(tpu_vote_sender);
|
2023-01-18 17:04:55 -08:00
|
|
|
drop(gossip_vote_sender);
|
2019-03-29 20:00:36 -07:00
|
|
|
exit.store(true, Ordering::Relaxed);
|
|
|
|
banking_stage.join().unwrap();
|
|
|
|
poh_service.join().unwrap();
|
|
|
|
}
|
2022-02-03 00:56:36 -08:00
|
|
|
Blockstore::destroy(ledger_path.path()).unwrap();
|
2018-09-26 05:52:13 -07:00
|
|
|
}
|
|
|
|
|
2018-09-25 15:01:51 -07:00
|
|
|
#[test]
|
|
|
|
fn test_banking_stage_tick() {
|
2019-03-03 16:44:06 -08:00
|
|
|
solana_logger::setup();
|
2019-11-08 20:56:57 -08:00
|
|
|
let GenesisConfigInfo {
|
|
|
|
mut genesis_config, ..
|
|
|
|
} = create_genesis_config(2);
|
|
|
|
genesis_config.ticks_per_slot = 4;
|
2019-10-16 12:37:27 -07:00
|
|
|
let num_extra_ticks = 2;
|
2022-07-05 21:24:58 -07:00
|
|
|
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
|
|
|
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
|
|
|
let bank = Arc::new(bank_forks.read().unwrap().get(0).unwrap());
|
2019-03-02 10:25:16 -08:00
|
|
|
let start_hash = bank.last_blockhash();
|
2023-01-25 04:54:38 -08:00
|
|
|
let banking_tracer = BankingTracer::new_disabled();
|
|
|
|
let (non_vote_sender, non_vote_receiver) = banking_tracer.create_channel_non_vote();
|
|
|
|
let (tpu_vote_sender, tpu_vote_receiver) = banking_tracer.create_channel_tpu_vote();
|
|
|
|
let (gossip_vote_sender, gossip_vote_receiver) =
|
|
|
|
banking_tracer.create_channel_gossip_vote();
|
2022-02-03 00:56:36 -08:00
|
|
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
2019-03-29 20:00:36 -07:00
|
|
|
{
|
2020-01-13 13:13:52 -08:00
|
|
|
let blockstore = Arc::new(
|
2022-02-03 00:56:36 -08:00
|
|
|
Blockstore::open(ledger_path.path())
|
2020-01-13 13:13:52 -08:00
|
|
|
.expect("Expected to be able to open database ledger"),
|
2019-03-29 20:00:36 -07:00
|
|
|
);
|
2020-12-13 17:26:34 -08:00
|
|
|
let poh_config = PohConfig {
|
|
|
|
target_tick_count: Some(bank.max_tick_height() + num_extra_ticks),
|
|
|
|
..PohConfig::default()
|
|
|
|
};
|
2019-03-29 20:00:36 -07:00
|
|
|
let (exit, poh_recorder, poh_service, entry_receiver) =
|
2023-04-19 11:41:18 -07:00
|
|
|
create_test_recorder(&bank, blockstore, Some(poh_config), None);
|
2023-01-24 08:57:55 -08:00
|
|
|
let (_, cluster_info) = new_test_cluster_info(/*keypair:*/ None);
|
2020-04-21 12:54:45 -07:00
|
|
|
let cluster_info = Arc::new(cluster_info);
|
2023-01-17 21:14:04 -08:00
|
|
|
let (replay_vote_sender, _replay_vote_receiver) = unbounded();
|
2020-08-07 11:21:35 -07:00
|
|
|
|
2019-04-17 21:07:45 -07:00
|
|
|
let banking_stage = BankingStage::new(
|
|
|
|
&cluster_info,
|
|
|
|
&poh_recorder,
|
2023-01-18 17:04:55 -08:00
|
|
|
non_vote_receiver,
|
2021-10-07 02:38:23 -07:00
|
|
|
tpu_vote_receiver,
|
2023-01-18 17:04:55 -08:00
|
|
|
gossip_vote_receiver,
|
2019-11-20 15:43:10 -08:00
|
|
|
None,
|
2023-01-17 21:14:04 -08:00
|
|
|
replay_vote_sender,
|
2022-07-11 08:53:18 -07:00
|
|
|
None,
|
2022-06-08 04:57:12 -07:00
|
|
|
Arc::new(ConnectionCache::default()),
|
2022-07-05 21:24:58 -07:00
|
|
|
bank_forks,
|
2023-03-23 17:05:54 -07:00
|
|
|
&Arc::new(PrioritizationFeeCache::new(0u64)),
|
2019-04-17 21:07:45 -07:00
|
|
|
);
|
2019-03-29 20:00:36 -07:00
|
|
|
trace!("sending bank");
|
2023-01-18 17:04:55 -08:00
|
|
|
drop(non_vote_sender);
|
2021-10-07 02:38:23 -07:00
|
|
|
drop(tpu_vote_sender);
|
2023-01-18 17:04:55 -08:00
|
|
|
drop(gossip_vote_sender);
|
2019-03-29 20:00:36 -07:00
|
|
|
exit.store(true, Ordering::Relaxed);
|
|
|
|
poh_service.join().unwrap();
|
|
|
|
drop(poh_recorder);
|
|
|
|
|
|
|
|
trace!("getting entries");
|
|
|
|
let entries: Vec<_> = entry_receiver
|
|
|
|
.iter()
|
2019-09-18 12:16:22 -07:00
|
|
|
.map(|(_bank, (entry, _tick_height))| entry)
|
2019-03-29 20:00:36 -07:00
|
|
|
.collect();
|
|
|
|
trace!("done");
|
2019-11-08 20:56:57 -08:00
|
|
|
assert_eq!(entries.len(), genesis_config.ticks_per_slot as usize);
|
2021-05-19 07:31:47 -07:00
|
|
|
assert!(entries.verify(&start_hash));
|
2019-03-29 20:00:36 -07:00
|
|
|
assert_eq!(entries[entries.len() - 1].hash, bank.last_blockhash());
|
|
|
|
banking_stage.join().unwrap();
|
|
|
|
}
|
2022-02-03 00:56:36 -08:00
|
|
|
Blockstore::destroy(ledger_path.path()).unwrap();
|
2018-09-25 15:01:51 -07:00
|
|
|
}
|
|
|
|
|
2021-12-11 06:44:15 -08:00
|
|
|
pub fn convert_from_old_verified(
|
|
|
|
mut with_vers: Vec<(PacketBatch, Vec<u8>)>,
|
|
|
|
) -> Vec<PacketBatch> {
|
2019-11-01 14:23:03 -07:00
|
|
|
with_vers.iter_mut().for_each(|(b, v)| {
|
2022-05-23 13:30:15 -07:00
|
|
|
b.iter_mut()
|
2019-11-01 14:23:03 -07:00
|
|
|
.zip(v)
|
2022-12-06 03:54:49 -08:00
|
|
|
.for_each(|(p, f)| p.meta_mut().set_discard(*f == 0))
|
2019-11-01 14:23:03 -07:00
|
|
|
});
|
|
|
|
with_vers.into_iter().map(|(b, _)| b).collect()
|
|
|
|
}
|
|
|
|
|
2018-09-25 15:01:51 -07:00
|
|
|
#[test]
|
2018-09-26 13:31:39 -07:00
|
|
|
fn test_banking_stage_entries_only() {
|
2019-03-12 21:07:06 -07:00
|
|
|
solana_logger::setup();
|
2019-11-08 20:56:57 -08:00
|
|
|
let GenesisConfigInfo {
|
|
|
|
genesis_config,
|
2019-05-22 20:39:00 -07:00
|
|
|
mint_keypair,
|
|
|
|
..
|
2021-03-24 14:05:43 -07:00
|
|
|
} = create_slow_genesis_config(10);
|
2022-07-05 21:24:58 -07:00
|
|
|
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
|
|
|
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
|
|
|
let bank = Arc::new(bank_forks.read().unwrap().get(0).unwrap());
|
2019-03-02 10:25:16 -08:00
|
|
|
let start_hash = bank.last_blockhash();
|
2023-01-25 04:54:38 -08:00
|
|
|
let banking_tracer = BankingTracer::new_disabled();
|
|
|
|
let (non_vote_sender, non_vote_receiver) = banking_tracer.create_channel_non_vote();
|
|
|
|
let (tpu_vote_sender, tpu_vote_receiver) = banking_tracer.create_channel_tpu_vote();
|
|
|
|
let (gossip_vote_sender, gossip_vote_receiver) =
|
|
|
|
banking_tracer.create_channel_gossip_vote();
|
2022-02-03 00:56:36 -08:00
|
|
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
2019-03-29 20:00:36 -07:00
|
|
|
{
|
2020-01-13 13:13:52 -08:00
|
|
|
let blockstore = Arc::new(
|
2022-02-03 00:56:36 -08:00
|
|
|
Blockstore::open(ledger_path.path())
|
2020-01-13 13:13:52 -08:00
|
|
|
.expect("Expected to be able to open database ledger"),
|
2019-03-29 20:00:36 -07:00
|
|
|
);
|
2020-12-13 17:26:34 -08:00
|
|
|
let poh_config = PohConfig {
|
|
|
|
// limit tick count to avoid clearing working_bank at PohRecord then
|
|
|
|
// PohRecorderError(MaxHeightReached) at BankingStage
|
|
|
|
target_tick_count: Some(bank.max_tick_height() - 1),
|
|
|
|
..PohConfig::default()
|
|
|
|
};
|
2019-03-29 20:00:36 -07:00
|
|
|
let (exit, poh_recorder, poh_service, entry_receiver) =
|
2023-04-19 11:41:18 -07:00
|
|
|
create_test_recorder(&bank, blockstore, Some(poh_config), None);
|
2023-01-24 08:57:55 -08:00
|
|
|
let (_, cluster_info) = new_test_cluster_info(/*keypair:*/ None);
|
2020-04-21 12:54:45 -07:00
|
|
|
let cluster_info = Arc::new(cluster_info);
|
2023-01-17 21:14:04 -08:00
|
|
|
let (replay_vote_sender, _replay_vote_receiver) = unbounded();
|
2020-08-07 11:21:35 -07:00
|
|
|
|
2019-04-17 21:07:45 -07:00
|
|
|
let banking_stage = BankingStage::new(
|
|
|
|
&cluster_info,
|
|
|
|
&poh_recorder,
|
2023-01-18 17:04:55 -08:00
|
|
|
non_vote_receiver,
|
2021-10-07 02:38:23 -07:00
|
|
|
tpu_vote_receiver,
|
2023-01-18 17:04:55 -08:00
|
|
|
gossip_vote_receiver,
|
2019-11-20 15:43:10 -08:00
|
|
|
None,
|
2023-01-17 21:14:04 -08:00
|
|
|
replay_vote_sender,
|
2022-07-11 08:53:18 -07:00
|
|
|
None,
|
2022-06-08 04:57:12 -07:00
|
|
|
Arc::new(ConnectionCache::default()),
|
2022-07-05 21:24:58 -07:00
|
|
|
bank_forks,
|
2023-03-23 17:05:54 -07:00
|
|
|
&Arc::new(PrioritizationFeeCache::new(0u64)),
|
2019-04-17 21:07:45 -07:00
|
|
|
);
|
2018-09-25 15:01:51 -07:00
|
|
|
|
2019-03-29 20:00:36 -07:00
|
|
|
// fund another account so we can send 2 good transactions in a single batch.
|
|
|
|
let keypair = Keypair::new();
|
2019-10-19 18:23:27 -07:00
|
|
|
let fund_tx =
|
2019-10-23 22:01:22 -07:00
|
|
|
system_transaction::transfer(&mint_keypair, &keypair.pubkey(), 2, start_hash);
|
2019-03-29 20:00:36 -07:00
|
|
|
bank.process_transaction(&fund_tx).unwrap();
|
2019-03-12 21:07:06 -07:00
|
|
|
|
2019-03-29 20:00:36 -07:00
|
|
|
// good tx
|
2020-10-19 12:12:08 -07:00
|
|
|
let to = solana_sdk::pubkey::new_rand();
|
2019-10-23 22:01:22 -07:00
|
|
|
let tx = system_transaction::transfer(&mint_keypair, &to, 1, start_hash);
|
2019-03-29 20:00:36 -07:00
|
|
|
|
|
|
|
// good tx, but no verify
|
2020-10-19 12:12:08 -07:00
|
|
|
let to2 = solana_sdk::pubkey::new_rand();
|
2019-10-23 22:01:22 -07:00
|
|
|
let tx_no_ver = system_transaction::transfer(&keypair, &to2, 2, start_hash);
|
2019-03-29 20:00:36 -07:00
|
|
|
|
|
|
|
// bad tx, AccountNotFound
|
|
|
|
let keypair = Keypair::new();
|
2020-10-19 12:12:08 -07:00
|
|
|
let to3 = solana_sdk::pubkey::new_rand();
|
2019-10-23 22:01:22 -07:00
|
|
|
let tx_anf = system_transaction::transfer(&keypair, &to3, 1, start_hash);
|
2019-03-29 20:00:36 -07:00
|
|
|
|
|
|
|
// send 'em over
|
2021-12-11 06:44:15 -08:00
|
|
|
let packet_batches = to_packet_batches(&[tx_no_ver, tx_anf, tx], 3);
|
2019-03-29 20:00:36 -07:00
|
|
|
|
|
|
|
// glad they all fit
|
2021-12-11 06:44:15 -08:00
|
|
|
assert_eq!(packet_batches.len(), 1);
|
2019-05-20 09:15:00 -07:00
|
|
|
|
2021-12-11 06:44:15 -08:00
|
|
|
let packet_batches = packet_batches
|
2019-05-20 09:15:00 -07:00
|
|
|
.into_iter()
|
2021-12-11 06:44:15 -08:00
|
|
|
.map(|batch| (batch, vec![0u8, 1u8, 1u8]))
|
2019-05-20 09:15:00 -07:00
|
|
|
.collect();
|
2021-12-11 06:44:15 -08:00
|
|
|
let packet_batches = convert_from_old_verified(packet_batches);
|
2023-01-18 17:04:55 -08:00
|
|
|
non_vote_sender // no_ver, anf, tx
|
2023-01-25 04:54:38 -08:00
|
|
|
.send(BankingPacketBatch::new((packet_batches, None)))
|
2019-03-29 20:00:36 -07:00
|
|
|
.unwrap();
|
|
|
|
|
2023-01-18 17:04:55 -08:00
|
|
|
drop(non_vote_sender);
|
2021-10-07 02:38:23 -07:00
|
|
|
drop(tpu_vote_sender);
|
2023-01-18 17:04:55 -08:00
|
|
|
drop(gossip_vote_sender);
|
2019-10-16 12:37:27 -07:00
|
|
|
// wait until banking_stage to finish up all packets
|
|
|
|
banking_stage.join().unwrap();
|
|
|
|
|
2019-03-29 20:00:36 -07:00
|
|
|
exit.store(true, Ordering::Relaxed);
|
|
|
|
poh_service.join().unwrap();
|
|
|
|
drop(poh_recorder);
|
|
|
|
|
|
|
|
let mut blockhash = start_hash;
|
2021-08-05 12:50:25 -07:00
|
|
|
let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config));
|
2019-03-29 20:00:36 -07:00
|
|
|
bank.process_transaction(&fund_tx).unwrap();
|
|
|
|
//receive entries + ticks
|
2019-10-16 12:37:27 -07:00
|
|
|
loop {
|
2019-09-18 12:16:22 -07:00
|
|
|
let entries: Vec<Entry> = entry_receiver
|
2019-03-29 20:00:36 -07:00
|
|
|
.iter()
|
2019-09-18 12:16:22 -07:00
|
|
|
.map(|(_bank, (entry, _tick_height))| entry)
|
2019-03-29 20:00:36 -07:00
|
|
|
.collect();
|
|
|
|
|
2021-05-19 07:31:47 -07:00
|
|
|
assert!(entries.verify(&blockhash));
|
2019-10-16 12:37:27 -07:00
|
|
|
if !entries.is_empty() {
|
|
|
|
blockhash = entries.last().unwrap().hash;
|
|
|
|
for entry in entries {
|
2021-08-17 15:17:56 -07:00
|
|
|
bank.process_entry_transactions(entry.transactions)
|
2019-10-16 12:37:27 -07:00
|
|
|
.iter()
|
|
|
|
.for_each(|x| assert_eq!(*x, Ok(())));
|
|
|
|
}
|
2019-03-12 21:07:06 -07:00
|
|
|
}
|
2019-02-25 13:50:31 -08:00
|
|
|
|
2019-03-29 20:00:36 -07:00
|
|
|
if bank.get_balance(&to) == 1 {
|
|
|
|
break;
|
|
|
|
}
|
2019-03-12 21:07:06 -07:00
|
|
|
|
2019-03-29 20:00:36 -07:00
|
|
|
sleep(Duration::from_millis(200));
|
|
|
|
}
|
2019-03-12 21:07:06 -07:00
|
|
|
|
2019-03-29 20:00:36 -07:00
|
|
|
assert_eq!(bank.get_balance(&to), 1);
|
|
|
|
assert_eq!(bank.get_balance(&to2), 0);
|
2018-09-26 05:52:13 -07:00
|
|
|
|
2019-03-29 20:00:36 -07:00
|
|
|
drop(entry_receiver);
|
|
|
|
}
|
2022-02-03 00:56:36 -08:00
|
|
|
Blockstore::destroy(ledger_path.path()).unwrap();
|
2018-09-26 13:31:39 -07:00
|
|
|
}
|
2019-03-03 16:44:06 -08:00
|
|
|
|
2018-09-25 15:01:51 -07:00
|
|
|
#[test]
|
|
|
|
fn test_banking_stage_entryfication() {
|
2019-03-18 22:08:21 -07:00
|
|
|
solana_logger::setup();
|
2018-09-25 15:01:51 -07:00
|
|
|
// In this attack we'll demonstrate that a verifier can interpret the ledger
|
|
|
|
// differently if either the server doesn't signal the ledger to add an
|
|
|
|
// Entry OR if the verifier tries to parallelize across multiple Entries.
|
2019-11-08 20:56:57 -08:00
|
|
|
let GenesisConfigInfo {
|
|
|
|
genesis_config,
|
2019-05-22 20:39:00 -07:00
|
|
|
mint_keypair,
|
|
|
|
..
|
2021-03-24 14:05:43 -07:00
|
|
|
} = create_slow_genesis_config(2);
|
2023-01-25 04:54:38 -08:00
|
|
|
let banking_tracer = BankingTracer::new_disabled();
|
|
|
|
let (non_vote_sender, non_vote_receiver) = banking_tracer.create_channel_non_vote();
|
2018-09-25 15:01:51 -07:00
|
|
|
|
2022-05-12 08:36:19 -07:00
|
|
|
// Process a batch that includes a transaction that receives two lamports.
|
2018-09-25 15:01:51 -07:00
|
|
|
let alice = Keypair::new();
|
2022-05-12 08:36:19 -07:00
|
|
|
let tx =
|
|
|
|
system_transaction::transfer(&mint_keypair, &alice.pubkey(), 2, genesis_config.hash());
|
|
|
|
|
|
|
|
let packet_batches = to_packet_batches(&[tx], 1);
|
|
|
|
let packet_batches = packet_batches
|
|
|
|
.into_iter()
|
|
|
|
.map(|batch| (batch, vec![1u8]))
|
|
|
|
.collect();
|
|
|
|
let packet_batches = convert_from_old_verified(packet_batches);
|
2023-01-25 04:54:38 -08:00
|
|
|
non_vote_sender
|
|
|
|
.send(BankingPacketBatch::new((packet_batches, None)))
|
|
|
|
.unwrap();
|
2022-05-12 08:36:19 -07:00
|
|
|
|
|
|
|
// Process a second batch that uses the same from account, so conflicts with above TX
|
|
|
|
let tx =
|
|
|
|
system_transaction::transfer(&mint_keypair, &alice.pubkey(), 1, genesis_config.hash());
|
|
|
|
let packet_batches = to_packet_batches(&[tx], 1);
|
|
|
|
let packet_batches = packet_batches
|
|
|
|
.into_iter()
|
|
|
|
.map(|batch| (batch, vec![1u8]))
|
|
|
|
.collect();
|
|
|
|
let packet_batches = convert_from_old_verified(packet_batches);
|
2023-01-25 04:54:38 -08:00
|
|
|
non_vote_sender
|
|
|
|
.send(BankingPacketBatch::new((packet_batches, None)))
|
|
|
|
.unwrap();
|
2019-03-03 16:44:06 -08:00
|
|
|
|
2023-01-25 04:54:38 -08:00
|
|
|
let (tpu_vote_sender, tpu_vote_receiver) = banking_tracer.create_channel_tpu_vote();
|
|
|
|
let (gossip_vote_sender, gossip_vote_receiver) =
|
|
|
|
banking_tracer.create_channel_gossip_vote();
|
2022-02-03 00:56:36 -08:00
|
|
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
2019-03-29 20:00:36 -07:00
|
|
|
{
|
2023-01-17 21:14:04 -08:00
|
|
|
let (replay_vote_sender, _replay_vote_receiver) = unbounded();
|
2020-08-07 11:21:35 -07:00
|
|
|
|
2019-03-29 20:00:36 -07:00
|
|
|
let entry_receiver = {
|
|
|
|
// start a banking_stage to eat verified receiver
|
2022-07-05 21:24:58 -07:00
|
|
|
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
|
|
|
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
|
|
|
let bank = Arc::new(bank_forks.read().unwrap().get(0).unwrap());
|
2020-01-13 13:13:52 -08:00
|
|
|
let blockstore = Arc::new(
|
2022-02-03 00:56:36 -08:00
|
|
|
Blockstore::open(ledger_path.path())
|
2019-03-29 20:00:36 -07:00
|
|
|
.expect("Expected to be able to open database ledger"),
|
|
|
|
);
|
2020-12-13 17:26:34 -08:00
|
|
|
let poh_config = PohConfig {
|
|
|
|
// limit tick count to avoid clearing working_bank at
|
|
|
|
// PohRecord then PohRecorderError(MaxHeightReached) at BankingStage
|
|
|
|
target_tick_count: Some(bank.max_tick_height() - 1),
|
|
|
|
..PohConfig::default()
|
|
|
|
};
|
2019-03-29 20:00:36 -07:00
|
|
|
let (exit, poh_recorder, poh_service, entry_receiver) =
|
2023-04-19 11:41:18 -07:00
|
|
|
create_test_recorder(&bank, blockstore, Some(poh_config), None);
|
2023-01-24 08:57:55 -08:00
|
|
|
let (_, cluster_info) = new_test_cluster_info(/*keypair:*/ None);
|
2020-04-21 12:54:45 -07:00
|
|
|
let cluster_info = Arc::new(cluster_info);
|
2019-03-29 20:00:36 -07:00
|
|
|
let _banking_stage = BankingStage::new_num_threads(
|
|
|
|
&cluster_info,
|
|
|
|
&poh_recorder,
|
2023-01-18 17:04:55 -08:00
|
|
|
non_vote_receiver,
|
2021-10-07 02:38:23 -07:00
|
|
|
tpu_vote_receiver,
|
2023-01-18 17:04:55 -08:00
|
|
|
gossip_vote_receiver,
|
2021-10-07 02:38:23 -07:00
|
|
|
3,
|
2019-11-20 15:43:10 -08:00
|
|
|
None,
|
2023-01-17 21:14:04 -08:00
|
|
|
replay_vote_sender,
|
2022-07-11 08:53:18 -07:00
|
|
|
None,
|
2022-06-08 04:57:12 -07:00
|
|
|
Arc::new(ConnectionCache::default()),
|
2022-07-05 21:24:58 -07:00
|
|
|
bank_forks,
|
2023-03-23 17:05:54 -07:00
|
|
|
&Arc::new(PrioritizationFeeCache::new(0u64)),
|
2019-03-29 20:00:36 -07:00
|
|
|
);
|
2019-03-18 22:08:21 -07:00
|
|
|
|
2019-03-29 20:00:36 -07:00
|
|
|
// wait for banking_stage to eat the packets
|
2022-05-12 08:36:19 -07:00
|
|
|
while bank.get_balance(&alice.pubkey()) < 1 {
|
|
|
|
sleep(Duration::from_millis(10));
|
2019-03-29 20:00:36 -07:00
|
|
|
}
|
|
|
|
exit.store(true, Ordering::Relaxed);
|
|
|
|
poh_service.join().unwrap();
|
|
|
|
entry_receiver
|
|
|
|
};
|
2023-01-18 17:04:55 -08:00
|
|
|
drop(non_vote_sender);
|
2021-10-07 02:38:23 -07:00
|
|
|
drop(tpu_vote_sender);
|
2023-01-18 17:04:55 -08:00
|
|
|
drop(gossip_vote_sender);
|
2019-03-29 20:00:36 -07:00
|
|
|
|
|
|
|
// consume the entire entry_receiver, feed it into a new bank
|
|
|
|
// check that the balance is what we expect.
|
|
|
|
let entries: Vec<_> = entry_receiver
|
|
|
|
.iter()
|
2019-09-18 12:16:22 -07:00
|
|
|
.map(|(_bank, (entry, _tick_height))| entry)
|
2019-03-29 20:00:36 -07:00
|
|
|
.collect();
|
2018-09-25 15:01:51 -07:00
|
|
|
|
2021-08-05 12:50:25 -07:00
|
|
|
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
|
2021-08-17 15:17:56 -07:00
|
|
|
for entry in entries {
|
|
|
|
bank.process_entry_transactions(entry.transactions)
|
2019-03-29 20:00:36 -07:00
|
|
|
.iter()
|
|
|
|
.for_each(|x| assert_eq!(*x, Ok(())));
|
|
|
|
}
|
2019-03-18 22:08:21 -07:00
|
|
|
|
2022-05-12 08:36:19 -07:00
|
|
|
// Assert the user doesn't hold three lamports. If the stage only outputs one
|
|
|
|
// entry, then one of the transactions will be rejected, because it drives
|
2019-03-29 20:00:36 -07:00
|
|
|
// the account balance below zero before the credit is added.
|
2022-05-12 08:36:19 -07:00
|
|
|
assert!(bank.get_balance(&alice.pubkey()) != 3);
|
2019-03-11 12:45:45 -07:00
|
|
|
}
|
2022-02-03 00:56:36 -08:00
|
|
|
Blockstore::destroy(ledger_path.path()).unwrap();
|
2018-10-18 22:57:48 -07:00
|
|
|
}
|
2019-02-16 14:02:21 -08:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_bank_record_transactions() {
|
2021-03-23 07:10:04 -07:00
|
|
|
solana_logger::setup();
|
|
|
|
|
2019-11-08 20:56:57 -08:00
|
|
|
let GenesisConfigInfo {
|
|
|
|
genesis_config,
|
2019-05-22 20:39:00 -07:00
|
|
|
mint_keypair,
|
|
|
|
..
|
2019-11-08 20:56:57 -08:00
|
|
|
} = create_genesis_config(10_000);
|
2021-08-05 12:50:25 -07:00
|
|
|
let bank = Arc::new(Bank::new_no_wallclock_throttle_for_tests(&genesis_config));
|
2022-02-03 00:56:36 -08:00
|
|
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
2019-03-29 20:00:36 -07:00
|
|
|
{
|
2022-02-03 00:56:36 -08:00
|
|
|
let blockstore = Blockstore::open(ledger_path.path())
|
2020-01-13 13:13:52 -08:00
|
|
|
.expect("Expected to be able to open database ledger");
|
2021-03-23 07:10:04 -07:00
|
|
|
let (poh_recorder, entry_receiver, record_receiver) = PohRecorder::new(
|
|
|
|
// TODO use record_receiver
|
2019-03-29 20:00:36 -07:00
|
|
|
bank.tick_height(),
|
|
|
|
bank.last_blockhash(),
|
2021-09-13 16:55:35 -07:00
|
|
|
bank.clone(),
|
2019-03-29 20:00:36 -07:00
|
|
|
None,
|
|
|
|
bank.ticks_per_slot(),
|
|
|
|
&Pubkey::default(),
|
2023-04-19 11:41:18 -07:00
|
|
|
Arc::new(blockstore),
|
2019-04-19 02:39:44 -07:00
|
|
|
&Arc::new(LeaderScheduleCache::new_from_bank(&bank)),
|
2022-12-06 13:48:32 -08:00
|
|
|
&PohConfig::default(),
|
2021-04-14 10:07:21 -07:00
|
|
|
Arc::new(AtomicBool::default()),
|
2019-03-29 20:00:36 -07:00
|
|
|
);
|
2023-03-21 21:19:20 -07:00
|
|
|
let recorder = poh_recorder.new_recorder();
|
2022-07-05 07:29:44 -07:00
|
|
|
let poh_recorder = Arc::new(RwLock::new(poh_recorder));
|
2019-03-29 20:00:36 -07:00
|
|
|
|
2021-04-14 10:07:21 -07:00
|
|
|
let poh_simulator = simulate_poh(record_receiver, &poh_recorder);
|
2021-03-23 07:10:04 -07:00
|
|
|
|
2022-07-05 07:29:44 -07:00
|
|
|
poh_recorder.write().unwrap().set_bank(&bank, false);
|
2020-10-19 12:12:08 -07:00
|
|
|
let pubkey = solana_sdk::pubkey::new_rand();
|
2019-05-07 15:51:35 -07:00
|
|
|
let keypair2 = Keypair::new();
|
2020-10-19 12:12:08 -07:00
|
|
|
let pubkey2 = solana_sdk::pubkey::new_rand();
|
2019-03-29 20:00:36 -07:00
|
|
|
|
2022-04-21 06:06:26 -07:00
|
|
|
let txs = vec![
|
|
|
|
system_transaction::transfer(&mint_keypair, &pubkey, 1, genesis_config.hash())
|
|
|
|
.into(),
|
|
|
|
system_transaction::transfer(&keypair2, &pubkey2, 1, genesis_config.hash()).into(),
|
|
|
|
];
|
2019-03-29 20:00:36 -07:00
|
|
|
|
2023-02-09 08:34:02 -08:00
|
|
|
let _ = recorder.record_transactions(bank.slot(), txs.clone());
|
2019-09-18 12:16:22 -07:00
|
|
|
let (_bank, (entry, _tick_height)) = entry_receiver.recv().unwrap();
|
2022-04-21 06:06:26 -07:00
|
|
|
assert_eq!(entry.transactions, txs);
|
2019-06-26 22:39:50 -07:00
|
|
|
|
|
|
|
// Once bank is set to a new bank (setting bank.slot() + 1 in record_transactions),
|
2022-04-21 06:06:26 -07:00
|
|
|
// record_transactions should throw MaxHeightReached
|
2021-09-13 16:55:35 -07:00
|
|
|
let next_slot = bank.slot() + 1;
|
2022-04-21 06:06:26 -07:00
|
|
|
let RecordTransactionsSummary { result, .. } =
|
2023-02-09 08:34:02 -08:00
|
|
|
recorder.record_transactions(next_slot, txs);
|
2022-02-16 22:14:32 -08:00
|
|
|
assert_matches!(result, Err(PohRecorderError::MaxHeightReached));
|
2019-06-26 22:39:50 -07:00
|
|
|
// Should receive nothing from PohRecorder b/c record failed
|
|
|
|
assert!(entry_receiver.try_recv().is_err());
|
2021-03-23 07:10:04 -07:00
|
|
|
|
2021-04-14 10:07:21 -07:00
|
|
|
poh_recorder
|
2022-07-05 07:29:44 -07:00
|
|
|
.read()
|
2021-04-14 10:07:21 -07:00
|
|
|
.unwrap()
|
|
|
|
.is_exited
|
|
|
|
.store(true, Ordering::Relaxed);
|
2021-03-23 07:10:04 -07:00
|
|
|
let _ = poh_simulator.join();
|
2019-03-29 20:00:36 -07:00
|
|
|
}
|
2022-02-03 00:56:36 -08:00
|
|
|
Blockstore::destroy(ledger_path.path()).unwrap();
|
2019-02-16 14:02:21 -08:00
|
|
|
}
|
|
|
|
|
2023-01-25 12:31:59 -08:00
|
|
|
pub(crate) fn create_slow_genesis_config(lamports: u64) -> GenesisConfigInfo {
|
2023-01-24 08:57:55 -08:00
|
|
|
create_slow_genesis_config_with_leader(lamports, &solana_sdk::pubkey::new_rand())
|
|
|
|
}
|
|
|
|
|
2023-01-25 12:31:59 -08:00
|
|
|
pub(crate) fn create_slow_genesis_config_with_leader(
|
2023-01-24 08:57:55 -08:00
|
|
|
lamports: u64,
|
|
|
|
validator_pubkey: &Pubkey,
|
|
|
|
) -> GenesisConfigInfo {
|
|
|
|
let mut config_info = create_genesis_config_with_leader(
|
|
|
|
lamports,
|
|
|
|
validator_pubkey,
|
|
|
|
// See solana_ledger::genesis_utils::create_genesis_config.
|
|
|
|
bootstrap_validator_stake_lamports(),
|
|
|
|
);
|
2023-01-25 12:31:59 -08:00
|
|
|
|
2021-03-24 14:05:43 -07:00
|
|
|
// For these tests there's only 1 slot, don't want to run out of ticks
|
|
|
|
config_info.genesis_config.ticks_per_slot *= 8;
|
|
|
|
config_info
|
|
|
|
}
|
|
|
|
|
2023-02-15 08:52:13 -08:00
|
|
|
pub(crate) fn simulate_poh(
|
|
|
|
record_receiver: Receiver<Record>,
|
|
|
|
poh_recorder: &Arc<RwLock<PohRecorder>>,
|
|
|
|
) -> JoinHandle<()> {
|
|
|
|
let poh_recorder = poh_recorder.clone();
|
|
|
|
let is_exited = poh_recorder.read().unwrap().is_exited.clone();
|
|
|
|
let tick_producer = Builder::new()
|
|
|
|
.name("solana-simulate_poh".to_string())
|
|
|
|
.spawn(move || loop {
|
|
|
|
PohService::read_record_receiver_and_process(
|
|
|
|
&poh_recorder,
|
|
|
|
&record_receiver,
|
|
|
|
Duration::from_millis(10),
|
|
|
|
);
|
|
|
|
if is_exited.load(Ordering::Relaxed) {
|
2021-03-23 07:10:04 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
2021-04-14 10:07:21 -07:00
|
|
|
tick_producer.unwrap()
|
2021-03-23 07:10:04 -07:00
|
|
|
}
|
|
|
|
|
2022-05-04 19:50:56 -07:00
|
|
|
#[test]
|
2022-10-20 14:10:48 -07:00
|
|
|
fn test_unprocessed_transaction_storage_full_send() {
|
|
|
|
solana_logger::setup();
|
|
|
|
let GenesisConfigInfo {
|
|
|
|
mut genesis_config,
|
|
|
|
mint_keypair,
|
|
|
|
..
|
|
|
|
} = create_slow_genesis_config(10000);
|
|
|
|
activate_feature(
|
|
|
|
&mut genesis_config,
|
|
|
|
allow_votes_to_directly_update_vote_state::id(),
|
|
|
|
);
|
|
|
|
let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
|
|
|
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
|
|
|
|
let bank = Arc::new(bank_forks.read().unwrap().get(0).unwrap());
|
|
|
|
let start_hash = bank.last_blockhash();
|
2023-01-25 04:54:38 -08:00
|
|
|
let banking_tracer = BankingTracer::new_disabled();
|
|
|
|
let (non_vote_sender, non_vote_receiver) = banking_tracer.create_channel_non_vote();
|
|
|
|
let (tpu_vote_sender, tpu_vote_receiver) = banking_tracer.create_channel_tpu_vote();
|
|
|
|
let (gossip_vote_sender, gossip_vote_receiver) =
|
|
|
|
banking_tracer.create_channel_gossip_vote();
|
2022-10-20 14:10:48 -07:00
|
|
|
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
|
|
|
{
|
|
|
|
let blockstore = Arc::new(
|
|
|
|
Blockstore::open(ledger_path.path())
|
|
|
|
.expect("Expected to be able to open database ledger"),
|
|
|
|
);
|
|
|
|
let poh_config = PohConfig {
|
|
|
|
// limit tick count to avoid clearing working_bank at PohRecord then
|
|
|
|
// PohRecorderError(MaxHeightReached) at BankingStage
|
|
|
|
target_tick_count: Some(bank.max_tick_height() - 1),
|
|
|
|
..PohConfig::default()
|
|
|
|
};
|
|
|
|
let (exit, poh_recorder, poh_service, _entry_receiver) =
|
2023-04-19 11:41:18 -07:00
|
|
|
create_test_recorder(&bank, blockstore, Some(poh_config), None);
|
2023-01-24 08:57:55 -08:00
|
|
|
let (_, cluster_info) = new_test_cluster_info(/*keypair:*/ None);
|
2022-10-20 14:10:48 -07:00
|
|
|
let cluster_info = Arc::new(cluster_info);
|
2023-01-17 21:14:04 -08:00
|
|
|
let (replay_vote_sender, _replay_vote_receiver) = unbounded();
|
2022-05-04 19:50:56 -07:00
|
|
|
|
2022-10-20 14:10:48 -07:00
|
|
|
let banking_stage = BankingStage::new(
|
|
|
|
&cluster_info,
|
|
|
|
&poh_recorder,
|
2023-01-18 17:04:55 -08:00
|
|
|
non_vote_receiver,
|
2022-10-20 14:10:48 -07:00
|
|
|
tpu_vote_receiver,
|
2023-01-18 17:04:55 -08:00
|
|
|
gossip_vote_receiver,
|
2022-10-20 14:10:48 -07:00
|
|
|
None,
|
2023-01-17 21:14:04 -08:00
|
|
|
replay_vote_sender,
|
2022-10-20 14:10:48 -07:00
|
|
|
None,
|
|
|
|
Arc::new(ConnectionCache::default()),
|
|
|
|
bank_forks,
|
2023-03-23 17:05:54 -07:00
|
|
|
&Arc::new(PrioritizationFeeCache::new(0u64)),
|
2022-10-20 14:10:48 -07:00
|
|
|
);
|
2022-05-04 19:50:56 -07:00
|
|
|
|
2022-10-20 14:10:48 -07:00
|
|
|
let keypairs = (0..100).map(|_| Keypair::new()).collect_vec();
|
|
|
|
let vote_keypairs = (0..100).map(|_| Keypair::new()).collect_vec();
|
|
|
|
for keypair in keypairs.iter() {
|
|
|
|
bank.process_transaction(&system_transaction::transfer(
|
|
|
|
&mint_keypair,
|
|
|
|
&keypair.pubkey(),
|
|
|
|
20,
|
|
|
|
start_hash,
|
|
|
|
))
|
|
|
|
.unwrap();
|
|
|
|
}
|
2022-05-04 19:50:56 -07:00
|
|
|
|
2022-10-20 14:10:48 -07:00
|
|
|
// Send a bunch of votes and transfers
|
|
|
|
let tpu_votes = (0..100_usize)
|
|
|
|
.map(|i| {
|
|
|
|
new_vote_state_update_transaction(
|
|
|
|
VoteStateUpdate::from(vec![
|
|
|
|
(0, 8),
|
|
|
|
(1, 7),
|
|
|
|
(i as u64 + 10, 6),
|
|
|
|
(i as u64 + 11, 1),
|
|
|
|
]),
|
|
|
|
Hash::new_unique(),
|
|
|
|
&keypairs[i],
|
|
|
|
&vote_keypairs[i],
|
|
|
|
&vote_keypairs[i],
|
|
|
|
None,
|
|
|
|
);
|
|
|
|
})
|
|
|
|
.collect_vec();
|
|
|
|
let gossip_votes = (0..100_usize)
|
|
|
|
.map(|i| {
|
|
|
|
new_vote_state_update_transaction(
|
|
|
|
VoteStateUpdate::from(vec![
|
|
|
|
(0, 8),
|
|
|
|
(1, 7),
|
|
|
|
(i as u64 + 64 + 5, 6),
|
|
|
|
(i as u64 + 7, 1),
|
|
|
|
]),
|
|
|
|
Hash::new_unique(),
|
|
|
|
&keypairs[i],
|
|
|
|
&vote_keypairs[i],
|
|
|
|
&vote_keypairs[i],
|
|
|
|
None,
|
|
|
|
);
|
|
|
|
})
|
|
|
|
.collect_vec();
|
|
|
|
let txs = (0..100_usize)
|
|
|
|
.map(|i| {
|
|
|
|
system_transaction::transfer(
|
|
|
|
&keypairs[i],
|
|
|
|
&keypairs[(i + 1) % 100].pubkey(),
|
|
|
|
10,
|
|
|
|
start_hash,
|
|
|
|
);
|
|
|
|
})
|
|
|
|
.collect_vec();
|
2022-05-04 19:50:56 -07:00
|
|
|
|
2023-01-18 17:04:55 -08:00
|
|
|
let non_vote_packet_batches = to_packet_batches(&txs, 10);
|
2022-10-20 14:10:48 -07:00
|
|
|
let tpu_packet_batches = to_packet_batches(&tpu_votes, 10);
|
|
|
|
let gossip_packet_batches = to_packet_batches(&gossip_votes, 10);
|
2022-05-04 19:50:56 -07:00
|
|
|
|
2022-10-20 14:10:48 -07:00
|
|
|
// Send em all
|
|
|
|
[
|
2023-01-18 17:04:55 -08:00
|
|
|
(non_vote_packet_batches, non_vote_sender),
|
|
|
|
(tpu_packet_batches, tpu_vote_sender),
|
|
|
|
(gossip_packet_batches, gossip_vote_sender),
|
2022-10-20 14:10:48 -07:00
|
|
|
]
|
|
|
|
.into_iter()
|
|
|
|
.map(|(packet_batches, sender)| {
|
|
|
|
Builder::new()
|
2023-01-25 04:54:38 -08:00
|
|
|
.spawn(move || {
|
|
|
|
sender
|
|
|
|
.send(BankingPacketBatch::new((packet_batches, None)))
|
|
|
|
.unwrap()
|
|
|
|
})
|
2022-10-20 14:10:48 -07:00
|
|
|
.unwrap()
|
|
|
|
})
|
|
|
|
.for_each(|handle| handle.join().unwrap());
|
|
|
|
|
|
|
|
banking_stage.join().unwrap();
|
|
|
|
exit.store(true, Ordering::Relaxed);
|
|
|
|
poh_service.join().unwrap();
|
|
|
|
}
|
|
|
|
Blockstore::destroy(ledger_path.path()).unwrap();
|
2022-05-04 19:50:56 -07:00
|
|
|
}
|
2018-09-25 15:01:51 -07:00
|
|
|
}
|