Merge pull request #89 from garious/sig-verify-bench

Add microbenchmark for signature verification
This commit is contained in:
Greg Fitzgerald 2018-03-28 22:15:10 -06:00 committed by GitHub
commit cc2bb290c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 21 deletions

View File

@ -46,19 +46,6 @@ fn main() {
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);
let now = Instant::now();
let mut _sig = Default::default();

View File

@ -1,5 +1,6 @@
use event::Event;
use hash::{extend_and_hash, hash, Hash};
use rayon::prelude::*;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Entry {
@ -22,12 +23,8 @@ impl Entry {
/// 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.
pub fn verify(&self, start_hash: &Hash) -> bool {
for event in &self.events {
if !event.verify() {
return false;
}
}
self.id == next_hash(start_hash, self.num_hashes, &self.events)
self.events.par_iter().all(|event| event.verify())
&& self.id == next_hash(start_hash, self.num_hashes, &self.events)
}
}

View File

@ -19,8 +19,8 @@ use rayon::prelude::*;
/// Verifies the hashes and counts of a slice of events are all consistent.
pub fn verify_slice(entries: &[Entry], start_hash: &Hash) -> bool {
let genesis = [Entry::new_tick(Default::default(), start_hash)];
let event_pairs = genesis.par_iter().chain(entries).zip(entries);
event_pairs.all(|(x0, x1)| x1.verify(&x0.id))
let entry_pairs = genesis.par_iter().chain(entries).zip(entries);
entry_pairs.all(|(x0, x1)| x1.verify(&x0.id))
}
/// Create a vector of Ticks of length `len` from `start_hash` hash and `num_hashes`.

View File

@ -2,6 +2,7 @@
use bincode::serialize;
use chrono::prelude::*;
use rayon::prelude::*;
use hash::Hash;
use plan::{Condition, Payment, Plan};
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)]
mod tests {
use super::*;
@ -133,4 +149,39 @@ mod tests {
};
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));
});
}
}