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
|
|
|
|
//! if the `cuda` feature is enabled with `--features=cuda`.
|
2018-05-11 20:51:37 -07:00
|
|
|
|
2018-09-24 17:13:49 -07:00
|
|
|
use counter::Counter;
|
2018-11-16 08:45:59 -08:00
|
|
|
|
2018-09-24 17:13:49 -07:00
|
|
|
use log::Level;
|
2018-05-11 20:51:37 -07:00
|
|
|
use packet::SharedPackets;
|
|
|
|
use rand::{thread_rng, Rng};
|
2018-07-05 14:58:33 -07:00
|
|
|
use result::{Error, Result};
|
2018-07-03 21:14:08 -07:00
|
|
|
use service::Service;
|
2018-05-25 15:52:17 -07:00
|
|
|
use sigverify;
|
2018-11-16 08:45:59 -08:00
|
|
|
use solana_metrics::{influxdb, submit};
|
|
|
|
use solana_sdk::timing;
|
2018-09-24 17:13:49 -07:00
|
|
|
use std::sync::atomic::AtomicUsize;
|
2018-07-05 14:58:33 -07:00
|
|
|
use std::sync::mpsc::{channel, Receiver, RecvTimeoutError, Sender};
|
2018-05-11 20:51:37 -07:00
|
|
|
use std::sync::{Arc, Mutex};
|
2018-07-03 21:14:08 -07:00
|
|
|
use std::thread::{self, spawn, JoinHandle};
|
2018-05-11 20:51:37 -07:00
|
|
|
use std::time::Instant;
|
2018-06-27 11:33:56 -07:00
|
|
|
use streamer::{self, PacketReceiver};
|
2018-05-11 20:51:37 -07:00
|
|
|
|
2018-07-11 13:40:46 -07:00
|
|
|
pub type VerifiedPackets = Vec<(SharedPackets, Vec<u8>)>;
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
impl SigVerifyStage {
|
2018-12-07 19:01:28 -08:00
|
|
|
#[allow(clippy::new_ret_no_self)]
|
2018-07-31 16:54:24 -07:00
|
|
|
pub fn new(
|
|
|
|
packet_receiver: Receiver<SharedPackets>,
|
|
|
|
sigverify_disabled: bool,
|
|
|
|
) -> (Self, Receiver<VerifiedPackets>) {
|
2018-07-14 15:58:08 -07:00
|
|
|
sigverify::init();
|
2018-05-12 14:24:17 -07:00
|
|
|
let (verified_sender, verified_receiver) = channel();
|
2018-07-31 16:54:24 -07:00
|
|
|
let thread_hdls =
|
|
|
|
Self::verifier_services(packet_receiver, verified_sender, sigverify_disabled);
|
2018-12-07 19:01:28 -08:00
|
|
|
(Self { thread_hdls }, verified_receiver)
|
2018-05-11 20:51:37 -07:00
|
|
|
}
|
|
|
|
|
2018-07-31 16:54:24 -07:00
|
|
|
fn verify_batch(batch: Vec<SharedPackets>, sigverify_disabled: bool) -> VerifiedPackets {
|
|
|
|
let r = if sigverify_disabled {
|
|
|
|
sigverify::ed25519_verify_disabled(&batch)
|
|
|
|
} else {
|
|
|
|
sigverify::ed25519_verify(&batch)
|
|
|
|
};
|
2018-05-11 20:51:37 -07:00
|
|
|
batch.into_iter().zip(r).collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn verifier(
|
2018-06-27 11:33:56 -07:00
|
|
|
recvr: &Arc<Mutex<PacketReceiver>>,
|
2018-07-11 13:40:46 -07:00
|
|
|
sendr: &Arc<Mutex<Sender<VerifiedPackets>>>,
|
2018-07-31 16:54:24 -07:00
|
|
|
sigverify_disabled: bool,
|
2018-05-11 20:51:37 -07:00
|
|
|
) -> Result<()> {
|
2018-09-24 17:13:49 -07:00
|
|
|
let (batch, len, recv_time) =
|
2018-05-11 20:51:37 -07:00
|
|
|
streamer::recv_batch(&recvr.lock().expect("'recvr' lock in fn verifier"))?;
|
2018-09-24 17:13:49 -07:00
|
|
|
inc_new_counter_info!("sigverify_stage-entries_received", len);
|
2018-05-11 20:51:37 -07:00
|
|
|
|
|
|
|
let now = Instant::now();
|
|
|
|
let batch_len = batch.len();
|
|
|
|
let rand_id = thread_rng().gen_range(0, 100);
|
|
|
|
info!(
|
|
|
|
"@{:?} verifier: verifying: {} id: {}",
|
|
|
|
timing::timestamp(),
|
|
|
|
batch.len(),
|
|
|
|
rand_id
|
|
|
|
);
|
|
|
|
|
2018-07-31 16:54:24 -07:00
|
|
|
let verified_batch = Self::verify_batch(batch, sigverify_disabled);
|
2018-09-24 17:13:49 -07:00
|
|
|
inc_new_counter_info!(
|
|
|
|
"sigverify_stage-verified_entries_send",
|
|
|
|
verified_batch.len()
|
|
|
|
);
|
2018-09-14 14:34:32 -07:00
|
|
|
|
2018-09-23 14:38:17 -07:00
|
|
|
if sendr
|
2018-05-11 20:51:37 -07:00
|
|
|
.lock()
|
|
|
|
.expect("lock in fn verify_batch in tpu")
|
2018-09-14 14:34:32 -07:00
|
|
|
.send(verified_batch)
|
2018-09-23 14:38:17 -07:00
|
|
|
.is_err()
|
2018-09-14 14:34:32 -07:00
|
|
|
{
|
2018-09-23 14:38:17 -07:00
|
|
|
return Err(Error::SendError);
|
2018-09-14 14:34:32 -07:00
|
|
|
}
|
2018-05-11 20:51:37 -07:00
|
|
|
|
|
|
|
let total_time_ms = timing::duration_as_ms(&now.elapsed());
|
|
|
|
let total_time_s = timing::duration_as_s(&now.elapsed());
|
2018-09-24 17:13:49 -07:00
|
|
|
inc_new_counter_info!(
|
|
|
|
"sigverify_stage-time_ms",
|
|
|
|
(total_time_ms + recv_time) as usize
|
|
|
|
);
|
2018-05-11 20:51:37 -07:00
|
|
|
info!(
|
|
|
|
"@{:?} verifier: done. batches: {} total verify time: {:?} id: {} verified: {} v/s {}",
|
|
|
|
timing::timestamp(),
|
|
|
|
batch_len,
|
|
|
|
total_time_ms,
|
|
|
|
rand_id,
|
|
|
|
len,
|
|
|
|
(len as f32 / total_time_s)
|
|
|
|
);
|
2018-08-04 19:32:15 -07:00
|
|
|
|
2018-11-16 08:45:59 -08:00
|
|
|
submit(
|
2018-08-04 19:32:15 -07:00
|
|
|
influxdb::Point::new("sigverify_stage-total_verify_time")
|
|
|
|
.add_field("batch_len", influxdb::Value::Integer(batch_len as i64))
|
|
|
|
.add_field("len", influxdb::Value::Integer(len as i64))
|
|
|
|
.add_field(
|
|
|
|
"total_time_ms",
|
|
|
|
influxdb::Value::Integer(total_time_ms as i64),
|
2018-12-07 19:01:28 -08:00
|
|
|
)
|
|
|
|
.to_owned(),
|
2018-08-04 19:32:15 -07:00
|
|
|
);
|
|
|
|
|
2018-05-11 20:51:37 -07:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn verifier_service(
|
2018-06-27 11:33:56 -07:00
|
|
|
packet_receiver: Arc<Mutex<PacketReceiver>>,
|
2018-07-11 13:40:46 -07:00
|
|
|
verified_sender: Arc<Mutex<Sender<VerifiedPackets>>>,
|
2018-07-31 16:54:24 -07:00
|
|
|
sigverify_disabled: bool,
|
2018-05-11 20:51:37 -07:00
|
|
|
) -> JoinHandle<()> {
|
|
|
|
spawn(move || loop {
|
2018-07-31 16:54:24 -07:00
|
|
|
if let Err(e) = Self::verifier(&packet_receiver, &verified_sender, sigverify_disabled) {
|
2018-07-05 14:58:33 -07:00
|
|
|
match e {
|
|
|
|
Error::RecvTimeoutError(RecvTimeoutError::Disconnected) => break,
|
|
|
|
Error::RecvTimeoutError(RecvTimeoutError::Timeout) => (),
|
2018-09-14 14:34:32 -07:00
|
|
|
Error::SendError => {
|
|
|
|
break;
|
|
|
|
}
|
2018-07-05 14:58:33 -07:00
|
|
|
_ => error!("{:?}", e),
|
|
|
|
}
|
2018-05-11 20:51:37 -07:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn verifier_services(
|
2018-06-27 11:33:56 -07:00
|
|
|
packet_receiver: PacketReceiver,
|
2018-07-11 13:40:46 -07:00
|
|
|
verified_sender: Sender<VerifiedPackets>,
|
2018-07-31 16:54:24 -07:00
|
|
|
sigverify_disabled: bool,
|
2018-05-11 20:51:37 -07:00
|
|
|
) -> Vec<JoinHandle<()>> {
|
|
|
|
let sender = Arc::new(Mutex::new(verified_sender));
|
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)
|
2018-07-31 16:54:24 -07:00
|
|
|
.map(|_| Self::verifier_service(receiver.clone(), sender.clone(), sigverify_disabled))
|
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(())
|
|
|
|
}
|
|
|
|
}
|