Skip to content

Conversation

@ananas-block
Copy link
Contributor

@ananas-block ananas-block commented Jun 11, 2025

Issue:

  • We use pinocchio and solana crates interchangeably guarded by features in crates for Pubkey, AccountInfo and other types. This approach can cause compilation issues for example when crate light-compressed-account is used with pinocchio features in a program its tests use light-program-test which depends on light-compressed-account with solana features.
  • The issue exits in:
    1. light-account-checks
    2. light-batched-merkle-tree
    3. light-compressed-account
  • to a lesser extend error conversion in other crates has the potential to break compilation as well

Solution

  • ensure that every light- crate can be compiled with all-targets
    1. remove exclusive feature patterns eg all(not(feature = "pinocchio"), feature = "solana")
    2. replace use of solana or pinocchio Pubkey in light-compressed-account with local Pubkey type
    3. introduce AccountInfoTrait and implement it for pinocchio and solana-* AccountInfo
    4. use AccountInfoTrait in light-accounts-checks and light-batched-merkle-tree
    5. add sysvar Rent as associated constant to AccountInfoTrait

Summary by CodeRabbit

  • New Features

    • Introduced a generic account info trait, enabling unified account handling across different environments.
    • Added utility functions and modules for packing and indexing account-related data structures.
    • Added new procedural macro for base58 public key arrays.
  • Refactor

    • Standardized type conversions for public keys and owner fields throughout the codebase using .into() and byte-level comparisons.
    • Generalized account info handling in libraries and tests to use trait-based abstractions.
    • Simplified and unified error conversions, logging macros, and conditional compilation for Solana and Pinocchio environments.
    • Streamlined struct initialization and test setup for clarity and consistency.
    • Reorganized imports and removed redundant local variables for cleaner code.
  • Bug Fixes

    • Improved public key comparison logic by consistently comparing byte arrays where necessary.
    • Enhanced test coverage by enabling feature-gated test modules and expanding test cases for account validation.
  • Chores

    • Updated and reorganized Cargo feature flags and dependencies for improved modularity and reduced default features.
    • Improved documentation formatting and code comments for clarity.

@ananas-block ananas-block force-pushed the jorrit/chore-improve-crate-feature-robustness branch from 15cdd80 to fd19acc Compare June 11, 2025 03:35
@ananas-block ananas-block marked this pull request as ready for review June 11, 2025 03:50
@ananas-block ananas-block force-pushed the jorrit/chore-improve-crate-feature-robustness branch from fd19acc to 3afda7b Compare June 11, 2025 04:13
@ananas-block
Copy link
Contributor Author

This pr should be merged with rebase and merge intead of squash in merge to persist the commits!

@ananas-block ananas-block force-pushed the jorrit/chore-improve-crate-feature-robustness branch from 3afda7b to 7f94448 Compare June 11, 2025 04:28
@ananas-block ananas-block marked this pull request as draft June 11, 2025 05:25
@ananas-block
Copy link
Contributor Author

consider to move AccountInfoTrait into a separate crate

/// 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"))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason why we use conditional compilation explicitly here but not for the other functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch its a letftover

use pinocchio::sysvars::{clock::Clock, Sysvar};
self.rolledover_slot = Clock::get().unwrap().slot;
}
#[cfg(not(feature = "pinocchio"))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as?

Suggested change
#[cfg(not(feature = "pinocchio"))]
#[cfg(feature = "solana")]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case we need this condition else if we compile with all features we get an import conflict because we are importing this twice `use pinocchio::sysvars::{clock::Clock, Sysvar};' and we only need it once.

(pubkey, bump)
}
// Pinocchio does not support find_program_address outside of target_os solana.
// That is annoying for rust unit tests.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// That is annoying for rust unit tests.

@ananas-block ananas-block marked this pull request as ready for review June 11, 2025 16:45
Copy link
Contributor

@SwenSchaeferjohann SwenSchaeferjohann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 11, 2025

Walkthrough

This update introduces a comprehensive abstraction layer for account information handling in the account-checks library, enabling seamless interoperability between Solana and Pinocchio backends. The change centers around a new AccountInfoTrait, with concrete implementations for both Solana and Pinocchio account types. All account validation and Merkle tree-related functions are refactored to use this trait, replacing direct type usage. The update also includes extensive new tests for trait correctness and account validation, removes backend-specific conditional logic, and standardizes key conversions and error handling across the codebase. Supporting macros and utilities are added or updated to facilitate these abstractions.

Changes

File(s) / Group Change Summary
program-libs/account-checks/src/account_info/account_info_trait.rs Introduces AccountInfoTrait abstraction for account info handling.
program-libs/account-checks/src/account_info/mod.rs, program-libs/account-checks/src/account_info/pinocchio.rs, program-libs/account-checks/src/account_info/solana.rs Adds module organization and trait implementations for Solana and Pinocchio backends.
program-libs/account-checks/src/checks.rs Refactors all account validation functions to use AccountInfoTrait and [u8; 32] for program IDs; removes backend-specific logic and test module.
program-libs/account-checks/src/lib.rs Removes old modules, adds and re-exports new account_info module and AccountInfoTrait.
program-libs/account-checks/src/error.rs Splits error conversions by backend, adds conversions for borrow errors.
program-libs/account-checks/tests/account_info.rs, program-libs/account-checks/tests/tests.rs Adds comprehensive tests for trait implementations and account validation logic.
program-libs/batched-merkle-tree/src/*, program-libs/compressed-account/src/* Refactors all Merkle tree and account info functions to use generic AccountInfoTrait instead of concrete types; updates key conversions and logging.
program-libs/macros/src/lib.rs, program-libs/macros/src/pubkey.rs Adds pubkey_array macro and supporting logic for byte array public key constants.
program-libs/hasher/src/errors.rs, program-libs/merkle-tree-metadata/src/errors.rs, program-libs/bloom-filter/src/lib.rs, program-libs/concurrent-merkle-tree/src/errors.rs, program-libs/verifier/src/lib.rs, program-libs/indexed-merkle-tree/src/errors.rs Refines conditional compilation for error conversions, splitting by backend features.
program-libs/hasher/src/lib.rs, program-libs/merkle-tree-metadata/src/lib.rs Removes backend-specific imports and conditional logic.
program-libs/compressed-account/src/pubkey.rs Adds conversions, trait renaming, and interoperability for Pubkey types.
program-libs/macros/src/lib.rs Adds procedural macro for [u8; 32] pubkey arrays.
program-libs/account-checks/Cargo.toml, program-libs/compressed-account/Cargo.toml, program-libs/hasher/Cargo.toml, program-libs/merkle-tree-metadata/Cargo.toml, program-libs/verifier/Cargo.toml, program-libs/batched-merkle-tree/Cargo.toml, program-libs/concurrent-merkle-tree/Cargo.toml Updates feature flags, dependencies, and default features for backend flexibility.
program-tests/utils/src/pack.rs, program-tests/utils/src/lib.rs, program-tests/utils/src/e2e_test_env.rs Adds and updates utilities for packing account data and handling key conversions.
Many test files, examples, and program modules Updates usage to new trait-based APIs, standardizes key conversions, and removes backend-specific logic.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AccountInfo (Solana/Pinocchio)
    participant AccountInfoTrait
    participant ValidationFn
    participant ErrorType

    User->>AccountInfo: Provides account info (backend-specific)
    AccountInfo->>AccountInfoTrait: Uses trait interface
    AccountInfoTrait->>ValidationFn: Calls validation/check function
    ValidationFn->>AccountInfoTrait: Accesses metadata via trait methods
    ValidationFn->>ErrorType: Returns unified error on failure
    ValidationFn-->>User: Returns success or error
Loading

Poem

🐇
A trait for every account,
No backend left to flounder—
Solana or Pinocchio,
Now both can play together.
With tests and macros fresh and neat,
Our keys and checks are now complete!
Hop, hop, the code is fleet!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

🔭 Outside diff range comments (9)
programs/system/src/lib.rs (1)

24-34: ⚠️ Potential issue

pubkey_array! returns [u8; 32] – current ID definition does not compile

pub const ID: Pubkey = pubkey_array!(...) assigns a plain byte-array to a Pubkey.
pinocchio::pubkey::Pubkey does not have a const From<[u8;32]> impl, so this will fail at compile-time.

- pub const ID: Pubkey = pubkey_array!("SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7");
+ pub const ID: Pubkey =
+     Pubkey::new_from_array(pubkey_array!("SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7"));

This keeps ID a Pubkey, matches the rest of the program API, and remains a const.
Without this fix the crate will not build.

program-tests/sdk-test/src/create_pda.rs (1)

40-46: ⚠️ Potential issue

unwrap() in on-chain context can abort the program

Using unwrap() will panic if hashv_to_bn254_field_size_be_const_array ever returns an error, immediately aborting the transaction.
Propagate the error instead:

-        let address_seed = hashv_to_bn254_field_size_be_const_array::<3>(&[
-            b"compressed",
-            instruction_data.data.as_slice(),
-        ])
-        .unwrap();
+        let address_seed = hashv_to_bn254_field_size_be_const_array::<3>(&[
+            b"compressed",
+            instruction_data.data.as_slice(),
+        ])
+        .map_err(|_| LightSdkError::HashToFieldSize)?;

This keeps the program fail-safe and avoids unintended panics.

program-libs/compressed-account/src/indexer_event/parse.rs (1)

633-640: 🛠️ Refactor suggestion

Quadratic walk over accounts – switch to a HashMap lookup

For every sequence number we iterate over every input account, leading to O(n*m) behaviour.
Batch transactions with hundreds of inputs/outputs will pay for this-again CPU-wise in the indexer.

-    internal_input_sequence_numbers.iter_mut().for_each(|seq| {
-        for (i, merkle_tree_pubkey) in input_merkle_tree_pubkeys.iter().enumerate() {
-            if *merkle_tree_pubkey == seq.tree_pubkey {
-                nullifier_queue_indices[i] = seq.seq.into();
-                seq.seq += 1;
-            }
-        }
-    });
+    let mut map: std::collections::HashMap<Pubkey, &mut u64> =
+        internal_input_sequence_numbers.iter_mut().map(|s| (s.tree_pubkey, &mut s.seq)).collect();
+    for (idx, tree) in input_merkle_tree_pubkeys.iter().enumerate() {
+        if let Some(seq) = map.get_mut(tree) {
+            nullifier_queue_indices[idx] = (**seq).into();
+            **seq += 1;
+        }
+    }

Same applies to create_address_queue_indices.

This drops the complexity to linear time and allocates only a small additional map.

program-tests/system-cpi-test/src/create_pda.rs (1)

492-506: ⚠️ Potential issue

unwrap() will abort the on-chain program – propagate the error instead

Both the Poseidon hash and legacy address derivation can fail; unwrap() converts that into an unrecoverable panic which will consume all compute units and return a generic error to the caller.

-        data_hash: timelock_compressed_pda.hash::<Poseidon>().unwrap(),
+        data_hash: timelock_compressed_pda
+            .hash::<Poseidon>()
+            .map_err(|e| anchor_lang::error::Error::from(e))?,
@@
-        )
-        .unwrap(),
+        )?,

Define a dedicated ErrorCode::HashFailed / ErrorCode::AddressDerivationFailed if you need something more descriptive.

Failing gracefully keeps the program deterministic and makes debugging far easier.

program-libs/merkle-tree-metadata/src/rollover.rs (1)

105-118: ⚠️ Potential issue

Unchecked pow may overflow for tall trees

(rollover_fee * rollover_threshold * (2u64.pow(height))) silently wraps on u64 overflow (e.g. height >= 64).
Consider u128 math or checked_pow/checked_mul to detect impossible configurations instead of producing undefined economics.

forester/tests/batched_state_async_indexer_test.rs (1)

857-862: ⚠️ Potential issue

tree_type hard-coded to StateV2 even in the V1 branch

Inside transfer::<false,…> the merkle_contexts you build still use

tree_type: TreeType::StateV2,

leading to inconsistent proofs and root look-ups for V1 trees.

- tree_type: TreeType::StateV2,
+ tree_type: if V2 { TreeType::StateV2 } else { TreeType::StateV1 },

Failing to fix this will surface as “root not found” or mismatched-hash errors once V1 accounts are processed.

program-libs/verifier/src/lib.rs (1)

42-47: ⚠️ Potential issue

Use correct Solana ProgramError path

solana_program_error::ProgramError is not re-exported by the canonical Solana SDK; the type lives under solana_program::program_error::ProgramError.
Unless you have a bespoke crate named solana_program_error, this will not compile once the solana feature is enabled.

-impl From<VerifierError> for solana_program_error::ProgramError {
+use solana_program::program_error::ProgramError;
+
+impl From<VerifierError> for ProgramError {
     fn from(e: VerifierError) -> Self {
-        solana_program_error::ProgramError::Custom(e.into())
+        ProgramError::Custom(e.into())
     }
 }
programs/compressed-token/src/process_transfer.rs (2)

190-201: 🛠️ Refactor suggestion

Generic slice of impl AsPubkey is brittle

Using &[impl AsPubkey] for pubkeys/amounts creates a monomorphic slice tied to one concrete type.
If the caller mixes different AsPubkey impls (e.g. Pubkey and [u8;32]) the code won’t compile, defeating the purpose of this abstraction.

-pub fn create_output_compressed_accounts(
-    output_compressed_accounts: &mut [OutputCompressedAccountWithPackedContext],
-    mint_pubkey: impl AsPubkey,
-    pubkeys: &[impl AsPubkey],
+pub fn create_output_compressed_accounts<P, O>(
+    output_compressed_accounts: &mut [OutputCompressedAccountWithPackedContext],
+    mint_pubkey: P,
+    pubkeys: &[O],
 ) -> Result<u64>
 where
+    P: AsPubkey,
+    O: AsPubkey,

A regular generic parameter keeps the API flexible and avoids monomorph-code bloat when the same function is called with many concrete types.


150-165: ⚠️ Potential issue

Unsafe overflow on lamport change calculation

change_lamports = input_lamports - output_lamports; can underflow if the outputs exceed the inputs, causing a panic in release builds (checked subtraction is removed).
Use checked_sub and return a domain-specific error instead:

-    let change_lamports = input_lamports - output_lamports;
+    let change_lamports = input_lamports
+        .checked_sub(output_lamports)
+        .ok_or(ErrorCode::ComputeOutputLamportsFailed)?;
♻️ Duplicate comments (2)
program-libs/batched-merkle-tree/src/batch.rs (2)

188-192: Same logging duplication comment as above

When you refactor, remember to update this block to the wrapper macro too.


204-208: Third occurrence – candidate for macro consolidation

🧹 Nitpick comments (59)
program-libs/hasher/src/hash_to_field_size.rs (1)

142-176: Gating tests on solana looks good, but 10 000 iterations is overkill

Switching from #[cfg(not(feature = "pinocchio"))] to #[cfg(feature = "solana")] removes the mutual-exclusion problem – nice.

Minor nit: each test still hashes 10 000 random keys. On CI this costs ~200 ms per test on a fast machine; multiplied across crates it adds up. Consider trimming to 1 000 unless you specifically need that statistical confidence.

-        for _ in 0..10_000 {
+        for _ in 0..1_000 {
program-libs/account-checks/Cargo.toml (1)

32-36: Dev-dependencies force Solana + Pinocchio even when features are off

pinocchio and solana-pubkey are unconditional in [dev-dependencies], so cargo test will always compile both backends, defeating the purpose of mutually-exclusive features during CI size checks.
Consider gating them:

[dev-dependencies]
pinocchio = { workspace = true, optional = true }
solana-pubkey = { workspace = true, optional = true, features = ["curve25519","sha2"] }

[features]
test-solana = ["dep:solana-pubkey"]
test-pinocchio = ["dep:pinocchio"]

This keeps tests flexible without imposing both heavy deps every run.

examples/anchor/token-escrow/Cargo.toml (1)

31-34: Duplicate light-test-utils entries may confuse Cargo feature resolution

The crate is declared both in the target-specific section and again in [dev-dependencies] (lines 38–39). Cargo merges them, but the duplicated specification can become a maintenance foot-gun when versions/features diverge.

If both clauses need identical features you can drop the [dev-dependencies] entry – tests still inherit the target-specific dependency.

programs/account-compression/src/instructions/resize_registered_program_account.rs (1)

42-46: Avoid extra allocation by borrowing the program ID bytes directly

Pubkey::to_bytes() allocates a new [u8;32] each call.
Pubkey already implements AsRef<[u8]>, so you can pass a borrowed slice without copying:

-        light_account_checks::checks::check_owner(
-            &crate::ID.to_bytes(),
-            &ctx.accounts.registered_program_pda,
-        )
+        light_account_checks::checks::check_owner(
+            crate::ID.as_ref(),
+            &ctx.accounts.registered_program_pda,
+        )

This is cheaper and reads a bit cleaner.

programs/compressed-token/src/freeze.rs (2)

185-189: Minor perf / clarity nit – avoid repeated .into() inside the loop

crate::ID.into() is executed for every iteration. Cache once:

-        output_compressed_accounts[i] = OutputCompressedAccountWithPackedContext {
-            compressed_account: CompressedAccount {
-                owner: crate::ID.into(),
+        let program_owner: [u8; 32] = crate::ID.into();
+        output_compressed_accounts[i] = OutputCompressedAccountWithPackedContext {
+            compressed_account: CompressedAccount {
+                owner: program_owner,

Pure micro-optimisation; feel free to ignore if size-optimised build is not a concern.


524-527: Same .into() duplication in test helper – consider applying the same caching trick here to keep test code consistent.

program-tests/create-address-test-program/src/create_pda.rs (1)

118-120: Redundant conversion

crate::ID is already the program id. If owner expects [u8;32], convert once outside the struct literal to improve readability (same suggestion as in freeze.rs).

examples/anchor/counter/tests/test.rs (1)

52-68: Heavy repetition – consider a helper to fetch & decode the counter

Every verification block repeats the same three steps:
get_compressed_account → unwrap → CounterAccount::deserialize.
Extracting this into a small helper (e.g. fetch_counter_value(&rpc, address) -> Result<(CompressedAccount,u64)>) would:

  • remove ~25 duplicated lines,
  • consolidate the unwrap() panic into a single ?,
  • make the intent of each test section clearer.

Purely optional but improves readability/maintenance.

Also applies to: 74-86, 88-104

programs/system/src/context.rs (1)

358-365: Minor: avoid extra copy by matching input branch

See comment above – align the owner assignment once the expected return type is confirmed.

program-tests/utils/src/assert_token_tx.rs (1)

167-172: Prefer comparing Pubkeys directly for stronger type-safety

Both operands are converted to raw bytes before the equality check.
Instead, keep the comparison at the Pubkey level and convert the constant once.
This avoids repeated allocations/copies and keeps the compiler on your side if either side’s type ever changes again.

-assert_eq!(
-    transfer_recipient_compressed_account
-        .compressed_account
-        .owner
-        .to_bytes(),
-    light_compressed_token::ID.to_bytes()
-);
+assert_eq!(
+    transfer_recipient_compressed_account
+        .compressed_account
+        .owner,
+    light_compressed_token::ID.into()   // `From<[u8;32]> for Pubkey` impl
+);
program-libs/macros/src/lib.rs (1)

18-25: Add doc-tests for the new pubkey_array! macro

The macro implementation mirrors pubkey!, but there is no usage example or compile-time doctest yet.
Including a minimal doctest ensures the macro continues to expand correctly and signals intent to downstream users.

 /// Converts a base58 encoded public key into a raw byte array [u8; 32].
 #[proc_macro]
 pub fn pubkey_array(input: TokenStream) -> TokenStream {
@@
 }
+
+/// ```
+/// use light_macros::pubkey_array;
+///
+/// const KEY: [u8; 32] = pubkey_array!("11111111111111111111111111111111");
+/// assert_eq!(KEY.len(), 32);
+/// ```
examples/anchor/counter/src/lib.rs (1)

51-52: Minor duplication – consider a small helper

&crate::ID is repeated in every LightAccount::new_* call. A tiny wrapper (e.g. const PROGRAM_ID: &Pubkey = &crate::ID;) or a local let pid = &crate::ID; would remove the repetition and future-proof refactors.

-        let mut counter = LightAccount::<'_, CounterAccount>::new_mut(
-            &crate::ID,
+        let pid = &crate::ID;
+        let mut counter = LightAccount::<'_, CounterAccount>::new_mut(
+            pid,

Purely cosmetic, feel free to skip.

Also applies to: 83-84, 118-119, 159-160, 198-199

program-tests/system-cpi-test/src/invalidate_not_owned_account.rs (2)

126-135: Validate .into() conversion for owner field

light_compressed_token::ID.into() changes the compile-time type of ID to whatever CompressedAccount.owner expects.
Please double-check that:

  1. ID is now [u8; 32] (per the new local-pubkey approach) and not a wrapper struct.
  2. Into is implemented without allocating or hashing, otherwise this runs in hot paths for every CPI test and will add avoidable overhead.

If the conversion is just From<[u8;32]>[u8;32], you can drop the call entirely and assign the constant directly.


612-617: Same concern for ID.into() inside write_into_cpi_account

For consistency and potential micro-optimisation, consider avoiding the redundant .into() here as well once the owner type and constant match.

program-tests/e2e-test/tests/test.rs (1)

100-107: Minor tidy-up possibility

Because the omitted fields already default to None, setting them explicitly is redundant.
No action required—just a note in case you prefer the terser form:

let general_config = GeneralActionConfig {
    ..GeneralActionConfig::default()
};
program-libs/batched-merkle-tree/src/batch.rs (1)

170-176: Logging macro now Solana-only – unify with a thin wrapper

You replaced the previous crate::msg! macro with solana_msg::msg! behind cfg(feature = "solana").
As a result, nothing is logged when building with pinocchio, which might hinder debugging.

Consider re-introducing a simple shim:

#[cfg(feature = "solana")]
macro_rules! log { ($($t:tt)*) => { solana_msg::msg!($($t)*) } }
#[cfg(not(feature = "solana"))]
macro_rules! log { ($($t:tt)*) => { /* no-op or eprintln! */ } }

and use log! everywhere. It removes the repeated cfg attributes and keeps parity across back-ends.

examples/anchor/token-escrow/src/escrow_with_compressed_pda/withdrawal.rs (1)

90-91: Minor: unnecessary .into() – keep the code symmetric

crate::ID is already a Pubkey; adding .into() is redundant and slightly obscures intent. Harmless, just consider reverting for consistency with the rest of the codebase.

Also applies to: 115-116

program-tests/utils/src/batched_address_tree.rs (1)

183-185: Byte-wise Pubkey comparison is fine but document the reason

Switching to .to_bytes() avoids potential trait‐implementation mismatches between different Pubkey types, but the magic constants ([0u8; 32]) are now less self-explanatory. Consider a short comment:

// Compare raw bytes because different `Pubkey` newtypes are used under
// Solana vs Pinocchio builds and they don't share `PartialEq`.

Also applies to: 196-198

program-libs/account-checks/src/account_info/mod.rs (1)

1-6: Module scaffold looks good

Straight-forward mod declarations with proper feature gates. Add a brief crate-level doc comment explaining the purpose of this module to aid newcomers.

program-tests/utils/src/spl.rs (2)

595-598: Avoid repeated .into() calls inside hot loops

Every changed slice builds a new Vec<Pubkey> by mapping [u8; 32]Pubkey with .into().
In performance-sensitive test runs this conversion is executed for every token in the vector and allocates new Pubkeys repeatedly.

If get_state_merkle_tree_accounts already accepts [u8; 32], let the collection stay as Vec<[u8; 32]> and move the conversion (if really necessary) once at the API boundary.
This drops one allocation + one From per element.

-    let input_merkle_tree_pubkeys: Vec<Pubkey> = input_merkle_tree_context
-        .iter()
-        .map(|x| x.merkle_tree_pubkey.into())
-        .collect();
+    let input_merkle_tree_pubkeys: Vec<[u8; 32]> =
+        input_merkle_tree_context.iter().map(|x| x.merkle_tree_pubkey).collect();

Same remark applies to all other changed blocks listed above.
(Not performance-critical in CI, but worth keeping the data model lean.)

Also applies to: 770-778, 1149-1155, 1323-1329, 1489-1495, 1781-1785


686-687: Minor API-use inconsistency

Here you switched to output_merkle_tree_pubkeys.as_slice() but a few lines below still pass &input_merkle_tree_pubkeys directly.
Pick one style (&vec or .as_slice()) for consistency.

program-libs/batched-merkle-tree/src/constants.rs (1)

3-4: Constant now raw bytes – audit downstream usages

Switching ACCOUNT_COMPRESSION_PROGRAM_ID from Pubkey to [u8; 32] reduces deps and compile time – nice.
However, every caller that expects a Pubkey must now wrap the array (Pubkey::new_from_array(id) or id.into()). Failure to do so yields silent type mismatches.

Search for the constant name and ensure all comparisons / assignments still compile and perform the same equality semantics.

Also applies to: 29-30

program-tests/sdk-test/tests/test.rs (1)

47-48: Typo in variable name

ouput_queue is missing the second “t”.

-    let ouput_queue = rpc.get_random_state_tree_info().queue;
+    let output_queue = rpc.get_random_state_tree_info().queue;
.github/workflows/rust.yml (1)

48-58: light-batched-merkle-tree is built three times

The matrix now compiles this crate in:

  1. concurrent-merkle-tree group (--features test-only)
  2. program-libs group (--all-features --test test_e2e)
  3. sdk-libs group (--features test-only --skip …)

Consider dropping one invocation to shave several minutes off CI runtime and avoid cache evictions.

program-tests/system-cpi-test/src/sdk.rs (1)

25-26: Two helper functions that do the same thing – consolidate

to_account_metas_light is introduced here while to_account_metas is still used lower in the file.
They both turn a HashMap<Pubkey, usize> into sorted AccountMetas, so having two flavours increases cognitive load and the chance of subtle divergence.

Consider exposing a single helper (e.g. the new *_light version) and using it consistently:

-    let remaining_accounts = to_account_metas_light(remaining_accounts);
+    let remaining_accounts = to_account_metas(remaining_accounts);

(or remove the old one altogether).

This keeps the SDK surface minimal and avoids future maintenance friction.

Also applies to: 116-116

program-libs/macros/src/pubkey.rs (1)

42-60: Duplicate decoding logic – small DRY opportunity

pubkey_array() repeats the exact decoding & length-check logic from pubkey().
Extract the common part into a helper (e.g. decode_pubkey_bytes(&LitStr) -> Result<[u8;32]>) to avoid divergence in error handling.

program-tests/utils/src/assert_compressed_tx.rs (2)

235-238: Minor: Avoid double .into() conversions inside hot assert loop

The predicate converts two [u8;32] values to Pubkey on every iteration:

*x == output_account.merkle_context.merkle_tree_pubkey.into()
    || *x == output_account.merkle_context.queue_pubkey.into()

Compute once and reuse to save two temporary Pubkey constructions per output account:

- 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()),);
+ let tree_pk: Pubkey = output_account.merkle_context.merkle_tree_pubkey.into();
+ let queue_pk: Pubkey = output_account.merkle_context.queue_pubkey.into();
+ assert!(output_merkle_tree_pubkeys.iter().any(|x| *x == tree_pk || *x == queue_pk));

Very small, but this loop can run thousands of times in big tests.


260-263: Readability: pull the converted key out of the iterator

Same comment as above – convert once, compare many.

program-libs/compressed-account/src/constants.rs (1)

1-8: Public-key constants now raw [u8;32] – consider companion Pubkey helpers

Many call-sites will now require ACCOUNT_COMPRESSION_PROGRAM_ID.into().
Providing a companion constant or const fn returning Pubkey avoids repetitive conversions and keeps type‐safety:

pub const ACCOUNT_COMPRESSION_PROGRAM_ID_BYTES: [u8;32] = pubkey_array!(...);
pub const ACCOUNT_COMPRESSION_PROGRAM_ID: Pubkey = Pubkey::new_from_array(ACCOUNT_COMPRESSION_PROGRAM_ID_BYTES);

Not mandatory, but improves ergonomics & micro-performance.

program-libs/merkle-tree-metadata/src/rollover.rs (1)

70-82: Duplicated Clock::get() branches can be collapsed

Both the pinocchio and the solana branches perform identical logic (import Clock, call Clock::get().unwrap().slot).
Collapsing the duplicate code behind a single use based on the feature flag will shorten the block and avoid accidental drift in the future.

-#[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(feature = "pinocchio")]
+use pinocchio::sysvars::{clock::Clock, Sysvar};
+#[cfg(not(feature = "pinocchio"))]
+use solana_sysvar::{clock::Clock, Sysvar};
+
+self.rolledover_slot = Clock::get().unwrap().slot;
forester/tests/batched_state_async_indexer_test.rs (1)

870-876: Minor: redundant .into() allocations

payer.pubkey().into() is executed for every loop iteration, yet payer.pubkey() is already Pubkey; converting for every transfer adds avoidable copies.
Cache the converted key once outside the loop if the destination type differs, or store Pubkey directly in CompressedAccount.

program-tests/utils/src/assert_rollover.rs (1)

145-151: Inconsistent key comparison style

Above you switched to byte–wise comparison (to_bytes()) for associated_merkle_tree, but here you compare the raw structs:

assert_eq!(
    old_queue_metadata.next_queue,
    light_compressed_account::Pubkey::from(*new_queue_pubkey)
);

For consistency and easier diffing, prefer the same to_bytes() approach or use .eq() everywhere.

program-libs/batched-merkle-tree/src/rollover_address_tree.rs (1)

31-32: Unnecessary .into() on new_account.key()

new_account.key() already returns the Light-format Pubkey; converting it again is redundant and may allocate.

- new_account.key().into(),
+ new_account.key(),
program-libs/verifier/src/lib.rs (2)

221-226: target_os = "solana" gating makes local tests silent

The extra target_os = "solana" filter means the msg! logs are stripped from
off-chain tests (cargo test --features solana).
If the intention is to see those diagnostics during unit / integration tests, gate only on feature = "solana".


276-297: On-chain debug spam risks exceeding compute budget

Dumping full public inputs and proof elements every time verification fails
will inflate the log buffer and consume BPF compute units.
Consider limiting the log size (e.g. first N bytes) or guard with an additional
debug_assert!() / cfg!(debug_assertions).

program-tests/utils/src/system_program.rs (2)

57-61: Avoid repeated .into() inside tight loops

derive_address_legacy(&address_merkle_tree_pubkeys[i].into(), …) allocates a
new wrapper on every iteration. Convert once outside the loop to avoid needless
copies:

-for (i, address_seed) in address_seeds.iter().enumerate() {
-    let derived_address =
-        derive_address_legacy(&address_merkle_tree_pubkeys[i].into(), address_seed).unwrap();
+for (i, address_seed) in address_seeds.iter().enumerate() {
+    let tree: light_compressed_account::Pubkey = address_merkle_tree_pubkeys[i].into();
+    let derived_address = derive_address_legacy(&tree, address_seed).unwrap();
     derived_addresses.push(derived_address);
 }

569-610: Unnecessary .into() churn when populating remaining_accounts

merkle_tree_pubkey.into() / queue_pubkey.into() is called multiple times
for the same keys, causing duplicate conversions and extra HashMap look-ups.
Store the converted value in a local before using it in get/insert.

This also prevents accidental mismatches should Into perform non-idempotent
transformations (unlikely but safer).

program-tests/system-test/tests/test.rs (3)

252-267: Silencing Clippy instead of fixing the loop hides an easy improvement

#[allow(clippy::needless_range_loop)] suppresses a lint that is correct here – the manual index loop can be replaced by an iterator, improving readability and reducing the chance of off-by-one errors:

-#[allow(clippy::needless_range_loop)]
-for i in 0..num_outputs {
-    ...
-}
+for (i, output_account) in output_compressed_accounts.iter_mut().enumerate().take(num_outputs) {
+    if output_compressed_accounts_with_address && i < num_addresses {
+        output_account.address = Some(derived_addresses[i]);
+    }
+}

If the range loop is truly necessary (e.g. for i arithmetic), document the reason instead of globally muting the lint.


260-265: Repeated Pubkey → Wrapper conversions – cache once

The pattern owner: <pubkey>.into() is repeated dozens of times. Each call performs a conversion that is cheap but clutters the code and can become error-prone if the wrapper type changes.

Extract once per scope:

let payer_owner = payer_pubkey.into();
...
CompressedAccount {
    lamports: 0,
    owner: payer_owner,
    ...
}

This improves readability and avoids accidental mismatches (e.g. mixing payer.pubkey() and payer_pubkey).

Also applies to: 894-899, 943-949, 978-984, 1111-1117, 1470-1476, 1572-1577, 1856-1862


563-569: Passing references to temporaries created by .into()

derive_address_legacy(&env.v1_address_trees[0].merkle_tree.into(), address_seed) takes a reference to a value returned by .into().
While this compiles (the temporary lives for the duration of the call), it is easy to misuse and obscures the lifetime. Allocate the converted value once and pass a reference to the binding:

let address_tree: _ = env.v1_address_trees[0].merkle_tree.into();
let derived_address = derive_address_legacy(&address_tree, address_seed).unwrap();

The intent becomes explicit and avoids accidental dangling-reference bugs if the function signature ever changes.

program-tests/system-cpi-v2-test/tests/invoke_cpi_with_read_only.rs (2)

720-733: Legacy helper signatures diverged – test helper still compiles but hides a panic-path

derive_address_legacy(&address_tree.into(), &seed).unwrap()

derive_address_legacy previously returned Pubkey, now it returns Result<Pubkey, _> and is always unwrapped in test-code.
If the refactor ever changes the internal validation (e.g. rejects mixed back-ends) these tests will start panicking instead of failing gracefully.

Recommend replacing unconditional unwrap() with expect("derive_address_legacy failed") or a proper Result propagation so test output is meaningful.


2921-2923: Avoid double allocation in map(|x| x.merkle_tree.into())

Inside a tight loop this conversion is called for every output account.
If into() produces a copy it is fine, otherwise we are allocating a new value for every iteration when a simple clone() (or keeping a reference) would be cheaper.

-            .map(|x| x.merkle_tree.into())
+            .map(|x| x.merkle_tree) // avoid extra Into if both types are identical

Run cargo bloat --tests --release to confirm allocations are not regressed.

examples/anchor/token-escrow/tests/test_compressed_pda.rs (1)

211-213: Minor readability hit from chained .into() calls

The extra .into() casts on every *_pubkey field make the statement noise-heavy and add no functional value once the local Pubkey becomes the canonical type.

-    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_pubkey: env.v1_address_trees[0].merkle_tree,
+    address_queue_pubkey:       env.v1_address_trees[0].queue,

Same applies to the two MerkleContext literals below (lines 225-227 & 413-422).

Not a blocker but worth considering.

Also applies to: 225-227, 413-422

program-libs/compressed-account/src/instruction_data/zero_copy.rs (4)

124-126: Returning Pubkey by value copies 32 bytes each call

owner() now returns the Pubkey by value instead of by reference, introducing an unnecessary 32-byte copy every time the trait is used.

Unless the caller needs ownership, prefer &Pubkey for zero-cost access:

-fn owner(&self) -> Pubkey {
-    self.compressed_account.owner
-}
+fn owner(&self) -> &Pubkey {
+    &self.compressed_account.owner
+}

Mirrors the InputAccount::owner signature further below and keeps the API consistent.


276-279: Dropped .into() is correct but document the invariance

Assigning owner: compressed_account.owner assumes both structs use the same Pubkey concrete type after the refactor.
Add a short comment so future maintainers know no additional conversion is required.

// Same `Pubkey` concrete type – direct copy is fine.
owner: compressed_account.owner,

1403-1405: Avoid cloning when comparing pubkeys in tests

reference.owner.to_bytes() allocates a fresh array each time; as_bytes() on both sides is allocation-free:

-if reference.owner.to_bytes() != z_copy.owner.as_bytes() {
+if reference.owner.as_bytes() != z_copy.owner.as_bytes() {

Tiny win but free.


460-470: Duplicate logic – factor out helper for owner()

Both ZInstructionDataInvoke and ZInstructionDataInvokeCpi implement identical owner() bodies.
Extracting a small utility (or a blanket default method in the trait) removes duplication and future drift.

Not blocking this PR but worth tracking.

Also applies to: 535-547

program-tests/utils/src/create_address_test_program_sdk.rs (1)

33-37: HashMap ordering may cause non-deterministic meta ordering

Transaction AccountMeta order must be deterministic for replay protection.
Because HashMap iteration order is random, the order in which keys reach to_account_metas_light depends on the map’s internal hash order. If that helper does not sort internally, signatures could differ run-to-run.

-use std::collections::HashMap;
+use std::collections::BTreeMap;
 ...
-let mut remaining_accounts = HashMap::<light_compressed_account::Pubkey, usize>::new();
+let mut remaining_accounts = BTreeMap::<light_compressed_account::Pubkey, usize>::new();

A BTreeMap (or explicit sort before serialisation) guarantees stable ordering while keeping code size minimal.

programs/compressed-token/src/process_mint.rs (1)

40-45: Generic slice over impl AsPubkey can balloon monomorphisation

&[impl AsPubkey] creates a new monomorphised version of process_mint_to_or_compress for every concrete type array it is called with.
Unless you rely on multiple distinct key types, a single generic parameter avoids extra codegen:

-pub fn process_mint_to_or_compress<'info, const IS_MINT_TO: bool>(
-    ctx: Context<'_, '_, '_, 'info, MintToInstruction<'info>>,
-    recipient_pubkeys: &[impl AsPubkey],
+pub fn process_mint_to_or_compress<'info, const IS_MINT_TO: bool, P: AsPubkey>(
+    ctx: Context<'_, '_, '_, 'info, MintToInstruction<'info>>,
+    recipient_pubkeys: &[P],

This keeps one instantiation irrespective of the caller’s concrete slice element type.

program-libs/compressed-account/src/lib.rs (2)

19-29: Pubkey re-export: missing #[doc] / visibility clarity

Great to see the unified re-export, but consider adding a short rust-doc so downstream users understand that this is always the local, backend-agnostic type and not Solana’s Pubkey.

/// Backend-agnostic 32-byte public key used across Lightprotocol.
/// This is *not* `solana_sdk::pubkey::Pubkey`.
pub use pubkey::Pubkey;

82-88: Guard against feature combinations

Two independent From<CompressedAccountError> for ProgramError impls are fine, but if both solana and pinocchio are enabled you still avoid overlap because the target types differ.

Please add an explicit mutually-exclusive feature check to make intent obvious:

#[cfg(all(feature = "solana", feature = "pinocchio"))]
compile_error!("`solana` and `pinocchio` features cannot be enabled together in this crate");

This prevents accidental “everything” builds from compiling invalid binaries.

program-libs/batched-merkle-tree/src/queue.rs (2)

147-154: Redundant conversion when constructing program id

Pubkey::new_from_array(ACCOUNT_COMPRESSION_PROGRAM_ID) allocates a new Pubkey every call.
Since the constant is already a 32-byte array, cache the Pubkey:

lazy_static::lazy_static! {
    static ref ACCOUNT_COMPRESSION_PROGRAM_ID_PK: Pubkey =
        Pubkey::new_from_array(ACCOUNT_COMPRESSION_PROGRAM_ID);
}

...
Self::from_account_info::<OUTPUT_STATE_QUEUE_TYPE_V2, A>(
    &*ACCOUNT_COMPRESSION_PROGRAM_ID_PK,
    account_info,
)

This avoids repeated hashing of the same bytes.


499-502: solana_msg crate dependency may be unnecessary

The conditional log uses solana_msg::msg!, yet solana_program::msg! is already available with the solana feature and avoids another crate:

-            #[cfg(feature = "solana")]
-            for batch in batch_metadata.batches.iter() {
-                solana_msg::msg!("batch {:?}", batch);
-            }
+            #[cfg(feature = "solana")]
+            for batch in batch_metadata.batches.iter() {
+                solana_program::msg!("batch {:?}", batch);
+            }

Unless solana_msg wraps additional functionality, removing it simplifies dependency graph.

program-tests/utils/src/e2e_test_env.rs (1)

2876-2893: Repeated to_bytes() allocations inside tight filter

Inside get_random_compressed_sol_accounts the closure used in the
.find(..) chain converts both sides to byte arrays on every iteration:

x.accounts.merkle_tree.to_bytes() == first_account.merkle_context.merkle_tree_pubkey.to_bytes()

Pubkey::to_bytes() allocates a temporary [u8; 32] each time. When the
state set is large this becomes a hot path. Cache the byte array of
first_account once outside the loop and compare against it, or compare
the Pubkey values directly if both types now implement PartialEq.

program-libs/account-checks/tests/tests.rs (2)

1-1: Consider splitting tests by feature for better modularity.

While the current approach works with --all-features in CI, consider organizing tests into separate modules that can run independently with each feature. This would allow testing each backend in isolation when needed.


789-845: Track the commented out rent balance tests.

These tests are commented out due to sysvar unavailability in the test environment. Consider creating an issue to track implementing these tests with proper test setup or mock sysvar functionality.

Would you like me to help create a solution that mocks the sysvar functionality for testing or open an issue to track this work?

program-tests/account-compression-test/tests/merkle_tree_tests.rs (3)

229-229: Fix nested list formatting in test comment
Add a space after 6. and capitalize Try for consistency in comment style:

- ///    6.try inserting again it should fail with full error
+ /// 6. Try inserting again; it should still fail with a full error

422-424: Improve sub-point comment consistency (3.x)
The nested list items under "3. invalid queue accounts:" would be clearer with consistent punctuation and capitalization. Consider this style:

- ///    3.1 pass non queue account as queue account
+ ///   3.1. Pass non-queue account as queue account
- ///    3.2 pass address queue account
+ ///   3.2. Pass address queue account instead of nullifier queue
- ///    3.3 pass non associated queue account
+ ///   3.3. Pass non-associated queue account

427-428: Align punctuation for Merkle tree account comments (4.x)
Add periods after sub-point numbers and standardize wording:

- ///    4.1 pass non Merkle tree account as Merkle tree account
+ ///   4.1. Pass non-Merkle tree account as Merkle tree account
- ///    4.2 pass non associated Merkle tree account
+ ///   4.2. Pass non-associated Merkle tree account
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9df1ca5 and 2f88073.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (107)
  • .github/workflows/rust.yml (1 hunks)
  • examples/anchor/counter/src/lib.rs (5 hunks)
  • examples/anchor/counter/tests/test.rs (1 hunks)
  • examples/anchor/token-escrow/Cargo.toml (1 hunks)
  • examples/anchor/token-escrow/src/escrow_with_compressed_pda/escrow.rs (1 hunks)
  • examples/anchor/token-escrow/src/escrow_with_compressed_pda/sdk.rs (2 hunks)
  • examples/anchor/token-escrow/src/escrow_with_compressed_pda/withdrawal.rs (3 hunks)
  • examples/anchor/token-escrow/src/escrow_with_pda/sdk.rs (1 hunks)
  • examples/anchor/token-escrow/tests/test.rs (3 hunks)
  • examples/anchor/token-escrow/tests/test_compressed_pda.rs (7 hunks)
  • forester-utils/src/instructions/address_batch_update.rs (2 hunks)
  • forester/tests/address_v2_test.rs (4 hunks)
  • forester/tests/batched_state_async_indexer_test.rs (6 hunks)
  • program-libs/account-checks/Cargo.toml (2 hunks)
  • program-libs/account-checks/src/account_info/account_info_trait.rs (1 hunks)
  • program-libs/account-checks/src/account_info/mod.rs (1 hunks)
  • program-libs/account-checks/src/account_info/pinocchio.rs (1 hunks)
  • program-libs/account-checks/src/account_info/solana.rs (1 hunks)
  • program-libs/account-checks/src/checks.rs (7 hunks)
  • program-libs/account-checks/src/error.rs (1 hunks)
  • program-libs/account-checks/src/lib.rs (1 hunks)
  • program-libs/account-checks/tests/account_info.rs (1 hunks)
  • program-libs/account-checks/tests/tests.rs (1 hunks)
  • program-libs/batched-merkle-tree/Cargo.toml (1 hunks)
  • program-libs/batched-merkle-tree/src/batch.rs (3 hunks)
  • program-libs/batched-merkle-tree/src/constants.rs (2 hunks)
  • program-libs/batched-merkle-tree/src/initialize_address_tree.rs (5 hunks)
  • program-libs/batched-merkle-tree/src/initialize_state_tree.rs (4 hunks)
  • program-libs/batched-merkle-tree/src/lib.rs (0 hunks)
  • program-libs/batched-merkle-tree/src/merkle_tree.rs (8 hunks)
  • program-libs/batched-merkle-tree/src/queue.rs (7 hunks)
  • program-libs/batched-merkle-tree/src/queue_batch_metadata.rs (0 hunks)
  • program-libs/batched-merkle-tree/src/rollover_address_tree.rs (3 hunks)
  • program-libs/batched-merkle-tree/src/rollover_state_tree.rs (4 hunks)
  • program-libs/batched-merkle-tree/tests/account_access.rs (9 hunks)
  • program-libs/bloom-filter/src/lib.rs (1 hunks)
  • program-libs/compressed-account/Cargo.toml (2 hunks)
  • program-libs/compressed-account/src/constants.rs (1 hunks)
  • program-libs/compressed-account/src/indexer_event/event.rs (1 hunks)
  • program-libs/compressed-account/src/indexer_event/parse.rs (4 hunks)
  • program-libs/compressed-account/src/instruction_data/with_readonly.rs (3 hunks)
  • program-libs/compressed-account/src/instruction_data/zero_copy.rs (3 hunks)
  • program-libs/compressed-account/src/lib.rs (3 hunks)
  • program-libs/compressed-account/src/pubkey.rs (7 hunks)
  • program-libs/concurrent-merkle-tree/Cargo.toml (1 hunks)
  • program-libs/concurrent-merkle-tree/src/errors.rs (1 hunks)
  • program-libs/hasher/Cargo.toml (1 hunks)
  • program-libs/hasher/src/errors.rs (1 hunks)
  • program-libs/hasher/src/hash_to_field_size.rs (2 hunks)
  • program-libs/hasher/src/lib.rs (0 hunks)
  • program-libs/indexed-merkle-tree/src/errors.rs (1 hunks)
  • program-libs/macros/src/lib.rs (1 hunks)
  • program-libs/macros/src/pubkey.rs (1 hunks)
  • program-libs/merkle-tree-metadata/Cargo.toml (1 hunks)
  • program-libs/merkle-tree-metadata/src/errors.rs (1 hunks)
  • program-libs/merkle-tree-metadata/src/lib.rs (0 hunks)
  • program-libs/merkle-tree-metadata/src/rollover.rs (2 hunks)
  • program-libs/verifier/Cargo.toml (1 hunks)
  • program-libs/verifier/src/lib.rs (4 hunks)
  • program-tests/account-compression-test/tests/address_merkle_tree_tests.rs (1 hunks)
  • program-tests/account-compression-test/tests/merkle_tree_tests.rs (4 hunks)
  • program-tests/client-test/tests/light_client.rs (2 hunks)
  • program-tests/client-test/tests/light_program_test.rs (2 hunks)
  • program-tests/compressed-token-test/tests/test.rs (33 hunks)
  • program-tests/create-address-test-program/src/create_pda.rs (2 hunks)
  • program-tests/e2e-test/tests/test.rs (2 hunks)
  • program-tests/registry-test/tests/tests.rs (4 hunks)
  • program-tests/sdk-anchor-test/programs/sdk-anchor-test/src/lib.rs (2 hunks)
  • program-tests/sdk-test/src/create_pda.rs (3 hunks)
  • program-tests/sdk-test/src/update_pda.rs (1 hunks)
  • program-tests/sdk-test/tests/test.rs (2 hunks)
  • program-tests/system-cpi-test/Cargo.toml (1 hunks)
  • program-tests/system-cpi-test/src/create_pda.rs (4 hunks)
  • program-tests/system-cpi-test/src/invalidate_not_owned_account.rs (2 hunks)
  • program-tests/system-cpi-test/src/sdk.rs (3 hunks)
  • program-tests/system-cpi-test/tests/test.rs (10 hunks)
  • program-tests/system-cpi-test/tests/test_program_owned_trees.rs (2 hunks)
  • program-tests/system-cpi-v2-test/tests/event.rs (27 hunks)
  • program-tests/system-cpi-v2-test/tests/invoke_cpi_with_read_only.rs (40 hunks)
  • program-tests/system-test/tests/test.rs (48 hunks)
  • program-tests/utils/src/assert_compressed_tx.rs (3 hunks)
  • program-tests/utils/src/assert_merkle_tree.rs (1 hunks)
  • program-tests/utils/src/assert_rollover.rs (2 hunks)
  • program-tests/utils/src/assert_token_tx.rs (1 hunks)
  • program-tests/utils/src/batched_address_tree.rs (2 hunks)
  • program-tests/utils/src/create_address_test_program_sdk.rs (4 hunks)
  • program-tests/utils/src/e2e_test_env.rs (10 hunks)
  • program-tests/utils/src/lib.rs (1 hunks)
  • program-tests/utils/src/pack.rs (1 hunks)
  • program-tests/utils/src/spl.rs (7 hunks)
  • program-tests/utils/src/system_program.rs (16 hunks)
  • programs/account-compression/src/instructions/initialize_batched_state_merkle_tree.rs (1 hunks)
  • programs/account-compression/src/instructions/nullify_leaves.rs (1 hunks)
  • programs/account-compression/src/instructions/resize_registered_program_account.rs (1 hunks)
  • programs/account-compression/src/instructions/update_address_merkle_tree.rs (1 hunks)
  • programs/account-compression/src/processor/insert_addresses.rs (1 hunks)
  • programs/account-compression/src/processor/insert_nullifiers.rs (1 hunks)
  • programs/compressed-token/src/freeze.rs (2 hunks)
  • programs/compressed-token/src/process_mint.rs (4 hunks)
  • programs/compressed-token/src/process_transfer.rs (8 hunks)
  • programs/registry/src/lib.rs (1 hunks)
  • programs/system/src/accounts/init_context_account.rs (1 hunks)
  • programs/system/src/context.rs (2 hunks)
  • programs/system/src/errors.rs (0 hunks)
  • programs/system/src/invoke/verify_signer.rs (2 hunks)
  • programs/system/src/invoke_cpi/process_cpi_context.rs (5 hunks)
  • programs/system/src/lib.rs (2 hunks)
⛔ Files not processed due to max files limit (19)
  • programs/system/src/processor/create_address_cpi_data.rs
  • programs/system/src/processor/sum_check.rs
  • programs/system/tests/invoke_cpi_instruction.rs
  • programs/system/tests/invoke_cpi_instruction_small.rs
  • scripts/format.sh
  • scripts/lint.sh
  • sdk-libs/client/src/indexer/types.rs
  • sdk-libs/client/src/rpc/client.rs
  • sdk-libs/macros/Cargo.toml
  • sdk-libs/macros/src/discriminator.rs
  • sdk-libs/program-test/src/indexer/test_indexer.rs
  • sdk-libs/program-test/src/program_test/rpc.rs
  • sdk-libs/program-test/src/utils/setup_light_programs.rs
  • sdk-libs/sdk/Cargo.toml
  • sdk-libs/sdk/src/account.rs
  • sdk-libs/sdk/src/account_info.rs
  • sdk-libs/sdk/src/address.rs
  • sdk-libs/sdk/src/instruction/tree_info.rs
  • sdk-libs/sdk/src/lib.rs
💤 Files with no reviewable changes (5)
  • programs/system/src/errors.rs
  • program-libs/hasher/src/lib.rs
  • program-libs/batched-merkle-tree/src/queue_batch_metadata.rs
  • program-libs/merkle-tree-metadata/src/lib.rs
  • program-libs/batched-merkle-tree/src/lib.rs
🧰 Additional context used
🧬 Code Graph Analysis (16)
examples/anchor/token-escrow/src/escrow_with_pda/sdk.rs (1)
program-tests/utils/src/pack.rs (1)
  • add_and_get_remaining_account_indices (17-34)
program-tests/utils/src/assert_token_tx.rs (1)
sdk-libs/sdk/src/account.rs (1)
  • owner (153-155)
program-libs/macros/src/lib.rs (1)
program-libs/macros/src/pubkey.rs (2)
  • pubkey_array (42-61)
  • pubkey (21-40)
programs/system/src/lib.rs (2)
program-libs/macros/src/lib.rs (1)
  • pubkey_array (20-25)
program-libs/macros/src/pubkey.rs (1)
  • pubkey_array (42-61)
programs/system/src/invoke/verify_signer.rs (1)
program-libs/compressed-account/src/pubkey.rs (1)
  • new_unique (148-150)
examples/anchor/token-escrow/src/escrow_with_compressed_pda/escrow.rs (1)
program-libs/compressed-account/src/address.rs (1)
  • derive_address_legacy (18-28)
forester-utils/src/instructions/address_batch_update.rs (1)
js/stateless.js/src/state/types.ts (1)
  • CompressedProof (133-137)
program-libs/batched-merkle-tree/src/constants.rs (2)
program-libs/macros/src/lib.rs (1)
  • pubkey_array (20-25)
program-libs/macros/src/pubkey.rs (1)
  • pubkey_array (42-61)
program-libs/batched-merkle-tree/src/rollover_address_tree.rs (1)
program-libs/account-checks/src/checks.rs (1)
  • check_account_balance_is_rent_exempt (93-115)
program-tests/utils/src/spl.rs (2)
program-tests/system-cpi-test/tests/test.rs (1)
  • test_indexer (1280-1288)
program-tests/compressed-token-test/tests/test.rs (4)
  • test_indexer (2562-2571)
  • test_indexer (3025-3034)
  • test_indexer (3077-3086)
  • test_indexer (3878-3887)
program-libs/compressed-account/src/constants.rs (2)
program-libs/macros/src/lib.rs (1)
  • pubkey_array (20-25)
program-libs/macros/src/pubkey.rs (1)
  • pubkey_array (42-61)
programs/compressed-token/src/process_mint.rs (4)
program-libs/compressed-account/src/instruction_data/with_readonly.rs (1)
  • data (96-102)
program-libs/compressed-account/src/indexer_event/parse.rs (3)
  • data (353-361)
  • data (399-419)
  • data (420-442)
program-libs/compressed-account/src/instruction_data/zero_copy.rs (4)
  • data (140-145)
  • data (361-363)
  • data (751-755)
  • data (756-760)
program-libs/macros/src/pubkey.rs (1)
  • pubkey (21-40)
program-libs/account-checks/src/account_info/pinocchio.rs (3)
program-libs/account-checks/src/account_info/account_info_trait.rs (12)
  • key (15-15)
  • is_writable (16-16)
  • is_signer (17-17)
  • executable (18-18)
  • lamports (19-19)
  • data_len (20-20)
  • try_borrow_data (23-23)
  • try_borrow_mut_data (24-24)
  • is_owned_by (27-27)
  • find_program_address (30-30)
  • create_program_address (31-34)
  • get_min_rent_balance (37-37)
program-libs/account-checks/src/account_info/solana.rs (12)
  • key (15-17)
  • is_writable (19-21)
  • is_signer (23-25)
  • executable (27-29)
  • lamports (31-33)
  • data_len (35-37)
  • try_borrow_data (39-44)
  • try_borrow_mut_data (46-51)
  • is_owned_by (53-55)
  • find_program_address (57-61)
  • create_program_address (63-71)
  • get_min_rent_balance (73-78)
program-libs/account-checks/src/error.rs (6)
  • from (37-54)
  • from (59-61)
  • from (66-68)
  • from (73-75)
  • from (80-82)
  • from (87-89)
program-libs/compressed-account/src/instruction_data/zero_copy.rs (1)
program-libs/compressed-account/src/compressed_account.rs (1)
  • reference (555-676)
program-libs/batched-merkle-tree/src/rollover_state_tree.rs (3)
program-libs/account-checks/src/checks.rs (1)
  • check_account_balance_is_rent_exempt (93-115)
program-libs/account-checks/src/account_info/account_info_trait.rs (1)
  • get_min_rent_balance (37-37)
program-libs/account-checks/src/account_info/solana.rs (1)
  • get_min_rent_balance (73-78)
program-libs/account-checks/tests/tests.rs (2)
program-libs/account-checks/src/account_info/test_account_info.rs (3)
  • new (121-129)
  • get_account_info (13-64)
  • get_account_info (131-142)
program-libs/account-checks/src/checks.rs (9)
  • check_account_info_mut (23-31)
  • check_account_info_non_mut (37-44)
  • check_non_mut (46-51)
  • check_signer (117-122)
  • check_owner (124-132)
  • check_program (134-145)
  • check_pda_seeds (147-157)
  • check_pda_seeds_with_bump (159-169)
  • check_account_balance_is_rent_exempt (93-115)
🪛 GitHub Actions: forester-tests
program-tests/utils/src/lib.rs

[warning] 1-1: Operation failed, retrying in 1s (attempt 1/30): CustomError("Airdrop not confirmed")

program-libs/macros/src/lib.rs

[warning] 1-1: Operation failed, retrying in 1s (attempt 1/30): CustomError("Airdrop not confirmed")

programs/system/src/lib.rs

[warning] 1-1: Operation failed, retrying in 1s (attempt 1/30): CustomError("Airdrop not confirmed")

program-tests/sdk-anchor-test/programs/sdk-anchor-test/src/lib.rs

[warning] 1-1: Operation failed, retrying in 1s (attempt 1/30): CustomError("Airdrop not confirmed")

program-libs/bloom-filter/src/lib.rs

[warning] 1-1: Operation failed, retrying in 1s (attempt 1/30): CustomError("Airdrop not confirmed")

examples/anchor/counter/src/lib.rs

[warning] 1-1: Operation failed, retrying in 1s (attempt 1/30): CustomError("Airdrop not confirmed")

programs/registry/src/lib.rs

[warning] 1-1: Operation failed, retrying in 1s (attempt 1/30): CustomError("Airdrop not confirmed")

program-libs/account-checks/src/lib.rs

[warning] 1-1: Operation failed, retrying in 1s (attempt 1/30): CustomError("Airdrop not confirmed")

program-libs/verifier/src/lib.rs

[warning] 1-1: Operation failed, retrying in 1s (attempt 1/30): CustomError("Airdrop not confirmed")

program-libs/compressed-account/src/lib.rs

[warning] 1-1: Operation failed, retrying in 1s (attempt 1/30): CustomError("Airdrop not confirmed")

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Test concurrent-merkle-tree
  • GitHub Check: system-programs (system-cpi-test-v2, ["cargo-test-sbf -p system-cpi-v2-test"])
  • GitHub Check: stateless-js
🔇 Additional comments (87)
program-libs/hasher/Cargo.toml (1)

9-13: Removing default features can break downstream builds – double-check all dependents

default = [] means crates that previously compiled implicitly with the solana path must now opt-in via features = ["solana"] (or "pinocchio"). Please make sure:

  1. Every program-libs/* crate that relies on light-hasher adds the correct feature in its own Cargo.toml.
  2. CI jobs that build or test sub-crates run with --all-features (already updated) and at least one job exercises the “no-features” build to keep that configuration green.

A quick grep for light-hasher without an explicit feature flag in the workspace would catch any omissions.

program-libs/indexed-merkle-tree/src/errors.rs (1)

60-65: Consistent feature gating – LGTM

The conversion to solana_program_error::ProgramError is now enabled by feature = "solana" rather than “not pinocchio”, mirroring the pattern used everywhere else. Good clean-up.

program-libs/bloom-filter/src/lib.rs (1)

22-34: Feature flags simplified – looks correct

Each From<...> for ProgramError impl is now guarded solely by its own backend feature. This matches other crates after the refactor and avoids mutually exclusive cfgs. No action needed.

program-tests/utils/src/lib.rs (1)

32-32: Export the new pack module
Adding pub mod pack; correctly exposes the packing utilities to consumers of light_test_utils.

examples/anchor/token-escrow/src/escrow_with_pda/sdk.rs (1)

16-16: Redirect add_and_get_remaining_account_indices import
Swapping the import to light_test_utils::pack aligns with the new utility placement and is consistent with related examples.

program-libs/batched-merkle-tree/Cargo.toml (1)

42-42: Make solana-msg a non-optional dependency
Including solana-msg unconditionally ensures logging macros are available when both Solana and Pinocchio features are enabled, resolving previous compilation conflicts.

program-tests/sdk-test/src/update_pda.rs (1)

28-28: Simplify LightAccount::new_mut call
Removing the intermediate program_id variable and using &crate::ID directly cleans up the code without altering behavior.

program-tests/system-cpi-test/Cargo.toml (1)

37-37: Conditionally include light-test-utils for non-Solana targets
Moving light-test-utils into the cfg(not(target_os = "solana")) section provides the necessary utilities where they’re used, while keeping Solana builds lean.

program-libs/verifier/Cargo.toml (1)

9-12: Removal of default features is potentially breaking – confirm reverse-dependencies still build

Setting

default = []

means any downstream crate that previously relied on light-verifier’s implicit "solana" feature must now opt‐in explicitly. Please run a workspace-wide cargo check --all (and CI) with no extra features to ensure nothing unexpectedly fails to compile, and document the change in the release notes.

program-libs/account-checks/Cargo.toml (1)

9-12: Same breaking-change risk as above

default = [] removes the automatic Solana backend. Verify all crates/tests that depend on light-account-checks specify a backend feature or they will now fail to compile.

program-tests/account-compression-test/tests/address_merkle_tree_tests.rs (1)

509-512: Docstring numbering fix looks good

The clarification in comment numbering improves readability; no further action required.

programs/account-compression/src/instructions/initialize_batched_state_merkle_tree.rs (1)

60-64: Conversion looks good – just confirm trait bounds

Passing owner.into() is correct if init_batched_state_merkle_tree_from_account_info now expects impl Into<[u8;32]>. No further action needed.

examples/anchor/token-escrow/src/escrow_with_compressed_pda/sdk.rs (1)

16-18: Import path update LGTM

Switching to light_test_utils::pack::* centralises packing utilities and removes duplicate helpers. No issues spotted.

examples/anchor/counter/tests/test.rs (1)

1-1: Feature-gate now active – double-check CI matrix

The test module is now compiled only when the test-sbf feature is enabled.
Be sure that all CI jobs intended to execute these tests pass --features test-sbf (or --all-features, as in the updated workflow) and that local developers are aware of the flag.

programs/system/src/accounts/init_context_account.rs (1)

57-58: Generic parameter order looks correct

account_info_init::<CpiContextAccount, AccountInfo> matches the new two-parameter signature introduced by AccountInfoTrait; no issues spotted.

programs/system/src/context.rs (1)

337-347: Inconsistent owner value vs reference

owner: *input.owner(), dereferences a &Pubkey to copy the value – fine if
InputAccount::owner() -> &Pubkey.
A few lines below, the output path uses owner: output.owner(), (line 359) with no
dereference. If OutputAccount::owner() returns a Pubkey by value this is
consistent; otherwise the code will fail to compile or incur an extra copy.

Please confirm the two trait signatures are indeed different. If both return
&Pubkey use the same pattern for consistency:

-                owner: output.owner(),
+                owner: *output.owner(),
programs/system/src/invoke/verify_signer.rs (1)

50-52: Conversion now explicit – no objections

Using .into() makes the [u8;32] → Pubkey conversion explicit and self-documenting; looks good.

Also applies to: 72-75

program-tests/sdk-anchor-test/programs/sdk-anchor-test/src/lib.rs (1)

47-52: Redundant local removed – 👍

Passing &crate::ID directly simplifies the call sites and removes an unnecessary binding. No functional change.

Also applies to: 78-82

programs/account-compression/src/instructions/nullify_leaves.rs (1)

107-114:

✅ Verification successful

Double-check associated_queue’s concrete type

merkle_tree.metadata.associated_queue is now compared to ctx.accounts.nullifier_queue.key() without the previous .into().
This indicates that associated_queue has been promoted to a Pubkey, while other metadata fields (e.g. owner) still store [u8; 32] and require .into().

Please verify that:

  1. The struct definition of StateMerkleTreeAccount::metadata.associated_queue has indeed been updated to Pubkey.
  2. All serialization/deserialization paths were adjusted accordingly (Borsh / Anchor zero-copy).

If the field is still [u8; 32], this comparison will not compile and the missing .into() needs to be reinstated.


🏁 Script executed:

#!/bin/bash
# Locate the definition of `associated_queue` and print its type.
ast-grep --pattern $'struct StateMerkleTreeAccount { $$$ associated_queue: $_, $$$ }'

Length of output: 86


🏁 Script executed:

#!/bin/bash
# Search for where `associated_queue` is defined and inspect its type
rg 'associated_queue' -n -C 3

# Locate the definition of `StateMerkleTreeAccount` to confirm its metadata field types
rg 'struct StateMerkleTreeAccount' -n -C 5

Length of output: 27705


No action needed: associated_queue is already a Pubkey.
Verified that in:

  • program-libs/merkle-tree-metadata/src/merkle_tree.rs
  • programs/system/src/account_compression_state/state.rs
  • programs/account-compression/src/state/public_state_merkle_tree.rs
    the field associated_queue is declared as Pubkey, so comparing directly to ctx.accounts.nullifier_queue.key() is type-correct and no .into() is required.
program-tests/client-test/tests/light_client.rs (1)

639-656: Conversions look correct

The switch to .into() for owner, address_queue_pubkey, and address_merkle_tree_pubkey matches the new [u8; 32]-first model.
No issues spotted.

Also applies to: 670-675

program-tests/client-test/tests/light_program_test.rs (1)

639-642: Conversions align with the updated key representation

Same pattern as in light_client.rs; the explicit .into() keeps the test compiling across both back-ends. Looks good.

Also applies to: 657-663

programs/account-compression/src/processor/insert_addresses.rs (1)

139-145: Redundant .into() removed – OK

queue.metadata.associated_merkle_tree and *merkle_pubkey are now compared directly.
Assuming both are Pubkey, this improves clarity and avoids the extra allocation the former conversion incurred. Looks good.

programs/account-compression/src/processor/insert_nullifiers.rs (1)

176-184: Direct Pubkey comparison – looks correct

The equality check now compares two Pubkeys without a superfluous .into().
This keeps the hot path tight and avoids an unnecessary conversion.

examples/anchor/token-escrow/tests/test.rs (1)

370-374: Verify the signer-slice change

create_and_send_transaction previously received &[&Keypair]; it now receives &[Keypair].
If the function signature still expects a slice of references (&[&Keypair]), this will fail to compile.
Please confirm that the helper now accepts &[Keypair]; otherwise revert to &[&payer].

forester-utils/src/instructions/address_batch_update.rs (1)

17-17: Import path & extra dereference look fine

The new CompressedProof path and the extra * in &(*merkle_tree_pubkey).into() compile cleanly and avoid any ambiguity with the trait impls you introduced elsewhere.
No follow-up required.

Also applies to: 48-49

program-tests/utils/src/assert_merkle_tree.rs (1)

87-89: Byte-wise comparison is a sensible decoupling

Switching to .to_bytes() avoids the cross-crate Pubkey type mismatch and keeps the tests stable; good move.

Also applies to: 91-109

programs/registry/src/lib.rs (1)

685-687: Type unification looks correct

Removing .into() aligns both sides to the same Pubkey type after your earlier macro changes.

programs/account-compression/src/instructions/update_address_merkle_tree.rs (1)

58-66: Removed .into() – ensure both sides share the exact type

merkle_tree.metadata.associated_queue is now compared directly with ctx.accounts.queue.key().
If associated_queue is [u8; 32] while key() returns a wrapper Pubkey, the comparison will fail to compile or silently diverge depending on PartialEq impls.

Please confirm the two fields are the same concrete type after the refactor; otherwise restore a deterministic conversion on one side.

program-tests/e2e-test/tests/test.rs (1)

45-50: Idiomatic struct initialisation – looks good

Nice use of struct-update syntax; it eliminates the mutable default and is clearer.

program-libs/account-checks/src/lib.rs (1)

1-7: Public re-export of AccountInfoTrait looks correct

pub use account_info::account_info_trait::AccountInfoTrait; cleanly exposes the trait to dependants; modules compile with a single import line.

🧰 Tools
🪛 GitHub Actions: forester-tests

[warning] 1-1: Operation failed, retrying in 1s (attempt 1/30): CustomError("Airdrop not confirmed")

program-libs/compressed-account/src/instruction_data/with_readonly.rs (2)

133-136: LGTM – direct Pubkey assignment is clearer

Removing the .into() keeps the field type explicit and avoids an extra conversion. No concerns here.


471-475: Tests updated correctly

The test structs now pass a concrete Pubkey without conversion – matches the production code change above.

Also applies to: 686-690

program-tests/system-cpi-test/tests/test_program_owned_trees.rs (1)

53-56: Initialization simplified – no issues

Replacing the mutable config block with a struct literal improves readability. Behaviour is unchanged.

Also applies to: 203-206

program-libs/compressed-account/src/indexer_event/event.rs (1)

72-76: Confirm raw-array vs Pubkey alias after .into() removal

tree_pubkey/queue_pubkey are now copied directly from seq.* without .into().
If crate::Pubkey is still a distinct new-type, this will not compile; if you intentionally re-aliased it to [u8; 32], all good.

Please run cargo check --all-features across dependent crates to make sure no implicit From<[u8;32]> for Pubkey usages remain elsewhere.

program-tests/sdk-test/tests/test.rs (1)

1-1: Feature-gated test now active

Un-commenting #![cfg(feature = "test-sbf")] means this file is ignored unless the flag is on.
If you rely on these checks in CI, make sure the workflow sets --features test-sbf; otherwise the test will silently disappear again.

program-tests/system-cpi-test/src/create_pda.rs (1)

531-533: Owner supplied from caller – sanity-check before writing to state

owner_program is taken from the instruction data and written straight into the compressed account.
Nothing guards against a malicious client passing an arbitrary key and thereby spoofing ownership.

At minimum:

require!(
    *owner_program == crate::ID,
    CustomError::InvalidOwner
);

(or gate it behind a test-only cfg).

This closes a potential privilege-escalation vector.

program-libs/batched-merkle-tree/tests/account_access.rs (1)

4-32: Import & conversion updates look sound

The switch to the new account_info path and the pervasive .into() conversions compile on nightly and make the tests backend-agnostic. No concerns here.

program-tests/utils/src/assert_compressed_tx.rs (1)

351-353: Consistent type usage 👍

Switching to .into() keeps the API uniform after the [u8;32] refactor.

program-tests/registry-test/tests/tests.rs (1)

1880-1883: Good simplification

Direct struct-literal initialisation is clearer and removes a mutable temp.

forester/tests/address_v2_test.rs (1)

353-355: Good use of the new pack helpers

Switching to pack_output_compressed_accounts centralises packing logic and reduces boilerplate.
No issues spotted in this segment.

program-libs/batched-merkle-tree/src/rollover_address_tree.rs (1)

15-18: Generic AccountInfoTrait adoption looks correct

The signature update makes the helper usable from both Solana & Pinocchio contexts without duplication.
No functional concerns—nice refactor.

program-libs/hasher/src/errors.rs (1)

55-59: Pinocchio path looks good

Conversion for the pinocchio backend is consistent and compiles as-is.

program-tests/system-cpi-v2-test/tests/event.rs (1)

88-90: 👍 Consistent newtype conversion

The switch to .into() for merkle_tree when hashing brings the test in line
with the production code that now operates on the local Pubkey newtype.
No issues spotted.

program-libs/merkle-tree-metadata/src/errors.rs (1)

41-52: Confirm unique error-code spaces per backend

Both impls blindly wrap the same numeric space into a Custom error for each backend.
If Solana and Pinocchio are ever enabled together the numeric codes are still unique inside each backend, so there is no collision, but please double-check that other crates do not rely on a shared global namespace.

program-tests/system-cpi-v2-test/tests/invoke_cpi_with_read_only.rs (2)

291-295: Type conversion may hide a logic bug

address_merkle_tree_pubkey: address_tree.into(),

address_tree is already a Pubkey. Converting it with .into() only has an effect when a newtype wrapper is in scope; otherwise it is a no-op that moves the value.
Because the same address_tree is reused later in the loop, repeated .into() calls will move the value the first time and trigger a use-after-move compilation error unless a Copy implementation exists for the target type. That Copy automatically falls back to a byte-wise copy, which is cheap but easy to overlook.

Please confirm that:

  1. Both source and target types implement Copy.
  2. The semantic difference between the two types (likely Solana Pubkey vs local light_sdk::Pubkey) is indeed only a wrapper, not endianness or domain specific.

If (1) or (2) is not true, introduce an explicit (&address_tree).into() or address_tree.clone().into() to avoid accidental moves.


2848-2861: light_test_utils::pack is pulled in – verify dev-dependency scope

The new import tree (light_test_utils::pack::*) increases compile time for every test crate that depends on this file.
If the pack helpers are only needed for tests, ensure light_test_utils is behind dev-dependencies in Cargo.toml of the parent crate to avoid bloating normal builds.

examples/anchor/token-escrow/tests/test_compressed_pda.rs (1)

194-196: Use the newtype Pubkey consistently – removal of the previous .into() conversions looks good

The call now passes &env.v1_address_trees[0].merkle_tree.into() instead of the raw Pubkey.
Because derive_address_legacy was recently made generic over both Solana and Light Pubkey variants, this change keeps the compile-time type inference straightforward.

No action needed.

program-libs/compressed-account/src/instruction_data/zero_copy.rs (1)

339-341: API inconsistency between InputAccount::owner and OutputAccount::owner

InputAccount::owner returns &Pubkey while OutputAccount::owner (line 124) now returns Pubkey by value.
Aligning the two keeps downstream generic code simpler.

Consider making both return references.

program-tests/compressed-token-test/tests/test.rs (10)

1627-1628: Add .into() conversion for merkle_tree_pubkey
Converts the raw Pubkey field to the unified local type, matching the new AccountInfoTrait abstraction.


1871-1873: Apply .into() on delegated account’s merkle_tree_pubkey
Maintains consistency by casting the field into the local Pubkey representation.


2012-2014: Convert merkle_tree_pubkey with .into() in mixed delegation test
Ensures compatibility with the new trait-based key type.


2539-2541: Cast merkle_tree_pubkey via .into() in revoke helper
Aligns the key conversion with the updated AccountInfoTrait API.


2687-2689: Use .into() for merkle_tree_pubkey in revoke failing tests
Standardizes the type conversion for negative-path scenarios.


2894-2896: Uniform .into() conversion for merkle_tree_pubkey in burn test
Keeps test logic in sync with the new Pubkey abstraction.


3042-3044: Introduce .into() for queue_pubkey in freeze failure test
Casts the queue key to the local type to satisfy trait requirements.


3383-3384: Add .into() for queue_pubkey in secondary burn failure
Ensures the queue key is converted to our unified Pubkey type.


4066-4066: Convert outputs_merkle_tree with .into() in thaw failing test
Maintains consistent key handling in negative-path thaw logic.


5291-5292: Apply .into() conversions in MerkleContext mapping
Wraps both merkle_tree_pubkey and queue_pubkey into the local Pubkey type for downstream usage.

program-libs/concurrent-merkle-tree/src/errors.rs (1)

64-76: Feature-gated From impls look correct

Providing separate implementations for Solana and Pinocchio without the previous mutual-exclusion guard removes the earlier compilation conflict while keeping the APIs intact.

program-libs/batched-merkle-tree/src/initialize_address_tree.rs (1)

73-80: Confirm error propagation after switching to AccountInfoTrait

try_borrow_mut_data()? now propagates the trait’s error type, relying on a From<TraitError> for BatchedMerkleTreeError impl.
Please verify that such an impl exists for both Solana and Pinocchio builds; otherwise the ? will fail to compile.

If missing, add:

impl From<light_account_checks::error::AccountError> for BatchedMerkleTreeError {
    fn from(e: light_account_checks::error::AccountError) -> Self {
        BatchedMerkleTreeError::AccountChecks(e)
    }
}

(or similar) to keep the conversion explicit.

programs/compressed-token/src/process_transfer.rs (1)

242-244: Potential missing AsPubkey impl for references

owner.to_pubkey_bytes() is called on &O (O: AsPubkey).
Unless a blanket impl<T: AsPubkey + ?Sized> AsPubkey for &T exists, this line will not compile.
Either add that blanket impl in pubkey.rs or deref here:

-        let hashed_owner = hash_to_bn254_field_size_be(owner.to_pubkey_bytes().as_slice());
+        let hashed_owner = hash_to_bn254_field_size_be((*owner).to_pubkey_bytes().as_slice());
program-libs/compressed-account/Cargo.toml (1)

9-16: Removal of default solana feature is a breaking change

Setting default = [] requires every downstream crate to explicitly opt-in to either solana or pinocchio. All internal workspace crates have been updated, but external users will experience unexpected compilation errors.

Consider publishing this as 0.3.0 (semver-major) and highlight the migration step in the changelog.

program-libs/batched-merkle-tree/src/initialize_state_tree.rs (3)

2-2: LGTM!

The import correctly brings in the necessary trait and function for the generic account info handling.


69-113: Generic implementation looks good!

The function has been properly generalized to accept any type implementing AccountInfoTrait. The key conversions using .key().into() correctly handle the [u8; 32] to Pubkey conversion, and the simplified owner parameter type improves clarity.


139-140: Logging update is consistent!

The change to use solana_msg::msg! with a positive feature gate #[cfg(feature = "solana")] is cleaner and aligns with the logging pattern across the codebase.

program-libs/batched-merkle-tree/src/rollover_state_tree.rs (3)

1-1: Import changes look good!

The imports correctly bring in the trait and rent exemption check function needed for the generic implementation.


233-234: Consistent logging pattern!

The logging change follows the same pattern as other files in the codebase.


48-111:

✅ Verification successful

Generic rollover implementation is correct!

The function properly uses the trait abstraction. The rent calculation now correctly uses A::get_min_rent_balance() which provides the appropriate implementation for each backend.

Let me verify that the rent calculation behavior is preserved:


🏁 Script executed:

#!/bin/bash
# Description: Verify that get_min_rent_balance implementations match the previous behavior

# Check the trait definition for get_min_rent_balance
ast-grep --pattern 'fn get_min_rent_balance'

# Check how the old code calculated rent
rg -A 5 'crate::Rent::get' --type rust

Length of output: 2931


Rent calculation equivalence confirmed

The trait’s get_min_rent_balance implementations in

  • program-libs/account-checks/src/account_info/solana.rs
  • program-libs/account-checks/src/account_info/pinocchio.rs

both invoke Rent::get().minimum_balance(size), exactly matching the original crate::Rent::get().minimum_balance(...) logic. No semantic changes to rent computation—approving the generic rollover implementation.

program-libs/account-checks/src/account_info/pinocchio.rs (2)

5-44: Trait implementation looks correct!

The basic trait methods properly delegate to pinocchio's native methods with appropriate error conversion.


90-111: Rent calculation implementation is correct!

The method properly handles different environments with appropriate fallbacks.

program-libs/account-checks/src/account_info/solana.rs (1)

5-79: Excellent Solana trait implementation!

The implementation correctly handles all trait methods with proper lifetime bounds on associated types and consistent error mapping. The data borrowing methods elegantly map RefCell's smart pointers to slice references.

program-libs/account-checks/tests/account_info.rs (1)

1-493: Comprehensive test coverage!

The tests thoroughly validate both Solana and Pinocchio implementations of AccountInfoTrait, covering all methods including edge cases and error conditions. The test structure is well-organized and easy to follow.

Note: The commented-out get_min_rent_balance() tests (lines 233-257 and 448-492) should be enabled once the sysvar is available in the test environment.

program-libs/account-checks/src/account_info/account_info_trait.rs (1)

1-43: LGTM! Well-designed trait abstraction.

The AccountInfoTrait provides a comprehensive abstraction over different AccountInfo implementations with proper error handling and all necessary methods for account validation and manipulation.

program-tests/system-cpi-test/tests/test.rs (1)

224-225: LGTM! Consistent public key handling improvements.

All changes properly standardize public key comparisons to byte-level comparisons and use explicit .into() conversions, aligning with the PR's goal of improving type compatibility across different public key representations.

Also applies to: 236-237, 333-336, 622-623, 719-720, 839-839, 842-850, 877-887, 963-963, 1805-1806, 1812-1812, 1820-1820, 1825-1825, 2010-2011

program-libs/compressed-account/src/pubkey.rs (1)

14-15: LGTM! Excellent improvements to Pubkey interoperability.

The changes enhance type compatibility:

  • Added Eq and Hash derives for use in collections
  • Added AsRef<[u8]> and PartialEq implementations for better comparisons
  • Proper conversions between different Pubkey types
  • Better trait naming from PubkeyTrait to AsPubkey following Rust conventions

Also applies to: 67-84, 118-147, 157-200

program-libs/account-checks/tests/tests.rs (1)

45-787: LGTM! Comprehensive test coverage.

Excellent test suite that thoroughly covers both success and failure cases for all account check functions across both Solana and Pinocchio backends. The helper functions and test organization are well-structured.

program-libs/batched-merkle-tree/src/merkle_tree.rs (4)

6-6: LGTM!

The addition of AccountInfoTrait import is necessary for the generic refactoring.


93-96: Consistent generic parameter usage across public methods.

The refactoring to use generic A: AccountInfoTrait parameter is applied consistently across all public methods that handle account information, enabling seamless support for different implementations.

Also applies to: 104-107, 120-122, 147-149


156-167: Clean abstraction using byte arrays for program IDs.

The change from &Pubkey to &[u8; 32] for program IDs, combined with the generic trait approach, provides better decoupling from specific implementations. The .into() conversion on line 166 properly handles the type conversion.


253-261: Verify logging behavior for non-Solana implementations.

The logging is now exclusively gated by the solana feature. This means logs won't appear when using other implementations like Pinocchio. Is this intentional, or should there be logging support for other backends as well?

program-tests/utils/src/pack.rs (2)

17-34: LGTM! Well-structured account index tracking.

The function correctly maintains account indices and safely handles the unwrap on line 31 since the pubkey is guaranteed to be in the map after the insertion logic.


157-182: 🛠️ Refactor suggestion

Unexpected mutation of input data.

The function mutates merkle_context.prove_by_index = true on line 170, which is unexpected for a packing function. This side effect could surprise callers who don't expect their input data to be modified.

Consider cloning the merkle_context before modification to avoid side effects.

         .zip(root_indices.iter())
         .map(|(x, root_index)| {
-            let mut merkle_context = x.merkle_context;
+            let mut merkle_context = x.merkle_context.clone();
             let root_index = if let Some(root) = root_index {
                 *root
             } else {

Likely an incorrect or invalid review comment.

program-libs/account-checks/src/checks.rs (3)

1-5: LGTM! Clean trait import.

The AccountInfoTrait import replaces the previous concrete type dependencies.


8-17: Excellent generic refactoring of account check functions.

All account check functions have been consistently updated to:

  • Accept generic A: AccountInfoTrait parameter
  • Use &[u8; 32] for program IDs instead of &Pubkey
  • Access account properties through trait methods

This provides a clean abstraction over different account info implementations.

Also applies to: 23-31, 37-44, 56-66


93-115: Proper trait-based rent exemption check.

The function correctly uses A::get_min_rent_balance to access rent information through the trait interface, maintaining proper abstraction while preserving platform-specific behavior.

program-tests/account-compression-test/tests/merkle_tree_tests.rs (2)

15-15: Confirm import path for InsertIntoQueuesInstructionDataMut
The module path light_compressed_account::instruction_data::insert_into_queues::InsertIntoQueuesInstructionDataMut aligns with the refactored structure. Ensure this matches the published crate's API and is consistent in other test files.


40-40: Update pack_pubkey import to unified test utils
Good consolidation: pack_pubkey now resides in light_test_utils::pack, centralizing helper functions for consistency across tests.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
program-libs/account-checks/src/error.rs (1)

74-101: 🛠️ Refactor suggestion

Still lossy: non-Custom Pinocchio errors get flattened

The new mapping converts every non-Custom ProgramError into a numeric code and then wraps it back into PinocchioProgramError.
Call-sites can no longer distinguish between, e.g., InvalidArgument and InsufficientFunds.

Introduce a dedicated catch-all variant (or map 1-to-1):

-    PinocchioProgramError(u32),
+    /// Raw Pinocchio error that does not map to a dedicated variant.
+    UnknownPinocchioProgramError(u32),

and keep the original semantic information:

match error {
    pinocchio::program_error::ProgramError::Custom(code) => {
        AccountError::PinocchioProgramError(code)
    }
    other => AccountError::UnknownPinocchioProgramError(other.into()),
}

This preserves fidelity while still fitting in a single enum.

🧹 Nitpick comments (1)
program-libs/account-checks/src/error.rs (1)

33-35: Consider feature-gating or renaming the new variant

PinocchioProgramError is always compiled in, even when the solana backend is used exclusively.
Either wrap the variant itself in #[cfg(feature = "pinocchio")] or rename it to a backend-agnostic catch-all such as ExternalProgramError(u32) to avoid leaking Pinocchio-specific details into Solana-only builds.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f88073 and ab19578.

📒 Files selected for processing (6)
  • program-libs/account-checks/src/account_info/pinocchio.rs (1 hunks)
  • program-libs/account-checks/src/error.rs (2 hunks)
  • program-tests/account-compression-test/tests/merkle_tree_tests.rs (5 hunks)
  • program-tests/utils/src/e2e_test_env.rs (10 hunks)
  • program-tests/utils/src/system_program.rs (16 hunks)
  • programs/compressed-token/src/process_transfer.rs (9 hunks)
✅ Files skipped from review due to trivial changes (1)
  • program-tests/utils/src/system_program.rs
🚧 Files skipped from review as they are similar to previous changes (4)
  • program-tests/account-compression-test/tests/merkle_tree_tests.rs
  • program-tests/utils/src/e2e_test_env.rs
  • programs/compressed-token/src/process_transfer.rs
  • program-libs/account-checks/src/account_info/pinocchio.rs
⏰ Context from checks skipped due to timeout of 90000ms (22)
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-test"])
  • GitHub Check: system-programs (counter-test, ["cargo test-sbf -p counter"])
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test"])
  • GitHub Check: system-programs (token-escrow-test, [ "cargo test-sbf -p token-escrow" ])
  • GitHub Check: lint
  • GitHub Check: test-state-batched
  • GitHub Check: Test program-libs
  • GitHub Check: Test sdk-libs
  • GitHub Check: Test concurrent-merkle-tree
  • GitHub Check: test-2-foresters
  • GitHub Check: test-address-batched
  • GitHub Check: system-programs (random-e2e-test, ["cargo-test-sbf -p e2e-test"])
  • GitHub Check: system-programs (light-system-program, ["cargo-test-sbf -p system-test"])
  • GitHub Check: system-programs (account-compression, ["cargo-test-sbf -p account-compression-test"])
  • GitHub Check: system-programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test"])
  • GitHub Check: test-double-registration
  • GitHub Check: system-programs (system-cpi-test-v2, ["cargo-test-sbf -p system-cpi-v2-test"])
  • GitHub Check: test-state-photon-batched
  • GitHub Check: system-programs (light-compressed-token, ["cargo-test-sbf -p compressed-token-test"])
  • GitHub Check: test-e2e
  • GitHub Check: system-programs (light-registry, ["cargo-test-sbf -p registry-test"])
  • GitHub Check: stateless-js
🔇 Additional comments (1)
program-libs/account-checks/src/error.rs (1)

103-115: LGTM – keeps Solana borrow errors isolated

The targeted BorrowError/BorrowMutError conversions are concise and backend-specific. No issues spotted.

@ananas-block ananas-block merged commit 0ca65f9 into main Jun 11, 2025
32 checks passed
@ananas-block ananas-block deleted the jorrit/chore-improve-crate-feature-robustness branch June 11, 2025 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants