From 899bd1572a804fbb6870402c7a9f6636a6984469 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 16 Mar 2021 10:43:06 +0000 Subject: [PATCH] Show flags for accounts in tx by solana confirm (#15804) (#15906) * Show flags for accounts in tx by solana confirm * Address review comments * Improve comment a bit * Apply suggestions from code review Co-authored-by: Tyera Eulberg * Further apply review suggestions Co-authored-by: Tyera Eulberg (cherry picked from commit 74aa32175bfe50180a601ae0b02f8f833fd78567) Co-authored-by: Ryo Onodera --- cli-output/src/display.rs | 48 ++++++++++++++++++++++++++++++++++---- cli/src/cli.rs | 11 +++++++++ sdk/program/src/message.rs | 4 ++++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/cli-output/src/display.rs b/cli-output/src/display.rs index 0eb2f34301..fdcf7e9e18 100644 --- a/cli-output/src/display.rs +++ b/cli-output/src/display.rs @@ -4,7 +4,7 @@ use { console::style, indicatif::{ProgressBar, ProgressStyle}, solana_sdk::{ - clock::UnixTimestamp, hash::Hash, native_token::lamports_to_sol, + clock::UnixTimestamp, hash::Hash, message::Message, native_token::lamports_to_sol, program_utils::limited_deserialize, transaction::Transaction, }, solana_transaction_status::UiTransactionStatusMeta, @@ -125,6 +125,31 @@ pub fn println_signers( println!(); } +fn format_account_mode(message: &Message, index: usize) -> String { + format!( + "{}r{}{}", // accounts are always readable... + if message.is_signer(index) { + "s" // stands for signer + } else { + "-" + }, + if message.is_writable(index) { + "w" // comment for consistent rust fmt (no joking; lol) + } else { + "-" + }, + // account may be executable on-chain while not being + // designated as a program-id in the message + if message.maybe_executable(index) { + "x" + } else { + // programs to be executed via CPI cannot be identified as + // executable from the message + "-" + }, + ) +} + pub fn write_transaction( w: &mut W, transaction: &Transaction, @@ -167,16 +192,31 @@ pub fn write_transaction( prefix, signature_index, signature, sigverify_status, )?; } - writeln!(w, "{}{:?}", prefix, message.header)?; + let mut fee_payer_index = None; for (account_index, account) in message.account_keys.iter().enumerate() { - writeln!(w, "{}Account {}: {:?}", prefix, account_index, account)?; + if fee_payer_index.is_none() && message.is_non_loader_key(account, account_index) { + fee_payer_index = Some(account_index) + } + writeln!( + w, + "{}Account {}: {} {}{}", + prefix, + account_index, + format_account_mode(message, account_index), + account, + if Some(account_index) == fee_payer_index { + " (fee payer)" + } else { + "" + }, + )?; } for (instruction_index, instruction) in message.instructions.iter().enumerate() { let program_pubkey = message.account_keys[instruction.program_id_index as usize]; writeln!(w, "{}Instruction {}", prefix, instruction_index)?; writeln!( w, - "{} Program: {} ({})", + "{} Program: {} ({})", prefix, program_pubkey, instruction.program_id_index )?; for (account_index, account) in instruction.accounts.iter().enumerate() { diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 599df37e6b..d84a8a6682 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -1987,6 +1987,17 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .takes_value(true) .required(true) .help("The transaction signature to confirm"), + ) + .after_help(// Formatted specifically for the manually-indented heredoc string + "Note: This will show more detailed information for finalized transactions with verbose mode (-v/--verbose).\ + \n\ + \nAccount modes:\ + \n |srwx|\ + \n s: signed\ + \n r: readable (always true)\ + \n w: writable\ + \n x: program account (inner instructions excluded)\ + " ), ) .subcommand( diff --git a/sdk/program/src/message.rs b/sdk/program/src/message.rs index b9afc2311a..ade4f12708 100644 --- a/sdk/program/src/message.rs +++ b/sdk/program/src/message.rs @@ -319,6 +319,10 @@ impl Message { .position(|&&pubkey| pubkey == self.account_keys[index]) } + pub fn maybe_executable(&self, i: usize) -> bool { + self.program_position(i).is_some() + } + pub fn is_writable(&self, i: usize) -> bool { i < (self.header.num_required_signatures - self.header.num_readonly_signed_accounts) as usize