Skip to content

Commit

Permalink
chore: Hint the light account space in LightAccountMeta
Browse files Browse the repository at this point in the history
  • Loading branch information
vadorovsky committed Nov 10, 2024
1 parent 27b62af commit cdb6208
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#![cfg(feature = "test-sbf")]

use std::net::{Ipv4Addr, Ipv6Addr};
use std::{
mem,
net::{Ipv4Addr, Ipv6Addr},
};

use anchor_lang::{AnchorDeserialize, InstructionData, ToAccountMetas};
use light_client::indexer::test_indexer::TestIndexer;
Expand Down Expand Up @@ -297,12 +300,13 @@ where
address_queue_pubkey: env.address_merkle_tree_queue_pubkey,
};
let account = LightAccountMeta::new_init(
None,
&env.merkle_tree_pubkey,
Some(&address_merkle_context),
Some(rpc_result.address_root_indices[0]),
Some(mem::size_of::<NameRecord>() + name.len()),
remaining_accounts,
);
)
.unwrap();

let inputs = LightInstructionData {
proof: Some(rpc_result),
Expand Down
29 changes: 7 additions & 22 deletions sdk/src/account_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,35 +79,20 @@ impl<'a> LightAccountInfo<'a> {
.ok_or(LightSdkError::ExpectedAddressRootIndex)?,
};

let data = match meta.space {
Some(space) => Vec::with_capacity(space.into()),
None => Vec::new(),
};
let data = Some(Rc::new(RefCell::new(data)));

let account_info = LightAccountInfo {
input: None,
owner: Some(*program_id),
// Needs to be assigned by the program.
lamports: None,
// Needs to be assigned by the program.
discriminator: Some(discriminator),
// NOTE(vadorovsky): A `clone()` here is unavoidable.
// What we have here is an immutable reference to `LightAccountMeta`,
// from which we can take an immutable reference to `data`.
//
// - That immutable reference can be used in the input account,
// since we don't make modifications there.
// - In the most cases, we intend to make modifications for the
// output account. We make a copy, which then we try not to
// copy again until the moment of creating a CPI call.
//
// The reason why `solana_account_info::AccountInfo` stores data as
// `Rc<RefCell<&'a mut [u8]>>` is that the reference points to
// runtime's memory region which provides the accout and is mutable
// by design.
//
// In our case, compressed accounts are part of instruction data.
// Instruction data is immutable (`&[u8]`). There is no way to
// mutate instruction data without copy.
data: meta
.data
.as_ref()
.map(|data| Rc::new(RefCell::new(data.clone()))),
data,
// Needs to be assigned by the program.
data_hash: None,
address: Some(new_address),
Expand Down
26 changes: 21 additions & 5 deletions sdk/src/account_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use solana_program::pubkey::Pubkey;

use crate::{
compressed_account::CompressedAccountWithMerkleContext,
error::LightSdkError,
merkle_context::{
pack_address_merkle_context, pack_merkle_context, AddressMerkleContext,
PackedAddressMerkleContext, PackedMerkleContext, RemainingAccounts,
Expand All @@ -19,6 +20,14 @@ pub struct LightAccountMeta {
pub address: Option<[u8; 32]>,
/// Data of the account.
pub data: Option<Vec<u8>>,
/// Size of the account.
///
/// Relevant only for `init` accounts.
///
/// This option is not mandatory, but it's recommended and used for
/// memory allocation of the new account data in the program. Not
/// setting it might result in wasteful re-allocations.
pub space: Option<u16>,
/// Merkle tree.
pub merkle_context: Option<PackedMerkleContext>,
/// Merkle tree root index.
Expand All @@ -38,26 +47,31 @@ pub struct LightAccountMeta {
impl LightAccountMeta {
#[allow(clippy::too_many_arguments)]
pub fn new_init(
data: Option<Vec<u8>>,
output_merkle_tree: &Pubkey,
address_merkle_context: Option<&AddressMerkleContext>,
address_merkle_tree_root_index: Option<u16>,
space: Option<usize>,
remaining_accounts: &mut RemainingAccounts,
) -> Self {
) -> Result<Self, LightSdkError> {
let output_merkle_tree_index = remaining_accounts.insert_or_get(*output_merkle_tree);
let address_merkle_context =
address_merkle_context.map(|ctx| pack_address_merkle_context(ctx, remaining_accounts));
Self {
let space = match space {
Some(space) => Some(space.try_into().map_err(|_| LightSdkError::SpaceTooLarge)?),
None => None,
};
Ok(Self {
lamports: None,
address: None,
data,
data: None,
space,
merkle_context: None,
merkle_tree_root_index: None,
output_merkle_tree_index: Some(output_merkle_tree_index),
address_merkle_context,
address_merkle_tree_root_index,
read_only: false,
}
})
}

#[allow(clippy::too_many_arguments)]
Expand All @@ -82,6 +96,7 @@ impl LightAccountMeta {
.data
.as_ref()
.map(|data| data.data.clone()),
space: None,
merkle_context: Some(merkle_context),
merkle_tree_root_index: Some(merkle_tree_root_index),
output_merkle_tree_index: Some(output_merkle_tree_index),
Expand All @@ -106,6 +121,7 @@ impl LightAccountMeta {
.data
.as_ref()
.map(|data| data.data.clone()),
space: None,
merkle_context: Some(merkle_context),
merkle_tree_root_index: Some(merkle_tree_root_index),
output_merkle_tree_index: None,
Expand Down
2 changes: 2 additions & 0 deletions sdk/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ pub enum LightSdkError {
ExpectedMerkleContext,
#[msg("Expected root index to be provided")]
ExpectedRootIndex,
#[msg("Provided account space is too large")]
SpaceTooLarge,
#[msg("Cannot transfer lamports from an account without input")]
TransferFromNoInput,
#[msg("Cannot transfer from an account without lamports")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ where
address_queue_pubkey: env.address_merkle_tree_queue_pubkey,
};
let account = LightAccountMeta::new_init(
None,
&env.merkle_tree_pubkey,
Some(&address_merkle_context),
Some(rpc_result.address_root_indices[0]),
Expand Down

0 comments on commit cdb6208

Please sign in to comment.