Add microbenchmark for signature verification
This commit is contained in:
parent
4bc41d81ee
commit
878ca8c5c5
|
@ -46,19 +46,6 @@ fn main() {
|
||||||
nsps / 1_000_f64
|
nsps / 1_000_f64
|
||||||
);
|
);
|
||||||
|
|
||||||
println!("Verify signatures...");
|
|
||||||
let now = Instant::now();
|
|
||||||
transactions.par_iter().for_each(|tr| assert!(tr.verify()));
|
|
||||||
let duration = now.elapsed();
|
|
||||||
let ns = duration.as_secs() * 1_000_000_000 + u64::from(duration.subsec_nanos());
|
|
||||||
let bsvps = txs as f64 / ns as f64;
|
|
||||||
let nspsv = ns as f64 / txs as f64;
|
|
||||||
println!(
|
|
||||||
"Done. {} thousand signature verifications per second, {}us per signature verification",
|
|
||||||
bsvps * 1_000_000_f64,
|
|
||||||
nspsv / 1_000_f64
|
|
||||||
);
|
|
||||||
|
|
||||||
println!("Transferring 1 unit {} times...", txs);
|
println!("Transferring 1 unit {} times...", txs);
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let mut _sig = Default::default();
|
let mut _sig = Default::default();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use event::Event;
|
use event::Event;
|
||||||
use hash::{extend_and_hash, hash, Hash};
|
use hash::{extend_and_hash, hash, Hash};
|
||||||
|
use rayon::prelude::*;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct Entry {
|
pub struct Entry {
|
||||||
|
@ -22,12 +23,8 @@ impl Entry {
|
||||||
/// Verifies self.id is the result of hashing a `start_hash` `self.num_hashes` times.
|
/// Verifies self.id is the result of hashing a `start_hash` `self.num_hashes` times.
|
||||||
/// If the event is not a Tick, then hash that as well.
|
/// If the event is not a Tick, then hash that as well.
|
||||||
pub fn verify(&self, start_hash: &Hash) -> bool {
|
pub fn verify(&self, start_hash: &Hash) -> bool {
|
||||||
for event in &self.events {
|
self.events.par_iter().all(|event| event.verify())
|
||||||
if !event.verify() {
|
&& self.id == next_hash(start_hash, self.num_hashes, &self.events)
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.id == next_hash(start_hash, self.num_hashes, &self.events)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@ use rayon::prelude::*;
|
||||||
/// Verifies the hashes and counts of a slice of events are all consistent.
|
/// Verifies the hashes and counts of a slice of events are all consistent.
|
||||||
pub fn verify_slice(entries: &[Entry], start_hash: &Hash) -> bool {
|
pub fn verify_slice(entries: &[Entry], start_hash: &Hash) -> bool {
|
||||||
let genesis = [Entry::new_tick(Default::default(), start_hash)];
|
let genesis = [Entry::new_tick(Default::default(), start_hash)];
|
||||||
let event_pairs = genesis.par_iter().chain(entries).zip(entries);
|
let entry_pairs = genesis.par_iter().chain(entries).zip(entries);
|
||||||
event_pairs.all(|(x0, x1)| x1.verify(&x0.id))
|
entry_pairs.all(|(x0, x1)| x1.verify(&x0.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a vector of Ticks of length `len` from `start_hash` hash and `num_hashes`.
|
/// Create a vector of Ticks of length `len` from `start_hash` hash and `num_hashes`.
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
|
use rayon::prelude::*;
|
||||||
use hash::Hash;
|
use hash::Hash;
|
||||||
use plan::{Condition, Payment, Plan};
|
use plan::{Condition, Payment, Plan};
|
||||||
use signature::{KeyPair, KeyPairUtil, PublicKey, Signature, SignatureUtil};
|
use signature::{KeyPair, KeyPairUtil, PublicKey, Signature, SignatureUtil};
|
||||||
|
@ -67,6 +68,21 @@ impl Transaction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verify a batch of signatures.
|
||||||
|
pub fn verify_signatures(transactions: &[Transaction]) -> bool {
|
||||||
|
transactions.par_iter().all(|tr| tr.verify())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Verify a batch of spending plans.
|
||||||
|
pub fn verify_plans(transactions: &[Transaction]) -> bool {
|
||||||
|
transactions.par_iter().all(|tr| tr.plan.verify(tr.tokens))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Verify a batch of transactions.
|
||||||
|
pub fn verify_transactions(transactions: &[Transaction]) -> bool {
|
||||||
|
verify_signatures(transactions) && verify_plans(transactions)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -133,4 +149,39 @@ mod tests {
|
||||||
};
|
};
|
||||||
assert!(!tr.verify());
|
assert!(!tr.verify());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_verify_transactions() {
|
||||||
|
let alice_keypair = KeyPair::new();
|
||||||
|
let bob_pubkey = KeyPair::new().pubkey();
|
||||||
|
let carol_pubkey = KeyPair::new().pubkey();
|
||||||
|
let last_id = Hash::default();
|
||||||
|
let tr0 = Transaction::new(&alice_keypair, bob_pubkey, 1, last_id);
|
||||||
|
let tr1 = Transaction::new(&alice_keypair, carol_pubkey, 1, last_id);
|
||||||
|
let transactions = vec![tr0, tr1];
|
||||||
|
assert!(verify_transactions(&transactions));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "unstable", test))]
|
||||||
|
mod bench {
|
||||||
|
extern crate test;
|
||||||
|
use self::test::Bencher;
|
||||||
|
use transaction::*;
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn verify_signatures_bench(bencher: &mut Bencher) {
|
||||||
|
let alice_keypair = KeyPair::new();
|
||||||
|
let last_id = Hash::default();
|
||||||
|
let transactions: Vec<_> = (0..64)
|
||||||
|
.into_par_iter()
|
||||||
|
.map(|_| {
|
||||||
|
let rando_pubkey = KeyPair::new().pubkey();
|
||||||
|
Transaction::new(&alice_keypair, rando_pubkey, 1, last_id)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
bencher.iter(|| {
|
||||||
|
assert!(verify_signatures(&transactions));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue