From a547c57ff4a144dad3e3b1cfe7a6f46ed0703751 Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Sat, 13 Apr 2024 13:13:54 +0530
Subject: [PATCH 01/14] add checks for program data account overflow during
 upgrade and add --auto-extend-program flag to solana program deploy command

---
 cli/src/program.rs   | 114 +++++++++++++++++-------------
 cli/tests/program.rs | 165 ++++++++++++++++++++++++++++++++++++-------
 2 files changed, 204 insertions(+), 75 deletions(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 5640a89738eedf..ded59595f7b36a 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -54,7 +54,7 @@ use {
         account::Account,
         account_utils::StateMut,
         bpf_loader, bpf_loader_deprecated,
-        bpf_loader_upgradeable::{self, UpgradeableLoaderState},
+        bpf_loader_upgradeable::{self, get_program_data_address, UpgradeableLoaderState},
         compute_budget,
         feature_set::FeatureSet,
         instruction::{Instruction, InstructionError},
@@ -71,6 +71,7 @@ use {
         fs::File,
         io::{Read, Write},
         mem::size_of,
+        ops::Sub,
         path::PathBuf,
         rc::Rc,
         str::FromStr,
@@ -99,7 +100,7 @@ pub enum ProgramCliCommand {
         skip_fee_check: bool,
         compute_unit_price: Option<u64>,
         max_sign_attempts: usize,
-        use_rpc: bool,
+        auto_extend_program: bool,
     },
     Upgrade {
         fee_payer_signer_index: SignerIndex,
@@ -270,10 +271,15 @@ impl ProgramSubCommands for App<'_, '_> {
                                     whichever comes first.",
                                 ),
                         )
-                        .arg(Arg::with_name("use_rpc").long("use-rpc").help(
-                            "Send write transactions to the configured RPC instead of validator TPUs",
-                        ))
-                        .arg(compute_unit_price_arg()),
+                        .arg(compute_unit_price_arg())
+                        .arg(
+                              Arg::with_name("auto_extend_program")
+                                .long("auto-extend-program")
+                                .takes_value(false)
+                                .help(
+                                    "Automatically extend the program data account size to match the updated program's data size",
+                                ),
+                        ),
                 )
                 .subcommand(
                     SubCommand::with_name("upgrade")
@@ -665,6 +671,8 @@ pub fn parse_program_subcommand(
             let compute_unit_price = value_of(matches, "compute_unit_price");
             let max_sign_attempts = value_of(matches, "max_sign_attempts").unwrap();
 
+            let auto_extend_program = matches.is_present("auto_extend_program");
+
             CliCommandInfo {
                 command: CliCommand::Program(ProgramCliCommand::Deploy {
                     program_location,
@@ -682,7 +690,7 @@ pub fn parse_program_subcommand(
                     skip_fee_check,
                     compute_unit_price,
                     max_sign_attempts,
-                    use_rpc: matches.is_present("use_rpc"),
+                    auto_extend_program,
                 }),
                 signers: signer_info.signers,
             }
@@ -970,7 +978,7 @@ pub fn process_program_subcommand(
             skip_fee_check,
             compute_unit_price,
             max_sign_attempts,
-            use_rpc,
+            auto_extend_program,
         } => process_program_deploy(
             rpc_client,
             config,
@@ -987,7 +995,7 @@ pub fn process_program_subcommand(
             *skip_fee_check,
             *compute_unit_price,
             *max_sign_attempts,
-            *use_rpc,
+            *auto_extend_program,
         ),
         ProgramCliCommand::Upgrade {
             fee_payer_signer_index,
@@ -1165,7 +1173,7 @@ fn process_program_deploy(
     skip_fee_check: bool,
     compute_unit_price: Option<u64>,
     max_sign_attempts: usize,
-    use_rpc: bool,
+    auto_extend_program: bool,
 ) -> ProcessResult {
     let fee_payer_signer = config.signers[fee_payer_signer_index];
     let upgrade_authority_signer = config.signers[upgrade_authority_signer_index];
@@ -1350,7 +1358,7 @@ fn process_program_deploy(
             skip_fee_check,
             compute_unit_price,
             max_sign_attempts,
-            use_rpc,
+            auto_extend_program,
         )
     };
     if result.is_ok() && is_final {
@@ -2490,9 +2498,38 @@ fn do_process_program_upgrade(
     skip_fee_check: bool,
     compute_unit_price: Option<u64>,
     max_sign_attempts: usize,
-    use_rpc: bool,
+    auto_extend_program: bool,
 ) -> ProcessResult {
     let blockhash = rpc_client.get_latest_blockhash()?;
+    let program_data_address = get_program_data_address(program_id);
+    let program_data_account = rpc_client.get_account(&program_data_address)?;
+
+    //CHECK: if passed program size is greater than the current program data account size,
+    //throw an err along with a message including additional bytes required
+    let add_program_extend_ix = if program_len > program_data_account.data.len() {
+        let metadata_size = UpgradeableLoaderState::size_of_programdata_metadata();
+        let additional_bytes = program_len
+            .sub(program_data_account.data.len())
+            .saturating_add(metadata_size);
+        println!("additional_bytes: {}", additional_bytes);
+        if auto_extend_program {
+            Some(bpf_loader_upgradeable::extend_program(
+                program_id,
+                Some(&fee_payer_signer.pubkey()),
+                additional_bytes as u32,
+            ))
+        } else {
+            let err_string = format!(
+                r#"Program Data Account space is not enough
+please extend the program data account with command: solana program extend {} {}
+or pass flag --auto-extend-program to extend program data account automatically"#,
+                program_id, additional_bytes
+            );
+            return Err(err_string.into());
+        }
+    } else {
+        None
+    };
 
     let (initial_message, write_messages, balance_needed) = if let Some(buffer_signer) =
         buffer_signer
@@ -2526,6 +2563,11 @@ fn do_process_program_upgrade(
                 )
             };
 
+        // Add extend program instruction if ProgramData account needs to be extended
+        if let Some(add_program_extend_ix) = add_program_extend_ix {
+            initial_instructions.push(add_program_extend_ix);
+        }
+
         let initial_message = if !initial_instructions.is_empty() {
             Some(Message::new_with_blockhash(
                 &initial_instructions
@@ -2959,7 +3001,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    use_rpc: false,
+                    auto_extend_program: false,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -2990,7 +3032,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    use_rpc: false,
+                    auto_extend_program: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3023,7 +3065,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    use_rpc: false,
+                    auto_extend_program: false
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3058,7 +3100,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    use_rpc: false,
+                    auto_extend_program: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3092,7 +3134,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    use_rpc: false,
+                    auto_extend_program: false
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3129,7 +3171,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    use_rpc: false,
+                    auto_extend_program: false
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3162,7 +3204,7 @@ mod tests {
                     allow_excessive_balance: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    use_rpc: false,
+                    auto_extend_program: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3193,37 +3235,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 1,
-                    use_rpc: false,
-                }),
-                signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
-            }
-        );
-
-        let test_command = test_commands.clone().get_matches_from(vec![
-            "test",
-            "program",
-            "deploy",
-            "/Users/test/program.so",
-            "--use-rpc",
-        ]);
-        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: None,
-                    allow_excessive_balance: false,
-                    skip_fee_check: false,
-                    compute_unit_price: None,
-                    max_sign_attempts: 5,
-                    use_rpc: true,
+                    auto_extend_program: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3966,7 +3978,7 @@ mod tests {
                 skip_fee_check: false,
                 compute_unit_price: None,
                 max_sign_attempts: 5,
-                use_rpc: false,
+                auto_extend_program: false,
             }),
             signers: vec![&default_keypair],
             output_format: OutputFormat::JsonCompact,
diff --git a/cli/tests/program.rs b/cli/tests/program.rs
index 5e2098de9c455a..db5d04cfea72c1 100644
--- a/cli/tests/program.rs
+++ b/cli/tests/program.rs
@@ -99,7 +99,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -148,7 +148,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     process_command(&config).unwrap();
     let account1 = rpc_client
@@ -206,7 +206,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     let err = process_command(&config).unwrap_err();
     assert_eq!(
@@ -232,7 +232,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     process_command(&config).unwrap_err();
 }
@@ -296,7 +296,7 @@ fn test_cli_program_deploy_no_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -326,7 +326,7 @@ fn test_cli_program_deploy_no_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     process_command(&config).unwrap_err();
 }
@@ -391,7 +391,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -443,7 +443,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     let response = process_command(&config);
     let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -489,7 +489,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     process_command(&config).unwrap();
     let program_account = rpc_client.get_account(&program_pubkey).unwrap();
@@ -567,7 +567,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     process_command(&config).unwrap();
     let program_account = rpc_client.get_account(&program_pubkey).unwrap();
@@ -649,7 +649,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     process_command(&config).unwrap_err();
 
@@ -669,7 +669,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     let response = process_command(&config);
     let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -776,7 +776,7 @@ fn test_cli_program_close_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -889,7 +889,7 @@ fn test_cli_program_extend_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -939,7 +939,7 @@ fn test_cli_program_extend_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     process_command(&config).unwrap_err();
 
@@ -974,7 +974,7 @@ fn test_cli_program_extend_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     process_command(&config).unwrap();
 }
@@ -1329,7 +1329,7 @@ fn test_cli_program_write_buffer() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let error = process_command(&config).unwrap_err();
@@ -1459,7 +1459,7 @@ fn test_cli_program_set_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap_err();
@@ -1507,7 +1507,7 @@ fn test_cli_program_set_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -1593,7 +1593,7 @@ fn test_cli_program_mismatch_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     process_command(&config).unwrap_err();
 
@@ -1613,7 +1613,7 @@ fn test_cli_program_mismatch_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     process_command(&config).unwrap();
 }
@@ -1699,7 +1699,7 @@ fn test_cli_program_deploy_with_offline_signing(use_offline_signer_as_fee_payer:
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -1933,7 +1933,7 @@ fn test_cli_program_show() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        use_rpc: false,
+        auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let min_slot = rpc_client.get_slot().unwrap();
@@ -2210,7 +2210,7 @@ fn test_cli_program_deploy_with_args(compute_unit_price: Option<u64>, use_rpc: b
         skip_fee_check: false,
         compute_unit_price,
         max_sign_attempts: 5,
-        use_rpc,
+        auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -2312,3 +2312,120 @@ fn test_cli_program_deploy_with_args(compute_unit_price: Option<u64>, use_rpc: b
         );
     }
 }
+
+#[test]
+fn test_cli_program_deploy_with_compute_unit_price() {
+    cli_program_deploy_with_args(Some(1000));
+    cli_program_deploy_with_args(None);
+}
+
+#[test]
+fn test_cli_program_upgrade_auto_extend_program_data_account() {
+    solana_logger::setup();
+
+    let mut noop_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+    noop_path.push("tests");
+    noop_path.push("fixtures");
+    noop_path.push("noop");
+    noop_path.set_extension("so");
+
+    let mut noop_large_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+    noop_large_path.push("tests");
+    noop_large_path.push("fixtures");
+    noop_large_path.push("noop_large");
+    noop_large_path.set_extension("so");
+
+    let mint_keypair = Keypair::new();
+    let mint_pubkey = mint_keypair.pubkey();
+    let faucet_addr = run_local_faucet(mint_keypair, None);
+    let test_validator =
+        TestValidator::with_no_fees(mint_pubkey, Some(faucet_addr), SocketAddrSpace::Unspecified);
+
+    let rpc_client =
+        RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
+
+    let mut file = File::open(noop_path.to_str().unwrap()).unwrap();
+    let mut program_data = Vec::new();
+    file.read_to_end(&mut program_data).unwrap();
+    let max_len = program_data.len();
+    let minimum_balance_for_programdata = rpc_client
+        .get_minimum_balance_for_rent_exemption(UpgradeableLoaderState::size_of_programdata(
+            max_len,
+        ))
+        .unwrap();
+    let minimum_balance_for_program = rpc_client
+        .get_minimum_balance_for_rent_exemption(UpgradeableLoaderState::size_of_program())
+        .unwrap();
+    let upgrade_authority = Keypair::new();
+
+    let mut config = CliConfig::recent_for_tests();
+    let keypair = Keypair::new();
+    config.json_rpc_url = test_validator.rpc_url();
+    config.signers = vec![&keypair];
+    config.command = CliCommand::Airdrop {
+        pubkey: None,
+        lamports: 100 * minimum_balance_for_programdata + minimum_balance_for_program,
+    };
+    process_command(&config).unwrap();
+
+    // Deploy the upgradeable program
+    let program_keypair = Keypair::new();
+    config.signers = vec![&keypair, &upgrade_authority, &program_keypair];
+    config.command = CliCommand::Program(ProgramCliCommand::Deploy {
+        program_location: Some(noop_path.to_str().unwrap().to_string()),
+        fee_payer_signer_index: 0,
+        program_signer_index: Some(2),
+        program_pubkey: Some(program_keypair.pubkey()),
+        buffer_signer_index: None,
+        buffer_pubkey: None,
+        allow_excessive_balance: false,
+        upgrade_authority_signer_index: 1,
+        is_final: false,
+        max_len: None, // Use None to check that it defaults to the max length
+        skip_fee_check: false,
+        compute_unit_price: None,
+        max_sign_attempts: 5,
+        auto_extend_program: false,
+    });
+    config.output_format = OutputFormat::JsonCompact;
+    process_command(&config).unwrap();
+
+    let (programdata_pubkey, _) = Pubkey::find_program_address(
+        &[program_keypair.pubkey().as_ref()],
+        &bpf_loader_upgradeable::id(),
+    );
+
+    let programdata_account = rpc_client.get_account(&programdata_pubkey).unwrap();
+    let expected_len = UpgradeableLoaderState::size_of_programdata(max_len);
+    assert_eq!(expected_len, programdata_account.data.len());
+
+    // Wait one slot to avoid "Program was deployed in this block already" error
+    wait_n_slots(&rpc_client, 1);
+
+    // Extend program for larger program, minus 1 required byte
+    let mut file = File::open(noop_large_path.to_str().unwrap()).unwrap();
+    let mut new_program_data = Vec::new();
+    file.read_to_end(&mut new_program_data).unwrap();
+
+    let programdata_account = rpc_client.get_account(&programdata_pubkey).unwrap();
+    assert_eq!(expected_len, programdata_account.data.len());
+
+    config.signers = vec![&keypair, &upgrade_authority];
+    config.command = CliCommand::Program(ProgramCliCommand::Deploy {
+        program_location: Some(noop_large_path.to_str().unwrap().to_string()),
+        fee_payer_signer_index: 0,
+        program_signer_index: None,
+        program_pubkey: Some(program_keypair.pubkey()),
+        buffer_signer_index: None,
+        buffer_pubkey: None,
+        allow_excessive_balance: false,
+        upgrade_authority_signer_index: 1,
+        is_final: false,
+        max_len: None,
+        skip_fee_check: false,
+        compute_unit_price: None,
+        max_sign_attempts: 5,
+        auto_extend_program: true,
+    });
+    process_command(&config).unwrap();
+}

From b44539310cc76414113b95285bae45020e225c21 Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Sat, 13 Apr 2024 13:24:49 +0530
Subject: [PATCH 02/14] remove logs

---
 cli/src/program.rs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index ded59595f7b36a..5ff13ae7bfa3f8 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -277,7 +277,7 @@ impl ProgramSubCommands for App<'_, '_> {
                                 .long("auto-extend-program")
                                 .takes_value(false)
                                 .help(
-                                    "Automatically extend the program data account size to match the updated program's data size",
+                                    "Automatically extend the program data account's size to match the updated program's data size",
                                 ),
                         ),
                 )
@@ -2511,7 +2511,6 @@ fn do_process_program_upgrade(
         let additional_bytes = program_len
             .sub(program_data_account.data.len())
             .saturating_add(metadata_size);
-        println!("additional_bytes: {}", additional_bytes);
         if auto_extend_program {
             Some(bpf_loader_upgradeable::extend_program(
                 program_id,

From a19c506965acf2a0ef6de909a83a0dc348c81f44 Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Sat, 13 Apr 2024 13:25:56 +0530
Subject: [PATCH 03/14] cleanup tests

---
 cli/tests/program.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cli/tests/program.rs b/cli/tests/program.rs
index db5d04cfea72c1..017cb17e9bd2dc 100644
--- a/cli/tests/program.rs
+++ b/cli/tests/program.rs
@@ -2402,7 +2402,6 @@ fn test_cli_program_upgrade_auto_extend_program_data_account() {
     // Wait one slot to avoid "Program was deployed in this block already" error
     wait_n_slots(&rpc_client, 1);
 
-    // Extend program for larger program, minus 1 required byte
     let mut file = File::open(noop_large_path.to_str().unwrap()).unwrap();
     let mut new_program_data = Vec::new();
     file.read_to_end(&mut new_program_data).unwrap();
@@ -2425,6 +2424,7 @@ fn test_cli_program_upgrade_auto_extend_program_data_account() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
+        // Enable auto_extend_program
         auto_extend_program: true,
     });
     process_command(&config).unwrap();

From d5aae8c6109ad9751b9b543eed67ea54034df5ad Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Wed, 17 Apr 2024 21:18:43 +0530
Subject: [PATCH 04/14] automatically extend program data account and add a
 --no-auto-extend-program falg

---
 cli/src/program.rs   | 48 ++++++++++++++++----------------
 cli/tests/program.rs | 65 ++++++++++++++++++++++++--------------------
 2 files changed, 59 insertions(+), 54 deletions(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 5ff13ae7bfa3f8..2cb66e2f13e577 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -100,7 +100,7 @@ pub enum ProgramCliCommand {
         skip_fee_check: bool,
         compute_unit_price: Option<u64>,
         max_sign_attempts: usize,
-        auto_extend_program: bool,
+        no_auto_extend_program: bool,
     },
     Upgrade {
         fee_payer_signer_index: SignerIndex,
@@ -273,12 +273,10 @@ impl ProgramSubCommands for App<'_, '_> {
                         )
                         .arg(compute_unit_price_arg())
                         .arg(
-                              Arg::with_name("auto_extend_program")
-                                .long("auto-extend-program")
+                            Arg::with_name("no_auto_extend_program")
+                                .long("no-auto-extend-program")
                                 .takes_value(false)
-                                .help(
-                                    "Automatically extend the program data account's size to match the updated program's data size",
-                                ),
+                                .help("Don't automatically extend the program's data account size"),
                         ),
                 )
                 .subcommand(
@@ -671,7 +669,7 @@ pub fn parse_program_subcommand(
             let compute_unit_price = value_of(matches, "compute_unit_price");
             let max_sign_attempts = value_of(matches, "max_sign_attempts").unwrap();
 
-            let auto_extend_program = matches.is_present("auto_extend_program");
+            let no_auto_extend_program = matches.is_present("no_auto_extend_program");
 
             CliCommandInfo {
                 command: CliCommand::Program(ProgramCliCommand::Deploy {
@@ -690,7 +688,7 @@ pub fn parse_program_subcommand(
                     skip_fee_check,
                     compute_unit_price,
                     max_sign_attempts,
-                    auto_extend_program,
+                    no_auto_extend_program,
                 }),
                 signers: signer_info.signers,
             }
@@ -978,7 +976,7 @@ pub fn process_program_subcommand(
             skip_fee_check,
             compute_unit_price,
             max_sign_attempts,
-            auto_extend_program,
+            no_auto_extend_program,
         } => process_program_deploy(
             rpc_client,
             config,
@@ -995,7 +993,7 @@ pub fn process_program_subcommand(
             *skip_fee_check,
             *compute_unit_price,
             *max_sign_attempts,
-            *auto_extend_program,
+            *no_auto_extend_program,
         ),
         ProgramCliCommand::Upgrade {
             fee_payer_signer_index,
@@ -1173,7 +1171,7 @@ fn process_program_deploy(
     skip_fee_check: bool,
     compute_unit_price: Option<u64>,
     max_sign_attempts: usize,
-    auto_extend_program: bool,
+    no_auto_extend_program: bool,
 ) -> ProcessResult {
     let fee_payer_signer = config.signers[fee_payer_signer_index];
     let upgrade_authority_signer = config.signers[upgrade_authority_signer_index];
@@ -1358,7 +1356,7 @@ fn process_program_deploy(
             skip_fee_check,
             compute_unit_price,
             max_sign_attempts,
-            auto_extend_program,
+            no_auto_extend_program,
         )
     };
     if result.is_ok() && is_final {
@@ -2498,7 +2496,7 @@ fn do_process_program_upgrade(
     skip_fee_check: bool,
     compute_unit_price: Option<u64>,
     max_sign_attempts: usize,
-    auto_extend_program: bool,
+    no_auto_extend_program: bool,
 ) -> ProcessResult {
     let blockhash = rpc_client.get_latest_blockhash()?;
     let program_data_address = get_program_data_address(program_id);
@@ -2511,7 +2509,7 @@ fn do_process_program_upgrade(
         let additional_bytes = program_len
             .sub(program_data_account.data.len())
             .saturating_add(metadata_size);
-        if auto_extend_program {
+        if !no_auto_extend_program {
             Some(bpf_loader_upgradeable::extend_program(
                 program_id,
                 Some(&fee_payer_signer.pubkey()),
@@ -2520,8 +2518,8 @@ fn do_process_program_upgrade(
         } else {
             let err_string = format!(
                 r#"Program Data Account space is not enough
-please extend the program data account with command: solana program extend {} {}
-or pass flag --auto-extend-program to extend program data account automatically"#,
+please extend the program data account with command: solana program extend {} {},
+please disable the --no-extend-program flag to automatically extend the program account size"#,
                 program_id, additional_bytes
             );
             return Err(err_string.into());
@@ -3000,7 +2998,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    auto_extend_program: false,
+                    no_auto_extend_program: false,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3031,7 +3029,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    auto_extend_program: false
+                    no_auto_extend_program: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3064,7 +3062,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    auto_extend_program: false
+                    no_auto_extend_program: false
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3099,7 +3097,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    auto_extend_program: false
+                    no_auto_extend_program: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3133,7 +3131,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    auto_extend_program: false
+                    no_auto_extend_program: false
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3170,7 +3168,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    auto_extend_program: false
+                    no_auto_extend_program: false
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3203,7 +3201,7 @@ mod tests {
                     allow_excessive_balance: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    auto_extend_program: false
+                    no_auto_extend_program: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3234,7 +3232,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 1,
-                    auto_extend_program: false
+                    no_auto_extend_program: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3977,7 +3975,7 @@ mod tests {
                 skip_fee_check: false,
                 compute_unit_price: None,
                 max_sign_attempts: 5,
-                auto_extend_program: false,
+                no_auto_extend_program: false,
             }),
             signers: vec![&default_keypair],
             output_format: OutputFormat::JsonCompact,
diff --git a/cli/tests/program.rs b/cli/tests/program.rs
index 017cb17e9bd2dc..c12eeab174877e 100644
--- a/cli/tests/program.rs
+++ b/cli/tests/program.rs
@@ -99,7 +99,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -148,7 +148,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     process_command(&config).unwrap();
     let account1 = rpc_client
@@ -206,7 +206,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     let err = process_command(&config).unwrap_err();
     assert_eq!(
@@ -232,7 +232,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     process_command(&config).unwrap_err();
 }
@@ -296,7 +296,7 @@ fn test_cli_program_deploy_no_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -326,7 +326,7 @@ fn test_cli_program_deploy_no_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     process_command(&config).unwrap_err();
 }
@@ -391,7 +391,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -443,7 +443,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     let response = process_command(&config);
     let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -489,7 +489,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     process_command(&config).unwrap();
     let program_account = rpc_client.get_account(&program_pubkey).unwrap();
@@ -567,7 +567,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     process_command(&config).unwrap();
     let program_account = rpc_client.get_account(&program_pubkey).unwrap();
@@ -649,7 +649,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     process_command(&config).unwrap_err();
 
@@ -669,7 +669,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     let response = process_command(&config);
     let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -776,7 +776,7 @@ fn test_cli_program_close_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -889,7 +889,7 @@ fn test_cli_program_extend_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -939,7 +939,7 @@ fn test_cli_program_extend_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     process_command(&config).unwrap_err();
 
@@ -974,7 +974,7 @@ fn test_cli_program_extend_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     process_command(&config).unwrap();
 }
@@ -1329,7 +1329,7 @@ fn test_cli_program_write_buffer() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let error = process_command(&config).unwrap_err();
@@ -1459,7 +1459,7 @@ fn test_cli_program_set_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap_err();
@@ -1507,7 +1507,7 @@ fn test_cli_program_set_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -1593,7 +1593,7 @@ fn test_cli_program_mismatch_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     process_command(&config).unwrap_err();
 
@@ -1613,7 +1613,7 @@ fn test_cli_program_mismatch_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     process_command(&config).unwrap();
 }
@@ -1699,7 +1699,7 @@ fn test_cli_program_deploy_with_offline_signing(use_offline_signer_as_fee_payer:
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -1933,7 +1933,7 @@ fn test_cli_program_show() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let min_slot = rpc_client.get_slot().unwrap();
@@ -2210,7 +2210,7 @@ fn test_cli_program_deploy_with_args(compute_unit_price: Option<u64>, use_rpc: b
         skip_fee_check: false,
         compute_unit_price,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -2320,7 +2320,7 @@ fn test_cli_program_deploy_with_compute_unit_price() {
 }
 
 #[test]
-fn test_cli_program_upgrade_auto_extend_program_data_account() {
+fn test_cli_program_upgrade_results_in_error_if_no_extend_program_flag_is_set() {
     solana_logger::setup();
 
     let mut noop_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
@@ -2385,7 +2385,7 @@ fn test_cli_program_upgrade_auto_extend_program_data_account() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        auto_extend_program: false,
+        no_auto_extend_program: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -2424,8 +2424,15 @@ fn test_cli_program_upgrade_auto_extend_program_data_account() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        // Enable auto_extend_program
-        auto_extend_program: true,
+        // set no_auto_extend_program
+        no_auto_extend_program: true,
     });
-    process_command(&config).unwrap();
+    let err = process_command(&config).unwrap_err();
+    let err_string_to_match = format!(
+        r#"Program Data Account space is not enough
+please extend the program data account with command: solana program extend {} 3184,
+please disable the --no-extend-program flag to automatically extend the program account size"#,
+        program_keypair.pubkey()
+    );
+    assert_eq!(err.to_string(), err_string_to_match);
 }

From ed895275f4037e25059b1d114ac30c81c4c98f85 Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Wed, 17 Apr 2024 21:27:17 +0530
Subject: [PATCH 05/14] change comments in do_process_program_upgrade

---
 cli/src/program.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 2cb66e2f13e577..833ee577744199 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -2503,6 +2503,7 @@ fn do_process_program_upgrade(
     let program_data_account = rpc_client.get_account(&program_data_address)?;
 
     //CHECK: if passed program size is greater than the current program data account size,
+    //auto extend the program data account .if no-auto-extend-program flag is set then
     //throw an err along with a message including additional bytes required
     let add_program_extend_ix = if program_len > program_data_account.data.len() {
         let metadata_size = UpgradeableLoaderState::size_of_programdata_metadata();

From fe201ae0bdebce8928d8fce9bdadd993f9381362 Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Wed, 17 Apr 2024 21:29:00 +0530
Subject: [PATCH 06/14] simplify  comments in do_process_program_upgrade

---
 cli/src/program.rs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 833ee577744199..060a79899c227b 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -2502,8 +2502,7 @@ fn do_process_program_upgrade(
     let program_data_address = get_program_data_address(program_id);
     let program_data_account = rpc_client.get_account(&program_data_address)?;
 
-    //CHECK: if passed program size is greater than the current program data account size,
-    //auto extend the program data account .if no-auto-extend-program flag is set then
+    //CHECK: auto extend program data account in case of insufficient space .if no-auto-extend-program flag is set then
     //throw an err along with a message including additional bytes required
     let add_program_extend_ix = if program_len > program_data_account.data.len() {
         let metadata_size = UpgradeableLoaderState::size_of_programdata_metadata();

From 6ed4600c745a3b2eab44f4bbe37e8c8ebfb7d0ed Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Thu, 18 Apr 2024 09:36:22 +0530
Subject: [PATCH 07/14] resolve comments

---
 cli/src/program.rs   |  97 ++++++++++++++-----------
 cli/tests/program.rs | 166 +++++++------------------------------------
 2 files changed, 79 insertions(+), 184 deletions(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 060a79899c227b..7a81aad9922660 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -100,7 +100,7 @@ pub enum ProgramCliCommand {
         skip_fee_check: bool,
         compute_unit_price: Option<u64>,
         max_sign_attempts: usize,
-        no_auto_extend_program: bool,
+        no_extend: bool,
     },
     Upgrade {
         fee_payer_signer_index: SignerIndex,
@@ -273,8 +273,8 @@ impl ProgramSubCommands for App<'_, '_> {
                         )
                         .arg(compute_unit_price_arg())
                         .arg(
-                            Arg::with_name("no_auto_extend_program")
-                                .long("no-auto-extend-program")
+                            Arg::with_name("no_extend")
+                                .long("no-extend")
                                 .takes_value(false)
                                 .help("Don't automatically extend the program's data account size"),
                         ),
@@ -669,7 +669,7 @@ pub fn parse_program_subcommand(
             let compute_unit_price = value_of(matches, "compute_unit_price");
             let max_sign_attempts = value_of(matches, "max_sign_attempts").unwrap();
 
-            let no_auto_extend_program = matches.is_present("no_auto_extend_program");
+            let no_extend = matches.is_present("no_extend");
 
             CliCommandInfo {
                 command: CliCommand::Program(ProgramCliCommand::Deploy {
@@ -688,7 +688,7 @@ pub fn parse_program_subcommand(
                     skip_fee_check,
                     compute_unit_price,
                     max_sign_attempts,
-                    no_auto_extend_program,
+                    no_extend,
                 }),
                 signers: signer_info.signers,
             }
@@ -976,7 +976,7 @@ pub fn process_program_subcommand(
             skip_fee_check,
             compute_unit_price,
             max_sign_attempts,
-            no_auto_extend_program,
+            no_extend,
         } => process_program_deploy(
             rpc_client,
             config,
@@ -993,7 +993,7 @@ pub fn process_program_subcommand(
             *skip_fee_check,
             *compute_unit_price,
             *max_sign_attempts,
-            *no_auto_extend_program,
+            *no_extend,
         ),
         ProgramCliCommand::Upgrade {
             fee_payer_signer_index,
@@ -1171,7 +1171,7 @@ fn process_program_deploy(
     skip_fee_check: bool,
     compute_unit_price: Option<u64>,
     max_sign_attempts: usize,
-    no_auto_extend_program: bool,
+    no_extend: bool,
 ) -> ProcessResult {
     let fee_payer_signer = config.signers[fee_payer_signer_index];
     let upgrade_authority_signer = config.signers[upgrade_authority_signer_index];
@@ -1356,7 +1356,7 @@ fn process_program_deploy(
             skip_fee_check,
             compute_unit_price,
             max_sign_attempts,
-            no_auto_extend_program,
+            no_extend,
         )
     };
     if result.is_ok() && is_final {
@@ -2496,36 +2496,49 @@ fn do_process_program_upgrade(
     skip_fee_check: bool,
     compute_unit_price: Option<u64>,
     max_sign_attempts: usize,
-    no_auto_extend_program: bool,
+    no_extend: bool,
 ) -> ProcessResult {
     let blockhash = rpc_client.get_latest_blockhash()?;
     let program_data_address = get_program_data_address(program_id);
-    let program_data_account = rpc_client.get_account(&program_data_address)?;
-
-    //CHECK: auto extend program data account in case of insufficient space .if no-auto-extend-program flag is set then
-    //throw an err along with a message including additional bytes required
-    let add_program_extend_ix = if program_len > program_data_account.data.len() {
-        let metadata_size = UpgradeableLoaderState::size_of_programdata_metadata();
-        let additional_bytes = program_len
-            .sub(program_data_account.data.len())
-            .saturating_add(metadata_size);
-        if !no_auto_extend_program {
-            Some(bpf_loader_upgradeable::extend_program(
-                program_id,
-                Some(&fee_payer_signer.pubkey()),
-                additional_bytes as u32,
-            ))
-        } else {
-            let err_string = format!(
-                r#"Program Data Account space is not enough
+    let program_data_account = rpc_client.get_account(&program_data_address);
+    let program_len_with_metadata = UpgradeableLoaderState::size_of_programdata(program_len);
+    // Check - auto extend program data account in case of insufficient space .
+    // if no-extend flag is set then
+    // throw an err along with a message including additional bytes required
+    let add_program_extend_ix = match program_data_account {
+        Ok(program_data_account) => {
+            if program_len_with_metadata > program_data_account.data.len() {
+                let additional_bytes =
+                    program_len_with_metadata.sub(program_data_account.data.len());
+                if !no_extend {
+                    if additional_bytes > u32::MAX as usize {
+                        let err_string = format!(
+                            r#"Cannot auto-extend Program Data Account space due to size limit
+please extend it manually by using the command: solana program extend {} {},"#,
+                            program_id, additional_bytes
+                        );
+
+                        return Err(err_string.into());
+                    }
+                    Some(bpf_loader_upgradeable::extend_program(
+                        program_id,
+                        Some(&fee_payer_signer.pubkey()),
+                        additional_bytes as u32,
+                    ))
+                } else {
+                    let err_string = format!(
+                        r#"Program Data Account space is not enough
 please extend the program data account with command: solana program extend {} {},
 please disable the --no-extend-program flag to automatically extend the program account size"#,
-                program_id, additional_bytes
-            );
-            return Err(err_string.into());
+                        program_id, additional_bytes
+                    );
+                    return Err(err_string.into());
+                }
+            } else {
+                None
+            }
         }
-    } else {
-        None
+        Err(_) => None,
     };
 
     let (initial_message, write_messages, balance_needed) = if let Some(buffer_signer) =
@@ -2998,7 +3011,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_auto_extend_program: false,
+                    no_extend: false,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3029,7 +3042,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_auto_extend_program: false
+                    no_extend: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3062,7 +3075,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_auto_extend_program: false
+                    no_extend: false
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3097,7 +3110,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_auto_extend_program: false
+                    no_extend: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3131,7 +3144,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_auto_extend_program: false
+                    no_extend: false
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3168,7 +3181,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_auto_extend_program: false
+                    no_extend: false
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3201,7 +3214,7 @@ mod tests {
                     allow_excessive_balance: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_auto_extend_program: false
+                    no_extend: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3232,7 +3245,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 1,
-                    no_auto_extend_program: false
+                    no_extend: false
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3975,7 +3988,7 @@ mod tests {
                 skip_fee_check: false,
                 compute_unit_price: None,
                 max_sign_attempts: 5,
-                no_auto_extend_program: false,
+                no_extend: false,
             }),
             signers: vec![&default_keypair],
             output_format: OutputFormat::JsonCompact,
diff --git a/cli/tests/program.rs b/cli/tests/program.rs
index c12eeab174877e..5193559e8e3052 100644
--- a/cli/tests/program.rs
+++ b/cli/tests/program.rs
@@ -99,7 +99,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -148,7 +148,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     process_command(&config).unwrap();
     let account1 = rpc_client
@@ -206,7 +206,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     let err = process_command(&config).unwrap_err();
     assert_eq!(
@@ -232,7 +232,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     process_command(&config).unwrap_err();
 }
@@ -296,7 +296,7 @@ fn test_cli_program_deploy_no_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -326,7 +326,7 @@ fn test_cli_program_deploy_no_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     process_command(&config).unwrap_err();
 }
@@ -391,7 +391,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -443,7 +443,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     let response = process_command(&config);
     let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -489,7 +489,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     process_command(&config).unwrap();
     let program_account = rpc_client.get_account(&program_pubkey).unwrap();
@@ -567,7 +567,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     process_command(&config).unwrap();
     let program_account = rpc_client.get_account(&program_pubkey).unwrap();
@@ -649,7 +649,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     process_command(&config).unwrap_err();
 
@@ -669,7 +669,7 @@ fn test_cli_program_deploy_with_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     let response = process_command(&config);
     let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -776,7 +776,7 @@ fn test_cli_program_close_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -889,7 +889,7 @@ fn test_cli_program_extend_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -939,7 +939,7 @@ fn test_cli_program_extend_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     process_command(&config).unwrap_err();
 
@@ -974,7 +974,7 @@ fn test_cli_program_extend_program() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     process_command(&config).unwrap();
 }
@@ -1329,7 +1329,7 @@ fn test_cli_program_write_buffer() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let error = process_command(&config).unwrap_err();
@@ -1459,7 +1459,7 @@ fn test_cli_program_set_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap_err();
@@ -1507,7 +1507,7 @@ fn test_cli_program_set_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -1593,7 +1593,7 @@ fn test_cli_program_mismatch_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     process_command(&config).unwrap_err();
 
@@ -1613,7 +1613,7 @@ fn test_cli_program_mismatch_buffer_authority() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     process_command(&config).unwrap();
 }
@@ -1699,7 +1699,7 @@ fn test_cli_program_deploy_with_offline_signing(use_offline_signer_as_fee_payer:
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -1933,7 +1933,7 @@ fn test_cli_program_show() {
         skip_fee_check: false,
         compute_unit_price: None,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let min_slot = rpc_client.get_slot().unwrap();
@@ -2210,7 +2210,7 @@ fn test_cli_program_deploy_with_args(compute_unit_price: Option<u64>, use_rpc: b
         skip_fee_check: false,
         compute_unit_price,
         max_sign_attempts: 5,
-        no_auto_extend_program: false,
+        no_extend: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -2318,121 +2318,3 @@ fn test_cli_program_deploy_with_compute_unit_price() {
     cli_program_deploy_with_args(Some(1000));
     cli_program_deploy_with_args(None);
 }
-
-#[test]
-fn test_cli_program_upgrade_results_in_error_if_no_extend_program_flag_is_set() {
-    solana_logger::setup();
-
-    let mut noop_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
-    noop_path.push("tests");
-    noop_path.push("fixtures");
-    noop_path.push("noop");
-    noop_path.set_extension("so");
-
-    let mut noop_large_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
-    noop_large_path.push("tests");
-    noop_large_path.push("fixtures");
-    noop_large_path.push("noop_large");
-    noop_large_path.set_extension("so");
-
-    let mint_keypair = Keypair::new();
-    let mint_pubkey = mint_keypair.pubkey();
-    let faucet_addr = run_local_faucet(mint_keypair, None);
-    let test_validator =
-        TestValidator::with_no_fees(mint_pubkey, Some(faucet_addr), SocketAddrSpace::Unspecified);
-
-    let rpc_client =
-        RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
-
-    let mut file = File::open(noop_path.to_str().unwrap()).unwrap();
-    let mut program_data = Vec::new();
-    file.read_to_end(&mut program_data).unwrap();
-    let max_len = program_data.len();
-    let minimum_balance_for_programdata = rpc_client
-        .get_minimum_balance_for_rent_exemption(UpgradeableLoaderState::size_of_programdata(
-            max_len,
-        ))
-        .unwrap();
-    let minimum_balance_for_program = rpc_client
-        .get_minimum_balance_for_rent_exemption(UpgradeableLoaderState::size_of_program())
-        .unwrap();
-    let upgrade_authority = Keypair::new();
-
-    let mut config = CliConfig::recent_for_tests();
-    let keypair = Keypair::new();
-    config.json_rpc_url = test_validator.rpc_url();
-    config.signers = vec![&keypair];
-    config.command = CliCommand::Airdrop {
-        pubkey: None,
-        lamports: 100 * minimum_balance_for_programdata + minimum_balance_for_program,
-    };
-    process_command(&config).unwrap();
-
-    // Deploy the upgradeable program
-    let program_keypair = Keypair::new();
-    config.signers = vec![&keypair, &upgrade_authority, &program_keypair];
-    config.command = CliCommand::Program(ProgramCliCommand::Deploy {
-        program_location: Some(noop_path.to_str().unwrap().to_string()),
-        fee_payer_signer_index: 0,
-        program_signer_index: Some(2),
-        program_pubkey: Some(program_keypair.pubkey()),
-        buffer_signer_index: None,
-        buffer_pubkey: None,
-        allow_excessive_balance: false,
-        upgrade_authority_signer_index: 1,
-        is_final: false,
-        max_len: None, // Use None to check that it defaults to the max length
-        skip_fee_check: false,
-        compute_unit_price: None,
-        max_sign_attempts: 5,
-        no_auto_extend_program: false,
-    });
-    config.output_format = OutputFormat::JsonCompact;
-    process_command(&config).unwrap();
-
-    let (programdata_pubkey, _) = Pubkey::find_program_address(
-        &[program_keypair.pubkey().as_ref()],
-        &bpf_loader_upgradeable::id(),
-    );
-
-    let programdata_account = rpc_client.get_account(&programdata_pubkey).unwrap();
-    let expected_len = UpgradeableLoaderState::size_of_programdata(max_len);
-    assert_eq!(expected_len, programdata_account.data.len());
-
-    // Wait one slot to avoid "Program was deployed in this block already" error
-    wait_n_slots(&rpc_client, 1);
-
-    let mut file = File::open(noop_large_path.to_str().unwrap()).unwrap();
-    let mut new_program_data = Vec::new();
-    file.read_to_end(&mut new_program_data).unwrap();
-
-    let programdata_account = rpc_client.get_account(&programdata_pubkey).unwrap();
-    assert_eq!(expected_len, programdata_account.data.len());
-
-    config.signers = vec![&keypair, &upgrade_authority];
-    config.command = CliCommand::Program(ProgramCliCommand::Deploy {
-        program_location: Some(noop_large_path.to_str().unwrap().to_string()),
-        fee_payer_signer_index: 0,
-        program_signer_index: None,
-        program_pubkey: Some(program_keypair.pubkey()),
-        buffer_signer_index: None,
-        buffer_pubkey: None,
-        allow_excessive_balance: false,
-        upgrade_authority_signer_index: 1,
-        is_final: false,
-        max_len: None,
-        skip_fee_check: false,
-        compute_unit_price: None,
-        max_sign_attempts: 5,
-        // set no_auto_extend_program
-        no_auto_extend_program: true,
-    });
-    let err = process_command(&config).unwrap_err();
-    let err_string_to_match = format!(
-        r#"Program Data Account space is not enough
-please extend the program data account with command: solana program extend {} 3184,
-please disable the --no-extend-program flag to automatically extend the program account size"#,
-        program_keypair.pubkey()
-    );
-    assert_eq!(err.to_string(), err_string_to_match);
-}

From d58e62f46afbb98c6e5775c11476011445d84d4c Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Thu, 18 Apr 2024 09:42:11 +0530
Subject: [PATCH 08/14] cleanup

---
 cli/src/program.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 7a81aad9922660..71a7a04c692451 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -2502,7 +2502,7 @@ fn do_process_program_upgrade(
     let program_data_address = get_program_data_address(program_id);
     let program_data_account = rpc_client.get_account(&program_data_address);
     let program_len_with_metadata = UpgradeableLoaderState::size_of_programdata(program_len);
-    // Check - auto extend program data account in case of insufficient space .
+    // Check - auto extend program data account in case of insufficient space
     // if no-extend flag is set then
     // throw an err along with a message including additional bytes required
     let add_program_extend_ix = match program_data_account {

From d92dcbc79d8039287c2f98f182affed23da5744a Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Thu, 18 Apr 2024 10:12:02 +0530
Subject: [PATCH 09/14] change error messages

---
 cli/src/program.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 71a7a04c692451..62666669c54f0b 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -2514,7 +2514,8 @@ fn do_process_program_upgrade(
                     if additional_bytes > u32::MAX as usize {
                         let err_string = format!(
                             r#"Cannot auto-extend Program Data Account space due to size limit
-please extend it manually by using the command: solana program extend {} {},"#,
+please extend it manually by runinng the command solana program extend {} <BYTES> multiple times 
+using chunks of additional bytes required:{}"#,
                             program_id, additional_bytes
                         );
 

From 1ed7c6574994f2c66aa70b38c99ea8232ea7a12e Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Tue, 23 Apr 2024 09:28:59 +0530
Subject: [PATCH 10/14] resolve comments

---
 cli/src/program.rs          | 74 ++++++++++++++-----------------------
 transaction-dos/src/main.rs |  1 +
 2 files changed, 29 insertions(+), 46 deletions(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 62666669c54f0b..254eb336fc46fe 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -2499,54 +2499,12 @@ fn do_process_program_upgrade(
     no_extend: bool,
 ) -> ProcessResult {
     let blockhash = rpc_client.get_latest_blockhash()?;
-    let program_data_address = get_program_data_address(program_id);
-    let program_data_account = rpc_client.get_account(&program_data_address);
-    let program_len_with_metadata = UpgradeableLoaderState::size_of_programdata(program_len);
-    // Check - auto extend program data account in case of insufficient space
-    // if no-extend flag is set then
-    // throw an err along with a message including additional bytes required
-    let add_program_extend_ix = match program_data_account {
-        Ok(program_data_account) => {
-            if program_len_with_metadata > program_data_account.data.len() {
-                let additional_bytes =
-                    program_len_with_metadata.sub(program_data_account.data.len());
-                if !no_extend {
-                    if additional_bytes > u32::MAX as usize {
-                        let err_string = format!(
-                            r#"Cannot auto-extend Program Data Account space due to size limit
-please extend it manually by runinng the command solana program extend {} <BYTES> multiple times 
-using chunks of additional bytes required:{}"#,
-                            program_id, additional_bytes
-                        );
-
-                        return Err(err_string.into());
-                    }
-                    Some(bpf_loader_upgradeable::extend_program(
-                        program_id,
-                        Some(&fee_payer_signer.pubkey()),
-                        additional_bytes as u32,
-                    ))
-                } else {
-                    let err_string = format!(
-                        r#"Program Data Account space is not enough
-please extend the program data account with command: solana program extend {} {},
-please disable the --no-extend-program flag to automatically extend the program account size"#,
-                        program_id, additional_bytes
-                    );
-                    return Err(err_string.into());
-                }
-            } else {
-                None
-            }
-        }
-        Err(_) => None,
-    };
 
     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, buffer_program_data) =
+        let (mut initial_instructions, balance_needed, buffer_program_data) =
             if let Some(mut account) = buffer_account {
                 let (ixs, balance_needed) = complete_partial_program_init(
                     &fee_payer_signer.pubkey(),
@@ -2574,9 +2532,33 @@ please disable the --no-extend-program flag to automatically extend the program
                 )
             };
 
-        // Add extend program instruction if ProgramData account needs to be extended
-        if let Some(add_program_extend_ix) = add_program_extend_ix {
-            initial_instructions.push(add_program_extend_ix);
+        if !no_extend {
+            // Attempt to look up the existing program's size, and automatically
+            // add an extend instruction if the program data account is too small.
+            let program_data_address = get_program_data_address(program_id);
+            if let Some(program_data_account) = rpc_client
+                .get_account_with_commitment(&program_data_address, config.commitment)?
+                .value
+            {
+                let program_len = UpgradeableLoaderState::size_of_programdata(program_len);
+                let account_data_len = program_data_account.data.len();
+                if program_len > account_data_len {
+                    let additional_bytes = program_len.sub(account_data_len);
+                    let additional_bytes: u32 = additional_bytes.try_into().map_err(|_| {
+                        format!(
+                            "Cannot auto-extend Program Data Account space due to size limit \
+                        please extend it manually with command `solana program extend {} \
+                        <BYTES>`. Additional bytes required: {}",
+                            program_id, additional_bytes
+                        )
+                    })?;
+                    initial_instructions.push(bpf_loader_upgradeable::extend_program(
+                        program_id,
+                        Some(&fee_payer_signer.pubkey()),
+                        additional_bytes,
+                    ));
+                }
+            }
         }
 
         let initial_message = if !initial_instructions.is_empty() {
diff --git a/transaction-dos/src/main.rs b/transaction-dos/src/main.rs
index 1e45a1fa5ccda4..8cd02173d62591 100644
--- a/transaction-dos/src/main.rs
+++ b/transaction-dos/src/main.rs
@@ -251,6 +251,7 @@ fn run_transactions_dos(
             max_sign_attempts: 5,
             use_rpc: false,
             skip_fee_check: true, // skip_fee_check
+            no_extend: false,
         });
 
         process_command(&config).expect("deploy didn't pass");

From c0af1f9d6d537cb0c24110afc9652a9c0cade334 Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Tue, 23 Apr 2024 20:46:21 +0530
Subject: [PATCH 11/14] Fix after rebase

---
 cli/src/program.rs   | 50 ++++++++++++++++++++++++++++++++++++++++++++
 cli/tests/program.rs | 30 ++++++++++++++++++++------
 2 files changed, 74 insertions(+), 6 deletions(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 254eb336fc46fe..9ca3d1c568a767 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -101,6 +101,7 @@ pub enum ProgramCliCommand {
         compute_unit_price: Option<u64>,
         max_sign_attempts: usize,
         no_extend: bool,
+        use_rpc: bool,
     },
     Upgrade {
         fee_payer_signer_index: SignerIndex,
@@ -271,6 +272,9 @@ impl ProgramSubCommands for App<'_, '_> {
                                     whichever comes first.",
                                 ),
                         )
+                        .arg(Arg::with_name("use_rpc").long("use-rpc").help(
+                            "Send transactions to the configured RPC instead of validator TPUs",
+                        ))
                         .arg(compute_unit_price_arg())
                         .arg(
                             Arg::with_name("no_extend")
@@ -688,6 +692,7 @@ pub fn parse_program_subcommand(
                     skip_fee_check,
                     compute_unit_price,
                     max_sign_attempts,
+                    use_rpc: matches.is_present("use_rpc"),
                     no_extend,
                 }),
                 signers: signer_info.signers,
@@ -977,6 +982,7 @@ pub fn process_program_subcommand(
             compute_unit_price,
             max_sign_attempts,
             no_extend,
+            use_rpc,
         } => process_program_deploy(
             rpc_client,
             config,
@@ -994,6 +1000,7 @@ pub fn process_program_subcommand(
             *compute_unit_price,
             *max_sign_attempts,
             *no_extend,
+            *use_rpc,
         ),
         ProgramCliCommand::Upgrade {
             fee_payer_signer_index,
@@ -1172,6 +1179,7 @@ fn process_program_deploy(
     compute_unit_price: Option<u64>,
     max_sign_attempts: usize,
     no_extend: bool,
+    use_rpc: bool,
 ) -> ProcessResult {
     let fee_payer_signer = config.signers[fee_payer_signer_index];
     let upgrade_authority_signer = config.signers[upgrade_authority_signer_index];
@@ -1357,6 +1365,7 @@ fn process_program_deploy(
             compute_unit_price,
             max_sign_attempts,
             no_extend,
+            use_rpc,
         )
     };
     if result.is_ok() && is_final {
@@ -2497,6 +2506,7 @@ fn do_process_program_upgrade(
     compute_unit_price: Option<u64>,
     max_sign_attempts: usize,
     no_extend: bool,
+    use_rpc: bool,
 ) -> ProcessResult {
     let blockhash = rpc_client.get_latest_blockhash()?;
 
@@ -2995,6 +3005,7 @@ mod tests {
                     compute_unit_price: None,
                     max_sign_attempts: 5,
                     no_extend: false,
+                    use_rpc: false,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3026,6 +3037,7 @@ mod tests {
                     compute_unit_price: None,
                     max_sign_attempts: 5,
                     no_extend: false
+                    use_rpc: false,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3059,6 +3071,7 @@ mod tests {
                     compute_unit_price: None,
                     max_sign_attempts: 5,
                     no_extend: false
+                    use_rpc: false,
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3094,6 +3107,7 @@ mod tests {
                     compute_unit_price: None,
                     max_sign_attempts: 5,
                     no_extend: false
+                    use_rpc: false,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3128,6 +3142,7 @@ mod tests {
                     compute_unit_price: None,
                     max_sign_attempts: 5,
                     no_extend: false
+                    use_rpc: false,
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3165,6 +3180,7 @@ mod tests {
                     compute_unit_price: None,
                     max_sign_attempts: 5,
                     no_extend: false
+                    use_rpc: false,
                 }),
                 signers: vec![
                     Box::new(read_keypair_file(&keypair_file).unwrap()),
@@ -3198,6 +3214,7 @@ mod tests {
                     compute_unit_price: None,
                     max_sign_attempts: 5,
                     no_extend: false
+                    use_rpc: false,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3229,6 +3246,38 @@ mod tests {
                     compute_unit_price: None,
                     max_sign_attempts: 1,
                     no_extend: false
+                    use_rpc: false,
+                }),
+                signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
+            }
+        );
+
+        let test_command = test_commands.clone().get_matches_from(vec![
+            "test",
+            "program",
+            "deploy",
+            "/Users/test/program.so",
+            "--use-rpc",
+        ]);
+        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: None,
+                    allow_excessive_balance: false,
+                    skip_fee_check: false,
+                    compute_unit_price: None,
+                    max_sign_attempts: 5,
+                    no_extend: false,
+                    use_rpc: true,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
             }
@@ -3972,6 +4021,7 @@ mod tests {
                 compute_unit_price: None,
                 max_sign_attempts: 5,
                 no_extend: false,
+                use_rpc: false,
             }),
             signers: vec![&default_keypair],
             output_format: OutputFormat::JsonCompact,
diff --git a/cli/tests/program.rs b/cli/tests/program.rs
index 5193559e8e3052..7224b1f94098f3 100644
--- a/cli/tests/program.rs
+++ b/cli/tests/program.rs
@@ -100,6 +100,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -149,6 +150,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     process_command(&config).unwrap();
     let account1 = rpc_client
@@ -207,6 +209,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     let err = process_command(&config).unwrap_err();
     assert_eq!(
@@ -233,6 +236,7 @@ fn test_cli_program_deploy_non_upgradeable() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     process_command(&config).unwrap_err();
 }
@@ -297,6 +301,7 @@ fn test_cli_program_deploy_no_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -327,6 +332,7 @@ fn test_cli_program_deploy_no_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     process_command(&config).unwrap_err();
 }
@@ -392,6 +398,7 @@ fn test_cli_program_deploy_with_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -444,6 +451,7 @@ fn test_cli_program_deploy_with_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     let response = process_command(&config);
     let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -490,6 +498,7 @@ fn test_cli_program_deploy_with_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     process_command(&config).unwrap();
     let program_account = rpc_client.get_account(&program_pubkey).unwrap();
@@ -568,6 +577,7 @@ fn test_cli_program_deploy_with_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     process_command(&config).unwrap();
     let program_account = rpc_client.get_account(&program_pubkey).unwrap();
@@ -650,6 +660,7 @@ fn test_cli_program_deploy_with_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     process_command(&config).unwrap_err();
 
@@ -670,6 +681,7 @@ fn test_cli_program_deploy_with_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     let response = process_command(&config);
     let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
@@ -777,6 +789,7 @@ fn test_cli_program_close_program() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -890,6 +903,7 @@ fn test_cli_program_extend_program() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -940,6 +954,7 @@ fn test_cli_program_extend_program() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     process_command(&config).unwrap_err();
 
@@ -975,6 +990,7 @@ fn test_cli_program_extend_program() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     process_command(&config).unwrap();
 }
@@ -1330,6 +1346,7 @@ fn test_cli_program_write_buffer() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let error = process_command(&config).unwrap_err();
@@ -1460,6 +1477,7 @@ fn test_cli_program_set_buffer_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap_err();
@@ -1508,6 +1526,7 @@ fn test_cli_program_set_buffer_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -1594,6 +1613,7 @@ fn test_cli_program_mismatch_buffer_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     process_command(&config).unwrap_err();
 
@@ -1614,6 +1634,7 @@ fn test_cli_program_mismatch_buffer_authority() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     process_command(&config).unwrap();
 }
@@ -1700,6 +1721,7 @@ fn test_cli_program_deploy_with_offline_signing(use_offline_signer_as_fee_payer:
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     process_command(&config).unwrap();
@@ -1934,6 +1956,7 @@ fn test_cli_program_show() {
         compute_unit_price: None,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc: false,
     });
     config.output_format = OutputFormat::JsonCompact;
     let min_slot = rpc_client.get_slot().unwrap();
@@ -2211,6 +2234,7 @@ fn test_cli_program_deploy_with_args(compute_unit_price: Option<u64>, use_rpc: b
         compute_unit_price,
         max_sign_attempts: 5,
         no_extend: false,
+        use_rpc,
     });
     config.output_format = OutputFormat::JsonCompact;
     let response = process_command(&config);
@@ -2312,9 +2336,3 @@ fn test_cli_program_deploy_with_args(compute_unit_price: Option<u64>, use_rpc: b
         );
     }
 }
-
-#[test]
-fn test_cli_program_deploy_with_compute_unit_price() {
-    cli_program_deploy_with_args(Some(1000));
-    cli_program_deploy_with_args(None);
-}

From 581f8813459ceafe96cc65c78f7604d37f89a3d8 Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Wed, 24 Apr 2024 09:14:46 +0530
Subject: [PATCH 12/14] Fix after rebase

---
 cli/src/program.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 9ca3d1c568a767..8fb4821852586a 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -273,7 +273,7 @@ impl ProgramSubCommands for App<'_, '_> {
                                 ),
                         )
                         .arg(Arg::with_name("use_rpc").long("use-rpc").help(
-                            "Send transactions to the configured RPC instead of validator TPUs",
+                            "Send write transactions to the configured RPC instead of validator TPUs",
                         ))
                         .arg(compute_unit_price_arg())
                         .arg(

From 4ee4dd239af5d46d76c1c087b8d4c08da4f68863 Mon Sep 17 00:00:00 2001
From: NagaprasadVr <nagaprasadvr246@gmail.com>
Date: Wed, 24 Apr 2024 09:57:40 +0530
Subject: [PATCH 13/14] fix cargo clippy

---
 cli/src/program.rs | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 8fb4821852586a..2b3b733da2e097 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -3036,7 +3036,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_extend: false
+                    no_extend: false,
                     use_rpc: false,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
@@ -3070,7 +3070,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_extend: false
+                    no_extend: false,
                     use_rpc: false,
                 }),
                 signers: vec![
@@ -3106,7 +3106,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_extend: false
+                    no_extend: false,
                     use_rpc: false,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
@@ -3141,7 +3141,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_extend: false
+                    no_extend: false,
                     use_rpc: false,
                 }),
                 signers: vec![
@@ -3179,7 +3179,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_extend: false
+                    no_extend: false,
                     use_rpc: false,
                 }),
                 signers: vec![
@@ -3213,7 +3213,7 @@ mod tests {
                     allow_excessive_balance: false,
                     compute_unit_price: None,
                     max_sign_attempts: 5,
-                    no_extend: false
+                    no_extend: false,
                     use_rpc: false,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
@@ -3245,7 +3245,7 @@ mod tests {
                     skip_fee_check: false,
                     compute_unit_price: None,
                     max_sign_attempts: 1,
-                    no_extend: false
+                    no_extend: false,
                     use_rpc: false,
                 }),
                 signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],

From 9b189a7b3955707264bb518c80a98f0a8b8d8a57 Mon Sep 17 00:00:00 2001
From: Joe Caulfield <joe.caulfield@anza.xyz>
Date: Wed, 24 Apr 2024 00:32:12 -0500
Subject: [PATCH 14/14] cli: add tests for auto-extend

---
 cli/src/program.rs   |   3 +-
 cli/tests/program.rs | 149 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+), 2 deletions(-)

diff --git a/cli/src/program.rs b/cli/src/program.rs
index 2b3b733da2e097..26b7db382e4764 100644
--- a/cli/src/program.rs
+++ b/cli/src/program.rs
@@ -71,7 +71,6 @@ use {
         fs::File,
         io::{Read, Write},
         mem::size_of,
-        ops::Sub,
         path::PathBuf,
         rc::Rc,
         str::FromStr,
@@ -2553,7 +2552,7 @@ fn do_process_program_upgrade(
                 let program_len = UpgradeableLoaderState::size_of_programdata(program_len);
                 let account_data_len = program_data_account.data.len();
                 if program_len > account_data_len {
-                    let additional_bytes = program_len.sub(account_data_len);
+                    let additional_bytes = program_len.saturating_sub(account_data_len);
                     let additional_bytes: u32 = additional_bytes.try_into().map_err(|_| {
                         format!(
                             "Cannot auto-extend Program Data Account space due to size limit \
diff --git a/cli/tests/program.rs b/cli/tests/program.rs
index 7224b1f94098f3..2215f84a453af9 100644
--- a/cli/tests/program.rs
+++ b/cli/tests/program.rs
@@ -19,6 +19,7 @@ use {
     solana_rpc_client::rpc_client::RpcClient,
     solana_rpc_client_nonce_utils::blockhash_query::BlockhashQuery,
     solana_sdk::{
+        account::ReadableAccount,
         account_utils::StateMut,
         borsh1::try_from_slice_unchecked,
         bpf_loader_upgradeable::{self, UpgradeableLoaderState},
@@ -728,6 +729,154 @@ fn test_cli_program_deploy_with_authority() {
     assert_eq!("none", authority_pubkey_str);
 }
 
+#[test]
+fn test_cli_program_upgrade_auto_extend() {
+    solana_logger::setup();
+
+    let mut noop_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+    noop_path.push("tests");
+    noop_path.push("fixtures");
+    noop_path.push("noop");
+    noop_path.set_extension("so");
+
+    let mut noop_large_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+    noop_large_path.push("tests");
+    noop_large_path.push("fixtures");
+    noop_large_path.push("noop_large");
+    noop_large_path.set_extension("so");
+
+    let mint_keypair = Keypair::new();
+    let mint_pubkey = mint_keypair.pubkey();
+    let faucet_addr = run_local_faucet(mint_keypair, None);
+    let test_validator =
+        TestValidator::with_no_fees(mint_pubkey, Some(faucet_addr), SocketAddrSpace::Unspecified);
+
+    let rpc_client =
+        RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
+
+    let mut file = File::open(noop_path.to_str().unwrap()).unwrap();
+    let mut program_data = Vec::new();
+    file.read_to_end(&mut program_data).unwrap();
+
+    let mut file = File::open(noop_large_path.to_str().unwrap()).unwrap();
+    let mut program_data_large = Vec::new();
+    file.read_to_end(&mut program_data_large).unwrap();
+
+    // Use the larger program to calculate rent.
+    let max_len = program_data_large.len();
+    let minimum_balance_for_programdata = rpc_client
+        .get_minimum_balance_for_rent_exemption(UpgradeableLoaderState::size_of_programdata(
+            max_len,
+        ))
+        .unwrap();
+    let minimum_balance_for_program = rpc_client
+        .get_minimum_balance_for_rent_exemption(UpgradeableLoaderState::size_of_program())
+        .unwrap();
+    let upgrade_authority = Keypair::new();
+
+    let mut config = CliConfig::recent_for_tests();
+    let keypair = Keypair::new();
+    config.json_rpc_url = test_validator.rpc_url();
+    config.signers = vec![&keypair];
+    config.command = CliCommand::Airdrop {
+        pubkey: None,
+        lamports: 100 * minimum_balance_for_programdata + minimum_balance_for_program,
+    };
+    process_command(&config).unwrap();
+
+    // Deploy the first, smaller program.
+    let program_keypair = Keypair::new();
+    config.signers = vec![&keypair, &upgrade_authority, &program_keypair];
+    config.command = CliCommand::Program(ProgramCliCommand::Deploy {
+        program_location: Some(noop_path.to_str().unwrap().to_string()),
+        fee_payer_signer_index: 0,
+        program_signer_index: Some(2),
+        program_pubkey: Some(program_keypair.pubkey()),
+        buffer_signer_index: None,
+        buffer_pubkey: None,
+        allow_excessive_balance: false,
+        upgrade_authority_signer_index: 1,
+        is_final: false,
+        max_len: None,
+        skip_fee_check: false,
+        compute_unit_price: None,
+        max_sign_attempts: 5,
+        no_extend: false,
+        use_rpc: false,
+    });
+    config.output_format = OutputFormat::JsonCompact;
+    process_command(&config).unwrap();
+
+    // Attempt to upgrade the program with a larger program, but with the
+    // --no-extend flag.
+    config.signers = vec![&keypair, &upgrade_authority];
+    config.command = CliCommand::Program(ProgramCliCommand::Deploy {
+        program_location: Some(noop_large_path.to_str().unwrap().to_string()),
+        fee_payer_signer_index: 0,
+        program_signer_index: None,
+        program_pubkey: Some(program_keypair.pubkey()),
+        buffer_signer_index: None,
+        buffer_pubkey: None,
+        allow_excessive_balance: false,
+        upgrade_authority_signer_index: 1,
+        is_final: true,
+        max_len: None,
+        skip_fee_check: false,
+        compute_unit_price: None,
+        max_sign_attempts: 5,
+        no_extend: true, // --no-extend (true)
+        use_rpc: false,
+    });
+    process_command(&config).unwrap_err();
+
+    // Attempt to upgrade the program with a larger program, this time without
+    // the --no-extend flag. This should automatically extend the program data.
+    config.signers = vec![&keypair, &upgrade_authority];
+    config.command = CliCommand::Program(ProgramCliCommand::Deploy {
+        program_location: Some(noop_large_path.to_str().unwrap().to_string()),
+        fee_payer_signer_index: 0,
+        program_signer_index: None,
+        program_pubkey: Some(program_keypair.pubkey()),
+        buffer_signer_index: None,
+        buffer_pubkey: None,
+        allow_excessive_balance: false,
+        upgrade_authority_signer_index: 1,
+        is_final: true,
+        max_len: None,
+        skip_fee_check: false,
+        compute_unit_price: None,
+        max_sign_attempts: 5,
+        no_extend: false, // --no-extend (false)
+        use_rpc: false,
+    });
+    let response = process_command(&config);
+    let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
+    let program_pubkey_str = json
+        .as_object()
+        .unwrap()
+        .get("programId")
+        .unwrap()
+        .as_str()
+        .unwrap();
+    let program_pubkey = Pubkey::from_str(program_pubkey_str).unwrap();
+    let (programdata_pubkey, _) =
+        Pubkey::find_program_address(&[program_pubkey.as_ref()], &bpf_loader_upgradeable::id());
+    let programdata_account = rpc_client.get_account(&programdata_pubkey).unwrap();
+    if let UpgradeableLoaderState::ProgramData {
+        slot: _,
+        upgrade_authority_address,
+    } = programdata_account.state().unwrap()
+    {
+        assert_eq!(upgrade_authority_address, None);
+    } else {
+        panic!("not a ProgramData account");
+    }
+    assert_eq!(
+        programdata_account.data().len(),
+        UpgradeableLoaderState::size_of_programdata(program_data_large.len()),
+    );
+}
+
 #[test]
 fn test_cli_program_close_program() {
     solana_logger::setup();