Initialize the testnode from a log

$ cargo run --bin silk-genesis-file-demo > demo-genesis.json
$ cat demo-genesis.json | cargo run --bin silk-genesis-block > demo-genesis.log
$ cat demo-genesis.log | cargo run --bin silk-testnode
This commit is contained in:
Greg Fitzgerald 2018-03-05 15:34:15 -07:00
parent 298989c4b9
commit a4336a39d6
10 changed files with 69 additions and 70 deletions

View File

@ -2,7 +2,7 @@
//! event log to record transactions. Its users can deposit funds and
//! transfer funds to other users.
use log::Sha256Hash;
use log::{Entry, Sha256Hash};
use event::{get_pubkey, sign_transaction_data, verify_event, Event, PublicKey, Signature};
use genesis::Genesis;
use historian::{reserve_signature, Historian};
@ -28,8 +28,17 @@ pub struct Accountant {
}
impl Accountant {
pub fn new(gen: &Genesis, ms_per_tick: Option<u64>) -> Self {
let start_hash = gen.get_seed();
pub fn new_from_entries<I>(entries: I, ms_per_tick: Option<u64>) -> Self
where
I: IntoIterator<Item = Entry<u64>>,
{
let mut entries = entries.into_iter();
// The first item in the log is required to be an entry with zero num_hashes,
// which implies its id can be used as the log's seed.
let entry0 = entries.next().unwrap();
let start_hash = entry0.id;
let hist = Historian::<u64>::new(&start_hash, ms_per_tick);
let mut acc = Accountant {
historian: hist,
@ -37,12 +46,23 @@ impl Accountant {
first_id: start_hash,
last_id: start_hash,
};
for (i, event) in gen.create_events().iter().enumerate() {
acc.process_verified_event(event, i < 2).unwrap();
// The second item in the log is a special transaction where the to and from
// fields are the same. That entry should be treated as a deposit, not a
// transfer to oneself.
let entry1 = entries.next().unwrap();
acc.process_verified_event(&entry1.event, true).unwrap();
for entry in entries {
acc.process_verified_event(&entry.event, false).unwrap();
}
acc
}
pub fn new(gen: &Genesis, ms_per_tick: Option<u64>) -> Self {
Self::new_from_entries(gen.create_entries(), ms_per_tick)
}
pub fn sync(self: &mut Self) -> Sha256Hash {
while let Ok(entry) = self.historian.receiver.try_recv() {
self.last_id = entry.id;
@ -66,7 +86,6 @@ impl Accountant {
}
self.process_verified_event(&event, false)?;
if let Err(SendError(_)) = self.historian.sender.send(event) {
return Err(AccountingError::SendError);
}

View File

@ -31,7 +31,7 @@ pub enum Request {
#[derive(Serialize, Deserialize, Debug)]
pub enum Response {
Balance { key: PublicKey, val: u64 },
Balance { key: PublicKey, val: Option<u64> },
Entries { entries: Vec<Entry<u64>> },
Id { id: Sha256Hash, is_last: bool },
}
@ -58,12 +58,12 @@ impl AccountantSkel {
sig,
};
if let Err(err) = self.acc.process_event(event) {
println!("Transfer error: {:?}", err);
eprintln!("Transfer error: {:?}", err);
}
None
}
Request::GetBalance { key } => {
let val = self.acc.get_balance(&key).unwrap();
let val = self.acc.get_balance(&key);
Some(Response::Balance { key, val })
}
Request::GetEntries { .. } => Some(Response::Entries { entries: vec![] }),

View File

@ -57,7 +57,7 @@ impl AccountantStub {
.map(|_| sig)
}
pub fn get_balance(&self, pubkey: &PublicKey) -> io::Result<u64> {
pub fn get_balance(&self, pubkey: &PublicKey) -> io::Result<Option<u64>> {
let req = Request::GetBalance { key: *pubkey };
let data = serialize(&req).expect("serialize GetBalance");
self.socket.send_to(&data, &self.addr)?;
@ -68,7 +68,7 @@ impl AccountantStub {
assert_eq!(key, *pubkey);
return Ok(val);
}
Ok(0)
Ok(None)
}
fn get_id(&self, is_last: bool) -> io::Result<Sha256Hash> {
@ -147,6 +147,6 @@ mod tests {
let sig = acc.transfer(500, &alice.get_keypair(), bob_pubkey, &last_id)
.unwrap();
acc.wait_on_signature(&sig).unwrap();
assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_500);
assert_eq!(acc.get_balance(&bob_pubkey).unwrap().unwrap(), 1_500);
}
}

View File

@ -1,36 +1,28 @@
//extern crate serde_json;
extern crate serde_json;
extern crate silk;
use silk::accountant_stub::AccountantStub;
use silk::accountant_skel::AccountantSkel;
use silk::accountant::Accountant;
use silk::event::{generate_keypair, get_pubkey, sign_transaction_data, verify_event, Event};
use silk::genesis::Genesis;
use std::time::Instant;
use std::net::UdpSocket;
use std::thread::{sleep, spawn};
use std::time::Duration;
//use std::io::stdin;
use std::io::stdin;
fn main() {
let addr = "127.0.0.1:8000";
let send_addr = "127.0.0.1:8001";
let txs = 200;
let gen = Genesis::new(txs, vec![]);
let alice_keypair = generate_keypair();
//let gen: Genesis = serde_json::from_reader(stdin()).unwrap();
//let alice_keypair = gen.get_keypair();
let acc = Accountant::new(&gen, None);
spawn(move || AccountantSkel::new(acc).serve(addr).unwrap());
sleep(Duration::from_millis(30));
let gen: Genesis = serde_json::from_reader(stdin()).unwrap();
let alice_keypair = gen.get_keypair();
let alice_pubkey = gen.get_pubkey();
let socket = UdpSocket::bind(send_addr).unwrap();
let mut acc = AccountantStub::new(addr, socket);
let last_id = acc.get_last_id().unwrap();
let alice_pubkey = get_pubkey(&alice_keypair);
let txs = acc.get_balance(&alice_pubkey).unwrap().unwrap();
println!("Alice's Initial Balance {}", txs);
let one = 1;
println!("Signing transactions...");
let now = Instant::now();
@ -89,7 +81,7 @@ fn main() {
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;
println!("Done. {} tps!", tps);
let val = acc.get_balance(&alice_pubkey).unwrap();
let val = acc.get_balance(&alice_pubkey).unwrap().unwrap();
println!("Alice's Final Balance {}", val);
assert_eq!(val, 0);
}

View File

@ -12,13 +12,7 @@ fn main() {
let gen: Genesis = serde_json::from_reader(stdin()).unwrap();
let entries = gen.create_entries();
verify_slice_u64(&entries, &entries[0].id);
println!("[");
let len = entries.len();
for (i, x) in entries.iter().enumerate() {
let s = serde_json::to_string(&x).unwrap();
let terminator = if i + 1 == len { "" } else { "," };
println!(" {}{}", s, terminator);
for x in entries {
println!("{}", serde_json::to_string(&x).unwrap());
}
println!("]");
}

View File

@ -14,6 +14,6 @@ fn main() {
pubkey: get_pubkey(&generate_keypair()),
};
let creators = vec![alice, bob];
let gen = Genesis::new(300, creators);
let gen = Genesis::new(500, creators);
println!("{}", serde_json::to_string(&gen).unwrap());
}

View File

@ -3,14 +3,17 @@ extern crate silk;
use silk::accountant_skel::AccountantSkel;
use silk::accountant::Accountant;
use silk::genesis::Genesis;
use std::io::stdin;
use std::io::{self, BufRead};
fn main() {
let addr = "127.0.0.1:8000";
let gen: Genesis = serde_json::from_reader(stdin()).unwrap();
let acc = Accountant::new(&gen, Some(1000));
let stdin = io::stdin();
let entries = stdin
.lock()
.lines()
.map(|line| serde_json::from_str(&line.unwrap()).unwrap());
let acc = Accountant::new_from_entries(entries, Some(1000));
let mut skel = AccountantSkel::new(acc);
println!("Listening on {}", addr);
eprintln!("Listening on {}", addr);
skel.serve(addr).unwrap();
}

View File

@ -32,6 +32,7 @@ impl Genesis {
pub fn new(tokens: u64, creators: Vec<Creator>) -> Self {
let rnd = SystemRandom::new();
let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rnd).unwrap().to_vec();
println!("{:?}", pkcs8);
Genesis {
pkcs8,
tokens,
@ -86,6 +87,7 @@ impl Genesis {
#[cfg(test)]
mod tests {
use super::*;
use log::verify_slice_u64;
#[test]
fn test_create_events() {
@ -108,4 +110,16 @@ mod tests {
3
);
}
#[test]
fn test_verify_entries() {
let entries = Genesis::new(100, vec![]).create_entries();
assert!(verify_slice_u64(&entries, &entries[0].id));
}
#[test]
fn test_verify_entries_with_transactions() {
let entries = Genesis::new(100, vec![Creator::new(42)]).create_entries();
assert!(verify_slice_u64(&entries, &entries[0].id));
}
}

View File

@ -14,5 +14,6 @@ extern crate ring;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate sha2;
extern crate untrusted;

View File

@ -11,6 +11,7 @@ use log::{create_entry_mut, Entry, Sha256Hash};
use event::Event;
use serde::Serialize;
use std::fmt::Debug;
use serde_json;
#[derive(Debug, PartialEq, Eq)]
pub enum ExitReason {
@ -43,6 +44,7 @@ impl<T: Serialize + Clone + Debug> Logger<T> {
pub fn log_event(&mut self, event: Event<T>) -> Result<Entry<T>, ExitReason> {
let entry = create_entry_mut(&mut self.last_id, &mut self.num_hashes, event);
println!("{}", serde_json::to_string(&entry).unwrap());
Ok(entry)
}
@ -78,8 +80,6 @@ mod tests {
use super::*;
use log::*;
use event::*;
use genesis::*;
use std::sync::mpsc::sync_channel;
#[test]
fn test_bad_event_signature() {
@ -94,28 +94,4 @@ mod tests {
);
assert!(!verify_event(&event0));
}
fn run_genesis(gen: Genesis) -> Vec<Entry<u64>> {
let (sender, event_receiver) = sync_channel(100);
let (entry_sender, receiver) = sync_channel(100);
let mut logger = Logger::new(event_receiver, entry_sender, gen.get_seed());
for tx in gen.create_events() {
sender.send(tx).unwrap();
}
logger.process_events(Instant::now(), None).unwrap();
drop(logger.sender);
receiver.iter().collect::<Vec<_>>()
}
#[test]
fn test_genesis_no_creators() {
let entries = run_genesis(Genesis::new(100, vec![]));
assert!(verify_slice_u64(&entries, &entries[0].id));
}
#[test]
fn test_genesis() {
let entries = run_genesis(Genesis::new(100, vec![Creator::new(42)]));
assert!(verify_slice_u64(&entries, &entries[0].id));
}
}