Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI: Auto-extend program accounts by default #791

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
Loading