From 7af48465faac3bb2d7bc4d92ff86e8227a9dc3b4 Mon Sep 17 00:00:00 2001 From: Jon Cinque Date: Tue, 22 Mar 2022 23:17:05 +0100 Subject: [PATCH] transaction-status: Add return data to meta (#23688) * transaction-status: Add return data to meta * Add return data to simulation results * Use pretty-hex for printing return data * Update arg name, make TransactionRecord struct * Rename TransactionRecord -> ExecutionRecord --- Cargo.lock | 2 + banks-client/src/error.rs | 6 +- banks-client/src/lib.rs | 1 + banks-interface/src/lib.rs | 2 + banks-server/src/banks_server.rs | 2 + cli-output/Cargo.toml | 1 + cli-output/src/display.rs | 35 ++++++ client/src/mock_sender.rs | 2 + client/src/rpc_response.rs | 2 + core/src/banking_stage.rs | 2 + core/src/validator.rs | 6 +- ledger/src/blockstore.rs | 34 +++++ ledger/src/blockstore_processor.rs | 2 + multinode-demo/bootstrap-validator.sh | 3 + multinode-demo/validator.sh | 3 + net/remote/remote-node.sh | 4 +- program-test/Cargo.toml | 1 + program-test/tests/return_data.rs | 57 +++++++++ programs/bpf/Cargo.lock | 8 ++ programs/bpf/tests/programs.rs | 4 + rpc/src/rpc.rs | 13 +- rpc/src/transaction_status_service.rs | 13 +- runtime/src/accounts.rs | 1 + runtime/src/bank.rs | 138 +++++++++++++++++++-- scripts/run.sh | 2 +- sdk/src/transaction_context.rs | 54 +++++--- storage-bigtable/src/bigtable.rs | 4 +- storage-bigtable/src/lib.rs | 1 + storage-proto/proto/confirmed_block.proto | 7 ++ storage-proto/src/convert.rs | 32 +++++ storage-proto/src/lib.rs | 7 ++ transaction-status/src/lib.rs | 6 + validator/src/bin/solana-test-validator.rs | 2 +- validator/src/main.rs | 27 +++- 34 files changed, 439 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9721b090d..e7e0911d5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4424,6 +4424,7 @@ dependencies = [ "ed25519-dalek", "humantime", "indicatif", + "pretty-hex", "serde", "serde_json", "solana-account-decoder", @@ -5309,6 +5310,7 @@ dependencies = [ name = "solana-program-test" version = "1.11.0" dependencies = [ + "assert_matches", "async-trait", "base64 0.13.0", "bincode", diff --git a/banks-client/src/error.rs b/banks-client/src/error.rs index 6f27f3ce5f..3767a0c46d 100644 --- a/banks-client/src/error.rs +++ b/banks-client/src/error.rs @@ -1,5 +1,8 @@ use { - solana_sdk::{transaction::TransactionError, transport::TransportError}, + solana_sdk::{ + transaction::TransactionError, transaction_context::TransactionReturnData, + transport::TransportError, + }, std::io, tarpc::client::RpcError, thiserror::Error, @@ -25,6 +28,7 @@ pub enum BanksClientError { err: TransactionError, logs: Vec, units_consumed: u64, + return_data: Option, }, } diff --git a/banks-client/src/lib.rs b/banks-client/src/lib.rs index cb3b053731..6af3383208 100644 --- a/banks-client/src/lib.rs +++ b/banks-client/src/lib.rs @@ -247,6 +247,7 @@ impl BanksClient { err, logs: simulation_details.logs, units_consumed: simulation_details.units_consumed, + return_data: simulation_details.return_data, }), BanksTransactionResultWithSimulation { result: Some(result), diff --git a/banks-interface/src/lib.rs b/banks-interface/src/lib.rs index 597cf60167..d8ca61978d 100644 --- a/banks-interface/src/lib.rs +++ b/banks-interface/src/lib.rs @@ -12,6 +12,7 @@ use { pubkey::Pubkey, signature::Signature, transaction::{self, Transaction, TransactionError}, + transaction_context::TransactionReturnData, }, }; @@ -35,6 +36,7 @@ pub struct TransactionStatus { pub struct TransactionSimulationDetails { pub logs: Vec, pub units_consumed: u64, + pub return_data: Option, } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] diff --git a/banks-server/src/banks_server.rs b/banks-server/src/banks_server.rs index 8664b7e61e..a2a33023f9 100644 --- a/banks-server/src/banks_server.rs +++ b/banks-server/src/banks_server.rs @@ -266,6 +266,7 @@ impl Banks for BanksServer { logs, post_simulation_accounts: _, units_consumed, + return_data, } = self .bank(commitment) .simulate_transaction_unchecked(sanitized_transaction) @@ -275,6 +276,7 @@ impl Banks for BanksServer { simulation_details: Some(TransactionSimulationDetails { logs, units_consumed, + return_data, }), }; } diff --git a/cli-output/Cargo.toml b/cli-output/Cargo.toml index c9f2d52c6e..126dfc05a2 100644 --- a/cli-output/Cargo.toml +++ b/cli-output/Cargo.toml @@ -17,6 +17,7 @@ clap = "2.33.0" console = "0.15.0" humantime = "2.0.1" indicatif = "0.16.2" +pretty-hex = "0.2.1" serde = "1.0.136" serde_json = "1.0.79" solana-account-decoder = { path = "../account-decoder", version = "=1.11.0" } diff --git a/cli-output/src/display.rs b/cli-output/src/display.rs index 52ae71ccc2..430fdeed2e 100644 --- a/cli-output/src/display.rs +++ b/cli-output/src/display.rs @@ -14,6 +14,7 @@ use { signature::Signature, stake, transaction::{TransactionError, TransactionVersion, VersionedTransaction}, + transaction_context::TransactionReturnData, }, solana_transaction_status::{Rewards, UiTransactionStatusMeta}, spl_memo::{id as spl_memo_id, v1::id as spl_memo_v1_id}, @@ -246,6 +247,7 @@ fn write_transaction( write_fees(w, transaction_status.fee, prefix)?; write_balances(w, transaction_status, prefix)?; write_log_messages(w, transaction_status.log_messages.as_ref(), prefix)?; + write_return_data(w, transaction_status.return_data.as_ref(), prefix)?; write_rewards(w, transaction_status.rewards.as_ref(), prefix)?; } else { writeln!(w, "{}Status: Unavailable", prefix)?; @@ -576,6 +578,25 @@ fn write_balances( Ok(()) } +fn write_return_data( + w: &mut W, + return_data: Option<&TransactionReturnData>, + prefix: &str, +) -> io::Result<()> { + if let Some(return_data) = return_data { + if !return_data.data.is_empty() { + use pretty_hex::*; + writeln!( + w, + "{}Return Data from Program {}:", + prefix, return_data.program_id + )?; + writeln!(w, "{} {:?}", prefix, return_data.data.hex_dump())?; + } + } + Ok(()) +} + fn write_log_messages( w: &mut W, log_messages: Option<&Vec>, @@ -750,6 +771,10 @@ mod test { commission: None, }]), loaded_addresses: LoadedAddresses::default(), + return_data: Some(TransactionReturnData { + program_id: Pubkey::new_from_array([2u8; 32]), + data: vec![1, 2, 3], + }), }; let output = { @@ -786,6 +811,9 @@ Status: Ok Account 1 balance: ◎0.00001 -> ◎0.0000099 Log Messages: Test message +Return Data from Program 8qbHbw2BbbTHBW1sbeqakYXVKRQM8Ne7pLK7m6CVfeR: + Length: 3 (0x3) bytes +0000: 01 02 03 ... Rewards: Address Type Amount New Balance \0 4vJ9JU1bJJE96FWSJKvHsmmFADCg4gpZQff4P3bkLKi rent -◎0.000000100 ◎0.000009900 \0 @@ -820,6 +848,10 @@ Rewards: commission: None, }]), loaded_addresses, + return_data: Some(TransactionReturnData { + program_id: Pubkey::new_from_array([2u8; 32]), + data: vec![1, 2, 3], + }), }; let output = { @@ -865,6 +897,9 @@ Status: Ok Account 3 balance: ◎0.00002 Log Messages: Test message +Return Data from Program 8qbHbw2BbbTHBW1sbeqakYXVKRQM8Ne7pLK7m6CVfeR: + Length: 3 (0x3) bytes +0000: 01 02 03 ... Rewards: Address Type Amount New Balance \0 CktRuQ2mttgRGkXJtyksdKHjUdc2C4TgDzyB98oEzy8 rent -◎0.000000100 ◎0.000014900 \0 diff --git a/client/src/mock_sender.rs b/client/src/mock_sender.rs index 3b6c0856df..218d7cca50 100644 --- a/client/src/mock_sender.rs +++ b/client/src/mock_sender.rs @@ -229,6 +229,7 @@ impl RpcSender for MockSender { post_token_balances: None, rewards: None, loaded_addresses: None, + return_data: None, }), }, block_time: Some(1628633791), @@ -340,6 +341,7 @@ impl RpcSender for MockSender { logs: None, accounts: None, units_consumed: None, + return_data: None, }, })?, "getMinimumBalanceForRentExemption" => json![20], diff --git a/client/src/rpc_response.rs b/client/src/rpc_response.rs index 78a79a8672..885cec85b5 100644 --- a/client/src/rpc_response.rs +++ b/client/src/rpc_response.rs @@ -7,6 +7,7 @@ use { hash::Hash, inflation::Inflation, transaction::{Result, TransactionError}, + transaction_context::TransactionReturnData, }, solana_transaction_status::{ ConfirmedTransactionStatusWithSignature, TransactionConfirmationStatus, UiConfirmedBlock, @@ -347,6 +348,7 @@ pub struct RpcSimulateTransactionResult { pub logs: Option>, pub accounts: Option>>, pub units_consumed: Option, + pub return_data: Option, } #[derive(Serialize, Deserialize, Clone, Debug)] diff --git a/core/src/banking_stage.rs b/core/src/banking_stage.rs index 590231de2d..9e78cc4183 100644 --- a/core/src/banking_stage.rs +++ b/core/src/banking_stage.rs @@ -1180,6 +1180,7 @@ impl BankingStage { MAX_PROCESSING_AGE, transaction_status_sender.is_some(), transaction_status_sender.is_some(), + transaction_status_sender.is_some(), &mut execute_and_commit_timings.execute_timings, ) }, @@ -2149,6 +2150,7 @@ mod tests { log_messages: None, inner_instructions: None, durable_nonce_fee: None, + return_data: None, }) } diff --git a/core/src/validator.rs b/core/src/validator.rs index 63a9ac061c..7726c4db39 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -1331,7 +1331,7 @@ fn load_blockstore( blockstore.clone(), exit, enable_rpc_transaction_history, - config.rpc_config.enable_cpi_and_log_storage, + config.rpc_config.enable_extended_tx_metadata_storage, transaction_notifier, ) } else { @@ -1538,7 +1538,7 @@ fn initialize_rpc_transaction_history_services( blockstore: Arc, exit: &Arc, enable_rpc_transaction_history: bool, - enable_cpi_and_log_storage: bool, + enable_extended_tx_metadata_storage: bool, transaction_notifier: Option, ) -> TransactionHistoryServices { let max_complete_transaction_status_slot = Arc::new(AtomicU64::new(blockstore.max_root())); @@ -1552,7 +1552,7 @@ fn initialize_rpc_transaction_history_services( enable_rpc_transaction_history, transaction_notifier.clone(), blockstore.clone(), - enable_cpi_and_log_storage, + enable_extended_tx_metadata_storage, exit, )); diff --git a/ledger/src/blockstore.rs b/ledger/src/blockstore.rs index e70b45196d..870221e75f 100644 --- a/ledger/src/blockstore.rs +++ b/ledger/src/blockstore.rs @@ -4697,6 +4697,7 @@ pub mod tests { pubkey::Pubkey, signature::Signature, transaction::{Transaction, TransactionError}, + transaction_context::TransactionReturnData, }, solana_storage_proto::convert::generated, solana_transaction_status::{InnerInstructions, Reward, Rewards, TransactionTokenBalance}, @@ -6858,6 +6859,7 @@ pub mod tests { post_token_balances: Some(vec![]), rewards: Some(vec![]), loaded_addresses: LoadedAddresses::default(), + return_data: Some(TransactionReturnData::default()), } .into(); blockstore @@ -6875,6 +6877,7 @@ pub mod tests { post_token_balances: Some(vec![]), rewards: Some(vec![]), loaded_addresses: LoadedAddresses::default(), + return_data: Some(TransactionReturnData::default()), } .into(); blockstore @@ -6892,6 +6895,7 @@ pub mod tests { post_token_balances: Some(vec![]), rewards: Some(vec![]), loaded_addresses: LoadedAddresses::default(), + return_data: Some(TransactionReturnData::default()), } .into(); blockstore @@ -6911,6 +6915,7 @@ pub mod tests { post_token_balances: Some(vec![]), rewards: Some(vec![]), loaded_addresses: LoadedAddresses::default(), + return_data: Some(TransactionReturnData::default()), }, } }) @@ -7023,6 +7028,10 @@ pub mod tests { writable: vec![Pubkey::new_unique()], readonly: vec![Pubkey::new_unique()], }; + let test_return_data = TransactionReturnData { + program_id: Pubkey::new_unique(), + data: vec![1, 2, 3], + }; // result not found assert!(transaction_status_cf @@ -7042,6 +7051,7 @@ pub mod tests { post_token_balances: Some(post_token_balances_vec.clone()), rewards: Some(rewards_vec.clone()), loaded_addresses: test_loaded_addresses.clone(), + return_data: Some(test_return_data.clone()), } .into(); assert!(transaction_status_cf @@ -7060,6 +7070,7 @@ pub mod tests { post_token_balances, rewards, loaded_addresses, + return_data, } = transaction_status_cf .get_protobuf_or_bincode::((0, Signature::default(), 0)) .unwrap() @@ -7076,6 +7087,7 @@ pub mod tests { assert_eq!(post_token_balances.unwrap(), post_token_balances_vec); assert_eq!(rewards.unwrap(), rewards_vec); assert_eq!(loaded_addresses, test_loaded_addresses); + assert_eq!(return_data.unwrap(), test_return_data); // insert value let status = TransactionStatusMeta { @@ -7089,6 +7101,7 @@ pub mod tests { post_token_balances: Some(post_token_balances_vec.clone()), rewards: Some(rewards_vec.clone()), loaded_addresses: test_loaded_addresses.clone(), + return_data: Some(test_return_data.clone()), } .into(); assert!(transaction_status_cf @@ -7107,6 +7120,7 @@ pub mod tests { post_token_balances, rewards, loaded_addresses, + return_data, } = transaction_status_cf .get_protobuf_or_bincode::(( 0, @@ -7129,6 +7143,7 @@ pub mod tests { assert_eq!(post_token_balances.unwrap(), post_token_balances_vec); assert_eq!(rewards.unwrap(), rewards_vec); assert_eq!(loaded_addresses, test_loaded_addresses); + assert_eq!(return_data.unwrap(), test_return_data); } #[test] @@ -7357,6 +7372,7 @@ pub mod tests { post_token_balances: Some(vec![]), rewards: Some(vec![]), loaded_addresses: LoadedAddresses::default(), + return_data: Some(TransactionReturnData::default()), } .into(); @@ -7552,6 +7568,7 @@ pub mod tests { post_token_balances: Some(vec![]), rewards: Some(vec![]), loaded_addresses: LoadedAddresses::default(), + return_data: Some(TransactionReturnData::default()), } .into(); @@ -7723,6 +7740,10 @@ pub mod tests { let post_token_balances = Some(vec![]); let rewards = Some(vec![]); let signature = transaction.signatures[0]; + let return_data = Some(TransactionReturnData { + program_id: Pubkey::new_unique(), + data: vec![1, 2, 3], + }); let status = TransactionStatusMeta { status: Ok(()), fee: 42, @@ -7734,6 +7755,7 @@ pub mod tests { post_token_balances: post_token_balances.clone(), rewards: rewards.clone(), loaded_addresses: LoadedAddresses::default(), + return_data: return_data.clone(), } .into(); blockstore @@ -7753,6 +7775,7 @@ pub mod tests { post_token_balances, rewards, loaded_addresses: LoadedAddresses::default(), + return_data, }, } }) @@ -7824,6 +7847,10 @@ pub mod tests { let pre_token_balances = Some(vec![]); let post_token_balances = Some(vec![]); let rewards = Some(vec![]); + let return_data = Some(TransactionReturnData { + program_id: Pubkey::new_unique(), + data: vec![1, 2, 3], + }); let signature = transaction.signatures[0]; let status = TransactionStatusMeta { status: Ok(()), @@ -7836,6 +7863,7 @@ pub mod tests { post_token_balances: post_token_balances.clone(), rewards: rewards.clone(), loaded_addresses: LoadedAddresses::default(), + return_data: return_data.clone(), } .into(); blockstore @@ -7855,6 +7883,7 @@ pub mod tests { post_token_balances, rewards, loaded_addresses: LoadedAddresses::default(), + return_data, }, } }) @@ -8614,6 +8643,7 @@ pub mod tests { post_token_balances: Some(vec![]), rewards: Some(vec![]), loaded_addresses: LoadedAddresses::default(), + return_data: Some(TransactionReturnData::default()), } .into(); transaction_status_cf @@ -9171,6 +9201,10 @@ pub mod tests { commission: None, }]), loaded_addresses: LoadedAddresses::default(), + return_data: Some(TransactionReturnData { + program_id: Pubkey::new_unique(), + data: vec![1, 2, 3], + }), }; let deprecated_status: StoredTransactionStatusMeta = status.clone().try_into().unwrap(); let protobuf_status: generated::TransactionStatusMeta = status.into(); diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index dde1ce562c..7c68581b6f 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -181,6 +181,7 @@ fn execute_batch( transaction_status_sender.is_some(), transaction_status_sender.is_some(), transaction_status_sender.is_some(), + transaction_status_sender.is_some(), timings, ); @@ -3510,6 +3511,7 @@ pub mod tests { false, false, false, + false, &mut ExecuteTimings::default(), ); let (err, signature) = get_first_error(&batch, fee_collection_results).unwrap(); diff --git a/multinode-demo/bootstrap-validator.sh b/multinode-demo/bootstrap-validator.sh index f8d9077308..580f7843ca 100755 --- a/multinode-demo/bootstrap-validator.sh +++ b/multinode-demo/bootstrap-validator.sh @@ -55,6 +55,9 @@ while [[ -n $1 ]]; do elif [[ $1 = --enable-cpi-and-log-storage ]]; then args+=("$1") shift + elif [[ $1 = --enable-extended-tx-metadata-storage ]]; then + args+=("$1") + shift elif [[ $1 = --enable-rpc-bigtable-ledger-storage ]]; then args+=("$1") shift diff --git a/multinode-demo/validator.sh b/multinode-demo/validator.sh index 362ef03dcb..8bae785a02 100755 --- a/multinode-demo/validator.sh +++ b/multinode-demo/validator.sh @@ -141,6 +141,9 @@ while [[ -n $1 ]]; do elif [[ $1 = --enable-cpi-and-log-storage ]]; then args+=("$1") shift + elif [[ $1 = --enable-extended-tx-metadata-storage ]]; then + args+=("$1") + shift elif [[ $1 = --skip-poh-verify ]]; then args+=("$1") shift diff --git a/net/remote/remote-node.sh b/net/remote/remote-node.sh index eedb35672d..2b93ffed14 100755 --- a/net/remote/remote-node.sh +++ b/net/remote/remote-node.sh @@ -280,7 +280,7 @@ EOF if $maybeFullRpc; then args+=(--enable-rpc-transaction-history) - args+=(--enable-cpi-and-log-storage) + args+=(--enable-extended-tx-metadata-storage) fi if [[ $airdropsEnabled = true ]]; then @@ -408,7 +408,7 @@ EOF if $maybeFullRpc; then args+=(--enable-rpc-transaction-history) - args+=(--enable-cpi-and-log-storage) + args+=(--enable-extended-tx-metadata-storage) fi cat >> ~/solana/on-reboot < ProgramResult { + set_return_data(input); + Err(ProgramError::InvalidInstructionData) +} + +#[tokio::test] +async fn simulation_return_data() { + let error_set_return_data_program_id = Pubkey::new_unique(); + let program_test = ProgramTest::new( + "error_set_return_data", + error_set_return_data_program_id, + processor!(error_set_return_data_process_instruction), + ); + + let mut context = program_test.start_with_context().await; + let expected_data = vec![240, 159, 166, 150]; + let instructions = vec![Instruction { + program_id: error_set_return_data_program_id, + accounts: vec![], + data: expected_data.clone(), + }]; + + let transaction = Transaction::new_signed_with_payer( + &instructions, + Some(&context.payer.pubkey()), + &[&context.payer], + context.last_blockhash, + ); + + let error = context + .banks_client + .process_transaction_with_preflight_and_commitment(transaction, CommitmentLevel::Confirmed) + .await + .unwrap_err(); + assert_matches!( + error, + BanksClientError::SimulationError { + return_data: Some(TransactionReturnData { + program_id, + data, + }), + .. + } if program_id == error_set_return_data_program_id && data == expected_data + ); +} diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index 3e9ed4f78e..50edc171dd 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -1862,6 +1862,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +[[package]] +name = "pretty-hex" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5c99d529f0d30937f6f4b8a86d988047327bb88d04d2c4afc356de74722131" + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -3075,6 +3081,7 @@ dependencies = [ "console", "humantime", "indicatif", + "pretty-hex", "serde", "serde_json", "solana-account-decoder", @@ -3419,6 +3426,7 @@ dependencies = [ name = "solana-program-test" version = "1.11.0" dependencies = [ + "assert_matches", "async-trait", "base64 0.13.0", "bincode", diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index f92f18b1d9..fc9a8e8423 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -323,6 +323,7 @@ fn process_transaction_and_record_inner( false, true, false, + false, &mut ExecuteTimings::default(), ) .0; @@ -364,6 +365,7 @@ fn execute_transactions( true, true, true, + true, &mut timings, ); let tx_post_token_balances = collect_token_balances(&bank, &batch, &mut mint_decimals); @@ -392,6 +394,7 @@ fn execute_transactions( log_messages, inner_instructions, durable_nonce_fee, + return_data, } = details; let lamports_per_signature = match durable_nonce_fee { @@ -432,6 +435,7 @@ fn execute_transactions( log_messages, rewards: None, loaded_addresses: LoadedAddresses::default(), + return_data, }; Ok(ConfirmedTransactionWithStatusMeta { diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index ba93817702..1575ae243e 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -143,7 +143,7 @@ fn is_finalized( #[derive(Debug, Default, Clone)] pub struct JsonRpcConfig { pub enable_rpc_transaction_history: bool, - pub enable_cpi_and_log_storage: bool, + pub enable_extended_tx_metadata_storage: bool, pub faucet_addr: Option, pub health_check_slot_distance: u64, pub rpc_bigtable_config: Option, @@ -3551,6 +3551,7 @@ pub mod rpc_full { logs, post_simulation_accounts: _, units_consumed, + return_data, } = preflight_bank.simulate_transaction(transaction) { match err { @@ -3568,6 +3569,7 @@ pub mod rpc_full { logs: Some(logs), accounts: None, units_consumed: Some(units_consumed), + return_data, }, } .into()); @@ -3625,6 +3627,7 @@ pub mod rpc_full { logs, post_simulation_accounts, units_consumed, + return_data, } = bank.simulate_transaction(transaction); let accounts = if let Some(config_accounts) = config.accounts { @@ -3676,6 +3679,7 @@ pub mod rpc_full { logs: Some(logs), accounts, units_consumed: Some(units_consumed), + return_data, }, )) } @@ -5574,6 +5578,7 @@ pub mod tests { "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" ], + "returnData":null, "unitsConsumed":0 } }, @@ -5660,6 +5665,7 @@ pub mod tests { "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" ], + "returnData":null, "unitsConsumed":0 } }, @@ -5688,6 +5694,7 @@ pub mod tests { "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" ], + "returnData":null, "unitsConsumed":0 } }, @@ -5737,6 +5744,7 @@ pub mod tests { "err":"BlockhashNotFound", "accounts":null, "logs":[], + "returnData":null, "unitsConsumed":0 } }, @@ -5766,6 +5774,7 @@ pub mod tests { "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" ], + "returnData":null, "unitsConsumed":0 } }, @@ -6123,7 +6132,7 @@ pub mod tests { assert_eq!( res, Some( - r#"{"jsonrpc":"2.0","error":{"code":-32002,"message":"Transaction simulation failed: Blockhash not found","data":{"accounts":null,"err":"BlockhashNotFound","logs":[],"unitsConsumed":0}},"id":1}"#.to_string(), + r#"{"jsonrpc":"2.0","error":{"code":-32002,"message":"Transaction simulation failed: Blockhash not found","data":{"accounts":null,"err":"BlockhashNotFound","logs":[],"returnData":null,"unitsConsumed":0}},"id":1}"#.to_string(), ) ); diff --git a/rpc/src/transaction_status_service.rs b/rpc/src/transaction_status_service.rs index feeb6657fc..c61743af6b 100644 --- a/rpc/src/transaction_status_service.rs +++ b/rpc/src/transaction_status_service.rs @@ -34,7 +34,7 @@ impl TransactionStatusService { enable_rpc_transaction_history: bool, transaction_notifier: Option, blockstore: Arc, - enable_cpi_and_log_storage: bool, + enable_extended_tx_metadata_storage: bool, exit: &Arc, ) -> Self { let exit = exit.clone(); @@ -51,7 +51,7 @@ impl TransactionStatusService { enable_rpc_transaction_history, transaction_notifier.clone(), &blockstore, - enable_cpi_and_log_storage, + enable_extended_tx_metadata_storage, ) { break; } @@ -66,7 +66,7 @@ impl TransactionStatusService { enable_rpc_transaction_history: bool, transaction_notifier: Option, blockstore: &Arc, - enable_cpi_and_log_storage: bool, + enable_extended_tx_metadata_storage: bool, ) -> Result<(), RecvTimeoutError> { match write_transaction_status_receiver.recv_timeout(Duration::from_secs(1))? { TransactionStatusMessage::Batch(TransactionStatusBatch { @@ -101,6 +101,7 @@ impl TransactionStatusService { log_messages, inner_instructions, durable_nonce_fee, + return_data, } = details; let lamports_per_signature = match durable_nonce_fee { Some(DurableNonceFee::Valid(lamports_per_signature)) => { @@ -156,6 +157,7 @@ impl TransactionStatusService { post_token_balances, rewards, loaded_addresses, + return_data, }; if let Some(transaction_notifier) = transaction_notifier.as_ref() { @@ -167,9 +169,11 @@ impl TransactionStatusService { ); } - if !(enable_cpi_and_log_storage || transaction_notifier.is_some()) { + if !(enable_extended_tx_metadata_storage || transaction_notifier.is_some()) + { transaction_status_meta.log_messages.take(); transaction_status_meta.inner_instructions.take(); + transaction_status_meta.return_data.take(); } if enable_rpc_transaction_history { @@ -347,6 +351,7 @@ pub(crate) mod tests { ) .unwrap(), )), + return_data: None, }); let balances = TransactionBalancesSet { diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index 663ac3ec90..6d934e3946 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -1374,6 +1374,7 @@ mod tests { log_messages: None, inner_instructions: None, durable_nonce_fee: nonce.map(DurableNonceFee::from), + return_data: None, }) } diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index d32d0d26a3..726de0ef02 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -130,7 +130,10 @@ use { MessageHash, Result, SanitizedTransaction, Transaction, TransactionError, TransactionVerificationMode, VersionedTransaction, }, - transaction_context::{InstructionTrace, TransactionAccount, TransactionContext}, + transaction_context::{ + ExecutionRecord, InstructionTrace, TransactionAccount, TransactionContext, + TransactionReturnData, + }, }, solana_stake_program::stake_state::{ self, InflationPointCalculationEvent, PointValue, StakeState, @@ -579,6 +582,7 @@ pub struct TransactionExecutionDetails { pub log_messages: Option>, pub inner_instructions: Option, pub durable_nonce_fee: Option, + pub return_data: Option, } /// Type safe representation of a transaction execution attempt which @@ -670,6 +674,7 @@ pub struct TransactionSimulationResult { pub logs: TransactionLogMessages, pub post_simulation_accounts: Vec, pub units_consumed: u64, + pub return_data: Option, } pub struct TransactionBalancesSet { pub pre_balances: TransactionBalances, @@ -3541,6 +3546,7 @@ impl Bank { MAX_PROCESSING_AGE - MAX_TRANSACTION_FORWARDING_DELAY, false, true, + true, &mut timings, ); @@ -3571,17 +3577,20 @@ impl Bank { let execution_result = execution_results.pop().unwrap(); let flattened_result = execution_result.flattened_result(); - let logs = match execution_result { - TransactionExecutionResult::Executed(details) => details.log_messages, - TransactionExecutionResult::NotExecuted(_) => None, - } - .unwrap_or_default(); + let (logs, return_data) = match execution_result { + TransactionExecutionResult::Executed(details) => { + (details.log_messages, details.return_data) + } + TransactionExecutionResult::NotExecuted(_) => (None, None), + }; + let logs = logs.unwrap_or_default(); TransactionSimulationResult { result: flattened_result, logs, post_simulation_accounts, units_consumed, + return_data, } } @@ -3858,6 +3867,7 @@ impl Bank { /// Execute a transaction using the provided loaded accounts and update /// the executors cache if the transaction was successful. + #[allow(clippy::too_many_arguments)] fn execute_loaded_transaction( &self, tx: &SanitizedTransaction, @@ -3866,6 +3876,7 @@ impl Bank { durable_nonce_fee: Option, enable_cpi_recording: bool, enable_log_recording: bool, + enable_return_data_recording: bool, timings: &mut ExecuteTimings, error_counters: &mut ErrorCounters, ) -> TransactionExecutionResult { @@ -3960,7 +3971,11 @@ impl Bank { .ok() }); - let (accounts, instruction_trace) = transaction_context.deconstruct(); + let ExecutionRecord { + accounts, + instruction_trace, + mut return_data, + } = transaction_context.into(); loaded_transaction.accounts = accounts; let inner_instructions = if enable_cpi_recording { @@ -3971,11 +3986,25 @@ impl Bank { None }; + let return_data = if enable_return_data_recording { + if let Some(end_index) = return_data.data.iter().rposition(|&x| x != 0) { + let end_index = end_index.saturating_add(1); + error!("end index {}", end_index); + return_data.data.truncate(end_index); + Some(return_data) + } else { + None + } + } else { + None + }; + TransactionExecutionResult::Executed(TransactionExecutionDetails { status, log_messages, inner_instructions, durable_nonce_fee, + return_data, }) } @@ -3986,6 +4015,7 @@ impl Bank { max_age: usize, enable_cpi_recording: bool, enable_log_recording: bool, + enable_return_data_recording: bool, timings: &mut ExecuteTimings, ) -> LoadAndExecuteTransactionsOutput { let sanitized_txs = batch.sanitized_transactions(); @@ -4089,6 +4119,7 @@ impl Bank { durable_nonce_fee, enable_cpi_recording, enable_log_recording, + enable_return_data_recording, timings, &mut error_counters, ) @@ -5240,6 +5271,7 @@ impl Bank { collect_balances: bool, enable_cpi_recording: bool, enable_log_recording: bool, + enable_return_data_recording: bool, timings: &mut ExecuteTimings, ) -> (TransactionResults, TransactionBalancesSet) { let pre_balances = if collect_balances { @@ -5260,6 +5292,7 @@ impl Bank { max_age, enable_cpi_recording, enable_log_recording, + enable_return_data_recording, timings, ); @@ -5346,6 +5379,7 @@ impl Bank { false, false, false, + false, &mut ExecuteTimings::default(), ) .0 @@ -6774,6 +6808,7 @@ pub(crate) mod tests { message::{Message, MessageHeader}, nonce, poh_config::PohConfig, + program::MAX_RETURN_DATA, rent::Rent, signature::{keypair_from_seed, Keypair, Signer}, stake::{ @@ -6813,6 +6848,7 @@ pub(crate) mod tests { log_messages: None, inner_instructions: None, durable_nonce_fee: nonce.map(DurableNonceFee::from), + return_data: None, }) } @@ -9949,6 +9985,7 @@ pub(crate) mod tests { false, false, false, + false, &mut ExecuteTimings::default(), ) .0 @@ -12482,6 +12519,7 @@ pub(crate) mod tests { true, false, false, + false, &mut ExecuteTimings::default(), ); @@ -15407,6 +15445,7 @@ pub(crate) mod tests { false, false, true, + false, &mut ExecuteTimings::default(), ) .0 @@ -15449,6 +15488,91 @@ pub(crate) mod tests { assert!(failure_log.contains(&"failed".to_string())); } + #[test] + fn test_tx_return_data() { + solana_logger::setup(); + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config_with_leader( + 1_000_000_000_000_000, + &Pubkey::new_unique(), + bootstrap_validator_stake_lamports(), + ); + let mut bank = Bank::new_for_tests(&genesis_config); + + let mock_program_id = Pubkey::new(&[2u8; 32]); + fn mock_process_instruction( + _first_instruction_account: usize, + data: &[u8], + invoke_context: &mut InvokeContext, + ) -> result::Result<(), InstructionError> { + let mock_program_id = Pubkey::new(&[2u8; 32]); + let transaction_context = &mut invoke_context.transaction_context; + let mut return_data = [0u8; MAX_RETURN_DATA]; + if !data.is_empty() { + let index = usize::from_le_bytes(data.try_into().unwrap()); + return_data[index] = 1; + transaction_context + .set_return_data(mock_program_id, return_data.to_vec()) + .unwrap(); + } + Ok(()) + } + let blockhash = bank.last_blockhash(); + bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction); + + for index in [ + None, + Some(0), + Some(MAX_RETURN_DATA / 2), + Some(MAX_RETURN_DATA - 1), + ] { + let data = if let Some(index) = index { + usize::to_le_bytes(index).to_vec() + } else { + Vec::new() + }; + let txs = vec![Transaction::new_signed_with_payer( + &[Instruction { + program_id: mock_program_id, + data, + accounts: vec![AccountMeta::new(Pubkey::new_unique(), false)], + }], + Some(&mint_keypair.pubkey()), + &[&mint_keypair], + blockhash, + )]; + let batch = bank.prepare_batch_for_tests(txs); + let return_data = bank + .load_execute_and_commit_transactions( + &batch, + MAX_PROCESSING_AGE, + false, + false, + false, + true, + &mut ExecuteTimings::default(), + ) + .0 + .execution_results[0] + .details() + .unwrap() + .return_data + .clone(); + if let Some(index) = index { + let return_data = return_data.unwrap(); + assert_eq!(return_data.program_id, mock_program_id); + let mut expected_data = vec![0u8; index]; + expected_data.push(1u8); + assert_eq!(return_data.data, expected_data); + } else { + assert!(return_data.is_none()); + } + } + } + #[test] fn test_get_largest_accounts() { let GenesisConfigInfo { genesis_config, .. } = diff --git a/scripts/run.sh b/scripts/run.sh index 86407d339d..a890aa10c1 100755 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -108,7 +108,7 @@ args=( --rpc-faucet-address 127.0.0.1:9900 --log - --enable-rpc-transaction-history - --enable-cpi-and-log-storage + --enable-extended-tx-metadata-storage --init-complete-file "$dataDir"/init-completed --snapshot-compression none --require-tower diff --git a/sdk/src/transaction_context.rs b/sdk/src/transaction_context.rs index 59dd5e6411..90db0ed3c4 100644 --- a/sdk/src/transaction_context.rs +++ b/sdk/src/transaction_context.rs @@ -35,7 +35,7 @@ pub struct TransactionContext { instruction_stack: Vec, number_of_instructions_at_transaction_level: usize, instruction_trace: InstructionTrace, - return_data: (Pubkey, Vec), + return_data: TransactionReturnData, } impl TransactionContext { @@ -57,25 +57,10 @@ impl TransactionContext { instruction_stack: Vec::with_capacity(instruction_context_capacity), number_of_instructions_at_transaction_level, instruction_trace: Vec::with_capacity(number_of_instructions_at_transaction_level), - return_data: (Pubkey::default(), Vec::new()), + return_data: TransactionReturnData::default(), } } - /// Used by the bank in the runtime to write back the processed accounts and recorded instructions - pub fn deconstruct(self) -> (Vec, Vec>) { - ( - Vec::from(Pin::into_inner(self.account_keys)) - .into_iter() - .zip( - Vec::from(Pin::into_inner(self.accounts)) - .into_iter() - .map(|account| account.into_inner()), - ) - .collect(), - self.instruction_trace, - ) - } - /// Used in mock_process_instruction pub fn deconstruct_without_keys(self) -> Result, InstructionError> { if !self.instruction_stack.is_empty() { @@ -225,7 +210,7 @@ impl TransactionContext { /// Gets the return data of the current InstructionContext or any above pub fn get_return_data(&self) -> (&Pubkey, &[u8]) { - (&self.return_data.0, &self.return_data.1) + (&self.return_data.program_id, &self.return_data.data) } /// Set the return data of the current InstructionContext @@ -234,7 +219,7 @@ impl TransactionContext { program_id: Pubkey, data: Vec, ) -> Result<(), InstructionError> { - self.return_data = (program_id, data); + self.return_data = TransactionReturnData { program_id, data }; Ok(()) } @@ -254,6 +239,13 @@ impl TransactionContext { } } +/// Return data at the end of a transaction +#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] +pub struct TransactionReturnData { + pub program_id: Pubkey, + pub data: Vec, +} + /// List of (stack height, instruction) for each top-level instruction pub type InstructionTrace = Vec>; @@ -628,3 +620,27 @@ impl<'a> BorrowedAccount<'a> { .unwrap_or_default() } } + +/// Everything that needs to be recorded from a TransactionContext after execution +pub struct ExecutionRecord { + pub accounts: Vec, + pub instruction_trace: InstructionTrace, + pub return_data: TransactionReturnData, +} +/// Used by the bank in the runtime to write back the processed accounts and recorded instructions +impl From for ExecutionRecord { + fn from(context: TransactionContext) -> Self { + Self { + accounts: Vec::from(Pin::into_inner(context.account_keys)) + .into_iter() + .zip( + Vec::from(Pin::into_inner(context.accounts)) + .into_iter() + .map(|account| account.into_inner()), + ) + .collect(), + instruction_trace: context.instruction_trace, + return_data: context.return_data, + } + } +} diff --git a/storage-bigtable/src/bigtable.rs b/storage-bigtable/src/bigtable.rs index e95825736e..b8ca060617 100644 --- a/storage-bigtable/src/bigtable.rs +++ b/storage-bigtable/src/bigtable.rs @@ -792,7 +792,7 @@ mod tests { prost::Message, solana_sdk::{ hash::Hash, message::v0::LoadedAddresses, signature::Keypair, system_transaction, - transaction::VersionedTransaction, + transaction::VersionedTransaction, transaction_context::TransactionReturnData, }, solana_storage_proto::convert::generated, solana_transaction_status::{ @@ -842,6 +842,7 @@ mod tests { post_token_balances: Some(vec![]), rewards: Some(vec![]), loaded_addresses: LoadedAddresses::default(), + return_data: Some(TransactionReturnData::default()), }, }); let expected_block = ConfirmedBlock { @@ -899,6 +900,7 @@ mod tests { meta.pre_token_balances = None; // Legacy bincode implementation does not support token balances meta.post_token_balances = None; // Legacy bincode implementation does not support token balances meta.rewards = None; // Legacy bincode implementation does not support rewards + meta.return_data = None; // Legacy bincode implementation does not support return data } assert_eq!(block, bincode_block.into()); } else { diff --git a/storage-bigtable/src/lib.rs b/storage-bigtable/src/lib.rs index 2f28f0857a..7409536925 100644 --- a/storage-bigtable/src/lib.rs +++ b/storage-bigtable/src/lib.rs @@ -237,6 +237,7 @@ impl From for TransactionStatusMeta { post_token_balances: None, rewards: None, loaded_addresses: LoadedAddresses::default(), + return_data: None, } } } diff --git a/storage-proto/proto/confirmed_block.proto b/storage-proto/proto/confirmed_block.proto index 4387fe99ae..b2a6c48898 100644 --- a/storage-proto/proto/confirmed_block.proto +++ b/storage-proto/proto/confirmed_block.proto @@ -57,6 +57,8 @@ message TransactionStatusMeta { repeated Reward rewards = 9; repeated bytes loaded_writable_addresses = 12; repeated bytes loaded_readonly_addresses = 13; + ReturnData return_data = 14; + bool return_data_none = 15; } message TransactionError { @@ -88,6 +90,11 @@ message UiTokenAmount { string ui_amount_string = 4; } +message ReturnData { + bytes program_id = 1; + bytes data = 2; +} + enum RewardType { Unspecified = 0; Fee = 1; diff --git a/storage-proto/src/convert.rs b/storage-proto/src/convert.rs index fadf65f184..57fbe4edb8 100644 --- a/storage-proto/src/convert.rs +++ b/storage-proto/src/convert.rs @@ -12,6 +12,7 @@ use { pubkey::Pubkey, signature::Signature, transaction::{Transaction, TransactionError, VersionedTransaction}, + transaction_context::TransactionReturnData, }, solana_transaction_status::{ ConfirmedBlock, InnerInstructions, Reward, RewardType, TransactionByAddrInfo, @@ -363,6 +364,7 @@ impl From for generated::TransactionStatusMeta { post_token_balances, rewards, loaded_addresses, + return_data, } = value; let err = match status { Ok(()) => None, @@ -403,6 +405,8 @@ impl From for generated::TransactionStatusMeta { .into_iter() .map(|key| >::as_ref(&key).into()) .collect(); + let return_data_none = return_data.is_none(); + let return_data = return_data.map(|return_data| return_data.into()); Self { err, @@ -418,6 +422,8 @@ impl From for generated::TransactionStatusMeta { rewards, loaded_writable_addresses, loaded_readonly_addresses, + return_data, + return_data_none, } } } @@ -447,6 +453,8 @@ impl TryFrom for TransactionStatusMeta { rewards, loaded_writable_addresses, loaded_readonly_addresses, + return_data, + return_data_none, } = value; let status = match &err { None => Ok(()), @@ -490,6 +498,11 @@ impl TryFrom for TransactionStatusMeta { .map(|key| Pubkey::new(&key)) .collect(), }; + let return_data = if return_data_none { + None + } else { + return_data.map(|return_data| return_data.into()) + }; Ok(Self { status, fee, @@ -501,6 +514,7 @@ impl TryFrom for TransactionStatusMeta { post_token_balances, rewards, loaded_addresses, + return_data, }) } } @@ -587,6 +601,24 @@ impl From for MessageAddressTableLookup { } } +impl From for generated::ReturnData { + fn from(value: TransactionReturnData) -> Self { + Self { + program_id: >::as_ref(&value.program_id).into(), + data: value.data, + } + } +} + +impl From for TransactionReturnData { + fn from(value: generated::ReturnData) -> Self { + Self { + program_id: Pubkey::new(&value.program_id), + data: value.data, + } + } +} + impl From for generated::CompiledInstruction { fn from(value: CompiledInstruction) -> Self { Self { diff --git a/storage-proto/src/lib.rs b/storage-proto/src/lib.rs index ac85e3672e..04b98a99bc 100644 --- a/storage-proto/src/lib.rs +++ b/storage-proto/src/lib.rs @@ -6,6 +6,7 @@ use { }, solana_sdk::{ deserialize_utils::default_on_eof, message::v0::LoadedAddresses, transaction::Result, + transaction_context::TransactionReturnData, }, solana_transaction_status::{ InnerInstructions, Reward, RewardType, TransactionStatusMeta, TransactionTokenBalance, @@ -167,6 +168,8 @@ pub struct StoredTransactionStatusMeta { pub post_token_balances: Option>, #[serde(deserialize_with = "default_on_eof")] pub rewards: Option>, + #[serde(deserialize_with = "default_on_eof")] + pub return_data: Option, } impl From for TransactionStatusMeta { @@ -181,6 +184,7 @@ impl From for TransactionStatusMeta { pre_token_balances, post_token_balances, rewards, + return_data, } = value; Self { status, @@ -196,6 +200,7 @@ impl From for TransactionStatusMeta { rewards: rewards .map(|rewards| rewards.into_iter().map(|reward| reward.into()).collect()), loaded_addresses: LoadedAddresses::default(), + return_data, } } } @@ -214,6 +219,7 @@ impl TryFrom for StoredTransactionStatusMeta { post_token_balances, rewards, loaded_addresses, + return_data, } = value; if !loaded_addresses.is_empty() { @@ -237,6 +243,7 @@ impl TryFrom for StoredTransactionStatusMeta { .map(|balances| balances.into_iter().map(|balance| balance.into()).collect()), rewards: rewards .map(|rewards| rewards.into_iter().map(|reward| reward.into()).collect()), + return_data, }) } } diff --git a/transaction-status/src/lib.rs b/transaction-status/src/lib.rs index 24fcf30770..dc0e53178c 100644 --- a/transaction-status/src/lib.rs +++ b/transaction-status/src/lib.rs @@ -22,6 +22,7 @@ use { Result as TransactionResult, Transaction, TransactionError, TransactionVersion, VersionedTransaction, }, + transaction_context::TransactionReturnData, }, std::fmt, thiserror::Error, @@ -279,6 +280,7 @@ pub struct TransactionStatusMeta { pub post_token_balances: Option>, pub rewards: Option, pub loaded_addresses: LoadedAddresses, + pub return_data: Option, } impl Default for TransactionStatusMeta { @@ -294,6 +296,7 @@ impl Default for TransactionStatusMeta { post_token_balances: None, rewards: None, loaded_addresses: LoadedAddresses::default(), + return_data: None, } } } @@ -314,6 +317,7 @@ pub struct UiTransactionStatusMeta { pub rewards: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub loaded_addresses: Option, + pub return_data: Option, } /// A duplicate representation of LoadedAddresses @@ -364,6 +368,7 @@ impl UiTransactionStatusMeta { .map(|balance| balance.into_iter().map(Into::into).collect()), rewards: meta.rewards, loaded_addresses: Some(UiLoadedAddresses::from(&meta.loaded_addresses)), + return_data: meta.return_data, } } } @@ -388,6 +393,7 @@ impl From for UiTransactionStatusMeta { .map(|balance| balance.into_iter().map(Into::into).collect()), rewards: meta.rewards, loaded_addresses: Some(UiLoadedAddresses::from(&meta.loaded_addresses)), + return_data: meta.return_data, } } } diff --git a/validator/src/bin/solana-test-validator.rs b/validator/src/bin/solana-test-validator.rs index 02d54901fa..85f9fb67f8 100644 --- a/validator/src/bin/solana-test-validator.rs +++ b/validator/src/bin/solana-test-validator.rs @@ -657,7 +657,7 @@ fn main() { ) .rpc_config(JsonRpcConfig { enable_rpc_transaction_history: true, - enable_cpi_and_log_storage: true, + enable_extended_tx_metadata_storage: true, rpc_bigtable_config, faucet_addr, ..JsonRpcConfig::default_for_test() diff --git a/validator/src/main.rs b/validator/src/main.rs index a469c37dc2..c03bd16d6c 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -656,8 +656,18 @@ pub fn main() { .long("enable-cpi-and-log-storage") .requires("enable_rpc_transaction_history") .takes_value(false) - .help("Include CPI inner instructions and logs in the \ - historical transaction info stored"), + .hidden(true) + .help("Deprecated, please use \"enable-extended-tx-metadata-storage\". \ + Include CPI inner instructions, logs and return data in \ + the historical transaction info stored"), + ) + .arg( + Arg::with_name("enable_extended_tx_metadata_storage") + .long("enable-extended-tx-metadata-storage") + .requires("enable_rpc_transaction_history") + .takes_value(false) + .help("Include CPI inner instructions, logs, and return data in \ + the historical transaction info stored"), ) .arg( Arg::with_name("rpc_max_multiple_accounts") @@ -2294,7 +2304,15 @@ pub fn main() { }; if matches.is_present("minimal_rpc_api") { - warn!("--minimal-rpc-api is now the default behavior. This flag is deprecated and can be removed from the launch args") + warn!("--minimal-rpc-api is now the default behavior. This flag is deprecated and can be removed from the launch args"); + } + + if matches.is_present("enable_cpi_and_log_storage") { + warn!( + "--enable-cpi-and-log-storage is deprecated. Please update the \ + launch args to use --enable-extended-tx-metadata-storage and remove \ + --enable-cpi-and-log-storage" + ); } let rpc_bigtable_config = if matches.is_present("enable_rpc_bigtable_ledger_storage") @@ -2325,7 +2343,8 @@ pub fn main() { new_hard_forks: hardforks_of(&matches, "hard_forks"), rpc_config: JsonRpcConfig { enable_rpc_transaction_history: matches.is_present("enable_rpc_transaction_history"), - enable_cpi_and_log_storage: matches.is_present("enable_cpi_and_log_storage"), + enable_extended_tx_metadata_storage: matches.is_present("enable_cpi_and_log_storage") + || matches.is_present("enable_extended_tx_metadata_storage"), rpc_bigtable_config, faucet_addr: matches.value_of("rpc_faucet_addr").map(|address| { solana_net_utils::parse_host_port(address).expect("failed to parse faucet address")