2019-07-11 20:33:36 -07:00
|
|
|
use clap::{crate_description, crate_name, crate_version, value_t, App, Arg, SubCommand};
|
2019-02-07 20:52:39 -08:00
|
|
|
use solana::blocktree::Blocktree;
|
2019-03-02 08:16:46 -08:00
|
|
|
use solana::blocktree_processor::process_blocktree;
|
2019-02-18 22:26:22 -08:00
|
|
|
use solana_sdk::genesis_block::GenesisBlock;
|
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
|
|
|
|
2019-07-11 20:33:36 -07:00
|
|
|
#[derive(PartialEq)]
|
|
|
|
enum LedgerOutputMethod {
|
|
|
|
Print,
|
|
|
|
Json,
|
|
|
|
}
|
|
|
|
fn output_ledger(blocktree: Blocktree, starting_slot: u64, method: LedgerOutputMethod) {
|
|
|
|
let rooted_slot_iterator = blocktree
|
|
|
|
.rooted_slot_iterator(starting_slot)
|
|
|
|
.unwrap_or_else(|err| {
|
|
|
|
eprintln!(
|
|
|
|
"Failed to load entries starting from slot {}: {:?}",
|
|
|
|
starting_slot, err
|
|
|
|
);
|
|
|
|
exit(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
if method == LedgerOutputMethod::Json {
|
|
|
|
stdout().write_all(b"{\"ledger\":[\n").expect("open array");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (slot, slot_meta) in rooted_slot_iterator {
|
|
|
|
match method {
|
|
|
|
LedgerOutputMethod::Print => println!("Slot {}", slot),
|
|
|
|
LedgerOutputMethod::Json => {
|
|
|
|
serde_json::to_writer(stdout(), &slot_meta).expect("serialize slot_meta");
|
|
|
|
stdout().write_all(b",\n").expect("newline");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let entries = blocktree
|
|
|
|
.get_slot_entries(slot, 0, None)
|
|
|
|
.unwrap_or_else(|err| {
|
|
|
|
eprintln!("Failed to load entries for slot {}: {:?}", slot, err);
|
|
|
|
exit(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
for entry in entries {
|
|
|
|
match method {
|
|
|
|
LedgerOutputMethod::Print => println!("{:?}", entry),
|
|
|
|
LedgerOutputMethod::Json => {
|
|
|
|
serde_json::to_writer(stdout(), &entry).expect("serialize entry");
|
|
|
|
stdout().write_all(b",\n").expect("newline");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if method == LedgerOutputMethod::Json {
|
|
|
|
stdout().write_all(b"\n]}\n").expect("close array");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-04 14:31:12 -07:00
|
|
|
fn main() {
|
2018-12-14 12:36:50 -08:00
|
|
|
solana_logger::setup();
|
2019-07-11 20:33:36 -07:00
|
|
|
let matches = App::new(crate_name!())
|
|
|
|
.about(crate_description!())
|
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)
|
2018-09-14 15:32:57 -07:00
|
|
|
.help("Use directory for ledger location"),
|
2018-08-04 14:31:12 -07:00
|
|
|
)
|
2018-08-09 22:14:04 -07:00
|
|
|
.arg(
|
2019-07-11 20:33:36 -07:00
|
|
|
Arg::with_name("starting_slot")
|
|
|
|
.long("starting-slot")
|
2018-12-07 20:44:59 -08:00
|
|
|
.value_name("NUM")
|
|
|
|
.takes_value(true)
|
2019-07-11 20:33:36 -07:00
|
|
|
.default_value("0")
|
|
|
|
.help("Start at this slot (only applies to print and json commands)"),
|
2018-09-26 18:37:24 -07:00
|
|
|
)
|
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
|
|
|
|
2019-01-24 12:04:04 -08:00
|
|
|
let genesis_block = GenesisBlock::load(ledger_path).unwrap_or_else(|err| {
|
|
|
|
eprintln!(
|
|
|
|
"Failed to open ledger genesis_block at {}: {}",
|
|
|
|
ledger_path, err
|
|
|
|
);
|
|
|
|
exit(1);
|
|
|
|
});
|
|
|
|
|
2019-02-07 20:52:39 -08:00
|
|
|
let blocktree = match Blocktree::open(ledger_path) {
|
|
|
|
Ok(blocktree) => blocktree,
|
2019-01-03 21:29:21 -08:00
|
|
|
Err(err) => {
|
|
|
|
eprintln!("Failed to open ledger at {}: {}", ledger_path, err);
|
2018-08-10 18:41:26 -07:00
|
|
|
exit(1);
|
|
|
|
}
|
2019-01-03 21:29:21 -08:00
|
|
|
};
|
2018-09-26 18:37:24 -07:00
|
|
|
|
2019-07-11 20:33:36 -07:00
|
|
|
let starting_slot = value_t!(matches, "starting_slot", u64).unwrap_or_else(|e| e.exit());
|
2018-12-07 20:44:59 -08:00
|
|
|
|
2018-08-06 16:03:08 -07:00
|
|
|
match matches.subcommand() {
|
|
|
|
("print", _) => {
|
2019-07-11 20:33:36 -07:00
|
|
|
output_ledger(blocktree, starting_slot, LedgerOutputMethod::Print);
|
2018-08-09 22:14:04 -07:00
|
|
|
}
|
|
|
|
("json", _) => {
|
2019-07-11 20:33:36 -07:00
|
|
|
output_ledger(blocktree, starting_slot, LedgerOutputMethod::Json);
|
|
|
|
}
|
|
|
|
("verify", _) => {
|
|
|
|
println!("Verifying ledger...");
|
|
|
|
match process_blocktree(&genesis_block, &blocktree, None) {
|
|
|
|
Ok((_bank_forks, bank_forks_info, _)) => {
|
|
|
|
println!("{:?}", bank_forks_info);
|
2018-08-09 22:14:04 -07:00
|
|
|
}
|
2019-07-11 20:33:36 -07:00
|
|
|
Err(err) => {
|
|
|
|
eprintln!("Ledger verification failed: {:?}", err);
|
|
|
|
exit(1);
|
2018-12-07 20:44:59 -08: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
|
|
|
}
|