From bd27eedd151360f3814ce90db35b0809ef110331 Mon Sep 17 00:00:00 2001 From: Trent Nelson Date: Fri, 25 Mar 2022 14:43:43 -0600 Subject: [PATCH] cli: allow skipping fee-checks when writing program buffers (hidden) --- cli/src/cli.rs | 9 ++++++ cli/src/program.rs | 61 +++++++++++++++++++++++++++++++++++-- cli/tests/program.rs | 27 ++++++++++++++++ transaction-dos/src/main.rs | 1 + 4 files changed, 95 insertions(+), 3 deletions(-) diff --git a/cli/src/cli.rs b/cli/src/cli.rs index ac5aae1e1..40b900b98 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -162,6 +162,7 @@ pub enum CliCommand { address: Option, use_deprecated_loader: bool, allow_excessive_balance: bool, + skip_fee_check: bool, }, Program(ProgramCliCommand), // Stake Commands @@ -744,6 +745,7 @@ pub fn parse_command( signers.push(signer); 1 }); + let skip_fee_check = matches.is_present("skip_fee_check"); Ok(CliCommandInfo { command: CliCommand::Deploy { @@ -751,6 +753,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, }) @@ -1129,6 +1132,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult { address, use_deprecated_loader, allow_excessive_balance, + skip_fee_check, } => process_deploy( rpc_client, config, @@ -1136,6 +1140,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) @@ -1967,6 +1972,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()], } @@ -1989,6 +1995,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(), @@ -2382,6 +2389,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); @@ -2402,6 +2410,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 7b6d9bf9c..baa868376 100644 --- a/cli/src/program.rs +++ b/cli/src/program.rs @@ -66,6 +66,7 @@ pub enum ProgramCliCommand { is_final: bool, max_len: Option, allow_excessive_balance: bool, + skip_fee_check: bool, }, WriteBuffer { program_location: String, @@ -73,6 +74,7 @@ pub enum ProgramCliCommand { buffer_pubkey: Option, buffer_authority_signer_index: Option, max_len: Option, + skip_fee_check: bool, }, SetBufferAuthority { buffer_pubkey: Pubkey, @@ -114,6 +116,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") @@ -406,6 +415,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) ), ) } @@ -416,7 +431,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)?, @@ -476,6 +498,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, } @@ -521,6 +544,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, } @@ -669,6 +693,7 @@ pub fn process_program_subcommand( is_final, max_len, allow_excessive_balance, + skip_fee_check, } => process_program_deploy( rpc_client, config, @@ -681,6 +706,7 @@ pub fn process_program_subcommand( *is_final, *max_len, *allow_excessive_balance, + *skip_fee_check, ), ProgramCliCommand::WriteBuffer { program_location, @@ -688,6 +714,7 @@ pub fn process_program_subcommand( buffer_pubkey, buffer_authority_signer_index, max_len, + skip_fee_check, } => process_write_buffer( rpc_client, config, @@ -696,6 +723,7 @@ pub fn process_program_subcommand( *buffer_pubkey, *buffer_authority_signer_index, *max_len, + *skip_fee_check, ), ProgramCliCommand::SetBufferAuthority { buffer_pubkey, @@ -793,6 +821,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 { @@ -947,6 +976,7 @@ fn process_program_deploy( &buffer_pubkey, Some(upgrade_authority_signer), allow_excessive_balance, + skip_fee_check, ) } else { do_process_program_upgrade( @@ -957,6 +987,7 @@ fn process_program_deploy( config.signers[upgrade_authority_signer_index], &buffer_pubkey, buffer_signer, + skip_fee_check, ) }; if result.is_ok() && is_final { @@ -983,6 +1014,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()?; @@ -1050,6 +1082,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() { @@ -1636,6 +1669,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()?; @@ -1666,6 +1700,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); @@ -1704,6 +1739,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(); @@ -1834,7 +1870,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, @@ -1868,6 +1906,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(); @@ -1967,7 +2006,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, @@ -2255,6 +2297,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()], } @@ -2281,6 +2324,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()], } @@ -2309,6 +2353,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(), @@ -2339,6 +2384,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()], } @@ -2368,6 +2414,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(), @@ -2400,6 +2447,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(), @@ -2427,6 +2475,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()], @@ -2460,6 +2509,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()], } @@ -2483,6 +2533,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()], } @@ -2509,6 +2560,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(), @@ -2538,6 +2590,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(), @@ -2572,6 +2625,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(), @@ -3014,6 +3068,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 9e73af7c2..75c676d50 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 393bf2f8d..c75d3b8d1 100644 --- a/transaction-dos/src/main.rs +++ b/transaction-dos/src/main.rs @@ -242,6 +242,7 @@ fn run_transactions_dos( Some(1), false, true, + true, /* skip_fee_check */ ) .expect("deploy didn't pass"); } else {