diff --git a/cli/src/cli.rs b/cli/src/cli.rs index ce6df92bd3..4a406d17b8 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -161,6 +161,7 @@ pub enum CliCommand { address: Option, use_deprecated_loader: bool, allow_excessive_balance: bool, + skip_fee_check: bool, }, Program(ProgramCliCommand), // Stake Commands @@ -743,6 +744,7 @@ pub fn parse_command( signers.push(signer); 1 }); + let skip_fee_check = matches.is_present("skip_fee_check"); Ok(CliCommandInfo { command: CliCommand::Deploy { @@ -750,6 +752,7 @@ pub fn parse_command( address, use_deprecated_loader: matches.is_present("use_deprecated_loader"), allow_excessive_balance: matches.is_present("allow_excessive_balance"), + skip_fee_check, }, signers, }) @@ -1126,6 +1129,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult { address, use_deprecated_loader, allow_excessive_balance, + skip_fee_check, } => process_deploy( rpc_client, config, @@ -1133,6 +1137,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult { *address, *use_deprecated_loader, *allow_excessive_balance, + *skip_fee_check, ), CliCommand::Program(program_subcommand) => { process_program_subcommand(rpc_client, config, program_subcommand) @@ -1964,6 +1969,7 @@ mod tests { address: None, use_deprecated_loader: false, allow_excessive_balance: false, + skip_fee_check: false, }, signers: vec![read_keypair_file(&keypair_file).unwrap().into()], } @@ -1986,6 +1992,7 @@ mod tests { address: Some(1), use_deprecated_loader: false, allow_excessive_balance: false, + skip_fee_check: false, }, signers: vec![ read_keypair_file(&keypair_file).unwrap().into(), @@ -2379,6 +2386,7 @@ mod tests { address: None, use_deprecated_loader: false, allow_excessive_balance: false, + skip_fee_check: false, }; config.output_format = OutputFormat::JsonCompact; let result = process_command(&config); @@ -2399,6 +2407,7 @@ mod tests { address: None, use_deprecated_loader: false, allow_excessive_balance: false, + skip_fee_check: false, }; assert!(process_command(&config).is_err()); } diff --git a/cli/src/program.rs b/cli/src/program.rs index bfed249343..1106005bee 100644 --- a/cli/src/program.rs +++ b/cli/src/program.rs @@ -65,6 +65,7 @@ pub enum ProgramCliCommand { is_final: bool, max_len: Option, allow_excessive_balance: bool, + skip_fee_check: bool, }, WriteBuffer { program_location: String, @@ -72,6 +73,7 @@ pub enum ProgramCliCommand { buffer_pubkey: Option, buffer_authority_signer_index: Option, max_len: Option, + skip_fee_check: bool, }, SetBufferAuthority { buffer_pubkey: Pubkey, @@ -113,6 +115,13 @@ impl ProgramSubCommands for App<'_, '_> { SubCommand::with_name("program") .about("Program management") .setting(AppSettings::SubcommandRequiredElseHelp) + .arg( + Arg::with_name("skip_fee_check") + .long("skip-fee-check") + .hidden(true) + .takes_value(false) + .global(true) + ) .subcommand( SubCommand::with_name("deploy") .about("Deploy a program") @@ -405,6 +414,12 @@ impl ProgramSubCommands for App<'_, '_> { .long("allow-excessive-deploy-account-balance") .takes_value(false) .help("Use the designated program id, even if the account already holds a large balance of SOL") + ) + .arg( + Arg::with_name("skip_fee_check") + .long("skip-fee-check") + .hidden(true) + .takes_value(false) ), ) } @@ -415,7 +430,14 @@ pub fn parse_program_subcommand( default_signer: &DefaultSigner, wallet_manager: &mut Option>, ) -> Result { - let response = match matches.subcommand() { + let (subcommand, sub_matches) = matches.subcommand(); + let matches_skip_fee_check = matches.is_present("skip_fee_check"); + let sub_matches_skip_fee_check = sub_matches + .map(|m| m.is_present("skip_fee_check")) + .unwrap_or(false); + let skip_fee_check = matches_skip_fee_check || sub_matches_skip_fee_check; + + let response = match (subcommand, sub_matches) { ("deploy", Some(matches)) => { let mut bulk_signers = vec![Some( default_signer.signer_from_path(matches, wallet_manager)?, @@ -475,6 +497,7 @@ pub fn parse_program_subcommand( is_final: matches.is_present("final"), max_len, allow_excessive_balance: matches.is_present("allow_excessive_balance"), + skip_fee_check, }), signers: signer_info.signers, } @@ -520,6 +543,7 @@ pub fn parse_program_subcommand( buffer_authority_signer_index: signer_info .index_of_or_none(buffer_authority_pubkey), max_len, + skip_fee_check, }), signers: signer_info.signers, } @@ -668,6 +692,7 @@ pub fn process_program_subcommand( is_final, max_len, allow_excessive_balance, + skip_fee_check, } => process_program_deploy( rpc_client, config, @@ -680,6 +705,7 @@ pub fn process_program_subcommand( *is_final, *max_len, *allow_excessive_balance, + *skip_fee_check, ), ProgramCliCommand::WriteBuffer { program_location, @@ -687,6 +713,7 @@ pub fn process_program_subcommand( buffer_pubkey, buffer_authority_signer_index, max_len, + skip_fee_check, } => process_write_buffer( rpc_client, config, @@ -695,6 +722,7 @@ pub fn process_program_subcommand( *buffer_pubkey, *buffer_authority_signer_index, *max_len, + *skip_fee_check, ), ProgramCliCommand::SetBufferAuthority { buffer_pubkey, @@ -792,6 +820,7 @@ fn process_program_deploy( is_final: bool, max_len: Option, allow_excessive_balance: bool, + skip_fee_check: bool, ) -> ProcessResult { let (words, mnemonic, buffer_keypair) = create_ephemeral_keypair()?; let (buffer_provided, buffer_signer, buffer_pubkey) = if let Some(i) = buffer_signer_index { @@ -946,6 +975,7 @@ fn process_program_deploy( &buffer_pubkey, Some(upgrade_authority_signer), allow_excessive_balance, + skip_fee_check, ) } else { do_process_program_upgrade( @@ -956,6 +986,7 @@ fn process_program_deploy( config.signers[upgrade_authority_signer_index], &buffer_pubkey, buffer_signer, + skip_fee_check, ) }; if result.is_ok() && is_final { @@ -982,6 +1013,7 @@ fn process_write_buffer( buffer_pubkey: Option, buffer_authority_signer_index: Option, max_len: Option, + skip_fee_check: bool, ) -> ProcessResult { // Create ephemeral keypair to use for Buffer account, if not provided let (words, mnemonic, buffer_keypair) = create_ephemeral_keypair()?; @@ -1049,6 +1081,7 @@ fn process_write_buffer( &buffer_pubkey, Some(buffer_authority), true, + skip_fee_check, ); if result.is_err() && buffer_signer_index.is_none() && buffer_signer.is_some() { @@ -1635,6 +1668,7 @@ pub fn process_deploy( buffer_signer_index: Option, use_deprecated_loader: bool, allow_excessive_balance: bool, + skip_fee_check: bool, ) -> ProcessResult { // Create ephemeral keypair to use for Buffer account, if not provided let (words, mnemonic, buffer_keypair) = create_ephemeral_keypair()?; @@ -1665,6 +1699,7 @@ pub fn process_deploy( &buffer_signer.pubkey(), Some(buffer_signer), allow_excessive_balance, + skip_fee_check, ); if result.is_err() && buffer_signer_index.is_none() { report_ephemeral_mnemonic(words, mnemonic); @@ -1703,6 +1738,7 @@ fn do_process_program_write_and_deploy( buffer_pubkey: &Pubkey, buffer_authority_signer: Option<&dyn Signer>, allow_excessive_balance: bool, + skip_fee_check: bool, ) -> ProcessResult { // Build messages to calculate fees let mut messages: Vec<&Message> = Vec::new(); @@ -1833,7 +1869,9 @@ fn do_process_program_write_and_deploy( messages.push(message); } - check_payer(&rpc_client, config, balance_needed, &messages)?; + if !skip_fee_check { + check_payer(&rpc_client, config, balance_needed, &messages)?; + } send_deploy_messages( rpc_client, @@ -1867,6 +1905,7 @@ fn do_process_program_upgrade( upgrade_authority: &dyn Signer, buffer_pubkey: &Pubkey, buffer_signer: Option<&dyn Signer>, + skip_fee_check: bool, ) -> ProcessResult { let loader_id = bpf_loader_upgradeable::id(); let data_len = program_data.len(); @@ -1966,7 +2005,10 @@ fn do_process_program_upgrade( ); messages.push(&final_message); - check_payer(&rpc_client, config, balance_needed, &messages)?; + if !skip_fee_check { + check_payer(&rpc_client, config, balance_needed, &messages)?; + } + send_deploy_messages( rpc_client, config, @@ -2253,6 +2295,7 @@ mod tests { is_final: false, max_len: None, allow_excessive_balance: false, + skip_fee_check: false, }), signers: vec![read_keypair_file(&keypair_file).unwrap().into()], } @@ -2279,6 +2322,7 @@ mod tests { is_final: false, max_len: Some(42), allow_excessive_balance: false, + skip_fee_check: false, }), signers: vec![read_keypair_file(&keypair_file).unwrap().into()], } @@ -2307,6 +2351,7 @@ mod tests { is_final: false, max_len: None, allow_excessive_balance: false, + skip_fee_check: false, }), signers: vec![ read_keypair_file(&keypair_file).unwrap().into(), @@ -2337,6 +2382,7 @@ mod tests { is_final: false, max_len: None, allow_excessive_balance: false, + skip_fee_check: false, }), signers: vec![read_keypair_file(&keypair_file).unwrap().into()], } @@ -2366,6 +2412,7 @@ mod tests { is_final: false, max_len: None, allow_excessive_balance: false, + skip_fee_check: false, }), signers: vec![ read_keypair_file(&keypair_file).unwrap().into(), @@ -2398,6 +2445,7 @@ mod tests { is_final: false, max_len: None, allow_excessive_balance: false, + skip_fee_check: false, }), signers: vec![ read_keypair_file(&keypair_file).unwrap().into(), @@ -2425,6 +2473,7 @@ mod tests { upgrade_authority_signer_index: 0, is_final: true, max_len: None, + skip_fee_check: false, allow_excessive_balance: false, }), signers: vec![read_keypair_file(&keypair_file).unwrap().into()], @@ -2458,6 +2507,7 @@ mod tests { buffer_pubkey: None, buffer_authority_signer_index: Some(0), max_len: None, + skip_fee_check: false, }), signers: vec![read_keypair_file(&keypair_file).unwrap().into()], } @@ -2481,6 +2531,7 @@ mod tests { buffer_pubkey: None, buffer_authority_signer_index: Some(0), max_len: Some(42), + skip_fee_check: false, }), signers: vec![read_keypair_file(&keypair_file).unwrap().into()], } @@ -2507,6 +2558,7 @@ mod tests { buffer_pubkey: Some(buffer_keypair.pubkey()), buffer_authority_signer_index: Some(0), max_len: None, + skip_fee_check: false, }), signers: vec![ read_keypair_file(&keypair_file).unwrap().into(), @@ -2536,6 +2588,7 @@ mod tests { buffer_pubkey: None, buffer_authority_signer_index: Some(1), max_len: None, + skip_fee_check: false, }), signers: vec![ read_keypair_file(&keypair_file).unwrap().into(), @@ -2570,6 +2623,7 @@ mod tests { buffer_pubkey: Some(buffer_keypair.pubkey()), buffer_authority_signer_index: Some(2), max_len: None, + skip_fee_check: false, }), signers: vec![ read_keypair_file(&keypair_file).unwrap().into(), @@ -3012,6 +3066,7 @@ mod tests { is_final: false, max_len: None, allow_excessive_balance: false, + skip_fee_check: false, }), signers: vec![&default_keypair], output_format: OutputFormat::JsonCompact, diff --git a/cli/tests/program.rs b/cli/tests/program.rs index 54282c8c2e..3696550ad7 100644 --- a/cli/tests/program.rs +++ b/cli/tests/program.rs @@ -62,6 +62,7 @@ fn test_cli_program_deploy_non_upgradeable() { address: None, use_deprecated_loader: false, allow_excessive_balance: false, + skip_fee_check: false, }; config.output_format = OutputFormat::JsonCompact; let response = process_command(&config); @@ -91,6 +92,7 @@ fn test_cli_program_deploy_non_upgradeable() { address: Some(1), use_deprecated_loader: false, allow_excessive_balance: false, + skip_fee_check: false, }; process_command(&config).unwrap(); let account1 = rpc_client @@ -118,6 +120,7 @@ fn test_cli_program_deploy_non_upgradeable() { address: Some(1), use_deprecated_loader: false, allow_excessive_balance: false, + skip_fee_check: false, }; process_command(&config).unwrap_err(); @@ -127,6 +130,7 @@ fn test_cli_program_deploy_non_upgradeable() { address: Some(1), use_deprecated_loader: false, allow_excessive_balance: true, + skip_fee_check: false, }; process_command(&config).unwrap(); let account2 = rpc_client @@ -193,6 +197,7 @@ fn test_cli_program_deploy_no_authority() { upgrade_authority_signer_index: 1, is_final: true, max_len: None, + skip_fee_check: false, }); config.output_format = OutputFormat::JsonCompact; let response = process_command(&config); @@ -218,6 +223,7 @@ fn test_cli_program_deploy_no_authority() { upgrade_authority_signer_index: 1, is_final: false, max_len: None, + skip_fee_check: false, }); process_command(&config).unwrap_err(); } @@ -278,6 +284,7 @@ fn test_cli_program_deploy_with_authority() { upgrade_authority_signer_index: 1, is_final: false, max_len: Some(max_len), + skip_fee_check: false, }); config.output_format = OutputFormat::JsonCompact; let response = process_command(&config); @@ -325,6 +332,7 @@ fn test_cli_program_deploy_with_authority() { upgrade_authority_signer_index: 1, is_final: false, max_len: Some(max_len), + skip_fee_check: false, }); let response = process_command(&config); let json: Value = serde_json::from_str(&response.unwrap()).unwrap(); @@ -366,6 +374,7 @@ fn test_cli_program_deploy_with_authority() { upgrade_authority_signer_index: 1, is_final: false, max_len: Some(max_len), + skip_fee_check: false, }); process_command(&config).unwrap(); let program_account = rpc_client.get_account(&program_pubkey).unwrap(); @@ -420,6 +429,7 @@ fn test_cli_program_deploy_with_authority() { upgrade_authority_signer_index: 1, is_final: false, max_len: None, + skip_fee_check: false, }); process_command(&config).unwrap(); let program_account = rpc_client.get_account(&program_pubkey).unwrap(); @@ -494,6 +504,7 @@ fn test_cli_program_deploy_with_authority() { upgrade_authority_signer_index: 1, is_final: false, max_len: None, + skip_fee_check: false, }); process_command(&config).unwrap_err(); @@ -509,6 +520,7 @@ fn test_cli_program_deploy_with_authority() { upgrade_authority_signer_index: 1, is_final: true, max_len: None, + skip_fee_check: false, }); let response = process_command(&config); let json: Value = serde_json::from_str(&response.unwrap()).unwrap(); @@ -611,6 +623,7 @@ fn test_cli_program_close_program() { upgrade_authority_signer_index: 1, is_final: false, max_len: Some(max_len), + skip_fee_check: false, }); config.output_format = OutputFormat::JsonCompact; process_command(&config).unwrap(); @@ -695,6 +708,7 @@ fn test_cli_program_write_buffer() { buffer_pubkey: None, buffer_authority_signer_index: None, max_len: None, + skip_fee_check: false, }); config.output_format = OutputFormat::JsonCompact; let response = process_command(&config); @@ -729,6 +743,7 @@ fn test_cli_program_write_buffer() { buffer_pubkey: Some(buffer_keypair.pubkey()), buffer_authority_signer_index: None, max_len: Some(max_len), + skip_fee_check: false, }); let response = process_command(&config); let json: Value = serde_json::from_str(&response.unwrap()).unwrap(); @@ -790,6 +805,7 @@ fn test_cli_program_write_buffer() { buffer_pubkey: Some(buffer_keypair.pubkey()), buffer_authority_signer_index: Some(2), max_len: None, + skip_fee_check: false, }); let response = process_command(&config); let json: Value = serde_json::from_str(&response.unwrap()).unwrap(); @@ -827,6 +843,7 @@ fn test_cli_program_write_buffer() { buffer_pubkey: None, buffer_authority_signer_index: Some(2), max_len: None, + skip_fee_check: false, }); let response = process_command(&config); let json: Value = serde_json::from_str(&response.unwrap()).unwrap(); @@ -899,6 +916,7 @@ fn test_cli_program_write_buffer() { buffer_pubkey: None, buffer_authority_signer_index: None, max_len: None, + skip_fee_check: false, }); config.output_format = OutputFormat::JsonCompact; let response = process_command(&config); @@ -938,6 +956,7 @@ fn test_cli_program_write_buffer() { buffer_pubkey: Some(buffer_keypair.pubkey()), buffer_authority_signer_index: None, max_len: None, //Some(max_len), + skip_fee_check: false, }); process_command(&config).unwrap(); config.signers = vec![&keypair, &buffer_keypair]; @@ -951,6 +970,7 @@ fn test_cli_program_write_buffer() { upgrade_authority_signer_index: 1, is_final: true, max_len: None, + skip_fee_check: false, }); config.output_format = OutputFormat::JsonCompact; let error = process_command(&config).unwrap_err(); @@ -1008,6 +1028,7 @@ fn test_cli_program_set_buffer_authority() { buffer_pubkey: Some(buffer_keypair.pubkey()), buffer_authority_signer_index: None, max_len: None, + skip_fee_check: false, }); process_command(&config).unwrap(); let buffer_account = rpc_client.get_account(&buffer_keypair.pubkey()).unwrap(); @@ -1123,6 +1144,7 @@ fn test_cli_program_mismatch_buffer_authority() { buffer_pubkey: Some(buffer_keypair.pubkey()), buffer_authority_signer_index: Some(2), max_len: None, + skip_fee_check: false, }); process_command(&config).unwrap(); let buffer_account = rpc_client.get_account(&buffer_keypair.pubkey()).unwrap(); @@ -1145,6 +1167,7 @@ fn test_cli_program_mismatch_buffer_authority() { upgrade_authority_signer_index: 1, is_final: true, max_len: None, + skip_fee_check: false, }); process_command(&config).unwrap_err(); @@ -1160,6 +1183,7 @@ fn test_cli_program_mismatch_buffer_authority() { upgrade_authority_signer_index: 1, is_final: true, max_len: None, + skip_fee_check: false, }); process_command(&config).unwrap(); } @@ -1216,6 +1240,7 @@ fn test_cli_program_show() { buffer_pubkey: Some(buffer_keypair.pubkey()), buffer_authority_signer_index: Some(2), max_len: None, + skip_fee_check: false, }); process_command(&config).unwrap(); @@ -1275,6 +1300,7 @@ fn test_cli_program_show() { upgrade_authority_signer_index: 1, is_final: false, max_len: Some(max_len), + skip_fee_check: false, }); config.output_format = OutputFormat::JsonCompact; let min_slot = rpc_client.get_slot().unwrap(); @@ -1401,6 +1427,7 @@ fn test_cli_program_dump() { buffer_pubkey: Some(buffer_keypair.pubkey()), buffer_authority_signer_index: Some(2), max_len: None, + skip_fee_check: false, }); process_command(&config).unwrap(); diff --git a/transaction-dos/src/main.rs b/transaction-dos/src/main.rs index b8693c97c6..3bb462020c 100644 --- a/transaction-dos/src/main.rs +++ b/transaction-dos/src/main.rs @@ -237,6 +237,7 @@ fn run_transactions_dos( Some(1), false, true, + true, /* skip_fee_check */ ) .expect("deploy didn't pass"); } else {