diff --git a/src/bin/client-demo.rs b/src/bin/client-demo.rs index 05e4f2fd1b..38b3223842 100644 --- a/src/bin/client-demo.rs +++ b/src/bin/client-demo.rs @@ -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(); diff --git a/src/entry.rs b/src/entry.rs index f69d8d125e..1cc2819e85 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -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) } } diff --git a/src/ledger.rs b/src/ledger.rs index 5beef93e9c..9385ab555a 100644 --- a/src/ledger.rs +++ b/src/ledger.rs @@ -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`. diff --git a/src/transaction.rs b/src/transaction.rs index 7e7674c195..4aca2742a7 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -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)); + }); + } }