Move Transaction data into its own struct
This will allow us to add addition transfer types to the log.
This commit is contained in:
parent
7d9af5a937
commit
6543497c17
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
28
src/event.rs
28
src/event.rs
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
14
src/log.rs
14
src/log.rs
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue