Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
Check transaction signatures in entry verify
Browse files Browse the repository at this point in the history
  • Loading branch information
sakridge committed Mar 4, 2020
1 parent 4f05f08 commit 6fbba93
Showing 1 changed file with 60 additions and 3 deletions.
63 changes: 60 additions & 3 deletions ledger/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ pub trait EntrySlice {
fn verify_tick_hash_count(&self, tick_hash_count: &mut u64, hashes_per_tick: u64) -> bool;
/// Counts tick entries
fn tick_count(&self) -> u64;
fn verify_transaction_signatures(&self) -> bool;
}

impl EntrySlice for [Entry] {
Expand Down Expand Up @@ -304,20 +305,42 @@ impl EntrySlice for [Entry] {
})
}

fn verify_transaction_signatures(&self) -> bool {
PAR_THREAD_POOL.with(|thread_pool| {
thread_pool.borrow().install(|| {
self.par_iter().all(|e| {
e.transactions
.par_iter()
.all(|transaction| transaction.verify().is_ok())
})
})
})
}

fn start_verify(
&self,
start_hash: &Hash,
recyclers: VerifyRecyclers,
) -> EntryVerificationState {
let start = Instant::now();
let res = self.verify_transaction_signatures();
if !res {
return EntryVerificationState::CPU(VerificationData {
thread_h: None,
verification_status: EntryVerificationStatus::Failure,
duration_ms: timing::duration_as_ms(&start.elapsed()),
hashes: None,
tx_hashes: vec![],
});
}

let api = perf_libs::api();
if api.is_none() {
return self.verify_cpu(start_hash);
}
let api = api.unwrap();
inc_new_counter_warn!("entry_verify-num_entries", self.len() as usize);

let start = Instant::now();

let genesis = [Entry {
num_hashes: 0,
hash: *start_hash,
Expand Down Expand Up @@ -509,6 +532,40 @@ mod tests {
assert!(!e0.verify(&zero));
}

#[test]
fn test_transaction_signing() {
use solana_sdk::signature::Signature;
let zero = Hash::default();

let keypair = Keypair::new();
let tx0 = system_transaction::transfer(&keypair, &keypair.pubkey(), 0, zero);
let tx1 = system_transaction::transfer(&keypair, &keypair.pubkey(), 1, zero);

// Verify entry with 2 transctions
let mut e0 = vec![Entry::new(&zero, 0, vec![tx0.clone(), tx1.clone()])];
assert!(e0.verify(&zero));

// Clear signature of the first transaction, see that it does not verify
let orig_sig = e0[0].transactions[0].signatures[0];
e0[0].transactions[0].signatures[0] = Signature::default();
assert!(!e0.verify(&zero));

// restore original signature
e0[0].transactions[0].signatures[0] = orig_sig;
assert!(e0.verify(&zero));

// Resize signatures and see verification fails.
let len = e0[0].transactions[0].signatures.len();
e0[0].transactions[0]
.signatures
.resize(len - 1, Signature::default());
assert!(!e0.verify(&zero));

// Pass an entry with no transactions
let e0 = vec![Entry::new(&zero, 0, vec![])];
assert!(e0.verify(&zero));
}

#[test]
fn test_witness_reorder_attack() {
let zero = Hash::default();
Expand Down Expand Up @@ -597,7 +654,7 @@ mod tests {
let zero = Hash::default();
let one = hash(&zero.as_ref());
let two = hash(&one.as_ref());
let alice_pubkey = Keypair::default();
let alice_pubkey = Keypair::new();
let tx0 = create_sample_payment(&alice_pubkey, one);
let tx1 = create_sample_timestamp(&alice_pubkey, one);
assert_eq!(vec![][..].verify(&one), true); // base case
Expand Down

0 comments on commit 6fbba93

Please sign in to comment.