Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Bank: Add function to replace empty account with upgradeable program on feature activation #32783

Merged
merged 33 commits into from
Oct 4, 2023
Merged
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
4ab4bf1
replace program account
buffalojoec Aug 9, 2023
fb1d4c9
modify for all cases
buffalojoec Aug 16, 2023
99eb96e
remove non-data swap
buffalojoec Aug 17, 2023
acbca38
address tests & conditional feedback
buffalojoec Aug 18, 2023
a8800b8
get the rent involved
buffalojoec Aug 18, 2023
86833f9
mix in owner & executable
buffalojoec Aug 18, 2023
637dd83
feature-related cases
buffalojoec Aug 18, 2023
e6bfb43
stripped back to feature-specific case only
buffalojoec Aug 18, 2023
24e75d5
added feature
buffalojoec Aug 18, 2023
a573a97
address initial feedback
buffalojoec Aug 21, 2023
c221038
added more lamport checks
buffalojoec Aug 21, 2023
b36f56a
condense tests
buffalojoec Aug 21, 2023
9a61900
using test_case
buffalojoec Aug 21, 2023
67986b4
add fail cases to tests
buffalojoec Aug 21, 2023
453dc8a
more cleanup
buffalojoec Aug 22, 2023
7d3f877
add verifiably built program
buffalojoec Aug 22, 2023
a6dd68e
update program account state
buffalojoec Aug 22, 2023
59a4132
cleaned up serializing logic
buffalojoec Aug 23, 2023
acfa993
use full word capitalization
buffalojoec Sep 15, 2023
6ef8353
rename old & new to dst & src
buffalojoec Sep 15, 2023
069dd53
swap src and dst in parameters
buffalojoec Sep 15, 2023
f044890
add warnings and errors
buffalojoec Sep 15, 2023
1e7b4e5
rename feature to programify
buffalojoec Sep 20, 2023
251b9a9
test suite description clarity
buffalojoec Sep 20, 2023
1b37cdc
remove strings from datapoints
buffalojoec Sep 20, 2023
5b280fd
spell out source and destination
buffalojoec Sep 29, 2023
6ccf0f1
more verbose comments in account replace functions
buffalojoec Sep 29, 2023
0392ad8
move lamport calculation
buffalojoec Sep 29, 2023
41c9c40
swap lamport check for state check
buffalojoec Sep 29, 2023
5cadf5b
move replace functions to helper module
buffalojoec Sep 29, 2023
3e7dc30
make replace_account methods fallible
buffalojoec Oct 3, 2023
19b35de
refactor error handling
buffalojoec Oct 4, 2023
91bfec7
add test for source program state
buffalojoec Oct 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add fail cases to tests
  • Loading branch information
buffalojoec committed Oct 4, 2023
commit 67986b48f3669169f9bd4ce61f62adc048c86545
93 changes: 93 additions & 0 deletions runtime/src/bank/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8136,7 +8136,10 @@ fn test_replace_empty_account_success(

// Derive the well-known PDA address for the old data account
let (old_data, _) = Pubkey::find_program_address(&[old.as_ref()], &bpf_upgradeable_id);

// Determine the lamports that will be burnt after the replacement
let burnt_after_rent = if let Some(old_data_bytes) = maybe_old_data_bytes {
// Create the data account if necessary
let old_data_lamports = bank.get_minimum_balance_for_rent_exemption(old_data_bytes.len());
test_program_replace_set_up_account(
&mut bank,
Expand Down Expand Up @@ -8199,6 +8202,96 @@ fn test_replace_empty_account_success(
);
}

#[test_case(
None;
"Existing account _without_ corresponding data account"
)]
#[test_case(
Some(vec![4; 40]);
"Existing account _with_ corresponding data account"
)]
fn test_replace_empty_account_fail_when_account_exists(
maybe_old_data_bytes: Option<Vec<u8>>, // Inner data of the old program _data_ account
) {
// Should not be allowed to execute replacement
let bpf_upgradeable_id = bpf_loader_upgradeable::id();
let mut bank = create_simple_test_bank(0);

// Create the test old account with some arbitrary data and lamports balance
let old = Pubkey::new_unique();
let old_bytes = vec![0, 0, 0, 0]; // Arbitrary bytes, doesn't matter
let old_lamports = bank.get_minimum_balance_for_rent_exemption(old_bytes.len());
let old_account = test_program_replace_set_up_account(
&mut bank,
&old,
old_lamports,
old_bytes,
&bpf_upgradeable_id,
true,
);

// Create the test new accounts, one for program and one for data
let new = Pubkey::new_unique();
let (new_data, _) = Pubkey::find_program_address(&[new.as_ref()], &bpf_upgradeable_id);
let new_bytes = new_data.to_bytes().to_vec();
let new_lamports = bank.get_minimum_balance_for_rent_exemption(new_bytes.len());
let new_data_bytes = vec![6; 30];
let new_data_lamports = bank.get_minimum_balance_for_rent_exemption(new_data_bytes.len());
let new_account = test_program_replace_set_up_account(
&mut bank,
&new,
new_lamports,
new_bytes,
&bpf_upgradeable_id,
true,
);
let new_data_account = test_program_replace_set_up_account(
&mut bank,
&new_data,
new_data_lamports,
new_data_bytes,
&bpf_upgradeable_id,
false,
);

// Derive the well-known PDA address for the old data account
let (old_data, _) = Pubkey::find_program_address(&[old.as_ref()], &bpf_upgradeable_id);

// Create the data account if necessary
let old_data_account = if let Some(old_data_bytes) = maybe_old_data_bytes {
let old_data_lamports = bank.get_minimum_balance_for_rent_exemption(old_data_bytes.len());
let old_data_account = test_program_replace_set_up_account(
&mut bank,
&old_data,
old_data_lamports,
old_data_bytes,
&bpf_upgradeable_id,
false,
);
Some(old_data_account)
} else {
None
};

let original_capitalization = bank.capitalization();

// Attempt the replacement
bank.replace_empty_account_with_upgradeable_program(
&old,
&new,
"bank-apply_empty_account_replacement_for_program",
);

// Everything should be unchanged
assert_eq!(bank.get_account(&old).unwrap(), old_account);
if let Some(old_data_account) = old_data_account {
assert_eq!(bank.get_account(&old_data).unwrap(), old_data_account);
}
assert_eq!(bank.get_account(&new).unwrap(), new_account);
assert_eq!(bank.get_account(&new_data).unwrap(), new_data_account);
assert_eq!(bank.capitalization(), original_capitalization);
}

fn min_rent_exempt_balance_for_sysvars(bank: &Bank, sysvar_ids: &[Pubkey]) -> u64 {
sysvar_ids
.iter()
Expand Down