From fbc65f387249bfaf53286737f647c19eccbde097 Mon Sep 17 00:00:00 2001 From: Joe C Date: Thu, 10 Aug 2023 17:00:50 -0600 Subject: [PATCH] condense TLV AR state to one init (#4988) * condense TLV AR state to one init * dropped unnecessary to_vec --- libraries/tlv-account-resolution/README.md | 10 +- .../tlv-account-resolution/src/account.rs | 12 +- libraries/tlv-account-resolution/src/error.rs | 3 +- libraries/tlv-account-resolution/src/state.rs | 147 +++++------------- .../program-2022-test/tests/transfer_hook.rs | 20 ++- token/transfer-hook-example/src/processor.rs | 9 +- token/transfer-hook-example/src/state.rs | 8 +- 7 files changed, 80 insertions(+), 129 deletions(-) diff --git a/libraries/tlv-account-resolution/README.md b/libraries/tlv-account-resolution/README.md index 164fd803549..1c425a5a6f4 100644 --- a/libraries/tlv-account-resolution/README.md +++ b/libraries/tlv-account-resolution/README.md @@ -23,10 +23,10 @@ impl SplDiscriminate for MyInstruction { // Actually put it in the additional required account keys and signer / writable let extra_metas = [ - AccountMeta::new(Pubkey::new_unique(), false), - AccountMeta::new(Pubkey::new_unique(), true), - AccountMeta::new_readonly(Pubkey::new_unique(), true), - AccountMeta::new_readonly(Pubkey::new_unique(), false), + AccountMeta::new(Pubkey::new_unique(), false).into(), + AccountMeta::new(Pubkey::new_unique(), true).into(), + AccountMeta::new_readonly(Pubkey::new_unique(), true).into(), + AccountMeta::new_readonly(Pubkey::new_unique(), false).into(), ]; // Assume that this buffer is actually account data, already allocated to `account_size` @@ -34,7 +34,7 @@ let account_size = ExtraAccountMetaList::size_of(extra_metas.len()).unwrap(); let mut buffer = vec![0; account_size]; // Initialize the structure for your instruction -ExtraAccountMetaList::init_with_account_metas::(&mut buffer, &extra_metas).unwrap(); +ExtraAccountMetaList::init::(&mut buffer, &extra_metas).unwrap(); // Off-chain, you can add the additional accounts directly from the account data let program_id = Pubkey::new_unique(); diff --git a/libraries/tlv-account-resolution/src/account.rs b/libraries/tlv-account-resolution/src/account.rs index 76fbb310cd6..107ffdf9f2d 100644 --- a/libraries/tlv-account-resolution/src/account.rs +++ b/libraries/tlv-account-resolution/src/account.rs @@ -136,7 +136,6 @@ impl ExtraAccountMeta { } } -// Conversions to `ExtraAccountMeta` impl From<&AccountMeta> for ExtraAccountMeta { fn from(meta: &AccountMeta) -> Self { Self { @@ -147,6 +146,11 @@ impl From<&AccountMeta> for ExtraAccountMeta { } } } +impl From for ExtraAccountMeta { + fn from(meta: AccountMeta) -> Self { + ExtraAccountMeta::from(&meta) + } +} impl From<&AccountInfo<'_>> for ExtraAccountMeta { fn from(account_info: &AccountInfo) -> Self { Self { @@ -157,8 +161,12 @@ impl From<&AccountInfo<'_>> for ExtraAccountMeta { } } } +impl From> for ExtraAccountMeta { + fn from(account_info: AccountInfo) -> Self { + ExtraAccountMeta::from(&account_info) + } +} -// Conversions from `ExtraAccountMeta` impl TryFrom<&ExtraAccountMeta> for AccountMeta { type Error = ProgramError; diff --git a/libraries/tlv-account-resolution/src/error.rs b/libraries/tlv-account-resolution/src/error.rs index 9e160703b70..e2ea5032a35 100644 --- a/libraries/tlv-account-resolution/src/error.rs +++ b/libraries/tlv-account-resolution/src/error.rs @@ -26,7 +26,8 @@ pub enum AccountResolutionError { /// Attempted to deserialize an `AccountMeta` but the underlying type has /// PDA configs rather than a fixed address #[error( - "Attempted to deserialize an `AccountMeta` but the underlying type has PDA configs rather than a fixed address" + "Attempted to deserialize an `AccountMeta` but the underlying type has PDA configs rather \ + than a fixed address" )] AccountTypeNotAccountMeta, /// Provided list of seed configurations too large for a validation account diff --git a/libraries/tlv-account-resolution/src/state.rs b/libraries/tlv-account-resolution/src/state.rs index 54e67ef87af..a837e874f76 100644 --- a/libraries/tlv-account-resolution/src/state.rs +++ b/libraries/tlv-account-resolution/src/state.rs @@ -3,9 +3,7 @@ use { crate::{account::ExtraAccountMeta, error::AccountResolutionError}, solana_program::{ - account_info::AccountInfo, - instruction::{AccountMeta, Instruction}, - program_error::ProgramError, + account_info::AccountInfo, instruction::Instruction, program_error::ProgramError, }, spl_discriminator::SplDiscriminate, spl_type_length_value::{ @@ -42,10 +40,10 @@ use { /// /// // actually put it in the additional required account keys and signer / writable /// let extra_metas = [ -/// AccountMeta::new(Pubkey::new_unique(), false), -/// AccountMeta::new(Pubkey::new_unique(), true), -/// AccountMeta::new_readonly(Pubkey::new_unique(), true), -/// AccountMeta::new_readonly(Pubkey::new_unique(), false), +/// AccountMeta::new(Pubkey::new_unique(), false).into(), +/// AccountMeta::new(Pubkey::new_unique(), true).into(), +/// AccountMeta::new_readonly(Pubkey::new_unique(), true).into(), +/// AccountMeta::new_readonly(Pubkey::new_unique(), false).into(), /// ]; /// /// // assume that this buffer is actually account data, already allocated to `account_size` @@ -53,7 +51,7 @@ use { /// let mut buffer = vec![0; account_size]; /// /// // Initialize the structure for your instruction -/// ExtraAccountMetaList::init_with_account_metas::(&mut buffer, &extra_metas).unwrap(); +/// ExtraAccountMetaList::init::(&mut buffer, &extra_metas).unwrap(); /// /// // Off-chain, you can add the additional accounts directly from the account data /// let program_id = Pubkey::new_unique(); @@ -73,60 +71,22 @@ use { /// ``` pub struct ExtraAccountMetaList; impl ExtraAccountMetaList { - /// Initialize pod slice data for the given instruction and any type - /// convertible to account metas - fn init<'a, T: SplDiscriminate, F, M>( + /// Initialize pod slice data for the given instruction and its required + /// list of `ExtraAccountMeta`s + pub fn init( data: &mut [u8], - convertible_account_metas: &'a [M], - conversion_fn: F, - ) -> Result<(), ProgramError> - where - F: Fn(&'a M) -> ExtraAccountMeta, - { + extra_account_metas: &[ExtraAccountMeta], + ) -> Result<(), ProgramError> { let mut state = TlvStateMut::unpack(data).unwrap(); - let tlv_size = PodSlice::::size_of(convertible_account_metas.len())?; + let tlv_size = PodSlice::::size_of(extra_account_metas.len())?; let (bytes, _) = state.alloc::(tlv_size, false)?; - let mut extra_account_metas = PodSliceMut::init(bytes)?; - for account_meta in convertible_account_metas { - extra_account_metas.push(conversion_fn(account_meta))?; + let mut validation_data = PodSliceMut::init(bytes)?; + for meta in extra_account_metas { + validation_data.push(*meta)?; } Ok(()) } - /// Initialize a TLV entry for the given discriminator, populating the data - /// with the given account infos - pub fn init_with_account_infos( - data: &mut [u8], - account_infos: &[AccountInfo<'_>], - ) -> Result<(), ProgramError> { - Self::init::(data, account_infos, |account_info| { - ExtraAccountMeta::from(account_info) - }) - } - - /// Initialize a TLV entry for the given discriminator, populating the data - /// with the given account metas - pub fn init_with_account_metas( - data: &mut [u8], - account_metas: &[AccountMeta], - ) -> Result<(), ProgramError> { - Self::init::(data, account_metas, |account_meta| { - ExtraAccountMeta::from(account_meta) - }) - } - - /// Initialize a TLV entry for the given discriminator, populating the data - /// with the given required accounts - which can be standard `AccountMeta`s - /// or PDAs - pub fn init_with_pod_account_metas( - data: &mut [u8], - pod_account_metas: &[ExtraAccountMeta], - ) -> Result<(), ProgramError> { - Self::init::(data, pod_account_metas, |pod_account_meta| { - *pod_account_meta - }) - } - /// Get the underlying `PodSlice` from an unpacked TLV /// /// Due to lifetime annoyances, this function can't just take in the bytes, @@ -211,16 +171,15 @@ mod tests { #[test] fn init_with_metas() { let metas = [ - AccountMeta::new(Pubkey::new_unique(), false), - AccountMeta::new(Pubkey::new_unique(), true), - AccountMeta::new_readonly(Pubkey::new_unique(), true), - AccountMeta::new_readonly(Pubkey::new_unique(), false), + AccountMeta::new(Pubkey::new_unique(), false).into(), + AccountMeta::new(Pubkey::new_unique(), true).into(), + AccountMeta::new_readonly(Pubkey::new_unique(), true).into(), + AccountMeta::new_readonly(Pubkey::new_unique(), false).into(), ]; let account_size = ExtraAccountMetaList::size_of(metas.len()).unwrap(); let mut buffer = vec![0; account_size]; - ExtraAccountMetaList::init_with_account_metas::(&mut buffer, &metas) - .unwrap(); + ExtraAccountMetaList::init::(&mut buffer, &metas).unwrap(); let mut instruction = Instruction::new_with_bytes(Pubkey::new_unique(), &[], vec![]); ExtraAccountMetaList::add_to_instruction::(&mut instruction, &buffer) @@ -232,7 +191,7 @@ mod tests { .iter() .map(ExtraAccountMeta::from) .collect::>(), - metas.iter().map(ExtraAccountMeta::from).collect::>() + metas ); } @@ -258,7 +217,8 @@ mod tests { &owner, false, Epoch::default(), - ), + ) + .into(), AccountInfo::new( &pubkey2, true, @@ -268,7 +228,8 @@ mod tests { &owner, false, Epoch::default(), - ), + ) + .into(), AccountInfo::new( &pubkey3, false, @@ -278,16 +239,13 @@ mod tests { &owner, false, Epoch::default(), - ), + ) + .into(), ]; let account_size = ExtraAccountMetaList::size_of(account_infos.len()).unwrap(); let mut buffer = vec![0; account_size]; - ExtraAccountMetaList::init_with_account_infos::( - &mut buffer, - &account_infos, - ) - .unwrap(); + ExtraAccountMetaList::init::(&mut buffer, &account_infos).unwrap(); let mut instruction = Instruction::new_with_bytes(Pubkey::new_unique(), &[], vec![]); ExtraAccountMetaList::add_to_instruction::(&mut instruction, &buffer) @@ -300,14 +258,11 @@ mod tests { .map(ExtraAccountMeta::from) .collect::>(), account_infos - .iter() - .map(ExtraAccountMeta::from) - .collect::>() ); } #[test] - fn init_with_pod_account_metas() { + fn init_with_extra_account_metas() { let program_id = Pubkey::new_unique(); let extra_meta3_literal_str = "seed_prefix"; @@ -347,10 +302,7 @@ mod tests { let account_size = ExtraAccountMetaList::size_of(metas.len()).unwrap(); let mut buffer = vec![0; account_size]; - // Notice we use `init_with_required_accounts` instead of - // `init_with_account_metas` - ExtraAccountMetaList::init_with_pod_account_metas::(&mut buffer, &metas) - .unwrap(); + ExtraAccountMetaList::init::(&mut buffer, &metas).unwrap(); ExtraAccountMetaList::add_to_instruction::(&mut instruction, &buffer) .unwrap(); @@ -450,13 +402,8 @@ mod tests { + ExtraAccountMetaList::size_of(other_metas.len()).unwrap(); let mut buffer = vec![0; account_size]; - ExtraAccountMetaList::init_with_pod_account_metas::(&mut buffer, &metas) - .unwrap(); - ExtraAccountMetaList::init_with_pod_account_metas::( - &mut buffer, - &other_metas, - ) - .unwrap(); + ExtraAccountMetaList::init::(&mut buffer, &metas).unwrap(); + ExtraAccountMetaList::init::(&mut buffer, &other_metas).unwrap(); let program_id = Pubkey::new_unique(); let ix_data = vec![0, 0, 0, 0, 0, 7, 0, 0]; @@ -568,7 +515,8 @@ mod tests { &owner, false, Epoch::default(), - ), + ) + .into(), AccountInfo::new( &pubkey2, true, @@ -578,7 +526,8 @@ mod tests { &owner, false, Epoch::default(), - ), + ) + .into(), AccountInfo::new( &pubkey3, false, @@ -588,7 +537,8 @@ mod tests { &owner, false, Epoch::default(), - ), + ) + .into(), ]; let extra_meta1 = AccountMeta::new(Pubkey::new_unique(), false); @@ -640,16 +590,8 @@ mod tests { + ExtraAccountMetaList::size_of(metas.len()).unwrap(); let mut buffer = vec![0; account_size]; - ExtraAccountMetaList::init_with_account_infos::( - &mut buffer, - &account_infos, - ) - .unwrap(); - ExtraAccountMetaList::init_with_pod_account_metas::( - &mut buffer, - &metas, - ) - .unwrap(); + ExtraAccountMetaList::init::(&mut buffer, &account_infos).unwrap(); + ExtraAccountMetaList::init::(&mut buffer, &metas).unwrap(); let program_id = Pubkey::new_unique(); let mut instruction = Instruction::new_with_bytes(program_id, &[], vec![]); @@ -662,9 +604,6 @@ mod tests { .map(ExtraAccountMeta::from) .collect::>(), account_infos - .iter() - .map(ExtraAccountMeta::from) - .collect::>() ); let program_id = Pubkey::new_unique(); @@ -872,11 +811,7 @@ mod tests { let account_size = ExtraAccountMetaList::size_of(required_accounts.len()).unwrap(); let mut buffer = vec![0; account_size]; - ExtraAccountMetaList::init_with_pod_account_metas::( - &mut buffer, - &required_accounts, - ) - .unwrap(); + ExtraAccountMetaList::init::(&mut buffer, &required_accounts).unwrap(); // Make an instruction to check later // We'll also check the instruction seed components later diff --git a/token/program-2022-test/tests/transfer_hook.rs b/token/program-2022-test/tests/transfer_hook.rs index 97c4c117b3b..0506ca1553e 100644 --- a/token/program-2022-test/tests/transfer_hook.rs +++ b/token/program-2022-test/tests/transfer_hook.rs @@ -176,23 +176,25 @@ fn setup_program_test(program_id: &Pubkey) -> ProgramTest { fn add_validation_account(program_test: &mut ProgramTest, mint: &Pubkey, program_id: &Pubkey) { let validation_address = get_extra_account_metas_address(mint, program_id); - let account_metas = vec![ + let extra_account_metas = vec![ AccountMeta { pubkey: Pubkey::new_unique(), is_signer: false, is_writable: false, - }, + } + .into(), AccountMeta { pubkey: Pubkey::new_unique(), is_signer: false, is_writable: false, - }, + } + .into(), ]; program_test.add_account( validation_address, Account { lamports: 1_000_000_000, // a lot, just to be safe - data: spl_transfer_hook_example::state::example_data(&account_metas).unwrap(), + data: spl_transfer_hook_example::state::example_data(&extra_account_metas).unwrap(), owner: *program_id, ..Account::default() }, @@ -565,23 +567,25 @@ async fn success_downgrade_writable_and_signer_accounts() { let alice = Keypair::new(); let alice_account = Keypair::new(); let validation_address = get_extra_account_metas_address(&mint.pubkey(), &program_id); - let account_metas = vec![ + let extra_account_metas = vec![ AccountMeta { pubkey: alice_account.pubkey(), is_signer: false, is_writable: true, - }, + } + .into(), AccountMeta { pubkey: alice.pubkey(), is_signer: true, is_writable: false, - }, + } + .into(), ]; program_test.add_account( validation_address, Account { lamports: 1_000_000_000, // a lot, just to be safe - data: spl_transfer_hook_example::state::example_data(&account_metas).unwrap(), + data: spl_transfer_hook_example::state::example_data(&extra_account_metas).unwrap(), owner: program_id, ..Account::default() }, diff --git a/token/transfer-hook-example/src/processor.rs b/token/transfer-hook-example/src/processor.rs index ba4fbe8ddc9..5fff669c7cd 100644 --- a/token/transfer-hook-example/src/processor.rs +++ b/token/transfer-hook-example/src/processor.rs @@ -11,7 +11,7 @@ use { pubkey::Pubkey, system_instruction, }, - spl_tlv_account_resolution::state::ExtraAccountMetaList, + spl_tlv_account_resolution::{account::ExtraAccountMeta, state::ExtraAccountMetaList}, spl_token_2022::{ extension::{ transfer_hook::TransferHookAccount, BaseStateWithExtensions, StateWithExtensions, @@ -143,9 +143,12 @@ pub fn process_initialize_extra_account_metas( // Write the data let mut data = extra_account_metas_info.try_borrow_mut_data()?; - ExtraAccountMetaList::init_with_account_infos::( + ExtraAccountMetaList::init::( &mut data, - extra_account_infos, + &extra_account_infos + .iter() + .map(ExtraAccountMeta::from) + .collect::>(), )?; Ok(()) diff --git a/token/transfer-hook-example/src/state.rs b/token/transfer-hook-example/src/state.rs index 03be3535fad..b2c962c5072 100644 --- a/token/transfer-hook-example/src/state.rs +++ b/token/transfer-hook-example/src/state.rs @@ -1,15 +1,15 @@ //! State helpers for working with the example program use { - solana_program::{instruction::AccountMeta, program_error::ProgramError}, - spl_tlv_account_resolution::state::ExtraAccountMetaList, + solana_program::program_error::ProgramError, + spl_tlv_account_resolution::{account::ExtraAccountMeta, state::ExtraAccountMetaList}, spl_transfer_hook_interface::instruction::ExecuteInstruction, }; /// Generate example data to be used directly in an account for testing -pub fn example_data(account_metas: &[AccountMeta]) -> Result, ProgramError> { +pub fn example_data(account_metas: &[ExtraAccountMeta]) -> Result, ProgramError> { let account_size = ExtraAccountMetaList::size_of(account_metas.len())?; let mut data = vec![0; account_size]; - ExtraAccountMetaList::init_with_account_metas::(&mut data, account_metas)?; + ExtraAccountMetaList::init::(&mut data, account_metas)?; Ok(data) }