1

Program logged: "Error: memory allocation failed, out of memory". ( The error occurs in line data.extend(checkpoint_data_init_data.serialize_struct()) )

This is function in my programA:

pub fn create_checkpoint(ctx: Context<CreateCheckpoint>) -> Result<()>{
        let save_checkpoint_data = &mut ctx.accounts.save_checkpoint_data;
        let authority = &mut ctx.accounts.authority;
        let user_account = &mut ctx.accounts.user_account;
        let mission = &mut ctx.accounts.mission;
        let checkpoint = &mut ctx.accounts.checkpoint;
        let checkpoint_data_init = &mut ctx.accounts.checkpoint_data_init;
        let vote_machine = &mut ctx.accounts.vote_machine;
        let dash_program_id = &mut ctx.accounts.dash_program_id;
        let system_program = &mut ctx.accounts.system_program;

        let mut accounts: Vec<AccountMeta> = authority.to_account_metas(Some(true));
        accounts.append(&mut user_account.to_account_metas(Some(false)));
        accounts.append(&mut mission.to_account_metas(Some(false)));
        accounts.append(&mut checkpoint.to_account_metas(Some(false)));
        accounts.append(&mut checkpoint_data_init.to_account_metas(Some(false)));
        accounts.append(&mut vote_machine.to_account_metas(Some(false)));
        accounts.append(&mut system_program.to_account_metas(Some(false)));

        let discriminator: [u8; 8] = [ 50, 117, 93, 67, 67, 187, 63, 166 ];

        let checkpoint_data = CheckpointDataToInvoke{
            max_length : save_checkpoint_data.max_length,
            metadata: save_checkpoint_data.metadata.clone(),
            votemachine: save_checkpoint_data.votemachine,
            children: save_checkpoint_data.children.clone(),
        };

        let length_checkpoint_data = checkpoint_data.serialize_struct().len() as u32;

        let checkpoint_data_init_data = VoteDataOfCheckpoint{
            options: save_checkpoint_data.data.options.clone() ,
            max_to_win: save_checkpoint_data.data.max_to_win,
            max_choice: save_checkpoint_data.data.max_choice,
            how_many: save_checkpoint_data.data.how_many,
        };

        // let checkpoint_data_init_data = save_checkpoint_data.data.clone();

        let length_checkpoint_data_init_data = checkpoint_data_init_data.serialize_struct().len() as u32;

        let mut data = discriminator.to_vec();
        data.extend(save_checkpoint_data.checkpoint_id.to_le_bytes().to_vec());
        data.extend(length_checkpoint_data.to_le_bytes().to_vec());
        data.extend(checkpoint_data.serialize_struct());
        data.push(1);
        data.extend(length_checkpoint_data_init_data.to_le_bytes().to_vec());
        data.extend(checkpoint_data_init_data.serialize_struct());

        msg!("Send data: {:?}", data);
        
        let ins = Instruction {
            program_id: dash_program_id.key(),
            accounts: accounts,
            data: data,
        };


        invoke(
            &ins,
            [authority.to_account_info(), user_account.to_account_info(), mission.to_account_info(), checkpoint.to_account_info(), checkpoint_data_init.to_account_info(), vote_machine.to_account_info(), system_program.to_account_info()].as_ref(),
        );

        Ok(())
}

This is function in my programB:

pub fn init_checkpoint(ctx: Context<InitCheckpoint>, checkpoint_id: u16, checkpoint_data: Vec<u8>, checkpoint_data_init_data: Option<Vec<u8>>) -> Result<()> { }

this code in programA is the parameter I need to pass to init_checkpoint function in program B

let mut data = discriminator.to_vec();
        data.extend(save_checkpoint_data.checkpoint_id.to_le_bytes().to_vec());
        data.extend(length_checkpoint_data.to_le_bytes().to_vec());
        data.extend(checkpoint_data.serialize_struct());
        data.push(1);
        data.extend(length_checkpoint_data_init_data.to_le_bytes().to_vec());
        data.extend(checkpoint_data_init_data.serialize_struct()); 

i think data variable is a vector of bytes array. so it too long and exceed the limit of solana i don't init any account or execute CPI from program A to program B with big account. so it's not exceed the amount of allocation. i can't find any solution. if you know please help. Thank you!

3 Answers 3

2

When you use a vector in your program, you're using the heap provided by the runtime, which maxes out at 32KB.

So when you keep pushing to data, you can eventually run out of heap space. Normally, there are some ways to deal with this, by using stack allocations as much as possible, or by using account bytes directly.

However, you're trying to pass this data into a CPI, where it might be rejected, since you can only pass 10240 bytes into a CPI.

You may want to redesign the data that you're passing into the other program, and simply use the account directly rather than serializing it into another buffer.

More info at https://docs.solana.com/developing/on-chain-programs/faq#heap-size

2
  • I really appreciate your support. But the function in our program B wants it to be able to accept any data. So we can't define a struct account in program B, because we don't know what data they are sending. this is the key point. :(( Do you have any other suggestions? Jun 16, 2023 at 16:23
  • 1
    Unfortunately no, because of the limit that I mentioned, you cannot pass all that data via CPI instruction data, so you'll have to pass it via account data. Or you'll have to pass less data.
    – Jon C
    Jun 17, 2023 at 12:21
1

Here is an example on how to create accounts bigger than 10Kb using zero copy and an account loader: https://github.com/solana-developers/anchor-zero-copy-example Also comes with a video walkthrough.

1
  • i don't init any account or execute CPI from program A to program B with big account. so it's not exceed the amount of allocation. Jun 19, 2023 at 11:01
0

I really appreciate your support. But the function in our program B wants it to be able to accept any data. So we can't define a struct account in program B, because we don't know what data they are sending. this is the key point. Do you have any other suggestions?

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.