Give Transaction its own module
This commit is contained in:
@ -3,8 +3,9 @@
|
|||||||
//! 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_transaction, Event, PublicKey, Signature,
|
use event::Event;
|
||||||
Transaction};
|
use transaction::{get_pubkey, sign_transaction_data, verify_transaction, PublicKey, Signature,
|
||||||
|
Transaction};
|
||||||
use genesis::Genesis;
|
use genesis::Genesis;
|
||||||
use historian::{reserve_signature, Historian};
|
use historian::{reserve_signature, Historian};
|
||||||
use ring::signature::Ed25519KeyPair;
|
use ring::signature::Ed25519KeyPair;
|
||||||
@ -157,7 +158,7 @@ impl Accountant {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use event::{generate_keypair, get_pubkey};
|
use transaction::{generate_keypair, get_pubkey};
|
||||||
use logger::ExitReason;
|
use logger::ExitReason;
|
||||||
use genesis::Creator;
|
use genesis::Creator;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use accountant::Accountant;
|
use accountant::Accountant;
|
||||||
use event::{PublicKey, Transaction};
|
use transaction::{PublicKey, Transaction};
|
||||||
use log::{Entry, Sha256Hash};
|
use log::{Entry, Sha256Hash};
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
use bincode::{deserialize, serialize};
|
use bincode::{deserialize, serialize};
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
use std::io;
|
use std::io;
|
||||||
use bincode::{deserialize, serialize};
|
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 log::{Entry, Sha256Hash};
|
||||||
use ring::signature::Ed25519KeyPair;
|
use ring::signature::Ed25519KeyPair;
|
||||||
use accountant_skel::{Request, Response};
|
use accountant_skel::{Request, Response};
|
||||||
|
@ -2,8 +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::{verify_event, Event};
|
||||||
Transaction};
|
use silk::transaction::{generate_keypair, get_pubkey, sign_transaction_data, Transaction};
|
||||||
use silk::genesis::Genesis;
|
use silk::genesis::Genesis;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
|
@ -2,7 +2,8 @@ extern crate silk;
|
|||||||
|
|
||||||
use silk::historian::Historian;
|
use silk::historian::Historian;
|
||||||
use silk::log::{verify_slice, Entry, Sha256Hash};
|
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::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::sync::mpsc::SendError;
|
use std::sync::mpsc::SendError;
|
||||||
|
@ -2,7 +2,7 @@ extern crate serde_json;
|
|||||||
extern crate silk;
|
extern crate silk;
|
||||||
|
|
||||||
use silk::genesis::{Creator, Genesis};
|
use silk::genesis::{Creator, Genesis};
|
||||||
use silk::event::{generate_keypair, get_pubkey};
|
use silk::transaction::{generate_keypair, get_pubkey};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let alice = Creator {
|
let alice = Creator {
|
||||||
|
101
src/event.rs
101
src/event.rs
@ -1,38 +1,9 @@
|
|||||||
//! The `event` crate provides the data structures for log events.
|
//! The `event` crate provides the data structures for log events.
|
||||||
|
|
||||||
use generic_array::GenericArray;
|
use transaction::{verify_transaction, PublicKey, Signature, Transaction};
|
||||||
use generic_array::typenum::{U32, U64};
|
|
||||||
use ring::signature::Ed25519KeyPair;
|
|
||||||
use ring::{rand, signature};
|
|
||||||
use untrusted;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use bincode::serialize;
|
|
||||||
use log::Sha256Hash;
|
use log::Sha256Hash;
|
||||||
|
|
||||||
pub type PublicKey = GenericArray<u8, U32>;
|
|
||||||
pub type Signature = GenericArray<u8, U64>;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
|
||||||
pub struct Transaction<T> {
|
|
||||||
pub from: PublicKey,
|
|
||||||
pub to: PublicKey,
|
|
||||||
pub data: T,
|
|
||||||
pub last_id: Sha256Hash,
|
|
||||||
pub sig: Signature,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Transaction<T> {
|
|
||||||
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
|
/// 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
|
||||||
@ -50,52 +21,6 @@ impl<T> Event<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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<T: Serialize>(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<T: Serialize>(
|
|
||||||
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<T: Serialize>(
|
|
||||||
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<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,
|
||||||
@ -109,27 +34,3 @@ pub fn verify_event<T: Serialize>(event: &Event<T>) -> bool {
|
|||||||
Event::Transaction(ref tr) => verify_transaction(tr),
|
Event::Transaction(ref tr) => verify_transaction(tr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_transaction<T: Serialize>(tr: &Transaction<T>) -> 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<u8> = deserialize(&buf).unwrap();
|
|
||||||
assert_eq!(claim1, claim0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! 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, Transaction};
|
use event::Event;
|
||||||
|
use transaction::{generate_keypair, get_pubkey, sign_transaction_data, PublicKey, Transaction};
|
||||||
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;
|
||||||
|
@ -7,7 +7,8 @@ use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
|||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use log::{hash, Entry, Sha256Hash};
|
use log::{hash, Entry, Sha256Hash};
|
||||||
use logger::{ExitReason, Logger};
|
use logger::{ExitReason, Logger};
|
||||||
use event::{Event, Signature};
|
use transaction::Signature;
|
||||||
|
use event::Event;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
@ -68,6 +69,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
use event::*;
|
use event::*;
|
||||||
|
use transaction::*;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
pub mod log;
|
pub mod log;
|
||||||
pub mod logger;
|
pub mod logger;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
|
pub mod transaction;
|
||||||
pub mod genesis;
|
pub mod genesis;
|
||||||
pub mod historian;
|
pub mod historian;
|
||||||
pub mod accountant;
|
pub mod accountant;
|
||||||
|
@ -169,7 +169,8 @@ 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, Transaction};
|
use transaction::{generate_keypair, get_pubkey, sign_claim_data, sign_transaction_data,
|
||||||
|
Transaction};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_event_verify() {
|
fn test_event_verify() {
|
||||||
|
@ -80,6 +80,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
use event::*;
|
use event::*;
|
||||||
|
use transaction::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bad_event_signature() {
|
fn test_bad_event_signature() {
|
||||||
|
104
src/transaction.rs
Normal file
104
src/transaction.rs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
//! The `transaction` crate provides functionality for creating log transactions.
|
||||||
|
|
||||||
|
use generic_array::GenericArray;
|
||||||
|
use generic_array::typenum::{U32, U64};
|
||||||
|
use ring::signature::Ed25519KeyPair;
|
||||||
|
use ring::{rand, signature};
|
||||||
|
use untrusted;
|
||||||
|
use serde::Serialize;
|
||||||
|
use bincode::serialize;
|
||||||
|
use log::Sha256Hash;
|
||||||
|
|
||||||
|
pub type PublicKey = GenericArray<u8, U32>;
|
||||||
|
pub type Signature = GenericArray<u8, U64>;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
|
pub struct Transaction<T> {
|
||||||
|
pub from: PublicKey,
|
||||||
|
pub to: PublicKey,
|
||||||
|
pub data: T,
|
||||||
|
pub last_id: Sha256Hash,
|
||||||
|
pub sig: Signature,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Transaction<T> {
|
||||||
|
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<T: Serialize>(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<T: Serialize>(
|
||||||
|
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<T: Serialize>(
|
||||||
|
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<T: Serialize>(tr: &Transaction<T>) -> 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<u8> = deserialize(&buf).unwrap();
|
||||||
|
assert_eq!(claim1, claim0);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user