1

I have initilized a PDA with 10000 bytes of space and a Vector on its stored data:

#[derive(Accounts, Clone)]
pub struct CreateVectorPda<'info> {
    /// CHECK: Just testing
    #[account(mut)]
    pub payer: Signer<'info>,
    /// CHECK: Just testing
    pub rent: Sysvar<'info, Rent>,
    pub system_program: Program<'info, System>,
    #[account(init, payer=payer, space = 10000 , seeds = [b"seeds".as_ref()], bump)]
    vector_pda: Account<'info, VectorPDA>,

}
#[account]
#[derive(Default)]
pub struct VectorPDA {
    pub addresses: Vec<Pubkey>,
    pub bump: u8,
}

But I cant store as much data as I want. For what I have researched yet, this happens because I am using Vec::push() on the vector stored in the account's data and, as the push method allocates the entire account's state I get the Error: memory allocation failed, out of memory.

This is my function for testing, just a loop trying to store 100 pubkeys in the vector each time the function is called.

pub fn populate_vector(ctx: Context<PopulateVector>) -> Result<()> {
        for i in 0..100 {
            ctx.accounts
                .vector_pda
                .addresses
                .push(ctx.accounts.payer.key())
        }
        Ok(())
    }

#[derive(Accounts, Clone)]
pub struct PopulateVector<'info> {
    /// CHECK: Just testing
    #[account(mut)]
    pub payer: Signer<'info>,
    /// CHECK: Just testing
    pub rent: Sysvar<'info, Rent>,
    pub system_program: Program<'info, System>,
    #[account(mut, seeds = [b"seeds".as_ref(), bump = reveal_pda.bump)]
    vector_pda: Account<'info, VectorPDA>,
}

I have been told to use Vec::copy_from_slice() but cant figure how to get this data after storing it.

const SIZE1: usize = 13;
const SIZE2: usize = 45;

let data_ref: &mut [u8] = &mut ctx.accounts.pda_account.try_borrow_mut_data()?;
let account_to_store: [u8; 32] = ctx.accounts.account_to_store.key().to_bytes();
let data = data_ref.get_mut(SIZE1..SIZE2).unwrap();
data.copy_from_slice(&account_to_store);

The question is, how can I allocate data on an specific memory region instead of using Vec::push? Do I need to desirialize the account first in order to access memory region?

Thanks.

2
  • can you elaborate what you've tried and the problems you've encountered with copy_from_slice?
    – trent.sol
    Commented Aug 2, 2022 at 1:58
  • Sure, I have tried this. I think this stores the public key: const SIZE1: usize = 13; const SIZE2: usize = 45; let data_ref: &mut [u8] = &mut ctx.accounts.pda_account.try_borrow_mut_data()?; let account_to_store: [u8; 32] = ctx.accounts.account_to_store.key().to_bytes(); let data = data_ref.get_mut(SIZE1..SIZE2).unwrap(); data.copy_from_slice(&account_to_store); Commented Aug 2, 2022 at 6:49

1 Answer 1

2

A vector with a borsh account is intensive as on deserialization it copies all the existing data into the VectorPda addresses field and allocate a Pubkey for each element.

If you need to handle a large data structure and want to avoid large copies, read/write, you need to use Anchor zero copy.

It does not support Vec<T> but you can approximate the same behaviour using an array [Pubkey; MAX_LEN] This will allow you to append and access elements without triggering a lot of overhead on serialization/deserialization.

Unfortunately, this isn't yet included in the Anchor book but you can learn how to use it thanks to the zero copy tests.

EventQ can contain up to 25,000 Event structs https://github.com/coral-xyz/anchor/blob/master/tests/zero-copy/programs/zero-copy/src/lib.rs#L156-L165

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.