Skip to content

Commit

Permalink
Merge pull request #30 from garious/simplify
Browse files Browse the repository at this point in the history
Unify Claim and Transaction handling
  • Loading branch information
garious authored Mar 2, 2018
2 parents 662e10c + a148454 commit 8871bb2
Show file tree
Hide file tree
Showing 10 changed files with 287 additions and 241 deletions.
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,18 @@ with by verifying each entry's hash can be generated from the hash in the previo
extern crate silk;

use silk::historian::Historian;
use silk::log::{verify_slice, Entry, Event, Sha256Hash};
use silk::log::{verify_slice, Entry, Sha256Hash};
use silk::event::{generate_keypair, get_pubkey, sign_claim_data, Event};
use std::thread::sleep;
use std::time::Duration;
use std::sync::mpsc::SendError;

fn create_log(hist: &Historian) -> Result<(), SendError<Event>> {
fn create_log(hist: &Historian<Sha256Hash>) -> Result<(), SendError<Event<Sha256Hash>>> {
sleep(Duration::from_millis(15));
let data = Sha256Hash::default();
hist.sender.send(Event::Claim { data })?;
let keypair = generate_keypair();
let event0 = Event::new_claim(get_pubkey(&keypair), data, sign_claim_data(&data, &keypair));
hist.sender.send(event0)?;
sleep(Duration::from_millis(10));
Ok(())
}
Expand All @@ -55,11 +58,10 @@ fn main() {
let hist = Historian::new(&seed, Some(10));
create_log(&hist).expect("send error");
drop(hist.sender);
let entries: Vec<Entry> = hist.receiver.iter().collect();
let entries: Vec<Entry<Sha256Hash>> = hist.receiver.iter().collect();
for entry in &entries {
println!("{:?}", entry);
}

// Proof-of-History: Verify the historian learned about the events
// in the same order they appear in the vector.
assert!(verify_slice(&entries, &seed));
Expand All @@ -70,7 +72,7 @@ Running the program should produce a log similar to:

```rust
Entry { num_hashes: 0, end_hash: [0, ...], event: Tick }
Entry { num_hashes: 2, end_hash: [67, ...], event: Claim { data: [37, ...] } }
Entry { num_hashes: 2, end_hash: [67, ...], event: Transaction { data: [37, ...] } }
Entry { num_hashes: 3, end_hash: [123, ...], event: Tick }
```

Expand Down
137 changes: 69 additions & 68 deletions src/accountant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,22 @@
//! event log to record transactions. Its users can deposit funds and
//! transfer funds to other users.
use log::{Entry, Event, PublicKey, Sha256Hash, Signature};
use log::{Entry, Sha256Hash};
use event::{Event, PublicKey, Signature};
use historian::Historian;
use ring::signature::Ed25519KeyPair;
use std::sync::mpsc::{RecvError, SendError};
use std::sync::mpsc::SendError;
use std::collections::HashMap;
use std::result;

#[derive(Debug, PartialEq, Eq)]
pub enum AccountingError {
InsufficientFunds,
InvalidEvent,
SendError,
}

pub type Result<T> = result::Result<T, AccountingError>;

pub struct Accountant {
pub historian: Historian<u64>,
Expand All @@ -24,71 +35,43 @@ impl Accountant {
}
}

pub fn process_event(self: &mut Self, event: &Event<u64>) {
match *event {
Event::Claim { key, data, .. } => {
if self.balances.contains_key(&key) {
if let Some(x) = self.balances.get_mut(&key) {
*x += data;
}
} else {
self.balances.insert(key, data);
}
}
Event::Transaction { from, to, data, .. } => {
if let Some(x) = self.balances.get_mut(&from) {
*x -= data;
}
if self.balances.contains_key(&to) {
if let Some(x) = self.balances.get_mut(&to) {
*x += data;
}
} else {
self.balances.insert(to, data);
}
}
_ => (),
}
}

pub fn sync(self: &mut Self) -> Vec<Entry<u64>> {
let mut entries = vec![];
while let Ok(entry) = self.historian.receiver.try_recv() {
entries.push(entry);
}
// TODO: Does this cause the historian's channel to get blocked?
//use log::verify_slice_u64;
//println!("accountant: verifying {} entries...", entries.len());
//assert!(verify_slice_u64(&entries, &self.end_hash));
//println!("accountant: Done verifying {} entries.", entries.len());

if let Some(last_entry) = entries.last() {
self.end_hash = last_entry.end_hash;
}
for e in &entries {
self.process_event(&e.event);
}

entries
}

pub fn deposit_signed(
self: &Self,
key: PublicKey,
data: u64,
sig: Signature,
) -> Result<(), SendError<Event<u64>>> {
let event = Event::Claim { key, data, sig };
self.historian.sender.send(event)
pub fn deposit_signed(self: &mut Self, to: PublicKey, data: u64, sig: Signature) -> Result<()> {
let event = Event::new_claim(to, data, sig);
if !self.historian.verify_event(&event) {
return Err(AccountingError::InvalidEvent);
}
if let Err(SendError(_)) = self.historian.sender.send(event) {
return Err(AccountingError::SendError);
}

if self.balances.contains_key(&to) {
if let Some(x) = self.balances.get_mut(&to) {
*x += data;
}
} else {
self.balances.insert(to, data);
}

Ok(())
}

pub fn deposit(
self: &Self,
n: u64,
keypair: &Ed25519KeyPair,
) -> Result<Signature, SendError<Event<u64>>> {
use log::{get_pubkey, sign_serialized};
pub fn deposit(self: &mut Self, n: u64, keypair: &Ed25519KeyPair) -> Result<Signature> {
use event::{get_pubkey, sign_claim_data};
let key = get_pubkey(keypair);
let sig = sign_serialized(&n, keypair);
let sig = sign_claim_data(&n, keypair);
self.deposit_signed(key, n, sig).map(|_| sig)
}

Expand All @@ -98,37 +81,53 @@ impl Accountant {
to: PublicKey,
data: u64,
sig: Signature,
) -> Result<(), SendError<Event<u64>>> {
if self.get_balance(&from).unwrap() < data {
// TODO: Replace the SendError result with a custom one.
println!("Error: Insufficient funds");
return Ok(());
) -> Result<()> {
if self.get_balance(&from).unwrap_or(0) < data {
return Err(AccountingError::InsufficientFunds);
}

let event = Event::Transaction {
from,
from: Some(from),
to,
data,
sig,
};
self.historian.sender.send(event)
if !self.historian.verify_event(&event) {
return Err(AccountingError::InvalidEvent);
}
if let Err(SendError(_)) = self.historian.sender.send(event) {
return Err(AccountingError::SendError);
}

if let Some(x) = self.balances.get_mut(&from) {
*x -= data;
}

if self.balances.contains_key(&to) {
if let Some(x) = self.balances.get_mut(&to) {
*x += data;
}
} else {
self.balances.insert(to, data);
}

Ok(())
}

pub fn transfer(
self: &mut Self,
n: u64,
keypair: &Ed25519KeyPair,
to: PublicKey,
) -> Result<Signature, SendError<Event<u64>>> {
use log::{get_pubkey, sign_transaction_data};

) -> Result<Signature> {
use event::{get_pubkey, sign_transaction_data};
let from = get_pubkey(keypair);
let sig = sign_transaction_data(&n, keypair, &to);
self.transfer_signed(from, to, n, sig).map(|_| sig)
}

pub fn get_balance(self: &mut Self, pubkey: &PublicKey) -> Result<u64, RecvError> {
self.sync();
Ok(*self.balances.get(pubkey).unwrap_or(&0))
pub fn get_balance(self: &Self, pubkey: &PublicKey) -> Option<u64> {
self.balances.get(pubkey).map(|x| *x)
}

pub fn wait_on_signature(self: &mut Self, wait_sig: &Signature) {
Expand All @@ -138,7 +137,6 @@ impl Accountant {
let mut found = false;
while !found {
found = entries.iter().any(|e| match e.event {
Event::Claim { sig, .. } => sig == *wait_sig,
Event::Transaction { sig, .. } => sig == *wait_sig,
_ => false,
});
Expand All @@ -153,7 +151,7 @@ impl Accountant {
#[cfg(test)]
mod tests {
use super::*;
use log::{generate_keypair, get_pubkey};
use event::{generate_keypair, get_pubkey};
use historian::ExitReason;

#[test]
Expand Down Expand Up @@ -192,7 +190,10 @@ mod tests {
acc.wait_on_signature(&sig);

let bob_pubkey = get_pubkey(&bob_keypair);
acc.transfer(10_001, &alice_keypair, bob_pubkey).unwrap();
assert_eq!(
acc.transfer(10_001, &alice_keypair, bob_pubkey),
Err(AccountingError::InsufficientFunds)
);
sleep(Duration::from_millis(30));

let alice_pubkey = get_pubkey(&alice_keypair);
Expand Down
2 changes: 1 addition & 1 deletion src/accountant_skel.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::io;
use accountant::Accountant;
use log::{PublicKey, Signature};
use event::{PublicKey, Signature};
//use serde::Serialize;

pub struct AccountantSkel {
Expand Down
11 changes: 6 additions & 5 deletions src/accountant_stub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use std::net::UdpSocket;
use std::io;
use bincode::{deserialize, serialize};
use log::{PublicKey, Signature};
use event::{PublicKey, Signature};
use ring::signature::Ed25519KeyPair;
use accountant_skel::{Request, Response};

Expand Down Expand Up @@ -34,9 +34,9 @@ impl AccountantStub {
}

pub fn deposit(self: &mut Self, n: u64, keypair: &Ed25519KeyPair) -> io::Result<Signature> {
use log::{get_pubkey, sign_serialized};
use event::{get_pubkey, sign_claim_data};
let key = get_pubkey(keypair);
let sig = sign_serialized(&n, keypair);
let sig = sign_claim_data(&n, keypair);
self.deposit_signed(key, n, sig).map(|_| sig)
}

Expand All @@ -58,7 +58,7 @@ impl AccountantStub {
keypair: &Ed25519KeyPair,
to: PublicKey,
) -> io::Result<Signature> {
use log::{get_pubkey, sign_transaction_data};
use event::{get_pubkey, sign_transaction_data};
let from = get_pubkey(keypair);
let sig = sign_transaction_data(&n, keypair, &to);
self.transfer_signed(from, to, n, sig).map(|_| sig)
Expand Down Expand Up @@ -100,7 +100,8 @@ mod tests {
use accountant_skel::AccountantSkel;
use std::thread::{sleep, spawn};
use std::time::Duration;
use log::{generate_keypair, get_pubkey, Sha256Hash};
use log::Sha256Hash;
use event::{generate_keypair, get_pubkey};

#[test]
fn test_accountant_stub() {
Expand Down
4 changes: 2 additions & 2 deletions src/bin/client-demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ fn main() {
use silk::accountant_stub::AccountantStub;
use std::time::Instant;
use std::net::UdpSocket;
use silk::log::{generate_keypair, get_pubkey};
use silk::event::{generate_keypair, get_pubkey};

let addr = "127.0.0.1:8000";
let send_addr = "127.0.0.1:8001";
let socket = UdpSocket::bind(send_addr).unwrap();
let mut acc = AccountantStub::new(addr, socket);
let alice_keypair = generate_keypair();
let alice_pubkey = get_pubkey(&alice_keypair);
let txs = 10_000;
let txs = 2_000;
println!("Depositing {} units in Alice's account...", txs);
let sig = acc.deposit(txs, &alice_keypair).unwrap();
acc.wait_on_signature(&sig).unwrap();
Expand Down
12 changes: 5 additions & 7 deletions src/bin/demo.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
extern crate silk;

use silk::historian::Historian;
use silk::log::{generate_keypair, get_pubkey, sign_serialized, verify_slice, Entry, Event,
Sha256Hash};
use silk::log::{verify_slice, Entry, Sha256Hash};
use silk::event::{generate_keypair, get_pubkey, sign_claim_data, Event};
use std::thread::sleep;
use std::time::Duration;
use std::sync::mpsc::SendError;
Expand All @@ -11,11 +11,7 @@ fn create_log(hist: &Historian<Sha256Hash>) -> Result<(), SendError<Event<Sha256
sleep(Duration::from_millis(15));
let data = Sha256Hash::default();
let keypair = generate_keypair();
let event0 = Event::Claim {
key: get_pubkey(&keypair),
data,
sig: sign_serialized(&data, &keypair),
};
let event0 = Event::new_claim(get_pubkey(&keypair), data, sign_claim_data(&data, &keypair));
hist.sender.send(event0)?;
sleep(Duration::from_millis(10));
Ok(())
Expand All @@ -30,5 +26,7 @@ fn main() {
for entry in &entries {
println!("{:?}", entry);
}
// Proof-of-History: Verify the historian learned about the events
// in the same order they appear in the vector.
assert!(verify_slice(&entries, &seed));
}
Loading

0 comments on commit 8871bb2

Please sign in to comment.