chunk_loader/instructions/
pass_to_cpi.rs

1use crate::{error::*, state::*};
2use anchor_lang::{prelude::*, solana_program::instruction::Instruction};
3use solana_invoke::invoke;
4
5#[derive(Accounts)]
6pub struct PassToCpi<'info> {
7    #[account(mut)]
8    owner: Signer<'info>,
9    #[account(mut, has_one = owner, close = owner)]
10    chunk_holder: Account<'info, ChunkHolder>,
11    /// CHECK: This is the program that gets invoked.
12    program: AccountInfo<'info>,
13}
14
15// `u16` is sufficient, more than 10240 bytes cannot be passed to CPI.
16pub fn pass_to_cpi_checked(ctx: Context<PassToCpi>, expected_length: u16) -> Result<()> {
17    let chunk_holder = &ctx.accounts.chunk_holder;
18    let len: usize = chunk_holder
19        .chunks
20        .iter()
21        .map(|chunk| chunk.data.len())
22        .sum();
23    if len != expected_length as usize {
24        return err!(ChunkLoaderError::DataLengthMismatch);
25    }
26
27    pass_to_cpi(ctx)
28}
29
30pub fn pass_to_cpi(ctx: Context<PassToCpi>) -> Result<()> {
31    let data = ctx.accounts.chunk_holder.join_chunks();
32    let accounts = ctx
33        .remaining_accounts
34        .iter()
35        .map(|x| AccountMeta {
36            pubkey: x.key(),
37            is_signer: x.is_signer,
38            is_writable: x.is_writable,
39        })
40        .collect();
41    let instruction = Instruction {
42        program_id: ctx.accounts.program.key(),
43        accounts,
44        data,
45    };
46    invoke(&instruction, ctx.remaining_accounts)?;
47    Ok(())
48}