From 4d25e6a57f90f6d081c4eb1706a0e819f64c38ff Mon Sep 17 00:00:00 2001 From: Joe Date: Mon, 4 Dec 2023 20:16:38 -0600 Subject: [PATCH] rpc: return inner instructions from simulate tx --- docs/src/api/methods/_simulateTransaction.mdx | 1 + rpc-client-api/src/response.rs | 5 +-- rpc-client/src/mock_sender.rs | 1 + rpc/src/rpc.rs | 36 +++++++++++++++---- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/docs/src/api/methods/_simulateTransaction.mdx b/docs/src/api/methods/_simulateTransaction.mdx index 2a8e53dc4287ec..3eea5c78d8d32a 100644 --- a/docs/src/api/methods/_simulateTransaction.mdx +++ b/docs/src/api/methods/_simulateTransaction.mdx @@ -123,6 +123,7 @@ The result will be an RpcResponse JSON object with `value` set to a JSON object - `returnData: ` - the most-recent return data generated by an instruction in the transaction, with the following fields: - `programId: ` - the program that generated the return data, as base-58 encoded Pubkey - `data: <[string, encoding]>` - the return data itself, as base-64 encoded binary data +- `innerInstructions: ` - List of [inner instructions](#inner-instructions-structure) or `null` if inner instruction recording was not requested in this simulation diff --git a/rpc-client-api/src/response.rs b/rpc-client-api/src/response.rs index 7591c58c036d32..96f021750462fb 100644 --- a/rpc-client-api/src/response.rs +++ b/rpc-client-api/src/response.rs @@ -10,8 +10,8 @@ use { transaction::{Result, TransactionError}, }, solana_transaction_status::{ - ConfirmedTransactionStatusWithSignature, TransactionConfirmationStatus, UiConfirmedBlock, - UiTransactionReturnData, + ConfirmedTransactionStatusWithSignature, InnerInstructions, TransactionConfirmationStatus, + UiConfirmedBlock, UiTransactionReturnData, }, std::{collections::HashMap, fmt, net::SocketAddr, str::FromStr}, thiserror::Error, @@ -423,6 +423,7 @@ pub struct RpcSimulateTransactionResult { pub accounts: Option>>, pub units_consumed: Option, pub return_data: Option, + pub inner_instructions: Option>, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] diff --git a/rpc-client/src/mock_sender.rs b/rpc-client/src/mock_sender.rs index 654f45d0296477..de8f8cdddd5638 100644 --- a/rpc-client/src/mock_sender.rs +++ b/rpc-client/src/mock_sender.rs @@ -350,6 +350,7 @@ impl RpcSender for MockSender { accounts: None, units_consumed: None, return_data: None, + inner_instructions: None, }, })?, "getMinimumBalanceForRentExemption" => json![20], diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index 4ea64ebb7d839b..022a53920e0156 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -88,9 +88,9 @@ use { solana_streamer::socket::SocketAddrSpace, solana_transaction_status::{ BlockEncodingOptions, ConfirmedBlock, ConfirmedTransactionStatusWithSignature, - ConfirmedTransactionWithStatusMeta, EncodedConfirmedTransactionWithStatusMeta, Reward, - RewardType, TransactionBinaryEncoding, TransactionConfirmationStatus, TransactionStatus, - UiConfirmedBlock, UiTransactionEncoding, + ConfirmedTransactionWithStatusMeta, EncodedConfirmedTransactionWithStatusMeta, + InnerInstruction, InnerInstructions, Reward, RewardType, TransactionBinaryEncoding, + TransactionConfirmationStatus, TransactionStatus, UiConfirmedBlock, UiTransactionEncoding, }, solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY}, spl_token_2022::{ @@ -3675,7 +3675,7 @@ pub mod rpc_full { post_simulation_accounts: _, units_consumed, return_data, - inner_instructions: _, + inner_instructions: _, // Always `None` due to `enable_cpi_recording = false` } = preflight_bank.simulate_transaction(transaction, false) { match err { @@ -3694,6 +3694,7 @@ pub mod rpc_full { accounts: None, units_consumed: Some(units_consumed), return_data: return_data.map(|return_data| return_data.into()), + inner_instructions: None, }, } .into()); @@ -3762,7 +3763,7 @@ pub mod rpc_full { post_simulation_accounts, units_consumed, return_data, - inner_instructions: _, + inner_instructions, } = bank.simulate_transaction(transaction, enable_cpi_recording); let accounts = if let Some(config_accounts) = config_accounts { @@ -3806,6 +3807,23 @@ pub mod rpc_full { None }; + let inner_instructions = inner_instructions.map(|info| { + info.into_iter() + .enumerate() + .map(|(index, instructions)| InnerInstructions { + index: index as u8, + instructions: instructions + .into_iter() + .map(|info| InnerInstruction { + stack_height: Some(u32::from(info.stack_height)), + instruction: info.instruction, + }) + .collect(), + }) + .filter(|i| !i.instructions.is_empty()) + .collect() + }); + Ok(new_response( bank, RpcSimulateTransactionResult { @@ -3814,6 +3832,7 @@ pub mod rpc_full { accounts, units_consumed: Some(units_consumed), return_data: return_data.map(|return_data| return_data.into()), + inner_instructions, }, )) } @@ -5912,6 +5931,7 @@ pub mod tests { } ], "err":null, + "innerInstructions": null, "logs":[ "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" @@ -5996,6 +6016,7 @@ pub mod tests { "value":{ "accounts":null, "err":null, + "innerInstructions":null, "logs":[ "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" @@ -6024,6 +6045,7 @@ pub mod tests { "value":{ "accounts":null, "err":null, + "innerInstructions":null, "logs":[ "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" @@ -6076,6 +6098,7 @@ pub mod tests { "value":{ "err":"BlockhashNotFound", "accounts":null, + "innerInstructions":null, "logs":[], "returnData":null, "unitsConsumed":0, @@ -6102,6 +6125,7 @@ pub mod tests { "value":{ "accounts":null, "err":null, + "innerInstructions":null, "logs":[ "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" @@ -6482,7 +6506,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":[],"returnData":null,"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","innerInstructions":null,"logs":[],"returnData":null,"unitsConsumed":0}},"id":1}"#.to_string(), ) );