Report incorrect code
Copy
Ask AI
#![allow(unexpected_cfgs)]
#[cfg(any(test, feature = "test-helpers"))]
pub mod test_helpers;
use borsh::{BorshDeserialize, BorshSerialize};
use light_macros::pubkey;
use light_sdk::{
account::sha::LightAccount,
address::v1::derive_address,
cpi::{
v1::{CpiAccounts, LightSystemProgramCpi},
CpiSigner, InvokeLightSystemProgram, LightCpiInstruction,
},
derive_light_cpi_signer,
error::LightSdkError,
instruction::{account_meta::CompressedAccountMeta, PackedAddressTreeInfo, ValidityProof},
LightDiscriminator,
};
use solana_program::{
account_info::AccountInfo, entrypoint, program_error::ProgramError, pubkey::Pubkey,
};
pub const ID: Pubkey = pubkey!("C9WiPUaQ5PRjEWg7vUmgekfuQtAgFZFhn12ytXEMDr8y");
pub const LIGHT_CPI_SIGNER: CpiSigner = derive_light_cpi_signer!("C9WiPUaQ5PRjEWg7vUmgekfuQtAgFZFhn12ytXEMDr8y");
#[cfg(not(feature = "no-entrypoint"))]
entrypoint!(process_instruction);
#[derive(Debug, BorshSerialize, BorshDeserialize)]
pub enum InstructionType {
Create,
Close,
Reinit,
}
#[derive(Debug, BorshSerialize, BorshDeserialize)]
pub struct CreateInstructionData {
pub proof: ValidityProof,
pub address_tree_info: PackedAddressTreeInfo,
pub output_state_tree_index: u8,
pub message: String,
}
#[derive(Debug, BorshSerialize, BorshDeserialize)]
pub struct CloseInstructionData {
pub proof: ValidityProof,
pub account_meta: CompressedAccountMeta,
pub current_message: String,
}
#[derive(Debug, BorshSerialize, BorshDeserialize)]
pub struct ReinitInstructionData {
pub proof: ValidityProof,
pub account_meta: CompressedAccountMeta,
}
#[derive(Debug, Default, Clone, BorshSerialize, BorshDeserialize, LightDiscriminator)]
pub struct MyCompressedAccount {
pub owner: Pubkey,
pub message: String,
}
pub fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> Result<(), ProgramError> {
let (instruction_type, rest) = instruction_data
.split_first()
.ok_or(ProgramError::InvalidInstructionData)?;
match InstructionType::try_from_slice(&[*instruction_type])
.map_err(|_| ProgramError::InvalidInstructionData)?
{
InstructionType::Create => create(accounts, rest)?,
InstructionType::Close => close(accounts, rest)?,
InstructionType::Reinit => reinit(accounts, rest)?,
}
Ok(())
}
fn create(accounts: &[AccountInfo], instruction_data: &[u8]) -> Result<(), LightSdkError> {
let instruction_data =
CreateInstructionData::try_from_slice(instruction_data).map_err(|_| LightSdkError::Borsh)?;
let signer = accounts.first().ok_or(ProgramError::NotEnoughAccountKeys)?;
let light_cpi_accounts = CpiAccounts::new(signer, &accounts[1..], LIGHT_CPI_SIGNER);
let (address, address_seed) = derive_address(
&[b"message", signer.key.as_ref()],
&instruction_data
.address_tree_info
.get_tree_pubkey(&light_cpi_accounts)
.map_err(|_| ProgramError::NotEnoughAccountKeys)?,
&ID,
);
let new_address_params = instruction_data
.address_tree_info
.into_new_address_params_packed(address_seed);
let mut my_compressed_account = LightAccount::<MyCompressedAccount>::new_init(
&ID,
Some(address),
instruction_data.output_state_tree_index,
);
my_compressed_account.owner = *signer.key;
my_compressed_account.message = instruction_data.message;
LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof)
.with_light_account(my_compressed_account)?
.with_new_addresses(&[new_address_params])
.invoke(light_cpi_accounts)?;
Ok(())
}
fn close(accounts: &[AccountInfo], instruction_data: &[u8]) -> Result<(), LightSdkError> {
let instruction_data =
CloseInstructionData::try_from_slice(instruction_data).map_err(|_| LightSdkError::Borsh)?;
let (signer, remaining_accounts) = accounts
.split_first()
.ok_or(ProgramError::InvalidAccountData)?;
let cpi_accounts = CpiAccounts::new(signer, remaining_accounts, LIGHT_CPI_SIGNER);
let my_compressed_account = LightAccount::<MyCompressedAccount>::new_close(
&ID,
&instruction_data.account_meta,
MyCompressedAccount {
owner: *signer.key,
message: instruction_data.current_message,
},
)?;
LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof)
.with_light_account(my_compressed_account)?
.invoke(cpi_accounts)?;
Ok(())
}
fn reinit(accounts: &[AccountInfo], instruction_data: &[u8]) -> Result<(), LightSdkError> {
let instruction_data =
ReinitInstructionData::try_from_slice(instruction_data).map_err(|_| LightSdkError::Borsh)?;
let (signer, remaining_accounts) = accounts
.split_first()
.ok_or(ProgramError::InvalidAccountData)?;
let cpi_accounts = CpiAccounts::new(signer, remaining_accounts, LIGHT_CPI_SIGNER);
let my_compressed_account = LightAccount::<MyCompressedAccount>::new_empty(
&ID,
&instruction_data.account_meta,
)?;
LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof)
.with_light_account(my_compressed_account)?
.invoke(cpi_accounts)?;
Ok(())
}