2018-08-06 20:51:12 -07:00
|
|
|
#[macro_use]
|
2018-08-04 14:31:12 -07:00
|
|
|
extern crate clap;
|
|
|
|
extern crate serde_json;
|
|
|
|
extern crate solana;
|
|
|
|
|
2018-08-06 16:03:08 -07:00
|
|
|
use clap::{App, Arg, SubCommand};
|
|
|
|
use solana::bank::Bank;
|
2018-08-09 22:14:04 -07:00
|
|
|
use solana::ledger::{read_ledger, verify_ledger};
|
2018-08-06 17:33:51 -07:00
|
|
|
use solana::logger;
|
2018-08-04 14:31:12 -07:00
|
|
|
use std::io::{stdout, Write};
|
2018-08-06 16:03:08 -07:00
|
|
|
use std::process::exit;
|
2018-08-04 14:31:12 -07:00
|
|
|
|
|
|
|
fn main() {
|
2018-08-06 17:33:51 -07:00
|
|
|
logger::setup();
|
2018-08-06 16:03:08 -07:00
|
|
|
let matches = App::new("ledger-tool")
|
2018-08-06 20:51:12 -07:00
|
|
|
.version(crate_version!())
|
2018-08-04 14:31:12 -07:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("ledger")
|
|
|
|
.short("l")
|
|
|
|
.long("ledger")
|
|
|
|
.value_name("DIR")
|
|
|
|
.takes_value(true)
|
|
|
|
.required(true)
|
|
|
|
.help("use DIR for ledger location"),
|
|
|
|
)
|
2018-08-09 22:14:04 -07:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("head")
|
|
|
|
.short("n")
|
|
|
|
.long("head")
|
|
|
|
.value_name("NUM")
|
|
|
|
.takes_value(true)
|
|
|
|
.help("at most the first NUM entries in ledger\n (only applies to verify, print, json commands)"),
|
|
|
|
)
|
2018-08-10 18:41:26 -07:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("precheck")
|
|
|
|
.short("p")
|
|
|
|
.long("precheck")
|
|
|
|
.help("use ledger_verify() to check internal ledger consistency before proceeding"),
|
|
|
|
)
|
2018-08-06 16:03:08 -07:00
|
|
|
.subcommand(SubCommand::with_name("print").about("Print the ledger"))
|
2018-08-09 22:14:04 -07:00
|
|
|
.subcommand(SubCommand::with_name("json").about("Print the ledger in JSON format"))
|
|
|
|
.subcommand(SubCommand::with_name("verify").about("Verify the ledger's PoH"))
|
2018-08-04 14:31:12 -07:00
|
|
|
.get_matches();
|
|
|
|
|
|
|
|
let ledger_path = matches.value_of("ledger").unwrap();
|
2018-08-10 18:41:26 -07:00
|
|
|
|
|
|
|
if matches.is_present("precheck") {
|
|
|
|
if let Err(e) = verify_ledger(&ledger_path) {
|
|
|
|
eprintln!("ledger precheck failed, error: {:?} ", e);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
2018-08-10 17:56:08 -07:00
|
|
|
let entries = match read_ledger(ledger_path, true) {
|
2018-08-06 16:03:08 -07:00
|
|
|
Ok(entries) => entries,
|
|
|
|
Err(err) => {
|
2018-08-09 22:14:04 -07:00
|
|
|
eprintln!("Failed to open ledger at {}: {}", ledger_path, err);
|
2018-08-06 16:03:08 -07:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
};
|
2018-08-04 14:31:12 -07:00
|
|
|
|
2018-08-09 22:14:04 -07:00
|
|
|
let head = match matches.value_of("head") {
|
|
|
|
Some(head) => head.parse().expect("please pass a number for --head"),
|
|
|
|
None => <usize>::max_value(),
|
|
|
|
};
|
|
|
|
|
2018-08-06 16:03:08 -07:00
|
|
|
match matches.subcommand() {
|
|
|
|
("print", _) => {
|
2018-08-10 18:41:26 -07:00
|
|
|
let entries = match read_ledger(ledger_path, true) {
|
|
|
|
Ok(entries) => entries,
|
|
|
|
Err(err) => {
|
|
|
|
eprintln!("Failed to open ledger at {}: {}", ledger_path, err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
};
|
2018-08-10 11:46:37 -07:00
|
|
|
for (i, entry) in entries.enumerate() {
|
2018-08-09 22:14:04 -07:00
|
|
|
if i >= head {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
let entry = entry.unwrap();
|
|
|
|
println!("{:?}", entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
("json", _) => {
|
2018-08-06 16:03:08 -07:00
|
|
|
stdout().write_all(b"{\"ledger\":[\n").expect("open array");
|
2018-08-10 11:46:37 -07:00
|
|
|
for (i, entry) in entries.enumerate() {
|
2018-08-09 22:14:04 -07:00
|
|
|
if i >= head {
|
|
|
|
break;
|
|
|
|
}
|
2018-08-06 16:03:08 -07:00
|
|
|
let entry = entry.unwrap();
|
|
|
|
serde_json::to_writer(stdout(), &entry).expect("serialize");
|
|
|
|
stdout().write_all(b",\n").expect("newline");
|
|
|
|
}
|
|
|
|
stdout().write_all(b"\n]}\n").expect("close array");
|
|
|
|
}
|
|
|
|
("verify", _) => {
|
2018-08-10 19:34:39 -07:00
|
|
|
if head < 2 {
|
|
|
|
eprintln!("verify requires at least 2 entries to run");
|
|
|
|
exit(1);
|
|
|
|
}
|
2018-08-06 16:03:08 -07:00
|
|
|
let bank = Bank::default();
|
2018-08-10 19:34:39 -07:00
|
|
|
|
|
|
|
{
|
|
|
|
let genesis = match read_ledger(ledger_path, true) {
|
|
|
|
Ok(entries) => entries,
|
|
|
|
Err(err) => {
|
|
|
|
eprintln!("Failed to open ledger at {}: {}", ledger_path, err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let genesis = genesis.take(2).map(|e| e.unwrap());
|
|
|
|
|
|
|
|
if let Err(e) = bank.process_ledger(genesis) {
|
|
|
|
eprintln!("verify failed at genesis err: {:?}", e);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let entries = entries.map(|e| e.unwrap());
|
|
|
|
|
|
|
|
for (i, entry) in entries.enumerate() {
|
|
|
|
if i >= head {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if i >= 2 {
|
|
|
|
if let Err(e) = bank.process_entry(entry) {
|
|
|
|
eprintln!("verify failed at entry[{}], err: {:?}", i, e);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
2018-08-09 22:14:04 -07:00
|
|
|
}
|
2018-08-06 16:03:08 -07:00
|
|
|
}
|
|
|
|
("", _) => {
|
2018-08-09 22:14:04 -07:00
|
|
|
eprintln!("{}", matches.usage());
|
|
|
|
exit(1);
|
2018-08-06 16:03:08 -07:00
|
|
|
}
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
2018-08-04 14:31:12 -07:00
|
|
|
}
|