2018-06-06 10:31:18 -07:00
|
|
|
//! The `sigverify_stage` implements the signature verification stage of the TPU. It
|
|
|
|
//! receives a list of lists of packets and outputs the same list, but tags each
|
|
|
|
//! top-level list with a list of booleans, telling the next stage whether the
|
|
|
|
//! signature in that packet is valid. It assumes each packet contains one
|
|
|
|
//! transaction. All processing is done on the CPU by default and on a GPU
|
2019-09-26 13:36:51 -07:00
|
|
|
//! if perf-libs are available
|
2018-05-11 20:51:37 -07:00
|
|
|
|
2019-04-17 18:15:50 -07:00
|
|
|
use crate::packet::Packets;
|
2018-12-07 19:16:27 -08:00
|
|
|
use crate::result::{Error, Result};
|
|
|
|
use crate::service::Service;
|
|
|
|
use crate::sigverify;
|
|
|
|
use crate::streamer::{self, PacketReceiver};
|
2019-06-26 18:42:27 -07:00
|
|
|
use crossbeam_channel::Sender as CrossbeamSender;
|
2019-10-18 09:28:51 -07:00
|
|
|
use solana_ledger::perf_libs;
|
2019-06-29 06:34:49 -07:00
|
|
|
use solana_measure::measure::Measure;
|
2019-10-04 16:25:22 -07:00
|
|
|
use solana_metrics::{datapoint_debug, inc_new_counter_info};
|
2018-11-16 08:45:59 -08:00
|
|
|
use solana_sdk::timing;
|
2019-06-26 18:42:27 -07:00
|
|
|
use std::sync::mpsc::{Receiver, RecvTimeoutError};
|
2018-05-11 20:51:37 -07:00
|
|
|
use std::sync::{Arc, Mutex};
|
2019-04-12 16:31:59 -07:00
|
|
|
use std::thread::{self, Builder, JoinHandle};
|
2018-05-11 20:51:37 -07:00
|
|
|
|
2019-09-26 13:36:51 -07:00
|
|
|
const RECV_BATCH_MAX_CPU: usize = 1_000;
|
|
|
|
const RECV_BATCH_MAX_GPU: usize = 5_000;
|
2019-04-23 12:41:50 -07:00
|
|
|
|
2018-05-11 20:51:37 -07:00
|
|
|
pub struct SigVerifyStage {
|
2018-07-03 21:14:08 -07:00
|
|
|
thread_hdls: Vec<JoinHandle<()>>,
|
2018-05-11 20:51:37 -07:00
|
|
|
}
|
|
|
|
|
2019-10-28 16:07:51 -07:00
|
|
|
pub trait SigVerifier {
|
2019-11-01 14:23:03 -07:00
|
|
|
fn verify_batch(&self, batch: Vec<Packets>) -> Vec<Packets>;
|
2019-10-28 16:07:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Default, Clone)]
|
|
|
|
pub struct DisabledSigVerifier {}
|
|
|
|
|
|
|
|
impl SigVerifier for DisabledSigVerifier {
|
2019-11-01 14:23:03 -07:00
|
|
|
fn verify_batch(&self, mut batch: Vec<Packets>) -> Vec<Packets> {
|
2019-10-28 16:07:51 -07:00
|
|
|
let r = sigverify::ed25519_verify_disabled(&batch);
|
2019-11-01 14:23:03 -07:00
|
|
|
sigverify::mark_disabled(&mut batch, &r);
|
|
|
|
batch
|
2019-10-28 16:07:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-11 20:51:37 -07:00
|
|
|
impl SigVerifyStage {
|
2018-12-07 19:01:28 -08:00
|
|
|
#[allow(clippy::new_ret_no_self)]
|
2019-10-28 16:07:51 -07:00
|
|
|
pub fn new<T: SigVerifier + 'static + Send + Clone>(
|
2019-04-17 18:15:50 -07:00
|
|
|
packet_receiver: Receiver<Packets>,
|
2019-11-01 14:23:03 -07:00
|
|
|
verified_sender: CrossbeamSender<Vec<Packets>>,
|
2019-10-28 16:07:51 -07:00
|
|
|
verifier: T,
|
2019-04-09 12:57:12 -07:00
|
|
|
) -> Self {
|
2019-10-28 16:07:51 -07:00
|
|
|
let thread_hdls = Self::verifier_services(packet_receiver, verified_sender, verifier);
|
2019-04-09 12:57:12 -07:00
|
|
|
Self { thread_hdls }
|
2018-05-11 20:51:37 -07:00
|
|
|
}
|
|
|
|
|
2019-10-28 16:07:51 -07:00
|
|
|
fn verifier<T: SigVerifier>(
|
2018-06-27 11:33:56 -07:00
|
|
|
recvr: &Arc<Mutex<PacketReceiver>>,
|
2019-11-01 14:23:03 -07:00
|
|
|
sendr: &CrossbeamSender<Vec<Packets>>,
|
2019-04-12 16:31:59 -07:00
|
|
|
id: usize,
|
2019-10-28 16:07:51 -07:00
|
|
|
verifier: &T,
|
2018-05-11 20:51:37 -07:00
|
|
|
) -> Result<()> {
|
2019-04-23 12:41:50 -07:00
|
|
|
let (batch, len, recv_time) = streamer::recv_batch(
|
|
|
|
&recvr.lock().expect("'recvr' lock in fn verifier"),
|
2019-09-26 13:36:51 -07:00
|
|
|
if perf_libs::api().is_some() {
|
|
|
|
RECV_BATCH_MAX_GPU
|
|
|
|
} else {
|
|
|
|
RECV_BATCH_MAX_CPU
|
|
|
|
},
|
2019-04-23 12:41:50 -07:00
|
|
|
)?;
|
2019-04-11 10:04:45 -07:00
|
|
|
inc_new_counter_info!("sigverify_stage-packets_received", len);
|
2018-05-11 20:51:37 -07:00
|
|
|
|
2019-06-29 06:34:49 -07:00
|
|
|
let mut verify_batch_time = Measure::start("sigverify_batch_time");
|
2018-05-11 20:51:37 -07:00
|
|
|
let batch_len = batch.len();
|
2019-04-12 16:31:59 -07:00
|
|
|
debug!(
|
2018-05-11 20:51:37 -07:00
|
|
|
"@{:?} verifier: verifying: {} id: {}",
|
|
|
|
timing::timestamp(),
|
2019-06-27 00:32:32 -07:00
|
|
|
len,
|
2019-04-12 16:31:59 -07:00
|
|
|
id
|
2018-05-11 20:51:37 -07:00
|
|
|
);
|
|
|
|
|
2019-10-28 16:07:51 -07:00
|
|
|
let verified_batch = verifier.verify_batch(batch);
|
2019-04-11 10:04:45 -07:00
|
|
|
inc_new_counter_info!("sigverify_stage-verified_packets_send", len);
|
2018-09-14 14:34:32 -07:00
|
|
|
|
2019-06-29 06:34:49 -07:00
|
|
|
for v in verified_batch {
|
|
|
|
if sendr.send(vec![v]).is_err() {
|
|
|
|
return Err(Error::SendError);
|
|
|
|
}
|
2018-09-14 14:34:32 -07:00
|
|
|
}
|
2018-05-11 20:51:37 -07:00
|
|
|
|
2019-06-29 06:34:49 -07:00
|
|
|
verify_batch_time.stop();
|
|
|
|
|
2018-09-24 17:13:49 -07:00
|
|
|
inc_new_counter_info!(
|
|
|
|
"sigverify_stage-time_ms",
|
2019-06-29 06:34:49 -07:00
|
|
|
(verify_batch_time.as_ms() + recv_time) as usize
|
2018-09-24 17:13:49 -07:00
|
|
|
);
|
2019-04-12 16:31:59 -07:00
|
|
|
debug!(
|
2018-05-11 20:51:37 -07:00
|
|
|
"@{:?} verifier: done. batches: {} total verify time: {:?} id: {} verified: {} v/s {}",
|
|
|
|
timing::timestamp(),
|
|
|
|
batch_len,
|
2019-06-29 06:34:49 -07:00
|
|
|
verify_batch_time.as_ms(),
|
2019-04-12 16:31:59 -07:00
|
|
|
id,
|
2018-05-11 20:51:37 -07:00
|
|
|
len,
|
2019-06-29 06:34:49 -07:00
|
|
|
(len as f32 / verify_batch_time.as_s())
|
2018-05-11 20:51:37 -07:00
|
|
|
);
|
2018-08-04 19:32:15 -07:00
|
|
|
|
2019-10-04 16:25:22 -07:00
|
|
|
datapoint_debug!(
|
2019-05-10 08:33:58 -07:00
|
|
|
"sigverify_stage-total_verify_time",
|
|
|
|
("batch_len", batch_len, i64),
|
|
|
|
("len", len, i64),
|
2019-06-29 06:34:49 -07:00
|
|
|
("total_time_ms", verify_batch_time.as_ms(), i64)
|
2018-08-04 19:32:15 -07:00
|
|
|
);
|
|
|
|
|
2018-05-11 20:51:37 -07:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2019-10-28 16:07:51 -07:00
|
|
|
fn verifier_service<T: SigVerifier + 'static + Send + Clone>(
|
2018-06-27 11:33:56 -07:00
|
|
|
packet_receiver: Arc<Mutex<PacketReceiver>>,
|
2019-11-01 14:23:03 -07:00
|
|
|
verified_sender: CrossbeamSender<Vec<Packets>>,
|
2019-04-12 16:31:59 -07:00
|
|
|
id: usize,
|
2019-10-28 16:07:51 -07:00
|
|
|
verifier: &T,
|
2018-05-11 20:51:37 -07:00
|
|
|
) -> JoinHandle<()> {
|
2019-10-28 16:07:51 -07:00
|
|
|
let verifier = verifier.clone();
|
2019-04-12 16:31:59 -07:00
|
|
|
Builder::new()
|
|
|
|
.name(format!("solana-verifier-{}", id))
|
2019-10-28 16:07:51 -07:00
|
|
|
.spawn(move || loop {
|
|
|
|
if let Err(e) = Self::verifier(&packet_receiver, &verified_sender, id, &verifier) {
|
|
|
|
match e {
|
|
|
|
Error::RecvTimeoutError(RecvTimeoutError::Disconnected) => break,
|
|
|
|
Error::RecvTimeoutError(RecvTimeoutError::Timeout) => (),
|
|
|
|
Error::SendError => {
|
|
|
|
break;
|
2019-04-12 16:31:59 -07:00
|
|
|
}
|
2019-10-28 16:07:51 -07:00
|
|
|
_ => error!("{:?}", e),
|
2018-09-14 14:34:32 -07:00
|
|
|
}
|
2018-07-05 14:58:33 -07:00
|
|
|
}
|
2019-04-12 16:31:59 -07:00
|
|
|
})
|
|
|
|
.unwrap()
|
2018-05-11 20:51:37 -07:00
|
|
|
}
|
|
|
|
|
2019-10-28 16:07:51 -07:00
|
|
|
fn verifier_services<T: SigVerifier + 'static + Send + Clone>(
|
2018-06-27 11:33:56 -07:00
|
|
|
packet_receiver: PacketReceiver,
|
2019-11-01 14:23:03 -07:00
|
|
|
verified_sender: CrossbeamSender<Vec<Packets>>,
|
2019-10-28 16:07:51 -07:00
|
|
|
verifier: T,
|
2018-05-11 20:51:37 -07:00
|
|
|
) -> Vec<JoinHandle<()>> {
|
2018-05-15 11:15:29 -07:00
|
|
|
let receiver = Arc::new(Mutex::new(packet_receiver));
|
2018-05-11 20:51:37 -07:00
|
|
|
(0..4)
|
2019-04-12 16:31:59 -07:00
|
|
|
.map(|id| {
|
2019-10-28 16:07:51 -07:00
|
|
|
Self::verifier_service(receiver.clone(), verified_sender.clone(), id, &verifier)
|
2019-04-05 16:15:14 -07:00
|
|
|
})
|
2018-05-11 20:51:37 -07:00
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
}
|
2018-07-03 21:14:08 -07:00
|
|
|
|
|
|
|
impl Service for SigVerifyStage {
|
2018-09-13 14:00:17 -07:00
|
|
|
type JoinReturnType = ();
|
2018-07-03 21:14:08 -07:00
|
|
|
|
|
|
|
fn join(self) -> thread::Result<()> {
|
2018-09-13 14:00:17 -07:00
|
|
|
for thread_hdl in self.thread_hdls {
|
2018-07-03 21:14:08 -07:00
|
|
|
thread_hdl.join()?;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|