From dd5a2477536c1d52b72c2c93d75ff3853f5ccc60 Mon Sep 17 00:00:00 2001 From: ananas-block Date: Wed, 11 Jun 2025 04:32:35 +0100 Subject: [PATCH 1/4] fix: resolve pinocchio feature compile issues --- .../src/account_info/account_info_trait.rs | 42 ++ .../account-checks/src/account_info/mod.rs | 6 + .../src/account_info/pinocchio.rs | 113 ++++ .../account-checks/src/account_info/solana.rs | 79 +++ program-libs/account-checks/src/checks.rs | 598 ++---------------- program-libs/account-checks/src/error.rs | 33 +- program-libs/account-checks/src/lib.rs | 11 +- program-libs/batched-merkle-tree/Cargo.toml | 3 +- .../batched-merkle-tree/src/constants.rs | 11 +- .../src/initialize_address_tree.rs | 17 +- .../src/initialize_state_tree.rs | 19 +- program-libs/batched-merkle-tree/src/lib.rs | 32 - .../batched-merkle-tree/src/merkle_tree.rs | 39 +- program-libs/batched-merkle-tree/src/queue.rs | 35 +- .../src/queue_batch_metadata.rs | 1 - .../src/rollover_address_tree.rs | 14 +- .../src/rollover_state_tree.rs | 33 +- program-libs/compressed-account/Cargo.toml | 27 +- .../compressed-account/src/constants.rs | 16 +- .../src/indexer_event/event.rs | 4 +- .../src/indexer_event/parse.rs | 8 +- .../src/instruction_data/with_readonly.rs | 6 +- .../src/instruction_data/zero_copy.rs | 7 +- program-libs/compressed-account/src/lib.rs | 25 +- program-libs/compressed-account/src/pubkey.rs | 82 ++- program-libs/macros/src/lib.rs | 9 + program-libs/macros/src/pubkey.rs | 33 +- program-libs/merkle-tree-metadata/Cargo.toml | 14 +- .../merkle-tree-metadata/src/errors.rs | 12 +- program-libs/merkle-tree-metadata/src/lib.rs | 14 - .../merkle-tree-metadata/src/rollover.rs | 17 +- .../initialize_batched_state_merkle_tree.rs | 2 +- .../src/instructions/nullify_leaves.rs | 2 +- .../resize_registered_program_account.rs | 7 +- .../update_address_merkle_tree.rs | 2 +- .../src/processor/insert_addresses.rs | 2 +- .../src/processor/insert_nullifiers.rs | 2 +- programs/compressed-token/src/freeze.rs | 2 +- programs/compressed-token/src/process_mint.rs | 4 +- .../compressed-token/src/process_transfer.rs | 12 +- programs/registry/src/lib.rs | 2 +- .../src/accounts/init_context_account.rs | 2 +- programs/system/src/context.rs | 4 +- .../src/invoke_cpi/process_cpi_context.rs | 2 +- programs/system/src/lib.rs | 4 +- .../src/processor/create_address_cpi_data.rs | 2 +- 46 files changed, 558 insertions(+), 853 deletions(-) create mode 100644 program-libs/account-checks/src/account_info/account_info_trait.rs create mode 100644 program-libs/account-checks/src/account_info/mod.rs create mode 100644 program-libs/account-checks/src/account_info/pinocchio.rs create mode 100644 program-libs/account-checks/src/account_info/solana.rs diff --git a/program-libs/account-checks/src/account_info/account_info_trait.rs b/program-libs/account-checks/src/account_info/account_info_trait.rs new file mode 100644 index 0000000000..c39bd32ed9 --- /dev/null +++ b/program-libs/account-checks/src/account_info/account_info_trait.rs @@ -0,0 +1,42 @@ +use core::ops::{Deref, DerefMut}; + +use crate::error::AccountError; + +/// Trait to abstract over different AccountInfo implementations (pinocchio vs solana) +pub trait AccountInfoTrait { + type DataRef<'a>: Deref + where + Self: 'a; + type DataRefMut<'a>: DerefMut + where + Self: 'a; + + /// Return raw byte array for maximum compatibility + fn key(&self) -> [u8; 32]; + fn is_writable(&self) -> bool; + fn is_signer(&self) -> bool; + fn executable(&self) -> bool; + fn lamports(&self) -> u64; + fn data_len(&self) -> usize; + + /// Unified data access interface + fn try_borrow_data(&self) -> Result, AccountError>; + fn try_borrow_mut_data(&self) -> Result, AccountError>; + + /// Check ownership safely - each implementation handles this without exposing owner + fn is_owned_by(&self, program: &[u8; 32]) -> bool; + + /// PDA functions - each implementation uses its own backend + fn find_program_address(seeds: &[&[u8]], program_id: &[u8; 32]) -> ([u8; 32], u8); + fn create_program_address( + seeds: &[&[u8]], + program_id: &[u8; 32], + ) -> Result<[u8; 32], AccountError>; + + /// Get minimum rent balance for a given size + fn get_min_rent_balance(size: usize) -> Result; + + fn data_is_empty(&self) -> bool { + self.data_len() == 0 + } +} diff --git a/program-libs/account-checks/src/account_info/mod.rs b/program-libs/account-checks/src/account_info/mod.rs new file mode 100644 index 0000000000..d86788da66 --- /dev/null +++ b/program-libs/account-checks/src/account_info/mod.rs @@ -0,0 +1,6 @@ +pub mod account_info_trait; +#[cfg(feature = "pinocchio")] +pub mod pinocchio; +#[cfg(feature = "solana")] +pub mod solana; +pub mod test_account_info; diff --git a/program-libs/account-checks/src/account_info/pinocchio.rs b/program-libs/account-checks/src/account_info/pinocchio.rs new file mode 100644 index 0000000000..9474b3b205 --- /dev/null +++ b/program-libs/account-checks/src/account_info/pinocchio.rs @@ -0,0 +1,113 @@ +use super::account_info_trait::AccountInfoTrait; +use crate::error::AccountError; + +/// Implement trait for pinocchio AccountInfo +impl AccountInfoTrait for pinocchio::account_info::AccountInfo { + type DataRef<'a> = pinocchio::account_info::Ref<'a, [u8]>; + type DataRefMut<'a> = pinocchio::account_info::RefMut<'a, [u8]>; + + fn key(&self) -> [u8; 32] { + *self.key() + } + + fn is_writable(&self) -> bool { + self.is_writable() + } + + fn is_signer(&self) -> bool { + self.is_signer() + } + + fn executable(&self) -> bool { + self.executable() + } + + fn lamports(&self) -> u64 { + self.lamports() + } + + fn data_len(&self) -> usize { + self.data_len() + } + + fn try_borrow_data(&self) -> Result, AccountError> { + self.try_borrow_data().map_err(Into::into) + } + + fn try_borrow_mut_data(&self) -> Result, AccountError> { + self.try_borrow_mut_data().map_err(Into::into) + } + + fn is_owned_by(&self, program: &[u8; 32]) -> bool { + pinocchio::account_info::AccountInfo::is_owned_by(self, program) + } + + fn find_program_address(_seeds: &[&[u8]], _program_id: &[u8; 32]) -> ([u8; 32], u8) { + #[cfg(target_os = "solana")] + { + let program_pubkey = pinocchio::pubkey::Pubkey::from(*_program_id); + let (pubkey, bump) = pinocchio::pubkey::find_program_address(_seeds, &program_pubkey); + (pubkey, bump) + } + // Pinocchio does not support find_program_address outside of target_os solana. + // That is annoying for rust unit tests. + #[cfg(all(not(target_os = "solana"), feature = "solana"))] + { + let program_pubkey = solana_pubkey::Pubkey::from(*_program_id); + let (pubkey, bump) = + solana_pubkey::Pubkey::find_program_address(_seeds, &program_pubkey); + (pubkey.to_bytes(), bump) + } + #[cfg(all(not(target_os = "solana"), not(feature = "solana")))] + { + panic!("find_program_address not supported with pinocchio outside target_os = solana without solana feature"); + } + } + + fn create_program_address( + _seeds: &[&[u8]], + _program_id: &[u8; 32], + ) -> Result<[u8; 32], AccountError> { + #[cfg(target_os = "solana")] + { + let program_pubkey = pinocchio::pubkey::Pubkey::from(*_program_id); + pinocchio::pubkey::create_program_address(_seeds, &program_pubkey) + .map_err(|_| AccountError::InvalidSeeds) + } + // Pinocchio does not support find_program_address outside of target_os solana. + // That is annoying for rust unit tests. + #[cfg(all(not(target_os = "solana"), feature = "solana"))] + { + let program_pubkey = solana_pubkey::Pubkey::from(*_program_id); + let pubkey = solana_pubkey::Pubkey::create_program_address(_seeds, &program_pubkey) + .map_err(|_| AccountError::InvalidSeeds)?; + Ok(pubkey.to_bytes()) + } + #[cfg(all(not(target_os = "solana"), not(feature = "solana")))] + { + Err(AccountError::InvalidSeeds) + } + } + + fn get_min_rent_balance(_size: usize) -> Result { + #[cfg(target_os = "solana")] + { + use pinocchio::sysvars::Sysvar; + pinocchio::sysvars::rent::Rent::get() + .map(|rent| rent.minimum_balance(_size)) + .map_err(|_| AccountError::FailedBorrowRentSysvar) + } + #[cfg(all(not(target_os = "solana"), feature = "solana"))] + { + use solana_sysvar::Sysvar; + + solana_sysvar::rent::Rent::get() + .map(|rent| rent.minimum_balance(_size)) + .map_err(|_| AccountError::FailedBorrowRentSysvar) + } + #[cfg(all(not(target_os = "solana"), not(feature = "solana")))] + { + Err(AccountError::FailedBorrowRentSysvar) + } + } +} diff --git a/program-libs/account-checks/src/account_info/solana.rs b/program-libs/account-checks/src/account_info/solana.rs new file mode 100644 index 0000000000..7c68b80dfe --- /dev/null +++ b/program-libs/account-checks/src/account_info/solana.rs @@ -0,0 +1,79 @@ +use super::account_info_trait::AccountInfoTrait; +use crate::error::AccountError; + +/// Implement trait for solana AccountInfo +impl AccountInfoTrait for solana_account_info::AccountInfo<'_> { + type DataRef<'a> + = std::cell::Ref<'a, [u8]> + where + Self: 'a; + type DataRefMut<'a> + = std::cell::RefMut<'a, [u8]> + where + Self: 'a; + + fn key(&self) -> [u8; 32] { + self.key.to_bytes() + } + + fn is_writable(&self) -> bool { + self.is_writable + } + + fn is_signer(&self) -> bool { + self.is_signer + } + + fn executable(&self) -> bool { + self.executable + } + + fn lamports(&self) -> u64 { + **self.lamports.borrow() + } + + fn data_len(&self) -> usize { + self.data.borrow().len() + } + + fn try_borrow_data(&self) -> Result, AccountError> { + self.data + .try_borrow() + .map(|r| std::cell::Ref::map(r, |data| &**data)) + .map_err(Into::into) + } + + fn try_borrow_mut_data(&self) -> Result, AccountError> { + self.data + .try_borrow_mut() + .map(|r| std::cell::RefMut::map(r, |data| &mut **data)) + .map_err(Into::into) + } + + fn is_owned_by(&self, program: &[u8; 32]) -> bool { + self.owner.as_ref() == program + } + + fn find_program_address(seeds: &[&[u8]], program_id: &[u8; 32]) -> ([u8; 32], u8) { + let program_pubkey = solana_pubkey::Pubkey::from(*program_id); + let (pubkey, bump) = solana_pubkey::Pubkey::find_program_address(seeds, &program_pubkey); + (pubkey.to_bytes(), bump) + } + + fn create_program_address( + seeds: &[&[u8]], + program_id: &[u8; 32], + ) -> Result<[u8; 32], AccountError> { + let program_pubkey = solana_pubkey::Pubkey::from(*program_id); + solana_pubkey::Pubkey::create_program_address(seeds, &program_pubkey) + .map(|pubkey| pubkey.to_bytes()) + .map_err(|_| AccountError::InvalidSeeds) + } + + fn get_min_rent_balance(size: usize) -> Result { + use solana_sysvar::Sysvar; + solana_sysvar::rent::Rent::get() + .map(|rent| rent.minimum_balance(size)) + .map_err(|_| AccountError::FailedBorrowRentSysvar) + } +} diff --git a/program-libs/account-checks/src/checks.rs b/program-libs/account-checks/src/checks.rs index 3c4dd97ef8..e89cdb99f8 100644 --- a/program-libs/account-checks/src/checks.rs +++ b/program-libs/account-checks/src/checks.rs @@ -1,11 +1,13 @@ use crate::{ discriminator::{Discriminator, DISCRIMINATOR_LEN}, error::AccountError, - AccountInfo, Pubkey, + AccountInfoTrait, }; /// Sets discriminator in account data. -pub fn account_info_init(account_info: &AccountInfo) -> Result<(), AccountError> { +pub fn account_info_init( + account_info: &A, +) -> Result<(), AccountError> { set_discriminator::( &mut account_info .try_borrow_mut_data() @@ -18,40 +20,30 @@ pub fn account_info_init(account_info: &AccountInfo) -> Result /// 1. account is mutable /// 2. account owned by program_id /// 3. account discriminator -pub fn check_account_info_mut( - program_id: &Pubkey, - account_info: &AccountInfo, +pub fn check_account_info_mut( + program_id: &[u8; 32], + account_info: &A, ) -> Result<(), AccountError> { - #[cfg(not(feature = "pinocchio"))] - if !account_info.is_writable { - return Err(AccountError::AccountMutable); - } - #[cfg(feature = "pinocchio")] if !account_info.is_writable() { return Err(AccountError::AccountMutable); } - check_account_info::(program_id, account_info) + check_account_info::(program_id, account_info) } /// Checks: /// 1. account is not mutable /// 2. account owned by program_id /// 3. account discriminator -pub fn check_account_info_non_mut( - program_id: &Pubkey, - account_info: &AccountInfo, +pub fn check_account_info_non_mut( + program_id: &[u8; 32], + account_info: &A, ) -> Result<(), AccountError> { check_non_mut(account_info)?; - check_account_info::(program_id, account_info) + check_account_info::(program_id, account_info) } -pub fn check_non_mut(account_info: &AccountInfo) -> Result<(), AccountError> { - #[cfg(not(feature = "pinocchio"))] - if account_info.is_writable { - return Err(AccountError::AccountMutable); - } - #[cfg(feature = "pinocchio")] +pub fn check_non_mut(account_info: &A) -> Result<(), AccountError> { if account_info.is_writable() { return Err(AccountError::AccountMutable); } @@ -61,9 +53,9 @@ pub fn check_non_mut(account_info: &AccountInfo) -> Result<(), AccountError> { /// Checks: /// 1. account owned by program_id /// 2. account discriminator -pub fn check_account_info( - program_id: &Pubkey, - account_info: &AccountInfo, +pub fn check_account_info( + program_id: &[u8; 32], + account_info: &A, ) -> Result<(), AccountError> { check_owner(program_id, account_info)?; @@ -98,8 +90,9 @@ pub fn check_discriminator(bytes: &[u8]) -> Result<(), Account } /// Checks that the account balance is greater or eqal to rent exemption. -pub fn check_account_balance_is_rent_exempt( - account_info: &AccountInfo, +#[cfg(any(feature = "pinocchio", feature = "solana"))] +pub fn check_account_balance_is_rent_exempt( + account_info: &A, expected_size: usize, ) -> Result { let account_size = account_info.data_len(); @@ -109,10 +102,7 @@ pub fn check_account_balance_is_rent_exempt( let lamports = account_info.lamports(); #[cfg(target_os = "solana")] { - use crate::Sysvar; - let rent_exemption = (crate::Rent::get() - .map_err(|_| AccountError::FailedBorrowRentSysvar))? - .minimum_balance(expected_size); + let rent_exemption = A::get_min_rent_balance(expected_size)?; if lamports < rent_exemption { return Err(AccountError::InvalidAccountBalance); } @@ -125,64 +115,28 @@ pub fn check_account_balance_is_rent_exempt( } } -#[cfg(not(feature = "pinocchio"))] -pub fn check_signer(account_info: &AccountInfo) -> Result<(), AccountError> { - if !account_info.is_signer { - return Err(AccountError::InvalidSigner); - } - Ok(()) -} -#[cfg(feature = "pinocchio")] -pub fn check_signer(account_info: &AccountInfo) -> Result<(), AccountError> { +pub fn check_signer(account_info: &A) -> Result<(), AccountError> { if !account_info.is_signer() { return Err(AccountError::InvalidSigner); } Ok(()) } -#[cfg(not(feature = "pinocchio"))] -pub fn check_owner(owner: &Pubkey, account_info: &AccountInfo) -> Result<(), AccountError> { - if *owner != *account_info.owner { - return Err(AccountError::AccountOwnedByWrongProgram); - } - - Ok(()) -} - -#[cfg(feature = "pinocchio")] -pub fn check_owner(owner: &Pubkey, account_info: &AccountInfo) -> Result<(), AccountError> { +pub fn check_owner( + owner: &[u8; 32], + account_info: &A, +) -> Result<(), AccountError> { if !account_info.is_owned_by(owner) { - pinocchio::msg!( - format!("check_owner expected {:?} got: {:?}", owner, unsafe { - account_info.owner() - }) - .as_str() - ); return Err(AccountError::AccountOwnedByWrongProgram); } Ok(()) } -#[cfg(not(feature = "pinocchio"))] -pub fn check_program(program_id: &Pubkey, account_info: &AccountInfo) -> Result<(), AccountError> { - if *account_info.key != *program_id { - return Err(AccountError::InvalidProgramId); - } - if !account_info.executable { - return Err(AccountError::ProgramNotExecutable); - } - Ok(()) -} - -#[cfg(feature = "pinocchio")] -pub fn check_program(program_id: &Pubkey, account_info: &AccountInfo) -> Result<(), AccountError> { - if *account_info.key() != *program_id { - pinocchio::msg!(format!( - "check_owner expected {:?} got: {:?}", - program_id, - account_info.key() - ) - .as_str()); +pub fn check_program( + program_id: &[u8; 32], + account_info: &A, +) -> Result<(), AccountError> { + if account_info.key() != *program_id { return Err(AccountError::InvalidProgramId); } if !account_info.executable() { @@ -191,47 +145,25 @@ pub fn check_program(program_id: &Pubkey, account_info: &AccountInfo) -> Result< Ok(()) } -#[cfg(not(feature = "pinocchio"))] -pub fn check_pda_seeds( - seeds: &[&[u8]], - program_id: &Pubkey, - account_info: &AccountInfo, -) -> Result<(), AccountError> { - if !Pubkey::find_program_address(seeds, program_id) - .0 - .eq(account_info.key) - { - return Err(AccountError::InvalidSeeds); - } - - Ok(()) -} - -#[cfg(feature = "pinocchio")] -pub fn check_pda_seeds( +pub fn check_pda_seeds( seeds: &[&[u8]], - program_id: &Pubkey, - account_info: &AccountInfo, + program_id: &[u8; 32], + account_info: &A, ) -> Result<(), AccountError> { - if !pinocchio::pubkey::find_program_address(seeds, program_id) - .0 - .eq(account_info.key()) - { + let (derived_key, _) = A::find_program_address(seeds, program_id); + if derived_key != account_info.key() { return Err(AccountError::InvalidSeeds); } Ok(()) } -#[cfg(feature = "pinocchio")] -pub fn check_pda_seeds_with_bump( +pub fn check_pda_seeds_with_bump( seeds: &[&[u8]], - program_id: &Pubkey, - account_info: &AccountInfo, + program_id: &[u8; 32], + account_info: &A, ) -> Result<(), AccountError> { - if !pinocchio::pubkey::create_program_address(seeds, program_id) - .map_err(|_| AccountError::InvalidSeeds)? - .eq(account_info.key()) - { + let derived_key = A::create_program_address(seeds, program_id)?; + if derived_key != account_info.key() { return Err(AccountError::InvalidSeeds); } Ok(()) @@ -246,453 +178,3 @@ pub fn check_data_is_zeroed(data: &[u8]) -> Result<(), AccountEr } Ok(()) } - -#[cfg(not(feature = "pinocchio"))] -#[cfg(test)] -mod check_account_tests { - use std::{cell::RefCell, rc::Rc}; - - use borsh::{BorshDeserialize, BorshSerialize}; - - use super::*; - - // Helper function to create pubkeys for tests - #[cfg(not(feature = "pinocchio"))] - fn create_pubkey() -> Pubkey { - Pubkey::new_unique() - } - - #[cfg(feature = "pinocchio")] - fn create_pubkey() -> Pubkey { - let mut rng = [0u8; 32]; - for i in 0..32 { - rng[i] = i as u8; - } - rng - } - - #[repr(C)] - #[derive(Debug, PartialEq, Copy, Clone, BorshSerialize, BorshDeserialize)] - pub struct MyStruct { - pub data: u64, - } - impl Discriminator for MyStruct { - const LIGHT_DISCRIMINATOR: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; - const LIGHT_DISCRIMINATOR_SLICE: &[u8] = &Self::LIGHT_DISCRIMINATOR; - } - - /// Tests: - /// 1. functional set discriminator - /// 2. failing set discriminator - /// 3. functional check discriminator - /// 4. failing check discriminator - #[test] - fn test_discriminator() { - let mut bytes = vec![0; 8 + std::mem::size_of::()]; - - // Test 1 functional set discriminator. - assert_eq!(bytes[0..8], [0; 8]); - set_discriminator::(&mut bytes).unwrap(); - assert_eq!(bytes[0..8], MyStruct::LIGHT_DISCRIMINATOR); - // Test 2 failing set discriminator. - assert_eq!( - set_discriminator::(&mut bytes), - Err(AccountError::AlreadyInitialized) - ); - // Test 3 functional check discriminator. - assert!(check_discriminator::(&bytes).is_ok()); - // Test 4 failing check discriminator. - bytes[0] = 0; - assert_eq!( - check_discriminator::(&bytes), - Err(AccountError::InvalidDiscriminator) - ); - } - - pub struct TestAccount { - pub key: Pubkey, - pub owner: Pubkey, - pub data: Vec, - pub lamports: u64, - pub writable: bool, - pub is_signer: bool, - pub executable: bool, - } - impl TestAccount { - pub fn new(key: Pubkey, owner: Pubkey, size: usize) -> Self { - Self { - key, - owner, - data: vec![0; size], - lamports: 0, - writable: true, - is_signer: false, - executable: false, - } - } - - #[cfg(not(feature = "pinocchio"))] - pub fn get_account_info(&mut self) -> AccountInfo<'_> { - AccountInfo { - key: &self.key, - is_signer: self.is_signer, - is_writable: self.writable, - lamports: Rc::new(RefCell::new(&mut self.lamports)), - data: Rc::new(RefCell::new(&mut self.data)), - owner: &self.owner, - executable: self.executable, - rent_epoch: 0, - } - } - } - - /// Tests: - /// 1. functional check_account_info - /// 2. failing AccountOwnedByWrongProgram - /// 3. failing empty discriminator (InvalidDiscriminator) - /// 4. failing InvalidDiscriminator - /// 5. functional check_account_info_mut - /// 6. failing AccountNotMutable with check_account_info_mut - /// 7. functional check_account_info_non_mut - /// 8. failing AccountMutable with check_account_info_non_mut - #[test] - fn test_check_account_info() { - let key = create_pubkey(); - let program_id = create_pubkey(); - let size = 8 + std::mem::size_of::(); - - // Test 1 functional check_account_info. - { - let mut account = TestAccount::new(key, program_id, size); - set_discriminator::(&mut account.data).unwrap(); - assert!( - check_account_info::(&program_id, &account.get_account_info()).is_ok() - ); - } - // Test 2 failing AccountOwnedByWrongProgram. - { - let mut account = TestAccount::new(key, program_id, size); - set_discriminator::(&mut account.data).unwrap(); - account.owner = create_pubkey(); - assert_eq!( - check_account_info::(&program_id, &account.get_account_info()), - Err(AccountError::AccountOwnedByWrongProgram) - ); - } - // Test 3 failing empty discriminator (InvalidDiscriminator). - { - let mut account = TestAccount::new(key, program_id, size); - assert_eq!( - check_account_info::(&program_id, &account.get_account_info()), - Err(AccountError::InvalidDiscriminator) - ); - } - // Test 4 failing InvalidDiscriminator. - { - let mut account = TestAccount::new(key, program_id, size - 1); - account.data[0..8].copy_from_slice(&[1; 8]); - assert_eq!( - check_account_info::(&program_id, &account.get_account_info()), - Err(AccountError::InvalidDiscriminator) - ); - } - // Test 5 functional check_account_info_mut. - { - let mut account = TestAccount::new(key, program_id, size); - set_discriminator::(&mut account.data).unwrap(); - assert!( - check_account_info_mut::(&program_id, &account.get_account_info()) - .is_ok() - ); - } - // Test 6 failing AccountNotMutable with check_account_info_mut. - { - let mut account = TestAccount::new(key, program_id, size); - set_discriminator::(&mut account.data).unwrap(); - account.writable = false; - // The error can be different depending on the framework - let result = - check_account_info_mut::(&program_id, &account.get_account_info()); - assert!(result.is_err()); - } - // Test 7 functional check_account_info_non_mut. - { - let mut account = TestAccount::new(key, program_id, size); - set_discriminator::(&mut account.data).unwrap(); - account.writable = false; - assert!(check_account_info_non_mut::( - &program_id, - &account.get_account_info() - ) - .is_ok()); - } - // Test 8 failing with check_account_info_non_mut. - { - let mut account = TestAccount::new(key, program_id, size); - set_discriminator::(&mut account.data).unwrap(); - // Different behavior based on the feature flag - #[cfg(not(feature = "pinocchio"))] - assert_eq!( - check_account_info_non_mut::(&program_id, &account.get_account_info()), - Err(AccountError::AccountMutable) - ); - #[cfg(feature = "pinocchio")] - assert!(check_account_info_non_mut::( - &program_id, - &account.get_account_info() - ) - .is_err()); - } - // Test 9 functional account_info_init - { - let mut account = TestAccount::new(key, program_id, size); - assert!(account_info_init::(&account.get_account_info()).is_ok()); - } - // Test 10 failing account_info_init - { - let mut account = TestAccount::new(key, program_id, size); - set_discriminator::(&mut account.data).unwrap(); - assert_eq!( - account_info_init::(&account.get_account_info()), - Err(AccountError::AlreadyInitialized) - ); - } - } - - /// Tests for check_signer function - /// 1. Functional test - account is a signer - /// 2. Failing test - account is not a signer - #[test] - fn test_signer_check() { - let key = create_pubkey(); - let program_id = create_pubkey(); - let size = 8; - - // Test 1: Successful signer check - { - let mut account = TestAccount::new(key, program_id, size); - account.is_signer = true; - assert!(check_signer(&account.get_account_info()).is_ok()); - } - - // Test 2: Failed signer check - account is not a signer - { - let mut account = TestAccount::new(key, program_id, size); - account.is_signer = false; - assert_eq!( - check_signer(&account.get_account_info()), - Err(AccountError::InvalidSigner) - ); - } - } - - /// Tests for check_owner function - /// 1. Functional test - account is owned by the correct program - /// 2. Failing test - account is owned by a different program - #[test] - fn test_program_check() { - let key = create_pubkey(); - let program_id = create_pubkey(); - let wrong_program_id = create_pubkey(); - let size = 8; - - // Test 1: Successful program check - { - let mut account = TestAccount::new(key, program_id, size); - assert!(check_owner(&program_id, &account.get_account_info()).is_ok()); - } - - // Test 2: Failed program check - account owned by wrong program - { - let mut account = TestAccount::new(key, wrong_program_id, size); - assert_eq!( - check_owner(&program_id, &account.get_account_info()), - Err(AccountError::AccountOwnedByWrongProgram) - ); - } - } - - /// Tests for check_pda_seeds function - /// 1. Functional test - PDA matches with the given seeds and program ID - /// 2. Failing test - PDA doesn't match with the given seeds - /// 3. Failing test - Invalid seeds (can't create a valid PDA) - #[test] - #[ignore = "reason"] - #[cfg(not(feature = "pinocchio"))] - fn test_check_pda_seeds_solana() { - let program_id = create_pubkey(); - let size = 8; - - // Test 1: Create a valid PDA and verify it - { - let seeds = &[b"test_seed".as_ref(), &[1, 2, 3]]; - // Generate a PDA - let (pda, _) = Pubkey::find_program_address(seeds, &program_id); - - // Recreate the seeds for the check (without the bump) - let check_seeds = &[b"test_seed".as_ref(), &[1, 2, 3]]; - - // Create a test account with the PDA as key - let mut account = TestAccount::new(pda, program_id, size); - - // This should fail because find_program_address adds the bump seed automatically - // which check_pda_seeds doesn't do - assert!( - check_pda_seeds(check_seeds, &program_id, &account.get_account_info()).is_err() - ); - - // Get the correct seeds with bump - let (_, bump) = Pubkey::find_program_address(seeds, &program_id); - let correct_seeds = &[b"test_seed".as_ref(), &[1, 2, 3], &[bump]]; - // Now the check should pass with the correct seeds including bump - assert!( - check_pda_seeds(correct_seeds, &program_id, &account.get_account_info()).is_ok() - ); - } - - // Test 2: Failed check - PDA doesn't match with the given seeds - { - // Generate a valid PDA - let seeds = &[b"test_seed".as_ref(), &[1, 2, 3]]; - let (_, bump) = Pubkey::find_program_address(seeds, &program_id); - let correct_seeds = &[b"test_seed".as_ref(), &[1, 2, 3], &[bump]]; - - // Create account with a different key - let different_key = create_pubkey(); - let mut account = TestAccount::new(different_key, program_id, size); - - // This should fail because the account key doesn't match the PDA - assert_eq!( - check_pda_seeds(correct_seeds, &program_id, &account.get_account_info()), - Err(AccountError::InvalidSeeds) - ); - } - - // Test 3: Invalid seeds - use seeds that would not create a valid program address - { - // Create a random account key - let random_key = create_pubkey(); - let mut account = TestAccount::new(random_key, program_id, size); - - // Create seeds that don't correspond to this account's key - let invalid_seeds = &[b"random_seeds".as_ref()]; - - // This should return InvalidSeeds because the derived address doesn't match - assert!( - check_pda_seeds(invalid_seeds, &program_id, &account.get_account_info()).is_err() - ); - } - } - - #[cfg(feature = "pinocchio")] - mod pinocchio_tests { - use super::*; - - #[test] - fn test_discriminator() { - // Test that the discriminator functionality works - let mut bytes = vec![0; 8 + 8]; // 8 for discriminator for a u64 - - // Check that setting and checking a discriminator works as expected - struct TestDiscriminator {} - impl Discriminator for TestDiscriminator { - const DISCRIMINATOR: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; - } - - assert_eq!(bytes[0..8], [0; 8]); - set_discriminator::(&mut bytes).unwrap(); - assert_eq!(bytes[0..8], TestDiscriminator::DISCRIMINATOR); - - // Check that trying to set it again fails - assert_eq!( - set_discriminator::(&mut bytes), - Err(AccountError::AlreadyInitialized) - ); - - // Check that validating works - assert!(check_discriminator::(&bytes).is_ok()); - - // Modify discriminator and check that validation fails - bytes[0] = 0; - assert_eq!( - check_discriminator::(&bytes), - Err(AccountError::InvalidDiscriminator) - ); - } - } - - #[cfg(feature = "pinocchio")] - fn test_check_pda_seeds_pinocchio() { - let program_id = create_pubkey(); - - // Test 1: Create a valid PDA and verify it - { - let seeds = &[b"test_seed".as_ref(), &[1, 2, 3]]; - // Generate a PDA - let (pda, _) = pinocchio::pubkey::find_program_address(seeds, &program_id); - - // Recreate the seeds for the check (without the bump) - let check_seeds = &[b"test_seed".as_ref(), &[1, 2, 3]]; - - // Create a test account with the PDA as key - let mut account = TestAccount::new(pda, program_id, 8); - - // This should fail because find_program_address adds the bump seed automatically - // which check_pda_seeds doesn't do - assert!( - check_pda_seeds(check_seeds, &program_id, &account.get_account_info()).is_err() - ); - - // Get the correct seeds with bump - let (_, bump) = pinocchio::pubkey::find_program_address(seeds, &program_id); - let correct_seeds = &[b"test_seed".as_ref(), &[1, 2, 3], &[bump]]; - // Now the check should pass with the correct seeds including bump - assert!( - check_pda_seeds(correct_seeds, &program_id, &account.get_account_info()).is_ok() - ); - } - - // Test 2: Failed check - PDA doesn't match with the given seeds - { - // Generate a valid PDA - let seeds = &[b"test_seed".as_ref(), &[1, 2, 3]]; - let (_, bump) = pinocchio::pubkey::find_program_address(seeds, &program_id); - let correct_seeds = &[b"test_seed".as_ref(), &[1, 2, 3], &[bump]]; - - // Create account with a different key - let different_key = create_pubkey(); - let mut account = TestAccount::new(different_key, program_id, 8); - - // This should fail because the account key doesn't match the PDA - assert_eq!( - check_pda_seeds(correct_seeds, &program_id, &account.get_account_info()), - Err(AccountError::InvalidSeeds) - ); - } - - // Test 3: Invalid seeds - use seeds that would not create a valid program address - { - // Create a random account key - let random_key = create_pubkey(); - let mut account = TestAccount::new(random_key, program_id, 8); - - // Create seeds that don't correspond to this account's key - let invalid_seeds = &[b"random_seeds".as_ref()]; - - // This should return InvalidSeeds because the derived address doesn't match - assert!( - check_pda_seeds(invalid_seeds, &program_id, &account.get_account_info()).is_err() - ); - } - } - - #[test] - pub fn test_check_data_is_zeroed() { - let zeroed_data = [0u8; 32]; - check_data_is_zeroed::<8>(zeroed_data.as_slice()).unwrap(); - let mut not_zeroed_data = [0u8; 32]; - not_zeroed_data[7] = 1; - let failing_res = check_data_is_zeroed::<8>(not_zeroed_data.as_slice()); - assert_eq!(failing_res, Err(AccountError::AccountNotZeroed)); - } -} diff --git a/program-libs/account-checks/src/error.rs b/program-libs/account-checks/src/error.rs index cd1f0ce3d7..35e4a5061a 100644 --- a/program-libs/account-checks/src/error.rs +++ b/program-libs/account-checks/src/error.rs @@ -54,8 +54,37 @@ impl From for u32 { } } -impl From for crate::ProgramError { +#[cfg(feature = "pinocchio")] +impl From for pinocchio::program_error::ProgramError { fn from(e: AccountError) -> Self { - crate::ProgramError::Custom(e.into()) + pinocchio::program_error::ProgramError::Custom(e.into()) + } +} + +#[cfg(feature = "solana")] +impl From for solana_program_error::ProgramError { + fn from(e: AccountError) -> Self { + solana_program_error::ProgramError::Custom(e.into()) + } +} + +#[cfg(feature = "pinocchio")] +impl From for AccountError { + fn from(_: pinocchio::program_error::ProgramError) -> Self { + AccountError::BorrowAccountDataFailed + } +} + +#[cfg(feature = "solana")] +impl From for AccountError { + fn from(_: std::cell::BorrowError) -> Self { + AccountError::BorrowAccountDataFailed + } +} + +#[cfg(feature = "solana")] +impl From for AccountError { + fn from(_: std::cell::BorrowMutError) -> Self { + AccountError::BorrowAccountDataFailed } } diff --git a/program-libs/account-checks/src/lib.rs b/program-libs/account-checks/src/lib.rs index 1c8d82a078..1a45262277 100644 --- a/program-libs/account-checks/src/lib.rs +++ b/program-libs/account-checks/src/lib.rs @@ -1,13 +1,6 @@ +pub mod account_info; pub mod checks; pub mod discriminator; pub mod error; -pub mod test_account_info; -#[cfg(feature = "pinocchio")] -use pinocchio::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey}; -#[cfg(all(feature = "pinocchio", target_os = "solana"))] -use pinocchio::{sysvars::rent::Rent, sysvars::Sysvar}; -#[cfg(all(not(feature = "pinocchio"), target_os = "solana"))] -use solana_sysvar::{rent::Rent, Sysvar}; -#[cfg(not(feature = "pinocchio"))] -use {solana_account_info::AccountInfo, solana_program_error::ProgramError, solana_pubkey::Pubkey}; +pub use account_info::account_info_trait::AccountInfoTrait; diff --git a/program-libs/batched-merkle-tree/Cargo.toml b/program-libs/batched-merkle-tree/Cargo.toml index 5bab3a96f6..92f98ba869 100644 --- a/program-libs/batched-merkle-tree/Cargo.toml +++ b/program-libs/batched-merkle-tree/Cargo.toml @@ -14,7 +14,6 @@ solana = [ "solana-account-info", "solana-sysvar", "solana-pubkey", - "solana-msg", "light-zero-copy/solana", "light-hasher/solana", "light-account-checks/solana", @@ -40,7 +39,7 @@ aligned-sized = { workspace = true } solana-program-error = { workspace = true, optional = true } solana-pubkey = { workspace = true, optional = true } solana-sysvar = { workspace = true, optional = true } -solana-msg = { workspace = true, optional = true } +solana-msg = { workspace = true } solana-account-info = { workspace = true, optional = true } light-zero-copy = { workspace = true, features = ["std"] } light-hasher = { workspace = true } diff --git a/program-libs/batched-merkle-tree/src/constants.rs b/program-libs/batched-merkle-tree/src/constants.rs index a34a362e07..d03c305057 100644 --- a/program-libs/batched-merkle-tree/src/constants.rs +++ b/program-libs/batched-merkle-tree/src/constants.rs @@ -1,11 +1,6 @@ // This file stores constants which do not have to be configured. -#[cfg(feature = "pinocchio")] -use light_macros::pubkey; -#[cfg(not(feature = "pinocchio"))] -use solana_pubkey::pubkey; - -use crate::Pubkey; +use light_macros::pubkey_array; pub const DEFAULT_BATCH_ADDRESS_TREE_HEIGHT: u32 = 40; @@ -31,7 +26,7 @@ pub const ADDRESS_TREE_INIT_ROOT_40: [u8; 32] = [ 25, 95, 124, 248, 129, 44, 109, 229, 146, 106, 76, ]; -pub const ACCOUNT_COMPRESSION_PROGRAM_ID: Pubkey = - pubkey!("compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq"); +pub const ACCOUNT_COMPRESSION_PROGRAM_ID: [u8; 32] = + pubkey_array!("compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq"); pub const NUM_BATCHES: usize = 2; diff --git a/program-libs/batched-merkle-tree/src/initialize_address_tree.rs b/program-libs/batched-merkle-tree/src/initialize_address_tree.rs index 1559788f7b..2acfab612b 100644 --- a/program-libs/batched-merkle-tree/src/initialize_address_tree.rs +++ b/program-libs/batched-merkle-tree/src/initialize_address_tree.rs @@ -1,13 +1,10 @@ -use light_account_checks::{checks::check_account_balance_is_rent_exempt, error::AccountError}; +use light_account_checks::{checks::check_account_balance_is_rent_exempt, AccountInfoTrait}; use light_compressed_account::{pubkey::Pubkey, TreeType}; use light_merkle_tree_metadata::{ access::AccessMetadata, fee::compute_rollover_fee, merkle_tree::MerkleTreeMetadata, rollover::RolloverMetadata, }; -// Import feature-gated types from lib.rs -#[cfg(not(feature = "pinocchio"))] -use crate::AccountInfoTrait; use crate::{ constants::{ DEFAULT_ADDRESS_ZKP_BATCH_SIZE, DEFAULT_BATCH_ADDRESS_TREE_HEIGHT, DEFAULT_BATCH_SIZE, @@ -16,7 +13,7 @@ use crate::{ errors::BatchedMerkleTreeError, initialize_state_tree::match_circuit_size, merkle_tree::{get_merkle_tree_account_size, BatchedMerkleTreeAccount}, - AccountInfo, BorshDeserialize, BorshSerialize, + BorshDeserialize, BorshSerialize, }; #[repr(C)] @@ -58,10 +55,10 @@ impl Default for InitAddressTreeAccountsInstructionData { /// Initializes a batched address Merkle tree account. /// 1. Check rent exemption and that accounts are initialized with the correct size. /// 2. Initialized the address Merkle tree account. -pub fn init_batched_address_merkle_tree_from_account_info( +pub fn init_batched_address_merkle_tree_from_account_info( params: InitAddressTreeAccountsInstructionData, owner: Pubkey, - mt_account_info: &AccountInfo, + mt_account_info: &A, ) -> Result<(), BatchedMerkleTreeError> { // 1. Check rent exemption and that accounts are initialized with the correct size. let mt_account_size = get_merkle_tree_account_size( @@ -73,15 +70,13 @@ pub fn init_batched_address_merkle_tree_from_account_info( ); let merkle_tree_rent = check_account_balance_is_rent_exempt(mt_account_info, mt_account_size)?; // 2. Initialized the address Merkle tree account. - let mt_data = &mut mt_account_info - .try_borrow_mut_data() - .map_err(|_| AccountError::BorrowAccountDataFailed)?; + let mt_data = &mut mt_account_info.try_borrow_mut_data()?; init_batched_address_merkle_tree_account( owner, params, mt_data, merkle_tree_rent, - (*mt_account_info.key()).into(), + mt_account_info.key().into(), )?; Ok(()) } diff --git a/program-libs/batched-merkle-tree/src/initialize_state_tree.rs b/program-libs/batched-merkle-tree/src/initialize_state_tree.rs index d87e640921..1b9e14b47a 100644 --- a/program-libs/batched-merkle-tree/src/initialize_state_tree.rs +++ b/program-libs/batched-merkle-tree/src/initialize_state_tree.rs @@ -1,13 +1,11 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use light_account_checks::checks::check_account_balance_is_rent_exempt; +use light_account_checks::{checks::check_account_balance_is_rent_exempt, AccountInfoTrait}; use light_compressed_account::{pubkey::Pubkey, QueueType, TreeType}; use light_merkle_tree_metadata::{ access::AccessMetadata, fee::compute_rollover_fee, merkle_tree::MerkleTreeMetadata, queue::QueueMetadata, rollover::RolloverMetadata, }; -#[cfg(not(feature = "pinocchio"))] -use crate::AccountInfoTrait; use crate::{ constants::{ DEFAULT_BATCH_SIZE, DEFAULT_BATCH_STATE_TREE_HEIGHT, DEFAULT_CPI_CONTEXT_ACCOUNT_SIZE, @@ -16,7 +14,6 @@ use crate::{ errors::BatchedMerkleTreeError, merkle_tree::{get_merkle_tree_account_size, BatchedMerkleTreeAccount}, queue::{get_output_queue_account_size, BatchedQueueAccount}, - AccountInfo, }; #[repr(C)] @@ -69,11 +66,11 @@ impl Default for InitStateTreeAccountsInstructionData { /// Initializes the state Merkle tree and output queue accounts. /// 1. Check rent exemption and that accounts are initialized with the correct size. /// 2. Initialize the output queue and state Merkle tree accounts. -pub fn init_batched_state_merkle_tree_from_account_info( +pub fn init_batched_state_merkle_tree_from_account_info( params: InitStateTreeAccountsInstructionData, - owner: crate::Pubkey, - merkle_tree_account_info: &AccountInfo, - queue_account_info: &AccountInfo, + owner: Pubkey, + merkle_tree_account_info: &A, + queue_account_info: &A, additional_bytes_rent: u64, ) -> Result<(), BatchedMerkleTreeError> { // 1. Check rent exemption and that accounts are initialized with the correct size. @@ -103,13 +100,13 @@ pub fn init_batched_state_merkle_tree_from_account_info( let mt_data = &mut merkle_tree_account_info.try_borrow_mut_data()?; init_batched_state_merkle_tree_accounts( - owner.into(), + owner, params, queue_data, - (*queue_account_info.key()).into(), + queue_account_info.key().into(), queue_rent, mt_data, - (*merkle_tree_account_info.key()).into(), + merkle_tree_account_info.key().into(), merkle_tree_rent, additional_bytes_rent, )?; diff --git a/program-libs/batched-merkle-tree/src/lib.rs b/program-libs/batched-merkle-tree/src/lib.rs index 78acdcbec5..429cad16a9 100644 --- a/program-libs/batched-merkle-tree/src/lib.rs +++ b/program-libs/batched-merkle-tree/src/lib.rs @@ -13,35 +13,3 @@ pub mod rollover_state_tree; // Use the appropriate BorshDeserialize and BorshSerialize based on feature use borsh::{BorshDeserialize, BorshSerialize}; -// Pinocchio imports when pinocchio feature is enabled -#[cfg(feature = "pinocchio")] -use pinocchio::{ - account_info::AccountInfo, msg, pubkey::Pubkey, sysvars::rent::Rent, sysvars::Sysvar, -}; -// Solana program imports for non-pinocchio builds (default) -#[cfg(not(feature = "pinocchio"))] -pub(crate) use { - solana_account_info::AccountInfo, - solana_msg::msg, - solana_pubkey::Pubkey, - solana_sysvar::{rent::Rent, Sysvar}, -}; - -#[allow(unused)] -trait AccountInfoTrait { - fn key(&self) -> &Pubkey; -} - -#[cfg(not(feature = "pinocchio"))] -impl AccountInfoTrait for AccountInfo<'_> { - fn key(&self) -> &Pubkey { - self.key - } -} - -#[cfg(not(feature = "pinocchio"))] -impl AccountInfoTrait for &AccountInfo<'_> { - fn key(&self) -> &Pubkey { - self.key - } -} diff --git a/program-libs/batched-merkle-tree/src/merkle_tree.rs b/program-libs/batched-merkle-tree/src/merkle_tree.rs index 7a853bb396..5028f756a1 100644 --- a/program-libs/batched-merkle-tree/src/merkle_tree.rs +++ b/program-libs/batched-merkle-tree/src/merkle_tree.rs @@ -3,6 +3,7 @@ use std::ops::{Deref, DerefMut}; use light_account_checks::{ checks::{check_account_info, set_discriminator}, discriminator::{Discriminator, DISCRIMINATOR_LEN}, + AccountInfoTrait, }; use light_compressed_account::{ hash_chain::create_hash_chain_from_array, hash_to_bn254_field_size_be, @@ -25,8 +26,6 @@ use light_zero_copy::{ use zerocopy::Ref; use super::batch::Batch; -#[cfg(not(feature = "pinocchio"))] -use crate::AccountInfoTrait; use crate::{ batch::BatchState, constants::{ACCOUNT_COMPRESSION_PROGRAM_ID, ADDRESS_TREE_INIT_ROOT_40, NUM_BATCHES}, @@ -36,7 +35,7 @@ use crate::{ deserialize_bloom_filter_stores, insert_into_current_queue_batch, BatchedQueueAccount, }, queue_batch_metadata::QueueBatches, - AccountInfo, BorshDeserialize, BorshSerialize, + BorshDeserialize, BorshSerialize, }; /// Public inputs: @@ -91,8 +90,8 @@ impl Discriminator for BatchedMerkleTreeAccount<'_> { impl<'a> BatchedMerkleTreeAccount<'a> { /// Checks state Merkle tree account and returns the root. - pub fn get_state_root_by_index( - account_info: &AccountInfo, + pub fn get_state_root_by_index( + account_info: &A, index: usize, ) -> Result<[u8; 32], BatchedMerkleTreeError> { let tree = Self::state_from_account_info(account_info)?; @@ -102,8 +101,8 @@ impl<'a> BatchedMerkleTreeAccount<'a> { } /// Checks address Merkle tree account and returns the root. - pub fn get_address_root_by_index( - account_info: &AccountInfo, + pub fn get_address_root_by_index( + account_info: &A, index: usize, ) -> Result<[u8; 32], BatchedMerkleTreeError> { let tree = Self::address_from_account_info(account_info)?; @@ -118,10 +117,10 @@ impl<'a> BatchedMerkleTreeAccount<'a> { /// 1. the program owner is the light account compression program, /// 2. discriminator, /// 3. tree type is batched state tree type. - pub fn state_from_account_info( - account_info: &AccountInfo, + pub fn state_from_account_info( + account_info: &A, ) -> Result, BatchedMerkleTreeError> { - Self::from_account_info::( + Self::from_account_info::( &ACCOUNT_COMPRESSION_PROGRAM_ID, account_info, ) @@ -145,26 +144,26 @@ impl<'a> BatchedMerkleTreeAccount<'a> { /// 1. the program owner is the light account compression program, /// 2. discriminator, /// 3. tree type is batched address tree type. - pub fn address_from_account_info( - account_info: &AccountInfo, + pub fn address_from_account_info( + account_info: &A, ) -> Result, BatchedMerkleTreeError> { - Self::from_account_info::( + Self::from_account_info::( &ACCOUNT_COMPRESSION_PROGRAM_ID, account_info, ) } - fn from_account_info( - program_id: &crate::Pubkey, - account_info: &AccountInfo, + fn from_account_info( + program_id: &[u8; 32], + account_info: &A, ) -> Result, BatchedMerkleTreeError> { - check_account_info::(program_id, account_info)?; + check_account_info::(program_id, account_info)?; let mut data = account_info.try_borrow_mut_data()?; // Necessary to convince the borrow checker. let data_slice: &'a mut [u8] = unsafe { std::slice::from_raw_parts_mut(data.as_mut_ptr(), data.len()) }; - Self::from_bytes::(data_slice, &(*account_info.key()).into()) + Self::from_bytes::(data_slice, &account_info.key().into()) } /// Deserialize a state BatchedMerkleTreeAccount from bytes. @@ -340,9 +339,9 @@ impl<'a> BatchedMerkleTreeAccount<'a> { /// 1. Checks that the tree and queue are associated. /// 2. Updates the tree with the output queue account. /// 3. Returns the batch append event. - pub fn update_tree_from_output_queue_account_info( + pub fn update_tree_from_output_queue_account_info( &mut self, - queue_account_info: &AccountInfo, + queue_account_info: &A, instruction_data: InstructionDataBatchAppendInputs, ) -> Result { if self.tree_type != TreeType::StateV2 as u64 { diff --git a/program-libs/batched-merkle-tree/src/queue.rs b/program-libs/batched-merkle-tree/src/queue.rs index c27acb08cb..a8dc0125a6 100644 --- a/program-libs/batched-merkle-tree/src/queue.rs +++ b/program-libs/batched-merkle-tree/src/queue.rs @@ -4,6 +4,7 @@ use aligned_sized::aligned_sized; use light_account_checks::{ checks::{check_account_info, set_discriminator}, discriminator::{Discriminator, DISCRIMINATOR_LEN}, + AccountInfoTrait, }; use light_compressed_account::{ hash_to_bn254_field_size_be, pubkey::Pubkey, QueueType, OUTPUT_STATE_QUEUE_TYPE_V2, @@ -14,14 +15,12 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref}; // Import the feature-gated types from lib.rs use super::batch::BatchState; -#[cfg(not(feature = "pinocchio"))] -use crate::AccountInfoTrait; use crate::{ batch::Batch, constants::{ACCOUNT_COMPRESSION_PROGRAM_ID, NUM_BATCHES}, errors::BatchedMerkleTreeError, queue_batch_metadata::QueueBatches, - AccountInfo, BorshDeserialize, BorshSerialize, + BorshDeserialize, BorshSerialize, }; #[repr(C)] @@ -145,11 +144,11 @@ impl<'a> BatchedQueueAccount<'a> { /// 1. the program owner is the light account compression program, /// 2. discriminator, /// 3. queue type is output queue type. - pub fn output_from_account_info( - account_info: &AccountInfo, + pub fn output_from_account_info( + account_info: &A, ) -> Result, BatchedMerkleTreeError> { - Self::from_account_info::( - &ACCOUNT_COMPRESSION_PROGRAM_ID, + Self::from_account_info::( + &Pubkey::new_from_array(ACCOUNT_COMPRESSION_PROGRAM_ID), account_info, ) } @@ -157,17 +156,17 @@ impl<'a> BatchedQueueAccount<'a> { /// Deserialize a BatchedQueueAccount from account info. /// Should be used in solana programs. /// Checks the program owner, discriminator and queue type. - fn from_account_info( - program_id: &crate::Pubkey, - account_info: &AccountInfo, + fn from_account_info( + program_id: &Pubkey, + account_info: &A, ) -> Result, BatchedMerkleTreeError> { - check_account_info::(program_id, account_info)?; + check_account_info::(&program_id.to_bytes(), account_info)?; let account_data = &mut account_info.try_borrow_mut_data()?; // Necessary to convince the borrow checker. let account_data: &'a mut [u8] = unsafe { std::slice::from_raw_parts_mut(account_data.as_mut_ptr(), account_data.len()) }; - Self::from_bytes::(account_data, (*account_info.key()).into()) + Self::from_bytes::(account_data, account_info.key().into()) } /// Deserialize a BatchedQueueAccount from bytes. @@ -335,11 +334,11 @@ impl<'a> BatchedQueueAccount<'a> { } else { #[cfg(target_os = "solana")] { - crate::msg!( - format!("Index found but value doesn't match leaf_index {} compressed account hash: {:?} expected compressed account hash {:?}. (If the expected element is [0u8;32] it was already spent. Other possibly causes, data hash, discriminator, leaf index, or Merkle tree mismatch.)", + solana_msg::msg!( + "Index found but value doesn't match leaf_index {} compressed account hash: {:?} expected compressed account hash {:?}. (If the expected element is [0u8;32] it was already spent. Other possibly causes, data hash, discriminator, leaf index, or Merkle tree mismatch.)", leaf_index, hash_chain_value,*element - ).as_str()); + ); } return Err(BatchedMerkleTreeError::InclusionProofByIndexFailed); } @@ -366,11 +365,11 @@ impl<'a> BatchedQueueAccount<'a> { if prove_by_index { #[cfg(target_os = "solana")] { - crate::msg!( - format!("leaf_index {} compressed account hash: {:?}. Possibly causes, leaf index, or Merkle tree mismatch.)", + solana_msg::msg!( + "leaf_index {} compressed account hash: {:?}. Possibly causes, leaf index, or Merkle tree mismatch.)", leaf_index, hash_chain_value - ).as_str()); + ); } Err(BatchedMerkleTreeError::InclusionProofByIndexFailed) } else { diff --git a/program-libs/batched-merkle-tree/src/queue_batch_metadata.rs b/program-libs/batched-merkle-tree/src/queue_batch_metadata.rs index 518ff0458d..bc644f669a 100644 --- a/program-libs/batched-merkle-tree/src/queue_batch_metadata.rs +++ b/program-libs/batched-merkle-tree/src/queue_batch_metadata.rs @@ -157,7 +157,6 @@ impl QueueBatches { /// Increment the next full batch index if current state is BatchState::Inserted. pub fn increment_pending_batch_index_if_inserted(&mut self, state: BatchState) { if state == BatchState::Inserted { - crate::msg!("Incrementing next full batch index"); self.pending_batch_index = (self.pending_batch_index + 1) % self.num_batches; } } diff --git a/program-libs/batched-merkle-tree/src/rollover_address_tree.rs b/program-libs/batched-merkle-tree/src/rollover_address_tree.rs index ec5f041e3d..420080db7d 100644 --- a/program-libs/batched-merkle-tree/src/rollover_address_tree.rs +++ b/program-libs/batched-merkle-tree/src/rollover_address_tree.rs @@ -1,13 +1,9 @@ -use light_account_checks::checks::check_account_balance_is_rent_exempt; +use light_account_checks::{checks::check_account_balance_is_rent_exempt, AccountInfoTrait}; use light_compressed_account::pubkey::Pubkey; #[cfg(target_os = "solana")] use light_merkle_tree_metadata::errors::MerkleTreeMetadataError; use light_merkle_tree_metadata::utils::if_equals_none; -// Import feature-gated types from lib.rs -use crate::AccountInfo; -#[cfg(not(feature = "pinocchio"))] -use crate::AccountInfoTrait; use crate::{ errors::BatchedMerkleTreeError, initialize_address_tree::{ @@ -16,9 +12,9 @@ use crate::{ merkle_tree::BatchedMerkleTreeAccount, rollover_state_tree::batched_tree_is_ready_for_rollover, }; -pub fn rollover_batched_address_tree_from_account_info( - old_account: &AccountInfo, - new_account: &AccountInfo, +pub fn rollover_batched_address_tree_from_account_info( + old_account: &A, + new_account: &A, network_fee: Option, ) -> Result { let new_mt_rent = check_account_balance_is_rent_exempt(new_account, old_account.data_len())?; @@ -32,7 +28,7 @@ pub fn rollover_batched_address_tree_from_account_info( &mut old_merkle_tree, &mut new_mt_data, new_mt_rent, - (*new_account.key()).into(), + new_account.key().into(), network_fee, )?; Ok(new_mt_rent) diff --git a/program-libs/batched-merkle-tree/src/rollover_state_tree.rs b/program-libs/batched-merkle-tree/src/rollover_state_tree.rs index 8b8cbfcd75..a1ce4380b0 100644 --- a/program-libs/batched-merkle-tree/src/rollover_state_tree.rs +++ b/program-libs/batched-merkle-tree/src/rollover_state_tree.rs @@ -1,19 +1,14 @@ -use light_account_checks::checks::check_account_balance_is_rent_exempt; +use light_account_checks::{checks::check_account_balance_is_rent_exempt, AccountInfoTrait}; use light_compressed_account::pubkey::Pubkey; use light_merkle_tree_metadata::{errors::MerkleTreeMetadataError, utils::if_equals_none}; -// Import the appropriately feature-gated types from lib.rs -#[cfg(not(feature = "pinocchio"))] -use crate::AccountInfoTrait; use crate::{ errors::BatchedMerkleTreeError, initialize_state_tree::{ init_batched_state_merkle_tree_accounts, InitStateTreeAccountsInstructionData, }, merkle_tree::BatchedMerkleTreeAccount, - msg, queue::BatchedQueueAccount, - AccountInfo, }; #[derive(Debug)] @@ -50,11 +45,11 @@ pub struct RolloverBatchStateTreeParams<'a> { /// additional bytes since those are the basis for the old trees rollover fee. /// If new additional_bytes is greater than old additional_bytes additional /// rent reimbursements need to be calculated outside of this function. -pub fn rollover_batched_state_tree_from_account_info( - old_state_merkle_tree: &AccountInfo, - new_state_merkle_tree: &AccountInfo, - old_output_queue: &AccountInfo, - new_output_queue: &AccountInfo, +pub fn rollover_batched_state_tree_from_account_info( + old_state_merkle_tree: &A, + new_state_merkle_tree: &A, + old_output_queue: &A, + new_output_queue: &A, additional_bytes: u64, network_fee: Option, ) -> Result { @@ -76,26 +71,25 @@ pub fn rollover_batched_state_tree_from_account_info( let queue_rent = check_account_balance_is_rent_exempt(new_output_queue, old_output_queue.data_len())?; - use crate::Sysvar; - let additional_bytes_rent = crate::Rent::get()?.minimum_balance( + let additional_bytes_rent = A::get_min_rent_balance( old_output_queue_account .metadata .rollover_metadata .additional_bytes as usize, - ); + )?; let new_mt_data = &mut new_state_merkle_tree.try_borrow_mut_data()?; let params = RolloverBatchStateTreeParams { old_merkle_tree: old_merkle_tree_account, - old_mt_pubkey: (*old_state_merkle_tree.key()).into(), + old_mt_pubkey: old_state_merkle_tree.key().into(), new_mt_data, new_mt_rent: merkle_tree_rent, - new_mt_pubkey: (*new_state_merkle_tree.key()).into(), + new_mt_pubkey: new_state_merkle_tree.key().into(), old_output_queue: old_output_queue_account, - old_queue_pubkey: (*old_output_queue.key()).into(), + old_queue_pubkey: old_output_queue.key().into(), new_output_queue_data: &mut new_output_queue.try_borrow_mut_data()?, new_output_queue_rent: queue_rent, - new_output_queue_pubkey: (*new_output_queue.key()).into(), + new_output_queue_pubkey: new_output_queue.key().into(), additional_bytes_rent, additional_bytes, network_fee, @@ -236,7 +230,8 @@ pub fn batched_tree_is_ready_for_rollover( return Err(MerkleTreeMetadataError::NotReadyForRollover.into()); } if metadata.metadata.rollover_metadata.network_fee == 0 && network_fee.is_some() { - msg!("Network fee must be 0 for manually forested trees."); + #[cfg(feature = "solana")] + solana_msg::msg!("Network fee must be 0 for manually forested trees."); return Err(BatchedMerkleTreeError::InvalidNetworkFee); } Ok(()) diff --git a/program-libs/compressed-account/Cargo.toml b/program-libs/compressed-account/Cargo.toml index 383069ef41..b26dbc107d 100644 --- a/program-libs/compressed-account/Cargo.toml +++ b/program-libs/compressed-account/Cargo.toml @@ -7,21 +7,10 @@ license = "Apache-2.0" edition = "2021" [features] -default = ["solana"] -solana = [ - "dep:solana-program-error", - "dep:solana-pubkey", - "light-hasher/solana", - "light-zero-copy/solana", - "light-macros/solana", -] -anchor = ["solana", "anchor-lang"] -pinocchio = [ - "dep:pinocchio", - "light-hasher/pinocchio", - "light-zero-copy/pinocchio", - "light-macros/pinocchio", -] +default = [] +solana = ["dep:solana-pubkey", "dep:solana-program-error"] +anchor = ["anchor-lang"] +pinocchio = ["dep:pinocchio"] bytemuck-des = ["bytemuck"] new-unique = ["dep:solana-pubkey"] @@ -31,14 +20,14 @@ zerocopy = { workspace = true, features = ["derive"] } light-hasher = { workspace = true } light-zero-copy = { workspace = true, features = ["std"] } light-macros = { workspace = true } +pinocchio = { workspace = true, optional = true } +solana-program-error = { workspace = true, optional = true } # Feature-gated dependencies -solana-program-error = { workspace = true, optional = true } -solana-pubkey = { workspace = true, optional = true, features = ["borsh"] } anchor-lang = { workspace = true, optional = true } -pinocchio = { workspace = true, optional = true } -bytemuck = { workspace = true, optional = true } +bytemuck = { workspace = true, optional = true, features = ["derive"] } borsh = { workspace = true } +solana-pubkey = { workspace = true, optional = true } [dev-dependencies] rand = { workspace = true } diff --git a/program-libs/compressed-account/src/constants.rs b/program-libs/compressed-account/src/constants.rs index 871790b4b5..0a0b17b69f 100644 --- a/program-libs/compressed-account/src/constants.rs +++ b/program-libs/compressed-account/src/constants.rs @@ -1,13 +1,11 @@ -#[cfg(feature = "pinocchio")] -use light_macros::pubkey; -#[cfg(not(feature = "pinocchio"))] -use solana_pubkey::pubkey; +use light_macros::pubkey_array; -pub const ACCOUNT_COMPRESSION_PROGRAM_ID: crate::Pubkey = - pubkey!("compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq"); -pub const SYSTEM_PROGRAM_ID: crate::Pubkey = pubkey!("SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7"); -pub const REGISTERED_PROGRAM_PDA: crate::Pubkey = - pubkey!("35hkDgaAKwMCaxRz2ocSZ6NaUrtKkyNqU6c4RV3tYJRh"); +pub const ACCOUNT_COMPRESSION_PROGRAM_ID: [u8; 32] = + pubkey_array!("compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq"); +pub const SYSTEM_PROGRAM_ID: [u8; 32] = + pubkey_array!("SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7"); +pub const REGISTERED_PROGRAM_PDA: [u8; 32] = + pubkey_array!("35hkDgaAKwMCaxRz2ocSZ6NaUrtKkyNqU6c4RV3tYJRh"); pub const CREATE_CPI_CONTEXT_ACCOUNT: [u8; 8] = [233, 112, 71, 66, 121, 33, 178, 188]; pub const ADDRESS_MERKLE_TREE_ACCOUNT_DISCRIMINATOR: [u8; 8] = [11, 161, 175, 9, 212, 229, 73, 73]; diff --git a/program-libs/compressed-account/src/indexer_event/event.rs b/program-libs/compressed-account/src/indexer_event/event.rs index 898ecdb4d3..097cd829d2 100644 --- a/program-libs/compressed-account/src/indexer_event/event.rs +++ b/program-libs/compressed-account/src/indexer_event/event.rs @@ -71,8 +71,8 @@ impl MerkleTreeSequenceNumber { impl From<&InstructionDataSequenceNumber> for MerkleTreeSequenceNumber { fn from(seq: &InstructionDataSequenceNumber) -> Self { Self { - tree_pubkey: seq.tree_pubkey.into(), - queue_pubkey: seq.queue_pubkey.into(), + tree_pubkey: seq.tree_pubkey, + queue_pubkey: seq.queue_pubkey, tree_type: seq.tree_type.into(), seq: seq.seq.into(), } diff --git a/program-libs/compressed-account/src/indexer_event/parse.rs b/program-libs/compressed-account/src/indexer_event/parse.rs index ecb57fb8b5..606d3ad283 100644 --- a/program-libs/compressed-account/src/indexer_event/parse.rs +++ b/program-libs/compressed-account/src/indexer_event/parse.rs @@ -405,7 +405,7 @@ fn deserialize_instruction<'a>( OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { address: x.address, - owner: data.invoking_program_id.into(), + owner: data.invoking_program_id, lamports: account.lamports, data: Some(CompressedAccountData { discriminator: account.discriminator, @@ -426,7 +426,7 @@ fn deserialize_instruction<'a>( PackedCompressedAccountWithMerkleContext { compressed_account: CompressedAccount { address: x.address, - owner: data.invoking_program_id.into(), + owner: data.invoking_program_id, lamports: account.lamports, data: Some(CompressedAccountData { discriminator: account.discriminator, @@ -632,7 +632,7 @@ fn create_nullifier_queue_indices( // 3. increment the sequence number internal_input_sequence_numbers.iter_mut().for_each(|seq| { for (i, merkle_tree_pubkey) in input_merkle_tree_pubkeys.iter().enumerate() { - if crate::pubkey::Pubkey::from(*merkle_tree_pubkey) == seq.tree_pubkey { + if *merkle_tree_pubkey == seq.tree_pubkey { nullifier_queue_indices[i] = seq.seq.into(); seq.seq += 1; } @@ -660,7 +660,7 @@ fn create_address_queue_indices( .iter_mut() .for_each(|seq| { for (i, merkle_tree_pubkey) in address_merkle_tree_pubkeys.iter().enumerate() { - if crate::pubkey::Pubkey::from(*merkle_tree_pubkey) == seq.tree_pubkey { + if *merkle_tree_pubkey == seq.tree_pubkey { address_queue_indices[i] = seq.seq.into(); seq.seq += 1; } diff --git a/program-libs/compressed-account/src/instruction_data/with_readonly.rs b/program-libs/compressed-account/src/instruction_data/with_readonly.rs index cb6da828d7..59b9c27bd7 100644 --- a/program-libs/compressed-account/src/instruction_data/with_readonly.rs +++ b/program-libs/compressed-account/src/instruction_data/with_readonly.rs @@ -130,7 +130,7 @@ impl InAccount { merkle_context: self.merkle_context, root_index: self.root_index, compressed_account: CompressedAccount { - owner: owner.into(), + owner, address: self.address, lamports: self.lamports, data: Some(CompressedAccountData { @@ -468,7 +468,7 @@ fn test_read_only_zero_copy() { }], output_compressed_accounts: vec![OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: Pubkey::default().into(), + owner: Pubkey::default(), lamports: 2000, address: Some([40; 32]), data: Some(CompressedAccountData { @@ -682,7 +682,7 @@ mod test { .map(|_| { OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: Pubkey::new_unique().into(), + owner: Pubkey::new_unique(), lamports: rng.gen(), address: if rng.gen() { Some(rng.gen()) } else { None }, data: if rng.gen() { diff --git a/program-libs/compressed-account/src/instruction_data/zero_copy.rs b/program-libs/compressed-account/src/instruction_data/zero_copy.rs index 23188088ce..b474110872 100644 --- a/program-libs/compressed-account/src/instruction_data/zero_copy.rs +++ b/program-libs/compressed-account/src/instruction_data/zero_copy.rs @@ -273,7 +273,7 @@ impl From<&ZCompressedAccount<'_>> for CompressedAccount { data_hash: *data.data_hash, }); CompressedAccount { - owner: crate::Pubkey::from(compressed_account.owner), + owner: compressed_account.owner, lamports: compressed_account.lamports.into(), address: compressed_account.address.map(|x| *x), data, @@ -1299,8 +1299,7 @@ pub mod test { let expected_owner: Pubkey = invoke_ref .input_compressed_accounts_with_merkle_context[0] .compressed_account - .owner - .into(); + .owner; assert_eq!(z_copy.owner(), expected_owner); } else { assert_eq!(z_copy.owner(), Pubkey::default()); @@ -1401,7 +1400,7 @@ pub mod test { reference: &CompressedAccount, z_copy: &ZCompressedAccount, ) -> Result<(), CompressedAccountError> { - if reference.owner != z_copy.owner.into() { + if reference.owner.to_bytes() != z_copy.owner.as_bytes() { return Err(CompressedAccountError::InvalidArgument); } if reference.lamports != u64::from(z_copy.lamports) { diff --git a/program-libs/compressed-account/src/lib.rs b/program-libs/compressed-account/src/lib.rs index db25f8e5fc..46bcf7fbad 100644 --- a/program-libs/compressed-account/src/lib.rs +++ b/program-libs/compressed-account/src/lib.rs @@ -16,6 +16,7 @@ pub mod nullifier; pub mod pubkey; pub mod tx_hash; +// Re-export Pubkey type #[cfg(feature = "anchor")] use anchor_lang::{AnchorDeserialize, AnchorSerialize}; #[cfg(not(feature = "anchor"))] @@ -24,16 +25,7 @@ pub use light_hasher::{ bigint::bigint_to_be_bytes_array, hash_to_field_size::{hash_to_bn254_field_size_be, hashv_to_bn254_field_size_be}, }; -// Pinocchio framework imports -#[cfg(feature = "pinocchio")] -pub(crate) use pinocchio::program_error::ProgramError; -#[cfg(feature = "pinocchio")] -pub(crate) use pinocchio::pubkey::Pubkey; -// Solana program imports (default framework) -#[cfg(not(feature = "pinocchio"))] -pub(crate) use solana_program_error::ProgramError; -#[cfg(not(feature = "pinocchio"))] -pub(crate) use solana_pubkey::Pubkey; +pub use pubkey::Pubkey; #[derive(Debug, Error, PartialEq)] pub enum CompressedAccountError { @@ -87,10 +79,17 @@ impl From for u32 { } } -// Convert compressed account errors to program errors for both frameworks -impl From for ProgramError { +#[cfg(feature = "solana")] +impl From for solana_program_error::ProgramError { + fn from(e: CompressedAccountError) -> Self { + solana_program_error::ProgramError::Custom(e.into()) + } +} + +#[cfg(feature = "pinocchio")] +impl From for pinocchio::program_error::ProgramError { fn from(e: CompressedAccountError) -> Self { - ProgramError::Custom(e.into()) + pinocchio::program_error::ProgramError::Custom(e.into()) } } diff --git a/program-libs/compressed-account/src/pubkey.rs b/program-libs/compressed-account/src/pubkey.rs index a5a218ff45..9dc74ea35f 100644 --- a/program-libs/compressed-account/src/pubkey.rs +++ b/program-libs/compressed-account/src/pubkey.rs @@ -11,6 +11,8 @@ use crate::{AnchorDeserialize, AnchorSerialize}; Debug, Copy, PartialEq, + Eq, + Hash, Clone, Immutable, FromBytes, @@ -62,6 +64,25 @@ impl AsRef for Pubkey { } } +impl AsRef<[u8]> for Pubkey { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +impl PartialEq<[u8; 32]> for Pubkey { + fn eq(&self, other: &[u8; 32]) -> bool { + self.0 == *other + } +} + +#[cfg(feature = "anchor")] +impl PartialEq for Pubkey { + fn eq(&self, other: &anchor_lang::prelude::Pubkey) -> bool { + self.0 == other.to_bytes() + } +} + impl<'a> Deserialize<'a> for Pubkey { type Output = Ref<&'a [u8], Pubkey>; @@ -94,16 +115,16 @@ impl From<&[u8; 32]> for Pubkey { } } -#[cfg(not(feature = "anchor"))] -impl From for solana_pubkey::Pubkey { - fn from(pubkey: Pubkey) -> Self { +#[cfg(feature = "anchor")] +impl From<&anchor_lang::prelude::Pubkey> for Pubkey { + fn from(pubkey: &anchor_lang::prelude::Pubkey) -> Self { Self::new_from_array(pubkey.to_bytes()) } } -#[cfg(not(feature = "anchor"))] -impl From<&Pubkey> for solana_pubkey::Pubkey { - fn from(pubkey: &Pubkey) -> Self { +#[cfg(feature = "anchor")] +impl From for Pubkey { + fn from(pubkey: anchor_lang::prelude::Pubkey) -> Self { Self::new_from_array(pubkey.to_bytes()) } } @@ -122,27 +143,8 @@ impl From<&Pubkey> for anchor_lang::prelude::Pubkey { } } -#[cfg(not(feature = "pinocchio"))] -impl From for Pubkey { - fn from(pubkey: crate::Pubkey) -> Self { - Self(pubkey.to_bytes()) - } -} - -#[cfg(not(feature = "pinocchio"))] -impl From<&crate::Pubkey> for Pubkey { - fn from(pubkey: &crate::Pubkey) -> Self { - Self(pubkey.to_bytes()) - } -} - impl Pubkey { - #[cfg(not(feature = "pinocchio"))] - pub fn new_unique() -> Self { - Self(solana_pubkey::Pubkey::new_unique().to_bytes()) - } - - #[cfg(all(feature = "pinocchio", feature = "new-unique"))] + #[cfg(feature = "new-unique")] pub fn new_unique() -> Self { Self(solana_pubkey::Pubkey::new_unique().to_bytes()) } @@ -152,14 +154,14 @@ impl Pubkey { } } -pub trait PubkeyTrait { - fn trait_to_bytes(&self) -> [u8; 32]; +pub trait AsPubkey { + fn to_pubkey_bytes(&self) -> [u8; 32]; #[cfg(feature = "anchor")] fn to_anchor_pubkey(&self) -> anchor_lang::prelude::Pubkey; } -impl PubkeyTrait for Pubkey { - fn trait_to_bytes(&self) -> [u8; 32] { +impl AsPubkey for Pubkey { + fn to_pubkey_bytes(&self) -> [u8; 32] { self.to_bytes() } #[cfg(feature = "anchor")] @@ -169,8 +171,8 @@ impl PubkeyTrait for Pubkey { } #[cfg(feature = "anchor")] -impl PubkeyTrait for anchor_lang::prelude::Pubkey { - fn trait_to_bytes(&self) -> [u8; 32] { +impl AsPubkey for anchor_lang::prelude::Pubkey { + fn to_pubkey_bytes(&self) -> [u8; 32] { self.to_bytes() } @@ -180,9 +182,19 @@ impl PubkeyTrait for anchor_lang::prelude::Pubkey { } } -#[cfg(not(feature = "anchor"))] -impl PubkeyTrait for solana_pubkey::Pubkey { - fn trait_to_bytes(&self) -> [u8; 32] { +#[cfg(all(feature = "solana", not(feature = "anchor")))] +impl AsPubkey for solana_pubkey::Pubkey { + fn to_pubkey_bytes(&self) -> [u8; 32] { self.to_bytes() } } + +impl AsPubkey for [u8; 32] { + fn to_pubkey_bytes(&self) -> [u8; 32] { + *self + } + #[cfg(feature = "anchor")] + fn to_anchor_pubkey(&self) -> anchor_lang::prelude::Pubkey { + (*self).into() + } +} diff --git a/program-libs/macros/src/lib.rs b/program-libs/macros/src/lib.rs index f0eb6010da..588850f086 100644 --- a/program-libs/macros/src/lib.rs +++ b/program-libs/macros/src/lib.rs @@ -15,6 +15,15 @@ pub fn pubkey(input: TokenStream) -> TokenStream { .into() } +/// Converts a base58 encoded public key into a raw byte array [u8; 32]. +#[proc_macro] +pub fn pubkey_array(input: TokenStream) -> TokenStream { + let args = parse_macro_input!(input as pubkey::PubkeyArgs); + pubkey::pubkey_array(args) + .unwrap_or_else(|err| err.to_compile_error()) + .into() +} + #[proc_macro_attribute] pub fn heap_neutral(_: TokenStream, input: TokenStream) -> TokenStream { let mut function = parse_macro_input!(input as ItemFn); diff --git a/program-libs/macros/src/pubkey.rs b/program-libs/macros/src/pubkey.rs index 18b60bf2ca..e54ccb1d76 100644 --- a/program-libs/macros/src/pubkey.rs +++ b/program-libs/macros/src/pubkey.rs @@ -34,19 +34,30 @@ pub(crate) fn pubkey(args: PubkeyArgs) -> Result { ) })?; - #[cfg(not(feature = "pinocchio"))] - return Ok(quote! { + Ok(quote! { ::solana_program::pubkey::Pubkey::new_from_array([ #(#arr),* ]) - }); + }) +} - #[cfg(feature = "pinocchio")] - return Ok(quote! { - [ #(#arr),* ] - }); - #[allow(unreachable_code)] - { - unimplemented!("Activate exactly one feature: solana (default) or pinocchio.") - } +pub(crate) fn pubkey_array(args: PubkeyArgs) -> Result { + let v = decode(args.pubkey.value()) + .into_vec() + .map_err(|_| Error::new(args.pubkey.span(), "Invalid base58 string"))?; + let v_len = v.len(); + + let arr: [u8; PUBKEY_LEN] = v.try_into().map_err(|_| { + Error::new( + args.pubkey.span(), + format!( + "Invalid size of decoded public key, expected 32, got {}", + v_len, + ), + ) + })?; + + Ok(quote! { + [ #(#arr),* ] + }) } #[cfg(test)] diff --git a/program-libs/merkle-tree-metadata/Cargo.toml b/program-libs/merkle-tree-metadata/Cargo.toml index 46ee548a1c..208ad9c75b 100644 --- a/program-libs/merkle-tree-metadata/Cargo.toml +++ b/program-libs/merkle-tree-metadata/Cargo.toml @@ -7,30 +7,26 @@ license = "Apache-2.0" edition = "2021" [features] -default = ["solana"] +default = [] solana = [ - "dep:solana-program-error", "dep:solana-msg", "dep:solana-sysvar", + "solana-program-error", "solana-sysvar/bincode", "light-compressed-account/solana", "light-compressed-account/bytemuck-des", ] anchor = ["solana", "anchor-lang"] -pinocchio = [ - "dep:pinocchio", - "light-compressed-account/pinocchio", - "light-compressed-account/bytemuck-des", -] +pinocchio = ["dep:pinocchio", "light-compressed-account/bytemuck-des"] [dependencies] thiserror = { workspace = true } bytemuck = { workspace = true, features = ["derive"] } zerocopy = { workspace = true, features = ["derive"] } light-compressed-account = { workspace = true, features = ["bytemuck-des"] } -solana-program-error = { workspace = true, optional = true } solana-msg = { workspace = true, optional = true } solana-sysvar = { workspace = true, optional = true } +solana-program-error = { workspace = true, optional = true } anchor-lang = { workspace = true, optional = true } pinocchio = { workspace = true, optional = true } borsh = { workspace = true } @@ -38,3 +34,5 @@ borsh = { workspace = true } [lints.rust.unexpected_cfgs] level = "allow" check-cfg = ['cfg(target_os, values("solana"))'] +[dev-dependencies] +light-compressed-account = { workspace = true, features = ["new-unique"] } diff --git a/program-libs/merkle-tree-metadata/src/errors.rs b/program-libs/merkle-tree-metadata/src/errors.rs index c05c22db4d..b2b2ad794f 100644 --- a/program-libs/merkle-tree-metadata/src/errors.rs +++ b/program-libs/merkle-tree-metadata/src/errors.rs @@ -38,8 +38,16 @@ impl From for u32 { } } -impl From for crate::ProgramError { +#[cfg(feature = "solana")] +impl From for solana_program_error::ProgramError { fn from(e: MerkleTreeMetadataError) -> Self { - crate::ProgramError::Custom(e.into()) + solana_program_error::ProgramError::Custom(e.into()) + } +} + +#[cfg(feature = "pinocchio")] +impl From for pinocchio::program_error::ProgramError { + fn from(e: MerkleTreeMetadataError) -> Self { + pinocchio::program_error::ProgramError::Custom(e.into()) } } diff --git a/program-libs/merkle-tree-metadata/src/lib.rs b/program-libs/merkle-tree-metadata/src/lib.rs index 8cff288627..d963637305 100644 --- a/program-libs/merkle-tree-metadata/src/lib.rs +++ b/program-libs/merkle-tree-metadata/src/lib.rs @@ -16,17 +16,3 @@ pub use light_compressed_account::{ NULLIFIER_QUEUE_TYPE_V1, OUTPUT_STATE_QUEUE_TYPE_V2, STATE_MERKLE_TREE_TYPE_V1, STATE_MERKLE_TREE_TYPE_V2, }; -// Pinocchio imports -#[allow(unused_imports)] -#[cfg(feature = "pinocchio")] -pub(crate) use pinocchio::{ - msg, program_error::ProgramError, sysvars::clock::Clock, sysvars::Sysvar, -}; -// Solana imports (default) -#[allow(unused_imports)] -#[cfg(not(feature = "pinocchio"))] -pub(crate) use { - solana_msg::msg, - solana_program_error::ProgramError, - solana_sysvar::{clock::Clock, Sysvar}, -}; diff --git a/program-libs/merkle-tree-metadata/src/rollover.rs b/program-libs/merkle-tree-metadata/src/rollover.rs index e64129fc0e..a2bf34d402 100644 --- a/program-libs/merkle-tree-metadata/src/rollover.rs +++ b/program-libs/merkle-tree-metadata/src/rollover.rs @@ -67,11 +67,18 @@ impl RolloverMetadata { if self.rolledover_slot != u64::MAX { return Err(MerkleTreeMetadataError::MerkleTreeAlreadyRolledOver); } - #[cfg(target_os = "solana")] { - use crate::{Clock, Sysvar}; - self.rolledover_slot = Clock::get().unwrap().slot; + #[cfg(feature = "pinocchio")] + { + use pinocchio::sysvars::{clock::Clock, Sysvar}; + self.rolledover_slot = Clock::get().unwrap().slot; + } + #[cfg(not(feature = "pinocchio"))] + { + use solana_sysvar::{clock::Clock, Sysvar}; + self.rolledover_slot = Clock::get().unwrap().slot; + } } #[cfg(not(target_os = "solana"))] { @@ -95,9 +102,9 @@ pub fn check_rollover_fee_sufficient( if (rollover_fee * rollover_threshold * (2u64.pow(height))) / 100 < queue_rent + merkle_tree_rent { - #[cfg(not(feature = "pinocchio"))] + #[cfg(feature = "solana")] { - use crate::msg; + use solana_msg::msg; msg!("rollover_fee: {}", rollover_fee); msg!("rollover_threshold: {}", rollover_threshold); msg!("height: {}", height); diff --git a/programs/account-compression/src/instructions/initialize_batched_state_merkle_tree.rs b/programs/account-compression/src/instructions/initialize_batched_state_merkle_tree.rs index ec444938fe..eccea83a51 100644 --- a/programs/account-compression/src/instructions/initialize_batched_state_merkle_tree.rs +++ b/programs/account-compression/src/instructions/initialize_batched_state_merkle_tree.rs @@ -59,7 +59,7 @@ pub fn process_initialize_batched_state_merkle_tree<'info>( let additional_bytes_rent = Rent::get()?.minimum_balance(params.additional_bytes as usize); init_batched_state_merkle_tree_from_account_info( params, - owner, + owner.into(), &merkle_tree_account_info, &queue_account_info, additional_bytes_rent, diff --git a/programs/account-compression/src/instructions/nullify_leaves.rs b/programs/account-compression/src/instructions/nullify_leaves.rs index 4f77fdec01..4e05f7ca83 100644 --- a/programs/account-compression/src/instructions/nullify_leaves.rs +++ b/programs/account-compression/src/instructions/nullify_leaves.rs @@ -106,7 +106,7 @@ fn insert_nullifier<'a, 'c: 'info, 'info>( { let merkle_tree = ctx.accounts.merkle_tree.load()?; - if merkle_tree.metadata.associated_queue != ctx.accounts.nullifier_queue.key().into() { + if merkle_tree.metadata.associated_queue != ctx.accounts.nullifier_queue.key() { msg!( "Merkle tree and nullifier queue are not associated. Merkle tree associated nullifier queue {:?} != nullifier queue {}", merkle_tree.metadata.associated_queue, diff --git a/programs/account-compression/src/instructions/resize_registered_program_account.rs b/programs/account-compression/src/instructions/resize_registered_program_account.rs index 9a113c4eb6..d7c2da4b8f 100644 --- a/programs/account-compression/src/instructions/resize_registered_program_account.rs +++ b/programs/account-compression/src/instructions/resize_registered_program_account.rs @@ -39,8 +39,11 @@ pub fn process_resize_registered_program_pda<'info>( if discriminator_bytes != RegisteredProgram::DISCRIMINATOR { return err!(anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch); } - light_account_checks::checks::check_owner(&crate::ID, &ctx.accounts.registered_program_pda) - .map_err(ProgramError::from)?; + light_account_checks::checks::check_owner( + &crate::ID.to_bytes(), + &ctx.accounts.registered_program_pda, + ) + .map_err(ProgramError::from)?; } let pre_account = RegisteredProgramV1::try_from_slice( &ctx.accounts.registered_program_pda.try_borrow_mut_data()?[8..], diff --git a/programs/account-compression/src/instructions/update_address_merkle_tree.rs b/programs/account-compression/src/instructions/update_address_merkle_tree.rs index 81587eecf2..6433b145be 100644 --- a/programs/account-compression/src/instructions/update_address_merkle_tree.rs +++ b/programs/account-compression/src/instructions/update_address_merkle_tree.rs @@ -56,7 +56,7 @@ pub fn process_update_address_merkle_tree<'info>( { let merkle_tree = ctx.accounts.merkle_tree.load_mut()?; - if merkle_tree.metadata.associated_queue != ctx.accounts.queue.key().into() { + if merkle_tree.metadata.associated_queue != ctx.accounts.queue.key() { msg!( "Merkle tree and nullifier queue are not associated. Merkle tree associated address queue {:?} != provided queue {}", merkle_tree.metadata.associated_queue, diff --git a/programs/account-compression/src/processor/insert_addresses.rs b/programs/account-compression/src/processor/insert_addresses.rs index ed4792b700..3b98e20f9b 100644 --- a/programs/account-compression/src/processor/insert_addresses.rs +++ b/programs/account-compression/src/processor/insert_addresses.rs @@ -136,7 +136,7 @@ fn process_address_v1<'info>( let queue_data = address_queue.try_borrow_data()?; let queue = bytemuck::from_bytes::(&queue_data[8..QueueAccount::LEN]); // 3. Check queue and Merkle tree are associated. - if queue.metadata.associated_merkle_tree != (*merkle_pubkey).into() { + if queue.metadata.associated_merkle_tree != *merkle_pubkey { msg!( "Queue account {:?} is not associated with Merkle tree {:?}", address_queue.key(), diff --git a/programs/account-compression/src/processor/insert_nullifiers.rs b/programs/account-compression/src/processor/insert_nullifiers.rs index 20ecaaf2ce..e4748c56ce 100644 --- a/programs/account-compression/src/processor/insert_nullifiers.rs +++ b/programs/account-compression/src/processor/insert_nullifiers.rs @@ -175,7 +175,7 @@ fn process_nullifiers_v1<'info>( // Discriminator is already checked in try_from_account_infos. let queue = bytemuck::from_bytes::(&queue_data[8..QueueAccount::LEN]); // 3. Check queue and Merkle tree are associated. - if queue.metadata.associated_merkle_tree != (*merkle_pubkey).into() { + if queue.metadata.associated_merkle_tree != *merkle_pubkey { msg!( "Queue account {:?} is not associated with Merkle tree {:?}", nullifier_queue.key(), diff --git a/programs/compressed-token/src/freeze.rs b/programs/compressed-token/src/freeze.rs index c016f571bb..0711906faa 100644 --- a/programs/compressed-token/src/freeze.rs +++ b/programs/compressed-token/src/freeze.rs @@ -184,7 +184,7 @@ fn create_token_output_accounts( }; output_compressed_accounts[i] = OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: crate::ID, + owner: crate::ID.into(), lamports: token_data_with_context.lamports.unwrap_or(0), data: Some(data), address: None, diff --git a/programs/compressed-token/src/process_mint.rs b/programs/compressed-token/src/process_mint.rs index c0aa0ecc38..e4bcfa60a4 100644 --- a/programs/compressed-token/src/process_mint.rs +++ b/programs/compressed-token/src/process_mint.rs @@ -2,7 +2,7 @@ use account_compression::program::AccountCompression; use anchor_lang::prelude::*; use anchor_spl::token_interface::{TokenAccount, TokenInterface}; use light_compressed_account::{ - instruction_data::data::OutputCompressedAccountWithPackedContext, pubkey::PubkeyTrait, + instruction_data::data::OutputCompressedAccountWithPackedContext, pubkey::AsPubkey, }; use light_system_program::program::LightSystemProgram; use light_zero_copy::num_trait::ZeroCopyNumTrait; @@ -37,7 +37,7 @@ pub const MINT_TO: bool = true; #[allow(unused_variables)] pub fn process_mint_to_or_compress<'info, const IS_MINT_TO: bool>( ctx: Context<'_, '_, '_, 'info, MintToInstruction<'info>>, - recipient_pubkeys: &[impl PubkeyTrait], + recipient_pubkeys: &[impl AsPubkey], amounts: &[impl ZeroCopyNumTrait], lamports: Option, index: Option, diff --git a/programs/compressed-token/src/process_transfer.rs b/programs/compressed-token/src/process_transfer.rs index 49d45cfbac..7ada7f8c3f 100644 --- a/programs/compressed-token/src/process_transfer.rs +++ b/programs/compressed-token/src/process_transfer.rs @@ -11,7 +11,7 @@ use light_compressed_account::{ data::OutputCompressedAccountWithPackedContext, with_readonly::{InAccount, InstructionDataInvokeCpiWithReadOnly}, }, - pubkey::PubkeyTrait, + pubkey::AsPubkey, }; use light_heap::{bench_sbf_end, bench_sbf_start}; use light_system_program::account_traits::{InvokeAccounts, SignerAccounts}; @@ -154,7 +154,7 @@ pub fn process_transfer<'a, 'b, 'c, 'info: 'b + 'c>( new_len, OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: ctx.accounts.authority.key(), + owner: ctx.accounts.authority.key().into(), lamports: change_lamports, data: None, address: None, @@ -189,8 +189,8 @@ pub const OUTPUT_QUEUE_DISCRIMINATOR: &[u8] = b"queueacc"; #[allow(clippy::too_many_arguments)] pub fn create_output_compressed_accounts( output_compressed_accounts: &mut [OutputCompressedAccountWithPackedContext], - mint_pubkey: impl PubkeyTrait, - pubkeys: &[impl PubkeyTrait], + mint_pubkey: impl AsPubkey, + pubkeys: &[impl AsPubkey], delegate: Option, is_delegate: Option>, amounts: &[impl ZeroCopyNumTrait], @@ -239,7 +239,7 @@ pub fn create_output_compressed_accounts( // TODO: remove serialization, just write bytes. token_data.serialize(&mut token_data_bytes).unwrap(); bench_sbf_start!("token_data_hash"); - let hashed_owner = hash_to_bn254_field_size_be(owner.trait_to_bytes().as_slice()); + let hashed_owner = hash_to_bn254_field_size_be(owner.to_pubkey_bytes().as_slice()); let mut amount_bytes = [0u8; 32]; let discriminator_bytes = @@ -287,7 +287,7 @@ pub fn create_output_compressed_accounts( sum_lamports += lamports.into(); output_compressed_accounts[i] = OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: crate::ID, + owner: crate::ID.into(), lamports: lamports.into(), data: Some(data), address: None, diff --git a/programs/registry/src/lib.rs b/programs/registry/src/lib.rs index 43e0b45449..eda4e62106 100644 --- a/programs/registry/src/lib.rs +++ b/programs/registry/src/lib.rs @@ -682,7 +682,7 @@ pub fn check_forester( return err!(RegistryError::InvalidNetworkFee); } Ok(()) - } else if metadata.access_metadata.forester == authority.into() { + } else if metadata.access_metadata.forester == authority { Ok(()) } else { err!(RegistryError::InvalidSigner) diff --git a/programs/system/src/accounts/init_context_account.rs b/programs/system/src/accounts/init_context_account.rs index 11fa39e30d..3cd4de928a 100644 --- a/programs/system/src/accounts/init_context_account.rs +++ b/programs/system/src/accounts/init_context_account.rs @@ -54,7 +54,7 @@ pub fn init_cpi_context_account(accounts: &[AccountInfo]) -> Result<()> { // 1. Check discriminator bytes are zeroed. // 2. Set discriminator. - account_info_init::(ctx.cpi_context_account)?; + account_info_init::(ctx.cpi_context_account)?; let mut cpi_context_account_data = ctx.cpi_context_account.try_borrow_mut_data()?; let cpi_context_account = CpiContextAccount { diff --git a/programs/system/src/context.rs b/programs/system/src/context.rs index 7c7bc531ae..3a80014d3f 100644 --- a/programs/system/src/context.rs +++ b/programs/system/src/context.rs @@ -336,7 +336,7 @@ impl<'a, T: InstructionData<'a>> WrappedInstructionData<'a, T> { } let input_account = PackedCompressedAccountWithMerkleContext { compressed_account: CompressedAccount { - owner: input.owner().into(), + owner: *input.owner(), lamports: input.lamports(), address: input.address(), data: input.data(), @@ -356,7 +356,7 @@ impl<'a, T: InstructionData<'a>> WrappedInstructionData<'a, T> { } let output_account = OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: output.owner().into(), + owner: output.owner(), lamports: output.lamports(), address: output.address(), data: output.data(), diff --git a/programs/system/src/invoke_cpi/process_cpi_context.rs b/programs/system/src/invoke_cpi/process_cpi_context.rs index ecb2a7b8c3..f3eba721d8 100644 --- a/programs/system/src/invoke_cpi/process_cpi_context.rs +++ b/programs/system/src/invoke_cpi/process_cpi_context.rs @@ -188,7 +188,7 @@ fn validate_cpi_context_associated_with_merkle_tree<'a, 'info, T: InstructionDat return Err(SystemProgramError::NoInputs.into()); }; - if *cpi_context_account.associated_merkle_tree != first_merkle_tree_pubkey.into() { + if *cpi_context_account.associated_merkle_tree != first_merkle_tree_pubkey.to_pubkey_bytes() { msg!(format!( "first_merkle_tree_pubkey {:?} != associated_merkle_tree {:?}", first_merkle_tree_pubkey, cpi_context_account.associated_merkle_tree diff --git a/programs/system/src/lib.rs b/programs/system/src/lib.rs index f673f89605..64c7ab3119 100644 --- a/programs/system/src/lib.rs +++ b/programs/system/src/lib.rs @@ -21,7 +21,7 @@ use light_compressed_account::instruction_data::{ with_readonly::InstructionDataInvokeCpiWithReadOnly, zero_copy::{ZInstructionDataInvoke, ZInstructionDataInvokeCpi}, }; -use light_macros::pubkey; +use light_macros::pubkey_array; use light_zero_copy::borsh::Deserialize; use pinocchio::{ account_info::AccountInfo, msg, program_error::ProgramError, pubkey::Pubkey, ProgramResult, @@ -31,7 +31,7 @@ use crate::{ invoke::verify_signer::input_compressed_accounts_signer_check, processor::process::process, }; -pub const ID: Pubkey = pubkey!("SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7"); +pub const ID: Pubkey = pubkey_array!("SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7"); #[cfg(not(feature = "no-entrypoint"))] solana_security_txt::security_txt! { diff --git a/programs/system/src/processor/create_address_cpi_data.rs b/programs/system/src/processor/create_address_cpi_data.rs index ee4a28a947..56558ab07c 100644 --- a/programs/system/src/processor/create_address_cpi_data.rs +++ b/programs/system/src/processor/create_address_cpi_data.rs @@ -37,7 +37,7 @@ pub fn derive_new_addresses<'info, 'a, 'b: 'a, const ADDRESS_ASSIGNMENT: bool>( ); ( - derive_address_legacy(&pubkey.into(), &new_address_params.seed()) + derive_address_legacy(pubkey, &new_address_params.seed()) .map_err(ProgramError::from)?, context .get_legacy_merkle_context(new_address_params.address_queue_index()) From 7f94448cd5c6e381b4f51c6cfdf544246d41332c Mon Sep 17 00:00:00 2001 From: ananas-block Date: Wed, 11 Jun 2025 04:34:48 +0100 Subject: [PATCH 2/4] chore: fix tests and sdks --- .github/workflows/rust.yml | 18 +- Cargo.lock | 2 - examples/anchor/counter/src/lib.rs | 15 +- examples/anchor/counter/tests/test.rs | 2 +- examples/anchor/token-escrow/Cargo.toml | 1 + .../src/escrow_with_compressed_pda/escrow.rs | 9 +- .../src/escrow_with_compressed_pda/sdk.rs | 6 +- .../escrow_with_compressed_pda/withdrawal.rs | 14 +- .../token-escrow/src/escrow_with_pda/sdk.rs | 2 +- examples/anchor/token-escrow/tests/test.rs | 10 +- .../token-escrow/tests/test_compressed_pda.rs | 82 +- .../src/instructions/address_batch_update.rs | 4 +- forester/tests/address_v2_test.rs | 23 +- .../tests/batched_state_async_indexer_test.rs | 20 +- program-libs/account-checks/Cargo.toml | 4 +- .../{ => account_info}/test_account_info.rs | 0 .../account-checks/tests/account_info.rs | 493 ++++++++++ program-libs/account-checks/tests/tests.rs | 845 ++++++++++++++++++ program-libs/batched-merkle-tree/src/batch.rs | 13 +- .../src/initialize_address_tree.rs | 8 +- .../src/initialize_state_tree.rs | 4 +- .../batched-merkle-tree/src/merkle_tree.rs | 12 +- program-libs/batched-merkle-tree/src/queue.rs | 12 +- .../tests/account_access.rs | 24 +- program-libs/bloom-filter/src/lib.rs | 4 +- .../concurrent-merkle-tree/Cargo.toml | 14 +- .../concurrent-merkle-tree/src/errors.rs | 5 +- program-libs/hasher/Cargo.toml | 2 +- program-libs/hasher/src/errors.rs | 13 +- program-libs/hasher/src/hash_to_field_size.rs | 4 +- program-libs/hasher/src/lib.rs | 5 - .../indexed-merkle-tree/src/errors.rs | 2 +- program-libs/verifier/Cargo.toml | 2 +- program-libs/verifier/src/lib.rs | 8 +- .../tests/address_merkle_tree_tests.rs | 8 +- .../tests/merkle_tree_tests.rs | 17 +- .../client-test/tests/light_client.rs | 6 +- .../client-test/tests/light_program_test.rs | 6 +- .../compressed-token-test/tests/test.rs | 97 +- .../src/create_pda.rs | 6 +- program-tests/e2e-test/tests/test.rs | 25 +- program-tests/registry-test/tests/tests.rs | 24 +- .../programs/sdk-anchor-test/src/lib.rs | 6 +- program-tests/sdk-test/src/create_pda.rs | 7 +- program-tests/sdk-test/src/update_pda.rs | 3 +- program-tests/sdk-test/tests/test.rs | 4 +- program-tests/system-cpi-test/Cargo.toml | 2 +- .../system-cpi-test/src/create_pda.rs | 13 +- .../src/invalidate_not_owned_account.rs | 4 +- program-tests/system-cpi-test/src/sdk.rs | 9 +- program-tests/system-cpi-test/tests/test.rs | 72 +- .../tests/test_program_owned_trees.rs | 14 +- .../system-cpi-v2-test/tests/event.rs | 140 +-- .../tests/invoke_cpi_with_read_only.rs | 164 ++-- program-tests/system-test/tests/test.rs | 169 ++-- .../utils/src/assert_compressed_tx.rs | 15 +- program-tests/utils/src/assert_merkle_tree.rs | 24 +- program-tests/utils/src/assert_rollover.rs | 17 +- program-tests/utils/src/assert_token_tx.rs | 5 +- .../utils/src/batched_address_tree.rs | 8 +- .../src/create_address_test_program_sdk.rs | 13 +- program-tests/utils/src/e2e_test_env.rs | 67 +- program-tests/utils/src/lib.rs | 1 + program-tests/utils/src/pack.rs | 228 +++++ program-tests/utils/src/spl.rs | 39 +- program-tests/utils/src/system_program.rs | 76 +- programs/compressed-token/src/freeze.rs | 2 +- programs/compressed-token/src/process_mint.rs | 4 +- .../compressed-token/src/process_transfer.rs | 13 +- programs/system/src/errors.rs | 1 - programs/system/src/invoke/verify_signer.rs | 4 +- .../src/invoke_cpi/process_cpi_context.rs | 11 +- programs/system/src/processor/sum_check.rs | 4 +- .../system/tests/invoke_cpi_instruction.rs | 2 +- .../tests/invoke_cpi_instruction_small.rs | 2 +- scripts/format.sh | 5 +- scripts/lint.sh | 5 +- sdk-libs/client/src/indexer/types.rs | 16 +- sdk-libs/client/src/rpc/client.rs | 24 +- sdk-libs/macros/Cargo.toml | 2 +- sdk-libs/macros/src/discriminator.rs | 2 +- .../program-test/src/indexer/test_indexer.rs | 59 +- sdk-libs/program-test/src/program_test/rpc.rs | 32 +- .../src/utils/setup_light_programs.rs | 33 +- sdk-libs/sdk/Cargo.toml | 14 +- sdk-libs/sdk/src/account.rs | 2 +- sdk-libs/sdk/src/account_info.rs | 4 +- sdk-libs/sdk/src/address.rs | 8 +- sdk-libs/sdk/src/instruction/tree_info.rs | 12 +- sdk-libs/sdk/src/lib.rs | 3 +- 90 files changed, 2490 insertions(+), 745 deletions(-) rename program-libs/account-checks/src/{ => account_info}/test_account_info.rs (100%) create mode 100644 program-libs/account-checks/tests/account_info.rs create mode 100644 program-libs/account-checks/tests/tests.rs create mode 100644 program-tests/utils/src/pack.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 046a636d7d..62775c9ba6 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -45,16 +45,16 @@ jobs: light-verifier light-merkle-tree-metadata light-zero-copy light-hash-set light-indexed-merkle-tree light-batched-merkle-tree test_cmd: | cargo test -p aligned-sized - cargo test -p light-bloom-filter - cargo test -p light-hasher - cargo test -p light-compressed-account - cargo test -p light-account-checks - cargo test -p light-verifier - cargo test -p light-merkle-tree-metadata + cargo test -p light-bloom-filter --all-features + cargo test -p light-hasher --all-features + cargo test -p light-compressed-account --all-features + cargo test -p light-account-checks --all-features + cargo test -p light-verifier --all-features + cargo test -p light-merkle-tree-metadata --all-features cargo test -p light-zero-copy --features std - cargo test -p light-hash-set - cargo test -p light-indexed-merkle-tree - cargo test -p light-batched-merkle-tree --features test-only -- --test test_e2e + cargo test -p light-hash-set --all-features + cargo test -p light-indexed-merkle-tree --all-features + cargo test -p light-batched-merkle-tree --all-features -- --test test_e2e - name: sdk-libs packages: light-macros light-sdk light-program-test light-client light-batched-merkle-tree test_cmd: | diff --git a/Cargo.lock b/Cargo.lock index ec82eb694a..e897b5e994 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3629,7 +3629,6 @@ dependencies = [ "light-hasher", "light-macros", "light-sdk-macros", - "light-verifier", "num-bigint 0.4.6", "solana-account-info", "solana-cpi", @@ -3644,7 +3643,6 @@ dependencies = [ name = "light-sdk-macros" version = "0.6.0" dependencies = [ - "ark-bn254 0.5.0", "borsh 0.10.4", "light-compressed-account", "light-hasher", diff --git a/examples/anchor/counter/src/lib.rs b/examples/anchor/counter/src/lib.rs index fc4b4c28ed..f0b26e4670 100644 --- a/examples/anchor/counter/src/lib.rs +++ b/examples/anchor/counter/src/lib.rs @@ -25,7 +25,6 @@ pub mod counter { address_tree_info: PackedAddressTreeInfo, output_state_tree_index: u8, ) -> Result<()> { - let program_id = crate::ID.into(); // LightAccount::new_init will create an account with empty output state (no input state). // Modifying the account will modify the output state that when converted to_account_info() // is hashed with poseidon hashes, serialized with borsh @@ -49,7 +48,7 @@ pub mod counter { let new_address_params = address_tree_info.into_new_address_params_packed(address_seed); let mut counter = LightAccount::<'_, CounterAccount>::new_init( - &program_id, + &crate::ID, Some(address), output_state_tree_index, ); @@ -74,7 +73,6 @@ pub mod counter { counter_value: u64, account_meta: CompressedAccountMeta, ) -> Result<()> { - let program_id = crate::ID.into(); // LightAccount::new_mut will create an account with input state and output state. // The input state is hashed immediately when calling new_mut(). // Modifying the account will modify the output state that when converted to_account_info() @@ -82,7 +80,7 @@ pub mod counter { // and created with invoke_light_system_program by invoking the light-system-program. // The hashing scheme is the account structure derived with LightHasher. let mut counter = LightAccount::<'_, CounterAccount>::new_mut( - &program_id, + &crate::ID, &account_meta, CounterAccount { owner: ctx.accounts.signer.key(), @@ -116,9 +114,8 @@ pub mod counter { counter_value: u64, account_meta: CompressedAccountMeta, ) -> Result<()> { - let program_id = crate::ID.into(); let mut counter = LightAccount::<'_, CounterAccount>::new_mut( - &program_id, + &crate::ID, &account_meta, CounterAccount { owner: ctx.accounts.signer.key(), @@ -158,9 +155,8 @@ pub mod counter { counter_value: u64, account_meta: CompressedAccountMeta, ) -> Result<()> { - let program_id = crate::ID.into(); let mut counter = LightAccount::<'_, CounterAccount>::new_mut( - &program_id, + &crate::ID, &account_meta, CounterAccount { owner: ctx.accounts.signer.key(), @@ -195,12 +191,11 @@ pub mod counter { counter_value: u64, account_meta: CompressedAccountMetaClose, ) -> Result<()> { - let program_id = crate::ID.into(); // LightAccount::new_close() will create an account with only input state and no output state. // By providing no output state the account is closed after the instruction. // The address of a closed account cannot be reused. let counter = LightAccount::<'_, CounterAccount>::new_close( - &program_id, + &crate::ID, &account_meta, CounterAccount { owner: ctx.accounts.signer.key(), diff --git a/examples/anchor/counter/tests/test.rs b/examples/anchor/counter/tests/test.rs index f9843fb04e..ea5da12d73 100644 --- a/examples/anchor/counter/tests/test.rs +++ b/examples/anchor/counter/tests/test.rs @@ -1,4 +1,4 @@ -// #![cfg(feature = "test-sbf")] +#![cfg(feature = "test-sbf")] use anchor_lang::{AnchorDeserialize, InstructionData, ToAccountMetas}; use counter::CounterAccount; diff --git a/examples/anchor/token-escrow/Cargo.toml b/examples/anchor/token-escrow/Cargo.toml index 000cb05147..24b8311f74 100644 --- a/examples/anchor/token-escrow/Cargo.toml +++ b/examples/anchor/token-escrow/Cargo.toml @@ -30,6 +30,7 @@ light-compressed-account = { workspace = true, features = ["anchor"] } [target.'cfg(not(target_os = "solana"))'.dependencies] solana-sdk = { workspace = true } +light-test-utils = { workspace = true, features = ["devenv"] } [dev-dependencies] light-verifier = { workspace = true } diff --git a/examples/anchor/token-escrow/src/escrow_with_compressed_pda/escrow.rs b/examples/anchor/token-escrow/src/escrow_with_compressed_pda/escrow.rs index 8368276f10..88f3c33619 100644 --- a/examples/anchor/token-escrow/src/escrow_with_compressed_pda/escrow.rs +++ b/examples/anchor/token-escrow/src/escrow_with_compressed_pda/escrow.rs @@ -161,19 +161,18 @@ fn create_compressed_pda_data( let compressed_account_data = CompressedAccountData { discriminator: 1u64.to_le_bytes(), data: timelock_compressed_pda.try_to_vec().unwrap(), - data_hash: timelock_compressed_pda - .hash::() - .map_err(ProgramError::from)?, + data_hash: timelock_compressed_pda.hash::().unwrap(), }; let derive_address = derive_address_legacy( &ctx.remaining_accounts[new_address_params.address_merkle_tree_account_index as usize] - .key(), + .key() + .into(), &new_address_params.seed, ) .map_err(|_| ProgramError::InvalidArgument)?; Ok(OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: crate::ID, + owner: crate::ID.into(), lamports: 0, address: Some(derive_address), data: Some(compressed_account_data), diff --git a/examples/anchor/token-escrow/src/escrow_with_compressed_pda/sdk.rs b/examples/anchor/token-escrow/src/escrow_with_compressed_pda/sdk.rs index 2c47133b44..de69bf115d 100644 --- a/examples/anchor/token-escrow/src/escrow_with_compressed_pda/sdk.rs +++ b/examples/anchor/token-escrow/src/escrow_with_compressed_pda/sdk.rs @@ -2,8 +2,7 @@ use anchor_lang::{InstructionData, ToAccountMetas}; use light_compressed_account::{ - address::{add_and_get_remaining_account_indices, pack_new_address_params}, - compressed_account::{pack_merkle_context, CompressedAccount, MerkleContext}, + compressed_account::{CompressedAccount, MerkleContext}, instruction_data::{ compressed_proof::CompressedProof, cpi_context::CompressedCpiContext, data::NewAddressParams, @@ -14,6 +13,9 @@ use light_compressed_token::process_transfer::{ transfer_sdk::{create_inputs_and_remaining_accounts_checked, to_account_metas}, TokenTransferOutputData, }; +use light_test_utils::pack::{ + add_and_get_remaining_account_indices, pack_merkle_context, pack_new_address_params, +}; use solana_sdk::{instruction::Instruction, pubkey::Pubkey}; use crate::escrow_with_compressed_pda::escrow::PackedInputCompressedPda; diff --git a/examples/anchor/token-escrow/src/escrow_with_compressed_pda/withdrawal.rs b/examples/anchor/token-escrow/src/escrow_with_compressed_pda/withdrawal.rs index 1cd91746e2..8b92845cdc 100644 --- a/examples/anchor/token-escrow/src/escrow_with_compressed_pda/withdrawal.rs +++ b/examples/anchor/token-escrow/src/escrow_with_compressed_pda/withdrawal.rs @@ -83,13 +83,11 @@ fn create_compressed_pda_data_based_on_diff( let old_compressed_account_data = CompressedAccountData { discriminator: 1u64.to_le_bytes(), data: old_timelock_compressed_pda.try_to_vec().unwrap(), - data_hash: old_timelock_compressed_pda - .hash::() - .map_err(ProgramError::from)?, + data_hash: old_timelock_compressed_pda.hash::().unwrap(), }; let old_compressed_account = OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: crate::ID, + owner: crate::ID.into(), lamports: 0, address: Some(input_compressed_pda.address), data: Some(old_compressed_account_data), @@ -110,13 +108,11 @@ fn create_compressed_pda_data_based_on_diff( let new_compressed_account_data = CompressedAccountData { discriminator: 1u64.to_le_bytes(), data: new_timelock_compressed_pda.try_to_vec().unwrap(), - data_hash: new_timelock_compressed_pda - .hash::() - .map_err(ProgramError::from)?, + data_hash: new_timelock_compressed_pda.hash::().unwrap(), }; let new_state = OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: crate::ID, + owner: crate::ID.into(), lamports: 0, address: Some(input_compressed_pda.address), data: Some(new_compressed_account_data), @@ -171,7 +167,7 @@ fn cpi_compressed_pda_withdrawal<'info>( }, ) .unwrap(); - verify_borsh(&light_accounts, &inputs_struct).map_err(ProgramError::from)?; + verify_borsh(&light_accounts, &inputs_struct).unwrap(); Ok(()) } diff --git a/examples/anchor/token-escrow/src/escrow_with_pda/sdk.rs b/examples/anchor/token-escrow/src/escrow_with_pda/sdk.rs index 9b51add9b7..724c07f8b8 100644 --- a/examples/anchor/token-escrow/src/escrow_with_pda/sdk.rs +++ b/examples/anchor/token-escrow/src/escrow_with_pda/sdk.rs @@ -2,7 +2,6 @@ use anchor_lang::{InstructionData, ToAccountMetas}; use light_compressed_account::{ - address::add_and_get_remaining_account_indices, compressed_account::{CompressedAccount, MerkleContext}, instruction_data::compressed_proof::CompressedProof, }; @@ -14,6 +13,7 @@ use light_compressed_token::process_transfer::{ }, TokenTransferOutputData, }; +use light_test_utils::pack::add_and_get_remaining_account_indices; use solana_sdk::{instruction::Instruction, pubkey::Pubkey}; use crate::escrow_with_compressed_pda::sdk::get_token_owner_pda; diff --git a/examples/anchor/token-escrow/tests/test.rs b/examples/anchor/token-escrow/tests/test.rs index 8d04e86249..732a0673d0 100644 --- a/examples/anchor/token-escrow/tests/test.rs +++ b/examples/anchor/token-escrow/tests/test.rs @@ -195,8 +195,8 @@ pub async fn perform_escrow( leaf_index: compressed_input_account_with_context .merkle_context .leaf_index, - merkle_tree_pubkey: env.v1_state_trees[0].merkle_tree, - queue_pubkey: env.v1_state_trees[0].nullifier_queue, + merkle_tree_pubkey: env.v1_state_trees[0].merkle_tree.into(), + queue_pubkey: env.v1_state_trees[0].nullifier_queue.into(), prove_by_index: false, tree_type: TreeType::StateV1, }], @@ -331,8 +331,8 @@ pub async fn perform_withdrawal( leaf_index: compressed_input_account_with_context .merkle_context .leaf_index, - merkle_tree_pubkey: env.v1_state_trees[0].merkle_tree, - queue_pubkey: env.v1_state_trees[0].nullifier_queue, + merkle_tree_pubkey: env.v1_state_trees[0].merkle_tree.into(), + queue_pubkey: env.v1_state_trees[0].nullifier_queue.into(), prove_by_index: false, tree_type: TreeType::StateV1, }], @@ -369,7 +369,7 @@ pub async fn perform_withdrawal_failing( ) -> Result { let instruction = perform_withdrawal(rpc, payer, withdrawal_amount, invalid_signer).await; - rpc.create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer]) + rpc.create_and_send_transaction(&[instruction], &payer.pubkey(), &[payer]) .await } pub fn assert_withdrawal( diff --git a/examples/anchor/token-escrow/tests/test_compressed_pda.rs b/examples/anchor/token-escrow/tests/test_compressed_pda.rs index ea76e14617..4a481db315 100644 --- a/examples/anchor/token-escrow/tests/test_compressed_pda.rs +++ b/examples/anchor/token-escrow/tests/test_compressed_pda.rs @@ -191,7 +191,8 @@ async fn create_escrow_ix( .clone(); let input_compressed_account_hash = compressed_input_account_with_context.hash().unwrap(); - let address = derive_address_legacy(&env.v1_address_trees[0].merkle_tree, &seed).unwrap(); + let address = + derive_address_legacy(&env.v1_address_trees[0].merkle_tree.into(), &seed).unwrap(); let rpc_result = rpc .get_validity_proof( @@ -207,8 +208,8 @@ async fn create_escrow_ix( let new_address_params = NewAddressParams { seed, - address_merkle_tree_pubkey: env.v1_address_trees[0].merkle_tree, - address_queue_pubkey: env.v1_address_trees[0].queue, + address_merkle_tree_pubkey: env.v1_address_trees[0].merkle_tree.into(), + address_queue_pubkey: env.v1_address_trees[0].queue.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], }; let create_ix_inputs = CreateCompressedPdaEscrowInstructionInputs { @@ -221,8 +222,8 @@ async fn create_escrow_ix( leaf_index: compressed_input_account_with_context .merkle_context .leaf_index, - merkle_tree_pubkey: env.v1_state_trees[0].merkle_tree, - queue_pubkey: env.v1_state_trees[0].nullifier_queue, + merkle_tree_pubkey: env.v1_state_trees[0].merkle_tree.into(), + queue_pubkey: env.v1_state_trees[0].nullifier_queue.into(), prove_by_index: false, tree_type: TreeType::StateV1, }], @@ -283,29 +284,17 @@ pub async fn assert_escrow( ); let compressed_escrow_pda = test_indexer - .indexer - .as_ref() - .unwrap() - .compressed_accounts - .iter() - .find(|x| x.compressed_account.owner == token_escrow::ID) + .get_compressed_accounts_by_owner(&token_escrow::ID, None, None) + .await .unwrap() + .value + .items[0] .clone(); - let address = derive_address_legacy(&env.v1_address_trees[0].merkle_tree, seed).unwrap(); + let address = derive_address_legacy(&env.v1_address_trees[0].merkle_tree.into(), seed).unwrap(); - assert_eq!( - compressed_escrow_pda.compressed_account.address.unwrap(), - address - ); - assert_eq!( - compressed_escrow_pda.compressed_account.owner, - token_escrow::ID - ); - let compressed_escrow_pda_deserialized = compressed_escrow_pda - .compressed_account - .data - .as_ref() - .unwrap(); + assert_eq!(compressed_escrow_pda.address.unwrap(), address); + assert_eq!(compressed_escrow_pda.owner, token_escrow::ID); + let compressed_escrow_pda_deserialized = compressed_escrow_pda.data.as_ref().unwrap(); let compressed_escrow_pda_data = EscrowTimeLock::deserialize_reader(&mut &compressed_escrow_pda_deserialized.data[..]) .unwrap(); @@ -383,7 +372,7 @@ pub async fn perform_withdrawal( .unwrap() .compressed_accounts .iter() - .find(|x| x.compressed_account.owner == token_escrow::ID) + .find(|x| x.compressed_account.owner.to_bytes() == token_escrow::ID.to_bytes()) .unwrap() .clone(); println!("compressed_escrow_pda {:?}", compressed_escrow_pda); @@ -420,16 +409,16 @@ pub async fn perform_withdrawal( signer: &payer_pubkey, input_token_escrow_merkle_context: MerkleContext { leaf_index: token_escrow_account.merkle_context.leaf_index, - merkle_tree_pubkey: env.v1_state_trees[0].merkle_tree, - queue_pubkey: env.v1_state_trees[0].nullifier_queue, + merkle_tree_pubkey: env.v1_state_trees[0].merkle_tree.into(), + queue_pubkey: env.v1_state_trees[0].nullifier_queue.into(), prove_by_index: false, tree_type: TreeType::StateV1, }, input_cpda_merkle_context: MerkleContext { leaf_index: compressed_escrow_pda.merkle_context.leaf_index, - merkle_tree_pubkey: env.v1_state_trees[0].merkle_tree, - queue_pubkey: env.v1_state_trees[0].nullifier_queue, + merkle_tree_pubkey: env.v1_state_trees[0].merkle_tree.into(), + queue_pubkey: env.v1_state_trees[0].nullifier_queue.into(), prove_by_index: false, tree_type: TreeType::StateV1, }, @@ -490,30 +479,21 @@ pub async fn assert_withdrawal( assert!(withdrawal_account_exits); let compressed_escrow_pda = rpc - .indexer - .as_ref() - .unwrap() - .compressed_accounts - .iter() - .find(|x| x.compressed_account.owner == token_escrow::ID) + .get_compressed_accounts_by_owner(&token_escrow::ID, None, None) + .await .unwrap() + .value + .items[0] .clone(); - let address = - derive_address_legacy(&rpc.test_accounts.v1_address_trees[0].merkle_tree, seed).unwrap(); - assert_eq!( - compressed_escrow_pda.compressed_account.address.unwrap(), - address - ); - assert_eq!( - compressed_escrow_pda.compressed_account.owner, - token_escrow::ID - ); - let compressed_escrow_pda_deserialized = compressed_escrow_pda - .compressed_account - .data - .as_ref() - .unwrap(); + let address = derive_address_legacy( + &rpc.test_accounts.v1_address_trees[0].merkle_tree.into(), + seed, + ) + .unwrap(); + assert_eq!(compressed_escrow_pda.address.unwrap(), address); + assert_eq!(compressed_escrow_pda.owner, token_escrow::ID); + let compressed_escrow_pda_deserialized = compressed_escrow_pda.data.as_ref().unwrap(); let compressed_escrow_pda_data = EscrowTimeLock::deserialize_reader(&mut &compressed_escrow_pda_deserialized.data[..]) .unwrap(); diff --git a/forester-utils/src/instructions/address_batch_update.rs b/forester-utils/src/instructions/address_batch_update.rs index 3c67febee6..830cc8d597 100644 --- a/forester-utils/src/instructions/address_batch_update.rs +++ b/forester-utils/src/instructions/address_batch_update.rs @@ -14,7 +14,7 @@ use light_prover_client::{ proof_client::ProofClient, proof_types::batch_address_append::get_batch_address_append_circuit_inputs, }; -use light_sdk::verifier::CompressedProof; +use light_sdk::light_compressed_account::instruction_data::compressed_proof::CompressedProof; use light_sparse_merkle_tree::{ changelog::ChangelogEntry, indexed_changelog::IndexedChangelogEntry, SparseMerkleTree, }; @@ -45,7 +45,7 @@ where let (leaves_hash_chains, start_index, current_root, batch_size) = { let merkle_tree = BatchedMerkleTreeAccount::address_from_bytes( merkle_tree_account.data.as_mut_slice(), - &merkle_tree_pubkey.into(), + &(*merkle_tree_pubkey).into(), ) .unwrap(); diff --git a/forester/tests/address_v2_test.rs b/forester/tests/address_v2_test.rs index 67cca10f97..a74837c10b 100644 --- a/forester/tests/address_v2_test.rs +++ b/forester/tests/address_v2_test.rs @@ -13,10 +13,8 @@ use light_client::{ rpc::{client::RpcUrl, merkle_tree::MerkleTreeExt, LightClient, Rpc, RpcConfig}, }; use light_compressed_account::{ - address::{derive_address, pack_new_address_params_assigned}, - compressed_account::{ - pack_output_compressed_accounts, PackedCompressedAccountWithMerkleContext, - }, + address::derive_address, + compressed_account::PackedCompressedAccountWithMerkleContext, instruction_data::{ data::{NewAddressParams, NewAddressParamsAssigned, OutputCompressedAccountWithContext}, with_readonly::{InAccount, InstructionDataInvokeCpiWithReadOnly}, @@ -24,8 +22,11 @@ use light_compressed_account::{ }; use light_compressed_token::process_transfer::transfer_sdk::to_account_metas; use light_program_test::{accounts::test_accounts::TestAccounts, Indexer}; -use light_test_utils::create_address_test_program_sdk::{ - create_pda_instruction, CreateCompressedPdaInstructionInputs, +use light_test_utils::{ + create_address_test_program_sdk::{ + create_pda_instruction, CreateCompressedPdaInstructionInputs, + }, + pack::{pack_new_address_params_assigned, pack_output_compressed_accounts}, }; use rand::{prelude::StdRng, Rng, SeedableRng}; use serial_test::serial; @@ -295,8 +296,8 @@ async fn create_v2_addresses( let data: [u8; 31] = [1; 31]; let new_address_params = NewAddressParams { seed: address_seeds[0], - address_merkle_tree_pubkey: *batch_address_merkle_tree, - address_queue_pubkey: *batch_address_merkle_tree, + address_merkle_tree_pubkey: (*batch_address_merkle_tree).into(), + address_queue_pubkey: (*batch_address_merkle_tree).into(), address_merkle_tree_root_index: proof_result.value.get_address_root_indices()[0], }; @@ -329,8 +330,8 @@ async fn create_v2_addresses( .enumerate() .map(|(i, seed)| NewAddressParamsAssigned { seed: *seed, - address_queue_pubkey: *batch_address_merkle_tree, - address_merkle_tree_pubkey: *batch_address_merkle_tree, + address_queue_pubkey: (*batch_address_merkle_tree).into(), + address_merkle_tree_pubkey: (*batch_address_merkle_tree).into(), address_merkle_tree_root_index: proof_result.value.get_address_root_indices()[i], assigned_account_index: None, }) @@ -349,7 +350,7 @@ async fn create_v2_addresses( .as_slice(), output_accounts .iter() - .map(|x| x.merkle_tree) + .map(|x| x.merkle_tree.into()) .collect::>() .as_slice(), &mut remaining_accounts, diff --git a/forester/tests/batched_state_async_indexer_test.rs b/forester/tests/batched_state_async_indexer_test.rs index a740fa372a..d29bc71e19 100644 --- a/forester/tests/batched_state_async_indexer_test.rs +++ b/forester/tests/batched_state_async_indexer_test.rs @@ -854,8 +854,8 @@ async fn transfer( .iter() .map( |x| light_compressed_account::compressed_account::MerkleContext { - merkle_tree_pubkey: x.tree_info.tree, - queue_pubkey: x.tree_info.queue, + merkle_tree_pubkey: x.tree_info.tree.into(), + queue_pubkey: x.tree_info.queue.into(), leaf_index: x.leaf_index, prove_by_index: false, tree_type: TreeType::StateV2, @@ -867,7 +867,7 @@ async fn transfer( let mut compressed_accounts = vec![ CompressedAccount { lamports: lamp, - owner: payer.pubkey(), + owner: payer.pubkey().into(), address: None, data: None, }; @@ -896,7 +896,7 @@ async fn transfer( .iter() .map(|x| CompressedAccount { lamports: x.lamports, - owner: x.owner, + owner: x.owner.into(), address: x.address, data: x.data.clone(), }) @@ -945,7 +945,7 @@ async fn compress( ) -> Signature { let compress_account = CompressedAccount { lamports, - owner: payer.pubkey(), + owner: payer.pubkey().into(), address: None, data: None, }; @@ -1000,7 +1000,11 @@ async fn create_v1_address( for _ in 0..num_addresses { let seed = rng.gen::<[u8; 32]>(); seeds.push(seed); - let address = derive_address_legacy(merkle_tree_pubkey, &seed).unwrap(); + let address = derive_address_legacy( + &light_compressed_account::Pubkey::from(*merkle_tree_pubkey), + &seed, + ) + .unwrap(); address_proof_inputs.push(AddressWithTree { address, tree: *merkle_tree_pubkey, @@ -1018,8 +1022,8 @@ async fn create_v1_address( { new_address_params.push(NewAddressParams { seed: *seed, - address_queue_pubkey: *queue, - address_merkle_tree_pubkey: *merkle_tree_pubkey, + address_queue_pubkey: (*queue).into(), + address_merkle_tree_pubkey: (*merkle_tree_pubkey).into(), address_merkle_tree_root_index: *root_index, }); } diff --git a/program-libs/account-checks/Cargo.toml b/program-libs/account-checks/Cargo.toml index 0eba3dd1ea..fa95073710 100644 --- a/program-libs/account-checks/Cargo.toml +++ b/program-libs/account-checks/Cargo.toml @@ -7,7 +7,7 @@ license = "Apache-2.0" edition = "2021" [features] -default = ["solana"] +default = [] solana = [ "solana-program-error", "solana-sysvar", @@ -30,7 +30,9 @@ thiserror = { workspace = true } rand = { workspace = true, optional = true } [dev-dependencies] +pinocchio = { workspace = true } borsh = { workspace = true } +solana-pubkey = { workspace = true, features = ["curve25519", "sha2"] } [lints.rust.unexpected_cfgs] level = "allow" diff --git a/program-libs/account-checks/src/test_account_info.rs b/program-libs/account-checks/src/account_info/test_account_info.rs similarity index 100% rename from program-libs/account-checks/src/test_account_info.rs rename to program-libs/account-checks/src/account_info/test_account_info.rs diff --git a/program-libs/account-checks/tests/account_info.rs b/program-libs/account-checks/tests/account_info.rs new file mode 100644 index 0000000000..b196475130 --- /dev/null +++ b/program-libs/account-checks/tests/account_info.rs @@ -0,0 +1,493 @@ +#![cfg(all(feature = "solana", feature = "pinocchio"))] +// Comprehensive tests for AccountInfoTrait implementations: +// - Solana implementation (solana_account_info::AccountInfo) +// - Pinocchio implementation (pinocchio::account_info::AccountInfo) +// +// Tests cover all trait methods with both functional and failing test cases: +// 1. key() - Returns account public key +// 2. is_writable() - Check if account is writable +// 3. is_signer() - Check if account is a signer +// 4. executable() - Check if account is executable +// 5. lamports() - Get account lamport balance +// 6. data_len() - Get account data length +// 7. try_borrow_data() - Borrow account data immutably +// 8. try_borrow_mut_data() - Borrow account data mutably +// 9. is_owned_by() - Check account ownership +// 10. find_program_address() - Find PDA (static method) +// 11. create_program_address() - Create PDA (static method) +// 12. data_is_empty() - Check if account data is empty +// 13. get_min_rent_balance() - Get minimum rent balance for size + +use light_account_checks::AccountInfoTrait; + +// Test helper functions +#[cfg(feature = "solana")] +fn create_test_account_solana( + key: solana_pubkey::Pubkey, + owner: solana_pubkey::Pubkey, + lamports: u64, + data: Vec, + writable: bool, + _signer: bool, + _executable: bool, +) -> light_account_checks::account_info::test_account_info::solana_program::TestAccount { + let mut account = + light_account_checks::account_info::test_account_info::solana_program::TestAccount::new( + key, + owner, + data.len(), + ); + account.data = data; + account.lamports = lamports; + account.writable = writable; + // Note: TestAccount doesn't have an executable field + // Note: TestAccount doesn't support signer flag directly + account +} + +#[cfg(feature = "solana")] +fn create_pubkey() -> solana_pubkey::Pubkey { + solana_pubkey::Pubkey::new_unique() +} + +#[cfg(feature = "pinocchio")] +fn create_test_account_pinocchio( + key: [u8; 32], + owner: [u8; 32], + data: Vec, + writable: bool, + signer: bool, + executable: bool, +) -> pinocchio::account_info::AccountInfo { + light_account_checks::account_info::test_account_info::pinocchio::get_account_info( + key, owner, signer, writable, executable, data, + ) +} + +// Solana AccountInfoTrait implementation tests +#[test] +#[cfg(feature = "solana")] +fn test_solana_account_info_trait() { + let key = create_pubkey(); + let owner = create_pubkey(); + let data = vec![1, 2, 3, 4, 5]; + let lamports = 1000000u64; + + // Test writable account + { + let mut account = create_test_account_solana( + key, + owner, + lamports, + data.clone(), + true, // writable + false, // signer + false, // executable + ); + let account_info = account.get_account_info(); + + // Test key() - functional + assert_eq!(AccountInfoTrait::key(&account_info), key.to_bytes()); + + // Test is_writable() - functional (true case) + assert!(AccountInfoTrait::is_writable(&account_info)); + + // Test is_signer() - failing (TestAccount always returns false) + assert!(!AccountInfoTrait::is_signer(&account_info)); + + // Test executable() - failing (false case) + assert!(!AccountInfoTrait::executable(&account_info)); + + // Test lamports() - functional + assert_eq!(AccountInfoTrait::lamports(&account_info), lamports); + + // Test data_len() - functional + assert_eq!(AccountInfoTrait::data_len(&account_info), data.len()); + + // Test try_borrow_data() - functional + { + let borrowed_data = AccountInfoTrait::try_borrow_data(&account_info).unwrap(); + assert_eq!(*borrowed_data, data); + } // Drop immutable borrow + + // Test try_borrow_mut_data() - functional (writable account) + { + let mut borrowed_mut_data = + AccountInfoTrait::try_borrow_mut_data(&account_info).unwrap(); + borrowed_mut_data[0] = 99; + } // Drop mutable borrow + + // Verify mutation worked + { + let borrowed_data = AccountInfoTrait::try_borrow_data(&account_info).unwrap(); + assert_eq!(borrowed_data[0], 99); + } + + // Test is_owned_by() - functional (correct owner) + assert!(AccountInfoTrait::is_owned_by( + &account_info, + &owner.to_bytes() + )); + + // Test is_owned_by() - failing (wrong owner) + let wrong_owner = create_pubkey(); + assert!(!AccountInfoTrait::is_owned_by( + &account_info, + &wrong_owner.to_bytes() + )); + + // Test data_is_empty() - failing (has data) + assert!(!AccountInfoTrait::data_is_empty(&account_info)); + } + + // Test non-writable account + { + let mut account = create_test_account_solana( + key, + owner, + lamports, + data.clone(), + false, // not writable + false, // signer + false, // executable + ); + let account_info = account.get_account_info(); + + // Test is_writable() - failing (false case) + assert!(!AccountInfoTrait::is_writable(&account_info)); + + // Test try_borrow_mut_data() should still work (TestAccount doesn't enforce this) + // Note: Real Solana runtime would fail this for non-writable accounts + let _borrowed_mut_data = AccountInfoTrait::try_borrow_mut_data(&account_info).unwrap(); + } + + // Test executable account + // Note: TestAccount doesn't support executable flag in constructor, so we test the default false case + { + let mut account = create_test_account_solana( + key, + owner, + lamports, + data.clone(), + false, // not writable + false, // signer + false, // executable (TestAccount doesn't support setting this to true) + ); + let account_info = account.get_account_info(); + + // Test executable() - failing (TestAccount always returns false) + assert!(!AccountInfoTrait::executable(&account_info)); + } + + // Test empty data account + { + let mut account = create_test_account_solana( + key, + owner, + lamports, + vec![], // empty data + true, // writable + false, // signer + false, // executable + ); + let account_info = account.get_account_info(); + + // Test data_len() - functional (zero length) + assert_eq!(AccountInfoTrait::data_len(&account_info), 0); + + // Test data_is_empty() - functional (empty data) + assert!(AccountInfoTrait::data_is_empty(&account_info)); + } + + // Test static methods (find_program_address and create_program_address) + { + use light_account_checks::error::AccountError; + use solana_account_info::AccountInfo; + + let program_id = create_pubkey(); + let seeds = &[b"test_seed".as_ref(), &[1, 2, 3]]; + + // Test find_program_address() - functional + let (pda, bump) = AccountInfo::find_program_address(seeds, &program_id.to_bytes()); + + // Verify the PDA is valid by using Solana's function + let (expected_pda, expected_bump) = + solana_pubkey::Pubkey::find_program_address(seeds, &program_id); + assert_eq!(pda, expected_pda.to_bytes()); + assert_eq!(bump, expected_bump); + + // Test create_program_address() - functional + let seeds_with_bump = &[b"test_seed".as_ref(), &[1, 2, 3], &[bump]]; + let created_pda = + AccountInfo::create_program_address(seeds_with_bump, &program_id.to_bytes()).unwrap(); + assert_eq!(created_pda, pda); + + // Test create_program_address() - failing (invalid bump) + let invalid_seeds = &[b"test_seed".as_ref(), &[1, 2, 3], &[255u8]]; // Invalid bump + let result = AccountInfo::create_program_address(invalid_seeds, &program_id.to_bytes()); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AccountError::InvalidSeeds); + } + + // Test get_min_rent_balance() - static method + // TODO: Enable when sysvar is available in test environment + /* + { + use solana_account_info::AccountInfo; + + // Test get_min_rent_balance() - functional + let small_rent = AccountInfo::get_min_rent_balance(100); + assert!(small_rent.is_ok()); + let small_rent_value = small_rent.unwrap(); + assert_eq!(small_rent_value, 1002240); + + let large_rent = AccountInfo::get_min_rent_balance(1000); + assert!(large_rent.is_ok()); + let large_rent_value = large_rent.unwrap(); + assert_eq!(large_rent_value, 1009440); + + // Larger accounts should cost more rent + assert!(large_rent_value > small_rent_value); + + // Zero size should still have base rent + let zero_rent = AccountInfo::get_min_rent_balance(0); + assert!(zero_rent.is_ok()); + assert_eq!(zero_rent.unwrap(), 890880); + } + */ +} + +// Pinocchio AccountInfoTrait implementation tests +#[test] +#[cfg(feature = "pinocchio")] +fn test_pinocchio_account_info_trait() { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let data = vec![1, 2, 3, 4, 5]; + + // Test writable account + { + let account = create_test_account_pinocchio( + key, + owner, + data.clone(), + true, // writable + false, // signer + false, // executable + ); + + // Test key() - functional (using AccountInfoTrait method) + assert_eq!(AccountInfoTrait::key(&account), key); + + // Test is_writable() - functional (true case) + assert!(AccountInfoTrait::is_writable(&account)); + + // Test is_signer() - failing (false case) + assert!(!AccountInfoTrait::is_signer(&account)); + + // Test executable() - failing (false case) + assert!(!AccountInfoTrait::executable(&account)); + + // Test lamports() - functional (fixed at 1000 in test helper) + assert_eq!(AccountInfoTrait::lamports(&account), 1000); + + // Test data_len() - functional + assert_eq!(AccountInfoTrait::data_len(&account), data.len()); + + // Test try_borrow_data() - functional + { + let borrowed_data = AccountInfoTrait::try_borrow_data(&account).unwrap(); + assert_eq!(*borrowed_data, data); + } // Drop immutable borrow + + // Test try_borrow_mut_data() - functional (writable account) + { + let mut borrowed_mut_data = AccountInfoTrait::try_borrow_mut_data(&account).unwrap(); + borrowed_mut_data[0] = 99; + } // Drop mutable borrow + + // Verify mutation worked + { + let borrowed_data = AccountInfoTrait::try_borrow_data(&account).unwrap(); + assert_eq!(borrowed_data[0], 99); + } + + // Test is_owned_by() - functional (correct owner) + assert!(AccountInfoTrait::is_owned_by(&account, &owner)); + + // Test is_owned_by() - failing (wrong owner) + let wrong_owner = [3u8; 32]; + assert!(!AccountInfoTrait::is_owned_by(&account, &wrong_owner)); + + // Test data_is_empty() - failing (has data) + assert!(!AccountInfoTrait::data_is_empty(&account)); + } + + // Test non-writable account + { + let account = create_test_account_pinocchio( + key, + owner, + data.clone(), + false, // not writable + false, // signer + false, // executable + ); + + // Test is_writable() - failing (false case) + assert!(!AccountInfoTrait::is_writable(&account)); + + // Test try_borrow_mut_data() - should still work (test implementation doesn't enforce this) + let _borrowed_mut_data = AccountInfoTrait::try_borrow_mut_data(&account).unwrap(); + } + + // Test signer account + { + let account = create_test_account_pinocchio( + key, + owner, + data.clone(), + true, // writable + true, // signer + false, // executable + ); + + // Test is_signer() - functional (true case) + assert!(AccountInfoTrait::is_signer(&account)); + } + + // Test executable account + { + let account = create_test_account_pinocchio( + key, + owner, + data.clone(), + false, // not writable + false, // signer + true, // executable + ); + + // Test executable() - functional (true case) + assert!(AccountInfoTrait::executable(&account)); + } + + // Test empty data account + { + let account = create_test_account_pinocchio( + key, + owner, + vec![], // empty data + true, // writable + false, // signer + false, // executable + ); + + // Test data_len() - functional (zero length) + assert_eq!(AccountInfoTrait::data_len(&account), 0); + + // Test data_is_empty() - functional (empty data) + assert!(AccountInfoTrait::data_is_empty(&account)); + } + + // Test static methods (find_program_address and create_program_address) + // Note: Pinocchio implementation falls back to Solana when solana feature is enabled + #[cfg(feature = "solana")] + { + use light_account_checks::{error::AccountError, AccountInfoTrait}; + + let program_id = [4u8; 32]; + let seeds = &[b"test_seed".as_ref(), &[1, 2, 3]]; + + // Test find_program_address() - functional + let (pda, bump) = + pinocchio::account_info::AccountInfo::find_program_address(seeds, &program_id); + + // Verify the PDA is valid by using Solana's function + let (expected_pda, expected_bump) = solana_pubkey::Pubkey::find_program_address( + seeds, + &solana_pubkey::Pubkey::from(program_id), + ); + assert_eq!(pda, expected_pda.to_bytes()); + assert_eq!(bump, expected_bump); + + // Test create_program_address() - functional + let seeds_with_bump = &[b"test_seed".as_ref(), &[1, 2, 3], &[bump]]; + let created_pda = pinocchio::account_info::AccountInfo::create_program_address( + seeds_with_bump, + &program_id, + ) + .unwrap(); + assert_eq!(created_pda, pda); + + // Test create_program_address() - failing (invalid bump) + let invalid_seeds = &[b"test_seed".as_ref(), &[1, 2, 3], &[255u8]]; // Invalid bump + let result = pinocchio::account_info::AccountInfo::create_program_address( + invalid_seeds, + &program_id, + ); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AccountError::InvalidSeeds); + } + + // Test zero lamports account + { + let account = create_test_account_pinocchio( + key, + owner, + data.clone(), + true, // writable + false, // signer + false, // executable + ); + + // Test lamports() - functional (always 1000 in test helper) + assert_eq!(AccountInfoTrait::lamports(&account), 1000); + } + + // Test get_min_rent_balance() - static method + // TODO: Enable when sysvar is available in test environment + /* + { + use pinocchio::account_info::AccountInfo; + + // Test get_min_rent_balance() - functional + let small_rent = AccountInfo::get_min_rent_balance(100); + assert!(small_rent.is_ok()); + let small_rent_value = small_rent.unwrap(); + + let large_rent = AccountInfo::get_min_rent_balance(1000); + assert!(large_rent.is_ok()); + let large_rent_value = large_rent.unwrap(); + + // Behavior depends on feature configuration + #[cfg(feature = "solana")] + { + // When solana feature is available, should behave like solana + assert!(large_rent_value > small_rent_value); + assert_eq!(small_rent_value, 1002240); + assert_eq!(large_rent_value, 1009440); + } + + #[cfg(not(feature = "solana"))] + { + // When solana feature is not available, returns 0 for testing + assert_eq!(small_rent_value, 0); + assert_eq!(large_rent_value, 0); + } + + // Zero size should still have base rent (when solana feature enabled) or 0 (when not) + let zero_rent = AccountInfo::get_min_rent_balance(0); + assert!(zero_rent.is_ok()); + + #[cfg(feature = "solana")] + { + assert_eq!(zero_rent.unwrap(), 890880); + } + + #[cfg(not(feature = "solana"))] + { + assert_eq!(zero_rent.unwrap(), 0); + } + } + */ +} diff --git a/program-libs/account-checks/tests/tests.rs b/program-libs/account-checks/tests/tests.rs new file mode 100644 index 0000000000..c1e3df88ba --- /dev/null +++ b/program-libs/account-checks/tests/tests.rs @@ -0,0 +1,845 @@ +#![cfg(all(feature = "solana", feature = "pinocchio"))] +/// Tests for all functions in checks.rs with both pinocchio and solana backends: +/// 1. account_info_init - 4 tests +/// - Solana: Success + Failure (already initialized) +/// - Pinocchio: Success + Failure (already initialized) +/// 2. check_account_info_mut - 4 tests +/// - Solana: Success + Failure (not writable) +/// - Pinocchio: Success + Failure (not writable) +/// 3. check_account_info_non_mut - 4 tests +/// - Solana: Success + Failure (is writable) +/// - Pinocchio: Success + Failure (is writable) +/// 4. check_non_mut - 4 tests +/// - Solana: Success + Failure (is writable) +/// - Pinocchio: Success + Failure (is writable) +/// 5. check_account_info - 6 tests +/// - Solana: Success + Failure (wrong owner) + Failure (wrong discriminator) +/// - Pinocchio: Success + Failure (wrong owner) + Failure (wrong discriminator) +/// 6. check_signer - 3 tests +/// - Solana: Failure (TestAccount always returns false for is_signer) +/// - Pinocchio: Success + Failure +/// 7. check_owner - 4 tests +/// - Solana: Success + Failure (wrong owner) +/// - Pinocchio: Success + Failure (wrong owner) +/// 8. check_program - 5 tests +/// - Solana: Failure (not executable) + Failure (wrong key) +/// - Pinocchio: Success + Failure (not executable) + Failure (wrong key) +/// 9. check_pda_seeds - 4 tests +/// - Solana: Success + Failure +/// - Pinocchio: Success + Failure (requires solana feature for fallback) +/// 10. check_pda_seeds_with_bump - 4 tests +/// - Solana: Success + Failure +/// - Pinocchio: Success + Failure (requires solana feature for fallback) +/// 11. check_account_balance_is_rent_exempt - 4 tests +/// - Solana: Success + Failure (wrong size) +/// - Pinocchio: Success + Failure (wrong size) +/// 12. set_discriminator - 2 tests +/// - Success + Failure (already initialized) +/// 13. check_discriminator - 3 tests +/// - Success + Failure (invalid discriminator) + Failure (too small) +/// 14. check_data_is_zeroed - 2 tests +/// - Success + Failure (not zeroed) +/// 15. get_min_rent_balance - 4 tests +/// - Solana: Success + Failure (sysvar error) +/// - Pinocchio: Success + Test fallback cases +use borsh::{BorshDeserialize, BorshSerialize}; +use light_account_checks::{checks::*, discriminator::Discriminator, error::AccountError}; + +#[repr(C)] +#[derive(Debug, PartialEq, Copy, Clone, BorshSerialize, BorshDeserialize)] +pub struct TestStruct { + pub data: u64, +} + +impl Discriminator for TestStruct { + const LIGHT_DISCRIMINATOR: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + const LIGHT_DISCRIMINATOR_SLICE: &[u8] = &Self::LIGHT_DISCRIMINATOR; +} + +// Helper functions to create test accounts for both backends +#[cfg(feature = "solana")] +fn create_test_account_solana( + key: solana_pubkey::Pubkey, + owner: solana_pubkey::Pubkey, + size: usize, + writable: bool, +) -> light_account_checks::account_info::test_account_info::solana_program::TestAccount { + let mut account = + light_account_checks::account_info::test_account_info::solana_program::TestAccount::new( + key, owner, size, + ); + account.writable = writable; + account +} + +#[cfg(feature = "solana")] +fn create_pubkey() -> solana_pubkey::Pubkey { + solana_pubkey::Pubkey::new_unique() +} + +#[cfg(feature = "pinocchio")] +fn create_test_account_pinocchio( + key: [u8; 32], + owner: [u8; 32], + size: usize, + writable: bool, + signer: bool, + executable: bool, +) -> pinocchio::account_info::AccountInfo { + light_account_checks::account_info::test_account_info::pinocchio::get_account_info( + key, + owner, + signer, + writable, + executable, + vec![0u8; size], + ) +} + +// 1. account_info_init tests - 4 tests total +#[test] +fn test_account_info_init() { + // Solana success case + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + assert!(account_info_init::(&account.get_account_info()).is_ok()); + } + + // Solana failure case (already initialized) + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + set_discriminator::(&mut account.data).unwrap(); + assert_eq!( + account_info_init::(&account.get_account_info()), + Err(AccountError::AlreadyInitialized) + ); + } + + // Pinocchio success case + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + assert!(account_info_init::(&account).is_ok()); + } + + // Pinocchio failure case (already initialized) + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + account_info_init::(&account).unwrap(); + assert_eq!( + account_info_init::(&account), + Err(AccountError::AlreadyInitialized) + ); + } +} + +// 2. check_account_info_mut tests - 4 tests total +#[test] +fn test_check_account_info_mut() { + // Solana success case + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + set_discriminator::(&mut account.data).unwrap(); + assert!(check_account_info_mut::( + &owner.to_bytes(), + &account.get_account_info() + ) + .is_ok()); + } + + // Solana failure case (not writable) + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, false); + set_discriminator::(&mut account.data).unwrap(); + assert_eq!( + check_account_info_mut::(&owner.to_bytes(), &account.get_account_info()), + Err(AccountError::AccountMutable) + ); + } + + // Pinocchio success case + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + account_info_init::(&account).unwrap(); + assert!(check_account_info_mut::(&owner, &account).is_ok()); + } + + // Pinocchio failure case (not writable) + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, false, false, false); + account_info_init::(&account).unwrap(); + assert_eq!( + check_account_info_mut::(&owner, &account), + Err(AccountError::AccountMutable) + ); + } +} + +// 3. check_account_info_non_mut tests - 4 tests total +#[test] +fn test_check_account_info_non_mut() { + // Solana success case + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, false); + set_discriminator::(&mut account.data).unwrap(); + assert!(check_account_info_non_mut::( + &owner.to_bytes(), + &account.get_account_info() + ) + .is_ok()); + } + + // Solana failure case (is writable) + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + set_discriminator::(&mut account.data).unwrap(); + assert_eq!( + check_account_info_non_mut::( + &owner.to_bytes(), + &account.get_account_info() + ), + Err(AccountError::AccountMutable) + ); + } + + // Pinocchio success case + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, false, false, false); + account_info_init::(&account).unwrap(); + assert!(check_account_info_non_mut::(&owner, &account).is_ok()); + } + + // Pinocchio failure case (is writable) + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + account_info_init::(&account).unwrap(); + assert_eq!( + check_account_info_non_mut::(&owner, &account), + Err(AccountError::AccountMutable) + ); + } +} + +// 4. check_non_mut tests - 4 tests total +#[test] +fn test_check_non_mut() { + // Solana success case + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, false); + assert!(check_non_mut(&account.get_account_info()).is_ok()); + } + + // Solana failure case (is writable) + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + assert_eq!( + check_non_mut(&account.get_account_info()), + Err(AccountError::AccountMutable) + ); + } + + // Pinocchio success case + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, false, false, false); + assert!(check_non_mut(&account).is_ok()); + } + + // Pinocchio failure case (is writable) + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + assert_eq!(check_non_mut(&account), Err(AccountError::AccountMutable)); + } +} + +// 5. check_account_info tests - 6 tests total +#[test] +fn test_check_account_info() { + // Solana success case + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + set_discriminator::(&mut account.data).unwrap(); + assert!(check_account_info::( + &owner.to_bytes(), + &account.get_account_info() + ) + .is_ok()); + } + + // Solana failure case (wrong owner) + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let wrong_owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + set_discriminator::(&mut account.data).unwrap(); + assert_eq!( + check_account_info::( + &wrong_owner.to_bytes(), + &account.get_account_info() + ), + Err(AccountError::AccountOwnedByWrongProgram) + ); + } + + // Solana failure case (wrong discriminator) + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + assert_eq!( + check_account_info::(&owner.to_bytes(), &account.get_account_info()), + Err(AccountError::InvalidDiscriminator) + ); + } + + // Pinocchio success case + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + account_info_init::(&account).unwrap(); + assert!(check_account_info::(&owner, &account).is_ok()); + } + + // Pinocchio failure case (wrong owner) + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let wrong_owner = [3u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + account_info_init::(&account).unwrap(); + assert_eq!( + check_account_info::(&wrong_owner, &account), + Err(AccountError::AccountOwnedByWrongProgram) + ); + } + + // Pinocchio failure case (wrong discriminator) + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + assert_eq!( + check_account_info::(&owner, &account), + Err(AccountError::InvalidDiscriminator) + ); + } +} + +// 6. check_signer tests - 3 tests total +#[test] +fn test_check_signer() { + // Solana failure case (TestAccount always returns false for is_signer) + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + assert_eq!( + check_signer(&account.get_account_info()), + Err(AccountError::InvalidSigner) + ); + } + + // Pinocchio success case + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, true, false); + assert!(check_signer(&account).is_ok()); + } + + // Pinocchio failure case + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + assert_eq!(check_signer(&account), Err(AccountError::InvalidSigner)); + } +} + +// 7. check_owner tests - 4 tests total +#[test] +fn test_check_owner() { + // Solana success case + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + assert!(check_owner(&owner.to_bytes(), &account.get_account_info()).is_ok()); + } + + // Solana failure case (wrong owner) + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let wrong_owner = create_pubkey(); + let mut account = create_test_account_solana(key, owner, 16, true); + assert_eq!( + check_owner(&wrong_owner.to_bytes(), &account.get_account_info()), + Err(AccountError::AccountOwnedByWrongProgram) + ); + } + + // Pinocchio success case + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + assert!(check_owner(&owner, &account).is_ok()); + } + + // Pinocchio failure case (wrong owner) + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let wrong_owner = [3u8; 32]; + let account = create_test_account_pinocchio(key, owner, 16, true, false, false); + assert_eq!( + check_owner(&wrong_owner, &account), + Err(AccountError::AccountOwnedByWrongProgram) + ); + } +} + +// 8. check_program tests - 5 tests total +#[test] +fn test_check_program() { + // Solana failure case (not executable) + #[cfg(feature = "solana")] + { + let program_id = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(program_id, owner, 16, true); + assert_eq!( + check_program(&program_id.to_bytes(), &account.get_account_info()), + Err(AccountError::ProgramNotExecutable) + ); + } + + // Solana failure case (wrong key) + #[cfg(feature = "solana")] + { + let program_id = create_pubkey(); + let different_key = create_pubkey(); + let owner = create_pubkey(); + let mut account = create_test_account_solana(different_key, owner, 16, true); + assert_eq!( + check_program(&program_id.to_bytes(), &account.get_account_info()), + Err(AccountError::InvalidProgramId) + ); + } + + // Pinocchio success case + #[cfg(feature = "pinocchio")] + { + let program_id = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(program_id, owner, 16, true, false, true); + assert!(check_program(&program_id, &account).is_ok()); + } + + // Pinocchio failure case (not executable) + #[cfg(feature = "pinocchio")] + { + let program_id = [1u8; 32]; + let owner = [2u8; 32]; + let account = create_test_account_pinocchio(program_id, owner, 16, true, false, false); + assert_eq!( + check_program(&program_id, &account), + Err(AccountError::ProgramNotExecutable) + ); + } + + // Pinocchio failure case (wrong key) + #[cfg(feature = "pinocchio")] + { + let program_id = [1u8; 32]; + let different_key = [2u8; 32]; + let owner = [3u8; 32]; + let account = create_test_account_pinocchio(different_key, owner, 16, true, false, true); + assert_eq!( + check_program(&program_id, &account), + Err(AccountError::InvalidProgramId) + ); + } +} + +// 9. check_pda_seeds tests - 4 tests total +#[test] +fn test_check_pda_seeds() { + // Solana success case + #[cfg(feature = "solana")] + { + use solana_account_info::AccountInfo; + + let program_id = create_pubkey(); + let seeds = &[b"test_seed".as_ref()]; + let (pda, _) = solana_pubkey::Pubkey::find_program_address(seeds, &program_id); + let mut account = create_test_account_solana(pda, program_id, 16, true); + + assert!(check_pda_seeds::( + seeds, + &program_id.to_bytes(), + &account.get_account_info() + ) + .is_ok()); + } + + // Solana failure case + #[cfg(feature = "solana")] + { + use solana_account_info::AccountInfo; + + let program_id = create_pubkey(); + let wrong_key = create_pubkey(); + let seeds = &[b"test_seed".as_ref()]; + let mut account = create_test_account_solana(wrong_key, program_id, 16, true); + + assert_eq!( + check_pda_seeds::( + seeds, + &program_id.to_bytes(), + &account.get_account_info() + ), + Err(AccountError::InvalidSeeds) + ); + } + + // Pinocchio success case (requires solana feature for fallback) + #[cfg(all(feature = "pinocchio", feature = "solana"))] + { + let program_id = [1u8; 32]; + let seeds = &[b"test_seed".as_ref()]; + let (pda, _) = solana_pubkey::Pubkey::find_program_address( + seeds, + &solana_pubkey::Pubkey::from(program_id), + ); + let account = + create_test_account_pinocchio(pda.to_bytes(), program_id, 16, true, false, false); + + assert!(check_pda_seeds(seeds, &program_id, &account).is_ok()); + } + + // Pinocchio failure case (requires solana feature for fallback) + #[cfg(all(feature = "pinocchio", feature = "solana"))] + { + let program_id = [1u8; 32]; + let wrong_key = [2u8; 32]; + let seeds = &[b"test_seed".as_ref()]; + let account = create_test_account_pinocchio(wrong_key, program_id, 16, true, false, false); + + assert_eq!( + check_pda_seeds(seeds, &program_id, &account), + Err(AccountError::InvalidSeeds) + ); + } +} + +// 10. check_pda_seeds_with_bump tests - 4 tests total +#[test] +fn test_check_pda_seeds_with_bump() { + // Solana success case + #[cfg(feature = "solana")] + { + use solana_account_info::AccountInfo; + + let program_id = create_pubkey(); + let base_seeds = &[b"test_seed".as_ref()]; + let (pda, bump) = solana_pubkey::Pubkey::find_program_address(base_seeds, &program_id); + let seeds_with_bump = &[b"test_seed".as_ref(), &[bump]]; + let mut account = create_test_account_solana(pda, program_id, 16, true); + + assert!(check_pda_seeds_with_bump::( + seeds_with_bump, + &program_id.to_bytes(), + &account.get_account_info() + ) + .is_ok()); + } + + // Solana failure case + #[cfg(feature = "solana")] + { + use solana_account_info::AccountInfo; + + let program_id = create_pubkey(); + let wrong_key = create_pubkey(); + let base_seeds = &[b"test_seed".as_ref()]; + let (_, bump) = solana_pubkey::Pubkey::find_program_address(base_seeds, &program_id); + let seeds_with_bump = &[b"test_seed".as_ref(), &[bump]]; + let mut account = create_test_account_solana(wrong_key, program_id, 16, true); + + assert_eq!( + check_pda_seeds_with_bump::( + seeds_with_bump, + &program_id.to_bytes(), + &account.get_account_info() + ), + Err(AccountError::InvalidSeeds) + ); + } + + // Pinocchio success case (requires solana feature for fallback) + #[cfg(all(feature = "pinocchio", feature = "solana"))] + { + let program_id = [1u8; 32]; + let base_seeds = &[b"test_seed".as_ref()]; + let (pda, bump) = solana_pubkey::Pubkey::find_program_address( + base_seeds, + &solana_pubkey::Pubkey::from(program_id), + ); + let seeds_with_bump = &[b"test_seed".as_ref(), &[bump]]; + let account = + create_test_account_pinocchio(pda.to_bytes(), program_id, 16, true, false, false); + + assert!(check_pda_seeds_with_bump(seeds_with_bump, &program_id, &account).is_ok()); + } + + // Pinocchio failure case (requires solana feature for fallback) + #[cfg(all(feature = "pinocchio", feature = "solana"))] + { + let program_id = [1u8; 32]; + let wrong_key = [2u8; 32]; + let base_seeds = &[b"test_seed".as_ref()]; + let (_, bump) = solana_pubkey::Pubkey::find_program_address( + base_seeds, + &solana_pubkey::Pubkey::from(program_id), + ); + let seeds_with_bump = &[b"test_seed".as_ref(), &[bump]]; + let account = create_test_account_pinocchio(wrong_key, program_id, 16, true, false, false); + + assert_eq!( + check_pda_seeds_with_bump(seeds_with_bump, &program_id, &account), + Err(AccountError::InvalidSeeds) + ); + } +} + +// 11. check_account_balance_is_rent_exempt tests - 4 tests total +#[test] +fn test_check_account_balance_is_rent_exempt() { + // Solana success case + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let expected_size = 16; + let mut account = create_test_account_solana(key, owner, expected_size, true); + account.lamports = 1000000; // High lamports to ensure rent exemption + + assert!( + check_account_balance_is_rent_exempt(&account.get_account_info(), expected_size) + .is_ok() + ); + } + + // Solana failure case (wrong size) + #[cfg(feature = "solana")] + { + let key = create_pubkey(); + let owner = create_pubkey(); + let actual_size = 16; + let expected_size = 32; + let mut account = create_test_account_solana(key, owner, actual_size, true); + + assert_eq!( + check_account_balance_is_rent_exempt(&account.get_account_info(), expected_size), + Err(AccountError::InvalidAccountSize) + ); + } + + // Pinocchio success case + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let expected_size = 16; + let account = create_test_account_pinocchio(key, owner, expected_size, true, false, false); + + assert!(check_account_balance_is_rent_exempt(&account, expected_size).is_ok()); + } + + // Pinocchio failure case (wrong size) + #[cfg(feature = "pinocchio")] + { + let key = [1u8; 32]; + let owner = [2u8; 32]; + let actual_size = 16; + let expected_size = 32; + let account = create_test_account_pinocchio(key, owner, actual_size, true, false, false); + + assert_eq!( + check_account_balance_is_rent_exempt(&account, expected_size), + Err(AccountError::InvalidAccountSize) + ); + } +} + +// Additional tests for functions that work with raw bytes (not requiring AccountInfo) +#[test] +fn test_set_discriminator() { + let mut bytes = vec![0; 16]; + assert!(set_discriminator::(&mut bytes).is_ok()); + assert_eq!(bytes[0..8], TestStruct::LIGHT_DISCRIMINATOR); + + // Test failure case (already initialized) + assert_eq!( + set_discriminator::(&mut bytes), + Err(AccountError::AlreadyInitialized) + ); +} + +#[test] +fn test_check_discriminator() { + let mut bytes = vec![0; 16]; + set_discriminator::(&mut bytes).unwrap(); + assert!(check_discriminator::(&bytes).is_ok()); + + // Test failure case (invalid discriminator) + let bytes = vec![0; 16]; // No discriminator set + assert_eq!( + check_discriminator::(&bytes), + Err(AccountError::InvalidDiscriminator) + ); + + // Test failure case (too small) + let bytes = vec![0; 4]; // Too small for discriminator + assert_eq!( + check_discriminator::(&bytes), + Err(AccountError::InvalidAccountSize) + ); +} + +#[test] +fn test_check_data_is_zeroed() { + let zeroed_data = [0u8; 32]; + assert!(check_data_is_zeroed::<8>(zeroed_data.as_slice()).is_ok()); + + // Test failure case (not zeroed) + let mut not_zeroed_data = [0u8; 32]; + not_zeroed_data[7] = 1; + assert_eq!( + check_data_is_zeroed::<8>(not_zeroed_data.as_slice()), + Err(AccountError::AccountNotZeroed) + ); +} + +// 15. get_min_rent_balance tests - 4 tests total +// TODO: Enable when sysvar is available in test environment +/* +#[test] +fn test_get_min_rent_balance() { + // Solana success case - get rent for different sizes + #[cfg(feature = "solana")] + { + use solana_account_info::AccountInfo; + + // Test with common account sizes + let small_rent = AccountInfo::get_min_rent_balance(100); + let large_rent = AccountInfo::get_min_rent_balance(1000); + + // Rent for larger accounts should be higher than smaller accounts + assert!(small_rent.is_ok()); + assert!(large_rent.is_ok()); + assert!(large_rent.unwrap() > small_rent.unwrap()); + assert_eq!(small_rent.unwrap(), 1002240); + assert_eq!(large_rent.unwrap(), 1009440); + + // Test with zero size + let zero_rent = AccountInfo::get_min_rent_balance(0); + assert!(zero_rent.is_ok()); + assert_eq!(zero_rent.unwrap(), 890880); + } + + // Pinocchio success case - test different feature configurations + #[cfg(feature = "pinocchio")] + { + use pinocchio::account_info::AccountInfo; + + // Test with common account sizes + let small_rent = AccountInfo::get_min_rent_balance(100); + let large_rent = AccountInfo::get_min_rent_balance(1000); + + // Should succeed under any feature configuration + assert!(small_rent.is_ok()); + assert!(large_rent.is_ok()); + + #[cfg(feature = "solana")] + { + // When solana feature is available, should behave like solana + assert!(large_rent.unwrap() > small_rent.unwrap()); + assert_eq!(small_rent.unwrap(), 1002240); + assert_eq!(large_rent.unwrap(), 1009440); + } + + #[cfg(not(feature = "solana"))] + { + // When solana feature is not available, should return 0 for testing + assert_eq!(small_rent.unwrap(), 0); + assert_eq!(large_rent.unwrap(), 0); + } + } +} +*/ diff --git a/program-libs/batched-merkle-tree/src/batch.rs b/program-libs/batched-merkle-tree/src/batch.rs index 9bb47955ec..d09b20cf68 100644 --- a/program-libs/batched-merkle-tree/src/batch.rs +++ b/program-libs/batched-merkle-tree/src/batch.rs @@ -3,7 +3,6 @@ use light_hasher::{Hasher, Poseidon}; use light_zero_copy::vec::ZeroCopyVecU64; use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; -// Import crate::msg from lib.rs which has the appropriate feature gates use crate::{errors::BatchedMerkleTreeError, BorshDeserialize, BorshSerialize}; #[derive(Clone, Debug, PartialEq, Eq, Copy)] @@ -170,8 +169,8 @@ impl Batch { } self.num_full_zkp_batches = 0; } else { - #[cfg(not(feature = "pinocchio"))] - crate::msg!( + #[cfg(feature = "solana")] + solana_msg::msg!( "Batch is in incorrect state {} expected BatchState::Inserted 1", self.state ); @@ -186,8 +185,8 @@ impl Batch { if self.get_state() == BatchState::Full { self.state = BatchState::Inserted.into(); } else { - #[cfg(not(feature = "pinocchio"))] - crate::msg!( + #[cfg(feature = "solana")] + solana_msg::msg!( "Batch is in incorrect state {} expected BatchState::Full 2", self.state ); @@ -202,8 +201,8 @@ impl Batch { if self.get_state() == BatchState::Fill { self.state = BatchState::Full.into(); } else { - #[cfg(not(feature = "pinocchio"))] - crate::msg!( + #[cfg(feature = "solana")] + solana_msg::msg!( "Batch is in incorrect state {} expected BatchState::Fill 0", self.state ); diff --git a/program-libs/batched-merkle-tree/src/initialize_address_tree.rs b/program-libs/batched-merkle-tree/src/initialize_address_tree.rs index 2acfab612b..714f0f31da 100644 --- a/program-libs/batched-merkle-tree/src/initialize_address_tree.rs +++ b/program-libs/batched-merkle-tree/src/initialize_address_tree.rs @@ -97,10 +97,10 @@ pub fn init_batched_address_merkle_tree_account( } None => 0, }; - #[cfg(not(feature = "pinocchio"))] - crate::msg!("rollover fee {}", rollover_fee); - #[cfg(not(feature = "pinocchio"))] - crate::msg!("rollover threshold {:?}", params.rollover_threshold); + #[cfg(feature = "solana")] + solana_msg::msg!("rollover fee {}", rollover_fee); + #[cfg(feature = "solana")] + solana_msg::msg!("rollover threshold {:?}", params.rollover_threshold); let metadata = MerkleTreeMetadata { next_merkle_tree: Pubkey::default(), diff --git a/program-libs/batched-merkle-tree/src/initialize_state_tree.rs b/program-libs/batched-merkle-tree/src/initialize_state_tree.rs index 1b9e14b47a..c618e63b59 100644 --- a/program-libs/batched-merkle-tree/src/initialize_state_tree.rs +++ b/program-libs/batched-merkle-tree/src/initialize_state_tree.rs @@ -136,8 +136,8 @@ pub fn init_batched_state_merkle_tree_accounts<'a>( None => 0, }; - #[cfg(not(feature = "pinocchio"))] - crate::msg!(" Output queue rollover_fee: {}", rollover_fee); + #[cfg(feature = "solana")] + solana_msg::msg!(" Output queue rollover_fee: {}", rollover_fee); let metadata = QueueMetadata { next_queue: Pubkey::default(), access_metadata: AccessMetadata::new(owner, params.program_owner, params.forester), diff --git a/program-libs/batched-merkle-tree/src/merkle_tree.rs b/program-libs/batched-merkle-tree/src/merkle_tree.rs index 5028f756a1..1738b674d9 100644 --- a/program-libs/batched-merkle-tree/src/merkle_tree.rs +++ b/program-libs/batched-merkle-tree/src/merkle_tree.rs @@ -250,12 +250,12 @@ impl<'a> BatchedMerkleTreeAccount<'a> { account_metadata.queue_batches.bloom_filter_capacity = bloom_filter_capacity; if account_data_len != account_metadata.get_account_size()? { - #[cfg(not(feature = "pinocchio"))] - crate::msg!("merkle_tree_metadata: {:?}", account_metadata); - #[cfg(not(feature = "pinocchio"))] - crate::msg!("account_data.len(): {}", account_data_len); - #[cfg(not(feature = "pinocchio"))] - crate::msg!( + #[cfg(feature = "solana")] + solana_msg::msg!("merkle_tree_metadata: {:?}", account_metadata); + #[cfg(feature = "solana")] + solana_msg::msg!("account_data.len(): {}", account_data_len); + #[cfg(feature = "solana")] + solana_msg::msg!( "account.get_account_size(): {}", account_metadata.get_account_size()? ); diff --git a/program-libs/batched-merkle-tree/src/queue.rs b/program-libs/batched-merkle-tree/src/queue.rs index a8dc0125a6..0d120fc1c4 100644 --- a/program-libs/batched-merkle-tree/src/queue.rs +++ b/program-libs/batched-merkle-tree/src/queue.rs @@ -238,10 +238,10 @@ impl<'a> BatchedQueueAccount<'a> { .batch_metadata .queue_account_size(account_metadata.metadata.queue_type)? { - #[cfg(not(feature = "pinocchio"))] - crate::msg!("account_data.len() {:?}", account_data_len); - #[cfg(not(feature = "pinocchio"))] - crate::msg!( + #[cfg(feature = "solana")] + solana_msg::msg!("account_data.len() {:?}", account_data_len); + #[cfg(feature = "solana")] + solana_msg::msg!( "queue_account_size {:?}", account_metadata .batch_metadata @@ -495,9 +495,9 @@ pub(crate) fn insert_into_current_queue_batch( current_batch.advance_state_to_fill(current_index)?; } else { // We expect to insert into the current batch. - #[cfg(not(feature = "pinocchio"))] + #[cfg(feature = "solana")] for batch in batch_metadata.batches.iter() { - crate::msg!("batch {:?}", batch); + solana_msg::msg!("batch {:?}", batch); } return Err(BatchedMerkleTreeError::BatchNotReady); } diff --git a/program-libs/batched-merkle-tree/tests/account_access.rs b/program-libs/batched-merkle-tree/tests/account_access.rs index ea5c49a3ef..ff45f13724 100644 --- a/program-libs/batched-merkle-tree/tests/account_access.rs +++ b/program-libs/batched-merkle-tree/tests/account_access.rs @@ -1,7 +1,7 @@ #![cfg(feature = "test-only")] #![cfg(feature = "solana")] -use light_account_checks::test_account_info::solana_program::TestAccount; +use light_account_checks::account_info::test_account_info::solana_program::TestAccount; use light_batched_merkle_tree::{ constants::{ACCOUNT_COMPRESSION_PROGRAM_ID, ADDRESS_TREE_INIT_ROOT_40}, initialize_address_tree::{ @@ -28,7 +28,7 @@ fn address_from_account_info() { let key = Pubkey::new_unique(); let owner = ACCOUNT_COMPRESSION_PROGRAM_ID; let mt_account_size = get_merkle_tree_account_size_default(); - let mut account = TestAccount::new(key, owner, mt_account_size); + let mut account = TestAccount::new(key, owner.into(), mt_account_size); let params = InitAddressTreeAccountsInstructionData::test_default(); let merkle_tree_rent = 1_000_000_000; @@ -92,8 +92,9 @@ fn state_from_account_info() { let owner = ACCOUNT_COMPRESSION_PROGRAM_ID; let mt_account_size = get_merkle_tree_account_size_default(); let output_queue_size = get_output_queue_account_size_default(); - let mut merkle_tree_account = TestAccount::new(key, owner, mt_account_size); - let mut output_queue_account = TestAccount::new(Pubkey::new_unique(), owner, output_queue_size); + let mut merkle_tree_account = TestAccount::new(key, owner.into(), mt_account_size); + let mut output_queue_account = + TestAccount::new(Pubkey::new_unique(), owner.into(), output_queue_size); let params = InitStateTreeAccountsInstructionData::test_default(); let merkle_tree_rent = 1_000_000_000; @@ -109,7 +110,7 @@ fn state_from_account_info() { let result = init_batched_state_merkle_tree_from_account_info( params, - owner, + owner.into(), &merkle_tree_account_info, &output_queue_account_info, additional_rent, @@ -123,7 +124,7 @@ fn state_from_account_info() { let result = init_batched_state_merkle_tree_from_account_info( params, - owner, + owner.into(), &merkle_tree_account_info, &output_queue_account_info, additional_rent, @@ -189,8 +190,9 @@ fn test_get_state_root_by_index() { let owner = ACCOUNT_COMPRESSION_PROGRAM_ID; let mt_account_size = get_merkle_tree_account_size_default(); let output_queue_size = get_output_queue_account_size_default(); - let mut merkle_tree_account = TestAccount::new(key, owner, mt_account_size); - let mut output_queue_account = TestAccount::new(Pubkey::new_unique(), owner, output_queue_size); + let mut merkle_tree_account = TestAccount::new(key, owner.into(), mt_account_size); + let mut output_queue_account = + TestAccount::new(Pubkey::new_unique(), owner.into(), output_queue_size); let params = InitStateTreeAccountsInstructionData::test_default(); let merkle_tree_rent = 1_000_000_000; @@ -206,7 +208,7 @@ fn test_get_state_root_by_index() { let result = init_batched_state_merkle_tree_from_account_info( params, - owner, + owner.into(), &merkle_tree_account_info, &output_queue_account_info, additional_rent, @@ -234,7 +236,7 @@ fn test_get_address_root_by_index() { let params = InitAddressTreeAccountsInstructionData::test_default(); let mt_account_size = get_address_merkle_tree_account_size_from_params(params); - let mut merkle_tree_account = TestAccount::new(key, owner, mt_account_size); + let mut merkle_tree_account = TestAccount::new(key, owner.into(), mt_account_size); let merkle_tree_rent = 1_000_000_000; merkle_tree_account.lamports = merkle_tree_rent; @@ -271,7 +273,7 @@ fn test_merkle_tree_getters() { let params = InitAddressTreeAccountsInstructionData::test_default(); let mt_account_size = get_address_merkle_tree_account_size_from_params(params); - let mut merkle_tree_account = TestAccount::new(key, owner, mt_account_size); + let mut merkle_tree_account = TestAccount::new(key, owner.into(), mt_account_size); let merkle_tree_rent = 1_000_000_000; merkle_tree_account.lamports = merkle_tree_rent; diff --git a/program-libs/bloom-filter/src/lib.rs b/program-libs/bloom-filter/src/lib.rs index 0ea6bb787c..f3bd8384d0 100644 --- a/program-libs/bloom-filter/src/lib.rs +++ b/program-libs/bloom-filter/src/lib.rs @@ -19,14 +19,14 @@ impl From for u32 { } } -#[cfg(all(feature = "solana", not(feature = "pinocchio")))] +#[cfg(feature = "solana")] impl From for solana_program_error::ProgramError { fn from(e: BloomFilterError) -> Self { solana_program_error::ProgramError::Custom(e.into()) } } -#[cfg(all(feature = "pinocchio", not(feature = "solana")))] +#[cfg(feature = "pinocchio")] impl From for pinocchio::program_error::ProgramError { fn from(e: BloomFilterError) -> Self { pinocchio::program_error::ProgramError::Custom(e.into()) diff --git a/program-libs/concurrent-merkle-tree/Cargo.toml b/program-libs/concurrent-merkle-tree/Cargo.toml index d3622d3f19..6cfb1b19cb 100644 --- a/program-libs/concurrent-merkle-tree/Cargo.toml +++ b/program-libs/concurrent-merkle-tree/Cargo.toml @@ -8,20 +8,12 @@ license = "Apache-2.0" [features] heavy-tests = [] -solana = [ - "solana-program-error", - "light-bounded-vec/solana", - "light-hasher/solana", -] -pinocchio = [ - "dep:pinocchio", - "light-bounded-vec/solana", - "light-hasher/pinocchio", -] +solana = ["solana-program-error", "light-hasher/solana"] +pinocchio = ["dep:pinocchio", "light-hasher/pinocchio"] [dependencies] borsh = { workspace = true } -light-bounded-vec = { workspace = true } +light-bounded-vec = { workspace = true, features = ["solana"] } light-hasher = { workspace = true } memoffset = "0.9" solana-program-error = { workspace = true, optional = true } diff --git a/program-libs/concurrent-merkle-tree/src/errors.rs b/program-libs/concurrent-merkle-tree/src/errors.rs index d54da20ea9..3e12e17fdd 100644 --- a/program-libs/concurrent-merkle-tree/src/errors.rs +++ b/program-libs/concurrent-merkle-tree/src/errors.rs @@ -38,7 +38,6 @@ pub enum ConcurrentMerkleTreeError { BoundedVec(#[from] BoundedVecError), } -#[cfg(any(feature = "solana", feature = "pinocchio"))] impl From for u32 { fn from(e: ConcurrentMerkleTreeError) -> u32 { match e { @@ -62,14 +61,14 @@ impl From for u32 { } } -#[cfg(all(feature = "solana", not(feature = "pinocchio")))] +#[cfg(feature = "solana")] impl From for solana_program_error::ProgramError { fn from(e: ConcurrentMerkleTreeError) -> Self { solana_program_error::ProgramError::Custom(e.into()) } } -#[cfg(all(feature = "pinocchio", not(feature = "solana")))] +#[cfg(feature = "pinocchio")] impl From for pinocchio::program_error::ProgramError { fn from(e: ConcurrentMerkleTreeError) -> Self { pinocchio::program_error::ProgramError::Custom(e.into()) diff --git a/program-libs/hasher/Cargo.toml b/program-libs/hasher/Cargo.toml index 8e54319788..5f1c4cbb4b 100644 --- a/program-libs/hasher/Cargo.toml +++ b/program-libs/hasher/Cargo.toml @@ -7,7 +7,7 @@ license = "Apache-2.0" edition = "2021" [features] -default = ["solana"] +default = [] solana = ["solana-program-error", "solana-pubkey"] pinocchio = ["dep:pinocchio"] diff --git a/program-libs/hasher/src/errors.rs b/program-libs/hasher/src/errors.rs index 9849db11d3..dcba85c721 100644 --- a/program-libs/hasher/src/errors.rs +++ b/program-libs/hasher/src/errors.rs @@ -45,9 +45,16 @@ impl From for u32 { } } -#[cfg(any(feature = "solana", feature = "pinocchio"))] -impl From for crate::ProgramError { +#[cfg(feature = "solana")] +impl From for solana_program_error::ProgramError { fn from(e: HasherError) -> Self { - crate::ProgramError::Custom(e.into()) + solana_program_error::ProgramError::Custom(e.into()) + } +} + +#[cfg(feature = "pinocchio")] +impl From for pinocchio::program_error::ProgramError { + fn from(e: HasherError) -> Self { + pinocchio::program_error::ProgramError::Custom(e.into()) } } diff --git a/program-libs/hasher/src/hash_to_field_size.rs b/program-libs/hasher/src/hash_to_field_size.rs index e01da7862f..2e7b67c4d3 100644 --- a/program-libs/hasher/src/hash_to_field_size.rs +++ b/program-libs/hasher/src/hash_to_field_size.rs @@ -139,7 +139,7 @@ mod tests { assert_eq!(hash, manual_hash); } - #[cfg(not(feature = "pinocchio"))] + #[cfg(feature = "solana")] #[test] fn test_hash_to_bn254_field_size_be() { use solana_pubkey::Pubkey; @@ -160,7 +160,7 @@ mod tests { ); } - #[cfg(not(feature = "pinocchio"))] + #[cfg(feature = "solana")] #[test] fn test_hashv_to_bn254_field_size_be() { use solana_pubkey::Pubkey; diff --git a/program-libs/hasher/src/lib.rs b/program-libs/hasher/src/lib.rs index 54985ee29d..9f4e4758c0 100644 --- a/program-libs/hasher/src/lib.rs +++ b/program-libs/hasher/src/lib.rs @@ -29,8 +29,3 @@ pub trait Hasher { fn zero_bytes() -> ZeroBytes; fn zero_indexed_leaf() -> [u8; 32]; } - -#[cfg(feature = "pinocchio")] -use pinocchio::program_error::ProgramError; -#[cfg(not(feature = "pinocchio"))] -use solana_program_error::ProgramError; diff --git a/program-libs/indexed-merkle-tree/src/errors.rs b/program-libs/indexed-merkle-tree/src/errors.rs index 108929a6eb..7a882ddc16 100644 --- a/program-libs/indexed-merkle-tree/src/errors.rs +++ b/program-libs/indexed-merkle-tree/src/errors.rs @@ -57,7 +57,7 @@ impl From for pinocchio::program_error::ProgramError { pinocchio::program_error::ProgramError::Custom(e.into()) } } -#[cfg(not(feature = "pinocchio"))] +#[cfg(feature = "solana")] impl From for solana_program_error::ProgramError { fn from(e: IndexedMerkleTreeError) -> Self { solana_program_error::ProgramError::Custom(e.into()) diff --git a/program-libs/verifier/Cargo.toml b/program-libs/verifier/Cargo.toml index 04be7e2740..c5d6aa0586 100644 --- a/program-libs/verifier/Cargo.toml +++ b/program-libs/verifier/Cargo.toml @@ -7,7 +7,7 @@ license = "Apache-2.0" edition = "2021" [features] -default = ["solana"] +default = [] solana = [ "solana-program-error", "light-compressed-account/solana", diff --git a/program-libs/verifier/src/lib.rs b/program-libs/verifier/src/lib.rs index 4fdf2f2a5e..b7804175ee 100644 --- a/program-libs/verifier/src/lib.rs +++ b/program-libs/verifier/src/lib.rs @@ -39,7 +39,7 @@ impl From for u32 { } } -#[cfg(not(feature = "pinocchio"))] +#[cfg(feature = "solana")] impl From for solana_program_error::ProgramError { fn from(e: VerifierError) -> Self { solana_program_error::ProgramError::Custom(e.into()) @@ -218,7 +218,7 @@ pub fn select_verifying_key<'a>( num_leaves: usize, num_addresses: usize, ) -> Result<&'a Groth16Verifyingkey<'static>, VerifierError> { - #[cfg(all(not(feature = "pinocchio"), target_os = "solana"))] + #[cfg(all(feature = "solana", target_os = "solana"))] solana_msg::msg!( "select_verifying_key num_leaves: {}, num_addresses: {}", num_leaves, @@ -273,7 +273,7 @@ pub fn verify( let proof_c = decompress_g1(&proof.c).map_err(|_| crate::DecompressG1Failed)?; let mut verifier = Groth16Verifier::new(&proof_a, &proof_b, &proof_c, public_inputs, vk) .map_err(|_| { - #[cfg(all(target_os = "solana", not(feature = "pinocchio")))] + #[cfg(all(target_os = "solana", feature = "solana"))] { use solana_msg::msg; msg!("Proof verification failed"); @@ -285,7 +285,7 @@ pub fn verify( CreateGroth16VerifierFailed })?; verifier.verify().map_err(|_| { - #[cfg(all(target_os = "solana", not(feature = "pinocchio")))] + #[cfg(all(target_os = "solana", feature = "solana"))] { use solana_msg::msg; msg!("Proof verification failed"); diff --git a/program-tests/account-compression-test/tests/address_merkle_tree_tests.rs b/program-tests/account-compression-test/tests/address_merkle_tree_tests.rs index 4f9394ffdd..1a67f70052 100644 --- a/program-tests/account-compression-test/tests/address_merkle_tree_tests.rs +++ b/program-tests/account-compression-test/tests/address_merkle_tree_tests.rs @@ -506,10 +506,10 @@ async fn test_address_queue_and_tree_invalid_config() { /// Tests: /// 1. cannot insert the same address twice /// 2. cannot insert an address with an invalid low address -/// 2.1 cannot insert an address with an invalid low address (NewElementGreaterOrEqualToNextElement) -/// 2.2 cannot insert an address with an invalid low address (LowElementGreaterOrEqualToNewElement) -/// 3.1 invalid value index (element does not exist) -/// 3.2 invalid value index (element has a sequence number) +/// 2.1 cannot insert an address with an invalid low address (NewElementGreaterOrEqualToNextElement) +/// 2.2 cannot insert an address with an invalid low address (LowElementGreaterOrEqualToNewElement) +/// 3.1 invalid value index (element does not exist) +/// 3.2 invalid value index (element has a sequence number) /// 4. invalid low element index /// 5. invalid low element value /// 6. invalid low element next index diff --git a/program-tests/account-compression-test/tests/merkle_tree_tests.rs b/program-tests/account-compression-test/tests/merkle_tree_tests.rs index f393193520..386d223b87 100644 --- a/program-tests/account-compression-test/tests/merkle_tree_tests.rs +++ b/program-tests/account-compression-test/tests/merkle_tree_tests.rs @@ -12,9 +12,7 @@ use account_compression::{ }; use anchor_lang::{InstructionData, ToAccountMetas}; use light_account_checks::error::AccountError; -use light_compressed_account::instruction_data::{ - data::pack_pubkey, insert_into_queues::InsertIntoQueuesInstructionDataMut, -}; +use light_compressed_account::instruction_data::insert_into_queues::InsertIntoQueuesInstructionDataMut; use light_concurrent_merkle_tree::{ errors::ConcurrentMerkleTreeError, event::MerkleTreeEvent, zero_copy::ConcurrentMerkleTreeZeroCopyMut, @@ -39,6 +37,7 @@ use light_test_utils::{ assert_queue::assert_nullifier_queue_initialized, create_account_instruction, create_address_merkle_tree_and_queue_account_with_assert, get_concurrent_merkle_tree, get_hash_set, + pack::pack_pubkey, state_tree_rollover::{ assert_rolled_over_pair, perform_state_merkle_tree_roll_over, set_state_merkle_tree_next_index, StateMerkleTreeRolloverMode, @@ -227,7 +226,7 @@ async fn test_init_and_insert_into_nullifier_queue_custom() { /// 3. try to insert again it should still generate the full error /// 4. advance Merkle tree seq until one before it would work check that it still fails /// 5. advance Merkle tree seq by one and check that inserting works now -/// 6.try inserting again it should fail with full error +/// 6.try inserting again it should fail with full error async fn test_full_nullifier_queue( merkle_tree_config: &StateMerkleTreeConfig, queue_config: &NullifierQueueConfig, @@ -420,12 +419,12 @@ async fn test_full_nullifier_queue_default() { /// 1. no nullifiers /// 2. mismatch remaining accounts and addresses (removed error) /// 3. invalid queue accounts: -/// 3.1 pass non queue account as queue account -/// 3.2 pass address queue account -/// 3.3 pass non associated queue account +/// 3.1 pass non queue account as queue account +/// 3.2 pass address queue account +/// 3.3 pass non associated queue account /// 4. invalid Merkle tree accounts: -/// 4.1 pass non Merkle tree account as Merkle tree account -/// 4.2 pass non associated Merkle tree account +/// 4.1 pass non Merkle tree account as Merkle tree account +/// 4.2 pass non associated Merkle tree account async fn failing_queue( merkle_tree_config: &StateMerkleTreeConfig, queue_config: &NullifierQueueConfig, diff --git a/program-tests/client-test/tests/light_client.rs b/program-tests/client-test/tests/light_client.rs index eb813c85fe..ba86a6b791 100644 --- a/program-tests/client-test/tests/light_client.rs +++ b/program-tests/client-test/tests/light_client.rs @@ -651,7 +651,7 @@ async fn create_address( let output_account = light_compressed_account::compressed_account::CompressedAccount { lamports, - owner, + owner: owner.into(), data: None, address: Some(address), }; @@ -669,8 +669,8 @@ async fn create_address( let new_address_params = NewAddressParams { seed: address_seed, - address_queue_pubkey: address_merkle_tree.queue, - address_merkle_tree_pubkey: address_merkle_tree.tree, + address_queue_pubkey: address_merkle_tree.queue.into(), + address_merkle_tree_pubkey: address_merkle_tree.tree.into(), address_merkle_tree_root_index: rpc_proof_result.value.addresses[0].root_index, }; let compute_budget_ix = ComputeBudgetInstruction::set_compute_unit_limit(500_000); diff --git a/program-tests/client-test/tests/light_program_test.rs b/program-tests/client-test/tests/light_program_test.rs index 82ead2d3a2..374dd6a21c 100644 --- a/program-tests/client-test/tests/light_program_test.rs +++ b/program-tests/client-test/tests/light_program_test.rs @@ -638,7 +638,7 @@ async fn create_address( let output_account = light_compressed_account::compressed_account::CompressedAccount { lamports, - owner, + owner: owner.into(), data: None, address: Some(address), }; @@ -656,8 +656,8 @@ async fn create_address( let new_address_params = NewAddressParams { seed: address_seed, - address_queue_pubkey: address_merkle_tree.queue, - address_merkle_tree_pubkey: address_merkle_tree.tree, + address_queue_pubkey: address_merkle_tree.queue.into(), + address_merkle_tree_pubkey: address_merkle_tree.tree.into(), address_merkle_tree_root_index: rpc_proof_result.value.addresses[0].root_index, }; let compute_budget_ix = ComputeBudgetInstruction::set_compute_unit_limit(500_000); diff --git a/program-tests/compressed-token-test/tests/test.rs b/program-tests/compressed-token-test/tests/test.rs index a7daa67727..d18b13c77a 100644 --- a/program-tests/compressed-token-test/tests/test.rs +++ b/program-tests/compressed-token-test/tests/test.rs @@ -1624,7 +1624,8 @@ async fn test_mint_to_and_burn_from_all_token_pools() { let change_account_merkle_tree = input_compressed_account .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); burn_test( &payer, &mut rpc, @@ -1867,7 +1868,8 @@ async fn test_delegation( let delegated_compressed_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); approve_test( &sender, &mut rpc, @@ -2007,7 +2009,8 @@ async fn test_delegation_mixed() { let delegated_compressed_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); approve_test( &sender, &mut rpc, @@ -2244,7 +2247,8 @@ async fn test_approve_failing() { let delegated_compressed_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); let input_compressed_account_hashes = input_compressed_accounts .iter() @@ -2535,7 +2539,8 @@ async fn test_revoke(num_inputs: usize, mint_amount: u64, delegated_amount: u64) let delegated_compressed_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); approve_test( &sender, &mut rpc, @@ -2572,7 +2577,8 @@ async fn test_revoke(num_inputs: usize, mint_amount: u64, delegated_amount: u64) let delegated_compressed_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); revoke_test( &sender, &mut rpc, @@ -2658,7 +2664,8 @@ async fn test_revoke_failing() { let delegated_compressed_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); approve_test( &sender, &mut rpc, @@ -2885,7 +2892,8 @@ async fn test_burn() { let change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); burn_test( &sender, &mut rpc, @@ -2912,7 +2920,8 @@ async fn test_burn() { let delegated_compressed_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); approve_test( &sender, &mut rpc, @@ -2944,7 +2953,8 @@ async fn test_burn() { let change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); burn_test( &delegate, &mut rpc, @@ -2979,7 +2989,8 @@ async fn test_burn() { let change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); burn_test( &delegate, &mut rpc, @@ -3029,7 +3040,8 @@ async fn test_burn() { let invalid_change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .queue_pubkey; + .queue_pubkey + .into(); let mut additional_token_pool_accounts = (0..4) .map(|x| get_token_pool_pda_with_index(&mint, x)) .collect::>(); @@ -3158,7 +3170,8 @@ async fn failing_tests_burn() { let delegated_compressed_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); approve_test( &sender, &mut rpc, @@ -3185,7 +3198,8 @@ async fn failing_tests_burn() { let change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); let (_, _, _, _, instruction) = create_burn_test_instruction( &sender, &mut rpc, @@ -3218,7 +3232,8 @@ async fn failing_tests_burn() { let change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); let (_, _, _, _, instruction) = create_burn_test_instruction( &delegate, &mut rpc, @@ -3259,7 +3274,8 @@ async fn failing_tests_burn() { let change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); let (_, _, _, _, instruction) = create_burn_test_instruction( &sender, &mut rpc, @@ -3291,7 +3307,8 @@ async fn failing_tests_burn() { let change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); let (_, _, _, _, instruction) = create_burn_test_instruction( &delegate, &mut rpc, @@ -3327,7 +3344,8 @@ async fn failing_tests_burn() { let change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); let (_, _, _, _, instruction) = create_burn_test_instruction( &sender, &mut rpc, @@ -3364,7 +3382,8 @@ async fn failing_tests_burn() { let invalid_change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .queue_pubkey; + .queue_pubkey + .into(); let (_, _, _, _, instruction) = create_burn_test_instruction( &sender, &mut rpc, @@ -3401,7 +3420,8 @@ async fn failing_tests_burn() { let invalid_change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .queue_pubkey; + .queue_pubkey + .into(); let (_, _, _, _, instruction) = create_burn_test_instruction( &sender, &mut rpc, @@ -3433,7 +3453,8 @@ async fn failing_tests_burn() { let invalid_change_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .queue_pubkey; + .queue_pubkey + .into(); let (_, _, _, _, mut instruction) = create_burn_test_instruction( &sender, &mut rpc, @@ -3515,7 +3536,8 @@ async fn test_freeze_and_thaw(mint_amount: u64, delegated_amount: u64) { let output_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); freeze_test( &payer, @@ -3543,7 +3565,8 @@ async fn test_freeze_and_thaw(mint_amount: u64, delegated_amount: u64) { let output_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); thaw_test( &payer, &mut rpc, @@ -3565,7 +3588,8 @@ async fn test_freeze_and_thaw(mint_amount: u64, delegated_amount: u64) { let delegated_compressed_account_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); approve_test( &sender, &mut rpc, @@ -3591,7 +3615,8 @@ async fn test_freeze_and_thaw(mint_amount: u64, delegated_amount: u64) { let output_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); freeze_test( &payer, @@ -3619,7 +3644,8 @@ async fn test_freeze_and_thaw(mint_amount: u64, delegated_amount: u64) { let output_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); thaw_test( &payer, @@ -3706,7 +3732,8 @@ async fn test_failing_freeze() { let outputs_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); let input_compressed_account_hashes = input_compressed_accounts .iter() @@ -3863,7 +3890,8 @@ async fn test_failing_freeze() { let outputs_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); let input_compressed_account_hashes = input_compressed_accounts .iter() @@ -3974,7 +4002,8 @@ async fn test_failing_thaw() { let output_merkle_tree = input_compressed_accounts[0] .compressed_account .merkle_context - .merkle_tree_pubkey; + .merkle_tree_pubkey + .into(); freeze_test( &payer, @@ -4034,7 +4063,7 @@ async fn test_failing_thaw() { .map(|x| &x.compressed_account.compressed_account) .cloned() .collect::>(), - outputs_merkle_tree, + outputs_merkle_tree: outputs_merkle_tree.into(), root_indices: proof_rpc_result.value.get_root_indices().clone(), proof: proof_rpc_result.value.proof.0.unwrap(), }; @@ -4113,7 +4142,7 @@ async fn test_failing_thaw() { .map(|x| &x.compressed_account.compressed_account) .cloned() .collect::>(), - outputs_merkle_tree, + outputs_merkle_tree: outputs_merkle_tree.into(), root_indices: proof_rpc_result.value.get_root_indices().clone(), proof: invalid_proof, }; @@ -4175,7 +4204,7 @@ async fn test_failing_thaw() { .map(|x| &x.compressed_account.compressed_account) .cloned() .collect::>(), - outputs_merkle_tree, + outputs_merkle_tree: outputs_merkle_tree.into(), root_indices: proof_rpc_result.value.get_root_indices().clone(), proof: proof_rpc_result.value.proof.0.unwrap(), }; @@ -5259,8 +5288,8 @@ async fn perform_transfer_failing_test( &input_compressed_accounts .iter() .map(|x| MerkleContext { - merkle_tree_pubkey: *merkle_tree_pubkey, - queue_pubkey: *nullifier_queue_pubkey, + merkle_tree_pubkey: (*merkle_tree_pubkey).into(), + queue_pubkey: (*nullifier_queue_pubkey).into(), leaf_index: x.merkle_context.leaf_index, prove_by_index: false, tree_type: TreeType::StateV1, diff --git a/program-tests/create-address-test-program/src/create_pda.rs b/program-tests/create-address-test-program/src/create_pda.rs index d42f606160..eceefaceeb 100644 --- a/program-tests/create-address-test-program/src/create_pda.rs +++ b/program-tests/create-address-test-program/src/create_pda.rs @@ -97,9 +97,7 @@ fn create_compressed_pda_data( let compressed_account_data = CompressedAccountData { discriminator: 1u64.to_le_bytes(), data: timelock_compressed_pda.try_to_vec().unwrap(), - data_hash: timelock_compressed_pda - .hash::() - .map_err(ProgramError::from)?, + data_hash: timelock_compressed_pda.hash::().unwrap(), }; let mut discriminator_bytes = [0u8; 8]; @@ -117,7 +115,7 @@ fn create_compressed_pda_data( Ok(OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: crate::ID, // should be crate::ID, test can provide an invalid owner + owner: crate::ID.into(), // should be crate::ID, test can provide an invalid owner lamports: 0, address: Some(address), data: Some(compressed_account_data), diff --git a/program-tests/e2e-test/tests/test.rs b/program-tests/e2e-test/tests/test.rs index f4314eb6b7..efcec09dae 100644 --- a/program-tests/e2e-test/tests/test.rs +++ b/program-tests/e2e-test/tests/test.rs @@ -42,10 +42,12 @@ async fn test_10_all() { .await; let mut config = KeypairActionConfig::test_default(); config.fee_assert = false; - let mut general_config = GeneralActionConfig::default(); - general_config.rollover = None; - general_config.create_address_mt = None; - general_config.create_state_mt = None; + let general_config = GeneralActionConfig { + create_address_mt: None, + create_state_mt: None, + rollover: None, + ..GeneralActionConfig::default() + }; let test_accounts = rpc.test_accounts.clone(); let mut env = E2ETestEnv::::new( rpc, @@ -95,13 +97,14 @@ async fn test_batched_only() { .await; let mut config = KeypairActionConfig::test_default(); config.fee_assert = false; - let mut general_config = GeneralActionConfig::default(); - general_config.rollover = None; - general_config.create_address_mt = None; - general_config.create_state_mt = None; - general_config.add_keypair = None; - general_config.rollover = None; - general_config.add_forester = None; + let general_config = GeneralActionConfig { + rollover: None, + create_address_mt: None, + create_state_mt: None, + add_keypair: None, + add_forester: None, + ..GeneralActionConfig::default() + }; let mut env = E2ETestEnv::::new( rpc, indexer, diff --git a/program-tests/registry-test/tests/tests.rs b/program-tests/registry-test/tests/tests.rs index b197fb9c54..fc46aa8a35 100644 --- a/program-tests/registry-test/tests/tests.rs +++ b/program-tests/registry-test/tests/tests.rs @@ -1450,7 +1450,11 @@ async fn test_migrate_state() { .get_state_merkle_trees() .iter() .find(|b| { - b.accounts.merkle_tree == compressed_account.merkle_context.merkle_tree_pubkey + b.accounts.merkle_tree.to_bytes() + == compressed_account + .merkle_context + .merkle_tree_pubkey + .to_bytes() }) .unwrap(); assert_eq!(merkle_tree.root(), bundle.merkle_tree.root()); @@ -1498,7 +1502,11 @@ async fn test_migrate_state() { .get_state_merkle_trees_mut() .iter_mut() .find(|b| { - b.accounts.merkle_tree == compressed_account.merkle_context.merkle_tree_pubkey + b.accounts.merkle_tree.to_bytes() + == compressed_account + .merkle_context + .merkle_tree_pubkey + .to_bytes() }) .unwrap(); bundle @@ -1533,7 +1541,11 @@ async fn test_migrate_state() { .get_state_merkle_trees() .iter() .find(|b| { - b.accounts.merkle_tree == compressed_account.merkle_context.merkle_tree_pubkey + b.accounts.merkle_tree.to_bytes() + == compressed_account + .merkle_context + .merkle_tree_pubkey + .to_bytes() }) .unwrap(); assert_eq!(merkle_tree.root(), bundle.merkle_tree.root()); @@ -1864,8 +1876,10 @@ async fn test_batch_address_tree() { let mut test_indexer = TestIndexer::init_from_acounts(&payer, &env, 50).await; { let new_merkle_tree = Keypair::new(); - let mut test_tree_params = InitAddressTreeAccountsInstructionData::default(); - test_tree_params.network_fee = Some(1); + let test_tree_params = InitAddressTreeAccountsInstructionData { + network_fee: Some(1), + ..Default::default() + }; let result = create_batch_address_merkle_tree(&mut rpc, &payer, &new_merkle_tree, test_tree_params) .await; diff --git a/program-tests/sdk-anchor-test/programs/sdk-anchor-test/src/lib.rs b/program-tests/sdk-anchor-test/programs/sdk-anchor-test/src/lib.rs index 38fccc2a7a..72f9dabcb3 100644 --- a/program-tests/sdk-anchor-test/programs/sdk-anchor-test/src/lib.rs +++ b/program-tests/sdk-anchor-test/programs/sdk-anchor-test/src/lib.rs @@ -23,7 +23,6 @@ pub mod sdk_anchor_test { output_tree_index: u8, name: String, ) -> Result<()> { - let program_id = crate::ID.into(); let light_cpi_accounts = CpiAccounts::new( ctx.accounts.signer.as_ref(), ctx.remaining_accounts, @@ -46,7 +45,7 @@ pub mod sdk_anchor_test { }; let mut my_compressed_account = LightAccount::<'_, MyCompressedAccount>::new_init( - &program_id, + &crate::ID, Some(address), output_tree_index, ); @@ -76,9 +75,8 @@ pub mod sdk_anchor_test { account_meta: CompressedAccountMeta, nested_data: NestedData, ) -> Result<()> { - let program_id = crate::ID.into(); let mut my_compressed_account = LightAccount::<'_, MyCompressedAccount>::new_mut( - &program_id, + &crate::ID, &account_meta, my_compressed_account, ) diff --git a/program-tests/sdk-test/src/create_pda.rs b/program-tests/sdk-test/src/create_pda.rs index cd0b9e8273..980c47678e 100644 --- a/program-tests/sdk-test/src/create_pda.rs +++ b/program-tests/sdk-test/src/create_pda.rs @@ -10,7 +10,7 @@ use light_sdk::{ instruction::tree_info::PackedAddressTreeInfo, LightDiscriminator, LightHasher, NewAddressParamsPacked, ValidityProof, }; -use solana_program::{account_info::AccountInfo, program_error::ProgramError}; +use solana_program::account_info::AccountInfo; /// CU usage: /// - sdk pre system program cpi 10,942 CU @@ -41,7 +41,7 @@ pub fn create_pda( b"compressed", instruction_data.data.as_slice(), ]) - .map_err(ProgramError::from)?; + .unwrap(); let address = light_compressed_account::address::derive_address( &address_seed, &cpi_accounts.tree_accounts()[instruction_data @@ -69,9 +69,8 @@ pub fn create_pda( address_merkle_tree_account_index: address_tree_info.address_merkle_tree_pubkey_index, }; - let program_id = crate::ID.into(); let mut my_compressed_account = LightAccount::<'_, MyCompressedAccount>::new_init( - &program_id, + &crate::ID, Some(address), instruction_data.output_merkle_tree_index, ); diff --git a/program-tests/sdk-test/src/update_pda.rs b/program-tests/sdk-test/src/update_pda.rs index 07c2a0ccb4..6aa4c75cb5 100644 --- a/program-tests/sdk-test/src/update_pda.rs +++ b/program-tests/sdk-test/src/update_pda.rs @@ -24,9 +24,8 @@ pub fn update_pda( let instruction_data = UpdatePdaInstructionData::deserialize(&mut instruction_data) .map_err(|_| LightSdkError::Borsh)?; - let program_id = crate::ID.into(); let mut my_compressed_account = LightAccount::<'_, MyCompressedAccount>::new_mut( - &program_id, + &crate::ID, &instruction_data.my_compressed_account.meta, MyCompressedAccount { data: instruction_data.my_compressed_account.data, diff --git a/program-tests/sdk-test/tests/test.rs b/program-tests/sdk-test/tests/test.rs index 6c223045ce..8d4ec91bb4 100644 --- a/program-tests/sdk-test/tests/test.rs +++ b/program-tests/sdk-test/tests/test.rs @@ -1,4 +1,4 @@ -// #![cfg(feature = "test-sbf")] +#![cfg(feature = "test-sbf")] use borsh::BorshSerialize; use light_compressed_account::{ @@ -44,7 +44,7 @@ async fn test_sdk_test() { &address_tree_pubkey.to_bytes(), &sdk_test::ID.to_bytes(), ); - let ouput_queue = rpc.get_state_merkle_tree_v2().output_queue; + let ouput_queue = rpc.get_random_state_tree_info().queue; create_pda( &payer, &mut rpc, diff --git a/program-tests/system-cpi-test/Cargo.toml b/program-tests/system-cpi-test/Cargo.toml index b49b5dfb54..a2bfa77ddb 100644 --- a/program-tests/system-cpi-test/Cargo.toml +++ b/program-tests/system-cpi-test/Cargo.toml @@ -34,12 +34,12 @@ light-account-checks = { workspace = true } [target.'cfg(not(target_os = "solana"))'.dependencies] solana-sdk = { workspace = true } +light-test-utils = { workspace = true, features = ["devenv"] } [dev-dependencies] light-client = { workspace = true, features = ["devenv"] } light-sdk = { workspace = true, features = ["anchor"] } light-program-test = { workspace = true, features = ["devenv"] } -light-test-utils = { workspace = true, features = ["devenv"] } tokio = { workspace = true } light-prover-client = { workspace = true, features = ["devenv"] } light-verifier = { workspace = true } diff --git a/program-tests/system-cpi-test/src/create_pda.rs b/program-tests/system-cpi-test/src/create_pda.rs index 74f1c20e93..a5914ee079 100644 --- a/program-tests/system-cpi-test/src/create_pda.rs +++ b/program-tests/system-cpi-test/src/create_pda.rs @@ -250,7 +250,7 @@ fn cpi_compressed_pda_transfer_as_program<'info>( CreatePdaMode::WriteToAccountNotOwned => { // account with data needs to be owned by the program let mut compressed_pda = compressed_pda; - compressed_pda.compressed_account.owner = ctx.accounts.signer.key(); + compressed_pda.compressed_account.owner = ctx.accounts.signer.key().into(); compressed_pda } CreatePdaMode::NoData => { @@ -489,9 +489,7 @@ fn create_compressed_pda_data( let compressed_account_data = CompressedAccountData { discriminator: 1u64.to_le_bytes(), data: timelock_compressed_pda.try_to_vec().unwrap(), - data_hash: timelock_compressed_pda - .hash::() - .map_err(ProgramError::from)?, + data_hash: timelock_compressed_pda.hash::().unwrap(), }; let discriminator_bytes = &ctx.remaining_accounts [new_address_params.address_merkle_tree_account_index as usize] @@ -500,10 +498,11 @@ fn create_compressed_pda_data( let address = match discriminator_bytes { AddressMerkleTreeAccount::DISCRIMINATOR => derive_address_legacy( &ctx.remaining_accounts[new_address_params.address_merkle_tree_account_index as usize] - .key(), + .key() + .into(), &new_address_params.seed, ) - .map_err(ProgramError::from)?, + .unwrap(), BatchedMerkleTreeAccount::LIGHT_DISCRIMINATOR_SLICE => derive_address( &new_address_params.seed, &ctx.remaining_accounts[new_address_params.address_merkle_tree_account_index as usize] @@ -529,7 +528,7 @@ fn create_compressed_pda_data( Ok(OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: *owner_program, // should be crate::ID, test can provide an invalid owner + owner: owner_program.into(), // should be crate::ID, test can provide an invalid owner lamports: 0, address: Some(address), data: Some(compressed_account_data), diff --git a/program-tests/system-cpi-test/src/invalidate_not_owned_account.rs b/program-tests/system-cpi-test/src/invalidate_not_owned_account.rs index 60fb9cb11d..e44f2a98b7 100644 --- a/program-tests/system-cpi-test/src/invalidate_not_owned_account.rs +++ b/program-tests/system-cpi-test/src/invalidate_not_owned_account.rs @@ -127,7 +127,7 @@ pub fn process_invalidate_not_owned_compressed_account<'info>( vec![OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { data: compressed_account.compressed_account.data.clone(), - owner: light_compressed_token::ID, + owner: light_compressed_token::ID.into(), lamports: 0, address: compressed_account.compressed_account.address, }, @@ -611,7 +611,7 @@ fn write_into_cpi_account<'info>( let compressed_pda = OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { data: compressed_account.compressed_account.data.clone(), - owner: ID, + owner: ID.into(), lamports: 0, address: compressed_account.compressed_account.address, }, diff --git a/program-tests/system-cpi-test/src/sdk.rs b/program-tests/system-cpi-test/src/sdk.rs index 1ebb015e39..7abb189bf8 100644 --- a/program-tests/system-cpi-test/src/sdk.rs +++ b/program-tests/system-cpi-test/src/sdk.rs @@ -22,6 +22,7 @@ use light_compressed_token::{ get_token_pool_pda, process_transfer::transfer_sdk::to_account_metas, }; use light_system_program::utils::get_registered_program_pda; +use light_test_utils::e2e_test_env::to_account_metas_light; use solana_sdk::{instruction::Instruction, pubkey::Pubkey}; use crate::CreatePdaMode; @@ -46,9 +47,11 @@ pub struct CreateCompressedPdaInstructionInputs<'a> { pub fn create_pda_instruction(input_params: CreateCompressedPdaInstructionInputs) -> Instruction { let (cpi_signer, bump) = Pubkey::find_program_address(&[CPI_AUTHORITY_PDA_SEED], &crate::id()); - let mut remaining_accounts = HashMap::new(); + let mut remaining_accounts = HashMap::::new(); remaining_accounts.insert( - *input_params.output_compressed_account_merkle_tree_pubkey, + input_params + .output_compressed_account_merkle_tree_pubkey + .into(), 0, ); let new_address_params = @@ -110,7 +113,7 @@ pub fn create_pda_instruction(input_params: CreateCompressedPdaInstructionInputs cpi_signer, system_program: solana_sdk::system_program::id(), }; - let remaining_accounts = to_account_metas(remaining_accounts); + let remaining_accounts = to_account_metas_light(remaining_accounts); Instruction { program_id: crate::ID, diff --git a/program-tests/system-cpi-test/tests/test.rs b/program-tests/system-cpi-test/tests/test.rs index 95fae7fd49..92c80074af 100644 --- a/program-tests/system-cpi-test/tests/test.rs +++ b/program-tests/system-cpi-test/tests/test.rs @@ -221,7 +221,8 @@ async fn test_read_only_accounts() { .iter() .find(|x| { x.merkle_context.leaf_index == 101 - && x.merkle_context.merkle_tree_pubkey == env.v2_state_trees[0].merkle_tree + && x.merkle_context.merkle_tree_pubkey.to_bytes() + == env.v2_state_trees[0].merkle_tree.to_bytes() }) .unwrap() .clone(); @@ -232,7 +233,8 @@ async fn test_read_only_accounts() { .iter() .find(|x| { x.merkle_context.leaf_index == 1 - && x.merkle_context.merkle_tree_pubkey == env.v2_state_trees[0].merkle_tree + && x.merkle_context.merkle_tree_pubkey.to_bytes() + == env.v2_state_trees[0].merkle_tree.to_bytes() }) .unwrap() .clone(); @@ -328,7 +330,10 @@ async fn test_read_only_accounts() { .indexer .get_compressed_accounts_with_merkle_context_by_owner(&ID) .iter() - .find(|x| x.merkle_context.merkle_tree_pubkey == env.v1_state_trees[0].merkle_tree) + .find(|x| { + x.merkle_context.merkle_tree_pubkey.to_bytes() + == env.v1_state_trees[0].merkle_tree.to_bytes() + }) .unwrap() .clone(); let result = perform_create_pda_with_event( @@ -614,7 +619,8 @@ async fn test_read_only_accounts() { .iter() .find(|x| { x.merkle_context.leaf_index == 2 - && x.merkle_context.merkle_tree_pubkey == env.v2_state_trees[0].merkle_tree + && x.merkle_context.merkle_tree_pubkey.to_bytes() + == env.v2_state_trees[0].merkle_tree.to_bytes() && x.merkle_context.leaf_index != account_not_in_value_array_and_in_mt .merkle_context @@ -1710,7 +1716,8 @@ async fn perform_create_pda( (address, env.v2_address_trees[0], env.v2_address_trees[0]) } else { - let address = derive_address_legacy(&env.v1_address_trees[0].merkle_tree, &seed).unwrap(); + let address = + derive_address_legacy(&env.v1_address_trees[0].merkle_tree.into(), &seed).unwrap(); ( address, env.v1_address_trees[0].merkle_tree, @@ -1795,14 +1802,14 @@ async fn perform_create_pda( .collect(); let new_address_params = NewAddressParams { seed, - address_merkle_tree_pubkey, - address_queue_pubkey, + address_merkle_tree_pubkey: address_merkle_tree_pubkey.into(), + address_queue_pubkey: address_queue_pubkey.into(), address_merkle_tree_root_index: address_root_indices[0], }; let readonly_adresses = if addresses.len() == 2 && mode != CreatePdaMode::TwoReadOnlyAddresses { let read_only_address = vec![ReadOnlyAddress { address: addresses[1], - address_merkle_tree_pubkey, + address_merkle_tree_pubkey: address_merkle_tree_pubkey.into(), address_merkle_tree_root_index: address_root_indices[1], }]; Some(read_only_address) @@ -1810,12 +1817,12 @@ async fn perform_create_pda( let read_only_address = vec![ ReadOnlyAddress { address: addresses[0], - address_merkle_tree_pubkey, + address_merkle_tree_pubkey: address_merkle_tree_pubkey.into(), address_merkle_tree_root_index: address_root_indices[0], }, ReadOnlyAddress { address: addresses[1], - address_merkle_tree_pubkey, + address_merkle_tree_pubkey: address_merkle_tree_pubkey.into(), address_merkle_tree_root_index: address_root_indices[1], }, ]; @@ -1829,22 +1836,18 @@ async fn perform_create_pda( } else { let input_account_len = input_accounts.as_ref().unwrap().len(); index += input_account_len; - Some(account_root_indices[..index].iter().map(|x| *x).collect()) + Some(account_root_indices[..index].to_vec()) }; - let read_only_accounts = if let Some(read_only_accounts) = read_only_accounts.as_ref() { - Some( - read_only_accounts - .iter() - .map(|x| { - index += 1; - x.into_read_only(account_root_indices[index - 1]).unwrap() - }) - .collect::>(), - ) - } else { - None - }; + let read_only_accounts = read_only_accounts.as_ref().map(|read_only_accounts| { + read_only_accounts + .iter() + .map(|x| { + index += 1; + x.into_read_only(account_root_indices[index - 1]).unwrap() + }) + .collect::>() + }); let create_ix_inputs = CreateCompressedPdaInstructionInputs { data: *data, @@ -1871,18 +1874,17 @@ pub async fn assert_created_pda( seed: &[u8; 32], data: &[u8; 31], ) { - let compressed_escrow_pda = test_indexer - .get_compressed_accounts_with_merkle_context_by_owner(&ID) - .iter() - .find(|x| x.compressed_account.owner == ID) - .unwrap() - .clone(); - let address = derive_address_legacy(&env.v1_address_trees[0].merkle_tree, seed).unwrap(); + let compressed_escrow_pda = + test_indexer.get_compressed_accounts_with_merkle_context_by_owner(&ID)[0].clone(); + let address = derive_address_legacy(&env.v1_address_trees[0].merkle_tree.into(), seed).unwrap(); assert_eq!( compressed_escrow_pda.compressed_account.address.unwrap(), address ); - assert_eq!(compressed_escrow_pda.compressed_account.owner, ID); + assert_eq!( + compressed_escrow_pda.compressed_account.owner.to_bytes(), + ID.to_bytes() + ); let compressed_escrow_pda_deserialized = compressed_escrow_pda .compressed_account .data @@ -1958,7 +1960,7 @@ pub async fn perform_with_input_accounts>(), output_compressed_accounts: output_accounts.to_vec(), sequence_numbers: vec![MerkleTreeSequenceNumberV1 { - tree_pubkey: env.v2_state_trees[0].merkle_tree, + tree_pubkey: env.v2_state_trees[0].merkle_tree.into(), // queue_pubkey: env.v2_state_trees[0].output_queue, // tree_type: TreeType::StateV2 as u64, seq: 0, @@ -96,7 +100,7 @@ async fn parse_batched_event_functional() { message: None, is_compress: false, compress_or_decompress_lamports: None, - pubkey_array: vec![env.v2_state_trees[0].output_queue], + pubkey_array: vec![env.v2_state_trees[0].output_queue.into()], }, address_sequence_numbers: Vec::new(), input_sequence_numbers: Vec::new(), @@ -116,17 +120,17 @@ async fn parse_batched_event_functional() { .map(|i| { get_compressed_input_account(MerkleContext { leaf_index: i, - merkle_tree_pubkey: env.v2_state_trees[0].merkle_tree, + merkle_tree_pubkey: env.v2_state_trees[0].merkle_tree.into(), prove_by_index: true, - queue_pubkey: env.v2_state_trees[0].output_queue, + queue_pubkey: env.v2_state_trees[0].output_queue.into(), tree_type: light_compressed_account::TreeType::StateV2, }) }) .collect::>(); - let new_addresses = vec![ - derive_address_legacy(&env.v1_address_trees[0].merkle_tree, &[1u8; 32]).unwrap(), - derive_address_legacy(&env.v1_address_trees[0].merkle_tree, &[2u8; 32]).unwrap(), + let new_addresses = [ + derive_address_legacy(&env.v1_address_trees[0].merkle_tree.into(), &[1u8; 32]).unwrap(), + derive_address_legacy(&env.v1_address_trees[0].merkle_tree.into(), &[2u8; 32]).unwrap(), ]; let payer = rpc.get_payer().insecure_clone(); @@ -147,15 +151,15 @@ async fn parse_batched_event_functional() { let new_address_params = vec![ NewAddressParamsAssigned { seed: [1u8; 32], - address_queue_pubkey: env.v1_address_trees[0].queue, - address_merkle_tree_pubkey: env.v1_address_trees[0].merkle_tree, + address_queue_pubkey: env.v1_address_trees[0].queue.into(), + address_merkle_tree_pubkey: env.v1_address_trees[0].merkle_tree.into(), address_merkle_tree_root_index: proof_result.get_address_root_indices()[0], assigned_account_index: None, }, NewAddressParamsAssigned { seed: [2u8; 32], - address_queue_pubkey: env.v1_address_trees[0].queue, - address_merkle_tree_pubkey: env.v1_address_trees[0].merkle_tree, + address_queue_pubkey: env.v1_address_trees[0].queue.into(), + address_merkle_tree_pubkey: env.v1_address_trees[0].merkle_tree.into(), address_merkle_tree_root_index: proof_result.get_address_root_indices()[1], assigned_account_index: None, }, @@ -183,7 +187,11 @@ async fn parse_batched_event_functional() { .enumerate() .map(|(i, x)| { x.compressed_account - .hash(&env.v2_state_trees[0].merkle_tree, &((i + 8) as u32), true) + .hash( + &env.v2_state_trees[0].merkle_tree.into(), + &((i + 8) as u32), + true, + ) .unwrap() }) .collect::>(); @@ -210,13 +218,17 @@ async fn parse_batched_event_functional() { .enumerate() .map(|(i, x)| { x.compressed_account - .hash(&env.v2_state_trees[0].merkle_tree, &((i + 8) as u32), true) + .hash( + &env.v2_state_trees[0].merkle_tree.into(), + &((i + 8) as u32), + true, + ) .unwrap() }) .collect::>(), output_compressed_accounts: output_accounts.to_vec(), sequence_numbers: vec![MerkleTreeSequenceNumberV1 { - tree_pubkey: env.v2_state_trees[0].merkle_tree, + tree_pubkey: env.v2_state_trees[0].merkle_tree.into(), // queue_pubkey: env.v2_state_trees[0].output_queue, // tree_type: TreeType::StateV2 as u64, seq: 8, @@ -226,16 +238,16 @@ async fn parse_batched_event_functional() { is_compress: false, compress_or_decompress_lamports: None, pubkey_array: vec![ - env.v1_address_trees[0].merkle_tree, - env.v1_address_trees[0].queue, - env.v2_state_trees[0].merkle_tree, - env.v2_state_trees[0].output_queue, + env.v1_address_trees[0].merkle_tree.into(), + env.v1_address_trees[0].queue.into(), + env.v2_state_trees[0].merkle_tree.into(), + env.v2_state_trees[0].output_queue.into(), ], }, address_sequence_numbers: Vec::new(), input_sequence_numbers: vec![MerkleTreeSequenceNumber { - tree_pubkey: env.v2_state_trees[0].merkle_tree, - queue_pubkey: env.v2_state_trees[0].output_queue, + tree_pubkey: env.v2_state_trees[0].merkle_tree.into(), + queue_pubkey: env.v2_state_trees[0].output_queue.into(), tree_type: TreeType::StateV2 as u64, seq: 0, }], @@ -244,7 +256,7 @@ async fn parse_batched_event_functional() { .iter() .map(|x| NewAddress { address: *x, - mt_pubkey: env.v1_address_trees[0].merkle_tree, + mt_pubkey: env.v1_address_trees[0].merkle_tree.into(), queue_index: u64::MAX, }) .collect(), @@ -261,15 +273,15 @@ async fn parse_batched_event_functional() { .map(|i| { get_compressed_input_account(MerkleContext { leaf_index: i, - merkle_tree_pubkey: env.v2_state_trees[0].merkle_tree, + merkle_tree_pubkey: env.v2_state_trees[0].merkle_tree.into(), prove_by_index: true, - queue_pubkey: env.v2_state_trees[0].output_queue, + queue_pubkey: env.v2_state_trees[0].output_queue.into(), tree_type: light_compressed_account::TreeType::StateV2, }) }) .collect::>(); - let new_addresses = vec![ + let new_addresses = [ derive_address( &[1u8; 32], &env.v2_address_trees[0].to_bytes(), @@ -300,15 +312,15 @@ async fn parse_batched_event_functional() { let new_address_params = vec![ NewAddressParamsAssigned { seed: [1u8; 32], - address_queue_pubkey: env.v2_address_trees[0], - address_merkle_tree_pubkey: env.v2_address_trees[0], + address_queue_pubkey: env.v2_address_trees[0].into(), + address_merkle_tree_pubkey: env.v2_address_trees[0].into(), address_merkle_tree_root_index: proof_result.get_address_root_indices()[0], assigned_account_index: None, }, NewAddressParamsAssigned { seed: [2u8; 32], - address_queue_pubkey: env.v2_address_trees[0], - address_merkle_tree_pubkey: env.v2_address_trees[0], + address_queue_pubkey: env.v2_address_trees[0].into(), + address_merkle_tree_pubkey: env.v2_address_trees[0].into(), address_merkle_tree_root_index: proof_result.get_address_root_indices()[1], assigned_account_index: None, }, @@ -332,7 +344,7 @@ async fn parse_batched_event_functional() { .map(|x| { x.compressed_account .hash( - &env.v2_state_trees[0].merkle_tree, + &env.v2_state_trees[0].merkle_tree.into(), &x.merkle_context.leaf_index, true, ) @@ -344,7 +356,11 @@ async fn parse_batched_event_functional() { .enumerate() .map(|(i, x)| { x.compressed_account - .hash(&env.v2_state_trees[0].merkle_tree, &((i + 16) as u32), true) + .hash( + &env.v2_state_trees[0].merkle_tree.into(), + &((i + 16) as u32), + true, + ) .unwrap() }) .collect::>(); @@ -371,13 +387,17 @@ async fn parse_batched_event_functional() { .enumerate() .map(|(i, x)| { x.compressed_account - .hash(&env.v2_state_trees[0].merkle_tree, &((i + 16) as u32), true) + .hash( + &env.v2_state_trees[0].merkle_tree.into(), + &((i + 16) as u32), + true, + ) .unwrap() }) .collect::>(), output_compressed_accounts: output_accounts.to_vec(), sequence_numbers: vec![MerkleTreeSequenceNumberV1 { - tree_pubkey: env.v2_state_trees[0].merkle_tree, + tree_pubkey: env.v2_state_trees[0].merkle_tree.into(), // queue_pubkey: env.v2_state_trees[0].output_queue, // tree_type: TreeType::StateV2 as u64, seq: 16, @@ -387,20 +407,20 @@ async fn parse_batched_event_functional() { is_compress: false, compress_or_decompress_lamports: None, pubkey_array: vec![ - env.v2_address_trees[0], - env.v2_state_trees[0].merkle_tree, - env.v2_state_trees[0].output_queue, + env.v2_address_trees[0].into(), + env.v2_state_trees[0].merkle_tree.into(), + env.v2_state_trees[0].output_queue.into(), ], }, address_sequence_numbers: vec![MerkleTreeSequenceNumber { - tree_pubkey: env.v2_address_trees[0], - queue_pubkey: Pubkey::default(), + tree_pubkey: env.v2_address_trees[0].into(), + queue_pubkey: Pubkey::default().into(), tree_type: TreeType::AddressV2 as u64, seq: 0, }], input_sequence_numbers: vec![MerkleTreeSequenceNumber { - tree_pubkey: env.v2_state_trees[0].merkle_tree, - queue_pubkey: env.v2_state_trees[0].output_queue, + tree_pubkey: env.v2_state_trees[0].merkle_tree.into(), + queue_pubkey: env.v2_state_trees[0].output_queue.into(), tree_type: TreeType::StateV2 as u64, seq: 8, }], @@ -410,7 +430,7 @@ async fn parse_batched_event_functional() { .enumerate() .map(|(i, x)| NewAddress { address: *x, - mt_pubkey: env.v2_address_trees[0], + mt_pubkey: env.v2_address_trees[0].into(), queue_index: i as u64, }) .collect(), @@ -462,11 +482,11 @@ async fn parse_multiple_batched_events_functional() { output_leaf_indices: vec![0], output_compressed_account_hashes: vec![output_accounts[0] .compressed_account - .hash(&env.v2_state_trees[0].merkle_tree, &0u32, true) + .hash(&env.v2_state_trees[0].merkle_tree.into(), &0u32, true) .unwrap()], output_compressed_accounts: output_accounts.to_vec(), sequence_numbers: vec![MerkleTreeSequenceNumberV1 { - tree_pubkey: env.v2_state_trees[0].merkle_tree, + tree_pubkey: env.v2_state_trees[0].merkle_tree.into(), // queue_pubkey: env.v2_state_trees[0].output_queue, // tree_type: TreeType::StateV2 as u64, seq: 0, @@ -475,7 +495,7 @@ async fn parse_multiple_batched_events_functional() { message: None, is_compress: false, compress_or_decompress_lamports: None, - pubkey_array: vec![env.v2_state_trees[0].output_queue], + pubkey_array: vec![env.v2_state_trees[0].output_queue.into()], }, address_sequence_numbers: Vec::new(), input_sequence_numbers: Vec::new(), @@ -487,7 +507,7 @@ async fn parse_multiple_batched_events_functional() { for i in 1..num_expected_events { let mut expected_event = expected_batched_event.clone(); expected_event.event.sequence_numbers = vec![MerkleTreeSequenceNumberV1 { - tree_pubkey: env.v2_state_trees[0].merkle_tree, + tree_pubkey: env.v2_state_trees[0].merkle_tree.into(), // queue_pubkey: env.v2_state_trees[0].output_queue, // tree_type: TreeType::StateV2 as u64, seq: i as u64, @@ -495,7 +515,7 @@ async fn parse_multiple_batched_events_functional() { expected_event.event.output_compressed_account_hashes = vec![output_accounts[0] .clone() .compressed_account - .hash(&env.v2_state_trees[0].merkle_tree, &(i as u32), true) + .hash(&env.v2_state_trees[0].merkle_tree.into(), &(i as u32), true) .unwrap()]; expected_event.event.output_leaf_indices = vec![i as u32]; assert_eq!(events[i as usize], expected_event); @@ -553,11 +573,11 @@ async fn generate_photon_test_data_multiple_events() { output_leaf_indices: vec![0], output_compressed_account_hashes: vec![output_accounts[0] .compressed_account - .hash(&env.v2_state_trees[0].merkle_tree, &0u32, true) + .hash(&env.v2_state_trees[0].merkle_tree.into(), &0u32, true) .unwrap()], output_compressed_accounts: output_accounts.to_vec(), sequence_numbers: vec![MerkleTreeSequenceNumberV1 { - tree_pubkey: env.v2_state_trees[0].merkle_tree, + tree_pubkey: env.v2_state_trees[0].merkle_tree.into(), // queue_pubkey: env.v2_state_trees[0].output_queue, // tree_type: TreeType::StateV2 as u64, seq: 0, @@ -566,7 +586,7 @@ async fn generate_photon_test_data_multiple_events() { message: None, is_compress: false, compress_or_decompress_lamports: None, - pubkey_array: vec![env.v2_state_trees[0].output_queue], + pubkey_array: vec![env.v2_state_trees[0].output_queue.into()], }, address_sequence_numbers: Vec::new(), input_sequence_numbers: Vec::new(), @@ -578,7 +598,7 @@ async fn generate_photon_test_data_multiple_events() { for i in 1..num_expected_events { let mut expected_event = expected_batched_event.clone(); expected_event.event.sequence_numbers = vec![MerkleTreeSequenceNumberV1 { - tree_pubkey: env.v2_state_trees[0].merkle_tree, + tree_pubkey: env.v2_state_trees[0].merkle_tree.into(), // queue_pubkey: env.v2_state_trees[0].output_queue, // tree_type: TreeType::StateV2 as u64, seq: i as u64, @@ -586,7 +606,7 @@ async fn generate_photon_test_data_multiple_events() { expected_event.event.output_compressed_account_hashes = vec![output_accounts[0] .clone() .compressed_account - .hash(&env.v2_state_trees[0].merkle_tree, &(i as u32), true) + .hash(&env.v2_state_trees[0].merkle_tree.into(), &(i as u32), true) .unwrap()]; expected_event.event.output_leaf_indices = vec![i as u32]; assert_eq!(events[i as usize], expected_event); @@ -599,7 +619,7 @@ pub fn get_compressed_input_account( ) -> CompressedAccountWithMerkleContext { CompressedAccountWithMerkleContext { compressed_account: CompressedAccount { - owner: create_address_test_program::ID, + owner: create_address_test_program::ID.into(), lamports: 0, address: None, data: Some(CompressedAccountData { @@ -618,7 +638,7 @@ pub fn get_compressed_output_account( ) -> OutputCompressedAccountWithContext { OutputCompressedAccountWithContext { compressed_account: CompressedAccount { - owner: create_address_test_program::ID, + owner: create_address_test_program::ID.into(), lamports: 0, address: None, data: if data { @@ -631,7 +651,7 @@ pub fn get_compressed_output_account( None }, }, - merkle_tree, + merkle_tree: merkle_tree.into(), } } @@ -669,7 +689,7 @@ pub async fn perform_test_transaction( .as_slice(), output_accounts .iter() - .map(|x| x.merkle_tree) + .map(|x| x.merkle_tree.into()) .collect::>() .as_slice(), &mut remaining_accounts, diff --git a/program-tests/system-cpi-v2-test/tests/invoke_cpi_with_read_only.rs b/program-tests/system-cpi-v2-test/tests/invoke_cpi_with_read_only.rs index d7cf3ac63b..9a73f35307 100644 --- a/program-tests/system-cpi-v2-test/tests/invoke_cpi_with_read_only.rs +++ b/program-tests/system-cpi-v2-test/tests/invoke_cpi_with_read_only.rs @@ -288,7 +288,7 @@ async fn functional_read_only() { .iter() .zip(read_only_addresses) .map(|(root_index, address)| ReadOnlyAddress { - address_merkle_tree_pubkey: address_tree, + address_merkle_tree_pubkey: address_tree.into(), address, address_merkle_tree_root_index: *root_index, }) @@ -590,7 +590,7 @@ async fn functional_account_infos() { .iter() .zip(read_only_addresses) .map(|(root_index, address)| ReadOnlyAddress { - address_merkle_tree_pubkey: address_tree, + address_merkle_tree_pubkey: address_tree.into(), address, address_merkle_tree_root_index: *root_index, }) @@ -717,7 +717,7 @@ async fn create_addresses_with_account_info() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; let seed1 = [2u8; 32]; @@ -728,7 +728,7 @@ async fn create_addresses_with_account_info() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed1).unwrap() + derive_address_legacy(&address_tree.into(), &seed1).unwrap() }; let account_info = CompressedAccountInfo { address: Some(address), @@ -759,15 +759,15 @@ async fn create_addresses_with_account_info() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: Some(0), }; let new_address_params1 = NewAddressParamsAssigned { seed: seed1, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[1], assigned_account_index: Some(1), }; @@ -955,7 +955,7 @@ async fn create_addresses_with_account_info() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; let seed1 = [4u8; 32]; @@ -966,7 +966,7 @@ async fn create_addresses_with_account_info() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed1).unwrap() + derive_address_legacy(&address_tree.into(), &seed1).unwrap() }; let rpc_result = rpc .get_validity_proof( @@ -987,15 +987,15 @@ async fn create_addresses_with_account_info() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: None, }; let new_address_params1 = NewAddressParamsAssigned { seed: seed1, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[1], assigned_account_index: None, }; @@ -1034,7 +1034,7 @@ async fn create_addresses_with_account_info() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; let rpc_result = rpc @@ -1050,8 +1050,8 @@ async fn create_addresses_with_account_info() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: None, }; @@ -1093,7 +1093,7 @@ async fn create_addresses_with_account_info() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; let seed1 = [7u8; 32]; @@ -1104,7 +1104,7 @@ async fn create_addresses_with_account_info() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed1).unwrap() + derive_address_legacy(&address_tree.into(), &seed1).unwrap() }; let account_info = CompressedAccountInfo { address: Some(address1), @@ -1131,15 +1131,15 @@ async fn create_addresses_with_account_info() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: None, }; let new_address_params1 = NewAddressParamsAssigned { seed: seed1, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[1], assigned_account_index: Some(0), }; @@ -1181,7 +1181,7 @@ async fn create_addresses_with_account_info() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; let account_info = CompressedAccountInfo { @@ -1203,8 +1203,8 @@ async fn create_addresses_with_account_info() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: Some(0), }; @@ -1314,7 +1314,7 @@ async fn create_addresses_with_read_only() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; let seed1 = [2u8; 32]; @@ -1325,7 +1325,7 @@ async fn create_addresses_with_read_only() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed1).unwrap() + derive_address_legacy(&address_tree.into(), &seed1).unwrap() }; let mut output_1 = get_compressed_output_account(true, if batched { queue } else { tree }); output_1.compressed_account.address = Some(address); @@ -1350,15 +1350,15 @@ async fn create_addresses_with_read_only() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: Some(0), }; let new_address_params1 = NewAddressParamsAssigned { seed: seed1, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[1], assigned_account_index: Some(1), }; @@ -1553,7 +1553,7 @@ async fn create_addresses_with_read_only() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; let seed1 = [4u8; 32]; @@ -1564,7 +1564,7 @@ async fn create_addresses_with_read_only() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed1).unwrap() + derive_address_legacy(&address_tree.into(), &seed1).unwrap() }; let rpc_result = rpc .get_validity_proof( @@ -1585,15 +1585,15 @@ async fn create_addresses_with_read_only() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: None, }; let new_address_params1 = NewAddressParamsAssigned { seed: seed1, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[1], assigned_account_index: None, }; @@ -1633,7 +1633,7 @@ async fn create_addresses_with_read_only() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; let rpc_result = rpc @@ -1649,8 +1649,8 @@ async fn create_addresses_with_read_only() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: None, }; @@ -1693,7 +1693,7 @@ async fn create_addresses_with_read_only() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; let seed1 = [7u8; 32]; @@ -1704,7 +1704,7 @@ async fn create_addresses_with_read_only() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed1).unwrap() + derive_address_legacy(&address_tree.into(), &seed1).unwrap() }; output_accounts[0].compressed_account.address = Some(address1); @@ -1727,15 +1727,15 @@ async fn create_addresses_with_read_only() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: None, }; let new_address_params1 = NewAddressParamsAssigned { seed: seed1, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[1], assigned_account_index: Some(0), }; @@ -1778,7 +1778,7 @@ async fn create_addresses_with_read_only() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; output_accounts[0].compressed_account.address = Some(address); @@ -1796,8 +1796,8 @@ async fn create_addresses_with_read_only() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: Some(0), }; @@ -1809,7 +1809,7 @@ async fn create_addresses_with_read_only() { vec![], output_accounts, vec![new_address_params], - rpc_result.value.proof.0.clone(), + rpc_result.value.proof.0, None, None, is_small_ix, @@ -2113,7 +2113,7 @@ async fn cpi_context_with_read_only() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; let seed1 = [2u8; 32]; @@ -2124,7 +2124,7 @@ async fn cpi_context_with_read_only() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed1).unwrap() + derive_address_legacy(&address_tree.into(), &seed1).unwrap() }; let addresses_with_tree = vec![ AddressWithTree { @@ -2143,15 +2143,15 @@ async fn cpi_context_with_read_only() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: Some(0), }; let new_address_params1 = NewAddressParamsAssigned { seed: seed1, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[1], assigned_account_index: Some(1), }; @@ -2159,15 +2159,15 @@ async fn cpi_context_with_read_only() { // Insert into cpi context. { let input_accounts = vec![get_compressed_input_account(MerkleContext { - merkle_tree_pubkey: tree, - queue_pubkey: queue, + merkle_tree_pubkey: tree.into(), + queue_pubkey: queue.into(), leaf_index: 2, prove_by_index: true, tree_type: TreeType::StateV2, })]; let mut output_account = get_compressed_output_account(false, queue); output_account.compressed_account.address = Some(address1); - output_account.compressed_account.owner = owner_account1; + output_account.compressed_account.owner = owner_account1.into(); local_sdk::perform_test_transaction( &mut rpc, &mut test_indexer, @@ -2203,14 +2203,14 @@ async fn cpi_context_with_read_only() { // Insert into cpi context 2. { let input_accounts = vec![get_compressed_input_account(MerkleContext { - merkle_tree_pubkey: tree, - queue_pubkey: queue, + merkle_tree_pubkey: tree.into(), + queue_pubkey: queue.into(), leaf_index: 0, prove_by_index: true, tree_type: TreeType::StateV2, })]; let mut output_account = get_compressed_output_account(false, queue); - output_account.compressed_account.owner = owner_account2; + output_account.compressed_account.owner = owner_account2.into(); local_sdk::perform_test_transaction( &mut rpc, &mut test_indexer, @@ -2246,8 +2246,8 @@ async fn cpi_context_with_read_only() { // Execute cpi context. { let input_accounts = vec![get_compressed_input_account(MerkleContext { - merkle_tree_pubkey: tree, - queue_pubkey: queue, + merkle_tree_pubkey: tree.into(), + queue_pubkey: queue.into(), leaf_index: 1, prove_by_index: true, tree_type: TreeType::StateV2, @@ -2409,7 +2409,7 @@ async fn cpi_context_with_account_info() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed).unwrap() + derive_address_legacy(&address_tree.into(), &seed).unwrap() }; let seed1 = [2u8; 32]; @@ -2420,7 +2420,7 @@ async fn cpi_context_with_account_info() { &create_address_test_program::ID.to_bytes(), ) } else { - derive_address_legacy(&address_tree, &seed1).unwrap() + derive_address_legacy(&address_tree.into(), &seed1).unwrap() }; let addresses_with_tree = vec![ AddressWithTree { @@ -2439,15 +2439,15 @@ async fn cpi_context_with_account_info() { .unwrap(); let new_address_params = NewAddressParamsAssigned { seed, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[0], assigned_account_index: Some(0), }; let new_address_params1 = NewAddressParamsAssigned { seed: seed1, - address_queue_pubkey: address_queue, - address_merkle_tree_pubkey: address_tree, + address_queue_pubkey: address_queue.into(), + address_merkle_tree_pubkey: address_tree.into(), address_merkle_tree_root_index: rpc_result.value.get_address_root_indices()[1], assigned_account_index: Some(2), }; @@ -2734,8 +2734,8 @@ async fn compress_sol_with_read_only() { // 2.Decompress sol { let mut input_account = get_compressed_input_account(MerkleContext { - merkle_tree_pubkey: tree, - queue_pubkey: queue, + merkle_tree_pubkey: tree.into(), + queue_pubkey: queue.into(), leaf_index: 0, prove_by_index: true, tree_type: TreeType::StateV2, @@ -2830,12 +2830,7 @@ pub mod local_sdk { use create_address_test_program::create_invoke_read_only_account_info_instruction; use light_client::indexer::Indexer; use light_compressed_account::{ - address::{ - pack_new_address_params_assigned, pack_read_only_accounts, - pack_read_only_address_params, - }, compressed_account::{ - pack_compressed_accounts, pack_output_compressed_accounts, CompressedAccountWithMerkleContext, MerkleContext, PackedCompressedAccountWithMerkleContext, ReadOnlyCompressedAccount, }, @@ -2851,11 +2846,18 @@ pub mod local_sdk { use light_program_test::indexer::TestIndexerExtensions; use light_sdk::{ cpi::CpiAccountsConfig, find_cpi_signer_macro, instruction::accounts::SystemAccountPubkeys, - pack_pubkey_usize, NewAddressParamsAssigned, OutputCompressedAccountWithContext, + NewAddressParamsAssigned, OutputCompressedAccountWithContext, OutputCompressedAccountWithPackedContext, ReadOnlyAddress, CPI_AUTHORITY_PDA_SEED, }; use light_system_program::constants::SOL_POOL_PDA_SEED; - use light_test_utils::{Rpc, RpcError}; + use light_test_utils::{ + pack::{ + pack_compressed_accounts, pack_new_address_params_assigned, + pack_output_compressed_accounts, pack_pubkey_usize, pack_read_only_accounts, + pack_read_only_address_params, + }, + Rpc, RpcError, + }; use solana_sdk::{ pubkey::Pubkey, signature::{Keypair, Signer}, @@ -2917,7 +2919,7 @@ pub mod local_sdk { .as_slice(), output_accounts .iter() - .map(|x| x.merkle_tree) + .map(|x| x.merkle_tree.into()) .collect::>() .as_slice(), &mut remaining_accounts, diff --git a/program-tests/system-test/tests/test.rs b/program-tests/system-test/tests/test.rs index 6b82e2bcf3..88dc173c0f 100644 --- a/program-tests/system-test/tests/test.rs +++ b/program-tests/system-test/tests/test.rs @@ -116,7 +116,7 @@ async fn invoke_failing_test() { let options = [0usize, 1usize, 2usize, 3usize, 4usize, 8usize]; for mut num_addresses in 0..=2 { - for j in 0..6 { + for (j, option) in options.iter().enumerate() { // there is no combined circuit instantiation for 8 inputs and addresses if j == 5 { num_addresses = 0; @@ -124,12 +124,12 @@ async fn invoke_failing_test() { for num_outputs in 1..8 { println!( "failing_transaction_inputs num_addresses: {}, num_outputs: {}, option: {}", - num_addresses, num_outputs, options[j] + num_addresses, num_outputs, option ); failing_transaction_inputs( &mut rpc, &payer, - options[j], + *option, 1_000_000, num_addresses, num_outputs, @@ -249,6 +249,7 @@ pub async fn failing_transaction_inputs( .sum::(); let output_amount = sum_lamports / num_outputs as u64; let remainder = sum_lamports % num_outputs as u64; + #[allow(clippy::needless_range_loop)] for i in 0..num_outputs { let address = if output_compressed_accounts_with_address && i < num_addresses { Some(derived_addresses[i]) @@ -257,7 +258,7 @@ pub async fn failing_transaction_inputs( }; output_compressed_accounts.push(CompressedAccount { lamports: output_amount, - owner: payer.pubkey(), + owner: payer.pubkey().into(), data: None, address, }); @@ -422,7 +423,7 @@ pub async fn failing_transaction_inputs_inner( let mut inputs_struct = inputs_struct.clone(); inputs_struct.input_compressed_accounts_with_merkle_context[num_inputs - 1] .compressed_account - .owner = Keypair::new().pubkey(); + .owner = Keypair::new().pubkey().into(); create_instruction_and_failing_transaction( rpc, @@ -558,12 +559,13 @@ fn create_address_test_inputs( for address_seed in address_seeds.iter() { new_address_params.push(NewAddressParams { seed: *address_seed, - address_queue_pubkey: env.v1_address_trees[0].queue, - address_merkle_tree_pubkey: env.v1_address_trees[0].merkle_tree, + address_queue_pubkey: env.v1_address_trees[0].queue.into(), + address_merkle_tree_pubkey: env.v1_address_trees[0].merkle_tree.into(), address_merkle_tree_root_index: 0, }); let derived_address = - derive_address_legacy(&env.v1_address_trees[0].merkle_tree, address_seed).unwrap(); + derive_address_legacy(&env.v1_address_trees[0].merkle_tree.into(), address_seed) + .unwrap(); derived_addresses.push(derived_address); } (new_address_params, derived_addresses) @@ -890,7 +892,7 @@ async fn invoke_test() { ); let output_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: payer_pubkey, + owner: payer_pubkey.into(), data: None, address: None, }]; @@ -940,7 +942,7 @@ async fn invoke_test() { let input_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: payer_pubkey, + owner: payer_pubkey.into(), data: None, address: None, }]; @@ -951,9 +953,9 @@ async fn invoke_test() { &input_compressed_accounts, &output_compressed_accounts, &[MerkleContext { - merkle_tree_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), leaf_index: 0, - queue_pubkey: nullifier_queue_pubkey, + queue_pubkey: nullifier_queue_pubkey.into(), prove_by_index: false, tree_type: TreeType::StateV1, }], @@ -975,7 +977,7 @@ async fn invoke_test() { // check invalid signer for in compressed_account let invalid_signer_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: Keypair::new().pubkey(), + owner: Keypair::new().pubkey().into(), data: None, address: None, }]; @@ -986,9 +988,9 @@ async fn invoke_test() { &invalid_signer_compressed_accounts, &output_compressed_accounts, &[MerkleContext { - merkle_tree_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), leaf_index: 0, - queue_pubkey: nullifier_queue_pubkey, + queue_pubkey: nullifier_queue_pubkey.into(), prove_by_index: false, tree_type: TreeType::StateV1, }], @@ -1029,9 +1031,9 @@ async fn invoke_test() { &input_compressed_accounts, &output_compressed_accounts, &[MerkleContext { - merkle_tree_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), leaf_index: 0, - queue_pubkey: nullifier_queue_pubkey, + queue_pubkey: nullifier_queue_pubkey.into(), prove_by_index: false, tree_type: TreeType::StateV1, }], @@ -1071,7 +1073,7 @@ async fn invoke_test() { println!("Double spend -------------------------"); let output_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: Keypair::new().pubkey(), + owner: Keypair::new().pubkey().into(), data: None, address: None, }]; @@ -1082,9 +1084,9 @@ async fn invoke_test() { &input_compressed_accounts, &output_compressed_accounts, &[MerkleContext { - merkle_tree_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), leaf_index: 0, - queue_pubkey: nullifier_queue_pubkey, + queue_pubkey: nullifier_queue_pubkey.into(), prove_by_index: false, tree_type: TreeType::StateV1, }], @@ -1108,7 +1110,7 @@ async fn invoke_test() { assert!(res.is_err()); let output_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: Keypair::new().pubkey(), + owner: Keypair::new().pubkey().into(), data: None, address: None, }]; @@ -1119,9 +1121,9 @@ async fn invoke_test() { &input_compressed_accounts, &output_compressed_accounts, &[MerkleContext { - merkle_tree_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), leaf_index: 1, - queue_pubkey: nullifier_queue_pubkey, + queue_pubkey: nullifier_queue_pubkey.into(), prove_by_index: false, tree_type: TreeType::StateV1, }], @@ -1168,13 +1170,13 @@ async fn test_with_address() { let address_seed = [1u8; 32]; let derived_address = derive_address_legacy( - &rpc.test_accounts.v1_address_trees[0].merkle_tree, + &rpc.test_accounts.v1_address_trees[0].merkle_tree.into(), &address_seed, ) .unwrap(); let output_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: payer_pubkey, + owner: payer_pubkey.into(), data: None, address: Some(derived_address), // this should not be sent, only derived on-chain }]; @@ -1213,15 +1215,15 @@ async fn test_with_address() { ); let output_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: payer_pubkey, + owner: payer_pubkey.into(), data: None, address: Some(derived_address), // this should not be sent, only derived on-chain }]; let address_params = vec![NewAddressParams { seed: address_seed, - address_queue_pubkey: rpc.test_accounts.v1_address_trees[0].queue, - address_merkle_tree_pubkey: rpc.test_accounts.v1_address_trees[0].merkle_tree, + address_queue_pubkey: rpc.test_accounts.v1_address_trees[0].queue.into(), + address_merkle_tree_pubkey: rpc.test_accounts.v1_address_trees[0].merkle_tree.into(), address_merkle_tree_root_index: 0, }]; let instruction = create_invoke_instruction( @@ -1260,14 +1262,14 @@ async fn test_with_address() { ); let output_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: payer_pubkey, + owner: payer_pubkey.into(), data: None, address: Some(derived_address), // this should not be sent, only derived on-chain }]; let address_params = vec![NewAddressParams { seed: address_seed, - address_queue_pubkey: rpc.test_accounts.v2_address_trees[0], - address_merkle_tree_pubkey: rpc.test_accounts.v2_address_trees[0], + address_queue_pubkey: rpc.test_accounts.v2_address_trees[0].into(), + address_merkle_tree_pubkey: rpc.test_accounts.v2_address_trees[0].into(), address_merkle_tree_root_index: 0, }]; @@ -1329,7 +1331,8 @@ async fn test_with_address() { &[recipient_pubkey], &[compressed_account_with_context .merkle_context - .merkle_tree_pubkey], + .merkle_tree_pubkey + .into()], None, ) .await @@ -1344,8 +1347,11 @@ async fn test_with_address() { derived_address ); assert_eq!( - indexer.compressed_accounts[0].compressed_account.owner, - recipient_pubkey + indexer.compressed_accounts[0] + .compressed_account + .owner + .to_bytes(), + recipient_pubkey.to_bytes() ); (*rpc.indexer_mut().unwrap()) = indexer; @@ -1463,7 +1469,7 @@ async fn test_with_compression() { let compress_amount = 1_000_000; let output_compressed_accounts = vec![CompressedAccount { lamports: compress_amount + 1, - owner: payer_pubkey, + owner: payer_pubkey.into(), data: None, address: None, }]; @@ -1496,7 +1502,7 @@ async fn test_with_compression() { .unwrap(); let output_compressed_accounts = vec![CompressedAccount { lamports: compress_amount, - owner: payer_pubkey, + owner: payer_pubkey.into(), data: None, address: None, }]; @@ -1565,7 +1571,7 @@ async fn test_with_compression() { let recipient_pubkey = Keypair::new().pubkey(); let output_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: recipient_pubkey, + owner: recipient_pubkey.into(), data: None, address: None, }]; @@ -1576,9 +1582,9 @@ async fn test_with_compression() { &input_compressed_accounts, &output_compressed_accounts, &[MerkleContext { - merkle_tree_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), leaf_index: 0, - queue_pubkey: nullifier_queue_pubkey, + queue_pubkey: nullifier_queue_pubkey.into(), prove_by_index: false, tree_type: TreeType::StateV1, }], @@ -1849,7 +1855,7 @@ async fn batch_invoke_test() { let output_queue_pubkey = env.v2_state_trees[0].output_queue; let output_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: payer.pubkey(), + owner: payer.pubkey().into(), data: None, address: None, }]; @@ -1865,7 +1871,7 @@ async fn batch_invoke_test() { ); let input_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: payer_pubkey, + owner: payer_pubkey.into(), data: None, address: None, }]; @@ -1876,9 +1882,9 @@ async fn batch_invoke_test() { &input_compressed_accounts, &output_compressed_accounts, &[MerkleContext { - merkle_tree_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), leaf_index: 0, - queue_pubkey: output_queue_pubkey, + queue_pubkey: output_queue_pubkey.into(), prove_by_index: false, tree_type: TreeType::StateV1, }], @@ -1906,7 +1912,7 @@ async fn batch_invoke_test() { // 3. Should fail: input compressed account with invalid signer. let invalid_signer_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: Keypair::new().pubkey(), + owner: Keypair::new().pubkey().into(), data: None, address: None, }]; @@ -1917,9 +1923,9 @@ async fn batch_invoke_test() { &invalid_signer_compressed_accounts, &output_compressed_accounts, &[MerkleContext { - merkle_tree_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), leaf_index: 0, - queue_pubkey: output_queue_pubkey, + queue_pubkey: output_queue_pubkey.into(), prove_by_index: false, tree_type: TreeType::StateV1, }], @@ -1968,9 +1974,9 @@ async fn batch_invoke_test() { &input_compressed_accounts, &output_compressed_accounts, &[MerkleContext { - merkle_tree_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), leaf_index: compressed_account_with_context.merkle_context.leaf_index, - queue_pubkey: output_queue_pubkey, + queue_pubkey: output_queue_pubkey.into(), prove_by_index: true, tree_type: TreeType::StateV2, }], @@ -2007,7 +2013,7 @@ async fn batch_invoke_test() { { let output_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: Keypair::new().pubkey(), + owner: Keypair::new().pubkey().into(), data: None, address: None, }]; @@ -2017,9 +2023,9 @@ async fn batch_invoke_test() { &input_compressed_accounts, &output_compressed_accounts, &[MerkleContext { - merkle_tree_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), leaf_index: 0, - queue_pubkey: output_queue_pubkey, + queue_pubkey: output_queue_pubkey.into(), prove_by_index: true, tree_type: TreeType::StateV2, }], @@ -2047,13 +2053,13 @@ async fn batch_invoke_test() { let input_compressed_account = rpc .get_compressed_accounts_with_merkle_context_by_owner(&payer_pubkey) .iter() - .filter(|x| x.merkle_context.queue_pubkey == output_queue_pubkey) - .last() + .filter(|x| x.merkle_context.queue_pubkey.to_bytes() == output_queue_pubkey.to_bytes()) + .next_back() .unwrap() .clone(); let output_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: Keypair::new().pubkey(), + owner: Keypair::new().pubkey().into(), data: None, address: None, }]; @@ -2063,9 +2069,9 @@ async fn batch_invoke_test() { &[input_compressed_account.compressed_account], &output_compressed_accounts, &[MerkleContext { - merkle_tree_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), leaf_index: input_compressed_account.merkle_context.leaf_index - 1, - queue_pubkey: output_queue_pubkey, + queue_pubkey: output_queue_pubkey.into(), prove_by_index: true, tree_type: TreeType::StateV2, }], @@ -2105,8 +2111,8 @@ async fn batch_invoke_test() { .compressed_accounts .iter() .filter(|x| { - x.compressed_account.owner == payer_pubkey - && x.merkle_context.queue_pubkey == output_queue_pubkey + x.compressed_account.owner.to_bytes() == payer_pubkey.to_bytes() + && x.merkle_context.queue_pubkey.to_bytes() == output_queue_pubkey.to_bytes() }) .cloned() .collect::>() @@ -2121,8 +2127,9 @@ async fn batch_invoke_test() { .compressed_accounts .iter() .filter(|x| { - x.compressed_account.owner == payer_pubkey - && x.merkle_context.queue_pubkey == env.v1_state_trees[0].nullifier_queue + x.compressed_account.owner.to_bytes() == payer_pubkey.to_bytes() + && x.merkle_context.queue_pubkey.to_bytes() + == env.v1_state_trees[0].nullifier_queue.to_bytes() }) .collect::>()[0] .clone(); @@ -2152,13 +2159,13 @@ async fn batch_invoke_test() { let output_compressed_accounts = vec![ CompressedAccount { lamports: 0, - owner: payer_pubkey, + owner: payer_pubkey.into(), data: None, address: None, }, CompressedAccount { lamports: 0, - owner: payer_pubkey, + owner: payer_pubkey.into(), data: None, address: None, }, @@ -2172,8 +2179,8 @@ async fn batch_invoke_test() { &output_compressed_accounts, merkle_context.as_slice(), &[ - merkle_context_1.queue_pubkey, // output queue - merkle_context_2.merkle_tree_pubkey, + merkle_context_1.queue_pubkey.into(), // output queue + merkle_context_2.merkle_tree_pubkey.into(), ], &proof_rpc_result .value @@ -2210,10 +2217,10 @@ async fn batch_invoke_test() { .compressed_accounts .iter() .filter(|x| { - x.compressed_account.owner == payer_pubkey - && x.merkle_context.queue_pubkey == output_queue_pubkey + x.compressed_account.owner.to_bytes() == payer_pubkey.to_bytes() + && x.merkle_context.queue_pubkey.to_bytes() == output_queue_pubkey.to_bytes() }) - .last() + .next_back() .unwrap() .clone(); let result = double_spend_compressed_account( @@ -2243,10 +2250,10 @@ async fn batch_invoke_test() { .compressed_accounts .iter() .filter(|x| { - x.compressed_account.owner == payer_pubkey - && x.merkle_context.queue_pubkey == output_queue_pubkey + x.compressed_account.owner.to_bytes() == payer_pubkey.to_bytes() + && x.merkle_context.queue_pubkey.to_bytes() == output_queue_pubkey.to_bytes() }) - .last() + .next_back() .unwrap() .clone(); let result = double_spend_compressed_account( @@ -2276,8 +2283,8 @@ async fn batch_invoke_test() { .compressed_accounts .iter() .filter(|x| { - x.compressed_account.owner == payer_pubkey - && x.merkle_context.queue_pubkey == output_queue_pubkey + x.compressed_account.owner.to_bytes() == payer_pubkey.to_bytes() + && x.merkle_context.queue_pubkey.to_bytes() == output_queue_pubkey.to_bytes() }) .next_back() .unwrap() @@ -2309,8 +2316,8 @@ async fn batch_invoke_test() { .compressed_accounts .iter() .filter(|x| { - x.compressed_account.owner == payer_pubkey - && x.merkle_context.queue_pubkey == output_queue_pubkey + x.compressed_account.owner.to_bytes() == payer_pubkey.to_bytes() + && x.merkle_context.queue_pubkey.to_bytes() == output_queue_pubkey.to_bytes() }) .next_back() .unwrap() @@ -2397,8 +2404,8 @@ async fn batch_invoke_test() { .compressed_accounts .iter() .filter(|x| { - x.compressed_account.owner == payer_pubkey - && x.merkle_context.queue_pubkey != output_queue_pubkey + x.compressed_account.owner.to_bytes() == payer_pubkey.to_bytes() + && x.merkle_context.queue_pubkey.to_bytes() != output_queue_pubkey.to_bytes() }) .next_back() .unwrap() @@ -2412,7 +2419,7 @@ async fn batch_invoke_test() { &input_compressed_accounts, &output_compressed_accounts, &[merkle_context], - &[merkle_context.merkle_tree_pubkey], + &[merkle_context.merkle_tree_pubkey.into()], &[None], &Vec::new(), None, @@ -2460,7 +2467,7 @@ pub async fn double_spend_compressed_account( let input_compressed_accounts = vec![compressed_account_with_context_1.compressed_account]; let output_compressed_accounts = vec![CompressedAccount { lamports: 0, - owner: payer.pubkey(), + owner: payer.pubkey().into(), data: None, address: None, }]; @@ -2471,7 +2478,7 @@ pub async fn double_spend_compressed_account( &input_compressed_accounts, &output_compressed_accounts, &[merkle_context_1], - &[merkle_context_1.queue_pubkey], + &[merkle_context_1.queue_pubkey.into()], &proof_rpc_result .value .accounts @@ -2495,7 +2502,7 @@ pub async fn double_spend_compressed_account( &input_compressed_accounts, &output_compressed_accounts, &[merkle_context], - &[merkle_context.queue_pubkey], + &[merkle_context.queue_pubkey.into()], &[None], &Vec::new(), None, @@ -2574,7 +2581,7 @@ pub async fn create_output_accounts( let output_compressed_accounts = vec![ CompressedAccount { lamports: 0, - owner: payer.pubkey(), + owner: payer.pubkey().into(), data: None, address: None, }; diff --git a/program-tests/utils/src/assert_compressed_tx.rs b/program-tests/utils/src/assert_compressed_tx.rs index f5e7865a81..6f0595d1ca 100644 --- a/program-tests/utils/src/assert_compressed_tx.rs +++ b/program-tests/utils/src/assert_compressed_tx.rs @@ -232,10 +232,9 @@ pub fn assert_created_compressed_accounts( && x.owner == output_account.compressed_account.owner && x.data == output_account.compressed_account.data && x.address == output_account.compressed_account.address),); - assert!(output_merkle_tree_pubkeys - .iter() - .any(|x| *x == output_account.merkle_context.merkle_tree_pubkey - || *x == output_account.merkle_context.queue_pubkey),); + assert!(output_merkle_tree_pubkeys.iter().any(|x| *x + == output_account.merkle_context.merkle_tree_pubkey.into() + || *x == output_account.merkle_context.queue_pubkey.into()),); } } @@ -258,9 +257,9 @@ pub fn assert_public_transaction_event( for account in event.output_compressed_accounts.iter() { assert!( output_merkle_tree_accounts.iter().any(|x| x.merkle_tree - == event.pubkey_array[account.merkle_tree_index as usize] + == event.pubkey_array[account.merkle_tree_index as usize].into() // handle output queue - || x.nullifier_queue == event.pubkey_array[account.merkle_tree_index as usize]), + || x.nullifier_queue == event.pubkey_array[account.merkle_tree_index as usize].into()), "assert_public_transaction_event: output state merkle tree account index mismatch" ); } @@ -349,8 +348,8 @@ pub async fn assert_merkle_tree_after_tx( ); assert_eq!( - merkle_tree_account.metadata.next_merkle_tree, - Pubkey::default().into() + merkle_tree_account.metadata.next_merkle_tree.to_bytes(), + [0u8; 32] ); assert_eq!( - merkle_tree_account.metadata.access_metadata.owner, - (*payer_pubkey).into() + merkle_tree_account + .metadata + .access_metadata + .owner + .to_bytes(), + (*payer_pubkey).to_bytes() ); assert_eq!( - merkle_tree_account.metadata.access_metadata.program_owner, - Pubkey::default().into() + merkle_tree_account + .metadata + .access_metadata + .program_owner + .to_bytes(), + [0u8; 32] ); assert_eq!( - merkle_tree_account.metadata.associated_queue, - (*queue_pubkey).into() + merkle_tree_account.metadata.associated_queue.to_bytes(), + (*queue_pubkey).to_bytes() ); let merkle_tree = get_concurrent_merkle_tree::( diff --git a/program-tests/utils/src/assert_rollover.rs b/program-tests/utils/src/assert_rollover.rs index 0fb86d0383..7fa91145bb 100644 --- a/program-tests/utils/src/assert_rollover.rs +++ b/program-tests/utils/src/assert_rollover.rs @@ -90,12 +90,12 @@ pub fn assert_rolledover_merkle_trees_metadata( ); assert_eq!( - new_merkle_tree_metadata.associated_queue, - (*new_queue_pubkey).into() + new_merkle_tree_metadata.associated_queue.to_bytes(), + (*new_queue_pubkey).to_bytes() ); assert_eq!( - new_merkle_tree_metadata.next_merkle_tree, - Pubkey::default().into() + new_merkle_tree_metadata.next_merkle_tree.to_bytes(), + Pubkey::default().to_bytes() ); } @@ -142,10 +142,13 @@ pub fn assert_rolledover_queues_metadata( new_queue_metadata.access_metadata.program_owner ); assert_eq!( - new_queue_metadata.associated_merkle_tree, - (*new_merkle_tree_pubkey).into() + new_queue_metadata.associated_merkle_tree.to_bytes(), + (*new_merkle_tree_pubkey).to_bytes() + ); + assert_eq!( + old_queue_metadata.next_queue, + light_compressed_account::Pubkey::from(*new_queue_pubkey) ); - assert_eq!(old_queue_metadata.next_queue, (*new_queue_pubkey).into()); assert_eq!( old_merkle_tree_lamports, new_merkle_tree_lamports + new_queue_lamports + old_merkle_tree_lamports diff --git a/program-tests/utils/src/assert_token_tx.rs b/program-tests/utils/src/assert_token_tx.rs index 4654d48c34..0934d869bd 100644 --- a/program-tests/utils/src/assert_token_tx.rs +++ b/program-tests/utils/src/assert_token_tx.rs @@ -166,8 +166,9 @@ pub fn assert_compressed_token_accounts( ); assert_eq!( - merkle_tree_account.metadata.next_merkle_tree, - Pubkey::default().into() + merkle_tree_account.metadata.next_merkle_tree.to_bytes(), + [0u8; 32] ); let expected_access_meta_data = AccessMetadata { owner: (*owner_pubkey).into(), @@ -193,8 +193,8 @@ pub async fn assert_address_merkle_tree_initialized( expected_access_meta_data ); assert_eq!( - merkle_tree_account.metadata.associated_queue, - (*queue_pubkey).into() + merkle_tree_account.metadata.associated_queue.to_bytes(), + (*queue_pubkey).to_bytes() ); let merkle_tree = get_indexed_merkle_tree::< diff --git a/program-tests/utils/src/create_address_test_program_sdk.rs b/program-tests/utils/src/create_address_test_program_sdk.rs index c175605788..a7282f6b76 100644 --- a/program-tests/utils/src/create_address_test_program_sdk.rs +++ b/program-tests/utils/src/create_address_test_program_sdk.rs @@ -10,10 +10,11 @@ use light_compressed_account::{ address::{derive_address, pack_new_address_params}, instruction_data::{compressed_proof::CompressedProof, data::NewAddressParams}, }; -use light_compressed_token::process_transfer::transfer_sdk::to_account_metas; use light_program_test::{accounts::test_accounts::TestAccounts, indexer::TestIndexerExtensions}; use solana_sdk::{instruction::Instruction, pubkey::Pubkey, signature::Keypair, signer::Signer}; +use crate::e2e_test_env::to_account_metas_light; + #[derive(Debug, Clone)] pub struct CreateCompressedPdaInstructionInputs<'a> { pub data: [u8; 31], @@ -29,9 +30,9 @@ pub fn create_pda_instruction(input_params: CreateCompressedPdaInstructionInputs &[CPI_AUTHORITY_PDA_SEED], &create_address_test_program::id(), ); - let mut remaining_accounts = HashMap::new(); + let mut remaining_accounts = HashMap::::new(); remaining_accounts.insert( - *input_params.output_compressed_account_merkle_tree_pubkey, + (*input_params.output_compressed_account_merkle_tree_pubkey).into(), 0, ); let new_address_params = @@ -58,7 +59,7 @@ pub fn create_pda_instruction(input_params: CreateCompressedPdaInstructionInputs cpi_signer, system_program: solana_sdk::system_program::id(), }; - let remaining_accounts = to_account_metas(remaining_accounts); + let remaining_accounts = to_account_metas_light(remaining_accounts); Instruction { program_id: create_address_test_program::ID, @@ -116,8 +117,8 @@ pub async fn perform_create_pda_with_event< let new_address_params = NewAddressParams { seed, - address_merkle_tree_pubkey: env.v2_address_trees[0], - address_queue_pubkey: env.v2_address_trees[0], + address_merkle_tree_pubkey: env.v2_address_trees[0].into(), + address_queue_pubkey: env.v2_address_trees[0].into(), address_merkle_tree_root_index: rpc_result.value.addresses[0].root_index, }; let create_ix_inputs = CreateCompressedPdaInstructionInputs { diff --git a/program-tests/utils/src/e2e_test_env.rs b/program-tests/utils/src/e2e_test_env.rs index d05853b7f2..a853e2afbf 100644 --- a/program-tests/utils/src/e2e_test_env.rs +++ b/program-tests/utils/src/e2e_test_env.rs @@ -70,7 +70,7 @@ use account_compression::{ AddressMerkleTreeConfig, AddressQueueConfig, NullifierQueueConfig, StateMerkleTreeConfig, SAFETY_MARGIN, }; -use anchor_lang::AnchorSerialize; +use anchor_lang::{prelude::AccountMeta, AnchorSerialize}; use create_address_test_program::create_invoke_cpi_instruction; use forester_utils::{ account_zero_copy::AccountZeroCopy, @@ -96,12 +96,17 @@ use light_client::{ // refactor all tests to work with that so that we can run all tests with a test validator and concurrency use light_compressed_account::{ address::{ - derive_address, pack_new_address_params, pack_read_only_accounts, - pack_read_only_address_params, + derive_address, + // pack_new_address_params, pack_read_only_accounts, + // pack_read_only_address_params, }, compressed_account::{ - pack_compressed_accounts, pack_output_compressed_accounts, CompressedAccount, - CompressedAccountData, CompressedAccountWithMerkleContext, ReadOnlyCompressedAccount, + // pack_compressed_accounts, pack_output_compressed_accounts, + CompressedAccount, + CompressedAccountData, + CompressedAccountWithMerkleContext, + + ReadOnlyCompressedAccount, }, instruction_data::{ compressed_proof::CompressedProof, @@ -177,6 +182,7 @@ use crate::{ assert_finalized_epoch_registration, assert_report_work, fetch_epoch_and_forester_pdas, }, create_address_merkle_tree_and_queue_account_with_assert, + pack::*, spl::{ approve_test, burn_test, compress_test, compressed_transfer_test, create_mint_helper, create_token_account, decompress_test, freeze_test, mint_tokens_helper, revoke_test, @@ -2553,8 +2559,8 @@ where .enumerate() .map(|(index, seed)| { NewAddressParams { - address_merkle_tree_pubkey: address_merkle_tree[index], - address_queue_pubkey: queues[index], + address_merkle_tree_pubkey: address_merkle_tree[index].into(), + address_queue_pubkey: queues[index].into(), seed: *seed, address_merkle_tree_root_index: 0, // set after proof generation } @@ -2583,7 +2589,7 @@ where ); proof_input_addresses.push((address, address_merkle_tree[index])); ReadOnlyAddress { - address_merkle_tree_pubkey: address_merkle_tree[index], + address_merkle_tree_pubkey: address_merkle_tree[index].into(), address, address_merkle_tree_root_index: 0, // set after proof generation } @@ -2615,7 +2621,7 @@ where None }; let account = CompressedAccount { - owner: create_address_test_program::ID, + owner: create_address_test_program::ID.into(), data: Some(CompressedAccountData { data: rnd_data.to_vec(), discriminator: [1; 8], @@ -2867,7 +2873,10 @@ where .indexer .get_state_merkle_trees() .iter() - .find(|x| x.accounts.merkle_tree == first_account.merkle_context.merkle_tree_pubkey) + .find(|x| { + x.accounts.merkle_tree.to_bytes() + == first_account.merkle_context.merkle_tree_pubkey.to_bytes() + }) .unwrap() .tree_type; let input_compressed_accounts_with_same_version = input_compressed_accounts @@ -2876,7 +2885,10 @@ where self.indexer .get_state_merkle_trees() .iter() - .find(|y| y.accounts.merkle_tree == x.merkle_context.merkle_tree_pubkey) + .find(|y| { + y.accounts.merkle_tree.to_bytes() + == x.merkle_context.merkle_tree_pubkey.to_bytes() + }) .unwrap() .tree_type == first_mt @@ -3140,7 +3152,13 @@ where a.compressed_account .merkle_context .merkle_tree_pubkey - .cmp(&b.compressed_account.merkle_context.merkle_tree_pubkey) + .to_bytes() + .cmp( + &b.compressed_account + .merkle_context + .merkle_tree_pubkey + .to_bytes(), + ) }); (mint, get_random_subset_of_token_accounts) } @@ -3363,3 +3381,28 @@ impl GeneralActionConfig { } } } + +pub fn to_account_metas_light( + remaining_accounts: HashMap, +) -> Vec { + let mut remaining_accounts = remaining_accounts + .iter() + .map(|(k, i)| { + ( + AccountMeta { + pubkey: (*k).into(), + is_signer: false, + is_writable: true, + }, + *i, + ) + }) + .collect::>(); + // hash maps are not sorted so we need to sort manually and collect into a vector again + remaining_accounts.sort_by(|a, b| a.1.cmp(&b.1)); + let remaining_accounts = remaining_accounts + .iter() + .map(|(k, _)| k.clone()) + .collect::>(); + remaining_accounts +} diff --git a/program-tests/utils/src/lib.rs b/program-tests/utils/src/lib.rs index e2e44820ff..889b6556a7 100644 --- a/program-tests/utils/src/lib.rs +++ b/program-tests/utils/src/lib.rs @@ -29,6 +29,7 @@ pub mod conversions; pub mod create_address_test_program_sdk; pub mod e2e_test_env; pub mod mock_batched_forester; +pub mod pack; pub mod registered_program_accounts_v1; pub mod setup_accounts; #[allow(unused)] diff --git a/program-tests/utils/src/pack.rs b/program-tests/utils/src/pack.rs new file mode 100644 index 0000000000..a86b4495fe --- /dev/null +++ b/program-tests/utils/src/pack.rs @@ -0,0 +1,228 @@ +use std::collections::HashMap; + +use light_compressed_account::{ + compressed_account::{ + CompressedAccount, CompressedAccountWithMerkleContext, MerkleContext, + PackedCompressedAccountWithMerkleContext, PackedMerkleContext, + PackedReadOnlyCompressedAccount, ReadOnlyCompressedAccount, + }, + instruction_data::data::{NewAddressParams, ReadOnlyAddress}, +}; +use light_sdk::{ + NewAddressParamsAssigned, NewAddressParamsAssignedPacked, NewAddressParamsPacked, + OutputCompressedAccountWithPackedContext, PackedReadOnlyAddress, +}; +use solana_sdk::pubkey::Pubkey; + +pub fn add_and_get_remaining_account_indices( + pubkeys: &[Pubkey], + remaining_accounts: &mut HashMap, +) -> Vec { + let mut vec = Vec::new(); + let mut next_index: usize = remaining_accounts.len(); + for pubkey in pubkeys.iter() { + match remaining_accounts.get(pubkey) { + Some(_) => {} + None => { + remaining_accounts.insert(*pubkey, next_index); + next_index += 1; + } + }; + vec.push(*remaining_accounts.get(pubkey).unwrap() as u8); + } + vec +} + +pub fn pack_merkle_context( + merkle_context: &[MerkleContext], + remaining_accounts: &mut HashMap, +) -> Vec { + merkle_context + .iter() + .map(|merkle_context| PackedMerkleContext { + leaf_index: merkle_context.leaf_index, + merkle_tree_pubkey_index: pack_account( + merkle_context.merkle_tree_pubkey.into(), + remaining_accounts, + ), + queue_pubkey_index: pack_account( + merkle_context.queue_pubkey.into(), + remaining_accounts, + ), + prove_by_index: merkle_context.prove_by_index, + }) + .collect::>() +} + +pub fn pack_account(pubkey: Pubkey, remaining_accounts: &mut HashMap) -> u8 { + match remaining_accounts.get(&pubkey) { + Some(index) => *index as u8, + None => { + let next_index = remaining_accounts.len(); + remaining_accounts.insert(pubkey, next_index); + next_index as u8 + } + } +} + +pub fn pack_read_only_accounts( + accounts: &[ReadOnlyCompressedAccount], + remaining_accounts: &mut HashMap, +) -> Vec { + accounts + .iter() + .map(|x| PackedReadOnlyCompressedAccount { + account_hash: x.account_hash, + merkle_context: pack_merkle_context(&[x.merkle_context], remaining_accounts)[0], + root_index: x.root_index, + }) + .collect::>() +} + +pub fn pack_new_address_params( + new_address_params: &[NewAddressParams], + remaining_accounts: &mut HashMap, +) -> Vec { + let mut new_address_params_packed = new_address_params + .iter() + .map(|x| NewAddressParamsPacked { + seed: x.seed, + address_merkle_tree_root_index: x.address_merkle_tree_root_index, + address_merkle_tree_account_index: 0, // will be assigned later + address_queue_account_index: 0, // will be assigned later + }) + .collect::>(); + let mut next_index: usize = remaining_accounts.len(); + for (i, params) in new_address_params.iter().enumerate() { + match remaining_accounts.get(¶ms.address_merkle_tree_pubkey.into()) { + Some(_) => {} + None => { + remaining_accounts.insert(params.address_merkle_tree_pubkey.into(), next_index); + next_index += 1; + } + }; + new_address_params_packed[i].address_merkle_tree_account_index = *remaining_accounts + .get(¶ms.address_merkle_tree_pubkey.into()) + .unwrap() + as u8; + } + + for (i, params) in new_address_params.iter().enumerate() { + match remaining_accounts.get(¶ms.address_queue_pubkey.into()) { + Some(_) => {} + None => { + remaining_accounts.insert(params.address_queue_pubkey.into(), next_index); + next_index += 1; + } + }; + new_address_params_packed[i].address_queue_account_index = *remaining_accounts + .get(¶ms.address_queue_pubkey.into()) + .unwrap() as u8; + } + new_address_params_packed +} + +pub fn pack_read_only_address_params( + new_address_params: &[ReadOnlyAddress], + remaining_accounts: &mut HashMap, +) -> Vec { + new_address_params + .iter() + .map(|x| PackedReadOnlyAddress { + address: x.address, + address_merkle_tree_root_index: x.address_merkle_tree_root_index, + address_merkle_tree_account_index: pack_account( + x.address_merkle_tree_pubkey.into(), + remaining_accounts, + ), + }) + .collect::>() +} + +pub fn pack_output_compressed_accounts( + compressed_accounts: &[CompressedAccount], + merkle_trees: &[Pubkey], + remaining_accounts: &mut HashMap, +) -> Vec { + compressed_accounts + .iter() + .zip(merkle_trees.iter()) + .map(|(x, tree)| OutputCompressedAccountWithPackedContext { + compressed_account: x.clone(), + merkle_tree_index: pack_account(*tree, remaining_accounts), + }) + .collect::>() +} + +pub fn pack_compressed_accounts( + compressed_accounts: &[CompressedAccountWithMerkleContext], + root_indices: &[Option], + remaining_accounts: &mut HashMap, +) -> Vec { + compressed_accounts + .iter() + .zip(root_indices.iter()) + .map(|(x, root_index)| { + let mut merkle_context = x.merkle_context; + let root_index = if let Some(root) = root_index { + *root + } else { + merkle_context.prove_by_index = true; + 0 + }; + + PackedCompressedAccountWithMerkleContext { + compressed_account: x.compressed_account.clone(), + merkle_context: pack_merkle_context(&[merkle_context], remaining_accounts)[0], + root_index, + read_only: false, + } + }) + .collect::>() +} +pub fn pack_new_address_params_assigned( + new_address_params: &[NewAddressParamsAssigned], + remaining_accounts: &mut HashMap, +) -> Vec { + let mut vec = Vec::new(); + for new_address_param in new_address_params.iter() { + let address_merkle_tree_account_index = pack_pubkey_usize( + &new_address_param.address_merkle_tree_pubkey.into(), + remaining_accounts, + ); + let address_queue_account_index = pack_pubkey_usize( + &new_address_param.address_queue_pubkey.into(), + remaining_accounts, + ); + vec.push(NewAddressParamsAssignedPacked { + seed: new_address_param.seed, + address_queue_account_index, + address_merkle_tree_root_index: new_address_param.address_merkle_tree_root_index, + address_merkle_tree_account_index, + assigned_to_account: new_address_param.assigned_account_index.is_some(), + assigned_account_index: new_address_param.assigned_account_index.unwrap_or_default(), + }); + } + + vec +} +pub fn pack_pubkey_usize(pubkey: &Pubkey, hash_set: &mut HashMap) -> u8 { + match hash_set.get(pubkey) { + Some(index) => (*index) as u8, + None => { + let index = hash_set.len(); + hash_set.insert(*pubkey, index); + index as u8 + } + } +} +pub fn pack_pubkey(pubkey: &Pubkey, hash_set: &mut HashMap) -> u8 { + match hash_set.get(pubkey) { + Some(index) => *index, + None => { + let index = hash_set.len() as u8; + hash_set.insert(*pubkey, index); + index + } + } +} diff --git a/program-tests/utils/src/spl.rs b/program-tests/utils/src/spl.rs index d144f2b8f0..ceb4ee04d1 100644 --- a/program-tests/utils/src/spl.rs +++ b/program-tests/utils/src/spl.rs @@ -594,7 +594,7 @@ pub async fn compressed_transfer_22_test< } let input_merkle_tree_pubkeys: Vec = input_merkle_tree_context .iter() - .map(|x| x.merkle_tree_pubkey) + .map(|x| x.merkle_tree_pubkey.into()) .collect(); println!("{:?}", input_compressed_accounts); println!( @@ -769,7 +769,12 @@ pub async fn decompress_test>(); let input_merkle_tree_pubkeys = input_compressed_accounts .iter() - .map(|x| x.compressed_account.merkle_context.merkle_tree_pubkey) + .map(|x| { + x.compressed_account + .merkle_context + .merkle_tree_pubkey + .into() + }) .collect::>(); let proof_rpc_result = rpc .get_validity_proof(input_compressed_account_hashes.clone(), vec![], None) @@ -1141,7 +1146,12 @@ pub async fn approve_test>(); let input_merkle_tree_pubkeys = input_compressed_accounts .iter() - .map(|x| x.compressed_account.merkle_context.merkle_tree_pubkey) + .map(|x| { + x.compressed_account + .merkle_context + .merkle_tree_pubkey + .into() + }) .collect::>(); println!( "input_compressed_account_hashes: {:?}", @@ -1223,7 +1233,7 @@ pub async fn approve_test(rpc, output_merkle_tree_accounts.as_slice()).await; let input_merkle_tree_accounts = - test_indexer.get_state_merkle_tree_accounts(&input_merkle_tree_pubkeys); + test_indexer.get_state_merkle_tree_accounts(input_merkle_tree_pubkeys.as_slice()); let input_merkle_tree_test_snapshots = get_merkle_tree_snapshots::(rpc, input_merkle_tree_accounts.as_slice()).await; let context_payer = rpc.get_payer().insecure_clone(); @@ -1310,7 +1320,12 @@ pub async fn revoke_test>(); let input_merkle_tree_pubkeys = input_compressed_accounts .iter() - .map(|x| x.compressed_account.merkle_context.merkle_tree_pubkey) + .map(|x| { + x.compressed_account + .merkle_context + .merkle_tree_pubkey + .into() + }) .collect::>(); let proof_rpc_result = rpc .get_validity_proof(input_compressed_account_hashes.clone(), vec![], None) @@ -1471,7 +1486,12 @@ pub async fn freeze_or_thaw_test< .collect::>(); let input_merkle_tree_pubkeys = input_compressed_accounts .iter() - .map(|x| x.compressed_account.merkle_context.merkle_tree_pubkey) + .map(|x| { + x.compressed_account + .merkle_context + .merkle_tree_pubkey + .into() + }) .collect::>(); let proof_rpc_result = rpc .get_validity_proof(input_compressed_account_hashes.clone(), vec![], None) @@ -1757,7 +1777,12 @@ pub async fn create_burn_test_instruction>(); let input_merkle_tree_pubkeys = input_compressed_accounts .iter() - .map(|x| x.compressed_account.merkle_context.merkle_tree_pubkey) + .map(|x| { + x.compressed_account + .merkle_context + .merkle_tree_pubkey + .into() + }) .collect::>(); let proof_rpc_result = rpc .get_validity_proof(input_compressed_account_hashes.clone(), vec![], None) diff --git a/program-tests/utils/src/system_program.rs b/program-tests/utils/src/system_program.rs index 50b3fd3bdd..40755d54dd 100644 --- a/program-tests/utils/src/system_program.rs +++ b/program-tests/utils/src/system_program.rs @@ -56,15 +56,15 @@ pub async fn create_addresses_test< let mut derived_addresses = Vec::new(); for (i, address_seed) in address_seeds.iter().enumerate() { let derived_address = - derive_address_legacy(&address_merkle_tree_pubkeys[i], address_seed).unwrap(); + derive_address_legacy(&address_merkle_tree_pubkeys[i].into(), address_seed).unwrap(); derived_addresses.push(derived_address); } let mut address_params = Vec::new(); for (i, seed) in address_seeds.iter().enumerate() { let new_address_params = NewAddressParams { - address_queue_pubkey: address_merkle_tree_queue_pubkeys[i], - address_merkle_tree_pubkey: address_merkle_tree_pubkeys[i], + address_queue_pubkey: address_merkle_tree_queue_pubkeys[i].into(), + address_merkle_tree_pubkey: address_merkle_tree_pubkeys[i].into(), seed: *seed, address_merkle_tree_root_index: 0, }; @@ -75,7 +75,7 @@ pub async fn create_addresses_test< for address in derived_addresses.iter() { output_compressed_accounts.push(CompressedAccount { lamports: 0, - owner: rpc.get_payer().pubkey(), + owner: rpc.get_payer().pubkey().into(), data: None, address: Some(*address), }); @@ -85,11 +85,12 @@ pub async fn create_addresses_test< for compressed_account in input_compressed_accounts.iter() { output_compressed_accounts.push(CompressedAccount { lamports: 0, - owner: rpc.get_payer().pubkey(), + owner: rpc.get_payer().pubkey().into(), data: None, address: compressed_account.compressed_account.address, }); - output_merkle_tree_pubkeys.push(compressed_account.merkle_context.merkle_tree_pubkey); + output_merkle_tree_pubkeys + .push(compressed_account.merkle_context.merkle_tree_pubkey.into()); } } @@ -138,7 +139,7 @@ pub async fn compress_sol_test>(); let state_input_merkle_trees = if state_input_merkle_trees.is_empty() { None @@ -345,7 +347,7 @@ pub async fn compressed_transaction_test< .enumerate() .map(|(i, x)| AddressWithTree { address: inputs.created_addresses.as_ref().unwrap()[i], - tree: x.address_merkle_tree_pubkey, + tree: x.address_merkle_tree_pubkey.into(), }) .collect::>(); let proof_rpc_res = inputs @@ -467,7 +469,7 @@ pub async fn compressed_transaction_test< address_queue_pubkeys: &inputs .new_address_params .iter() - .map(|x| x.address_queue_pubkey) + .map(|x| x.address_queue_pubkey.into()) .collect::>(), }; assert_compressed_transaction(input).await; @@ -564,10 +566,10 @@ pub fn create_invoke_instruction_data_and_remaining_accounts( }) .collect::>(); for (i, context) in merkle_context.iter().enumerate() { - match remaining_accounts.get(&context.merkle_tree_pubkey) { + match remaining_accounts.get(&context.merkle_tree_pubkey.into()) { Some(_) => {} None => { - remaining_accounts.insert(context.merkle_tree_pubkey, index); + remaining_accounts.insert(context.merkle_tree_pubkey.into(), index); index += 1; } }; @@ -581,7 +583,7 @@ pub fn create_invoke_instruction_data_and_remaining_accounts( compressed_account: input_compressed_accounts[i].clone(), merkle_context: PackedMerkleContext { merkle_tree_pubkey_index: *remaining_accounts - .get(&context.merkle_tree_pubkey) + .get(&context.merkle_tree_pubkey.into()) .unwrap() as u8, queue_pubkey_index: 0, leaf_index: context.leaf_index, @@ -593,16 +595,18 @@ pub fn create_invoke_instruction_data_and_remaining_accounts( } for (i, context) in merkle_context.iter().enumerate() { - match remaining_accounts.get(&context.queue_pubkey) { + match remaining_accounts.get(&context.queue_pubkey.into()) { Some(_) => {} None => { - remaining_accounts.insert(context.queue_pubkey, index); + remaining_accounts.insert(context.queue_pubkey.into(), index); index += 1; } }; _input_compressed_accounts[i] .merkle_context - .queue_pubkey_index = *remaining_accounts.get(&context.queue_pubkey).unwrap() as u8; + .queue_pubkey_index = *remaining_accounts + .get(&context.queue_pubkey.into()) + .unwrap() as u8; } let mut output_compressed_accounts_with_context: Vec = @@ -627,31 +631,35 @@ pub fn create_invoke_instruction_data_and_remaining_accounts( } for (i, params) in new_address_params.iter().enumerate() { - match remaining_accounts.get(¶ms.address_merkle_tree_pubkey) { + match remaining_accounts.get(¶ms.address_merkle_tree_pubkey.into()) { Some(_) => {} None => { - remaining_accounts.insert(params.address_merkle_tree_pubkey, index); + remaining_accounts.insert(params.address_merkle_tree_pubkey.into(), index); index += 1; } }; new_address_params_packed[i].address_merkle_tree_account_index = *remaining_accounts - .get(¶ms.address_merkle_tree_pubkey) + .get(¶ms.address_merkle_tree_pubkey.into()) .unwrap() as u8; } for (i, params) in new_address_params.iter().enumerate() { - match remaining_accounts.get(¶ms.address_queue_pubkey) { + match remaining_accounts.get(¶ms.address_queue_pubkey.into()) { Some(_) => {} None => { - remaining_accounts.insert(params.address_queue_pubkey, index); + remaining_accounts.insert(params.address_queue_pubkey.into(), index); index += 1; } }; new_address_params_packed[i].address_queue_account_index = *remaining_accounts - .get(¶ms.address_queue_pubkey) + .get(¶ms.address_queue_pubkey.into()) .unwrap() as u8; } + // let mut remaining_accounts = remaining_accounts + // .iter() + // .map(|(k, i)| (AccountMeta::new(*k, false), *i)) + // .collect::>(); let mut remaining_accounts = remaining_accounts .iter() .map(|(k, i)| (AccountMeta::new(*k, false), *i)) @@ -689,13 +697,13 @@ mod test { let input_compressed_accounts = vec![ CompressedAccount { lamports: 100, - owner: payer, + owner: payer.into(), address: None, data: None, }, CompressedAccount { lamports: 100, - owner: payer, + owner: payer.into(), address: None, data: None, }, @@ -703,13 +711,13 @@ mod test { let output_compressed_accounts = vec![ CompressedAccount { lamports: 50, - owner: payer, + owner: payer.into(), address: None, data: None, }, CompressedAccount { lamports: 150, - owner: recipient, + owner: recipient.into(), address: None, data: None, }, @@ -721,15 +729,15 @@ mod test { let nullifier_array_pubkey = Keypair::new().pubkey(); let input_merkle_context = vec![ MerkleContext { - merkle_tree_pubkey, - queue_pubkey: nullifier_array_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), + queue_pubkey: nullifier_array_pubkey.into(), leaf_index: 0, prove_by_index: false, tree_type: light_compressed_account::TreeType::StateV1, }, MerkleContext { - merkle_tree_pubkey, - queue_pubkey: nullifier_array_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), + queue_pubkey: nullifier_array_pubkey.into(), leaf_index: 1, prove_by_index: false, tree_type: light_compressed_account::TreeType::StateV1, diff --git a/programs/compressed-token/src/freeze.rs b/programs/compressed-token/src/freeze.rs index 0711906faa..bb43ea9b89 100644 --- a/programs/compressed-token/src/freeze.rs +++ b/programs/compressed-token/src/freeze.rs @@ -522,7 +522,7 @@ pub mod test_freeze { }; expected_compressed_output_accounts.push(OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: crate::ID, + owner: crate::ID.into(), lamports: 0, data: Some(change_data_struct), address: None, diff --git a/programs/compressed-token/src/process_mint.rs b/programs/compressed-token/src/process_mint.rs index e4bcfa60a4..719eeda736 100644 --- a/programs/compressed-token/src/process_mint.rs +++ b/programs/compressed-token/src/process_mint.rs @@ -570,7 +570,7 @@ mod test { output_compressed_accounts[i] = OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: crate::ID, + owner: crate::ID.into(), lamports, data: Some(data), address: None, @@ -635,7 +635,7 @@ mod test { output_compressed_accounts[i] = OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: crate::ID, + owner: crate::ID.into(), lamports, data: Some(data), address: None, diff --git a/programs/compressed-token/src/process_transfer.rs b/programs/compressed-token/src/process_transfer.rs index 7ada7f8c3f..b5f7b32b95 100644 --- a/programs/compressed-token/src/process_transfer.rs +++ b/programs/compressed-token/src/process_transfer.rs @@ -1000,10 +1000,11 @@ pub mod transfer_sdk { let mut input_token_data_with_context: Vec = Vec::new(); for (i, token_data) in input_token_data.iter().enumerate() { - match remaining_accounts.get(&input_merkle_context[i].merkle_tree_pubkey) { + match remaining_accounts.get(&input_merkle_context[i].merkle_tree_pubkey.into()) { Some(_) => {} None => { - remaining_accounts.insert(input_merkle_context[i].merkle_tree_pubkey, index); + remaining_accounts + .insert(input_merkle_context[i].merkle_tree_pubkey.into(), index); index += 1; } }; @@ -1031,7 +1032,7 @@ pub mod transfer_sdk { delegate_index, merkle_context: PackedMerkleContext { merkle_tree_pubkey_index: *remaining_accounts - .get(&input_merkle_context[i].merkle_tree_pubkey) + .get(&input_merkle_context[i].merkle_tree_pubkey.into()) .unwrap() as u8, queue_pubkey_index: 0, leaf_index: input_merkle_context[i].leaf_index, @@ -1044,17 +1045,17 @@ pub mod transfer_sdk { input_token_data_with_context.push(token_data_with_context); } for (i, _) in input_token_data.iter().enumerate() { - match remaining_accounts.get(&input_merkle_context[i].queue_pubkey) { + match remaining_accounts.get(&input_merkle_context[i].queue_pubkey.into()) { Some(_) => {} None => { - remaining_accounts.insert(input_merkle_context[i].queue_pubkey, index); + remaining_accounts.insert(input_merkle_context[i].queue_pubkey.into(), index); index += 1; } }; input_token_data_with_context[i] .merkle_context .queue_pubkey_index = *remaining_accounts - .get(&input_merkle_context[i].queue_pubkey) + .get(&input_merkle_context[i].queue_pubkey.into()) .unwrap() as u8; } let mut _output_compressed_accounts: Vec = diff --git a/programs/system/src/errors.rs b/programs/system/src/errors.rs index 735d56ce7d..2c6e06b27b 100644 --- a/programs/system/src/errors.rs +++ b/programs/system/src/errors.rs @@ -1,4 +1,3 @@ -// use anchor_lang::error_code; use pinocchio::program_error::ProgramError; use thiserror::Error; diff --git a/programs/system/src/invoke/verify_signer.rs b/programs/system/src/invoke/verify_signer.rs index 98a94015c6..18cd38b1d9 100644 --- a/programs/system/src/invoke/verify_signer.rs +++ b/programs/system/src/invoke/verify_signer.rs @@ -47,7 +47,7 @@ mod test { let compressed_account_with_context = PackedCompressedAccountWithMerkleContext { compressed_account: CompressedAccount { - owner: authority, + owner: authority.into(), ..CompressedAccount::default() }, ..PackedCompressedAccountWithMerkleContext::default() @@ -70,7 +70,7 @@ mod test { let invalid_compressed_account_with_context = PackedCompressedAccountWithMerkleContext { compressed_account: CompressedAccount { - owner: solana_pubkey::Pubkey::new_unique().to_bytes(), + owner: solana_pubkey::Pubkey::new_unique().to_bytes().into(), ..CompressedAccount::default() }, ..PackedCompressedAccountWithMerkleContext::default() diff --git a/programs/system/src/invoke_cpi/process_cpi_context.rs b/programs/system/src/invoke_cpi/process_cpi_context.rs index f3eba721d8..2076573ef8 100644 --- a/programs/system/src/invoke_cpi/process_cpi_context.rs +++ b/programs/system/src/invoke_cpi/process_cpi_context.rs @@ -1,7 +1,8 @@ use light_account_checks::discriminator::Discriminator; use light_batched_merkle_tree::queue::BatchedQueueAccount; -use light_compressed_account::instruction_data::{ - invoke_cpi::InstructionDataInvokeCpi, traits::InstructionData, +use light_compressed_account::{ + instruction_data::{invoke_cpi::InstructionDataInvokeCpi, traits::InstructionData}, + pubkey::AsPubkey, }; use pinocchio::{account_info::AccountInfo, msg, pubkey::Pubkey}; @@ -220,7 +221,7 @@ fn validate_cpi_context_associated_with_merkle_tree<'a, 'info, T: InstructionDat mod tests { use borsh::BorshSerialize; - use light_account_checks::test_account_info::pinocchio::get_account_info; + use light_account_checks::account_info::test_account_info::pinocchio::get_account_info; use light_compressed_account::{ compressed_account::{ CompressedAccount, PackedCompressedAccountWithMerkleContext, PackedMerkleContext, @@ -277,7 +278,7 @@ mod tests { input_compressed_accounts_with_merkle_context: vec![ PackedCompressedAccountWithMerkleContext { compressed_account: CompressedAccount { - owner: solana_pubkey::Pubkey::new_unique().to_bytes(), + owner: solana_pubkey::Pubkey::new_unique().to_bytes().into(), lamports: iter.into(), address: None, data: None, @@ -294,7 +295,7 @@ mod tests { ], output_compressed_accounts: vec![OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: solana_pubkey::Pubkey::new_unique().to_bytes(), + owner: solana_pubkey::Pubkey::new_unique().to_bytes().into(), lamports: iter.into(), address: None, data: None, diff --git a/programs/system/src/processor/sum_check.rs b/programs/system/src/processor/sum_check.rs index da8a59ef23..522d9f4b63 100644 --- a/programs/system/src/processor/sum_check.rs +++ b/programs/system/src/processor/sum_check.rs @@ -172,7 +172,7 @@ mod test { }; inputs.push(PackedCompressedAccountWithMerkleContext { compressed_account: CompressedAccount { - owner: Pubkey::new_unique().into(), + owner: Pubkey::new_unique(), lamports: *i, address: None, data: None, @@ -193,7 +193,7 @@ mod test { for amount in output_amounts.iter() { outputs.push(OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner: Pubkey::new_unique().into(), + owner: Pubkey::new_unique(), lamports: *amount, address: None, data: None, diff --git a/programs/system/tests/invoke_cpi_instruction.rs b/programs/system/tests/invoke_cpi_instruction.rs index 96bd56241a..e58e6a1dfe 100644 --- a/programs/system/tests/invoke_cpi_instruction.rs +++ b/programs/system/tests/invoke_cpi_instruction.rs @@ -1,8 +1,8 @@ use std::panic::catch_unwind; use light_account_checks::{ + account_info::test_account_info::pinocchio::{get_account_info, pubkey_unique}, error::AccountError, - test_account_info::pinocchio::{get_account_info, pubkey_unique}, }; use light_compressed_account::constants::ACCOUNT_COMPRESSION_PROGRAM_ID; use light_system_program_pinocchio::invoke_cpi::instruction::InvokeCpiInstruction; diff --git a/programs/system/tests/invoke_cpi_instruction_small.rs b/programs/system/tests/invoke_cpi_instruction_small.rs index 0dbbdecc30..c42941b79b 100644 --- a/programs/system/tests/invoke_cpi_instruction_small.rs +++ b/programs/system/tests/invoke_cpi_instruction_small.rs @@ -1,9 +1,9 @@ use std::panic::catch_unwind; use light_account_checks::{ + account_info::test_account_info::pinocchio::{get_account_info, pubkey_unique}, discriminator::Discriminator, error::AccountError, - test_account_info::pinocchio::{get_account_info, pubkey_unique}, }; use light_compressed_account::instruction_data::traits::AccountOptions; use light_system_program_pinocchio::invoke_cpi::{ diff --git a/scripts/format.sh b/scripts/format.sh index be223f73e8..92861e9c64 100755 --- a/scripts/format.sh +++ b/scripts/format.sh @@ -9,19 +9,16 @@ cargo +nightly fmt --all cargo clippy \ --workspace \ --no-deps \ + --all-features \ --exclude name-service \ --exclude photon-api \ --exclude name-service \ - --exclude light-system-program-pinocchio \ -- -A clippy::result_large_err \ -A clippy::empty-docs \ -A clippy::to-string-trait-impl \ -A unexpected-cfgs \ -A clippy::doc_lazy_continuation \ -D warnings -# We import the same crates with different features in light-system-program-pinocchio than in account-compression -# clippy cannot handle this. -> check light-system-program-pinocchio separately -cargo clippy --package light-system-program-pinocchio --all-targets -- -D warnings # Make sure that tests compile cargo test-sbf -p system-test --no-run diff --git a/scripts/lint.sh b/scripts/lint.sh index dbb5e42254..1f086f8872 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -5,7 +5,4 @@ npx nx run-many --target=format:check --all npx nx run-many --target=lint --all cargo +nightly fmt --all -- --check -cargo clippy --workspace --all-targets --exclude light-system-program-pinocchio -- -D warnings -# We import the same crates with different features in light-system-program-pinocchio than in account-compression -# clippy cannot handle this. -> check light-system-program-pinocchio separately. -cargo clippy --package light-system-program-pinocchio --all-targets -- -D warnings +cargo clippy --workspace --all-features --all-targets -- -D warnings diff --git a/sdk-libs/client/src/indexer/types.rs b/sdk-libs/client/src/indexer/types.rs index 7457650e24..4966c477ce 100644 --- a/sdk-libs/client/src/indexer/types.rs +++ b/sdk-libs/client/src/indexer/types.rs @@ -11,8 +11,8 @@ use light_sdk::{ pack_accounts::PackedAccounts, tree_info::{PackedAddressTreeInfo, PackedStateTreeInfo}, }, + light_compressed_account::instruction_data::compressed_proof::CompressedProof, token::{AccountState, TokenData}, - verifier::CompressedProof, ValidityProof, }; use num_bigint::BigUint; @@ -455,9 +455,10 @@ impl TreeInfo { leaf_index: u32, prove_by_index: bool, ) -> light_compressed_account::compressed_account::MerkleContext { + use light_compressed_account::Pubkey; light_compressed_account::compressed_account::MerkleContext { - merkle_tree_pubkey: self.tree, - queue_pubkey: self.queue, + merkle_tree_pubkey: Pubkey::new_from_array(self.tree.to_bytes()), + queue_pubkey: Pubkey::new_from_array(self.queue.to_bytes()), leaf_index, tree_type: self.tree_type, prove_by_index, @@ -498,13 +499,13 @@ impl TryFrom for CompressedAccount { lamports: account.compressed_account.lamports, leaf_index: account.merkle_context.leaf_index, tree_info: TreeInfo { - tree: account.merkle_context.merkle_tree_pubkey, - queue: account.merkle_context.queue_pubkey, + tree: Pubkey::new_from_array(account.merkle_context.merkle_tree_pubkey.to_bytes()), + queue: Pubkey::new_from_array(account.merkle_context.queue_pubkey.to_bytes()), tree_type: account.merkle_context.tree_type, cpi_context: None, next_tree_info: None, }, - owner: account.compressed_account.owner, + owner: Pubkey::new_from_array(account.compressed_account.owner.to_bytes()), prove_by_index: account.merkle_context.prove_by_index, seq: None, slot_created: u64::MAX, @@ -514,8 +515,9 @@ impl TryFrom for CompressedAccount { impl From for CompressedAccountWithMerkleContext { fn from(account: CompressedAccount) -> Self { + use light_compressed_account::Pubkey; let compressed_account = ProgramCompressedAccount { - owner: account.owner, + owner: Pubkey::new_from_array(account.owner.to_bytes()), lamports: account.lamports, address: account.address, data: account.data, diff --git a/sdk-libs/client/src/rpc/client.rs b/sdk-libs/client/src/rpc/client.rs index 5469284d96..f5d7fc2f0b 100644 --- a/sdk-libs/client/src/rpc/client.rs +++ b/sdk-libs/client/src/rpc/client.rs @@ -208,9 +208,16 @@ impl LightClient { let mut vec_accounts = Vec::new(); let mut program_ids = Vec::new(); instructions_vec.iter().for_each(|x| { - program_ids.push(x.program_id); + program_ids.push(light_compressed_account::Pubkey::new_from_array( + x.program_id.to_bytes(), + )); vec.push(x.data.clone()); - vec_accounts.push(x.accounts.iter().map(|x| x.pubkey).collect()); + vec_accounts.push( + x.accounts + .iter() + .map(|x| light_compressed_account::Pubkey::new_from_array(x.pubkey.to_bytes())) + .collect(), + ); }); { let rpc_transaction_config = RpcTransactionConfig { @@ -265,13 +272,18 @@ impl LightClient { ) })?; vec.push(data); - program_ids.push( - account_keys[ui_compiled_instruction.program_id_index as usize], - ); + program_ids.push(light_compressed_account::Pubkey::new_from_array( + account_keys[ui_compiled_instruction.program_id_index as usize] + .to_bytes(), + )); vec_accounts.push( accounts .iter() - .map(|x| account_keys[(*x) as usize]) + .map(|x| { + light_compressed_account::Pubkey::new_from_array( + account_keys[(*x) as usize].to_bytes(), + ) + }) .collect(), ); } diff --git a/sdk-libs/macros/Cargo.toml b/sdk-libs/macros/Cargo.toml index 47b14366a0..90db169c1f 100644 --- a/sdk-libs/macros/Cargo.toml +++ b/sdk-libs/macros/Cargo.toml @@ -12,7 +12,7 @@ quote = { workspace = true } syn = { workspace = true } light-hasher = { workspace = true } -ark-bn254 = { workspace = true } +# ark-bn254 = { workspace = true } light-poseidon = { workspace = true } [dev-dependencies] diff --git a/sdk-libs/macros/src/discriminator.rs b/sdk-libs/macros/src/discriminator.rs index 5498dfc49a..176749dcff 100644 --- a/sdk-libs/macros/src/discriminator.rs +++ b/sdk-libs/macros/src/discriminator.rs @@ -13,7 +13,7 @@ pub(crate) fn discriminator(input: ItemStruct) -> Result { let discriminator: proc_macro2::TokenStream = format!("{discriminator:?}").parse().unwrap(); Ok(quote! { - impl #impl_gen ::light_sdk::LightDiscriminator for #account_name #type_gen #where_clause { + impl #impl_gen LightDiscriminator for #account_name #type_gen #where_clause { const LIGHT_DISCRIMINATOR: [u8; 8] = #discriminator; const LIGHT_DISCRIMINATOR_SLICE: &'static [u8] = &Self::LIGHT_DISCRIMINATOR; diff --git a/sdk-libs/program-test/src/indexer/test_indexer.rs b/sdk-libs/program-test/src/indexer/test_indexer.rs index 219e415ddc..7eeed42db3 100644 --- a/sdk-libs/program-test/src/indexer/test_indexer.rs +++ b/sdk-libs/program-test/src/indexer/test_indexer.rs @@ -1124,7 +1124,7 @@ impl TestIndexerExtensions for TestIndexer { ) -> Vec { self.compressed_accounts .iter() - .filter(|x| x.compressed_account.owner == *owner) + .filter(|x| x.compressed_account.owner.to_bytes() == owner.to_bytes()) .cloned() .collect() } @@ -1562,7 +1562,7 @@ impl TestIndexer { pub fn get_compressed_balance(&self, owner: &Pubkey) -> u64 { self.compressed_accounts .iter() - .filter(|x| x.compressed_account.owner == *owner) + .filter(|x| x.compressed_account.owner.to_bytes() == owner.to_bytes()) .map(|x| x.compressed_account.lamports) .sum() } @@ -1572,7 +1572,7 @@ impl TestIndexer { self.token_compressed_accounts .iter() .filter(|x| { - x.compressed_account.compressed_account.owner == *owner + x.compressed_account.compressed_account.owner.to_bytes() == owner.to_bytes() && x.token_data.mint == *mint }) .map(|x| x.token_data.amount) @@ -1634,7 +1634,10 @@ impl TestIndexer { let bundle = &mut ::get_state_merkle_trees_mut(self) .iter_mut() - .find(|x| x.accounts.merkle_tree == merkle_tree_pubkey) + .find(|x| { + x.accounts.merkle_tree + == solana_pubkey::Pubkey::from(merkle_tree_pubkey.to_bytes()) + }) .unwrap(); // Store leaf indices of input accounts for batched trees if bundle.tree_type == TreeType::StateV2 { @@ -1656,8 +1659,11 @@ impl TestIndexer { } let merkle_tree = self.state_merkle_trees.iter().find(|x| { x.accounts.merkle_tree - == event.pubkey_array - [event.output_compressed_accounts[i].merkle_tree_index as usize] + == solana_pubkey::Pubkey::from( + event.pubkey_array + [event.output_compressed_accounts[i].merkle_tree_index as usize] + .to_bytes(), + ) }); // Check for output queue let merkle_tree = if let Some(merkle_tree) = merkle_tree { @@ -1667,8 +1673,12 @@ impl TestIndexer { .iter() .find(|x| { x.accounts.nullifier_queue - == event.pubkey_array - [event.output_compressed_accounts[i].merkle_tree_index as usize] + == solana_pubkey::Pubkey::from( + event.pubkey_array[event.output_compressed_accounts[i] + .merkle_tree_index + as usize] + .to_bytes(), + ) }) .unwrap() }; @@ -1679,7 +1689,7 @@ impl TestIndexer { // new accounts are inserted in front so that the newest accounts are found first match compressed_account.compressed_account.data.as_ref() { Some(data) => { - if compressed_account.compressed_account.owner == light_compressed_token::ID + if compressed_account.compressed_account.owner == light_compressed_token::ID.to_bytes() && data.discriminator == light_compressed_token::constants::TOKEN_COMPRESSED_ACCOUNT_DISCRIMINATOR { if let Ok(token_data) = TokenData::deserialize(&mut data.data.as_slice()) { @@ -1691,8 +1701,8 @@ impl TestIndexer { .clone(), merkle_context: MerkleContext { leaf_index: event.output_leaf_indices[i], - merkle_tree_pubkey, - queue_pubkey: nullifier_queue_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), + queue_pubkey: nullifier_queue_pubkey.into(), prove_by_index: false, tree_type:merkle_tree.tree_type, }, @@ -1706,8 +1716,8 @@ impl TestIndexer { compressed_account: compressed_account.compressed_account.clone(), merkle_context: MerkleContext { leaf_index: event.output_leaf_indices[i], - merkle_tree_pubkey, - queue_pubkey: nullifier_queue_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), + queue_pubkey: nullifier_queue_pubkey.into(), prove_by_index: false, tree_type: merkle_tree.tree_type }, @@ -1721,8 +1731,8 @@ impl TestIndexer { compressed_account: compressed_account.compressed_account.clone(), merkle_context: MerkleContext { leaf_index: event.output_leaf_indices[i], - merkle_tree_pubkey, - queue_pubkey: nullifier_queue_pubkey, + merkle_tree_pubkey: merkle_tree_pubkey.into(), + queue_pubkey: nullifier_queue_pubkey.into(), prove_by_index: false, tree_type: merkle_tree.tree_type, }, @@ -1733,8 +1743,11 @@ impl TestIndexer { }; let merkle_tree = &mut self.state_merkle_trees.iter_mut().find(|x| { x.accounts.merkle_tree - == event.pubkey_array - [event.output_compressed_accounts[i].merkle_tree_index as usize] + == solana_pubkey::Pubkey::from( + event.pubkey_array + [event.output_compressed_accounts[i].merkle_tree_index as usize] + .to_bytes(), + ) }); if merkle_tree.is_some() { let merkle_tree = merkle_tree.as_mut().unwrap(); @@ -1757,8 +1770,12 @@ impl TestIndexer { .iter_mut() .find(|x| { x.accounts.nullifier_queue - == event.pubkey_array - [event.output_compressed_accounts[i].merkle_tree_index as usize] + == solana_pubkey::Pubkey::from( + event.pubkey_array[event.output_compressed_accounts[i] + .merkle_tree_index + as usize] + .to_bytes(), + ) }) .unwrap(); @@ -1780,7 +1797,9 @@ impl TestIndexer { .address_merkle_trees .iter_mut() .enumerate() - .find(|(_, x)| x.accounts.merkle_tree == *pubkey) + .find(|(_, x)| { + x.accounts.merkle_tree == solana_pubkey::Pubkey::from(pubkey.to_bytes()) + }) { address_merkle_tree .queue_elements diff --git a/sdk-libs/program-test/src/program_test/rpc.rs b/sdk-libs/program-test/src/program_test/rpc.rs index 64a44487b7..a298a7ef8a 100644 --- a/sdk-libs/program-test/src/program_test/rpc.rs +++ b/sdk-libs/program-test/src/program_test/rpc.rs @@ -174,12 +174,10 @@ impl Rpc for LightProgramTest { .await?; } else { let _res = self.context.send_transaction(transaction).map_err(|x| { - #[cfg(not(debug_assertions))] - { - if self.config.log_failed_tx { - println!("{}", x.meta.pretty_logs()); - } + if self.config.log_failed_tx { + println!("{}", x.meta.pretty_logs()); } + RpcError::TransactionError(x.err) })?; #[cfg(debug_assertions)] @@ -350,12 +348,10 @@ impl LightProgramTest { .context .simulate_transaction(transaction.clone()) .map_err(|x| { - #[cfg(not(debug_assertions))] - { - if self.config.log_failed_tx { - println!("{}", x.meta.pretty_logs()); - } + if self.config.log_failed_tx { + println!("{}", x.meta.pretty_logs()); } + RpcError::TransactionError(x.err) })?; @@ -411,9 +407,12 @@ impl LightProgramTest { }); event_from_light_transaction( - program_ids.as_slice(), + &program_ids.iter().map(|x| (*x).into()).collect::>(), vec.as_slice(), - vec_accounts.to_vec(), + vec_accounts + .iter() + .map(|inner_vec| inner_vec.iter().map(|x| (*x).into()).collect()) + .collect(), ) .or(Ok::< Option>, @@ -424,12 +423,11 @@ impl LightProgramTest { // Transaction was successful, execute it. let _res = self.context.send_transaction(transaction).map_err(|x| { // Prevent duplicate prints for failing tx. - #[cfg(not(debug_assertions))] - { - if self.config.log_failed_tx { - println!("{}", x.meta.pretty_logs()); - } + + if self.config.log_failed_tx { + println!("{}", x.meta.pretty_logs()); } + RpcError::TransactionError(x.err) })?; #[cfg(debug_assertions)] diff --git a/sdk-libs/program-test/src/utils/setup_light_programs.rs b/sdk-libs/program-test/src/utils/setup_light_programs.rs index d723c15da4..221fcb826a 100644 --- a/sdk-libs/program-test/src/utils/setup_light_programs.rs +++ b/sdk-libs/program-test/src/utils/setup_light_programs.rs @@ -45,17 +45,40 @@ pub fn setup_light_programs( )))?; std::env::set_var("SBF_OUT_DIR", light_bin_path); let path = format!("{}/light_registry.so", light_bin_path); - program_test.add_program_from_file(light_registry::ID, path)?; + program_test + .add_program_from_file(light_registry::ID, path.clone()) + .inspect_err(|_| { + println!("Program light_registry bin not found in {}", path); + })?; let path = format!("{}/account_compression.so", light_bin_path); - program_test.add_program_from_file(account_compression::ID, path)?; + program_test + .add_program_from_file(account_compression::ID, path.clone()) + .inspect_err(|_| { + println!("Program account_compression bin not found in {}", path); + })?; let path = format!("{}/light_compressed_token.so", light_bin_path); - program_test.add_program_from_file(light_compressed_token::ID, path)?; + program_test + .add_program_from_file(light_compressed_token::ID, path.clone()) + .inspect_err(|_| { + println!("Program light_compressed_token bin not found in {}", path); + })?; let path = format!("{}/spl_noop.so", light_bin_path); - program_test.add_program_from_file(NOOP_PROGRAM_ID, path)?; + program_test + .add_program_from_file(NOOP_PROGRAM_ID, path.clone()) + .inspect_err(|_| { + println!("Program spl_noop bin not found in {}", path); + })?; #[cfg(feature = "devenv")] { let path = format!("{}/light_system_program_pinocchio.so", light_bin_path); - program_test.add_program_from_file(light_sdk::constants::PROGRAM_ID_LIGHT_SYSTEM, path)?; + program_test + .add_program_from_file(light_sdk::constants::PROGRAM_ID_LIGHT_SYSTEM, path.clone()) + .inspect_err(|_| { + println!( + "Program light_system_program_pinocchio bin not found in {}", + path + ); + })?; } #[cfg(not(feature = "devenv"))] diff --git a/sdk-libs/sdk/Cargo.toml b/sdk-libs/sdk/Cargo.toml index 04831098c0..d40492c813 100644 --- a/sdk-libs/sdk/Cargo.toml +++ b/sdk-libs/sdk/Cargo.toml @@ -15,22 +15,18 @@ solana = [ "solana-cpi", "solana-instruction", "solana-pubkey", + "solana-pubkey/borsh", + "solana-pubkey/curve25519", + "solana-pubkey/sha2", "solana-account-info", "solana-msg", "solana-program-error", "borsh", - "light-verifier/solana", "light-compressed-account/solana", - "light-hasher/solana", ] default = ["solana"] idl-build = ["anchor-lang/idl-build"] -anchor = [ - "anchor-lang", - "light-compressed-account/anchor", - "light-verifier/anchor", - "light-hasher/solana", -] +anchor = ["anchor-lang", "light-compressed-account/anchor"] v2 = [] [dependencies] @@ -51,9 +47,9 @@ thiserror = { workspace = true } light-sdk-macros = { workspace = true } light-macros = { workspace = true } light-compressed-account = { workspace = true } -light-verifier = { workspace = true } light-hasher = { workspace = true } light-account-checks = { workspace = true } [dev-dependencies] num-bigint = { workspace = true } +light-compressed-account = { workspace = true , features = ["new-unique"]} diff --git a/sdk-libs/sdk/src/account.rs b/sdk-libs/sdk/src/account.rs index 78fa544263..29da44c72c 100644 --- a/sdk-libs/sdk/src/account.rs +++ b/sdk-libs/sdk/src/account.rs @@ -3,9 +3,9 @@ use std::ops::{Deref, DerefMut}; use light_compressed_account::{ compressed_account::PackedMerkleContext, instruction_data::with_account_info::{CompressedAccountInfo, InAccountInfo, OutAccountInfo}, - pubkey::Pubkey, }; use light_hasher::{DataHasher, Poseidon}; +use solana_pubkey::Pubkey; use crate::{ error::LightSdkError, instruction::account_meta::CompressedAccountMetaTrait, AnchorDeserialize, diff --git a/sdk-libs/sdk/src/account_info.rs b/sdk-libs/sdk/src/account_info.rs index 5f54030bbf..6687cdffc8 100644 --- a/sdk-libs/sdk/src/account_info.rs +++ b/sdk-libs/sdk/src/account_info.rs @@ -193,7 +193,7 @@ impl AccountInfoTrait for CompressedAccountInfo { }); Ok(Some(PackedCompressedAccountWithMerkleContext { compressed_account: CompressedAccount { - owner, + owner: owner.to_bytes().into(), lamports: input.lamports, address: self.address, data, @@ -220,7 +220,7 @@ impl AccountInfoTrait for CompressedAccountInfo { }); Ok(Some(OutputCompressedAccountWithPackedContext { compressed_account: CompressedAccount { - owner, + owner: owner.to_bytes().into(), lamports: output.lamports, address: self.address, data, diff --git a/sdk-libs/sdk/src/address.rs b/sdk-libs/sdk/src/address.rs index 93e657da71..3adb5043f7 100644 --- a/sdk-libs/sdk/src/address.rs +++ b/sdk-libs/sdk/src/address.rs @@ -20,9 +20,9 @@ pub fn pack_new_addresses_params( .iter() .map(|x| { let address_queue_account_index = - remaining_accounts.insert_or_get(x.address_queue_pubkey); + remaining_accounts.insert_or_get(x.address_queue_pubkey.to_bytes().into()); let address_merkle_tree_account_index = - remaining_accounts.insert_or_get(x.address_merkle_tree_pubkey); + remaining_accounts.insert_or_get(x.address_merkle_tree_pubkey.to_bytes().into()); PackedNewAddressParams { seed: x.seed, address_queue_account_index, @@ -50,8 +50,8 @@ pub fn unpack_new_address_params( remaining_accounts[address_params.address_queue_account_index as usize].key; NewAddressParams { seed: address_params.seed, - address_queue_pubkey: *address_queue_pubkey, - address_merkle_tree_pubkey: *address_merkle_tree_pubkey, + address_queue_pubkey: address_queue_pubkey.to_bytes().into(), + address_merkle_tree_pubkey: address_merkle_tree_pubkey.to_bytes().into(), address_merkle_tree_root_index: address_params.address_merkle_tree_root_index, } } diff --git a/sdk-libs/sdk/src/instruction/tree_info.rs b/sdk-libs/sdk/src/instruction/tree_info.rs index b6ccab26b3..59fbbb378d 100644 --- a/sdk-libs/sdk/src/instruction/tree_info.rs +++ b/sdk-libs/sdk/src/instruction/tree_info.rs @@ -61,8 +61,9 @@ pub fn pack_merkle_context( prove_by_index, .. } = merkle_context; - let merkle_tree_pubkey_index = remaining_accounts.insert_or_get(*merkle_tree_pubkey); - let queue_pubkey_index = remaining_accounts.insert_or_get(*queue_pubkey); + let merkle_tree_pubkey_index = + remaining_accounts.insert_or_get(merkle_tree_pubkey.to_bytes().into()); + let queue_pubkey_index = remaining_accounts.insert_or_get(queue_pubkey.to_bytes().into()); PackedMerkleContext { merkle_tree_pubkey_index, @@ -136,6 +137,8 @@ pub fn unpack_address_tree_info( #[cfg(test)] mod test { + use light_compressed_account::Pubkey; + use super::*; #[test] @@ -168,7 +171,7 @@ mod test { #[test] fn test_pack_merkle_contexts() { let mut remaining_accounts = PackedAccounts::default(); - + use light_compressed_account::Pubkey; let merkle_contexts = &[ MerkleContext { merkle_tree_pubkey: Pubkey::new_unique(), @@ -223,6 +226,7 @@ mod test { #[test] fn test_pack_address_tree_info() { + use solana_pubkey::Pubkey; let mut remaining_accounts = PackedAccounts::default(); let address_tree_info = AddressTreeInfo { @@ -245,7 +249,7 @@ mod test { #[test] fn test_pack_address_tree_infos() { let mut remaining_accounts = PackedAccounts::default(); - + use solana_pubkey::Pubkey; let address_tree_infos = [ AddressTreeInfo { address_merkle_tree_pubkey: Pubkey::new_unique(), diff --git a/sdk-libs/sdk/src/lib.rs b/sdk-libs/sdk/src/lib.rs index ac893d4f37..bdf746d760 100644 --- a/sdk-libs/sdk/src/lib.rs +++ b/sdk-libs/sdk/src/lib.rs @@ -16,11 +16,10 @@ use anchor_lang::{AnchorDeserialize, AnchorSerialize}; #[cfg(not(feature = "anchor"))] use borsh::{BorshDeserialize as AnchorDeserialize, BorshSerialize as AnchorSerialize}; pub use light_account_checks::{discriminator::Discriminator as LightDiscriminator, *}; +use light_compressed_account::instruction_data::compressed_proof::CompressedProof; pub use light_compressed_account::{self, instruction_data::data::*}; pub use light_hasher::*; pub use light_sdk_macros::*; -pub use light_verifier as verifier; -use light_verifier::CompressedProof; use solana_account_info::AccountInfo; use solana_cpi::invoke_signed; use solana_instruction::{AccountMeta, Instruction}; From 2f88073ced4ce9a68dc0dd8b1238b9607416876d Mon Sep 17 00:00:00 2001 From: ananas-block Date: Wed, 11 Jun 2025 17:07:46 +0100 Subject: [PATCH 3/4] fix: pr feedback --- program-libs/account-checks/src/account_info/pinocchio.rs | 2 -- program-libs/account-checks/src/checks.rs | 1 - 2 files changed, 3 deletions(-) diff --git a/program-libs/account-checks/src/account_info/pinocchio.rs b/program-libs/account-checks/src/account_info/pinocchio.rs index 9474b3b205..99c9c8d7a5 100644 --- a/program-libs/account-checks/src/account_info/pinocchio.rs +++ b/program-libs/account-checks/src/account_info/pinocchio.rs @@ -50,7 +50,6 @@ impl AccountInfoTrait for pinocchio::account_info::AccountInfo { (pubkey, bump) } // Pinocchio does not support find_program_address outside of target_os solana. - // That is annoying for rust unit tests. #[cfg(all(not(target_os = "solana"), feature = "solana"))] { let program_pubkey = solana_pubkey::Pubkey::from(*_program_id); @@ -75,7 +74,6 @@ impl AccountInfoTrait for pinocchio::account_info::AccountInfo { .map_err(|_| AccountError::InvalidSeeds) } // Pinocchio does not support find_program_address outside of target_os solana. - // That is annoying for rust unit tests. #[cfg(all(not(target_os = "solana"), feature = "solana"))] { let program_pubkey = solana_pubkey::Pubkey::from(*_program_id); diff --git a/program-libs/account-checks/src/checks.rs b/program-libs/account-checks/src/checks.rs index e89cdb99f8..f5aff8d5de 100644 --- a/program-libs/account-checks/src/checks.rs +++ b/program-libs/account-checks/src/checks.rs @@ -90,7 +90,6 @@ pub fn check_discriminator(bytes: &[u8]) -> Result<(), Account } /// Checks that the account balance is greater or eqal to rent exemption. -#[cfg(any(feature = "pinocchio", feature = "solana"))] pub fn check_account_balance_is_rent_exempt( account_info: &A, expected_size: usize, From ab195786abba086f09606f57267dc0d56074b8bb Mon Sep 17 00:00:00 2001 From: ananas-block Date: Wed, 11 Jun 2025 19:36:24 +0100 Subject: [PATCH 4/4] fix: preserve error information in pinocchio ProgramError conversion --- .../src/account_info/pinocchio.rs | 2 +- program-libs/account-checks/src/error.rs | 29 +++++++++++++++++-- .../tests/merkle_tree_tests.rs | 2 +- program-tests/utils/src/e2e_test_env.rs | 2 +- program-tests/utils/src/system_program.rs | 2 +- .../compressed-token/src/process_transfer.rs | 2 +- 6 files changed, 32 insertions(+), 7 deletions(-) diff --git a/program-libs/account-checks/src/account_info/pinocchio.rs b/program-libs/account-checks/src/account_info/pinocchio.rs index 99c9c8d7a5..190e03c77d 100644 --- a/program-libs/account-checks/src/account_info/pinocchio.rs +++ b/program-libs/account-checks/src/account_info/pinocchio.rs @@ -73,7 +73,7 @@ impl AccountInfoTrait for pinocchio::account_info::AccountInfo { pinocchio::pubkey::create_program_address(_seeds, &program_pubkey) .map_err(|_| AccountError::InvalidSeeds) } - // Pinocchio does not support find_program_address outside of target_os solana. + // Pinocchio does not support create_program_address outside of target_os solana. #[cfg(all(not(target_os = "solana"), feature = "solana"))] { let program_pubkey = solana_pubkey::Pubkey::from(*_program_id); diff --git a/program-libs/account-checks/src/error.rs b/program-libs/account-checks/src/error.rs index 35e4a5061a..82b2fe0fc2 100644 --- a/program-libs/account-checks/src/error.rs +++ b/program-libs/account-checks/src/error.rs @@ -30,6 +30,8 @@ pub enum AccountError { ProgramNotExecutable, #[error("Account not zeroed.")] AccountNotZeroed, + #[error("Pinocchio program error with code: {0}")] + PinocchioProgramError(u32), } // TODO: reconfigure error codes @@ -50,6 +52,7 @@ impl From for u32 { AccountError::InvalidProgramId => 12017, AccountError::ProgramNotExecutable => 12018, AccountError::AccountNotZeroed => 12019, + AccountError::PinocchioProgramError(code) => code, } } } @@ -70,8 +73,30 @@ impl From for solana_program_error::ProgramError { #[cfg(feature = "pinocchio")] impl From for AccountError { - fn from(_: pinocchio::program_error::ProgramError) -> Self { - AccountError::BorrowAccountDataFailed + fn from(error: pinocchio::program_error::ProgramError) -> Self { + match error { + pinocchio::program_error::ProgramError::Custom(code) => { + AccountError::PinocchioProgramError(code) + } + _ => { + // Convert other ProgramError variants to error codes + let error_code = match error { + pinocchio::program_error::ProgramError::InvalidArgument => 1, + pinocchio::program_error::ProgramError::InvalidInstructionData => 2, + pinocchio::program_error::ProgramError::InvalidAccountData => 3, + pinocchio::program_error::ProgramError::AccountDataTooSmall => 4, + pinocchio::program_error::ProgramError::InsufficientFunds => 5, + pinocchio::program_error::ProgramError::IncorrectProgramId => 6, + pinocchio::program_error::ProgramError::MissingRequiredSignature => 7, + pinocchio::program_error::ProgramError::AccountAlreadyInitialized => 8, + pinocchio::program_error::ProgramError::UninitializedAccount => 9, + pinocchio::program_error::ProgramError::NotEnoughAccountKeys => 10, + pinocchio::program_error::ProgramError::AccountBorrowFailed => 11, + _ => 0, // Unknown error + }; + AccountError::PinocchioProgramError(error_code) + } + } } } diff --git a/program-tests/account-compression-test/tests/merkle_tree_tests.rs b/program-tests/account-compression-test/tests/merkle_tree_tests.rs index 386d223b87..13c6b09a5b 100644 --- a/program-tests/account-compression-test/tests/merkle_tree_tests.rs +++ b/program-tests/account-compression-test/tests/merkle_tree_tests.rs @@ -1407,7 +1407,7 @@ async fn insert_into_nullifier_queues( .iter() .map(|(pubkey, index)| (*pubkey, *index)) .collect::>(); - remaining_accounts.sort_by(|a, b| a.1.cmp(&b.1)); + remaining_accounts.sort_by_key(|(_, idx)| *idx); let remaining_accounts = remaining_accounts .iter() .map(|(pubkey, _)| AccountMeta::new(*pubkey, false)) diff --git a/program-tests/utils/src/e2e_test_env.rs b/program-tests/utils/src/e2e_test_env.rs index a853e2afbf..9a5f62ca06 100644 --- a/program-tests/utils/src/e2e_test_env.rs +++ b/program-tests/utils/src/e2e_test_env.rs @@ -3399,7 +3399,7 @@ pub fn to_account_metas_light( }) .collect::>(); // hash maps are not sorted so we need to sort manually and collect into a vector again - remaining_accounts.sort_by(|a, b| a.1.cmp(&b.1)); + remaining_accounts.sort_by_key(|(_, idx)| *idx); let remaining_accounts = remaining_accounts .iter() .map(|(k, _)| k.clone()) diff --git a/program-tests/utils/src/system_program.rs b/program-tests/utils/src/system_program.rs index 40755d54dd..42fc4bece7 100644 --- a/program-tests/utils/src/system_program.rs +++ b/program-tests/utils/src/system_program.rs @@ -665,7 +665,7 @@ pub fn create_invoke_instruction_data_and_remaining_accounts( .map(|(k, i)| (AccountMeta::new(*k, false), *i)) .collect::>(); // hash maps are not sorted so we need to sort manually and collect into a vector again - remaining_accounts.sort_by(|a, b| a.1.cmp(&b.1)); + remaining_accounts.sort_by_key(|(_, idx)| *idx); let remaining_accounts = remaining_accounts .iter() .map(|(k, _)| k.clone()) diff --git a/programs/compressed-token/src/process_transfer.rs b/programs/compressed-token/src/process_transfer.rs index b5f7b32b95..e6f097b73c 100644 --- a/programs/compressed-token/src/process_transfer.rs +++ b/programs/compressed-token/src/process_transfer.rs @@ -1098,7 +1098,7 @@ pub mod transfer_sdk { }) .collect::>(); // hash maps are not sorted so we need to sort manually and collect into a vector again - remaining_accounts.sort_by(|a, b| a.1.cmp(&b.1)); + remaining_accounts.sort_by_key(|(_, idx)| *idx); let remaining_accounts = remaining_accounts .iter() .map(|(k, _)| k.clone())