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:
parent
298989c4b9
commit
a4336a39d6
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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![] }),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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!("]");
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue