Skip to content

Commit

Permalink
CLI: Auto-extend program accounts by default (#791)
Browse files Browse the repository at this point in the history
* add checks for program data account overflow during upgrade and add --auto-extend-program flag to solana program deploy command

* remove logs

* cleanup tests

* automatically extend program data account and add a --no-auto-extend-program falg

* change comments in do_process_program_upgrade

* simplify  comments in do_process_program_upgrade

* resolve comments

* cleanup

* change error messages

* resolve comments

* Fix after rebase

* Fix after rebase

* fix cargo clippy

* cli: add tests for auto-extend

---------

Co-authored-by: Joe Caulfield <[email protected]>
  • Loading branch information
Nagaprasadvr and buffalojoec authored Apr 24, 2024
1 parent 748db10 commit 23905c0
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 3 deletions.
60 changes: 57 additions & 3 deletions cli/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -99,6 +99,7 @@ pub enum ProgramCliCommand {
skip_fee_check: bool,
compute_unit_price: Option<u64>,
max_sign_attempts: usize,
no_extend: bool,
use_rpc: bool,
},
Upgrade {
Expand Down Expand Up @@ -273,7 +274,13 @@ impl ProgramSubCommands for App<'_, '_> {
.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("no_extend")
.long("no-extend")
.takes_value(false)
.help("Don't automatically extend the program's data account size"),
),
)
.subcommand(
SubCommand::with_name("upgrade")
Expand Down Expand Up @@ -665,6 +672,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 no_extend = matches.is_present("no_extend");

CliCommandInfo {
command: CliCommand::Program(ProgramCliCommand::Deploy {
program_location,
Expand All @@ -683,6 +692,7 @@ pub fn parse_program_subcommand(
compute_unit_price,
max_sign_attempts,
use_rpc: matches.is_present("use_rpc"),
no_extend,
}),
signers: signer_info.signers,
}
Expand Down Expand Up @@ -970,6 +980,7 @@ pub fn process_program_subcommand(
skip_fee_check,
compute_unit_price,
max_sign_attempts,
no_extend,
use_rpc,
} => process_program_deploy(
rpc_client,
Expand All @@ -987,6 +998,7 @@ pub fn process_program_subcommand(
*skip_fee_check,
*compute_unit_price,
*max_sign_attempts,
*no_extend,
*use_rpc,
),
ProgramCliCommand::Upgrade {
Expand Down Expand Up @@ -1165,6 +1177,7 @@ fn process_program_deploy(
skip_fee_check: bool,
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];
Expand Down Expand Up @@ -1350,6 +1363,7 @@ fn process_program_deploy(
skip_fee_check,
compute_unit_price,
max_sign_attempts,
no_extend,
use_rpc,
)
};
Expand Down Expand Up @@ -2490,6 +2504,7 @@ fn do_process_program_upgrade(
skip_fee_check: bool,
compute_unit_price: Option<u64>,
max_sign_attempts: usize,
no_extend: bool,
use_rpc: bool,
) -> ProcessResult {
let blockhash = rpc_client.get_latest_blockhash()?;
Expand All @@ -2498,7 +2513,7 @@ fn do_process_program_upgrade(
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(),
Expand Down Expand Up @@ -2526,6 +2541,35 @@ fn do_process_program_upgrade(
)
};

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.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 \
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() {
Some(Message::new_with_blockhash(
&initial_instructions
Expand Down Expand Up @@ -2959,6 +3003,7 @@ mod tests {
skip_fee_check: false,
compute_unit_price: None,
max_sign_attempts: 5,
no_extend: false,
use_rpc: false,
}),
signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
Expand Down Expand Up @@ -2990,6 +3035,7 @@ mod tests {
skip_fee_check: false,
compute_unit_price: None,
max_sign_attempts: 5,
no_extend: false,
use_rpc: false,
}),
signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
Expand Down Expand Up @@ -3023,6 +3069,7 @@ mod tests {
skip_fee_check: false,
compute_unit_price: None,
max_sign_attempts: 5,
no_extend: false,
use_rpc: false,
}),
signers: vec![
Expand Down Expand Up @@ -3058,6 +3105,7 @@ mod tests {
skip_fee_check: false,
compute_unit_price: None,
max_sign_attempts: 5,
no_extend: false,
use_rpc: false,
}),
signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
Expand Down Expand Up @@ -3092,6 +3140,7 @@ mod tests {
skip_fee_check: false,
compute_unit_price: None,
max_sign_attempts: 5,
no_extend: false,
use_rpc: false,
}),
signers: vec![
Expand Down Expand Up @@ -3129,6 +3178,7 @@ mod tests {
skip_fee_check: false,
compute_unit_price: None,
max_sign_attempts: 5,
no_extend: false,
use_rpc: false,
}),
signers: vec![
Expand Down Expand Up @@ -3162,6 +3212,7 @@ mod tests {
allow_excessive_balance: false,
compute_unit_price: None,
max_sign_attempts: 5,
no_extend: false,
use_rpc: false,
}),
signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
Expand Down Expand Up @@ -3193,6 +3244,7 @@ mod tests {
skip_fee_check: false,
compute_unit_price: None,
max_sign_attempts: 1,
no_extend: false,
use_rpc: false,
}),
signers: vec![Box::new(read_keypair_file(&keypair_file).unwrap())],
Expand Down Expand Up @@ -3223,6 +3275,7 @@ mod tests {
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())],
Expand Down Expand Up @@ -3966,6 +4019,7 @@ mod tests {
skip_fee_check: false,
compute_unit_price: None,
max_sign_attempts: 5,
no_extend: false,
use_rpc: false,
}),
signers: vec![&default_keypair],
Expand Down
Loading

0 comments on commit 23905c0

Please sign in to comment.