From 4fcd9e3bd67c3954a901ce789fcf15e473c4338a Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 6 Mar 2018 12:18:17 -0700 Subject: [PATCH] Give Transaction its own module --- src/accountant.rs | 7 ++- src/accountant_skel.rs | 2 +- src/accountant_stub.rs | 3 +- src/bin/client-demo.rs | 4 +- src/bin/demo.rs | 3 +- src/bin/genesis-file-demo.rs | 2 +- src/event.rs | 101 +--------------------------------- src/genesis.rs | 3 +- src/historian.rs | 4 +- src/lib.rs | 1 + src/log.rs | 3 +- src/logger.rs | 1 + src/transaction.rs | 104 +++++++++++++++++++++++++++++++++++ 13 files changed, 126 insertions(+), 112 deletions(-) create mode 100644 src/transaction.rs diff --git a/src/accountant.rs b/src/accountant.rs index 5645a9271e..a36243e026 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -3,8 +3,9 @@ //! transfer funds to other users. use log::{Entry, Sha256Hash}; -use event::{get_pubkey, sign_transaction_data, verify_transaction, Event, PublicKey, Signature, - Transaction}; +use event::Event; +use transaction::{get_pubkey, sign_transaction_data, verify_transaction, PublicKey, Signature, + Transaction}; use genesis::Genesis; use historian::{reserve_signature, Historian}; use ring::signature::Ed25519KeyPair; @@ -157,7 +158,7 @@ impl Accountant { #[cfg(test)] mod tests { use super::*; - use event::{generate_keypair, get_pubkey}; + use transaction::{generate_keypair, get_pubkey}; use logger::ExitReason; use genesis::Creator; diff --git a/src/accountant_skel.rs b/src/accountant_skel.rs index 262fe2cba8..be00c76205 100644 --- a/src/accountant_skel.rs +++ b/src/accountant_skel.rs @@ -1,6 +1,6 @@ use std::io; use accountant::Accountant; -use event::{PublicKey, Transaction}; +use transaction::{PublicKey, Transaction}; use log::{Entry, Sha256Hash}; use std::net::UdpSocket; use bincode::{deserialize, serialize}; diff --git a/src/accountant_stub.rs b/src/accountant_stub.rs index 631ff5440f..fa46d442b8 100644 --- a/src/accountant_stub.rs +++ b/src/accountant_stub.rs @@ -5,7 +5,8 @@ use std::net::UdpSocket; use std::io; use bincode::{deserialize, serialize}; -use event::{get_pubkey, get_signature, sign_transaction_data, PublicKey, Signature, Transaction}; +use event::get_signature; +use transaction::{get_pubkey, sign_transaction_data, PublicKey, Signature, Transaction}; use log::{Entry, Sha256Hash}; use ring::signature::Ed25519KeyPair; use accountant_skel::{Request, Response}; diff --git a/src/bin/client-demo.rs b/src/bin/client-demo.rs index 2f518e8cb4..0c3ebe519b 100644 --- a/src/bin/client-demo.rs +++ b/src/bin/client-demo.rs @@ -2,8 +2,8 @@ extern crate serde_json; extern crate silk; use silk::accountant_stub::AccountantStub; -use silk::event::{generate_keypair, get_pubkey, sign_transaction_data, verify_event, Event, - Transaction}; +use silk::event::{verify_event, Event}; +use silk::transaction::{generate_keypair, get_pubkey, sign_transaction_data, Transaction}; use silk::genesis::Genesis; use std::time::Instant; use std::net::UdpSocket; diff --git a/src/bin/demo.rs b/src/bin/demo.rs index 4f6967e418..d7a364de8b 100644 --- a/src/bin/demo.rs +++ b/src/bin/demo.rs @@ -2,7 +2,8 @@ extern crate silk; use silk::historian::Historian; use silk::log::{verify_slice, Entry, Sha256Hash}; -use silk::event::{generate_keypair, get_pubkey, sign_claim_data, Event}; +use silk::transaction::{generate_keypair, get_pubkey, sign_claim_data}; +use silk::event::Event; use std::thread::sleep; use std::time::Duration; use std::sync::mpsc::SendError; diff --git a/src/bin/genesis-file-demo.rs b/src/bin/genesis-file-demo.rs index 26a47c5e8b..4c4cbe502a 100644 --- a/src/bin/genesis-file-demo.rs +++ b/src/bin/genesis-file-demo.rs @@ -2,7 +2,7 @@ extern crate serde_json; extern crate silk; use silk::genesis::{Creator, Genesis}; -use silk::event::{generate_keypair, get_pubkey}; +use silk::transaction::{generate_keypair, get_pubkey}; fn main() { let alice = Creator { diff --git a/src/event.rs b/src/event.rs index 98d426be04..88a44c402e 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,38 +1,9 @@ //! The `event` crate provides the data structures for log events. -use generic_array::GenericArray; -use generic_array::typenum::{U32, U64}; -use ring::signature::Ed25519KeyPair; -use ring::{rand, signature}; -use untrusted; +use transaction::{verify_transaction, PublicKey, Signature, Transaction}; use serde::Serialize; -use bincode::serialize; use log::Sha256Hash; -pub type PublicKey = GenericArray; -pub type Signature = GenericArray; - -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] -pub struct Transaction { - pub from: PublicKey, - pub to: PublicKey, - pub data: T, - pub last_id: Sha256Hash, - pub sig: Signature, -} - -impl Transaction { - pub fn new_claim(to: PublicKey, data: T, last_id: Sha256Hash, sig: Signature) -> Self { - Transaction { - from: to, - to, - data, - last_id, - sig, - } - } -} - /// 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 /// be generated in 'num_hashes' hashes and verified in 'num_hashes' hashes. By logging @@ -50,52 +21,6 @@ impl Event { } } -/// Return a new ED25519 keypair -pub fn generate_keypair() -> Ed25519KeyPair { - let rng = rand::SystemRandom::new(); - let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); - signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap() -} - -/// Return the public key for the given keypair -pub fn get_pubkey(keypair: &Ed25519KeyPair) -> PublicKey { - GenericArray::clone_from_slice(keypair.public_key_bytes()) -} - -/// Return a signature for the given data using the private key from the given keypair. -fn sign_serialized(data: &T, keypair: &Ed25519KeyPair) -> Signature { - let serialized = serialize(data).unwrap(); - GenericArray::clone_from_slice(keypair.sign(&serialized).as_ref()) -} - -/// Return a signature for the given transaction data using the private key from the given keypair. -pub fn sign_transaction_data( - data: &T, - keypair: &Ed25519KeyPair, - to: &PublicKey, - last_id: &Sha256Hash, -) -> Signature { - let from = &get_pubkey(keypair); - sign_serialized(&(from, to, data, last_id), keypair) -} - -/// Return a signature for the given data using the private key from the given keypair. -pub fn sign_claim_data( - data: &T, - keypair: &Ed25519KeyPair, - last_id: &Sha256Hash, -) -> Signature { - sign_transaction_data(data, keypair, &get_pubkey(keypair), last_id) -} - -/// Verify a signed message with the given public key. -pub fn verify_signature(peer_public_key_bytes: &[u8], msg_bytes: &[u8], sig_bytes: &[u8]) -> bool { - let peer_public_key = untrusted::Input::from(peer_public_key_bytes); - let msg = untrusted::Input::from(msg_bytes); - let sig = untrusted::Input::from(sig_bytes); - signature::verify(&signature::ED25519, peer_public_key, msg, sig).is_ok() -} - pub fn get_signature(event: &Event) -> Option { match *event { Event::Tick => None, @@ -109,27 +34,3 @@ pub fn verify_event(event: &Event) -> bool { Event::Transaction(ref tr) => verify_transaction(tr), } } - -pub fn verify_transaction(tr: &Transaction) -> bool { - let sign_data = serialize(&(&tr.from, &tr.to, &tr.data, &tr.last_id)).unwrap(); - verify_signature(&tr.from, &sign_data, &tr.sig) -} - -#[cfg(test)] -mod tests { - use super::*; - use bincode::{deserialize, serialize}; - - #[test] - fn test_serialize_claim() { - let claim0 = Event::new_claim( - Default::default(), - 0u8, - Default::default(), - Default::default(), - ); - let buf = serialize(&claim0).unwrap(); - let claim1: Event = deserialize(&buf).unwrap(); - assert_eq!(claim1, claim0); - } -} diff --git a/src/genesis.rs b/src/genesis.rs index d379590b4f..fcc3e321f8 100644 --- a/src/genesis.rs +++ b/src/genesis.rs @@ -1,6 +1,7 @@ //! A library for generating the chain's genesis block. -use event::{generate_keypair, get_pubkey, sign_transaction_data, Event, PublicKey, Transaction}; +use event::Event; +use transaction::{generate_keypair, get_pubkey, sign_transaction_data, PublicKey, Transaction}; use log::{create_entries, hash, Entry, Sha256Hash}; use ring::rand::SystemRandom; use ring::signature::Ed25519KeyPair; diff --git a/src/historian.rs b/src/historian.rs index 7b700e0613..8df3eac77f 100644 --- a/src/historian.rs +++ b/src/historian.rs @@ -7,7 +7,8 @@ use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; use std::time::Instant; use log::{hash, Entry, Sha256Hash}; use logger::{ExitReason, Logger}; -use event::{Event, Signature}; +use transaction::Signature; +use event::Event; use serde::Serialize; use std::fmt::Debug; @@ -68,6 +69,7 @@ mod tests { use super::*; use log::*; use event::*; + use transaction::*; use std::thread::sleep; use std::time::Duration; diff --git a/src/lib.rs b/src/lib.rs index bf65fb2d54..e264f0cd01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ pub mod log; pub mod logger; pub mod event; +pub mod transaction; pub mod genesis; pub mod historian; pub mod accountant; diff --git a/src/log.rs b/src/log.rs index b5af9abf15..d1f17fca99 100644 --- a/src/log.rs +++ b/src/log.rs @@ -169,7 +169,8 @@ pub fn next_ticks(start_hash: &Sha256Hash, num_hashes: u64, len: usize) -> Vec; +pub type Signature = GenericArray; + +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +pub struct Transaction { + pub from: PublicKey, + pub to: PublicKey, + pub data: T, + pub last_id: Sha256Hash, + pub sig: Signature, +} + +impl Transaction { + pub fn new_claim(to: PublicKey, data: T, last_id: Sha256Hash, sig: Signature) -> Self { + Transaction { + from: to, + to, + data, + last_id, + sig, + } + } +} + +/// Return a new ED25519 keypair +pub fn generate_keypair() -> Ed25519KeyPair { + let rng = rand::SystemRandom::new(); + let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); + signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap() +} + +/// Return the public key for the given keypair +pub fn get_pubkey(keypair: &Ed25519KeyPair) -> PublicKey { + GenericArray::clone_from_slice(keypair.public_key_bytes()) +} + +/// Return a signature for the given data using the private key from the given keypair. +fn sign_serialized(data: &T, keypair: &Ed25519KeyPair) -> Signature { + let serialized = serialize(data).unwrap(); + GenericArray::clone_from_slice(keypair.sign(&serialized).as_ref()) +} + +/// Return a signature for the given transaction data using the private key from the given keypair. +pub fn sign_transaction_data( + data: &T, + keypair: &Ed25519KeyPair, + to: &PublicKey, + last_id: &Sha256Hash, +) -> Signature { + let from = &get_pubkey(keypair); + sign_serialized(&(from, to, data, last_id), keypair) +} + +/// Return a signature for the given data using the private key from the given keypair. +pub fn sign_claim_data( + data: &T, + keypair: &Ed25519KeyPair, + last_id: &Sha256Hash, +) -> Signature { + sign_transaction_data(data, keypair, &get_pubkey(keypair), last_id) +} + +/// Verify a signed message with the given public key. +pub fn verify_signature(peer_public_key_bytes: &[u8], msg_bytes: &[u8], sig_bytes: &[u8]) -> bool { + let peer_public_key = untrusted::Input::from(peer_public_key_bytes); + let msg = untrusted::Input::from(msg_bytes); + let sig = untrusted::Input::from(sig_bytes); + signature::verify(&signature::ED25519, peer_public_key, msg, sig).is_ok() +} + +pub fn verify_transaction(tr: &Transaction) -> bool { + let sign_data = serialize(&(&tr.from, &tr.to, &tr.data, &tr.last_id)).unwrap(); + verify_signature(&tr.from, &sign_data, &tr.sig) +} + +#[cfg(test)] +mod tests { + use super::*; + use bincode::{deserialize, serialize}; + + #[test] + fn test_serialize_claim() { + let claim0 = Transaction::new_claim( + Default::default(), + 0u8, + Default::default(), + Default::default(), + ); + let buf = serialize(&claim0).unwrap(); + let claim1: Transaction = deserialize(&buf).unwrap(); + assert_eq!(claim1, claim0); + } +}