Skip to content

Commit

Permalink
condense TLV AR state to one init (#4988)
Browse files Browse the repository at this point in the history
* condense TLV AR state to one init

* dropped unnecessary to_vec
  • Loading branch information
buffalojoec authored Aug 10, 2023
1 parent 1f74d12 commit fbc65f3
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 129 deletions.
10 changes: 5 additions & 5 deletions libraries/tlv-account-resolution/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ 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`
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::<MyInstruction>(&mut buffer, &extra_metas).unwrap();
ExtraAccountMetaList::init::<MyInstruction>(&mut buffer, &extra_metas).unwrap();

// Off-chain, you can add the additional accounts directly from the account data
let program_id = Pubkey::new_unique();
Expand Down
12 changes: 10 additions & 2 deletions libraries/tlv-account-resolution/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ impl ExtraAccountMeta {
}
}

// Conversions to `ExtraAccountMeta`
impl From<&AccountMeta> for ExtraAccountMeta {
fn from(meta: &AccountMeta) -> Self {
Self {
Expand All @@ -147,6 +146,11 @@ impl From<&AccountMeta> for ExtraAccountMeta {
}
}
}
impl From<AccountMeta> for ExtraAccountMeta {
fn from(meta: AccountMeta) -> Self {
ExtraAccountMeta::from(&meta)
}
}
impl From<&AccountInfo<'_>> for ExtraAccountMeta {
fn from(account_info: &AccountInfo) -> Self {
Self {
Expand All @@ -157,8 +161,12 @@ impl From<&AccountInfo<'_>> for ExtraAccountMeta {
}
}
}
impl From<AccountInfo<'_>> for ExtraAccountMeta {
fn from(account_info: AccountInfo) -> Self {
ExtraAccountMeta::from(&account_info)
}
}

// Conversions from `ExtraAccountMeta`
impl TryFrom<&ExtraAccountMeta> for AccountMeta {
type Error = ProgramError;

Expand Down
3 changes: 2 additions & 1 deletion libraries/tlv-account-resolution/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
147 changes: 41 additions & 106 deletions libraries/tlv-account-resolution/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -42,18 +40,18 @@ 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`
/// 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::<MyInstruction>(&mut buffer, &extra_metas).unwrap();
/// ExtraAccountMetaList::init::<MyInstruction>(&mut buffer, &extra_metas).unwrap();
///
/// // Off-chain, you can add the additional accounts directly from the account data
/// let program_id = Pubkey::new_unique();
Expand All @@ -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<T: SplDiscriminate>(
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::<ExtraAccountMeta>::size_of(convertible_account_metas.len())?;
let tlv_size = PodSlice::<ExtraAccountMeta>::size_of(extra_account_metas.len())?;
let (bytes, _) = state.alloc::<T>(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<T: SplDiscriminate>(
data: &mut [u8],
account_infos: &[AccountInfo<'_>],
) -> Result<(), ProgramError> {
Self::init::<T, _, AccountInfo>(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<T: SplDiscriminate>(
data: &mut [u8],
account_metas: &[AccountMeta],
) -> Result<(), ProgramError> {
Self::init::<T, _, AccountMeta>(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<T: SplDiscriminate>(
data: &mut [u8],
pod_account_metas: &[ExtraAccountMeta],
) -> Result<(), ProgramError> {
Self::init::<T, _, ExtraAccountMeta>(data, pod_account_metas, |pod_account_meta| {
*pod_account_meta
})
}

/// 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 @@ -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::<TestInstruction>(&mut buffer, &metas)
.unwrap();
ExtraAccountMetaList::init::<TestInstruction>(&mut buffer, &metas).unwrap();

let mut instruction = Instruction::new_with_bytes(Pubkey::new_unique(), &[], vec![]);
ExtraAccountMetaList::add_to_instruction::<TestInstruction>(&mut instruction, &buffer)
Expand All @@ -232,7 +191,7 @@ mod tests {
.iter()
.map(ExtraAccountMeta::from)
.collect::<Vec<_>>(),
metas.iter().map(ExtraAccountMeta::from).collect::<Vec<_>>()
metas
);
}

Expand All @@ -258,7 +217,8 @@ mod tests {
&owner,
false,
Epoch::default(),
),
)
.into(),
AccountInfo::new(
&pubkey2,
true,
Expand All @@ -268,7 +228,8 @@ mod tests {
&owner,
false,
Epoch::default(),
),
)
.into(),
AccountInfo::new(
&pubkey3,
false,
Expand All @@ -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::<TestInstruction>(
&mut buffer,
&account_infos,
)
.unwrap();
ExtraAccountMetaList::init::<TestInstruction>(&mut buffer, &account_infos).unwrap();

let mut instruction = Instruction::new_with_bytes(Pubkey::new_unique(), &[], vec![]);
ExtraAccountMetaList::add_to_instruction::<TestInstruction>(&mut instruction, &buffer)
Expand All @@ -300,14 +258,11 @@ mod tests {
.map(ExtraAccountMeta::from)
.collect::<Vec<_>>(),
account_infos
.iter()
.map(ExtraAccountMeta::from)
.collect::<Vec<_>>()
);
}

#[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";
Expand Down Expand Up @@ -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::<TestInstruction>(&mut buffer, &metas)
.unwrap();
ExtraAccountMetaList::init::<TestInstruction>(&mut buffer, &metas).unwrap();

ExtraAccountMetaList::add_to_instruction::<TestInstruction>(&mut instruction, &buffer)
.unwrap();
Expand Down Expand Up @@ -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::<TestInstruction>(&mut buffer, &metas)
.unwrap();
ExtraAccountMetaList::init_with_pod_account_metas::<TestOtherInstruction>(
&mut buffer,
&other_metas,
)
.unwrap();
ExtraAccountMetaList::init::<TestInstruction>(&mut buffer, &metas).unwrap();
ExtraAccountMetaList::init::<TestOtherInstruction>(&mut buffer, &other_metas).unwrap();

let program_id = Pubkey::new_unique();
let ix_data = vec![0, 0, 0, 0, 0, 7, 0, 0];
Expand Down Expand Up @@ -568,7 +515,8 @@ mod tests {
&owner,
false,
Epoch::default(),
),
)
.into(),
AccountInfo::new(
&pubkey2,
true,
Expand All @@ -578,7 +526,8 @@ mod tests {
&owner,
false,
Epoch::default(),
),
)
.into(),
AccountInfo::new(
&pubkey3,
false,
Expand All @@ -588,7 +537,8 @@ mod tests {
&owner,
false,
Epoch::default(),
),
)
.into(),
];

let extra_meta1 = AccountMeta::new(Pubkey::new_unique(), false);
Expand Down Expand Up @@ -640,16 +590,8 @@ mod tests {
+ ExtraAccountMetaList::size_of(metas.len()).unwrap();
let mut buffer = vec![0; account_size];

ExtraAccountMetaList::init_with_account_infos::<TestInstruction>(
&mut buffer,
&account_infos,
)
.unwrap();
ExtraAccountMetaList::init_with_pod_account_metas::<TestOtherInstruction>(
&mut buffer,
&metas,
)
.unwrap();
ExtraAccountMetaList::init::<TestInstruction>(&mut buffer, &account_infos).unwrap();
ExtraAccountMetaList::init::<TestOtherInstruction>(&mut buffer, &metas).unwrap();

let program_id = Pubkey::new_unique();
let mut instruction = Instruction::new_with_bytes(program_id, &[], vec![]);
Expand All @@ -662,9 +604,6 @@ mod tests {
.map(ExtraAccountMeta::from)
.collect::<Vec<_>>(),
account_infos
.iter()
.map(ExtraAccountMeta::from)
.collect::<Vec<_>>()
);

let program_id = Pubkey::new_unique();
Expand Down Expand Up @@ -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::<TestInstruction>(
&mut buffer,
&required_accounts,
)
.unwrap();
ExtraAccountMetaList::init::<TestInstruction>(&mut buffer, &required_accounts).unwrap();

// Make an instruction to check later
// We'll also check the instruction seed components later
Expand Down
Loading

0 comments on commit fbc65f3

Please sign in to comment.