Report incorrect code
Copy
Ask AI
#![allow(unexpected_cfgs)]
// Suppress anchor realloc warning.
#![allow(deprecated)]
use anchor_lang::{prelude::*, AnchorDeserialize, AnchorSerialize};
use borsh::{BorshDeserialize, BorshSerialize};
use light_sdk::cpi::{v2::LightSystemProgramCpi, InvokeLightSystemProgram, LightCpiInstruction};
use light_sdk::{
account::LightAccount,
address::v2::derive_address,
cpi::{v2::CpiAccounts, CpiSigner},
derive_light_cpi_signer,
instruction::{
account_meta::CompressedAccountMetaReadOnly, PackedAddressTreeInfo, ValidityProof,
},
LightDiscriminator,
};
declare_id!("HNqStLMpNuNJqhBF1FbGTKHEFbBLJmq8RdJJmZKWz6jH");
pub const LIGHT_CPI_SIGNER: CpiSigner =
derive_light_cpi_signer!("HNqStLMpNuNJqhBF1FbGTKHEFbBLJmq8RdJJmZKWz6jH");
pub const FIRST_SEED: &[u8] = b"first";
#[program]
pub mod read_only {
use super::*;
/// Creates a new compressed account with initial data
pub fn create_compressed_account<'info>(
ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>,
proof: ValidityProof,
address_tree_info: PackedAddressTreeInfo,
output_state_tree_index: u8,
message: String,
) -> Result<()> {
let light_cpi_accounts = CpiAccounts::new(
ctx.accounts.signer.as_ref(),
ctx.remaining_accounts,
crate::LIGHT_CPI_SIGNER,
);
let (address, address_seed) = derive_address(
&[FIRST_SEED, ctx.accounts.signer.key().as_ref()],
&address_tree_info
.get_tree_pubkey(&light_cpi_accounts)
.map_err(|_| ErrorCode::AccountNotEnoughKeys)?,
&crate::ID,
);
let mut data_account = LightAccount::<DataAccount>::new_init(
&crate::ID,
Some(address),
output_state_tree_index,
);
data_account.owner = ctx.accounts.signer.key();
data_account.message = message;
msg!(
"Created compressed account with message: {}",
data_account.message
);
let new_address_params =
address_tree_info.into_new_address_params_assigned_packed(address_seed, Some(0));
LightSystemProgramCpi::new_cpi(crate::LIGHT_CPI_SIGNER, proof)
.with_light_account(data_account)?
.with_new_addresses(&[new_address_params])
.invoke(light_cpi_accounts)?;
Ok(())
}
/// Reads a compressed account and validates via read-only CPI
pub fn read<'info>(
ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>,
proof: ValidityProof,
existing_account: ExistingCompressedAccountIxData,
) -> Result<()> {
let light_cpi_accounts = CpiAccounts::new(
ctx.accounts.signer.as_ref(),
ctx.remaining_accounts,
crate::LIGHT_CPI_SIGNER,
);
let read_data_account = DataAccount {
owner: ctx.accounts.signer.key(),
message: existing_account.message.clone(),
};
let read_only_account = LightAccount::<DataAccount>::new_read_only(
&crate::ID,
&existing_account.account_meta,
read_data_account,
light_cpi_accounts.tree_pubkeys().unwrap().as_slice(),
)?;
LightSystemProgramCpi::new_cpi(crate::LIGHT_CPI_SIGNER, proof)
.with_light_account(read_only_account)?
.invoke(light_cpi_accounts)?;
Ok(())
}
}
#[derive(Accounts)]
pub struct GenericAnchorAccounts<'info> {
#[account(mut)]
pub signer: Signer<'info>,
}
#[derive(Clone, Debug, Default, BorshSerialize, BorshDeserialize, LightDiscriminator)]
pub struct DataAccount {
pub owner: Pubkey,
pub message: String,
}
#[derive(Clone, Debug, AnchorSerialize, AnchorDeserialize)]
pub struct ExistingCompressedAccountIxData {
pub account_meta: CompressedAccountMetaReadOnly,
pub message: String,
}