From 43cc2dd43494c12b50e8cd0fd6be1200379199d1 Mon Sep 17 00:00:00 2001 From: Jon C Date: Tue, 24 Sep 2024 11:07:46 +0200 Subject: [PATCH] cli: Use simulated compute units in vote interactions (#2696) * cli: Add simulated compute units to vote interactions #### Problem The CLI can simulate to get the compute budget used by a transaction, but vote interactions are still using the default compute unit limit. #### Summary of changes Add tests for setting a compute unit price with `test_case`, and then change the compute unit limit to `Simulated`. * Use simulated compute units * Fix rebase issues --- cli/src/vote.rs | 48 ++++++++++++++++++++++++++++++++++++----------- cli/tests/vote.rs | 47 ++++++++++++++++++++++++---------------------- 2 files changed, 62 insertions(+), 33 deletions(-) diff --git a/cli/src/vote.rs b/cli/src/vote.rs index 2e451a3d7f2150..66b925d9b88418 100644 --- a/cli/src/vote.rs +++ b/cli/src/vote.rs @@ -5,7 +5,9 @@ use { log_instruction_custom_error, CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult, }, - compute_budget::{ComputeUnitConfig, WithComputeUnitConfig}, + compute_budget::{ + simulate_and_update_compute_unit_limit, ComputeUnitConfig, WithComputeUnitConfig, + }, memo::WithMemo, nonce::check_nonce_account, spend_utils::{resolve_spend_tx_and_check_account_balances, SpendAmount}, @@ -821,7 +823,10 @@ pub fn process_create_vote_account( let nonce_authority = config.signers[nonce_authority]; let space = VoteStateVersions::vote_state_size_of(true) as u64; - let compute_unit_limit = ComputeUnitLimit::Default; + let compute_unit_limit = match blockhash_query { + BlockhashQuery::None(_) | BlockhashQuery::FeeCalculator(_, _) => ComputeUnitLimit::Default, + BlockhashQuery::All(_) => ComputeUnitLimit::Simulated, + }; let build_message = |lamports| { let vote_init = VoteInit { node_pubkey: identity_pubkey, @@ -1001,11 +1006,16 @@ pub fn process_vote_authorize( vote_authorize, // vote or withdraw ) }; + + let compute_unit_limit = match blockhash_query { + BlockhashQuery::None(_) | BlockhashQuery::FeeCalculator(_, _) => ComputeUnitLimit::Default, + BlockhashQuery::All(_) => ComputeUnitLimit::Simulated, + }; let ixs = vec![vote_ix] .with_memo(memo) .with_compute_unit_config(&ComputeUnitConfig { compute_unit_price, - compute_unit_limit: ComputeUnitLimit::Default, + compute_unit_limit, }); let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?; @@ -1013,7 +1023,7 @@ pub fn process_vote_authorize( let nonce_authority = config.signers[nonce_authority]; let fee_payer = config.signers[fee_payer]; - let message = if let Some(nonce_account) = &nonce_account { + let mut message = if let Some(nonce_account) = &nonce_account { Message::new_with_nonce( ixs, Some(&fee_payer.pubkey()), @@ -1023,6 +1033,7 @@ pub fn process_vote_authorize( } else { Message::new(&ixs, Some(&fee_payer.pubkey())) }; + simulate_and_update_compute_unit_limit(&compute_unit_limit, rpc_client, &mut message)?; let mut tx = Transaction::new_unsigned(message); if sign_only { @@ -1079,6 +1090,10 @@ pub fn process_vote_update_validator( (&new_identity_pubkey, "new_identity_account".to_string()), )?; let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?; + let compute_unit_limit = match blockhash_query { + BlockhashQuery::None(_) | BlockhashQuery::FeeCalculator(_, _) => ComputeUnitLimit::Default, + BlockhashQuery::All(_) => ComputeUnitLimit::Simulated, + }; let ixs = vec![vote_instruction::update_validator_identity( vote_account_pubkey, &authorized_withdrawer.pubkey(), @@ -1087,12 +1102,12 @@ pub fn process_vote_update_validator( .with_memo(memo) .with_compute_unit_config(&ComputeUnitConfig { compute_unit_price, - compute_unit_limit: ComputeUnitLimit::Default, + compute_unit_limit, }); let nonce_authority = config.signers[nonce_authority]; let fee_payer = config.signers[fee_payer]; - let message = if let Some(nonce_account) = &nonce_account { + let mut message = if let Some(nonce_account) = &nonce_account { Message::new_with_nonce( ixs, Some(&fee_payer.pubkey()), @@ -1102,6 +1117,7 @@ pub fn process_vote_update_validator( } else { Message::new(&ixs, Some(&fee_payer.pubkey())) }; + simulate_and_update_compute_unit_limit(&compute_unit_limit, rpc_client, &mut message)?; let mut tx = Transaction::new_unsigned(message); if sign_only { @@ -1152,6 +1168,10 @@ pub fn process_vote_update_commission( ) -> ProcessResult { let authorized_withdrawer = config.signers[withdraw_authority]; let recent_blockhash = blockhash_query.get_blockhash(rpc_client, config.commitment)?; + let compute_unit_limit = match blockhash_query { + BlockhashQuery::None(_) | BlockhashQuery::FeeCalculator(_, _) => ComputeUnitLimit::Default, + BlockhashQuery::All(_) => ComputeUnitLimit::Simulated, + }; let ixs = vec![vote_instruction::update_commission( vote_account_pubkey, &authorized_withdrawer.pubkey(), @@ -1160,12 +1180,12 @@ pub fn process_vote_update_commission( .with_memo(memo) .with_compute_unit_config(&ComputeUnitConfig { compute_unit_price, - compute_unit_limit: ComputeUnitLimit::Default, + compute_unit_limit, }); let nonce_authority = config.signers[nonce_authority]; let fee_payer = config.signers[fee_payer]; - let message = if let Some(nonce_account) = &nonce_account { + let mut message = if let Some(nonce_account) = &nonce_account { Message::new_with_nonce( ixs, Some(&fee_payer.pubkey()), @@ -1175,6 +1195,7 @@ pub fn process_vote_update_commission( } else { Message::new(&ixs, Some(&fee_payer.pubkey())) }; + simulate_and_update_compute_unit_limit(&compute_unit_limit, rpc_client, &mut message)?; let mut tx = Transaction::new_unsigned(message); if sign_only { tx.try_partial_sign(&config.signers, recent_blockhash)?; @@ -1318,7 +1339,10 @@ pub fn process_withdraw_from_vote_account( let fee_payer = config.signers[fee_payer]; let nonce_authority = config.signers[nonce_authority]; - let compute_unit_limit = ComputeUnitLimit::Default; + let compute_unit_limit = match blockhash_query { + BlockhashQuery::None(_) | BlockhashQuery::FeeCalculator(_, _) => ComputeUnitLimit::Default, + BlockhashQuery::All(_) => ComputeUnitLimit::Simulated, + }; let build_message = |lamports| { let ixs = vec![withdraw( vote_account_pubkey, @@ -1441,6 +1465,7 @@ pub fn process_close_vote_account( let current_balance = rpc_client.get_balance(vote_account_pubkey)?; + let compute_unit_limit = ComputeUnitLimit::Simulated; let ixs = vec![withdraw( vote_account_pubkey, &withdraw_authority.pubkey(), @@ -1450,10 +1475,11 @@ pub fn process_close_vote_account( .with_memo(memo) .with_compute_unit_config(&ComputeUnitConfig { compute_unit_price, - compute_unit_limit: ComputeUnitLimit::Default, + compute_unit_limit, }); - let message = Message::new(&ixs, Some(&fee_payer.pubkey())); + let mut message = Message::new(&ixs, Some(&fee_payer.pubkey())); + simulate_and_update_compute_unit_limit(&compute_unit_limit, rpc_client, &mut message)?; let mut tx = Transaction::new_unsigned(message); tx.try_sign(&config.signers, latest_blockhash)?; check_account_for_fee_with_commitment( diff --git a/cli/tests/vote.rs b/cli/tests/vote.rs index fb83d232a6f557..2a3f1104526186 100644 --- a/cli/tests/vote.rs +++ b/cli/tests/vote.rs @@ -17,10 +17,12 @@ use { solana_streamer::socket::SocketAddrSpace, solana_test_validator::TestValidator, solana_vote_program::vote_state::{VoteAuthorize, VoteState, VoteStateVersions}, + test_case::test_case, }; -#[test] -fn test_vote_authorize_and_withdraw() { +#[test_case(None; "base")] +#[test_case(Some(1_000_000); "with_compute_unit_price")] +fn test_vote_authorize_and_withdraw(compute_unit_price: Option) { let mint_keypair = Keypair::new(); let mint_pubkey = mint_keypair.pubkey(); let faucet_addr = run_local_faucet(mint_keypair, None); @@ -56,7 +58,7 @@ fn test_vote_authorize_and_withdraw() { nonce_authority: 0, memo: None, fee_payer: 0, - compute_unit_price: None, + compute_unit_price, }; process_command(&config).unwrap(); let vote_account = rpc_client @@ -88,7 +90,7 @@ fn test_vote_authorize_and_withdraw() { fee_payer: 0, derived_address_seed: None, derived_address_program_id: None, - compute_unit_price: None, + compute_unit_price, }; process_command(&config).unwrap(); let expected_balance = expected_balance + 10_000; @@ -110,7 +112,7 @@ fn test_vote_authorize_and_withdraw() { fee_payer: 0, authorized: 0, new_authorized: None, - compute_unit_price: None, + compute_unit_price, }; process_command(&config).unwrap(); let vote_account = rpc_client @@ -136,7 +138,7 @@ fn test_vote_authorize_and_withdraw() { fee_payer: 0, authorized: 1, new_authorized: Some(1), - compute_unit_price: None, + compute_unit_price, }; process_command(&config).unwrap_err(); // unsigned by new authority should fail config.signers = vec![ @@ -157,7 +159,7 @@ fn test_vote_authorize_and_withdraw() { fee_payer: 0, authorized: 1, new_authorized: Some(2), - compute_unit_price: None, + compute_unit_price, }; process_command(&config).unwrap(); let vote_account = rpc_client @@ -182,7 +184,7 @@ fn test_vote_authorize_and_withdraw() { nonce_authority: 0, memo: None, fee_payer: 0, - compute_unit_price: None, + compute_unit_price, }; process_command(&config).unwrap(); let expected_balance = expected_balance - 1_000; @@ -203,7 +205,7 @@ fn test_vote_authorize_and_withdraw() { nonce_authority: 0, memo: None, fee_payer: 0, - compute_unit_price: None, + compute_unit_price, }; process_command(&config).unwrap(); @@ -216,15 +218,16 @@ fn test_vote_authorize_and_withdraw() { destination_account_pubkey: destination_account, memo: None, fee_payer: 0, - compute_unit_price: None, + compute_unit_price, }; process_command(&config).unwrap(); check_balance!(0, &rpc_client, &vote_account_pubkey); check_balance!(expected_balance, &rpc_client, &destination_account); } -#[test] -fn test_offline_vote_authorize_and_withdraw() { +#[test_case(None; "base")] +#[test_case(Some(1_000_000); "with_compute_unit_price")] +fn test_offline_vote_authorize_and_withdraw(compute_unit_price: Option) { let mint_keypair = Keypair::new(); let mint_pubkey = mint_keypair.pubkey(); let faucet_addr = run_local_faucet(mint_keypair, None); @@ -283,7 +286,7 @@ fn test_offline_vote_authorize_and_withdraw() { nonce_authority: 0, memo: None, fee_payer: 0, - compute_unit_price: None, + compute_unit_price, }; process_command(&config_payer).unwrap(); let vote_account = rpc_client @@ -315,7 +318,7 @@ fn test_offline_vote_authorize_and_withdraw() { fee_payer: 0, derived_address_seed: None, derived_address_program_id: None, - compute_unit_price: None, + compute_unit_price, }; process_command(&config_payer).unwrap(); let expected_balance = expected_balance + 10_000; @@ -337,7 +340,7 @@ fn test_offline_vote_authorize_and_withdraw() { fee_payer: 0, authorized: 0, new_authorized: None, - compute_unit_price: None, + compute_unit_price, }; config_offline.output_format = OutputFormat::JsonCompact; let sig_response = process_command(&config_offline).unwrap(); @@ -360,7 +363,7 @@ fn test_offline_vote_authorize_and_withdraw() { fee_payer: 0, authorized: 0, new_authorized: None, - compute_unit_price: None, + compute_unit_price, }; process_command(&config_payer).unwrap(); let vote_account = rpc_client @@ -387,7 +390,7 @@ fn test_offline_vote_authorize_and_withdraw() { nonce_authority: 0, memo: None, fee_payer: 0, - compute_unit_price: None, + compute_unit_price, }; config_offline.output_format = OutputFormat::JsonCompact; let sig_response = process_command(&config_offline).unwrap(); @@ -408,7 +411,7 @@ fn test_offline_vote_authorize_and_withdraw() { nonce_authority: 0, memo: None, fee_payer: 0, - compute_unit_price: None, + compute_unit_price, }; process_command(&config_payer).unwrap(); let expected_balance = expected_balance - 1_000; @@ -435,7 +438,7 @@ fn test_offline_vote_authorize_and_withdraw() { nonce_authority: 0, memo: None, fee_payer: 0, - compute_unit_price: None, + compute_unit_price, }; process_command(&config_offline).unwrap(); config_offline.output_format = OutputFormat::JsonCompact; @@ -456,7 +459,7 @@ fn test_offline_vote_authorize_and_withdraw() { nonce_authority: 0, memo: None, fee_payer: 0, - compute_unit_price: None, + compute_unit_price, }; process_command(&config_payer).unwrap(); @@ -476,7 +479,7 @@ fn test_offline_vote_authorize_and_withdraw() { nonce_authority: 0, memo: None, fee_payer: 0, - compute_unit_price: None, + compute_unit_price, }; process_command(&config_offline).unwrap(); config_offline.output_format = OutputFormat::JsonCompact; @@ -498,7 +501,7 @@ fn test_offline_vote_authorize_and_withdraw() { nonce_authority: 0, memo: None, fee_payer: 0, - compute_unit_price: None, + compute_unit_price, }; process_command(&config_payer).unwrap(); check_balance!(0, &rpc_client, &vote_account_pubkey);