-
Notifications
You must be signed in to change notification settings - Fork 723
feat: add file support to stacks-inspect commands #6776
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 8 commits
4f30c3c
78e9e6e
41448cb
bee86f5
ecb56c7
740dfdb
b54e121
0dff765
37a8438
f3e1c52
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,7 +19,7 @@ extern crate stacks_common; | |
| use clarity::consts::CHAIN_ID_MAINNET; | ||
| use clarity::types::StacksEpochId; | ||
| use clarity::types::chainstate::StacksPrivateKey; | ||
| use clarity_cli::DEFAULT_CLI_EPOCH; | ||
| use clarity_cli::{DEFAULT_CLI_EPOCH, read_file_or_stdin, read_file_or_stdin_bytes}; | ||
| use stacks_inspect::{ | ||
| command_contract_hash, command_replay_mock_mining, command_try_mine, command_validate_block, | ||
| command_validate_block_nakamoto, drain_common_opts, | ||
|
|
@@ -394,12 +394,21 @@ fn main() { | |
|
|
||
| if argv[1] == "decode-tx" { | ||
| if argv.len() < 3 { | ||
| eprintln!("Usage: {} decode-tx TRANSACTION", argv[0]); | ||
| eprintln!( | ||
| "Usage: {} decode-tx <TX_HEX | TX_FILE | - (stdin)>", | ||
| argv[0] | ||
| ); | ||
| process::exit(1); | ||
| } | ||
|
|
||
| let tx_str = &argv[2]; | ||
| let tx_bytes = hex_bytes(tx_str) | ||
| let tx_arg = &argv[2]; | ||
| let tx_str = if tx_arg == "-" || std::path::Path::new(tx_arg).exists() { | ||
| read_file_or_stdin(tx_arg).trim().to_string() | ||
| } else { | ||
| // Treat as hex string directly | ||
| tx_arg.clone() | ||
| }; | ||
| let tx_bytes = hex_bytes(&tx_str) | ||
| .map_err(|_e| { | ||
| eprintln!("Failed to decode transaction: must be a hex string"); | ||
| process::exit(1); | ||
|
|
@@ -430,13 +439,12 @@ fn main() { | |
|
|
||
| if argv[1] == "decode-block" { | ||
| if argv.len() < 3 { | ||
| eprintln!("Usage: {} decode-block BLOCK_PATH", argv[0]); | ||
| eprintln!("Usage: {} decode-block <BLOCK_PATH | - (stdin)>", argv[0]); | ||
| process::exit(1); | ||
| } | ||
|
|
||
| let block_path = &argv[2]; | ||
| let block_data = | ||
| fs::read(block_path).unwrap_or_else(|_| panic!("Failed to open {block_path}")); | ||
| let block_data = read_file_or_stdin_bytes(block_path); | ||
|
|
||
| let block = StacksBlock::consensus_deserialize(&mut io::Cursor::new(&block_data)) | ||
| .map_err(|_e| { | ||
|
|
@@ -451,12 +459,21 @@ fn main() { | |
|
|
||
| if argv[1] == "decode-nakamoto-block" { | ||
| if argv.len() < 3 { | ||
| eprintln!("Usage: {} decode-nakamoto-block BLOCK_HEX", argv[0]); | ||
| eprintln!( | ||
| "Usage: {} decode-nakamoto-block <BLOCK_HEX | HEX_FILE | - (stdin)>", | ||
| argv[0] | ||
| ); | ||
| process::exit(1); | ||
| } | ||
|
|
||
| let block_hex = &argv[2]; | ||
| let block_data = hex_bytes(block_hex).unwrap_or_else(|_| panic!("Failed to decode hex")); | ||
| let block_arg = &argv[2]; | ||
| let block_hex = if block_arg == "-" || std::path::Path::new(block_arg).exists() { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This approach of making the "value or filename" decision based on whether a file of said name exists feels off to me, I don't think I've ever seen that. Do you know of any precedent for this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that's a good point, you're right that this pattern is uncommon. My reasoning was:
But I totally understand the concern and "extremely unlikely" is not something that I totally love either. Do you think I should add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You probably wouldn't need both -- if the default (backwards-compatible) behavior is a direct value, then you just need would be the value would refer to a file named This does feel cleaner to me, but you have more intuition on the practical uses of this.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that's definitely cleaner! Since I'm working on the refactoring of |
||
| read_file_or_stdin(block_arg).trim().to_string() | ||
| } else { | ||
| // Treat as hex string directly | ||
| block_arg.clone() | ||
| }; | ||
| let block_data = hex_bytes(&block_hex).unwrap_or_else(|_| panic!("Failed to decode hex")); | ||
| let block = NakamotoBlock::consensus_deserialize(&mut io::Cursor::new(&block_data)) | ||
| .map_err(|_e| { | ||
| eprintln!("Failed to decode block"); | ||
|
|
@@ -470,11 +487,10 @@ fn main() { | |
|
|
||
| if argv[1] == "decode-net-message" { | ||
| let data: String = argv[2].clone(); | ||
| let buf = if data == "-" { | ||
| let mut buffer = vec![]; | ||
| io::stdin().read_to_end(&mut buffer).unwrap(); | ||
| buffer | ||
| let buf = if data == "-" || std::path::Path::new(&data).exists() { | ||
| read_file_or_stdin_bytes(&data) | ||
| } else { | ||
| // Parse as JSON array of bytes | ||
| let data: serde_json::Value = serde_json::from_str(data.as_str()).unwrap(); | ||
| let data_array = data.as_array().unwrap(); | ||
| let mut buf = vec![]; | ||
|
|
@@ -804,15 +820,14 @@ check if the associated microblocks can be downloaded | |
| if argv[1] == "decode-microblocks" { | ||
| if argv.len() < 3 { | ||
| eprintln!( | ||
| "Usage: {} decode-microblocks MICROBLOCK_STREAM_PATH", | ||
| "Usage: {} decode-microblocks <MICROBLOCK_STREAM_PATH | - (stdin)>", | ||
| argv[0] | ||
| ); | ||
| process::exit(1); | ||
| } | ||
|
|
||
| let mblock_path = &argv[2]; | ||
| let mblock_data = | ||
| fs::read(mblock_path).unwrap_or_else(|_| panic!("Failed to open {mblock_path}")); | ||
| let mblock_data = read_file_or_stdin_bytes(mblock_path); | ||
|
|
||
| let mut cursor = io::Cursor::new(&mblock_data); | ||
| let mut debug_cursor = LogReader::from_reader(&mut cursor); | ||
|
|
@@ -1028,7 +1043,7 @@ check if the associated microblocks can be downloaded | |
| if argv[1] == "post-stackerdb" { | ||
| if argv.len() < 4 { | ||
| eprintln!( | ||
| "Usage: {} post-stackerdb slot_id slot_version privkey data", | ||
| "Usage: {} post-stackerdb slot_id slot_version privkey <DATA | DATA_FILE | - (stdin)>", | ||
| &argv[0] | ||
| ); | ||
| process::exit(1); | ||
|
|
@@ -1038,11 +1053,10 @@ check if the associated microblocks can be downloaded | |
| let privkey: String = argv[4].clone(); | ||
| let data: String = argv[5].clone(); | ||
|
|
||
| let buf = if data == "-" { | ||
| let mut buffer = vec![]; | ||
| io::stdin().read_to_end(&mut buffer).unwrap(); | ||
| buffer | ||
| let buf = if data == "-" || std::path::Path::new(&data).exists() { | ||
| read_file_or_stdin_bytes(&data) | ||
| } else { | ||
| // Use the argument directly as data | ||
| data.as_bytes().to_vec() | ||
| }; | ||
|
|
||
|
|
@@ -1221,7 +1235,7 @@ check if the associated microblocks can be downloaded | |
| if argv[1] == "shadow-chainstate-patch" { | ||
| if argv.len() < 5 { | ||
| eprintln!( | ||
| "Usage: {} shadow-chainstate-patch CHAINSTATE_DIR NETWORK SHADOW_BLOCKS_PATH.JSON", | ||
| "Usage: {} shadow-chainstate-patch CHAINSTATE_DIR NETWORK <SHADOW_BLOCKS.JSON | - (stdin)>", | ||
| &argv[0] | ||
| ); | ||
| process::exit(1); | ||
|
|
@@ -1232,10 +1246,7 @@ check if the associated microblocks can be downloaded | |
| let shadow_blocks_json_path = argv[4].as_str(); | ||
|
|
||
| let shadow_blocks_hex = { | ||
| let mut blocks_json_file = | ||
| File::open(shadow_blocks_json_path).expect("Unable to open file"); | ||
| let mut buffer = vec![]; | ||
| blocks_json_file.read_to_end(&mut buffer).unwrap(); | ||
| let buffer = read_file_or_stdin_bytes(shadow_blocks_json_path); | ||
| let shadow_blocks_hex: Vec<String> = serde_json::from_slice(&buffer).unwrap(); | ||
| shadow_blocks_hex | ||
| }; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
Nonecould defer to-handling instead of duplicating the logicThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
100% agree!