enhance ledger-tool
* add json, which does the thing with json, move print to Rust's {:?} * add --head NUM, to limit how much work gets done for print, json, verify * add verify-internal, which very carefully checks ledger format without trying first to "recover" it * exit with errors on mis-usage
This commit is contained in:
@ -5,7 +5,7 @@ extern crate solana;
|
||||
|
||||
use clap::{App, Arg, SubCommand};
|
||||
use solana::bank::Bank;
|
||||
use solana::ledger::read_ledger;
|
||||
use solana::ledger::{read_ledger, verify_ledger};
|
||||
use solana::logger;
|
||||
use std::io::{stdout, Write};
|
||||
use std::process::exit;
|
||||
@ -23,23 +23,57 @@ fn main() {
|
||||
.required(true)
|
||||
.help("use DIR for ledger location"),
|
||||
)
|
||||
.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)"),
|
||||
)
|
||||
.subcommand(SubCommand::with_name("print").about("Print the ledger"))
|
||||
.subcommand(SubCommand::with_name("verify").about("Verify the ledger"))
|
||||
.subcommand(SubCommand::with_name("json").about("Print the ledger in JSON format"))
|
||||
.subcommand(SubCommand::with_name("verify").about("Verify the ledger's PoH"))
|
||||
.subcommand(
|
||||
SubCommand::with_name("verify-internal")
|
||||
.about("Verify the ledger's internal structure"),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let ledger_path = matches.value_of("ledger").unwrap();
|
||||
let entries = match read_ledger(ledger_path, true) {
|
||||
Ok(entries) => entries,
|
||||
Err(err) => {
|
||||
println!("Failed to open ledger at {}: {}", ledger_path, err);
|
||||
eprintln!("Failed to open ledger at {}: {}", ledger_path, err);
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let head = match matches.value_of("head") {
|
||||
Some(head) => head.parse().expect("please pass a number for --head"),
|
||||
None => <usize>::max_value(),
|
||||
};
|
||||
|
||||
match matches.subcommand() {
|
||||
("print", _) => {
|
||||
let mut i = 0;
|
||||
for entry in entries {
|
||||
if i >= head {
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
let entry = entry.unwrap();
|
||||
println!("{:?}", entry);
|
||||
}
|
||||
}
|
||||
("json", _) => {
|
||||
let mut i = 0;
|
||||
stdout().write_all(b"{\"ledger\":[\n").expect("open array");
|
||||
for entry in entries {
|
||||
if i >= head {
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
let entry = entry.unwrap();
|
||||
serde_json::to_writer(stdout(), &entry).expect("serialize");
|
||||
stdout().write_all(b",\n").expect("newline");
|
||||
@ -47,13 +81,27 @@ fn main() {
|
||||
stdout().write_all(b"\n]}\n").expect("close array");
|
||||
}
|
||||
("verify", _) => {
|
||||
let entries = entries.map(|entry| entry.unwrap());
|
||||
let bank = Bank::default();
|
||||
let entry_height = bank.process_ledger(entries).expect("process_ledger").0;
|
||||
println!("Ledger is valid. Height: {}", entry_height);
|
||||
if head != <usize>::max_value() {
|
||||
let entries = entries.map(|entry| entry.unwrap()).take(head);
|
||||
bank.process_ledger(entries).expect("process_ledger").0;
|
||||
} else {
|
||||
let entries = entries.map(|entry| entry.unwrap());
|
||||
bank.process_ledger(entries).expect("process_ledger").0;
|
||||
}
|
||||
}
|
||||
("verify-internal", _) => {
|
||||
if let Err(e) = verify_ledger(&ledger_path, false) {
|
||||
eprintln!("Error {:?} ", e);
|
||||
exit(1);
|
||||
} else {
|
||||
println!("Ledger is valid");
|
||||
}
|
||||
}
|
||||
|
||||
("", _) => {
|
||||
println!("{}", matches.usage());
|
||||
eprintln!("{}", matches.usage());
|
||||
exit(1);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
Reference in New Issue
Block a user