rpc: add tests for simulate transaction inner instructions (#34495)
* rpc: add tests for simulate transaction inner instructions * update encoding * take out extra test case
This commit is contained in:
parent
45a2a701de
commit
9caf9e8f17
209
rpc/src/rpc.rs
209
rpc/src/rpc.rs
|
@ -6294,6 +6294,215 @@ pub mod tests {
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rpc_simulate_transaction_with_inner_instructions() {
|
||||||
|
let rpc = RpcHandler::start();
|
||||||
|
let bank = rpc.working_bank();
|
||||||
|
let recent_blockhash = bank.confirmed_last_blockhash();
|
||||||
|
let RpcHandler {
|
||||||
|
ref meta, ref io, ..
|
||||||
|
} = rpc;
|
||||||
|
|
||||||
|
let recent_slot = 123;
|
||||||
|
let mut slot_hashes = SlotHashes::default();
|
||||||
|
slot_hashes.add(recent_slot, Hash::new_unique());
|
||||||
|
bank.set_sysvar_for_tests(&slot_hashes);
|
||||||
|
|
||||||
|
let lookup_table_authority = Keypair::new();
|
||||||
|
let lookup_table_space = solana_sdk::address_lookup_table::state::LOOKUP_TABLE_META_SIZE;
|
||||||
|
let lookup_table_lamports = bank.get_minimum_balance_for_rent_exemption(lookup_table_space);
|
||||||
|
|
||||||
|
let (instruction, lookup_table_address) =
|
||||||
|
solana_sdk::address_lookup_table::instruction::create_lookup_table(
|
||||||
|
lookup_table_authority.pubkey(),
|
||||||
|
rpc.mint_keypair.pubkey(),
|
||||||
|
recent_slot,
|
||||||
|
);
|
||||||
|
let tx = Transaction::new_signed_with_payer(
|
||||||
|
&[instruction],
|
||||||
|
Some(&rpc.mint_keypair.pubkey()),
|
||||||
|
&[&rpc.mint_keypair],
|
||||||
|
recent_blockhash,
|
||||||
|
);
|
||||||
|
let tx_serialized_encoded =
|
||||||
|
base64::prelude::BASE64_STANDARD.encode(serialize(&tx).unwrap());
|
||||||
|
|
||||||
|
// Simulation bank must be frozen
|
||||||
|
bank.freeze();
|
||||||
|
|
||||||
|
// `innerInstructions` not provided, should not be in response
|
||||||
|
let req = format!(
|
||||||
|
r#"{{"jsonrpc":"2.0",
|
||||||
|
"id":1,
|
||||||
|
"method":"simulateTransaction",
|
||||||
|
"params":[
|
||||||
|
"{}",
|
||||||
|
{{ "encoding": "base64" }}
|
||||||
|
]
|
||||||
|
}}"#,
|
||||||
|
tx_serialized_encoded,
|
||||||
|
);
|
||||||
|
let res = io.handle_request_sync(&req, meta.clone());
|
||||||
|
let expected = json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"result": {
|
||||||
|
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||||
|
"value":{
|
||||||
|
"accounts": null,
|
||||||
|
"err":null,
|
||||||
|
"innerInstructions": null,
|
||||||
|
"logs":[
|
||||||
|
"Program AddressLookupTab1e1111111111111111111111111 invoke [1]",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [2]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [2]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [2]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program AddressLookupTab1e1111111111111111111111111 success"
|
||||||
|
],
|
||||||
|
"returnData":null,
|
||||||
|
"unitsConsumed":1200,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": 1,
|
||||||
|
});
|
||||||
|
let expected: Response =
|
||||||
|
serde_json::from_value(expected).expect("expected response deserialization");
|
||||||
|
let result: Response = serde_json::from_str(&res.expect("actual response"))
|
||||||
|
.expect("actual response deserialization");
|
||||||
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
// `innerInstructions` provided as `false`, should not be in response
|
||||||
|
let req = format!(
|
||||||
|
r#"{{"jsonrpc":"2.0",
|
||||||
|
"id":1,
|
||||||
|
"method":"simulateTransaction",
|
||||||
|
"params":[
|
||||||
|
"{}",
|
||||||
|
{{ "innerInstructions": false, "encoding": "base64" }}
|
||||||
|
]
|
||||||
|
}}"#,
|
||||||
|
tx_serialized_encoded,
|
||||||
|
);
|
||||||
|
let res = io.handle_request_sync(&req, meta.clone());
|
||||||
|
let expected = json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"result": {
|
||||||
|
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||||
|
"value":{
|
||||||
|
"accounts": null,
|
||||||
|
"err":null,
|
||||||
|
"innerInstructions": null,
|
||||||
|
"logs":[
|
||||||
|
"Program AddressLookupTab1e1111111111111111111111111 invoke [1]",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [2]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [2]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [2]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program AddressLookupTab1e1111111111111111111111111 success"
|
||||||
|
],
|
||||||
|
"returnData":null,
|
||||||
|
"unitsConsumed":1200,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": 1,
|
||||||
|
});
|
||||||
|
let expected: Response =
|
||||||
|
serde_json::from_value(expected).expect("expected response deserialization");
|
||||||
|
let result: Response = serde_json::from_str(&res.expect("actual response"))
|
||||||
|
.expect("actual response deserialization");
|
||||||
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
// `innerInstructions` provided as `true`, should have parsed inner instructions
|
||||||
|
let req = format!(
|
||||||
|
r#"{{"jsonrpc":"2.0",
|
||||||
|
"id":1,
|
||||||
|
"method":"simulateTransaction",
|
||||||
|
"params":[
|
||||||
|
"{}",
|
||||||
|
{{ "innerInstructions": true, "encoding": "base64" }}
|
||||||
|
]
|
||||||
|
}}"#,
|
||||||
|
tx_serialized_encoded,
|
||||||
|
);
|
||||||
|
let res = io.handle_request_sync(&req, meta.clone());
|
||||||
|
let expected = json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"result": {
|
||||||
|
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
|
||||||
|
"value":{
|
||||||
|
"accounts": null,
|
||||||
|
"err":null,
|
||||||
|
"innerInstructions": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"instructions": [
|
||||||
|
{
|
||||||
|
"parsed": {
|
||||||
|
"info": {
|
||||||
|
"destination": lookup_table_address.to_string(),
|
||||||
|
"lamports": lookup_table_lamports,
|
||||||
|
"source": rpc.mint_keypair.pubkey().to_string()
|
||||||
|
},
|
||||||
|
"type": "transfer"
|
||||||
|
},
|
||||||
|
"program": "system",
|
||||||
|
"programId": "11111111111111111111111111111111",
|
||||||
|
"stackHeight": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parsed": {
|
||||||
|
"info": {
|
||||||
|
"account": lookup_table_address.to_string(),
|
||||||
|
"space": lookup_table_space
|
||||||
|
},
|
||||||
|
"type": "allocate"
|
||||||
|
},
|
||||||
|
"program": "system",
|
||||||
|
"programId": "11111111111111111111111111111111",
|
||||||
|
"stackHeight": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parsed": {
|
||||||
|
"info": {
|
||||||
|
"account": lookup_table_address.to_string(),
|
||||||
|
"owner": "AddressLookupTab1e1111111111111111111111111"
|
||||||
|
},
|
||||||
|
"type": "assign"
|
||||||
|
},
|
||||||
|
"program": "system",
|
||||||
|
"programId": "11111111111111111111111111111111",
|
||||||
|
"stackHeight": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"logs":[
|
||||||
|
"Program AddressLookupTab1e1111111111111111111111111 invoke [1]",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [2]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [2]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [2]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program AddressLookupTab1e1111111111111111111111111 success"
|
||||||
|
],
|
||||||
|
"returnData":null,
|
||||||
|
"unitsConsumed":1200,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": 1,
|
||||||
|
});
|
||||||
|
let expected: Response =
|
||||||
|
serde_json::from_value(expected).expect("expected response deserialization");
|
||||||
|
let result: Response = serde_json::from_str(&res.expect("actual response"))
|
||||||
|
.expect("actual response deserialization");
|
||||||
|
assert_eq!(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "simulation bank must be frozen")]
|
#[should_panic(expected = "simulation bank must be frozen")]
|
||||||
fn test_rpc_simulate_transaction_panic_on_unfrozen_bank() {
|
fn test_rpc_simulate_transaction_panic_on_unfrozen_bank() {
|
||||||
|
|
Loading…
Reference in New Issue