use proc_macro::TokenStream;
use quote::quote;
use syn::Item;
pub fn arcium_program_macro(input: &mut Item) -> TokenStream {
let errors = quote! {
#[derive(Clone, Copy, Debug)]
pub enum CallbackError {
InvalidCallbackTx,
}
impl CallbackError {
pub fn name(&self) -> String {
match self {
CallbackError::InvalidCallbackTx => "InvalidCallbackTx".to_string(),
}
}
}
impl ::core::fmt::Display for CallbackError {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.write_str("Invalid callback transaction")
}
}
impl From<CallbackError> for u32 {
fn from(_: CallbackError) -> u32 {
9999
}
}
impl From<CallbackError> for ::anchor_lang::error::Error {
fn from(e: CallbackError) -> Self {
::anchor_lang::error::Error::from(
::anchor_lang::error::AnchorError {
error_name: e.name(),
error_code_number: e.into(),
error_msg: e.to_string(),
error_origin: None,
compared_values: None,
}
)
}
}
};
let signer_account_struct = quote! {
#[::anchor_lang::prelude::account]
pub struct ArciumSignerAccount {
bump: u8,
}
};
let validate_callback_ixs = quote! {
fn validate_callback_ixs(instructions_sysvar: &AccountInfo, arcium_program: &Pubkey) -> Result<()> {
const ARCIUM_CALLBACK_COMPUTATION_DISCRIMINATOR: [u8; 8] =
[11, 224, 42, 236, 0, 154, 74, 163];
const LIGHTHOUSE_PROGRAM_ID: Pubkey = ::anchor_lang::solana_program::pubkey::Pubkey::from_str_const(
"L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95",
);
let curr_ix_index = ::anchor_lang::solana_program::sysvar::instructions::load_current_index_checked(instructions_sysvar)?;
require!(curr_ix_index != 0, CallbackError::InvalidCallbackTx);
let prev_ix = ::anchor_lang::solana_program::sysvar::instructions::load_instruction_at_checked((curr_ix_index as usize) - 1, instructions_sysvar)?;
require!(
prev_ix.program_id == *arcium_program,
CallbackError::InvalidCallbackTx,
);
require!(
prev_ix.data[0..8] == ARCIUM_CALLBACK_COMPUTATION_DISCRIMINATOR,
CallbackError::InvalidCallbackTx
);
let mut check_index = (curr_ix_index as usize) + 1;
let mut lighthouse_count = 0;
while let Ok(ix) = ::anchor_lang::solana_program::sysvar::instructions::load_instruction_at_checked(
check_index,
instructions_sysvar,
) {
require!(
ix.program_id == LIGHTHOUSE_PROGRAM_ID,
CallbackError::InvalidCallbackTx
);
lighthouse_count += 1;
require!(
lighthouse_count <= 2,
CallbackError::InvalidCallbackTx
);
check_index += 1;
}
Ok(())
}
};
quote! {
#errors
#signer_account_struct
#validate_callback_ixs
#[program]
#input
}
.into()
}