Merge pull request #100 from garious/rollback

Cleanup use of event signatures and entry hashing
This commit is contained in:
Greg Fitzgerald 2018-04-02 21:17:37 -06:00 committed by GitHub
commit 95749ed0e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 66 additions and 21 deletions

View File

@ -3,12 +3,13 @@
//! in flux. Clients should use AccountantStub to interact with it.
use accountant::Accountant;
use historian::Historian;
use recorder::Signal;
use bincode::{deserialize, serialize};
use entry::Entry;
use event::Event;
use hash::Hash;
use historian::Historian;
use rayon::prelude::*;
use recorder::Signal;
use result::Result;
use serde_json;
use signature::PublicKey;
@ -22,7 +23,6 @@ use std::thread::{spawn, JoinHandle};
use std::time::Duration;
use streamer;
use transaction::Transaction;
use rayon::prelude::*;
pub struct AccountantSkel<W: Write + Send + 'static> {
acc: Accountant,

View File

@ -87,8 +87,8 @@ impl AccountantStub {
mod tests {
use super::*;
use accountant::Accountant;
use historian::Historian;
use accountant_skel::AccountantSkel;
use historian::Historian;
use mint::Mint;
use signature::{KeyPair, KeyPairUtil};
use std::io::sink;

View File

@ -2,15 +2,15 @@ extern crate rayon;
extern crate serde_json;
extern crate solana;
use rayon::prelude::*;
use solana::accountant_stub::AccountantStub;
use solana::mint::Mint;
use solana::signature::{KeyPair, KeyPairUtil};
use solana::transaction::Transaction;
use std::io::stdin;
use std::net::UdpSocket;
use std::time::{Duration, Instant};
use std::thread::sleep;
use rayon::prelude::*;
use std::time::{Duration, Instant};
fn main() {
let addr = "127.0.0.1:8000";

View File

@ -2,10 +2,10 @@ extern crate serde_json;
extern crate solana;
use solana::accountant::Accountant;
use solana::event::Event;
use solana::entry::Entry;
use solana::historian::Historian;
use solana::accountant_skel::AccountantSkel;
use solana::entry::Entry;
use solana::event::Event;
use solana::historian::Historian;
use std::io::{self, stdout, BufRead};
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Mutex};

View File

@ -43,6 +43,23 @@ impl Entry {
}
}
fn add_event_data(hash_data: &mut Vec<u8>, event: &Event) {
match *event {
Event::Transaction(ref tr) => {
hash_data.push(0u8);
hash_data.extend_from_slice(&tr.sig);
}
Event::Signature { ref sig, .. } => {
hash_data.push(1u8);
hash_data.extend_from_slice(sig);
}
Event::Timestamp { ref sig, .. } => {
hash_data.push(2u8);
hash_data.extend_from_slice(sig);
}
}
}
/// Creates the hash `num_hashes` after `start_hash`. If the event contains
/// signature, the final hash will be a hash of both the previous ID and
/// the signature.
@ -55,10 +72,7 @@ pub fn next_hash(start_hash: &Hash, num_hashes: u64, events: &[Event]) -> Hash {
// Hash all the event data
let mut hash_data = vec![];
for event in events {
let sig = event.get_signature();
if let Some(sig) = sig {
hash_data.extend_from_slice(&sig);
}
add_event_data(&mut hash_data, event);
}
if !hash_data.is_empty() {
@ -99,6 +113,7 @@ pub fn next_tick(start_hash: &Hash, num_hashes: u64) -> Entry {
#[cfg(test)]
mod tests {
use super::*;
use chrono::prelude::*;
use entry::create_entry;
use event::Event;
use hash::hash;
@ -132,6 +147,23 @@ mod tests {
assert!(!e0.verify(&zero));
}
#[test]
fn test_witness_reorder_attack() {
let zero = Hash::default();
// First, verify entries
let keypair = KeyPair::new();
let tr0 = Event::new_timestamp(&keypair, Utc::now());
let tr1 = Event::new_signature(&keypair, Default::default());
let mut e0 = create_entry(&zero, 0, vec![tr0.clone(), tr1.clone()]);
assert!(e0.verify(&zero));
// Next, swap two witness events and ensure verification fails.
e0.events[0] = tr1; // <-- attack
e0.events[1] = tr0;
assert!(!e0.verify(&zero));
}
#[test]
fn test_next_tick() {
let zero = Hash::default();

View File

@ -33,12 +33,13 @@ impl Event {
}
}
// TODO: Rename this to transaction_signature().
/// If the Event is a Transaction, return its Signature.
pub fn get_signature(&self) -> Option<Signature> {
match *self {
Event::Transaction(ref tr) => Some(tr.sig),
Event::Signature { .. } | Event::Timestamp { .. } => None,
/// Create and sign a new Witness Signature. Used for unit-testing.
pub fn new_signature(from: &KeyPair, tx_sig: Signature) -> Self {
let sig = Signature::clone_from_slice(from.sign(&tx_sig).as_ref());
Event::Signature {
from: from.pubkey(),
tx_sig,
sig,
}
}
@ -52,3 +53,15 @@ impl Event {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use signature::{KeyPair, KeyPairUtil};
#[test]
fn test_event_verify() {
assert!(Event::new_timestamp(&KeyPair::new(), Utc::now()).verify());
assert!(Event::new_signature(&KeyPair::new(), Signature::default()).verify());
}
}

View File

@ -2,9 +2,9 @@
use bincode::serialize;
use chrono::prelude::*;
use rayon::prelude::*;
use hash::Hash;
use plan::{Condition, Payment, Plan};
use rayon::prelude::*;
use signature::{KeyPair, KeyPairUtil, PublicKey, Signature, SignatureUtil};
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
@ -57,7 +57,7 @@ impl Transaction {
}
fn get_sign_data(&self) -> Vec<u8> {
serialize(&(&self.from, &self.plan, &self.tokens, &self.last_id)).unwrap()
serialize(&(&self.plan, &self.tokens, &self.last_id)).unwrap()
}
/// Sign this transaction.