Load the genesis block
This commit is contained in:
parent
876d7995e1
commit
572475ce14
|
@ -2,8 +2,9 @@
|
||||||
//! event log to record transactions. Its users can deposit funds and
|
//! event log to record transactions. Its users can deposit funds and
|
||||||
//! transfer funds to other users.
|
//! transfer funds to other users.
|
||||||
|
|
||||||
use log::{Entry, Sha256Hash};
|
use log::{hash, Entry, Sha256Hash};
|
||||||
use event::{Event, PublicKey, Signature};
|
use event::{Event, PublicKey, Signature};
|
||||||
|
use genesis::Genesis;
|
||||||
use historian::Historian;
|
use historian::Historian;
|
||||||
use ring::signature::Ed25519KeyPair;
|
use ring::signature::Ed25519KeyPair;
|
||||||
use std::sync::mpsc::SendError;
|
use std::sync::mpsc::SendError;
|
||||||
|
@ -26,13 +27,18 @@ pub struct Accountant {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Accountant {
|
impl Accountant {
|
||||||
pub fn new(start_hash: &Sha256Hash, ms_per_tick: Option<u64>) -> Self {
|
pub fn new(gen: &Genesis, ms_per_tick: Option<u64>) -> Self {
|
||||||
let hist = Historian::<u64>::new(start_hash, ms_per_tick);
|
let start_hash = hash(&gen.pkcs8);
|
||||||
Accountant {
|
let hist = Historian::<u64>::new(&start_hash, ms_per_tick);
|
||||||
|
let mut acc = Accountant {
|
||||||
historian: hist,
|
historian: hist,
|
||||||
balances: HashMap::new(),
|
balances: HashMap::new(),
|
||||||
end_hash: *start_hash,
|
end_hash: start_hash,
|
||||||
|
};
|
||||||
|
for (i, event) in gen.create_events().into_iter().enumerate() {
|
||||||
|
acc.process_verified_event(event, i < 2).unwrap();
|
||||||
}
|
}
|
||||||
|
acc
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync(self: &mut Self) -> Vec<Entry<u64>> {
|
pub fn sync(self: &mut Self) -> Vec<Entry<u64>> {
|
||||||
|
@ -151,19 +157,16 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use event::{generate_keypair, get_pubkey};
|
use event::{generate_keypair, get_pubkey};
|
||||||
use logger::ExitReason;
|
use logger::ExitReason;
|
||||||
|
use genesis::Creator;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_accountant() {
|
fn test_accountant() {
|
||||||
let zero = Sha256Hash::default();
|
let bob = Creator::new("Bob", 1_000);
|
||||||
let mut acc = Accountant::new(&zero, Some(2));
|
let bob_pubkey = bob.pubkey;
|
||||||
let alice_keypair = generate_keypair();
|
let alice = Genesis::new(10_000, vec![bob]);
|
||||||
let bob_keypair = generate_keypair();
|
let mut acc = Accountant::new(&alice, Some(2));
|
||||||
acc.deposit(10_000, &alice_keypair).unwrap();
|
|
||||||
let sig = acc.deposit(1_000, &bob_keypair).unwrap();
|
|
||||||
acc.wait_on_signature(&sig);
|
|
||||||
|
|
||||||
let bob_pubkey = get_pubkey(&bob_keypair);
|
let sig = acc.transfer(500, &alice.get_keypair(), bob_pubkey).unwrap();
|
||||||
let sig = acc.transfer(500, &alice_keypair, bob_pubkey).unwrap();
|
|
||||||
acc.wait_on_signature(&sig);
|
acc.wait_on_signature(&sig);
|
||||||
|
|
||||||
assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_500);
|
assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_500);
|
||||||
|
@ -179,22 +182,18 @@ mod tests {
|
||||||
fn test_invalid_transfer() {
|
fn test_invalid_transfer() {
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
let zero = Sha256Hash::default();
|
let bob = Creator::new("Bob", 1_000);
|
||||||
let mut acc = Accountant::new(&zero, Some(2));
|
let bob_pubkey = bob.pubkey;
|
||||||
let alice_keypair = generate_keypair();
|
let alice = Genesis::new(11_000, vec![bob]);
|
||||||
let bob_keypair = generate_keypair();
|
let mut acc = Accountant::new(&alice, Some(2));
|
||||||
acc.deposit(10_000, &alice_keypair).unwrap();
|
|
||||||
let sig = acc.deposit(1_000, &bob_keypair).unwrap();
|
|
||||||
acc.wait_on_signature(&sig);
|
|
||||||
|
|
||||||
let bob_pubkey = get_pubkey(&bob_keypair);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
acc.transfer(10_001, &alice_keypair, bob_pubkey),
|
acc.transfer(10_001, &alice.get_keypair(), bob_pubkey),
|
||||||
Err(AccountingError::InsufficientFunds)
|
Err(AccountingError::InsufficientFunds)
|
||||||
);
|
);
|
||||||
sleep(Duration::from_millis(30));
|
sleep(Duration::from_millis(30));
|
||||||
|
|
||||||
let alice_pubkey = get_pubkey(&alice_keypair);
|
let alice_pubkey = get_pubkey(&alice.get_keypair());
|
||||||
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);
|
||||||
|
|
||||||
|
@ -205,30 +204,11 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_multiple_claims() {
|
|
||||||
let zero = Sha256Hash::default();
|
|
||||||
let mut acc = Accountant::new(&zero, Some(2));
|
|
||||||
let keypair = generate_keypair();
|
|
||||||
acc.deposit(1, &keypair).unwrap();
|
|
||||||
let sig = acc.deposit(2, &keypair).unwrap();
|
|
||||||
acc.wait_on_signature(&sig);
|
|
||||||
|
|
||||||
let pubkey = get_pubkey(&keypair);
|
|
||||||
assert_eq!(acc.get_balance(&pubkey).unwrap(), 3);
|
|
||||||
|
|
||||||
drop(acc.historian.sender);
|
|
||||||
assert_eq!(
|
|
||||||
acc.historian.thread_hdl.join().unwrap().1,
|
|
||||||
ExitReason::RecvDisconnected
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_transfer_to_newb() {
|
fn test_transfer_to_newb() {
|
||||||
let zero = Sha256Hash::default();
|
let alice = Genesis::new(10_000, vec![]);
|
||||||
let mut acc = Accountant::new(&zero, Some(2));
|
let mut acc = Accountant::new(&alice, Some(2));
|
||||||
let alice_keypair = generate_keypair();
|
let alice_keypair = alice.get_keypair();
|
||||||
let bob_keypair = generate_keypair();
|
let bob_keypair = generate_keypair();
|
||||||
let sig = acc.deposit(10_000, &alice_keypair).unwrap();
|
let sig = acc.deposit(10_000, &alice_keypair).unwrap();
|
||||||
acc.wait_on_signature(&sig);
|
acc.wait_on_signature(&sig);
|
||||||
|
|
|
@ -82,27 +82,22 @@ 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 log::Sha256Hash;
|
use genesis::{Creator, Genesis};
|
||||||
use event::{generate_keypair, get_pubkey};
|
|
||||||
|
|
||||||
#[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 zero = Sha256Hash::default();
|
let bob = Creator::new("Bob", 1_000);
|
||||||
let alice_keypair = generate_keypair();
|
let bob_pubkey = bob.pubkey;
|
||||||
let bob_keypair = generate_keypair();
|
let alice = Genesis::new(10_000, vec![bob]);
|
||||||
let mut acc = Accountant::new(&zero, None);
|
let acc = Accountant::new(&alice, None);
|
||||||
acc.deposit(10_000, &alice_keypair).unwrap();
|
|
||||||
let sig = acc.deposit(1_000, &bob_keypair).unwrap();
|
|
||||||
acc.wait_on_signature(&sig);
|
|
||||||
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 acc = AccountantStub::new(addr, socket);
|
let acc = AccountantStub::new(addr, socket);
|
||||||
let bob_pubkey = get_pubkey(&bob_keypair);
|
let sig = acc.transfer(500, &alice.get_keypair(), bob_pubkey).unwrap();
|
||||||
let sig = acc.transfer(500, &alice_keypair, bob_pubkey).unwrap();
|
|
||||||
acc.wait_on_signature(&sig).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(), 1_500);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ fn main() {
|
||||||
use silk::accountant_skel::AccountantSkel;
|
use silk::accountant_skel::AccountantSkel;
|
||||||
use silk::accountant::Accountant;
|
use silk::accountant::Accountant;
|
||||||
use silk::event::{generate_keypair, get_pubkey, sign_transaction_data};
|
use silk::event::{generate_keypair, get_pubkey, sign_transaction_data};
|
||||||
|
use silk::genesis::Genesis;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
use std::thread::{sleep, spawn};
|
use std::thread::{sleep, spawn};
|
||||||
|
@ -13,12 +14,10 @@ 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 zero = Default::default();
|
|
||||||
let alice_keypair = generate_keypair();
|
|
||||||
let mut acc = Accountant::new(&zero, None);
|
|
||||||
let txs = 200;
|
let txs = 200;
|
||||||
let sig = acc.deposit(txs, &alice_keypair).unwrap();
|
let gen = Genesis::new(txs, vec![]);
|
||||||
acc.wait_on_signature(&sig);
|
let alice_keypair = generate_keypair();
|
||||||
|
let acc = Accountant::new(&gen, None);
|
||||||
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));
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
//! A command-line executable for generating the chain's genesis block.
|
//! A command-line executable for generating the chain's genesis block.
|
||||||
|
|
||||||
extern crate ring;
|
extern crate ring;
|
||||||
extern crate serde;
|
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate silk;
|
extern crate silk;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
|
extern crate serde_json;
|
||||||
extern crate silk;
|
extern crate silk;
|
||||||
|
|
||||||
use silk::accountant_skel::AccountantSkel;
|
use silk::accountant_skel::AccountantSkel;
|
||||||
use silk::accountant::Accountant;
|
use silk::accountant::Accountant;
|
||||||
use silk::log::Sha256Hash;
|
use silk::genesis::Genesis;
|
||||||
|
use std::io::stdin;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let addr = "127.0.0.1:8000";
|
let addr = "127.0.0.1:8000";
|
||||||
let zero = Sha256Hash::default();
|
let gen: Genesis = serde_json::from_reader(stdin()).unwrap();
|
||||||
let acc = Accountant::new(&zero, Some(1000));
|
let acc = Accountant::new(&gen, Some(1000));
|
||||||
let mut skel = AccountantSkel::new(acc);
|
let mut skel = AccountantSkel::new(acc);
|
||||||
println!("Listening on {}", addr);
|
println!("Listening on {}", addr);
|
||||||
skel.serve(addr).unwrap();
|
skel.serve(addr).unwrap();
|
||||||
|
|
|
@ -20,19 +20,6 @@ impl Creator {
|
||||||
tokens,
|
tokens,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_transaction(&self, keypair: &Ed25519KeyPair) -> Event<u64> {
|
|
||||||
let from = get_pubkey(keypair);
|
|
||||||
let to = self.pubkey;
|
|
||||||
let data = self.tokens;
|
|
||||||
let sig = sign_transaction_data(&data, keypair, &to);
|
|
||||||
Event::Transaction {
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
data,
|
|
||||||
sig,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
@ -53,15 +40,33 @@ impl Genesis {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_keypair(&self) -> Ed25519KeyPair {
|
||||||
|
Ed25519KeyPair::from_pkcs8(Input::from(&self.pkcs8)).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_pubkey(&self) -> PublicKey {
|
||||||
|
get_pubkey(&self.get_keypair())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_transaction(&self, data: u64, to: &PublicKey) -> Event<u64> {
|
||||||
|
let from = self.get_pubkey();
|
||||||
|
let sig = sign_transaction_data(&data, &self.get_keypair(), to);
|
||||||
|
Event::Transaction {
|
||||||
|
from,
|
||||||
|
to: *to,
|
||||||
|
data,
|
||||||
|
sig,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_events(&self) -> Vec<Event<u64>> {
|
pub fn create_events(&self) -> Vec<Event<u64>> {
|
||||||
let org_keypair = Ed25519KeyPair::from_pkcs8(Input::from(&self.pkcs8)).unwrap();
|
let pubkey = self.get_pubkey();
|
||||||
let event0 = Event::Tick;
|
let event0 = Event::Tick;
|
||||||
let treasury = Creator::new("Treasury", self.tokens);
|
let event1 = self.create_transaction(self.tokens, &pubkey);
|
||||||
let event1 = treasury.create_transaction(&org_keypair);
|
|
||||||
let mut events = vec![event0, event1];
|
let mut events = vec![event0, event1];
|
||||||
|
|
||||||
for creator in &self.creators {
|
for x in &self.creators {
|
||||||
let tx = creator.create_transaction(&org_keypair);
|
let tx = self.create_transaction(x.tokens, &x.pubkey);
|
||||||
events.push(tx);
|
events.push(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,17 +77,21 @@ impl Genesis {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use event::verify_event;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_creator_transaction() {
|
|
||||||
assert!(verify_event(&Creator::new("Satoshi", 42)
|
|
||||||
.create_transaction(&generate_keypair())));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_events() {
|
fn test_create_events() {
|
||||||
assert_eq!(Genesis::new(100, vec![]).create_events().len(), 2);
|
let mut events = Genesis::new(100, vec![]).create_events().into_iter();
|
||||||
|
assert_eq!(events.next().unwrap(), Event::Tick);
|
||||||
|
if let Event::Transaction { from, to, .. } = events.next().unwrap() {
|
||||||
|
assert_eq!(from, to);
|
||||||
|
} else {
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
assert_eq!(events.next(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_creator() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Genesis::new(100, vec![Creator::new("Satoshi", 42)])
|
Genesis::new(100, vec![Creator::new("Satoshi", 42)])
|
||||||
.create_events()
|
.create_events()
|
||||||
|
|
Loading…
Reference in New Issue