light_system_program/
cpi_context_account.rs

1use std::slice;
2
3use aligned_sized::aligned_sized;
4use anchor_lang::prelude::*;
5use light_compressed_account::instruction_data::{
6    invoke_cpi::InstructionDataInvokeCpi, zero_copy::ZInstructionDataInvokeCpi,
7};
8use light_zero_copy::{borsh::Deserialize, errors::ZeroCopyError};
9use zerocopy::{little_endian::U32, Ref};
10
11/// Collects instruction data without executing a compressed transaction.
12/// Signer checks are performed on instruction data.
13/// Collected instruction data is combined with the instruction data of the executing cpi,
14/// and executed as a single transaction.
15/// This enables to use input compressed accounts that are owned by multiple programs,
16/// with one zero-knowledge proof.
17#[aligned_sized(anchor)]
18#[derive(Debug, PartialEq, Default)]
19#[account]
20#[repr(C)]
21pub struct CpiContextAccount {
22    pub fee_payer: Pubkey,
23    pub associated_merkle_tree: Pubkey,
24    // Offset 72
25    pub context: Vec<InstructionDataInvokeCpi>,
26}
27
28impl CpiContextAccount {
29    pub fn init(&mut self, associated_merkle_tree: Pubkey) {
30        self.associated_merkle_tree = associated_merkle_tree;
31        self.context = Vec::new();
32    }
33}
34
35pub struct ZCpiContextAccount<'a> {
36    pub fee_payer: Ref<&'a mut [u8], light_compressed_account::pubkey::Pubkey>,
37    pub associated_merkle_tree: Ref<&'a mut [u8], light_compressed_account::pubkey::Pubkey>,
38    pub context: Vec<ZInstructionDataInvokeCpi<'a>>,
39}
40
41pub fn deserialize_cpi_context_account<'info, 'a>(
42    account_info: &AccountInfo<'info>,
43) -> std::result::Result<ZCpiContextAccount<'a>, ZeroCopyError> {
44    let mut account_data = account_info.try_borrow_mut_data().unwrap();
45    let data = unsafe { slice::from_raw_parts_mut(account_data.as_mut_ptr(), account_data.len()) };
46    let (fee_payer, data) =
47        Ref::<&'a mut [u8], light_compressed_account::pubkey::Pubkey>::from_prefix(&mut data[8..])?;
48    let (associated_merkle_tree, data) =
49        Ref::<&'a mut [u8], light_compressed_account::pubkey::Pubkey>::from_prefix(data)?;
50    let (len, data) = Ref::<&'a mut [u8], U32>::from_prefix(data)?;
51    let mut data = &*data;
52    let mut context = Vec::new();
53    for _ in 0..(u64::from(*len)) as usize {
54        let (context_item, new_data) = ZInstructionDataInvokeCpi::zero_copy_at(data)?;
55        context.push(context_item);
56        data = new_data;
57    }
58    Ok(ZCpiContextAccount {
59        fee_payer,
60        associated_merkle_tree,
61        context,
62    })
63}