Move Transaction data into its own struct

This will allow us to add addition transfer types to the log.
This commit is contained in:
Greg Fitzgerald 2018-03-06 10:49:40 -07:00
parent 7d9af5a937
commit 6543497c17
6 changed files with 39 additions and 34 deletions

View File

@ -3,7 +3,7 @@
//! transfer funds to other users. //! transfer funds to other users.
use log::{Entry, Sha256Hash}; use log::{Entry, Sha256Hash};
use event::{get_pubkey, sign_transaction_data, verify_event, Event, PublicKey, Signature}; use event::{get_pubkey, sign_transaction_data, verify_event, Event, PublicKey, Signature, Transfer};
use genesis::Genesis; use genesis::Genesis;
use historian::{reserve_signature, Historian}; use historian::{reserve_signature, Historian};
use ring::signature::Ed25519KeyPair; use ring::signature::Ed25519KeyPair;
@ -79,7 +79,7 @@ impl Accountant {
return Err(AccountingError::InvalidEvent); return Err(AccountingError::InvalidEvent);
} }
if let Event::Transaction { from, data, .. } = event { if let Event::Transaction(Transfer { from, data, .. }) = event {
if self.get_balance(&from).unwrap_or(0) < data { if self.get_balance(&from).unwrap_or(0) < data {
return Err(AccountingError::InsufficientFunds); return Err(AccountingError::InsufficientFunds);
} }
@ -102,7 +102,7 @@ impl Accountant {
return Err(AccountingError::InvalidEvent); return Err(AccountingError::InvalidEvent);
} }
if let Event::Transaction { from, to, data, .. } = *event { if let Event::Transaction(Transfer { from, to, data, .. }) = *event {
if !Self::is_deposit(allow_deposits, &from, &to) { if !Self::is_deposit(allow_deposits, &from, &to) {
if let Some(x) = self.balances.get_mut(&from) { if let Some(x) = self.balances.get_mut(&from) {
*x -= data; *x -= data;
@ -129,13 +129,13 @@ impl Accountant {
let from = get_pubkey(keypair); let from = get_pubkey(keypair);
let last_id = self.last_id; let last_id = self.last_id;
let sig = sign_transaction_data(&n, keypair, &to, &last_id); let sig = sign_transaction_data(&n, keypair, &to, &last_id);
let event = Event::Transaction { let event = Event::Transaction(Transfer {
from, from,
to, to,
data: n, data: n,
last_id, last_id,
sig, sig,
}; });
self.process_event(event).map(|_| sig) self.process_event(event).map(|_| sig)
} }

View File

@ -1,6 +1,6 @@
use std::io; use std::io;
use accountant::Accountant; use accountant::Accountant;
use event::{Event, PublicKey, Signature}; use event::{Event, PublicKey, Signature, Transfer};
use log::{Entry, Sha256Hash}; use log::{Entry, Sha256Hash};
use std::net::UdpSocket; use std::net::UdpSocket;
use bincode::{deserialize, serialize}; use bincode::{deserialize, serialize};
@ -50,13 +50,13 @@ impl AccountantSkel {
last_id, last_id,
sig, sig,
} => { } => {
let event = Event::Transaction { let event = Event::Transaction(Transfer {
from, from,
to, to,
data: val, data: val,
last_id, last_id,
sig, sig,
}; });
if let Err(err) = self.acc.process_event(event) { if let Err(err) = self.acc.process_event(event) {
eprintln!("Transfer error: {:?}", err); eprintln!("Transfer error: {:?}", err);
} }

View File

@ -2,7 +2,8 @@ extern crate serde_json;
extern crate silk; extern crate silk;
use silk::accountant_stub::AccountantStub; use silk::accountant_stub::AccountantStub;
use silk::event::{generate_keypair, get_pubkey, sign_transaction_data, verify_event, Event}; use silk::event::{generate_keypair, get_pubkey, sign_transaction_data, verify_event, Event,
Transfer};
use silk::genesis::Genesis; use silk::genesis::Genesis;
use std::time::Instant; use std::time::Instant;
use std::net::UdpSocket; use std::net::UdpSocket;
@ -47,13 +48,13 @@ fn main() {
println!("Verify signatures..."); println!("Verify signatures...");
let now = Instant::now(); let now = Instant::now();
for &(k, s) in &sigs { for &(k, s) in &sigs {
let e = Event::Transaction { let e = Event::Transaction(Transfer {
from: alice_pubkey, from: alice_pubkey,
to: k, to: k,
data: one, data: one,
last_id, last_id,
sig: s, sig: s,
}; });
assert!(verify_event(&e)); assert!(verify_event(&e));
} }
let duration = now.elapsed(); let duration = now.elapsed();

View File

@ -25,6 +25,15 @@ use log::Sha256Hash;
pub type PublicKey = GenericArray<u8, U32>; pub type PublicKey = GenericArray<u8, U32>;
pub type Signature = GenericArray<u8, U64>; pub type Signature = GenericArray<u8, U64>;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Transfer<T> {
pub from: PublicKey,
pub to: PublicKey,
pub data: T,
pub last_id: Sha256Hash,
pub sig: Signature,
}
/// When 'event' is Tick, the event represents a simple clock tick, and exists for the /// When 'event' is Tick, the event represents a simple clock tick, and exists for the
/// sole purpose of improving the performance of event log verification. A tick can /// sole purpose of improving the performance of event log verification. A tick can
/// be generated in 'num_hashes' hashes and verified in 'num_hashes' hashes. By logging /// be generated in 'num_hashes' hashes and verified in 'num_hashes' hashes. By logging
@ -33,24 +42,19 @@ pub type Signature = GenericArray<u8, U64>;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Event<T> { pub enum Event<T> {
Tick, Tick,
Transaction { Transaction(Transfer<T>),
from: PublicKey,
to: PublicKey,
data: T,
last_id: Sha256Hash,
sig: Signature,
},
} }
impl<T> Event<T> { impl<T> Event<T> {
pub fn new_claim(to: PublicKey, data: T, last_id: Sha256Hash, sig: Signature) -> Self { pub fn new_claim(to: PublicKey, data: T, last_id: Sha256Hash, sig: Signature) -> Self {
Event::Transaction { let transfer = Transfer {
from: to, from: to,
to, to,
data, data,
last_id, last_id,
sig, sig,
} };
Event::Transaction(transfer)
} }
} }
@ -103,18 +107,18 @@ pub fn verify_signature(peer_public_key_bytes: &[u8], msg_bytes: &[u8], sig_byte
pub fn get_signature<T>(event: &Event<T>) -> Option<Signature> { pub fn get_signature<T>(event: &Event<T>) -> Option<Signature> {
match *event { match *event {
Event::Tick => None, Event::Tick => None,
Event::Transaction { sig, .. } => Some(sig), Event::Transaction(Transfer { sig, .. }) => Some(sig),
} }
} }
pub fn verify_event<T: Serialize>(event: &Event<T>) -> bool { pub fn verify_event<T: Serialize>(event: &Event<T>) -> bool {
if let Event::Transaction { if let Event::Transaction(Transfer {
from, from,
to, to,
ref data, ref data,
last_id, last_id,
sig, sig,
} = *event }) = *event
{ {
let sign_data = serialize(&(&from, &to, &data, &last_id)).unwrap(); let sign_data = serialize(&(&from, &to, &data, &last_id)).unwrap();
if !verify_signature(&from, &sign_data, &sig) { if !verify_signature(&from, &sign_data, &sig) {

View File

@ -1,6 +1,6 @@
//! A library for generating the chain's genesis block. //! A library for generating the chain's genesis block.
use event::{generate_keypair, get_pubkey, sign_transaction_data, Event, PublicKey}; use event::{generate_keypair, get_pubkey, sign_transaction_data, Event, PublicKey, Transfer};
use log::{create_entries, hash, Entry, Sha256Hash}; use log::{create_entries, hash, Entry, Sha256Hash};
use ring::rand::SystemRandom; use ring::rand::SystemRandom;
use ring::signature::Ed25519KeyPair; use ring::signature::Ed25519KeyPair;
@ -56,13 +56,13 @@ impl Genesis {
let last_id = self.get_seed(); let last_id = self.get_seed();
let from = self.get_pubkey(); let from = self.get_pubkey();
let sig = sign_transaction_data(&data, &self.get_keypair(), to, &last_id); let sig = sign_transaction_data(&data, &self.get_keypair(), to, &last_id);
Event::Transaction { Event::Transaction(Transfer {
from, from,
to: *to, to: *to,
data, data,
last_id, last_id,
sig, sig,
} })
} }
pub fn create_events(&self) -> Vec<Event<i64>> { pub fn create_events(&self) -> Vec<Event<i64>> {
@ -93,7 +93,7 @@ mod tests {
fn test_create_events() { fn test_create_events() {
let mut events = Genesis::new(100, vec![]).create_events().into_iter(); let mut events = Genesis::new(100, vec![]).create_events().into_iter();
assert_eq!(events.next().unwrap(), Event::Tick); assert_eq!(events.next().unwrap(), Event::Tick);
if let Event::Transaction { from, to, .. } = events.next().unwrap() { if let Event::Transaction(Transfer { from, to, .. }) = events.next().unwrap() {
assert_eq!(from, to); assert_eq!(from, to);
} else { } else {
assert!(false); assert!(false);

View File

@ -169,7 +169,7 @@ pub fn next_ticks(start_hash: &Sha256Hash, num_hashes: u64, len: usize) -> Vec<E
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use event::{generate_keypair, get_pubkey, sign_claim_data, sign_transaction_data}; use event::{generate_keypair, get_pubkey, sign_claim_data, sign_transaction_data, Transfer};
#[test] #[test]
fn test_event_verify() { fn test_event_verify() {
@ -277,13 +277,13 @@ mod tests {
let keypair1 = generate_keypair(); let keypair1 = generate_keypair();
let pubkey1 = get_pubkey(&keypair1); let pubkey1 = get_pubkey(&keypair1);
let data = hash(b"hello, world"); let data = hash(b"hello, world");
let event0 = Event::Transaction { let event0 = Event::Transaction(Transfer {
from: get_pubkey(&keypair0), from: get_pubkey(&keypair0),
to: pubkey1, to: pubkey1,
data, data,
last_id: zero, last_id: zero,
sig: sign_transaction_data(&data, &keypair0, &pubkey1, &zero), sig: sign_transaction_data(&data, &keypair0, &pubkey1, &zero),
}; });
let entries = create_entries(&zero, vec![event0]); let entries = create_entries(&zero, vec![event0]);
assert!(verify_slice(&entries, &zero)); assert!(verify_slice(&entries, &zero));
} }
@ -295,13 +295,13 @@ mod tests {
let pubkey1 = get_pubkey(&keypair1); let pubkey1 = get_pubkey(&keypair1);
let data = hash(b"hello, world"); let data = hash(b"hello, world");
let zero = Sha256Hash::default(); let zero = Sha256Hash::default();
let event0 = Event::Transaction { let event0 = Event::Transaction(Transfer {
from: get_pubkey(&keypair0), from: get_pubkey(&keypair0),
to: pubkey1, to: pubkey1,
data: hash(b"goodbye cruel world"), // <-- attack! data: hash(b"goodbye cruel world"), // <-- attack!
last_id: zero, last_id: zero,
sig: sign_transaction_data(&data, &keypair0, &pubkey1, &zero), sig: sign_transaction_data(&data, &keypair0, &pubkey1, &zero),
}; });
let entries = create_entries(&zero, vec![event0]); let entries = create_entries(&zero, vec![event0]);
assert!(!verify_slice(&entries, &zero)); assert!(!verify_slice(&entries, &zero));
} }
@ -314,13 +314,13 @@ mod tests {
let pubkey1 = get_pubkey(&keypair1); let pubkey1 = get_pubkey(&keypair1);
let data = hash(b"hello, world"); let data = hash(b"hello, world");
let zero = Sha256Hash::default(); let zero = Sha256Hash::default();
let event0 = Event::Transaction { let event0 = Event::Transaction(Transfer {
from: get_pubkey(&keypair0), from: get_pubkey(&keypair0),
to: get_pubkey(&thief_keypair), // <-- attack! to: get_pubkey(&thief_keypair), // <-- attack!
data: hash(b"goodbye cruel world"), data: hash(b"goodbye cruel world"),
last_id: zero, last_id: zero,
sig: sign_transaction_data(&data, &keypair0, &pubkey1, &zero), sig: sign_transaction_data(&data, &keypair0, &pubkey1, &zero),
}; });
let entries = create_entries(&zero, vec![event0]); let entries = create_entries(&zero, vec![event0]);
assert!(!verify_slice(&entries, &zero)); assert!(!verify_slice(&entries, &zero));
} }