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