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

Token 22: Add functionality to update extra_account_metas after initializing. #5894

Merged
merged 40 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
e6bba4a
Added update function for ExtraAccountMetaList
tonton-sol Nov 26, 2023
fda5712
Updated interface to handle new update instruction
tonton-sol Nov 26, 2023
cf13287
Updated Cli to handle update command
tonton-sol Nov 26, 2023
84d8ac0
updated example program to handle updating
tonton-sol Nov 26, 2023
ca29fdc
Rust fmt trailing whitespace fix
tonton-sol Nov 27, 2023
2882a06
Removed unused variable
tonton-sol Nov 27, 2023
986e639
Added more explicit update instruction doc comment
tonton-sol Nov 27, 2023
3b177ce
Allow for resizing to smaller account size
tonton-sol Nov 28, 2023
5dc4a1a
Removed system program from update instruction
tonton-sol Nov 28, 2023
12c84cd
Added helper fn to calculate transfer lamports
tonton-sol Nov 28, 2023
155319d
Added unit tests for update function
tonton-sol Nov 28, 2023
2f3e041
Added unit test for update instruction
tonton-sol Nov 28, 2023
8b477d5
removed unnecessary commented out code
tonton-sol Nov 28, 2023
3a438b7
re-added checks on initialization
tonton-sol Nov 28, 2023
6334120
turned of zero_init for realloc for performance
tonton-sol Nov 28, 2023
b34c50c
Fixed update doc comments
tonton-sol Nov 29, 2023
2003517
Used block-scoping rather than explicit drop()
tonton-sol Nov 29, 2023
a69cfef
Removed unnecessary convert to vec
tonton-sol Nov 29, 2023
32d638b
refactored updated test into single test
tonton-sol Nov 29, 2023
93dfae6
added additional off-chain test of update instruct
tonton-sol Nov 29, 2023
666a36b
made on-chain invoke update test to match original
tonton-sol Nov 29, 2023
4262199
moved helper function up to others
tonton-sol Nov 29, 2023
54e77be
refactored create and update with helpers
tonton-sol Nov 29, 2023
de0e2f8
rustfmt: fix
tonton-sol Nov 30, 2023
f5b1a36
rustfmt: fix
tonton-sol Nov 30, 2023
f20c007
removed commented out system program in update
tonton-sol Nov 30, 2023
5e62a04
renamed helpers and removed unnecessary helper
tonton-sol Nov 30, 2023
1ba6c59
moved test helper up
tonton-sol Dec 1, 2023
9a22ce8
fixed test attribute location
tonton-sol Dec 1, 2023
9cf2129
removed multiple init extra account metas in test
tonton-sol Dec 1, 2023
4350929
added instruction assert to update test
tonton-sol Dec 1, 2023
a3e6c7e
renamed transfer address to extra account metas
tonton-sol Dec 2, 2023
58d7011
rustfmt: comment fix
tonton-sol Dec 3, 2023
451aaf4
clippy: fix
tonton-sol Dec 3, 2023
9fe5c86
added update test with simple PDA
tonton-sol Dec 3, 2023
a944952
made more changes to updated metas in test
tonton-sol Dec 3, 2023
ce76bf9
added check for if extra metas have be initialized
tonton-sol Dec 3, 2023
b8299b3
Merge branch 'master' into master
tonton-sol Dec 5, 2023
20d9185
spelling fix
tonton-sol Dec 7, 2023
9a508de
fixed initialized condition
tonton-sol Dec 7, 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
134 changes: 134 additions & 0 deletions libraries/tlv-account-resolution/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,22 @@ impl ExtraAccountMetaList {
Ok(())
}

/// Update pod slice data for the given instruction and its required
/// list of `ExtraAccountMeta`s
pub fn update<T: SplDiscriminate>(
data: &mut [u8],
extra_account_metas: &[ExtraAccountMeta],
) -> Result<(), ProgramError> {
let mut state = TlvStateMut::unpack(data).unwrap();
let tlv_size = PodSlice::<ExtraAccountMeta>::size_of(extra_account_metas.len())?;
let bytes = state.realloc_first::<T>(tlv_size)?;
let mut validation_data = PodSliceMut::init(bytes)?;
for meta in extra_account_metas {
validation_data.push(*meta)?;
}
tonton-sol marked this conversation as resolved.
Show resolved Hide resolved
Ok(())
}

/// Get the underlying `PodSlice<ExtraAccountMeta>` from an unpacked TLV
///
/// Due to lifetime annoyances, this function can't just take in the bytes,
Expand Down Expand Up @@ -1292,6 +1308,124 @@ mod tests {
}
}

async fn update_and_assert_metas(
program_id: Pubkey,
buffer: &mut Vec<u8>,
updated_metas: &[ExtraAccountMeta],
check_metas: &[AccountMeta],
) {
// resize buffer if necessary
let account_size = ExtraAccountMetaList::size_of(updated_metas.len()).unwrap();
if account_size > buffer.len() {
buffer.resize(account_size, 0);
}

// update
ExtraAccountMetaList::update::<TestInstruction>(buffer, updated_metas).unwrap();

// retrieve metas and assert
let state = TlvStateBorrowed::unpack(buffer).unwrap();
let unpacked_metas_pod =
ExtraAccountMetaList::unpack_with_tlv_state::<TestInstruction>(&state).unwrap();
let unpacked_metas = unpacked_metas_pod.data();
assert_eq!(
unpacked_metas, updated_metas,
"The ExtraAccountMetas in the buffer should match the expected ones."
);

let mock_rpc = MockRpc::setup(&[]);

let mut instruction = Instruction::new_with_bytes(program_id, &[], vec![]);
ExtraAccountMetaList::add_to_instruction::<TestInstruction, _, _>(
&mut instruction,
|pubkey| mock_rpc.get_account_data(pubkey),
buffer,
)
.await
.unwrap();

assert_eq!(instruction.accounts, check_metas,);
}

#[tokio::test]
async fn update_extra_account_meta_list() {
let program_id = Pubkey::new_unique();

// Create list of initial metas
let initial_metas = [
ExtraAccountMeta::new_with_pubkey(&Pubkey::new_unique(), false, true).unwrap(),
ExtraAccountMeta::new_with_pubkey(&Pubkey::new_unique(), true, false).unwrap(),
];

// initialize
let initial_account_size = ExtraAccountMetaList::size_of(initial_metas.len()).unwrap();
let mut buffer = vec![0; initial_account_size];
ExtraAccountMetaList::init::<TestInstruction>(&mut buffer, &initial_metas).unwrap();

// Create updated metas list of the same size
let updated_metas_1 = [
ExtraAccountMeta::new_with_pubkey(&Pubkey::new_unique(), true, true).unwrap(),
ExtraAccountMeta::new_with_pubkey(&Pubkey::new_unique(), false, false).unwrap(),
];
let check_metas_1 = updated_metas_1
.iter()
.map(|e| AccountMeta::try_from(e).unwrap())
.collect::<Vec<_>>();
update_and_assert_metas(program_id, &mut buffer, &updated_metas_1, &check_metas_1).await;

// Create updated and larger list of metas
let updated_metas_2 = [
ExtraAccountMeta::new_with_pubkey(&Pubkey::new_unique(), true, true).unwrap(),
ExtraAccountMeta::new_with_pubkey(&Pubkey::new_unique(), false, false).unwrap(),
ExtraAccountMeta::new_with_pubkey(&Pubkey::new_unique(), false, true).unwrap(),
];
let check_metas_2 = updated_metas_2
.iter()
.map(|e| AccountMeta::try_from(e).unwrap())
.collect::<Vec<_>>();
update_and_assert_metas(program_id, &mut buffer, &updated_metas_2, &check_metas_2).await;

// Create updated and smaller list of metas
let updated_metas_3 =
[ExtraAccountMeta::new_with_pubkey(&Pubkey::new_unique(), true, true).unwrap()];
let check_metas_3 = updated_metas_3
.iter()
.map(|e| AccountMeta::try_from(e).unwrap())
.collect::<Vec<_>>();
update_and_assert_metas(program_id, &mut buffer, &updated_metas_3, &check_metas_3).await;

// Create updated list of metas with a simple PDA
let seed_pubkey = Pubkey::new_unique();
let updated_metas_4 = [
ExtraAccountMeta::new_with_pubkey(&seed_pubkey, true, true).unwrap(),
ExtraAccountMeta::new_with_seeds(
&[
Seed::Literal {
bytes: b"seed-prefix".to_vec(),
},
Seed::AccountKey { index: 0 },
],
false,
true,
)
.unwrap(),
];
let simple_pda = Pubkey::find_program_address(
&[
b"seed-prefix", // Literal prefix
seed_pubkey.as_ref(), // Account at index 0
],
&program_id,
)
.0;
let check_metas_4 = [
AccountMeta::new(seed_pubkey, true),
AccountMeta::new(simple_pda, false),
];

update_and_assert_metas(program_id, &mut buffer, &updated_metas_4, &check_metas_4).await;
}

#[test]
fn check_account_infos_test() {
let program_id = Pubkey::new_unique();
Expand Down
Loading