light_system_program/invoke_cpi/
instruction.rs1use account_compression::{program::AccountCompression, utils::constants::CPI_AUTHORITY_PDA_SEED};
2use anchor_lang::{
3 prelude::*, solana_program::pubkey::Pubkey, system_program::System, AnchorDeserialize,
4 AnchorSerialize,
5};
6
7use super::account::CpiContextAccount;
8use crate::{
9 invoke::{processor::CompressedProof, sol_compression::SOL_POOL_PDA_SEED},
10 sdk::{
11 accounts::{InvokeAccounts, SignerAccounts},
12 compressed_account::PackedCompressedAccountWithMerkleContext,
13 CompressedCpiContext,
14 },
15 NewAddressParamsPacked, OutputCompressedAccountWithPackedContext,
16};
17
18#[derive(Accounts)]
19pub struct InvokeCpiInstruction<'info> {
20 #[account(mut)]
22 pub fee_payer: Signer<'info>,
23 pub authority: Signer<'info>,
24 #[account(
26 seeds = [&crate::ID.to_bytes()], bump, seeds::program = &account_compression::ID,
27 )]
28 pub registered_program_pda: AccountInfo<'info>,
29 pub noop_program: UncheckedAccount<'info>,
31 #[account(seeds = [CPI_AUTHORITY_PDA_SEED], bump)]
33 pub account_compression_authority: UncheckedAccount<'info>,
34 pub account_compression_program: Program<'info, AccountCompression>,
36 pub invoking_program: UncheckedAccount<'info>,
38 #[account(
39 mut,
40 seeds = [SOL_POOL_PDA_SEED], bump
41 )]
42 pub sol_pool_pda: Option<AccountInfo<'info>>,
43 #[account(mut)]
44 pub decompression_recipient: Option<AccountInfo<'info>>,
45 pub system_program: Program<'info, System>,
46 #[account(mut)]
47 pub cpi_context_account: Option<Account<'info, CpiContextAccount>>,
48}
49
50impl<'info> SignerAccounts<'info> for InvokeCpiInstruction<'info> {
51 fn get_fee_payer(&self) -> &Signer<'info> {
52 &self.fee_payer
53 }
54
55 fn get_authority(&self) -> &Signer<'info> {
56 &self.authority
57 }
58}
59
60impl<'info> InvokeAccounts<'info> for InvokeCpiInstruction<'info> {
61 fn get_registered_program_pda(&self) -> &AccountInfo<'info> {
62 &self.registered_program_pda
63 }
64
65 fn get_noop_program(&self) -> &UncheckedAccount<'info> {
66 &self.noop_program
67 }
68
69 fn get_account_compression_authority(&self) -> &UncheckedAccount<'info> {
70 &self.account_compression_authority
71 }
72
73 fn get_account_compression_program(&self) -> &Program<'info, AccountCompression> {
74 &self.account_compression_program
75 }
76
77 fn get_sol_pool_pda(&self) -> Option<&AccountInfo<'info>> {
78 self.sol_pool_pda.as_ref()
79 }
80
81 fn get_decompression_recipient(&self) -> Option<&AccountInfo<'info>> {
82 self.decompression_recipient.as_ref()
83 }
84
85 fn get_system_program(&self) -> &Program<'info, System> {
86 &self.system_program
87 }
88}
89
90#[derive(Debug, PartialEq, Default, Clone, AnchorSerialize, AnchorDeserialize)]
91pub struct InstructionDataInvokeCpi {
92 pub proof: Option<CompressedProof>,
93 pub new_address_params: Vec<NewAddressParamsPacked>,
94 pub input_compressed_accounts_with_merkle_context:
95 Vec<PackedCompressedAccountWithMerkleContext>,
96 pub output_compressed_accounts: Vec<OutputCompressedAccountWithPackedContext>,
97 pub relay_fee: Option<u64>,
98 pub compress_or_decompress_lamports: Option<u64>,
99 pub is_compress: bool,
100 pub cpi_context: Option<CompressedCpiContext>,
101}
102
103impl InstructionDataInvokeCpi {
104 pub fn combine(&mut self, other: &[InstructionDataInvokeCpi]) {
105 for other in other {
106 self.new_address_params
107 .extend_from_slice(&other.new_address_params);
108 self.input_compressed_accounts_with_merkle_context
109 .extend_from_slice(&other.input_compressed_accounts_with_merkle_context);
110 self.output_compressed_accounts
111 .extend_from_slice(&other.output_compressed_accounts);
112 }
113 }
114}
115#[cfg(test)]
116mod tests {
117 use std::vec;
118
119 use crate::{
120 invoke::processor::CompressedProof,
121 sdk::compressed_account::PackedCompressedAccountWithMerkleContext,
122 InstructionDataInvokeCpi, NewAddressParamsPacked, OutputCompressedAccountWithPackedContext,
123 };
124
125 #[test]
127 fn test_combine_instruction_data_transfer() {
128 let mut instruction_data_transfer = InstructionDataInvokeCpi {
129 proof: Some(CompressedProof {
130 a: [0; 32],
131 b: [0; 64],
132 c: [0; 32],
133 }),
134 new_address_params: vec![NewAddressParamsPacked::default()],
135 input_compressed_accounts_with_merkle_context: vec![
136 PackedCompressedAccountWithMerkleContext::default(),
137 ],
138 output_compressed_accounts: vec![OutputCompressedAccountWithPackedContext::default()],
139 relay_fee: Some(1),
140 compress_or_decompress_lamports: Some(1),
141 is_compress: true,
142 cpi_context: None,
143 };
144 let other = InstructionDataInvokeCpi {
145 proof: Some(CompressedProof {
146 a: [0; 32],
147 b: [0; 64],
148 c: [0; 32],
149 }),
150 input_compressed_accounts_with_merkle_context: vec![
151 PackedCompressedAccountWithMerkleContext::default(),
152 ],
153 output_compressed_accounts: vec![OutputCompressedAccountWithPackedContext::default()],
154 relay_fee: Some(1),
155 compress_or_decompress_lamports: Some(1),
156 is_compress: true,
157 new_address_params: vec![NewAddressParamsPacked::default()],
158 cpi_context: None,
159 };
160 instruction_data_transfer.combine(&[other]);
161 assert_eq!(instruction_data_transfer.new_address_params.len(), 2);
162 assert_eq!(
163 instruction_data_transfer
164 .input_compressed_accounts_with_merkle_context
165 .len(),
166 2
167 );
168 assert_eq!(
169 instruction_data_transfer.output_compressed_accounts.len(),
170 2
171 );
172 }
173}