Add command-line tool for generating a genesis block
This commit is contained in:
parent
74ebaf1744
commit
11a0f96f5e
|
@ -23,6 +23,10 @@ path = "src/bin/client-demo.rs"
|
|||
name = "silk-testnode"
|
||||
path = "src/bin/testnode.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "silk-genesis-block"
|
||||
path = "src/bin/genesis-block.rs"
|
||||
|
||||
[badges]
|
||||
codecov = { repository = "loomprotocol/silk", branch = "master", service = "github" }
|
||||
|
||||
|
@ -37,6 +41,7 @@ sha2-asm = {version="0.3", optional=true}
|
|||
generic-array = { version = "0.9.0", default-features = false, features = ["serde"] }
|
||||
serde = "1.0.27"
|
||||
serde_derive = "1.0.27"
|
||||
serde_json = "1.0.10"
|
||||
ring = "0.12.1"
|
||||
untrusted = "0.5.1"
|
||||
bincode = "1.0.0"
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
//! A command-line executable for generating the chain's genesis block.
|
||||
|
||||
extern crate ring;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate silk;
|
||||
|
||||
use silk::genesis::Genesis;
|
||||
use silk::log::verify_slice_u64;
|
||||
use silk::logger::Logger;
|
||||
use std::sync::mpsc::sync_channel;
|
||||
use std::io::stdin;
|
||||
|
||||
fn main() {
|
||||
let gen: Genesis = serde_json::from_reader(stdin()).unwrap();
|
||||
|
||||
let (_sender, event_receiver) = sync_channel(100);
|
||||
let (entry_sender, receiver) = sync_channel(100);
|
||||
let mut logger = Logger::new(event_receiver, entry_sender, gen.seed);
|
||||
for tx in gen.create_events() {
|
||||
logger.log_event(tx).unwrap();
|
||||
}
|
||||
drop(logger.sender);
|
||||
|
||||
let entries = receiver.iter().collect::<Vec<_>>();
|
||||
verify_slice_u64(&entries, &gen.seed);
|
||||
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);
|
||||
}
|
||||
println!("]");
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
//! A library for generating the chain's genesis block.
|
||||
|
||||
use event::{generate_keypair, get_pubkey, sign_claim_data, sign_transaction_data, Event, PublicKey};
|
||||
use log::Sha256Hash;
|
||||
use ring::rand::{SecureRandom, SystemRandom};
|
||||
use ring::signature::Ed25519KeyPair;
|
||||
use untrusted::Input;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Creator {
|
||||
pub name: String,
|
||||
pub pubkey: PublicKey,
|
||||
pub tokens: u64,
|
||||
}
|
||||
|
||||
impl Creator {
|
||||
pub fn new(name: &str, tokens: u64) -> Self {
|
||||
Creator {
|
||||
name: name.to_string(),
|
||||
pubkey: get_pubkey(&generate_keypair()),
|
||||
tokens,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_transaction(&self, keypair: &Ed25519KeyPair) -> Event<u64> {
|
||||
let from = Some(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)]
|
||||
pub struct Genesis {
|
||||
pub seed: Sha256Hash,
|
||||
pub pkcs8: Vec<u8>,
|
||||
pub tokens: u64,
|
||||
pub creators: Vec<Creator>,
|
||||
}
|
||||
|
||||
impl Genesis {
|
||||
pub fn new(tokens: u64, creators: Vec<Creator>) -> Self {
|
||||
let rnd = SystemRandom::new();
|
||||
let mut seed_arr = [0; 32];
|
||||
rnd.fill(&mut seed_arr).unwrap();
|
||||
let seed = *Sha256Hash::from_slice(&seed_arr);
|
||||
let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rnd).unwrap().to_vec();
|
||||
Genesis {
|
||||
seed,
|
||||
pkcs8,
|
||||
tokens,
|
||||
creators,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_events(&self) -> Vec<Event<u64>> {
|
||||
let org_keypair = Ed25519KeyPair::from_pkcs8(Input::from(&self.pkcs8)).unwrap();
|
||||
let sig = sign_claim_data(&self.tokens, &org_keypair);
|
||||
let event0 = Event::new_claim(get_pubkey(&org_keypair), self.tokens, sig);
|
||||
let mut events = vec![event0];
|
||||
|
||||
for creator in &self.creators {
|
||||
let tx = creator.create_transaction(&org_keypair);
|
||||
events.push(tx);
|
||||
}
|
||||
|
||||
events
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use event::verify_event;
|
||||
|
||||
#[test]
|
||||
fn test_creator_transaction() {
|
||||
assert!(verify_event(&Creator::new("Satoshi", 42)
|
||||
.create_transaction(&generate_keypair())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_events() {
|
||||
assert_eq!(Genesis::new(100, vec![]).create_events().len(), 1);
|
||||
assert_eq!(
|
||||
Genesis::new(100, vec![Creator::new("Satoshi", 42)])
|
||||
.create_events()
|
||||
.len(),
|
||||
2
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
pub mod log;
|
||||
pub mod logger;
|
||||
pub mod event;
|
||||
pub mod genesis;
|
||||
pub mod historian;
|
||||
pub mod accountant;
|
||||
pub mod accountant_skel;
|
||||
|
|
|
@ -110,6 +110,8 @@ mod tests {
|
|||
use super::*;
|
||||
use log::*;
|
||||
use event::*;
|
||||
use genesis::*;
|
||||
use std::sync::mpsc::sync_channel;
|
||||
|
||||
#[test]
|
||||
fn test_bad_event_signature() {
|
||||
|
@ -132,4 +134,27 @@ mod tests {
|
|||
assert!(verify_event_and_reserve_signature(&mut sigs, &event0));
|
||||
assert!(!verify_event_and_reserve_signature(&mut sigs, &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.seed);
|
||||
for tx in gen.create_events() {
|
||||
logger.log_event(tx).unwrap();
|
||||
}
|
||||
drop(logger.sender);
|
||||
receiver.iter().collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_genesis_no_creators() {
|
||||
let gen = Genesis::new(100, vec![]);
|
||||
assert!(verify_slice_u64(&run_genesis(&gen), &gen.seed));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_genesis() {
|
||||
let gen = Genesis::new(100, vec![Creator::new("Satoshi", 42)]);
|
||||
assert!(verify_slice_u64(&run_genesis(&gen), &gen.seed));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue