diff --git a/cli/src/program.rs b/cli/src/program.rs index 92c3c657adc40a..d2b470aebcabb8 100644 --- a/cli/src/program.rs +++ b/cli/src/program.rs @@ -48,6 +48,7 @@ use { account_utils::StateMut, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable::{self, UpgradeableLoaderState}, + compute_budget, feature_set::FeatureSet, instruction::{Instruction, InstructionError}, loader_instruction, @@ -90,6 +91,7 @@ pub enum ProgramCliCommand { max_len: Option, allow_excessive_balance: bool, skip_fee_check: bool, + prioritization_fees: Option, }, Upgrade { fee_payer_signer_index: SignerIndex, @@ -99,6 +101,7 @@ pub enum ProgramCliCommand { sign_only: bool, dump_transaction_message: bool, blockhash_query: BlockhashQuery, + prioritization_fees: Option, }, WriteBuffer { program_location: String, @@ -108,6 +111,7 @@ pub enum ProgramCliCommand { buffer_authority_signer_index: SignerIndex, max_len: Option, skip_fee_check: bool, + prioritization_fees: Option, }, SetBufferAuthority { buffer_pubkey: Pubkey, @@ -228,6 +232,17 @@ impl ProgramSubCommands for App<'_, '_> { [default: the length of the original deployed program]", ), ) + .arg( + Arg::with_name("prioritization_fee") + .long("prioritization-fee") + .value_name("prioritization_fee") + .takes_value(true) + .required(false) + .help( + "Prioritization fees for each transaction created to deploy program \ + [default: the prioritization fee of the original deployed program]", + ), + ) .arg( Arg::with_name("allow_excessive_balance") .long("allow-excessive-deploy-account-balance") @@ -266,6 +281,17 @@ impl ProgramSubCommands for App<'_, '_> { "Upgrade authority [default: the default configured keypair]", ), ) + .arg( + Arg::with_name("prioritization_fee") + .long("prioritization-fee") + .value_name("prioritization_fee") + .takes_value(true) + .required(false) + .help( + "Prioritization fees for each transaction created to deploy program \ + [default: the prioritization fee of the original deployed program]", + ), + ) .offline_args(), ) .subcommand( @@ -308,6 +334,17 @@ impl ProgramSubCommands for App<'_, '_> { "Maximum length of the upgradeable program \ [default: the length of the original deployed program]", ), + ) + .arg( + Arg::with_name("prioritization_fee") + .long("prioritization-fee") + .value_name("prioritization_fee") + .takes_value(true) + .required(false) + .help( + "Prioritization fees for each transaction created to deploy program \ + [default: the prioritization fee of the original deployed program]", + ), ), ) .subcommand( @@ -597,6 +634,7 @@ pub fn parse_program_subcommand( bulk_signers.push(upgrade_authority); let max_len = value_of(matches, "max_len"); + let prioritization_fees = value_of(matches, "prioritization_fee"); let signer_info = default_signer.generate_unique_signers(bulk_signers, matches, wallet_manager)?; @@ -616,6 +654,7 @@ pub fn parse_program_subcommand( max_len, allow_excessive_balance: matches.is_present("allow_excessive_balance"), skip_fee_check, + prioritization_fees, }), signers: signer_info.signers, } @@ -645,6 +684,7 @@ pub fn parse_program_subcommand( let signer_info = default_signer.generate_unique_signers(bulk_signers, matches, wallet_manager)?; + let prioritization_fees = value_of(matches, "prioritization_fee"); CliCommandInfo { command: CliCommand::Program(ProgramCliCommand::Upgrade { fee_payer_signer_index: signer_info.index_of(fee_payer_pubkey).unwrap(), @@ -656,6 +696,7 @@ pub fn parse_program_subcommand( sign_only, dump_transaction_message, blockhash_query, + prioritization_fees, }), signers: signer_info.signers, } @@ -687,6 +728,7 @@ pub fn parse_program_subcommand( let signer_info = default_signer.generate_unique_signers(bulk_signers, matches, wallet_manager)?; + let prioritization_fees = value_of(matches, "prioritization_fee"); CliCommandInfo { command: CliCommand::Program(ProgramCliCommand::WriteBuffer { program_location: matches.value_of("program_location").unwrap().to_string(), @@ -698,6 +740,7 @@ pub fn parse_program_subcommand( .unwrap(), max_len, skip_fee_check, + prioritization_fees, }), signers: signer_info.signers, } @@ -899,6 +942,7 @@ pub fn process_program_subcommand( max_len, allow_excessive_balance, skip_fee_check, + prioritization_fees, } => process_program_deploy( rpc_client, config, @@ -913,6 +957,7 @@ pub fn process_program_subcommand( *max_len, *allow_excessive_balance, *skip_fee_check, + *prioritization_fees, ), ProgramCliCommand::Upgrade { fee_payer_signer_index, @@ -922,6 +967,7 @@ pub fn process_program_subcommand( sign_only, dump_transaction_message, blockhash_query, + prioritization_fees, } => process_program_upgrade( rpc_client, config, @@ -932,6 +978,7 @@ pub fn process_program_subcommand( *sign_only, *dump_transaction_message, blockhash_query, + *prioritization_fees, ), ProgramCliCommand::WriteBuffer { program_location, @@ -941,6 +988,7 @@ pub fn process_program_subcommand( buffer_authority_signer_index, max_len, skip_fee_check, + prioritization_fees, } => process_write_buffer( rpc_client, config, @@ -951,6 +999,7 @@ pub fn process_program_subcommand( *buffer_authority_signer_index, *max_len, *skip_fee_check, + *prioritization_fees, ), ProgramCliCommand::SetBufferAuthority { buffer_pubkey, @@ -1091,6 +1140,7 @@ fn process_program_deploy( max_len: Option, allow_excessive_balance: bool, skip_fee_check: bool, + prioritization_fees: Option, ) -> ProcessResult { let fee_payer_signer = config.signers[fee_payer_signer_index]; let upgrade_authority_signer = config.signers[upgrade_authority_signer_index]; @@ -1230,6 +1280,7 @@ fn process_program_deploy( upgrade_authority_signer, allow_excessive_balance, skip_fee_check, + prioritization_fees, ) } else { do_process_program_upgrade( @@ -1244,6 +1295,7 @@ fn process_program_deploy( &buffer_pubkey, buffer_signer, skip_fee_check, + prioritization_fees, ) }; if result.is_ok() && is_final { @@ -1329,22 +1381,29 @@ fn process_program_upgrade( sign_only: bool, dump_transaction_message: bool, blockhash_query: &BlockhashQuery, + prioritization_fees: Option, ) -> ProcessResult { let fee_payer_signer = config.signers[fee_payer_signer_index]; let upgrade_authority_signer = config.signers[upgrade_authority_signer_index]; let blockhash = blockhash_query.get_blockhash(&rpc_client, config.commitment)?; - let message = Message::new_with_blockhash( - &[bpf_loader_upgradeable::upgrade( - &program_id, - &buffer_pubkey, - &upgrade_authority_signer.pubkey(), - &fee_payer_signer.pubkey(), - )], - Some(&fee_payer_signer.pubkey()), - &blockhash, + let upgrade_instruction = bpf_loader_upgradeable::upgrade( + &program_id, + &buffer_pubkey, + &upgrade_authority_signer.pubkey(), + &fee_payer_signer.pubkey(), ); + let ixs = match prioritization_fees { + Some(fees) => vec![ + compute_budget::ComputeBudgetInstruction::set_compute_unit_price(fees), + upgrade_instruction, + ], + None => vec![upgrade_instruction], + }; + + let message = Message::new_with_blockhash(&ixs, Some(&fee_payer_signer.pubkey()), &blockhash); + if sign_only { let mut tx = Transaction::new_unsigned(message); let signers = &[fee_payer_signer, upgrade_authority_signer]; @@ -1381,6 +1440,7 @@ fn process_program_upgrade( } } +#[allow(clippy::too_many_arguments)] fn process_write_buffer( rpc_client: Arc, config: &CliConfig, @@ -1391,6 +1451,7 @@ fn process_write_buffer( buffer_authority_signer_index: SignerIndex, max_len: Option, skip_fee_check: bool, + prioritization_fees: Option, ) -> ProcessResult { let fee_payer_signer = config.signers[fee_payer_signer_index]; let buffer_authority = config.signers[buffer_authority_signer_index]; @@ -1456,6 +1517,7 @@ fn process_write_buffer( buffer_authority, true, skip_fee_check, + prioritization_fees, ); if result.is_err() && buffer_signer_index.is_none() && buffer_signer.is_some() { report_ephemeral_mnemonic(words, mnemonic); @@ -2176,11 +2238,14 @@ fn process_extend_program( })) } -pub fn calculate_max_chunk_size(create_msg: &F) -> usize +pub fn calculate_max_chunk_size( + create_msg: &F, + prioritization_fee_ix: Option, +) -> usize where - F: Fn(u32, Vec) -> Message, + F: Fn(u32, Vec, Option) -> Message, { - let baseline_msg = create_msg(0, Vec::new()); + let baseline_msg = create_msg(0, Vec::new(), prioritization_fee_ix); let tx_size = bincode::serialized_size(&Transaction { signatures: vec![ Signature::default(); @@ -2209,11 +2274,14 @@ fn do_process_program_write_and_deploy( buffer_authority_signer: &dyn Signer, allow_excessive_balance: bool, skip_fee_check: bool, + prioritization_fees: Option, ) -> ProcessResult { let blockhash = rpc_client.get_latest_blockhash()?; + let prioritization_ix = + prioritization_fees.map(compute_budget::ComputeBudgetInstruction::set_compute_unit_price); // Initialize buffer account or complete if already partially initialized - let (initial_instructions, balance_needed) = if let Some(account) = rpc_client + let (mut initial_instructions, balance_needed) = if let Some(account) = rpc_client .get_account_with_commitment(buffer_pubkey, config.commitment)? .value { @@ -2254,6 +2322,9 @@ fn do_process_program_write_and_deploy( ) }; let initial_message = if !initial_instructions.is_empty() { + if let Some(prioritization_ix) = &prioritization_ix { + initial_instructions.push(prioritization_ix.clone()); + } Some(Message::new_with_blockhash( &initial_instructions, Some(&fee_payer_signer.pubkey()), @@ -2264,8 +2335,8 @@ fn do_process_program_write_and_deploy( }; // Create and add write messages - let create_msg = |offset: u32, bytes: Vec| { - let instruction = if loader_id == &bpf_loader_upgradeable::id() { + let create_msg = |offset: u32, bytes: Vec, prioritization_ix: Option| { + let instruction: Instruction = if loader_id == &bpf_loader_upgradeable::id() { bpf_loader_upgradeable::write( buffer_pubkey, &buffer_authority_signer.pubkey(), @@ -2275,38 +2346,47 @@ fn do_process_program_write_and_deploy( } else { loader_instruction::write(buffer_pubkey, loader_id, offset, bytes) }; - Message::new_with_blockhash(&[instruction], Some(&fee_payer_signer.pubkey()), &blockhash) + let ixs = match prioritization_ix { + Some(prioritization_ix) => vec![prioritization_ix, instruction], + None => vec![instruction], + }; + Message::new_with_blockhash(&ixs, Some(&fee_payer_signer.pubkey()), &blockhash) }; let mut write_messages = vec![]; - let chunk_size = calculate_max_chunk_size(&create_msg); + let chunk_size = calculate_max_chunk_size(&create_msg, prioritization_ix.clone()); for (chunk, i) in program_data.chunks(chunk_size).zip(0..) { - write_messages.push(create_msg((i * chunk_size) as u32, chunk.to_vec())); + write_messages.push(create_msg( + (i * chunk_size) as u32, + chunk.to_vec(), + prioritization_ix.clone(), + )); } // Create and add final message let final_message = if let Some(program_signers) = program_signers { let message = if loader_id == &bpf_loader_upgradeable::id() { - Message::new_with_blockhash( - &bpf_loader_upgradeable::deploy_with_max_program_len( - &fee_payer_signer.pubkey(), - &program_signers[0].pubkey(), - buffer_pubkey, - &program_signers[1].pubkey(), - rpc_client.get_minimum_balance_for_rent_exemption( - UpgradeableLoaderState::size_of_program(), - )?, - program_data_max_len, + let mut ixs = bpf_loader_upgradeable::deploy_with_max_program_len( + &fee_payer_signer.pubkey(), + &program_signers[0].pubkey(), + buffer_pubkey, + &program_signers[1].pubkey(), + rpc_client.get_minimum_balance_for_rent_exemption( + UpgradeableLoaderState::size_of_program(), )?, - Some(&fee_payer_signer.pubkey()), - &blockhash, - ) + program_data_max_len, + )?; + + if let Some(prioritization_ix) = &prioritization_ix { + ixs.push(prioritization_ix.clone()); + } + Message::new_with_blockhash(&ixs, Some(&fee_payer_signer.pubkey()), &blockhash) } else { - Message::new_with_blockhash( - &[loader_instruction::finalize(buffer_pubkey, loader_id)], - Some(&fee_payer_signer.pubkey()), - &blockhash, - ) + let mut ixs = vec![loader_instruction::finalize(buffer_pubkey, loader_id)]; + if let Some(prioritization_ix) = &prioritization_ix { + ixs.push(prioritization_ix.clone()); + } + Message::new_with_blockhash(&ixs, Some(&fee_payer_signer.pubkey()), &blockhash) }; Some(message) } else { @@ -2364,75 +2444,84 @@ fn do_process_program_upgrade( buffer_pubkey: &Pubkey, buffer_signer: Option<&dyn Signer>, skip_fee_check: bool, + prioritization_fees: Option, ) -> ProcessResult { let blockhash = rpc_client.get_latest_blockhash()?; + let prioritization_ix = + prioritization_fees.map(compute_budget::ComputeBudgetInstruction::set_compute_unit_price); - let (initial_message, write_messages, balance_needed) = - if let Some(buffer_signer) = buffer_signer { - // Check Buffer account to see if partial initialization has occurred - let (initial_instructions, balance_needed) = if let Some(account) = rpc_client - .get_account_with_commitment(&buffer_signer.pubkey(), config.commitment)? - .value - { - complete_partial_program_init( - &bpf_loader_upgradeable::id(), + let (initial_message, write_messages, balance_needed) = if let Some(buffer_signer) = + buffer_signer + { + // Check Buffer account to see if partial initialization has occurred + let (initial_instructions, balance_needed) = if let Some(account) = rpc_client + .get_account_with_commitment(&buffer_signer.pubkey(), config.commitment)? + .value + { + complete_partial_program_init( + &bpf_loader_upgradeable::id(), + &fee_payer_signer.pubkey(), + &buffer_signer.pubkey(), + &account, + UpgradeableLoaderState::size_of_buffer(program_len), + min_rent_exempt_program_data_balance, + true, + )? + } else { + ( + bpf_loader_upgradeable::create_buffer( &fee_payer_signer.pubkey(), - &buffer_signer.pubkey(), - &account, - UpgradeableLoaderState::size_of_buffer(program_len), - min_rent_exempt_program_data_balance, - true, - )? - } else { - ( - bpf_loader_upgradeable::create_buffer( - &fee_payer_signer.pubkey(), - buffer_pubkey, - &upgrade_authority.pubkey(), - min_rent_exempt_program_data_balance, - program_len, - )?, + buffer_pubkey, + &upgrade_authority.pubkey(), min_rent_exempt_program_data_balance, - ) - }; + program_len, + )?, + min_rent_exempt_program_data_balance, + ) + }; - let initial_message = if !initial_instructions.is_empty() { - Some(Message::new_with_blockhash( - &initial_instructions, - Some(&fee_payer_signer.pubkey()), - &blockhash, - )) - } else { - None - }; + let initial_message = if !initial_instructions.is_empty() { + Some(Message::new_with_blockhash( + &initial_instructions, + Some(&fee_payer_signer.pubkey()), + &blockhash, + )) + } else { + None + }; - let buffer_signer_pubkey = buffer_signer.pubkey(); - let upgrade_authority_pubkey = upgrade_authority.pubkey(); - let create_msg = |offset: u32, bytes: Vec| { - let instruction = bpf_loader_upgradeable::write( - &buffer_signer_pubkey, - &upgrade_authority_pubkey, - offset, - bytes, - ); - Message::new_with_blockhash( - &[instruction], - Some(&fee_payer_signer.pubkey()), - &blockhash, - ) + let buffer_signer_pubkey = buffer_signer.pubkey(); + let upgrade_authority_pubkey = upgrade_authority.pubkey(); + let create_msg = |offset: u32, bytes: Vec, prioritization_ix: Option| { + let instruction = bpf_loader_upgradeable::write( + &buffer_signer_pubkey, + &upgrade_authority_pubkey, + offset, + bytes, + ); + + let ixs = match &prioritization_ix { + Some(prioritization_ix) => vec![prioritization_ix.clone(), instruction], + None => vec![instruction], }; + Message::new_with_blockhash(&ixs, Some(&fee_payer_signer.pubkey()), &blockhash) + }; - // Create and add write messages - let mut write_messages = vec![]; - let chunk_size = calculate_max_chunk_size(&create_msg); - for (chunk, i) in program_data.chunks(chunk_size).zip(0..) { - write_messages.push(create_msg((i * chunk_size) as u32, chunk.to_vec())); - } + // Create and add write messages + let mut write_messages = vec![]; + let chunk_size = calculate_max_chunk_size(&create_msg, prioritization_ix.clone()); + for (chunk, i) in program_data.chunks(chunk_size).zip(0..) { + write_messages.push(create_msg( + (i * chunk_size) as u32, + chunk.to_vec(), + prioritization_ix.clone(), + )); + } - (initial_message, write_messages, balance_needed) - } else { - (None, vec![], 0) - }; + (initial_message, write_messages, balance_needed) + } else { + (None, vec![], 0) + }; // Create and add final message let final_message = Message::new_with_blockhash( @@ -2788,6 +2877,7 @@ mod tests { max_len: None, allow_excessive_balance: false, skip_fee_check: false, + prioritization_fees: None, }), signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())], } @@ -2816,6 +2906,7 @@ mod tests { max_len: Some(42), allow_excessive_balance: false, skip_fee_check: false, + prioritization_fees: None, }), signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())], } @@ -2846,6 +2937,7 @@ mod tests { max_len: None, allow_excessive_balance: false, skip_fee_check: false, + prioritization_fees: None, }), signers: vec![ Box::new(read_keypair_file(&keypair_file).unwrap()), @@ -2878,6 +2970,7 @@ mod tests { max_len: None, allow_excessive_balance: false, skip_fee_check: false, + prioritization_fees: None, }), signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())], } @@ -2909,6 +3002,7 @@ mod tests { max_len: None, allow_excessive_balance: false, skip_fee_check: false, + prioritization_fees: None, }), signers: vec![ Box::new(read_keypair_file(&keypair_file).unwrap()), @@ -2943,6 +3037,7 @@ mod tests { max_len: None, allow_excessive_balance: false, skip_fee_check: false, + prioritization_fees: None, }), signers: vec![ Box::new(read_keypair_file(&keypair_file).unwrap()), @@ -2973,6 +3068,38 @@ mod tests { max_len: None, skip_fee_check: false, allow_excessive_balance: false, + prioritization_fees: None, + }), + signers: vec![read_keypair_file(&keypair_file).unwrap().into()], + } + ); + + let test_command = test_commands.clone().get_matches_from(vec![ + "test", + "program", + "deploy", + "/Users/test/program.so", + "--max-len", + "42", + "--prioritization-fees", + "100", + ]); + assert_eq!( + parse_command(&test_command, &default_signer, &mut None).unwrap(), + CliCommandInfo { + command: CliCommand::Program(ProgramCliCommand::Deploy { + program_location: Some("/Users/test/program.so".to_string()), + fee_payer_signer_index: 0, + buffer_signer_index: None, + buffer_pubkey: None, + program_signer_index: None, + program_pubkey: None, + upgrade_authority_signer_index: 0, + is_final: false, + max_len: Some(42), + allow_excessive_balance: false, + skip_fee_check: false, + prioritization_fees: Some(100), }), signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())], } @@ -3007,6 +3134,7 @@ mod tests { buffer_authority_signer_index: 0, max_len: None, skip_fee_check: false, + prioritization_fees: None, }), signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())], } @@ -3032,6 +3160,7 @@ mod tests { buffer_authority_signer_index: 0, max_len: Some(42), skip_fee_check: false, + prioritization_fees: None, }), signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())], } @@ -3060,6 +3189,7 @@ mod tests { buffer_authority_signer_index: 0, max_len: None, skip_fee_check: false, + prioritization_fees: None, }), signers: vec![ Box::new(read_keypair_file(&keypair_file).unwrap()), @@ -3091,6 +3221,7 @@ mod tests { buffer_authority_signer_index: 1, max_len: None, skip_fee_check: false, + prioritization_fees: None, }), signers: vec![ Box::new(read_keypair_file(&keypair_file).unwrap()), @@ -3127,6 +3258,7 @@ mod tests { buffer_authority_signer_index: 2, max_len: None, skip_fee_check: false, + prioritization_fees: None, }), signers: vec![ Box::new(read_keypair_file(&keypair_file).unwrap()), @@ -3685,6 +3817,7 @@ mod tests { max_len: None, allow_excessive_balance: false, skip_fee_check: false, + prioritization_fees: None, }), signers: vec![&default_keypair], output_format: OutputFormat::JsonCompact, diff --git a/cli/src/program_v4.rs b/cli/src/program_v4.rs index 115f902127ad14..93baeb89339650 100644 --- a/cli/src/program_v4.rs +++ b/cli/src/program_v4.rs @@ -585,16 +585,16 @@ pub fn process_deploy_program( }; // Create and add write messages - let create_msg = |offset: u32, bytes: Vec| { + let create_msg = |offset: u32, bytes: Vec, _prioritization_fees_ix: Option| { let instruction = loader_v4::write(&buffer_address, &config.authority.pubkey(), offset, bytes); Message::new_with_blockhash(&[instruction], Some(&payer_pubkey), &blockhash) }; let mut write_messages = vec![]; - let chunk_size = calculate_max_chunk_size(&create_msg); + let chunk_size = calculate_max_chunk_size(&create_msg, None); for (chunk, i) in program_data.chunks(chunk_size).zip(0..) { - write_messages.push(create_msg((i * chunk_size) as u32, chunk.to_vec())); + write_messages.push(create_msg((i * chunk_size) as u32, chunk.to_vec(), None)); } let final_messages = if *program_address != buffer_address { diff --git a/cli/tests/program.rs b/cli/tests/program.rs index 039df1d64b8ae8..5386ba7c561afd 100644 --- a/cli/tests/program.rs +++ b/cli/tests/program.rs @@ -87,6 +87,7 @@ fn test_cli_program_deploy_non_upgradeable() { is_final: true, max_len: None, skip_fee_check: false, + prioritization_fees: Some(1000), }); config.output_format = OutputFormat::JsonCompact; let response = process_command(&config); @@ -136,6 +137,7 @@ fn test_cli_program_deploy_non_upgradeable() { is_final: true, max_len: None, skip_fee_check: false, + prioritization_fees: Some(100), }); process_command(&config).unwrap(); let account1 = rpc_client @@ -194,6 +196,7 @@ fn test_cli_program_deploy_non_upgradeable() { is_final: true, max_len: None, skip_fee_check: false, + prioritization_fees: Some(20), }); let err = process_command(&config).unwrap_err(); assert_eq!( @@ -217,6 +220,7 @@ fn test_cli_program_deploy_non_upgradeable() { is_final: true, max_len: None, skip_fee_check: false, + prioritization_fees: Some(1000), }); process_command(&config).unwrap_err(); } @@ -278,6 +282,7 @@ fn test_cli_program_deploy_no_authority() { is_final: true, max_len: None, skip_fee_check: false, + prioritization_fees: Some(1000), }); config.output_format = OutputFormat::JsonCompact; let response = process_command(&config); @@ -305,6 +310,7 @@ fn test_cli_program_deploy_no_authority() { is_final: false, max_len: None, skip_fee_check: false, + prioritization_fees: Some(1000), }); process_command(&config).unwrap_err(); } @@ -367,6 +373,7 @@ fn test_cli_program_deploy_with_authority() { is_final: false, max_len: Some(max_len), skip_fee_check: false, + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; let response = process_command(&config); @@ -419,6 +426,7 @@ fn test_cli_program_deploy_with_authority() { is_final: false, max_len: Some(max_len), skip_fee_check: false, + prioritization_fees: None, }); let response = process_command(&config); let json: Value = serde_json::from_str(&response.unwrap()).unwrap(); @@ -465,6 +473,7 @@ fn test_cli_program_deploy_with_authority() { is_final: false, max_len: Some(max_len), skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap(); let program_account = rpc_client.get_account(&program_pubkey).unwrap(); @@ -543,6 +552,7 @@ fn test_cli_program_deploy_with_authority() { is_final: false, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap(); let program_account = rpc_client.get_account(&program_pubkey).unwrap(); @@ -625,6 +635,7 @@ fn test_cli_program_deploy_with_authority() { is_final: false, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap_err(); @@ -642,6 +653,7 @@ fn test_cli_program_deploy_with_authority() { is_final: true, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); let response = process_command(&config); let json: Value = serde_json::from_str(&response.unwrap()).unwrap(); @@ -746,6 +758,7 @@ fn test_cli_program_close_program() { is_final: false, max_len: Some(max_len), skip_fee_check: false, + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; process_command(&config).unwrap(); @@ -856,6 +869,7 @@ fn test_cli_program_extend_program() { is_final: false, max_len: None, // Use None to check that it defaults to the max length skip_fee_check: false, + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; process_command(&config).unwrap(); @@ -903,6 +917,7 @@ fn test_cli_program_extend_program() { is_final: false, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap_err(); @@ -935,6 +950,7 @@ fn test_cli_program_extend_program() { is_final: false, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap(); } @@ -999,6 +1015,7 @@ fn test_cli_program_write_buffer() { buffer_authority_signer_index: 0, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; let response = process_command(&config); @@ -1035,6 +1052,7 @@ fn test_cli_program_write_buffer() { buffer_authority_signer_index: 0, max_len: Some(max_len), skip_fee_check: false, + prioritization_fees: None, }); let response = process_command(&config); let json: Value = serde_json::from_str(&response.unwrap()).unwrap(); @@ -1098,6 +1116,7 @@ fn test_cli_program_write_buffer() { buffer_authority_signer_index: 2, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); let response = process_command(&config); let json: Value = serde_json::from_str(&response.unwrap()).unwrap(); @@ -1137,6 +1156,7 @@ fn test_cli_program_write_buffer() { buffer_authority_signer_index: 2, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); let response = process_command(&config); let json: Value = serde_json::from_str(&response.unwrap()).unwrap(); @@ -1212,6 +1232,7 @@ fn test_cli_program_write_buffer() { buffer_authority_signer_index: 0, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; let response = process_command(&config); @@ -1254,6 +1275,7 @@ fn test_cli_program_write_buffer() { buffer_authority_signer_index: 0, max_len: None, //Some(max_len), skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap(); config.signers = vec![&keypair, &buffer_keypair]; @@ -1269,6 +1291,7 @@ fn test_cli_program_write_buffer() { is_final: true, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; let error = process_command(&config).unwrap_err(); @@ -1328,6 +1351,7 @@ fn test_cli_program_set_buffer_authority() { buffer_authority_signer_index: 0, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap(); let buffer_account = rpc_client.get_account(&buffer_keypair.pubkey()).unwrap(); @@ -1380,6 +1404,7 @@ fn test_cli_program_set_buffer_authority() { is_final: false, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; process_command(&config).unwrap_err(); @@ -1425,6 +1450,7 @@ fn test_cli_program_set_buffer_authority() { is_final: false, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; process_command(&config).unwrap(); @@ -1481,6 +1507,7 @@ fn test_cli_program_mismatch_buffer_authority() { buffer_authority_signer_index: 2, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap(); let buffer_account = rpc_client.get_account(&buffer_keypair.pubkey()).unwrap(); @@ -1505,6 +1532,7 @@ fn test_cli_program_mismatch_buffer_authority() { is_final: true, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap_err(); @@ -1522,6 +1550,7 @@ fn test_cli_program_mismatch_buffer_authority() { is_final: true, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap(); } @@ -1605,6 +1634,7 @@ fn test_cli_program_deploy_with_offline_signing(use_offline_signer_as_fee_payer: is_final: false, max_len: Some(max_program_data_len), // allows for larger program size with future upgrades skip_fee_check: false, + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; process_command(&config).unwrap(); @@ -1635,6 +1665,7 @@ fn test_cli_program_deploy_with_offline_signing(use_offline_signer_as_fee_payer: sign_only: true, dump_transaction_message: false, blockhash_query: BlockhashQuery::new(Some(blockhash), true, None), + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; let sig_response = process_command(&config).unwrap(); @@ -1656,6 +1687,7 @@ fn test_cli_program_deploy_with_offline_signing(use_offline_signer_as_fee_payer: sign_only: false, dump_transaction_message: false, blockhash_query: BlockhashQuery::new(Some(blockhash), true, None), + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; let error = process_command(&config).unwrap_err(); @@ -1677,6 +1709,7 @@ fn test_cli_program_deploy_with_offline_signing(use_offline_signer_as_fee_payer: sign_only: true, dump_transaction_message: false, blockhash_query: BlockhashQuery::new(Some(blockhash), true, None), + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; let sig_response = process_command(&config).unwrap(); @@ -1698,6 +1731,7 @@ fn test_cli_program_deploy_with_offline_signing(use_offline_signer_as_fee_payer: sign_only: false, dump_transaction_message: false, blockhash_query: BlockhashQuery::new(Some(blockhash), true, None), + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; process_command(&config).unwrap(); @@ -1772,6 +1806,7 @@ fn test_cli_program_show() { buffer_authority_signer_index: 2, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap(); @@ -1833,6 +1868,7 @@ fn test_cli_program_show() { is_final: false, max_len: Some(max_len), skip_fee_check: false, + prioritization_fees: None, }); config.output_format = OutputFormat::JsonCompact; let min_slot = rpc_client.get_slot().unwrap(); @@ -1961,6 +1997,7 @@ fn test_cli_program_dump() { buffer_authority_signer_index: 2, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); process_command(&config).unwrap(); @@ -2004,6 +2041,7 @@ fn create_buffer_with_offline_authority<'a>( buffer_authority_signer_index: 0, max_len: None, skip_fee_check: false, + prioritization_fees: None, }); process_command(config).unwrap(); let buffer_account = rpc_client.get_account(&buffer_signer.pubkey()).unwrap(); diff --git a/client/src/send_and_confirm_transactions_in_parallel.rs b/client/src/send_and_confirm_transactions_in_parallel.rs index f97761cba14fde..5776bc6bac0237 100644 --- a/client/src/send_and_confirm_transactions_in_parallel.rs +++ b/client/src/send_and_confirm_transactions_in_parallel.rs @@ -301,7 +301,16 @@ async fn sign_all_messages_and_send( ); } // collect to convert Vec> to Result> - join_all(futures).await.into_iter().collect::>()?; + match tokio::time::timeout(Duration::from_secs(120), join_all(futures)).await { + Ok(join_result) => { + join_result.into_iter().collect::>()?; + } + Err(_) => { + // It is fine if sending transactions to rpc is timed out here, we will retry it anyways, + // without this timeout cli waits indefinetly for all tasks to join + log::warn!("Timedout sending all transactions to RPC, will continue"); + } + } Ok(()) } diff --git a/transaction-dos/src/main.rs b/transaction-dos/src/main.rs index 94fecf5e6d5f73..d95f62b904cb6a 100644 --- a/transaction-dos/src/main.rs +++ b/transaction-dos/src/main.rs @@ -248,6 +248,7 @@ fn run_transactions_dos( is_final: true, max_len: None, skip_fee_check: true, // skip_fee_check + prioritization_fees: None, }); process_command(&config).expect("deploy didn't pass");