Reduce payer balance needed to deploy programs (#19645)
* Reduce payer balance needed to deploy programs * Fix test and unbalanced ix error * fix test * fix up tests
This commit is contained in:
parent
e6b4dd3866
commit
efd024510a
|
@ -31,11 +31,11 @@ use solana_sdk::{
|
|||
clock::Clock,
|
||||
entrypoint::{HEAP_LENGTH, SUCCESS},
|
||||
feature_set::{
|
||||
add_missing_program_error_mappings, close_upgradeable_program_accounts,
|
||||
add_missing_program_error_mappings, close_upgradeable_program_accounts, fix_write_privs,
|
||||
stop_verify_mul64_imm_nonzero,
|
||||
},
|
||||
ic_logger_msg, ic_msg,
|
||||
instruction::InstructionError,
|
||||
instruction::{AccountMeta, InstructionError},
|
||||
keyed_account::{from_keyed_account, keyed_account_at_index, KeyedAccount},
|
||||
loader_instruction::LoaderInstruction,
|
||||
loader_upgradeable_instruction::UpgradeableLoaderInstruction,
|
||||
|
@ -390,13 +390,27 @@ fn process_loader_upgradeable_instruction(
|
|||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
|
||||
let instruction = system_instruction::create_account(
|
||||
if invoke_context.is_feature_active(&fix_write_privs::id()) {
|
||||
// Drain the Buffer account to payer before paying for programdata account
|
||||
payer
|
||||
.try_account_ref_mut()?
|
||||
.checked_add_lamports(buffer.lamports()?)?;
|
||||
buffer.try_account_ref_mut()?.set_lamports(0);
|
||||
}
|
||||
|
||||
let mut instruction = system_instruction::create_account(
|
||||
payer.unsigned_key(),
|
||||
programdata.unsigned_key(),
|
||||
1.max(rent.minimum_balance(programdata_len)),
|
||||
programdata_len as u64,
|
||||
program_id,
|
||||
);
|
||||
|
||||
// pass an extra account to avoid the overly strict UnbalancedInstruction error
|
||||
instruction
|
||||
.accounts
|
||||
.push(AccountMeta::new(*buffer.unsigned_key(), false));
|
||||
|
||||
let caller_program_id = invoke_context.get_caller()?;
|
||||
let signers = [&[new_program_id.as_ref(), &[bump_seed]]]
|
||||
.iter()
|
||||
|
@ -405,7 +419,7 @@ fn process_loader_upgradeable_instruction(
|
|||
InstructionProcessor::native_invoke(
|
||||
invoke_context,
|
||||
instruction,
|
||||
&[0, 1, 6],
|
||||
&[0, 1, 3, 6],
|
||||
signers.as_slice(),
|
||||
)?;
|
||||
|
||||
|
@ -434,11 +448,13 @@ fn process_loader_upgradeable_instruction(
|
|||
})?;
|
||||
program.try_account_ref_mut()?.set_executable(true);
|
||||
|
||||
// Drain the Buffer account back to the payer
|
||||
payer
|
||||
.try_account_ref_mut()?
|
||||
.checked_add_lamports(buffer.lamports()?)?;
|
||||
buffer.try_account_ref_mut()?.set_lamports(0);
|
||||
if !invoke_context.is_feature_active(&fix_write_privs::id()) {
|
||||
// Drain the Buffer account back to the payer
|
||||
payer
|
||||
.try_account_ref_mut()?
|
||||
.checked_add_lamports(buffer.lamports()?)?;
|
||||
buffer.try_account_ref_mut()?.set_lamports(0);
|
||||
}
|
||||
|
||||
ic_logger_msg!(logger, "Deployed program {:?}", new_program_id);
|
||||
}
|
||||
|
@ -987,6 +1003,7 @@ mod tests {
|
|||
instruction::{AccountMeta, InstructionError},
|
||||
keyed_account::KeyedAccount,
|
||||
message::Message,
|
||||
native_token::LAMPORTS_PER_SOL,
|
||||
process_instruction::{MockComputeMeter, MockInvokeContext},
|
||||
pubkey::Pubkey,
|
||||
rent::Rent,
|
||||
|
@ -1644,34 +1661,48 @@ mod tests {
|
|||
let bank = Arc::new(bank);
|
||||
let bank_client = BankClient::new_shared(&bank);
|
||||
|
||||
// Setup initial accounts
|
||||
// Setup keypairs and addresses
|
||||
let payer_keypair = Keypair::new();
|
||||
let program_keypair = Keypair::new();
|
||||
let buffer_address = Pubkey::new_unique();
|
||||
let (programdata_address, _) = Pubkey::find_program_address(
|
||||
&[program_keypair.pubkey().as_ref()],
|
||||
&bpf_loader_upgradeable::id(),
|
||||
);
|
||||
let upgrade_authority_keypair = Keypair::new();
|
||||
|
||||
// Load program file
|
||||
let mut file = File::open("test_elfs/noop_aligned.so").expect("file open failed");
|
||||
let mut elf = Vec::new();
|
||||
file.read_to_end(&mut elf).unwrap();
|
||||
|
||||
// Compute rent exempt balances
|
||||
let program_len = elf.len();
|
||||
let min_program_balance = bank
|
||||
.get_minimum_balance_for_rent_exemption(UpgradeableLoaderState::program_len().unwrap());
|
||||
let min_buffer_balance = bank.get_minimum_balance_for_rent_exemption(
|
||||
UpgradeableLoaderState::buffer_len(program_len).unwrap(),
|
||||
);
|
||||
let min_programdata_balance = bank.get_minimum_balance_for_rent_exemption(
|
||||
UpgradeableLoaderState::programdata_len(elf.len()).unwrap(),
|
||||
UpgradeableLoaderState::programdata_len(program_len).unwrap(),
|
||||
);
|
||||
let buffer_address = Pubkey::new_unique();
|
||||
let mut buffer_account = AccountSharedData::new(
|
||||
min_programdata_balance,
|
||||
UpgradeableLoaderState::buffer_len(elf.len()).unwrap(),
|
||||
&bpf_loader_upgradeable::id(),
|
||||
);
|
||||
buffer_account
|
||||
.set_state(&UpgradeableLoaderState::Buffer {
|
||||
authority_address: Some(upgrade_authority_keypair.pubkey()),
|
||||
})
|
||||
.unwrap();
|
||||
buffer_account.data_as_mut_slice()[UpgradeableLoaderState::buffer_data_offset().unwrap()..]
|
||||
.copy_from_slice(&elf);
|
||||
|
||||
// Setup accounts
|
||||
let buffer_account = {
|
||||
let mut account = AccountSharedData::new(
|
||||
min_buffer_balance,
|
||||
UpgradeableLoaderState::buffer_len(elf.len()).unwrap(),
|
||||
&bpf_loader_upgradeable::id(),
|
||||
);
|
||||
account
|
||||
.set_state(&UpgradeableLoaderState::Buffer {
|
||||
authority_address: Some(upgrade_authority_keypair.pubkey()),
|
||||
})
|
||||
.unwrap();
|
||||
account.data_as_mut_slice()[UpgradeableLoaderState::buffer_data_offset().unwrap()..]
|
||||
.copy_from_slice(&elf);
|
||||
account
|
||||
};
|
||||
let program_account = AccountSharedData::new(
|
||||
min_programdata_balance,
|
||||
UpgradeableLoaderState::program_len().unwrap(),
|
||||
|
@ -1684,14 +1715,27 @@ mod tests {
|
|||
);
|
||||
|
||||
// Test successful deploy
|
||||
bank.clear_signatures();
|
||||
let payer_base_balance = LAMPORTS_PER_SOL;
|
||||
let deploy_fees = {
|
||||
let fee_calculator = genesis_config.fee_rate_governor.create_fee_calculator();
|
||||
3 * fee_calculator.lamports_per_signature
|
||||
};
|
||||
let min_payer_balance =
|
||||
min_program_balance + min_programdata_balance - min_buffer_balance + deploy_fees;
|
||||
bank.store_account(
|
||||
&payer_keypair.pubkey(),
|
||||
&AccountSharedData::new(
|
||||
payer_base_balance + min_payer_balance,
|
||||
0,
|
||||
&system_program::id(),
|
||||
),
|
||||
);
|
||||
bank.store_account(&buffer_address, &buffer_account);
|
||||
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
|
||||
bank.store_account(&programdata_address, &AccountSharedData::default());
|
||||
let before = bank.get_balance(&mint_keypair.pubkey());
|
||||
let message = Message::new(
|
||||
&bpf_loader_upgradeable::deploy_with_max_program_len(
|
||||
&mint_keypair.pubkey(),
|
||||
&payer_keypair.pubkey(),
|
||||
&program_keypair.pubkey(),
|
||||
&buffer_address,
|
||||
&upgrade_authority_keypair.pubkey(),
|
||||
|
@ -1699,17 +1743,17 @@ mod tests {
|
|||
elf.len(),
|
||||
)
|
||||
.unwrap(),
|
||||
Some(&mint_keypair.pubkey()),
|
||||
Some(&payer_keypair.pubkey()),
|
||||
);
|
||||
assert!(bank_client
|
||||
.send_and_confirm_message(
|
||||
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
|
||||
&[&payer_keypair, &program_keypair, &upgrade_authority_keypair],
|
||||
message
|
||||
)
|
||||
.is_ok());
|
||||
assert_eq!(
|
||||
bank.get_balance(&mint_keypair.pubkey()),
|
||||
before - min_program_balance
|
||||
bank.get_balance(&payer_keypair.pubkey()),
|
||||
payer_base_balance
|
||||
);
|
||||
assert_eq!(bank.get_balance(&buffer_address), 0);
|
||||
assert_eq!(None, bank.get_account(&buffer_address));
|
||||
|
@ -1991,11 +2035,12 @@ mod tests {
|
|||
.unwrap()
|
||||
);
|
||||
|
||||
// Test Insufficient payer funds
|
||||
// Test Insufficient payer funds (need more funds to cover the
|
||||
// difference between buffer lamports and programdata lamports)
|
||||
bank.clear_signatures();
|
||||
bank.store_account(
|
||||
&mint_keypair.pubkey(),
|
||||
&AccountSharedData::new(min_program_balance, 0, &system_program::id()),
|
||||
&AccountSharedData::new(deploy_fees + min_program_balance, 0, &system_program::id()),
|
||||
);
|
||||
bank.store_account(&buffer_address, &buffer_account);
|
||||
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
|
||||
|
|
Loading…
Reference in New Issue