* cli-output: Add option sigverify status to `println_transaction()` output (cherry picked from commita2aea0ca33
) * cli: Add sigverify status to `decode-transaction` output (cherry picked from commitd547585041
) * CLI: Modernize `decode-transaction` about message (cherry picked from commitfddbfe1052
) Co-authored-by: Trent Nelson <trent@solana.com>
This commit is contained in:
@ -1563,6 +1563,37 @@ pub fn parse_sign_only_reply_string(reply: &str) -> SignOnly {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum CliSignatureVerificationStatus {
|
||||||
|
None,
|
||||||
|
Pass,
|
||||||
|
Fail,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CliSignatureVerificationStatus {
|
||||||
|
pub fn verify_transaction(tx: &Transaction) -> Vec<Self> {
|
||||||
|
tx.verify_with_results()
|
||||||
|
.iter()
|
||||||
|
.zip(&tx.signatures)
|
||||||
|
.map(|(stat, sig)| match stat {
|
||||||
|
true => CliSignatureVerificationStatus::Pass,
|
||||||
|
false if sig == &Signature::default() => CliSignatureVerificationStatus::None,
|
||||||
|
false => CliSignatureVerificationStatus::Fail,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for CliSignatureVerificationStatus {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::None => write!(f, "none"),
|
||||||
|
Self::Pass => write!(f, "pass"),
|
||||||
|
Self::Fail => write!(f, "fail"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::cli_output::CliSignatureVerificationStatus;
|
||||||
use console::style;
|
use console::style;
|
||||||
use indicatif::{ProgressBar, ProgressStyle};
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
@ -126,6 +127,7 @@ pub fn write_transaction<W: io::Write>(
|
|||||||
transaction: &Transaction,
|
transaction: &Transaction,
|
||||||
transaction_status: &Option<UiTransactionStatusMeta>,
|
transaction_status: &Option<UiTransactionStatusMeta>,
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
|
sigverify_status: Option<&[CliSignatureVerificationStatus]>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let message = &transaction.message;
|
let message = &transaction.message;
|
||||||
writeln!(
|
writeln!(
|
||||||
@ -133,11 +135,24 @@ pub fn write_transaction<W: io::Write>(
|
|||||||
"{}Recent Blockhash: {:?}",
|
"{}Recent Blockhash: {:?}",
|
||||||
prefix, message.recent_blockhash
|
prefix, message.recent_blockhash
|
||||||
)?;
|
)?;
|
||||||
for (signature_index, signature) in transaction.signatures.iter().enumerate() {
|
let sigverify_statuses = if let Some(sigverify_status) = sigverify_status {
|
||||||
|
sigverify_status
|
||||||
|
.iter()
|
||||||
|
.map(|s| format!(" ({})", s))
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
vec!["".to_string(); transaction.signatures.len()]
|
||||||
|
};
|
||||||
|
for (signature_index, (signature, sigverify_status)) in transaction
|
||||||
|
.signatures
|
||||||
|
.iter()
|
||||||
|
.zip(&sigverify_statuses)
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
writeln!(
|
writeln!(
|
||||||
w,
|
w,
|
||||||
"{}Signature {}: {:?}",
|
"{}Signature {}: {:?}{}",
|
||||||
prefix, signature_index, signature
|
prefix, signature_index, signature, sigverify_status,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
writeln!(w, "{}{:?}", prefix, message.header)?;
|
writeln!(w, "{}{:?}", prefix, message.header)?;
|
||||||
@ -258,9 +273,18 @@ pub fn println_transaction(
|
|||||||
transaction: &Transaction,
|
transaction: &Transaction,
|
||||||
transaction_status: &Option<UiTransactionStatusMeta>,
|
transaction_status: &Option<UiTransactionStatusMeta>,
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
|
sigverify_status: Option<&[CliSignatureVerificationStatus]>,
|
||||||
) {
|
) {
|
||||||
let mut w = Vec::new();
|
let mut w = Vec::new();
|
||||||
if write_transaction(&mut w, transaction, transaction_status, prefix).is_ok() {
|
if write_transaction(
|
||||||
|
&mut w,
|
||||||
|
transaction,
|
||||||
|
transaction_status,
|
||||||
|
prefix,
|
||||||
|
sigverify_status,
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
if let Ok(s) = String::from_utf8(w) {
|
if let Ok(s) = String::from_utf8(w) {
|
||||||
print!("{}", s);
|
print!("{}", s);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ use solana_clap_utils::{
|
|||||||
};
|
};
|
||||||
use solana_cli_output::{
|
use solana_cli_output::{
|
||||||
display::{build_balance_message, println_name_value, println_transaction},
|
display::{build_balance_message, println_name_value, println_transaction},
|
||||||
return_signers, CliAccount, CliSignature, OutputFormat,
|
return_signers, CliAccount, CliSignature, CliSignatureVerificationStatus, OutputFormat,
|
||||||
};
|
};
|
||||||
use solana_client::{
|
use solana_client::{
|
||||||
blockhash_query::BlockhashQuery,
|
blockhash_query::BlockhashQuery,
|
||||||
@ -1011,6 +1011,7 @@ fn process_confirm(
|
|||||||
.expect("Successful decode"),
|
.expect("Successful decode"),
|
||||||
&confirmed_transaction.transaction.meta,
|
&confirmed_transaction.transaction.meta,
|
||||||
" ",
|
" ",
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@ -1043,7 +1044,8 @@ fn process_confirm(
|
|||||||
|
|
||||||
#[allow(clippy::unnecessary_wraps)]
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
fn process_decode_transaction(transaction: &Transaction) -> ProcessResult {
|
fn process_decode_transaction(transaction: &Transaction) -> ProcessResult {
|
||||||
println_transaction(transaction, &None, "");
|
let sig_stats = CliSignatureVerificationStatus::verify_transaction(&transaction);
|
||||||
|
println_transaction(transaction, &None, "", Some(&sig_stats));
|
||||||
Ok("".to_string())
|
Ok("".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1932,7 +1934,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
|
|||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("decode-transaction")
|
SubCommand::with_name("decode-transaction")
|
||||||
.about("Decode a base-58 binary transaction")
|
.about("Decode a serialized transaction")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("transaction")
|
Arg::with_name("transaction")
|
||||||
.index(1)
|
.index(1)
|
||||||
|
@ -967,6 +967,7 @@ pub fn process_get_block(
|
|||||||
&transaction_with_meta.transaction.decode().unwrap(),
|
&transaction_with_meta.transaction.decode().unwrap(),
|
||||||
&transaction_with_meta.meta,
|
&transaction_with_meta.meta,
|
||||||
" ",
|
" ",
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok("".to_string())
|
Ok("".to_string())
|
||||||
@ -1840,6 +1841,7 @@ pub fn process_transaction_history(
|
|||||||
.expect("Successful decode"),
|
.expect("Successful decode"),
|
||||||
&confirmed_transaction.transaction.meta,
|
&confirmed_transaction.transaction.meta,
|
||||||
" ",
|
" ",
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(err) => println!(" Unable to get confirmed transaction details: {}", err),
|
Err(err) => println!(" Unable to get confirmed transaction details: {}", err),
|
||||||
|
@ -69,6 +69,7 @@ async fn block(slot: Slot) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
&transaction_with_meta.transaction,
|
&transaction_with_meta.transaction,
|
||||||
&transaction_with_meta.meta.map(|meta| meta.into()),
|
&transaction_with_meta.meta.map(|meta| meta.into()),
|
||||||
" ",
|
" ",
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -104,6 +105,7 @@ async fn confirm(signature: &Signature, verbose: bool) -> Result<(), Box<dyn std
|
|||||||
&confirmed_transaction.transaction.transaction,
|
&confirmed_transaction.transaction.transaction,
|
||||||
&confirmed_transaction.transaction.meta.map(|m| m.into()),
|
&confirmed_transaction.transaction.meta.map(|m| m.into()),
|
||||||
" ",
|
" ",
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok(None) => println!("Finalized transaction details not available"),
|
Ok(None) => println!("Finalized transaction details not available"),
|
||||||
@ -183,6 +185,7 @@ pub async fn transaction_history(
|
|||||||
&transaction_with_meta.transaction,
|
&transaction_with_meta.transaction,
|
||||||
&transaction_with_meta.meta.clone().map(|m| m.into()),
|
&transaction_with_meta.meta.clone().map(|m| m.into()),
|
||||||
" ",
|
" ",
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,7 @@ fn output_entry(
|
|||||||
&transaction,
|
&transaction,
|
||||||
&transaction_status,
|
&transaction_status,
|
||||||
" ",
|
" ",
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,7 +387,7 @@ fn print_confirmed_tx(name: &str, confirmed_tx: ConfirmedTransaction) {
|
|||||||
let tx = confirmed_tx.transaction.transaction.clone();
|
let tx = confirmed_tx.transaction.transaction.clone();
|
||||||
let encoded = confirmed_tx.encode(UiTransactionEncoding::JsonParsed);
|
let encoded = confirmed_tx.encode(UiTransactionEncoding::JsonParsed);
|
||||||
println!("EXECUTE {} (slot {})", name, encoded.slot);
|
println!("EXECUTE {} (slot {})", name, encoded.slot);
|
||||||
println_transaction(&tx, &encoded.transaction.meta, " ");
|
println_transaction(&tx, &encoded.transaction.meta, " ", None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Reference in New Issue
Block a user