Merge pull request #55 from garious/the-mint

More intuitive demo, introducing The Mint
This commit is contained in:
Greg Fitzgerald
2018-03-07 17:18:24 -07:00
committed by GitHub
15 changed files with 153 additions and 135 deletions

View File

@ -12,8 +12,8 @@ authors = [
license = "Apache-2.0" license = "Apache-2.0"
[[bin]] [[bin]]
name = "silk-demo" name = "silk-historian-demo"
path = "src/bin/demo.rs" path = "src/bin/historian-demo.rs"
[[bin]] [[bin]]
name = "silk-client-demo" name = "silk-client-demo"
@ -24,12 +24,16 @@ name = "silk-testnode"
path = "src/bin/testnode.rs" path = "src/bin/testnode.rs"
[[bin]] [[bin]]
name = "silk-genesis-block" name = "silk-genesis"
path = "src/bin/genesis-block.rs" path = "src/bin/genesis.rs"
[[bin]] [[bin]]
name = "silk-genesis-file-demo" name = "silk-genesis-demo"
path = "src/bin/genesis-file-demo.rs" path = "src/bin/genesis-demo.rs"
[[bin]]
name = "silk-mint"
path = "src/bin/mint.rs"
[badges] [badges]
codecov = { repository = "loomprotocol/silk", branch = "master", service = "github" } codecov = { repository = "loomprotocol/silk", branch = "master", service = "github" }

View File

@ -32,27 +32,27 @@ First, build the demo executables in release mode (optimized for performance):
``` ```
The testnode server is initialized with a transaction log from stdin and The testnode server is initialized with a transaction log from stdin and
generates a log on stdout. To create the input log, we'll need to create generates new log entries on stdout. To create the input log, we'll need
a *genesis* configuration file and then generate a log from it. It's done to create *the mint* and use it to generate a *genesis log*. It's done in
in two steps here because the demo-genesis.json file contains a private two steps because the mint.json file contains a private key that will be
key that will be used later in this demo. used later in this demo.
```bash ```bash
$ ./silk-genesis-file-demo > demo-genesis.json $ echo 500 | ./silk-mint > mint.json
$ cat demo-genesis.json | ./silk-genesis-block > demo-genesis.log $ cat mint.json | ./silk-genesis > genesis.log
``` ```
Now you can start the server: Now you can start the server:
```bash ```bash
$ cat demo-genesis.log | ./silk-testnode > demo-entries0.log $ cat genesis.log | ./silk-testnode > transactions0.log
``` ```
Then, in a separate shell, let's execute some transactions. Note we pass in Then, in a separate shell, let's execute some transactions. Note we pass in
the JSON configuration file here, not the genesis log. the JSON configuration file here, not the genesis log.
```bash ```bash
$ cat demo-genesis.json | ./silk-client-demo $ cat mint.json | ./silk-client-demo
``` ```
Now kill the server with Ctrl-C, and take a look at the transaction log. You should Now kill the server with Ctrl-C, and take a look at the transaction log. You should
@ -68,7 +68,7 @@ Now restart the server from where we left off. Pass it both the genesis log, and
the transaction log. the transaction log.
```bash ```bash
$ cat demo-genesis.log demo-entries0.log | ./silk-testnode > demo-entries1.log $ cat genesis.log transactions0.log | ./silk-testnode > transactions1.log
``` ```
Lastly, run the client demo again, and verify that all funds were spent in the Lastly, run the client demo again, and verify that all funds were spent in the

View File

@ -7,7 +7,7 @@ use entry::Entry;
use event::Event; use event::Event;
use transaction::Transaction; use transaction::Transaction;
use signature::{KeyPair, PublicKey, Signature}; use signature::{KeyPair, PublicKey, Signature};
use genesis::Genesis; use mint::Mint;
use historian::{reserve_signature, Historian}; use historian::{reserve_signature, Historian};
use std::sync::mpsc::SendError; use std::sync::mpsc::SendError;
use std::collections::HashMap; use std::collections::HashMap;
@ -62,8 +62,8 @@ impl Accountant {
acc acc
} }
pub fn new(gen: &Genesis, ms_per_tick: Option<u64>) -> Self { pub fn new(mint: &Mint, ms_per_tick: Option<u64>) -> Self {
Self::new_from_entries(gen.create_entries(), ms_per_tick) Self::new_from_entries(mint.create_entries(), ms_per_tick)
} }
pub fn sync(self: &mut Self) -> Hash { pub fn sync(self: &mut Self) -> Hash {
@ -146,19 +146,18 @@ impl Accountant {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use signature::{generate_keypair, get_pubkey}; use signature::KeyPairUtil;
use logger::ExitReason; use logger::ExitReason;
#[test] #[test]
fn test_accountant() { fn test_accountant() {
let alice = Genesis::new(10_000); let alice = Mint::new(10_000);
let bob_pubkey = get_pubkey(&generate_keypair()); let bob_pubkey = KeyPair::new().pubkey();
let mut acc = Accountant::new(&alice, Some(2)); let mut acc = Accountant::new(&alice, Some(2));
acc.transfer(1_000, &alice.get_keypair(), bob_pubkey) acc.transfer(1_000, &alice.keypair(), bob_pubkey).unwrap();
.unwrap();
assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_000); assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_000);
acc.transfer(500, &alice.get_keypair(), bob_pubkey).unwrap(); acc.transfer(500, &alice.keypair(), bob_pubkey).unwrap();
assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_500); assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_500);
drop(acc.historian.sender); drop(acc.historian.sender);
@ -170,17 +169,16 @@ mod tests {
#[test] #[test]
fn test_invalid_transfer() { fn test_invalid_transfer() {
let alice = Genesis::new(11_000); let alice = Mint::new(11_000);
let mut acc = Accountant::new(&alice, Some(2)); let mut acc = Accountant::new(&alice, Some(2));
let bob_pubkey = get_pubkey(&generate_keypair()); let bob_pubkey = KeyPair::new().pubkey();
acc.transfer(1_000, &alice.get_keypair(), bob_pubkey) acc.transfer(1_000, &alice.keypair(), bob_pubkey).unwrap();
.unwrap();
assert_eq!( assert_eq!(
acc.transfer(10_001, &alice.get_keypair(), bob_pubkey), acc.transfer(10_001, &alice.keypair(), bob_pubkey),
Err(AccountingError::InsufficientFunds) Err(AccountingError::InsufficientFunds)
); );
let alice_pubkey = get_pubkey(&alice.get_keypair()); let alice_pubkey = alice.keypair().pubkey();
assert_eq!(acc.get_balance(&alice_pubkey).unwrap(), 10_000); assert_eq!(acc.get_balance(&alice_pubkey).unwrap(), 10_000);
assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_000); assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_000);
@ -193,10 +191,10 @@ mod tests {
#[test] #[test]
fn test_transfer_to_newb() { fn test_transfer_to_newb() {
let alice = Genesis::new(10_000); let alice = Mint::new(10_000);
let mut acc = Accountant::new(&alice, Some(2)); let mut acc = Accountant::new(&alice, Some(2));
let alice_keypair = alice.get_keypair(); let alice_keypair = alice.keypair();
let bob_pubkey = get_pubkey(&generate_keypair()); let bob_pubkey = KeyPair::new().pubkey();
acc.transfer(500, &alice_keypair, bob_pubkey).unwrap(); acc.transfer(500, &alice_keypair, bob_pubkey).unwrap();
assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 500); assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 500);

View File

@ -115,23 +115,23 @@ mod tests {
use accountant_skel::AccountantSkel; use accountant_skel::AccountantSkel;
use std::thread::{sleep, spawn}; use std::thread::{sleep, spawn};
use std::time::Duration; use std::time::Duration;
use genesis::Genesis; use mint::Mint;
use signature::{generate_keypair, get_pubkey}; use signature::{KeyPair, KeyPairUtil};
#[test] #[test]
fn test_accountant_stub() { fn test_accountant_stub() {
let addr = "127.0.0.1:9000"; let addr = "127.0.0.1:9000";
let send_addr = "127.0.0.1:9001"; let send_addr = "127.0.0.1:9001";
let alice = Genesis::new(10_000); let alice = Mint::new(10_000);
let acc = Accountant::new(&alice, None); let acc = Accountant::new(&alice, None);
let bob_pubkey = get_pubkey(&generate_keypair()); let bob_pubkey = KeyPair::new().pubkey();
spawn(move || AccountantSkel::new(acc).serve(addr).unwrap()); spawn(move || AccountantSkel::new(acc).serve(addr).unwrap());
sleep(Duration::from_millis(30)); sleep(Duration::from_millis(30));
let socket = UdpSocket::bind(send_addr).unwrap(); let socket = UdpSocket::bind(send_addr).unwrap();
let mut acc = AccountantStub::new(addr, socket); let mut acc = AccountantStub::new(addr, socket);
let last_id = acc.get_last_id().unwrap(); let last_id = acc.get_last_id().unwrap();
let sig = acc.transfer(500, &alice.get_keypair(), bob_pubkey, &last_id) let sig = acc.transfer(500, &alice.keypair(), bob_pubkey, &last_id)
.unwrap(); .unwrap();
acc.wait_on_signature(&sig).unwrap(); acc.wait_on_signature(&sig).unwrap();
assert_eq!(acc.get_balance(&bob_pubkey).unwrap().unwrap(), 500); assert_eq!(acc.get_balance(&bob_pubkey).unwrap().unwrap(), 500);

View File

@ -2,9 +2,9 @@ extern crate serde_json;
extern crate silk; extern crate silk;
use silk::accountant_stub::AccountantStub; use silk::accountant_stub::AccountantStub;
use silk::signature::{generate_keypair, get_pubkey}; use silk::signature::{KeyPair, KeyPairUtil};
use silk::transaction::Transaction; use silk::transaction::Transaction;
use silk::genesis::Genesis; use silk::mint::Mint;
use std::time::Instant; use std::time::Instant;
use std::net::UdpSocket; use std::net::UdpSocket;
use std::io::stdin; use std::io::stdin;
@ -13,23 +13,23 @@ fn main() {
let addr = "127.0.0.1:8000"; let addr = "127.0.0.1:8000";
let send_addr = "127.0.0.1:8001"; let send_addr = "127.0.0.1:8001";
let gen: Genesis = serde_json::from_reader(stdin()).unwrap(); let mint: Mint = serde_json::from_reader(stdin()).unwrap();
let alice_keypair = gen.get_keypair(); let mint_keypair = mint.keypair();
let alice_pubkey = gen.get_pubkey(); let mint_pubkey = mint.pubkey();
let socket = UdpSocket::bind(send_addr).unwrap(); let socket = UdpSocket::bind(send_addr).unwrap();
let mut acc = AccountantStub::new(addr, socket); let mut acc = AccountantStub::new(addr, socket);
let last_id = acc.get_last_id().unwrap(); let last_id = acc.get_last_id().unwrap();
let txs = acc.get_balance(&alice_pubkey).unwrap().unwrap(); let txs = acc.get_balance(&mint_pubkey).unwrap().unwrap();
println!("Alice's Initial Balance {}", txs); println!("Mint's Initial Balance {}", txs);
println!("Signing transactions..."); println!("Signing transactions...");
let now = Instant::now(); let now = Instant::now();
let transactions: Vec<_> = (0..txs) let transactions: Vec<_> = (0..txs)
.map(|_| { .map(|_| {
let rando_pubkey = get_pubkey(&generate_keypair()); let rando_pubkey = KeyPair::new().pubkey();
Transaction::new(&alice_keypair, rando_pubkey, 1, last_id) Transaction::new(&mint_keypair, rando_pubkey, 1, last_id)
}) })
.collect(); .collect();
let duration = now.elapsed(); let duration = now.elapsed();
@ -71,7 +71,7 @@ fn main() {
let ns = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64; let ns = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
let tps = (txs * 1_000_000_000) as f64 / ns as f64; let tps = (txs * 1_000_000_000) as f64 / ns as f64;
println!("Done. {} tps!", tps); println!("Done. {} tps!", tps);
let val = acc.get_balance(&alice_pubkey).unwrap().unwrap(); let val = acc.get_balance(&mint_pubkey).unwrap().unwrap();
println!("Alice's Final Balance {}", val); println!("Mint's Final Balance {}", val);
assert_eq!(val, 0); assert_eq!(val, 0);
} }

View File

@ -1,18 +0,0 @@
//! A command-line executable for generating the chain's genesis block.
extern crate ring;
extern crate serde_json;
extern crate silk;
use silk::genesis::Genesis;
use silk::log::verify_slice;
use std::io::stdin;
fn main() {
let gen: Genesis = serde_json::from_reader(stdin()).unwrap();
let entries = gen.create_entries();
verify_slice(&entries, &entries[0].id);
for x in entries {
println!("{}", serde_json::to_string(&x).unwrap());
}
}

View File

@ -1,30 +1,30 @@
extern crate serde_json; extern crate serde_json;
extern crate silk; extern crate silk;
use silk::genesis::Genesis; use silk::mint::Mint;
use silk::event::Event; use silk::event::Event;
use silk::transaction::Transaction; use silk::transaction::Transaction;
use silk::log::create_entries; use silk::log::create_entries;
use silk::signature::{generate_keypair, get_pubkey, KeyPair, PublicKey}; use silk::signature::{KeyPair, KeyPairUtil, PublicKey};
use silk::hash::Hash; use silk::hash::Hash;
use std::io::stdin;
fn transfer(from: &KeyPair, (to, tokens): (PublicKey, i64), last_id: Hash) -> Event { fn transfer(from: &KeyPair, (to, tokens): (PublicKey, i64), last_id: Hash) -> Event {
Event::Transaction(Transaction::new(&from, to, tokens, last_id)) Event::Transaction(Transaction::new(&from, to, tokens, last_id))
} }
fn main() { fn main() {
let alice = (get_pubkey(&generate_keypair()), 200); let alice = (KeyPair::new().pubkey(), 200);
let bob = (get_pubkey(&generate_keypair()), 100); let bob = (KeyPair::new().pubkey(), 100);
let gen = Genesis::new(500); let mint: Mint = serde_json::from_reader(stdin()).unwrap();
let from = gen.get_keypair(); let from = mint.keypair();
let seed = gen.get_seed(); let seed = mint.seed();
let mut events = gen.create_events(); let mut events = mint.create_events();
events.push(transfer(&from, alice, seed)); events.push(transfer(&from, alice, seed));
events.push(transfer(&from, bob, seed)); events.push(transfer(&from, bob, seed));
let entries = create_entries(&seed, events); for entry in create_entries(&seed, events) {
for entry in entries {
println!("{}", serde_json::to_string(&entry).unwrap()); println!("{}", serde_json::to_string(&entry).unwrap());
} }
} }

14
src/bin/genesis.rs Normal file
View File

@ -0,0 +1,14 @@
//! A command-line executable for generating the chain's genesis block.
extern crate serde_json;
extern crate silk;
use silk::mint::Mint;
use std::io::stdin;
fn main() {
let mint: Mint = serde_json::from_reader(stdin()).unwrap();
for x in mint.create_entries() {
println!("{}", serde_json::to_string(&x).unwrap());
}
}

View File

@ -4,7 +4,7 @@ use silk::historian::Historian;
use silk::hash::Hash; use silk::hash::Hash;
use silk::entry::Entry; use silk::entry::Entry;
use silk::log::verify_slice; use silk::log::verify_slice;
use silk::signature::{generate_keypair, get_pubkey}; use silk::signature::{KeyPair, KeyPairUtil};
use silk::transaction::Transaction; use silk::transaction::Transaction;
use silk::event::Event; use silk::event::Event;
use std::thread::sleep; use std::thread::sleep;
@ -13,8 +13,8 @@ use std::sync::mpsc::SendError;
fn create_log(hist: &Historian, seed: &Hash) -> Result<(), SendError<Event>> { fn create_log(hist: &Historian, seed: &Hash) -> Result<(), SendError<Event>> {
sleep(Duration::from_millis(15)); sleep(Duration::from_millis(15));
let keypair = generate_keypair(); let keypair = KeyPair::new();
let tr = Transaction::new(&keypair, get_pubkey(&keypair), 42, *seed); let tr = Transaction::new(&keypair, keypair.pubkey(), 42, *seed);
let event0 = Event::Transaction(tr); let event0 = Event::Transaction(tr);
hist.sender.send(event0)?; hist.sender.send(event0)?;
sleep(Duration::from_millis(10)); sleep(Duration::from_millis(10));

15
src/bin/mint.rs Normal file
View File

@ -0,0 +1,15 @@
extern crate serde_json;
extern crate silk;
use silk::mint::Mint;
use std::io;
fn main() {
let mut input_text = String::new();
io::stdin().read_line(&mut input_text).unwrap();
let trimmed = input_text.trim();
let tokens = trimmed.parse::<i64>().unwrap();
let mint = Mint::new(tokens);
println!("{}", serde_json::to_string(&mint).unwrap());
}

View File

@ -5,7 +5,7 @@ pub mod transaction;
pub mod event; pub mod event;
pub mod entry; pub mod entry;
pub mod log; pub mod log;
pub mod genesis; pub mod mint;
pub mod logger; pub mod logger;
pub mod historian; pub mod historian;
pub mod accountant; pub mod accountant;

View File

@ -48,7 +48,7 @@ pub fn next_ticks(start_hash: &Hash, num_hashes: u64, len: usize) -> Vec<Entry>
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use signature::{generate_keypair, get_pubkey}; use signature::{KeyPair, KeyPairUtil};
use transaction::Transaction; use transaction::Transaction;
use hash::hash; use hash::hash;
@ -71,9 +71,9 @@ mod tests {
let zero = Hash::default(); let zero = Hash::default();
// First, verify entries // First, verify entries
let keypair = generate_keypair(); let keypair = KeyPair::new();
let tr0 = Transaction::new(&keypair, get_pubkey(&keypair), 0, zero); let tr0 = Transaction::new(&keypair, keypair.pubkey(), 0, zero);
let tr1 = Transaction::new(&keypair, get_pubkey(&keypair), 1, zero); let tr1 = Transaction::new(&keypair, keypair.pubkey(), 1, zero);
let events = vec![Event::Transaction(tr0), Event::Transaction(tr1)]; let events = vec![Event::Transaction(tr0), Event::Transaction(tr1)];
let mut entries = create_entries(&zero, events); let mut entries = create_entries(&zero, events);
assert!(verify_slice(&entries, &zero)); assert!(verify_slice(&entries, &zero));

View File

@ -2,51 +2,45 @@
use event::Event; use event::Event;
use transaction::Transaction; use transaction::Transaction;
use signature::{get_pubkey, PublicKey}; use signature::{KeyPair, KeyPairUtil, PublicKey};
use entry::Entry; use entry::Entry;
use log::create_entries; use log::create_entries;
use hash::{hash, Hash}; use hash::{hash, Hash};
use ring::rand::SystemRandom; use ring::rand::SystemRandom;
use ring::signature::Ed25519KeyPair;
use untrusted::Input; use untrusted::Input;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct Genesis { pub struct Mint {
pub pkcs8: Vec<u8>, pub pkcs8: Vec<u8>,
pub tokens: i64, pub tokens: i64,
} }
impl Genesis { impl Mint {
pub fn new(tokens: i64) -> Self { pub fn new(tokens: i64) -> Self {
let rnd = SystemRandom::new(); let rnd = SystemRandom::new();
let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rnd).unwrap().to_vec(); let pkcs8 = KeyPair::generate_pkcs8(&rnd).unwrap().to_vec();
Genesis { pkcs8, tokens } Mint { pkcs8, tokens }
} }
pub fn get_seed(&self) -> Hash { pub fn seed(&self) -> Hash {
hash(&self.pkcs8) hash(&self.pkcs8)
} }
pub fn get_keypair(&self) -> Ed25519KeyPair { pub fn keypair(&self) -> KeyPair {
Ed25519KeyPair::from_pkcs8(Input::from(&self.pkcs8)).unwrap() KeyPair::from_pkcs8(Input::from(&self.pkcs8)).unwrap()
} }
pub fn get_pubkey(&self) -> PublicKey { pub fn pubkey(&self) -> PublicKey {
get_pubkey(&self.get_keypair()) self.keypair().pubkey()
} }
pub fn create_events(&self) -> Vec<Event> { pub fn create_events(&self) -> Vec<Event> {
let tr = Transaction::new( let tr = Transaction::new(&self.keypair(), self.pubkey(), self.tokens, self.seed());
&self.get_keypair(),
self.get_pubkey(),
self.tokens,
self.get_seed(),
);
vec![Event::Tick, Event::Transaction(tr)] vec![Event::Tick, Event::Transaction(tr)]
} }
pub fn create_entries(&self) -> Vec<Entry> { pub fn create_entries(&self) -> Vec<Entry> {
create_entries(&self.get_seed(), self.create_events()) create_entries(&self.seed(), self.create_events())
} }
} }
@ -57,7 +51,7 @@ mod tests {
#[test] #[test]
fn test_create_events() { fn test_create_events() {
let mut events = Genesis::new(100).create_events().into_iter(); let mut events = Mint::new(100).create_events().into_iter();
assert_eq!(events.next().unwrap(), Event::Tick); assert_eq!(events.next().unwrap(), Event::Tick);
if let Event::Transaction(tr) = events.next().unwrap() { if let Event::Transaction(tr) = events.next().unwrap() {
assert_eq!(tr.from, tr.to); assert_eq!(tr.from, tr.to);
@ -69,7 +63,7 @@ mod tests {
#[test] #[test]
fn test_verify_entries() { fn test_verify_entries() {
let entries = Genesis::new(100).create_entries(); let entries = Mint::new(100).create_entries();
assert!(verify_slice(&entries, &entries[0].id)); assert!(verify_slice(&entries, &entries[0].id));
} }
} }

View File

@ -10,22 +10,34 @@ pub type KeyPair = Ed25519KeyPair;
pub type PublicKey = GenericArray<u8, U32>; pub type PublicKey = GenericArray<u8, U32>;
pub type Signature = GenericArray<u8, U64>; pub type Signature = GenericArray<u8, U64>;
/// Return a new ED25519 keypair pub trait KeyPairUtil {
pub fn generate_keypair() -> KeyPair { fn new() -> Self;
let rng = rand::SystemRandom::new(); fn pubkey(&self) -> PublicKey;
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 impl KeyPairUtil for Ed25519KeyPair {
pub fn get_pubkey(keypair: &KeyPair) -> PublicKey { /// Return a new ED25519 keypair
GenericArray::clone_from_slice(keypair.public_key_bytes()) fn new() -> Self {
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
fn pubkey(&self) -> PublicKey {
GenericArray::clone_from_slice(self.public_key_bytes())
}
} }
/// Verify a signed message with the given public key. pub trait SignatureUtil {
pub fn verify_signature(peer_public_key_bytes: &[u8], msg_bytes: &[u8], sig_bytes: &[u8]) -> bool { fn verify(&self, peer_public_key_bytes: &[u8], msg_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); impl SignatureUtil for GenericArray<u8, U64> {
signature::verify(&signature::ED25519, peer_public_key, msg, sig).is_ok() fn verify(&self, peer_public_key_bytes: &[u8], msg_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(self);
signature::verify(&signature::ED25519, peer_public_key, msg, sig).is_ok()
}
} }

View File

@ -1,6 +1,6 @@
//! The `transaction` crate provides functionality for creating log transactions. //! The `transaction` crate provides functionality for creating log transactions.
use signature::{get_pubkey, verify_signature, KeyPair, PublicKey, Signature}; use signature::{KeyPair, KeyPairUtil, PublicKey, Signature, SignatureUtil};
use serde::Serialize; use serde::Serialize;
use bincode::serialize; use bincode::serialize;
use hash::Hash; use hash::Hash;
@ -17,7 +17,7 @@ pub struct Transaction<T> {
impl<T: Serialize> Transaction<T> { impl<T: Serialize> Transaction<T> {
pub fn new(from_keypair: &KeyPair, to: PublicKey, asset: T, last_id: Hash) -> Self { pub fn new(from_keypair: &KeyPair, to: PublicKey, asset: T, last_id: Hash) -> Self {
let mut tr = Transaction { let mut tr = Transaction {
from: get_pubkey(&from_keypair), from: from_keypair.pubkey(),
to, to,
asset, asset,
last_id, last_id,
@ -37,7 +37,7 @@ impl<T: Serialize> Transaction<T> {
} }
pub fn verify(&self) -> bool { pub fn verify(&self) -> bool {
verify_signature(&self.from, &self.get_sign_data(), &self.sig) self.sig.verify(&self.from, &self.get_sign_data())
} }
} }
@ -45,24 +45,23 @@ impl<T: Serialize> Transaction<T> {
mod tests { mod tests {
use super::*; use super::*;
use bincode::{deserialize, serialize}; use bincode::{deserialize, serialize};
use signature::*;
use hash::hash; use hash::hash;
#[test] #[test]
fn test_claim() { fn test_claim() {
let keypair = generate_keypair(); let keypair = KeyPair::new();
let asset = hash(b"hello, world"); let asset = hash(b"hello, world");
let zero = Hash::default(); let zero = Hash::default();
let tr0 = Transaction::new(&keypair, get_pubkey(&keypair), asset, zero); let tr0 = Transaction::new(&keypair, keypair.pubkey(), asset, zero);
assert!(tr0.verify()); assert!(tr0.verify());
} }
#[test] #[test]
fn test_transfer() { fn test_transfer() {
let zero = Hash::default(); let zero = Hash::default();
let keypair0 = generate_keypair(); let keypair0 = KeyPair::new();
let keypair1 = generate_keypair(); let keypair1 = KeyPair::new();
let pubkey1 = get_pubkey(&keypair1); let pubkey1 = keypair1.pubkey();
let asset = hash(b"hello, world"); let asset = hash(b"hello, world");
let tr0 = Transaction::new(&keypair0, pubkey1, asset, zero); let tr0 = Transaction::new(&keypair0, pubkey1, asset, zero);
assert!(tr0.verify()); assert!(tr0.verify());
@ -85,8 +84,8 @@ mod tests {
#[test] #[test]
fn test_bad_event_signature() { fn test_bad_event_signature() {
let zero = Hash::default(); let zero = Hash::default();
let keypair = generate_keypair(); let keypair = KeyPair::new();
let pubkey = get_pubkey(&keypair); let pubkey = keypair.pubkey();
let mut tr = Transaction::new(&keypair, pubkey, hash(b"hello, world"), zero); let mut tr = Transaction::new(&keypair, pubkey, hash(b"hello, world"), zero);
tr.sign(&keypair); tr.sign(&keypair);
tr.asset = hash(b"goodbye cruel world"); // <-- attack! tr.asset = hash(b"goodbye cruel world"); // <-- attack!
@ -95,14 +94,14 @@ mod tests {
#[test] #[test]
fn test_hijack_attack() { fn test_hijack_attack() {
let keypair0 = generate_keypair(); let keypair0 = KeyPair::new();
let keypair1 = generate_keypair(); let keypair1 = KeyPair::new();
let thief_keypair = generate_keypair(); let thief_keypair = KeyPair::new();
let pubkey1 = get_pubkey(&keypair1); let pubkey1 = keypair1.pubkey();
let zero = Hash::default(); let zero = Hash::default();
let mut tr = Transaction::new(&keypair0, pubkey1, hash(b"hello, world"), zero); let mut tr = Transaction::new(&keypair0, pubkey1, hash(b"hello, world"), zero);
tr.sign(&keypair0); tr.sign(&keypair0);
tr.to = get_pubkey(&thief_keypair); // <-- attack! tr.to = thief_keypair.pubkey(); // <-- attack!
assert!(!tr.verify()); assert!(!tr.verify());
} }
} }