use anchor_lang::prelude::*;
declare_id!("JA5cjkRJ1euVi9xLWsCJVzsRzEkT8vcC4rqw9sVAo5d6");
#[cfg(not(feature = "no-entrypoint"))]
solana_security_txt::security_txt! {
name: "light_protocol_merkle_tree",
project_url: "lightprotocol.com",
contacts: "email:security@lightprotocol.com",
policy: "https://github.com/Lightprotocol/light-protocol-program/blob/main/SECURITY.md",
source_code: "https://github.com/Lightprotocol/light-protocol-program/program_merkle_tree"
}
pub mod event_merkle_tree;
pub use event_merkle_tree::*;
pub mod instructions;
pub use instructions::*;
pub mod indexed_merkle_tree;
pub mod transaction_merkle_tree;
pub use transaction_merkle_tree::*;
pub mod verifier_invoked_instructions;
pub use verifier_invoked_instructions::*;
pub mod errors;
pub use errors::*;
pub mod utils;
pub mod config_accounts;
pub use config_accounts::*;
use crate::{
errors::ErrorCode,
transaction_merkle_tree::state::TransactionMerkleTree,
utils::{
accounts::deserialize_and_update_old_merkle_tree,
config::{self, MERKLE_TREE_HEIGHT, ZERO_BYTES_MERKLE_TREE_18},
constants::{EVENT_MERKLE_TREE_SEED, TRANSACTION_MERKLE_TREE_SEED},
},
};
#[program]
pub mod light_merkle_tree_program {
use super::*;
pub fn initialize_new_merkle_trees(
ctx: Context<InitializeNewMerkleTrees>,
lock_duration: u64,
) -> Result<()> {
if !ctx
.accounts
.merkle_tree_authority_pda
.enable_permissionless_merkle_tree_registration
&& ctx.accounts.authority.key() != ctx.accounts.merkle_tree_authority_pda.pubkey
{
return err!(ErrorCode::InvalidAuthority);
}
if ctx.remaining_accounts.len() != 2 {
return err!(ErrorCode::ExpectedOldMerkleTrees);
}
let merkle_tree_authority = &mut ctx.accounts.merkle_tree_authority_pda;
deserialize_and_update_old_merkle_tree::<TransactionMerkleTree>(
&ctx.remaining_accounts[0],
TRANSACTION_MERKLE_TREE_SEED,
ctx.program_id,
)?;
let new_transaction_merkle_tree =
&mut ctx.accounts.new_transaction_merkle_tree.load_init()?;
process_initialize_new_merkle_tree_18(
new_transaction_merkle_tree,
merkle_tree_authority,
MERKLE_TREE_HEIGHT,
ZERO_BYTES_MERKLE_TREE_18.to_vec(),
);
new_transaction_merkle_tree.lock_duration = lock_duration;
deserialize_and_update_old_merkle_tree::<event_merkle_tree::EventMerkleTree>(
&ctx.remaining_accounts[1],
EVENT_MERKLE_TREE_SEED,
ctx.program_id,
)?;
let new_event_merkle_tree = &mut ctx.accounts.new_event_merkle_tree.load_init()?;
process_initialize_new_event_merkle_tree(new_event_merkle_tree, merkle_tree_authority);
Ok(())
}
pub fn initialize_merkle_tree_authority(
ctx: Context<InitializeMerkleTreeAuthority>,
) -> Result<()> {
ctx.accounts.merkle_tree_authority_pda.pubkey = ctx.accounts.authority.key();
let merkle_tree = &mut ctx.accounts.transaction_merkle_tree.load_init()?;
let merkle_tree_authority = &mut ctx.accounts.merkle_tree_authority_pda;
process_initialize_new_merkle_tree_18(
merkle_tree,
merkle_tree_authority,
MERKLE_TREE_HEIGHT,
ZERO_BYTES_MERKLE_TREE_18.to_vec(),
);
let event_merkle_tree = &mut ctx.accounts.event_merkle_tree.load_init()?;
let merkle_tree_authority = &mut ctx.accounts.merkle_tree_authority_pda;
process_initialize_new_event_merkle_tree(event_merkle_tree, merkle_tree_authority);
Ok(())
}
pub fn update_merkle_tree_authority(ctx: Context<UpdateMerkleTreeAuthority>) -> Result<()> {
ctx.accounts.merkle_tree_authority_pda.pubkey = ctx.accounts.new_authority.key();
Ok(())
}
pub fn update_lock_duration(
ctx: Context<UpdateLockDuration>,
lock_duration: u64,
) -> Result<()> {
ctx.accounts
.transaction_merkle_tree
.load_mut()?
.lock_duration = lock_duration;
Ok(())
}
pub fn enable_permissionless_spl_tokens(
ctx: Context<UpdateMerkleTreeAuthorityConfig>,
enable_permissionless: bool,
) -> Result<()> {
ctx.accounts
.merkle_tree_authority_pda
.enable_permissionless_spl_tokens = enable_permissionless;
Ok(())
}
pub fn register_verifier(
ctx: Context<RegisterVerifier>,
verifier_pubkey: Pubkey,
) -> Result<()> {
if !ctx
.accounts
.merkle_tree_authority_pda
.enable_permissionless_merkle_tree_registration
&& ctx.accounts.authority.key() != ctx.accounts.merkle_tree_authority_pda.pubkey
{
return err!(ErrorCode::InvalidAuthority);
}
ctx.accounts.registered_verifier_pda.pubkey = verifier_pubkey;
Ok(())
}
pub fn register_pool_type(ctx: Context<RegisterPoolType>, pool_type: [u8; 32]) -> Result<()> {
if !ctx
.accounts
.merkle_tree_authority_pda
.enable_permissionless_spl_tokens
&& ctx.accounts.authority.key() != ctx.accounts.merkle_tree_authority_pda.pubkey
{
return err!(ErrorCode::InvalidAuthority);
}
ctx.accounts.registered_pool_type_pda.pool_type = pool_type;
Ok(())
}
pub fn register_spl_pool(ctx: Context<RegisterSplPool>) -> Result<()> {
if !ctx
.accounts
.merkle_tree_authority_pda
.enable_permissionless_spl_tokens
&& ctx.accounts.authority.key() != ctx.accounts.merkle_tree_authority_pda.pubkey
{
return err!(ErrorCode::InvalidAuthority);
}
ctx.accounts.registered_asset_pool_pda.asset_pool_pubkey =
ctx.accounts.merkle_tree_pda_token.key();
ctx.accounts.registered_asset_pool_pda.pool_type =
ctx.accounts.registered_pool_type_pda.pool_type;
ctx.accounts.registered_asset_pool_pda.index = ctx
.accounts
.merkle_tree_authority_pda
.registered_asset_index;
ctx.accounts
.merkle_tree_authority_pda
.registered_asset_index += 1;
Ok(())
}
pub fn register_sol_pool(ctx: Context<RegisterSolPool>) -> Result<()> {
if !ctx
.accounts
.merkle_tree_authority_pda
.enable_permissionless_spl_tokens
&& ctx.accounts.authority.key() != ctx.accounts.merkle_tree_authority_pda.pubkey
{
return err!(ErrorCode::InvalidAuthority);
}
ctx.accounts.registered_asset_pool_pda.asset_pool_pubkey =
ctx.accounts.registered_asset_pool_pda.key();
ctx.accounts.registered_asset_pool_pda.pool_type =
ctx.accounts.registered_pool_type_pda.pool_type;
ctx.accounts.registered_asset_pool_pda.index = ctx
.accounts
.merkle_tree_authority_pda
.registered_asset_index;
ctx.accounts
.merkle_tree_authority_pda
.registered_asset_index += 1;
Ok(())
}
pub fn initialize_merkle_tree_update_state<'info>(
ctx: Context<'_, '_, '_, 'info, InitializeUpdateState<'info>>,
) -> Result<()> {
process_initialize_update_state(ctx)
}
pub fn update_transaction_merkle_tree<'info>(
mut ctx: Context<'_, '_, '_, 'info, UpdateTransactionMerkleTree<'info>>,
_bump: u64,
) -> Result<()> {
process_update_merkle_tree(&mut ctx)
}
pub fn insert_root_merkle_tree<'info>(
mut ctx: Context<'_, '_, '_, 'info, InsertRoot<'info>>,
_bump: u64,
) -> Result<()> {
process_insert_root(&mut ctx)
}
pub fn close_merkle_tree_update_state(
_ctx: Context<CloseUpdateState>,
) -> anchor_lang::Result<()> {
Ok(())
}
pub fn insert_two_leaves<'info>(
ctx: Context<'_, '_, '_, 'info, InsertTwoLeaves<'info>>,
leaf_left: [u8; 32],
leaf_right: [u8; 32],
encrypted_utxo: [u8; 256],
) -> Result<()> {
process_insert_two_leaves(ctx, leaf_left, leaf_right, encrypted_utxo)
}
pub fn insert_two_leaves_event<'info>(
ctx: Context<'_, '_, '_, 'info, InsertTwoLeavesEvent<'info>>,
leaf_left: [u8; 32],
leaf_right: [u8; 32],
) -> Result<()> {
process_insert_two_leaves_event(ctx, leaf_left, leaf_right)
}
pub fn unshield_sol<'info>(
ctx: Context<'_, '_, '_, 'info, UnshieldSol<'info>>,
amount: u64,
) -> Result<()> {
process_sol_transfer(
&ctx.accounts.merkle_tree_token.to_account_info(),
&ctx.accounts.recipient.to_account_info(),
amount,
)
}
pub fn unshield_spl<'info>(
ctx: Context<'_, '_, '_, 'info, UnshieldSpl<'info>>,
amount: u64,
) -> Result<()> {
process_spl_transfer(ctx, amount)
}
pub fn initialize_nullifiers<'info>(
ctx: Context<'_, '_, '_, 'info, InitializeNullifiers<'info>>,
nullifiers: Vec<[u8; 32]>,
) -> Result<()> {
process_insert_nullifiers(ctx, nullifiers)
}
}