feat: decode_microblocks subcommand to blockstack-cli

This commit is contained in:
Jude Nelson
2022-12-28 21:33:23 -05:00
parent b1635b81f8
commit 9b8c1668c1

View File

@@ -72,6 +72,7 @@ This CLI has these methods:
decode-header used to decode a hex-encoded Stacks header into a human-readable representation
decode-block used to decode a hex-encoded Stacks block into a human-readable representation
decode-microblock used to decode a hex-encoded Stacks microblock into a human-readable representation
decode-microblocks used to decode a hex-encoded stream of Stacks microblocks into a human-readable representation
For usage information on those methods, call `blockstack-cli [method] -h`
@@ -174,6 +175,15 @@ raw binary microblock will be read from stdin.
N.B. Stacks microblocks are not stored as files in the Stacks chainstate -- they are stored in
block's sqlite database.";
const DECODE_MICROBLOCKS_USAGE: &str = "blockstack-cli (options) decode-microblocks [microblocks-path-or-stdin]
The decode-microblocks command decodes a serialized list of Stacks microblocks and prints it to stdout as JSON.
The microblocks, if given, must be a hex string. Alternatively, you may pass `-` instead, and the
raw binary microblocks will be read from stdin.
N.B. Stacks microblocks are not stored as files in the Stacks chainstate -- they are stored in
block's sqlite database.";
#[derive(Debug)]
enum CliError {
ClarityRuntimeError(RuntimeErrorType),
@@ -787,6 +797,45 @@ fn decode_microblock(args: &[String], _version: TransactionVersion) -> Result<St
}
}
fn decode_microblocks(args: &[String], _version: TransactionVersion) -> Result<String, CliError> {
if (args.len() >= 1 && args[0] == "-h") || args.len() != 1 {
return Err(CliError::Message(format!(
"Usage: {}\n",
DECODE_MICROBLOCKS_USAGE
)));
}
let mblock_data = if args[0] == "-" {
// read from stdin
let mut block_str = Vec::new();
io::stdin()
.read_to_end(&mut block_str)
.expect("Failed to read block from stdin");
block_str
} else {
// given as a command-line arg
hex_bytes(&args[0].clone()).expect("Failed to decode microblock: must be a hex string")
};
let mut cursor = io::Cursor::new(&mblock_data);
let mut debug_cursor = LogReader::from_reader(&mut cursor);
match Vec::<StacksMicroblock>::consensus_deserialize(&mut debug_cursor) {
Ok(blocks) => {
Ok(serde_json::to_string(&blocks).expect("Failed to serialize microblock to JSON"))
}
Err(e) => {
let mut ret = String::new();
ret.push_str(&format!("Failed to decode microblocks: {:?}\n", &e));
ret.push_str("Bytes consumed:\n");
for buf in debug_cursor.log().iter() {
ret.push_str(&format!(" {}\n", to_hex(buf)));
}
ret.push_str("\n");
Ok(ret)
}
}
}
fn main() {
let mut argv: Vec<String> = env::args().collect();
@@ -830,6 +879,7 @@ fn main_handler(mut argv: Vec<String>) -> Result<String, CliError> {
"decode-header" => decode_header(args, tx_version),
"decode-block" => decode_block(args, tx_version),
"decode-microblock" => decode_microblock(args, tx_version),
"decode-microblocks" => decode_microblocks(args, tx_version),
_ => Err(CliError::Usage),
}
} else {