Skip to main content

light_nullifier_program/
lib.rs

1#![allow(unexpected_cfgs)]
2#![allow(deprecated)]
3
4use anchor_lang::prelude::*;
5
6#[cfg(not(target_os = "solana"))]
7pub mod sdk;
8use light_sdk::constants::ADDRESS_TREE_V2;
9use light_sdk::{
10    account::LightAccount,
11    address::v2::derive_address,
12    cpi::{v2::CpiAccounts, CpiSigner},
13    derive_light_cpi_signer,
14    instruction::{PackedAddressTreeInfo, ValidityProof},
15    LightDiscriminator, PackedAddressTreeInfoExt,
16};
17
18declare_id!("NFLx5WGPrTHHvdRNsidcrNcLxRruMC92E4yv7zhZBoT");
19
20pub const LIGHT_CPI_SIGNER: CpiSigner =
21    derive_light_cpi_signer!("NFLx5WGPrTHHvdRNsidcrNcLxRruMC92E4yv7zhZBoT");
22
23#[program]
24pub mod create_nullifier {
25
26    use super::*;
27    use light_sdk::cpi::{
28        v2::LightSystemProgramCpi, InvokeLightSystemProgram, LightCpiInstruction,
29    };
30
31    /// Creates a rent-free PDA derived from id. If the id has been used before, the PDA already
32    /// exists, causing the instruction to fail.
33    pub fn create_nullifier<'info>(
34        ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>,
35        proof: ValidityProof,
36        address_tree_info: PackedAddressTreeInfo,
37        output_state_tree_index: u8,
38        id: [u8; 32],
39    ) -> Result<()> {
40        let light_cpi_accounts = CpiAccounts::new(
41            ctx.accounts.signer.as_ref(),
42            ctx.remaining_accounts,
43            crate::LIGHT_CPI_SIGNER,
44        );
45
46        let address_tree_pubkey = address_tree_info
47            .get_tree_pubkey(&light_cpi_accounts)
48            .map_err(|_| ErrorCode::AccountNotEnoughKeys)?;
49
50        if address_tree_pubkey.to_bytes() != ADDRESS_TREE_V2 {
51            msg!("Invalid address tree");
52            return Err(ProgramError::InvalidAccountData.into());
53        }
54
55        let (address, address_seed) =
56            derive_address(&[b"nullifier", &id], &address_tree_pubkey, &crate::ID);
57
58        let my_compressed_account = LightAccount::<NullifierAccount>::new_init(
59            &crate::ID,
60            Some(address),
61            output_state_tree_index,
62        );
63
64        msg!("Created nullifier account with id: {:?}", id);
65
66        LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof)
67            .with_light_account(my_compressed_account)?
68            .with_new_addresses(&[
69                address_tree_info.into_new_address_params_assigned_packed(address_seed, Some(0))
70            ])
71            .invoke(light_cpi_accounts)?;
72
73        Ok(())
74    }
75}
76
77#[derive(Accounts)]
78pub struct GenericAnchorAccounts<'info> {
79    #[account(mut)]
80    pub signer: Signer<'info>,
81}
82
83#[event]
84#[derive(Clone, Debug, Default, LightDiscriminator)]
85pub struct NullifierAccount {}