Skip to content

refactor: forester: add default tree / epoch#2127

Merged
sergeytimoshin merged 6 commits intomainfrom
sergey/add-default-tree-each-epoch
Dec 10, 2025
Merged

refactor: forester: add default tree / epoch#2127
sergeytimoshin merged 6 commits intomainfrom
sergey/add-default-tree-each-epoch

Conversation

@sergeytimoshin
Copy link
Contributor

@sergeytimoshin sergeytimoshin commented Dec 10, 2025

Summary by CodeRabbit

  • New Features

    • Added log-based tracking for account cleanup.
  • Configuration

    • Adjusted default batch size from 10 to 5.
  • Improvements

    • Enhanced compression tree handling and account state management.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 10, 2025

Walkthrough

This PR introduces log-based account cleanup for compressible tokens by adding a new LogSubscriber component that parses program logs to identify and remove closed accounts, while migrating shutdown channels from oneshot to broadcast to support multiple subscribers across the system.

Changes

Cohort / File(s) Summary
Shutdown Channel Migration (oneshot → broadcast)
forester/src/main.rs, forester/src/lib.rs, forester/tests/e2e_test.rs, forester/tests/test_batch_append_spent.rs
Replaces oneshot shutdown channels with tokio broadcast channels (capacity 1) to support multiple subscribers in the compressible pipeline. Updates parameter types and channel construction across main, lib, and test setups.
New Log-Based Account Cleanup
forester/src/compressible/subscriber.rs, forester/src/compressible/mod.rs, forester/tests/test_compressible_ctoken.rs, programs/registry/src/compressible/compress_and_close.rs
Introduces LogSubscriber component to subscribe to registry program logs via WebSocket, parse "compress_and_close:" messages, and update CompressibleAccountTracker. Adds program-level log emission in compress_and_close instruction. Updates public exports and test integration.
Compressor and State Simplification
forester/src/compressible/compressor.rs, forester/src/compressible/state.rs
Replaces dynamic RPC tree fetching with hardcoded TreeInfo; removes tracker synchronization post-compression. Removes public async method sync_accounts from CompressibleAccountTracker, delegating cleanup to LogSubscriber. Adds info-level logging after compress instruction.
Configuration and Epoch Management Updates
forester/src/compressible/config.rs, forester/src/epoch_manager.rs
Lowers default batch_size from 10 to 5. Refactors epoch_manager to insert synthetic compression tree during active-epoch phase, add V2 tree queue-poller registration, route Unknown tree types through compression pathway, and enhance dispatch_compression with eligibility checks and per-batch cancellation.
Dependency Addition
forester/Cargo.toml
Adds solana_pubkey to workspace dependencies.

Sequence Diagram

sequenceDiagram
    participant Program as Registry Program
    participant Logs as Solana Logs
    participant WebSocket as WebSocket/Pubsub
    participant LogSub as LogSubscriber
    participant Tracker as CompressibleAccountTracker
    
    Program->>Logs: emit "Program log: compress_and_close:<pubkey>"
    Logs->>WebSocket: propagate log message
    WebSocket->>LogSub: deliver RpcLogsResponse
    LogSub->>LogSub: parse log prefix & extract pubkey
    LogSub->>Tracker: remove account from tracked state
    Note over LogSub,Tracker: Closed accounts cleaned up via logs<br/>instead of RPC sync calls
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Areas requiring extra attention:

  • forester/src/epoch_manager.rs — Dense refactoring with multiple control-flow branches (V2 tree registration, Unknown routing, dispatch_compression enhancements, per-batch cancellation logic). Verify the queue-poller registration flow and cancellation semantics are sound.
  • forester/src/compressible/compressor.rs — Hardcoded TreeInfo replaces dynamic RPC fetching; confirm this is intentional and appropriate for the use case. Verify removed sync_accounts invocation doesn't break account state consistency expectations.
  • forester/src/compressible/subscriber.rs — LogSubscriber introduces WebSocket parsing and program-log extraction; validate error handling, pubkey parsing robustness, and race conditions between AccountSubscriber and LogSubscriber.
  • Shutdown channel migration — Broadcast channels now enable multiple subscribers; verify all resubscribe() calls are placed correctly and that broadcast semantics (message drop after all receivers lag) don't introduce unexpected behavior.

Possibly related PRs

Suggested labels

ai-review

Suggested reviewers

  • ananas-block
  • SwenSchaeferjohann

Poem

📋 Logs now track where RPC once roamed,
A broadcast signal calls the home,
Closed accounts fade to memory's song,
Subscribers listen all day long,
Where silence fell, a log now speaks!

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'refactor: forester: add default tree / epoch' is vague and doesn't clearly convey the main changes in the changeset. Consider a more specific title that captures the core refactoring, such as 'refactor: switch compressible shutdown to broadcast channel and add log-based account tracking' or similar to better reflect the substantive changes.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 77.27% which is sufficient. The required threshold is 70.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sergey/add-default-tree-each-epoch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 5

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d64a75 and 6f2821f.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock and included by none
  • xtask/src/create_ctoken_account.rs is excluded by none and included by none
📒 Files selected for processing (13)
  • forester/Cargo.toml (1 hunks)
  • forester/src/compressible/compressor.rs (5 hunks)
  • forester/src/compressible/config.rs (1 hunks)
  • forester/src/compressible/mod.rs (1 hunks)
  • forester/src/compressible/state.rs (0 hunks)
  • forester/src/compressible/subscriber.rs (3 hunks)
  • forester/src/epoch_manager.rs (9 hunks)
  • forester/src/lib.rs (3 hunks)
  • forester/src/main.rs (1 hunks)
  • forester/tests/e2e_test.rs (1 hunks)
  • forester/tests/test_batch_append_spent.rs (1 hunks)
  • forester/tests/test_compressible_ctoken.rs (3 hunks)
  • programs/registry/src/compressible/compress_and_close.rs (1 hunks)
💤 Files with no reviewable changes (1)
  • forester/src/compressible/state.rs
🧰 Additional context used
📓 Path-based instructions (3)
forester/src/main.rs

📄 CodeRabbit inference engine (forester/README.md)

Required configuration must include: --rpc-url, --ws-rpc-url, --indexer-url, --prover-url, --payer, and --derivation parameters

Files:

  • forester/src/main.rs
programs/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests in programs must not depend on light-test-utils; integration tests must be located in program-tests/

Files:

  • programs/registry/src/compressible/compress_and_close.rs
forester/**/*e2e*.rs

📄 CodeRabbit inference engine (forester/README.md)

forester/**/*e2e*.rs: Test environment variables should use TEST_MODE to specify 'local' or 'devnet' mode (default: devnet)
Test feature flags TEST_V1_STATE, TEST_V2_STATE, TEST_V1_ADDRESS, and TEST_V2_ADDRESS should default to true and control which test scenarios run
Devnet mode tests require PHOTON_RPC_URL, PHOTON_WSS_RPC_URL, PHOTON_INDEXER_URL, PHOTON_PROVER_URL, and PHOTON_API_KEY environment variables
Local validator mode tests should automatically spawn a local validator, start a local prover service, and use predefined local URLs (localhost:8899 for RPC, localhost:8784 for indexer)
Tests should automatically skip minting tokens, executing transactions, and root verification for disabled test types

Files:

  • forester/tests/e2e_test.rs
🧠 Learnings (98)
📓 Common learnings
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Account closure must distribute lamports according to: Solana rent exemption → returned to user, completed epoch rent → rent recipient, partial epoch rent → user, compression incentive → forester node
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/queue.rs : Output queues must store compressed account hashes in value vectors (one per batch) enabling access by leaf index before tree insertion
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Accounts become compressible when they lack rent for the current epoch plus the next epoch (compressibility window).
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run batched tree transfer test using `cargo test-sbf -p compressed-token-test -- test_transfer_with_photon_and_batched_tree` and apply retry logic in CI (max 3 attempts, 5s delay) due to known flakiness

Applied to files:

  • forester/tests/test_batch_append_spent.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Account closure must distribute lamports according to: Solana rent exemption → returned to user, completed epoch rent → rent recipient, partial epoch rent → user, compression incentive → forester node

Applied to files:

  • forester/tests/test_batch_append_spent.rs
  • forester/src/main.rs
  • forester/src/lib.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:02:15.670Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:15.670Z
Learning: Applies to programs/registry/src/account_compression_cpi/mod.rs : Export new wrapper modules in `account_compression_cpi/mod.rs` using `pub mod new_operation;` and `pub use new_operation::*;`, then import in `lib.rs`

Applied to files:

  • forester/src/compressible/mod.rs
  • forester/src/lib.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/mod.rs : Module declaration should be kept in `mod.rs`

Applied to files:

  • forester/src/compressible/mod.rs
  • forester/src/main.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/config.rs : CompressibleConfig account structure must support serialization via Anchor, Pinocchio, and Borsh formats for Light Registry program integration

Applied to files:

  • forester/src/compressible/mod.rs
  • forester/src/lib.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/variant_enum.rs : Account variant enum (`CompressedAccountVariant`) generation and `CompressedAccountData` wrapper struct should be implemented in `variant_enum.rs`

Applied to files:

  • forester/src/compressible/mod.rs
  • programs/registry/src/compressible/compress_and_close.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement state validation methods (`validate_active`, `validate_not_inactive`) on CompressibleConfig account structure

Applied to files:

  • forester/src/compressible/mod.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Implement account compressibility states in the following order: Funded (rent for current + 1 epoch) → Compressible (lacks rent for current + 1 epoch) → Claimable (funded but past epochs unclaimed)

Applied to files:

  • forester/src/compressible/mod.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement PDA derivation methods (`derive_pda`, `derive_v1_config_pda`) on CompressibleConfig for account discovery

Applied to files:

  • forester/src/compressible/mod.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-12-07T18:09:57.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-12-07T18:09:57.230Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Anchor deserialization of CompressibleConfig must use `AccountDeserialize::try_deserialize()` which automatically validates the discriminator to prevent invalid account type mismatches

Applied to files:

  • forester/src/compressible/mod.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/Cargo.toml : Depend on light-compressed-account crate for compressed account types and utilities

Applied to files:

  • forester/src/compressible/mod.rs
  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/decompress_context.rs : Decompression trait implementation (`DecompressContext`) with account accessors, PDA/token separation logic, and token processing delegation should be in `decompress_context.rs`

Applied to files:

  • forester/src/compressible/mod.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
📚 Learning: 2025-12-07T18:09:57.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-12-07T18:09:57.230Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : CompressibleConfig account state in Solana programs must validate active state using `validate_active()` method before allowing new compressible token account creation

Applied to files:

  • forester/src/compressible/mod.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/pack_unpack.rs : Pubkey compression logic and `PackedXxx` struct generation with Pack/Unpack trait implementations should be in `pack_unpack.rs`

Applied to files:

  • forester/src/main.rs
  • forester/src/compressible/compressor.rs
  • programs/registry/src/compressible/compress_and_close.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/traits.rs : Core trait implementations (`HasCompressionInfo`, `CompressAs`, `Compressible`) should be defined in `traits.rs`

Applied to files:

  • forester/src/main.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement default initialization for CToken V1 config in CompressibleConfig structure

Applied to files:

  • forester/src/main.rs
  • forester/src/compressible/config.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Charge rollover fee when creating output compressed accounts (insertion into output queue), not on tree operations

Applied to files:

  • forester/src/compressible/compressor.rs
  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/instructions.rs : Compress/decompress instruction handlers and context struct generation should be implemented in `instructions.rs`, with compress using PDA-only and decompress supporting full PDA + ctoken

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:02:15.670Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:15.670Z
Learning: Applies to programs/registry/src/account_compression_cpi/*.rs : Create wrapper instruction module at `src/account_compression_cpi/new_operation.rs` with `NewOperationContext` struct defining required accounts

Applied to files:

  • forester/src/compressible/compressor.rs
  • programs/registry/src/compressible/compress_and_close.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/queue.rs : Output queues must store compressed account hashes in value vectors (one per batch) enabling access by leaf index before tree insertion

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run account-compression tests using `cargo test-sbf -p account-compression-test` to test core account compression program (Merkle tree management)

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Compute and store hashed pubkeys by hashing and truncating to 31 bytes for bn254 field compatibility in both queue and tree accounts

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:57:53.312Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/TREE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:53.312Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/*.rs : When deserializing BatchedMerkleTreeAccount in Solana programs, use `BatchedMerkleTreeAccount::state_from_account_info()` for state trees and `BatchedMerkleTreeAccount::address_from_account_info()` for address trees

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:20.711Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_ADDRESS_TREE.md:0-0
Timestamp: 2025-11-24T17:56:20.711Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_address_tree.rs : `InitAddressTreeAccountsInstructionData` struct in `src/initialize_address_tree.rs` must include: height (u32, default 40), index (u64), root_history_capacity (u32, default 200), input_queue_batch_size (u64, default 15,000), input_queue_zkp_batch_size (u64, default 250), bloom_filter_capacity (u64, default batch_size * 8), bloom_filter_num_iters (u64, default 3 for test/10 for production), program_owner (Option<Pubkey>), forester (Option<Pubkey>), rollover_threshold (Option<u64>, default 95%), network_fee (Option<u64>, default 10,000 lamports), and close_threshold (Option<u64>).

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Use `check_account_balance_is_rent_exempt` function from `light-account-checks` to verify rent exemption for both queue_account and merkle_tree_account during initialization

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:59:03.485Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/ACCOUNT_INFO_TRAIT.md:0-0
Timestamp: 2025-11-24T17:59:03.485Z
Learning: Applies to program-libs/account-checks/docs/program-libs/account-checks/src/account_info/solana.rs : Use `std::cell::Ref` and `std::cell::RefMut` for DataRef and DataRefMut associated types when implementing AccountInfoTrait for solana-program SDK

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:57:53.312Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/TREE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:53.312Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/*.rs : Account validation for state trees must check: (1) account ownership by Light account compression program, (2) account discriminator is `BatchMta`, and (3) tree type is `STATE_MERKLE_TREE_TYPE_V2` (4)

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Define tree configuration parameters in `InitStateTreeAccountsInstructionData` struct: height (u32, default 32), index (u64), and root_history_capacity (u32, default 200)

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: State and instruction data structures must be defined in the separate 'light-ctoken-interface' crate (program-libs/ctoken-types/) to allow SDKs to import types without pulling in program dependencies

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:57:39.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/QUEUE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:39.230Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Validate account ownership by Light account compression program using `check_owner` from `light-account-checks` when deserializing `BatchedQueueAccount` with `output_from_account_info`

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: Applies to programs/compressed-token/program/src/close_token_account.rs : Close token account instruction must return rent exemption to rent recipient if compressible and remaining lamports to destination account

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:59:03.485Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/ACCOUNT_INFO_TRAIT.md:0-0
Timestamp: 2025-11-24T17:59:03.485Z
Learning: Applies to program-libs/account-checks/docs/program-libs/account-checks/src/account_info/{solana,pinocchio}.rs : Implement AccountInfoTrait with SDK-specific Pubkey types: `solana_pubkey::Pubkey` for solana-program feature and `[u8; 32]` raw bytes for pinocchio feature

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:58:35.079Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:35.079Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In `src/merkle_tree.rs`, implement `BatchedMerkleTreeAccount::update_tree_from_output_queue_account` method that batch appends values from output queue to state Merkle tree with ZKP verification, verifying proof of old_root + queue_values → new_root

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Set output queue account discriminator to b`queueacc` (8 bytes) and initialize queue metadata with QueueType::OutputStateV2

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Associate output queue with merkle_tree_account pubkey in queue metadata and calculate rollover_fee based on rollover_threshold, height, and total rent (merkle_tree_rent + additional_bytes_rent + queue_rent)

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Initialize an output queue account as `BatchedQueueAccount` with `QueueType::OutputStateV2`, temporary storage for compressed account hashes before tree insertion with immediate spending capability via proof-by-index, using discriminator b`queueacc` [113, 117, 101, 117, 101, 97, 99, 99]

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/merkle_tree.rs : Tree updates from output queue must use BatchedMerkleTreeAccount::update_tree_from_output_queue_account method with ZKP verification

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/merkle_tree.rs : Tree updates from input queue must use update_tree_from_input_queue function for state trees and update_tree_from_address_queue for address trees with ZKP verification

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Associate state tree with queue_account pubkey in tree metadata and set rollover_fee to 0 (charged on queue insertion, not tree operations)

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Initialize output queue with 2 alternating batches, each with batch_size = output_queue_batch_size and zkp_batch_size = output_queue_zkp_batch_size

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:58:35.079Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:35.079Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : BatchedMerkleTreeAccount must be of type `TreeType::StateV2` when updating tree from output queue

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/initialize_state_tree.rs : State tree initialization must create two Solana accounts: BatchedMerkleTreeAccount with integrated input queue and separate BatchedQueueAccount

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T18:02:15.670Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:15.670Z
Learning: Applies to programs/registry/src/lib.rs : In wrapper instruction handler in `lib.rs`, load account metadata, determine work units, call `check_forester()`, then call the processing function

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: Applies to programs/compressed-token/program/src/create_token_account.rs : Create token account instructions (CreateTokenAccount, CreateAssociatedCTokenAccount, CreateAssociatedTokenAccountIdempotent) require ACTIVE config validation only

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: Applies to programs/compressed-token/program/src/ctoken_transfer.rs : CTokenTransfer instruction (discriminator: 3) must implement SPL-compatible transfers between decompressed accounts

Applied to files:

  • forester/src/compressible/compressor.rs
  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:58:35.079Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:35.079Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : In `src/queue.rs`, define BatchedQueueAccount layout and implement `mark_as_inserted_in_merkle_tree` method to increment `num_inserted_zkp_batches` and transition batch state to `Inserted` when all ZKP batches are complete

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:53:53.971Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: forester/README.md:0-0
Timestamp: 2025-11-24T17:53:53.971Z
Learning: Applies to forester/src/**/*{auth,key,keypair}*.rs : The `FORESTER_KEYPAIR` environment variable should support both base58 format and byte array format like `[1,2,3,...]` for keypair specification

Applied to files:

  • forester/Cargo.toml
📚 Learning: 2025-12-07T03:17:28.794Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-07T03:17:28.794Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/Cargo.toml : Use path references in Cargo.toml dependencies pointing to `/Users/ananas/dev/light-protocol2/sdk-libs/` for light-ctoken-sdk, light-ctoken-types, light-sdk, light-sdk-types, and light-program-test

Applied to files:

  • forester/Cargo.toml
📚 Learning: 2025-11-24T17:53:53.971Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: forester/README.md:0-0
Timestamp: 2025-11-24T17:53:53.971Z
Learning: Applies to forester/src/**/*{transaction,batch}*.rs : Transaction V1 processing should configure `--max-concurrent-sends 50`, `--legacy-ixs-per-tx 1`, `--transaction-max-concurrent-batches 20`, `--cu-limit 1000000`, and `--enable-priority-fees false` by default

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Validate that ZKP batch sizes must be 10 or 500 (only supported circuit sizes)

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Define batch size parameters in `InitStateTreeAccountsInstructionData` struct: input_queue_batch_size (u64, default 15,000), output_queue_batch_size (u64, default 15,000), input_queue_zkp_batch_size (u64, default 500), and output_queue_zkp_batch_size (u64, default 500)

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Define bloom filter configuration for input queue: bloom_filter_capacity (u64, default batch_size * 8) and bloom_filter_num_iters (u64, default 3 for test and 10 for production)

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-12-07T18:09:57.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-12-07T18:09:57.230Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : When deserializing CompressibleConfig accounts, skip the 8-byte discriminator `[180, 4, 231, 26, 220, 144, 55, 168]` before deserialization in zero-copy implementations using bytemuck::pod_from_bytes

Applied to files:

  • forester/src/compressible/config.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-12-07T18:09:57.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-12-07T18:09:57.230Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : CompressibleConfig PDA must be derived using seeds `[b"compressible_config", version.to_le_bytes()]` with the stored bump seed for deterministic account address generation in Light Protocol

Applied to files:

  • forester/src/compressible/config.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:53:53.971Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: forester/README.md:0-0
Timestamp: 2025-11-24T17:53:53.971Z
Learning: Applies to forester/src/**/*{pool,connection,rpc}*.rs : RPC pool settings should use `--rpc-pool-size 10` (default), `--rpc-pool-connection-timeout-secs 15`, and `--rpc-pool-idle-timeout-secs 300` for optimal connection pooling

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Validate that bloom filter capacity must be divisible by 8 and must be >= batch_size * 8

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:56:20.711Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_ADDRESS_TREE.md:0-0
Timestamp: 2025-11-24T17:56:20.711Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_address_tree.rs : ZKP batch sizes for address trees must be 10 or 250 in `src/initialize_address_tree.rs`. Only these circuit sizes are supported for address trees.

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:56:20.711Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_ADDRESS_TREE.md:0-0
Timestamp: 2025-11-24T17:56:20.711Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_address_tree.rs : Validate bloom_filter_capacity is divisible by 8 in `src/initialize_address_tree.rs`. Capacity must be >= batch_size * 8.

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run compressed token core tests using `cargo test-sbf -p compressed-token-test --test ctoken`, `--test v1`, `--test mint`, and `--test transfer2`

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run Light system program compression tests using `cargo test-sbf -p system-test -- test_with_compression` and `cargo test-sbf -p system-test --test test_re_init_cpi_account` to test compressed account operations

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
📚 Learning: 2025-12-07T03:17:28.794Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-07T03:17:28.794Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/{lib,main}.rs : Clone AccountInfo structs when building CPI builder pattern account structs to avoid borrow checker issues

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
📚 Learning: 2025-12-06T00:49:57.458Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-token-test/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:57.458Z
Learning: Applies to sdk-tests/sdk-token-test/**/*test.rs : Tests should use light-ctoken-sdk functions from sdk-libs/compressed-token-sdk for testing ctoken instructions

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/rent.rs : Implement rent calculation functions including `rent_curve_per_epoch`, `calculate_rent_and_balance`, `claimable_lamports`, and `calculate_close_lamports` in rent.rs

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `claimable_lamports` function to return None if account is compressible, otherwise return Some(amount) for completed epochs only (excluding current ongoing epoch).

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_close_lamports` function to return (u64, u64) tuple splitting lamports between rent recipient and user, with rent recipient receiving completed epochs and user receiving partial epoch remainder.

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Light Protocol accounts must satisfy both Solana rent exemption and Light Protocol rent requirements, plus an 11,000 lamport compression incentive during creation

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: Applies to programs/compressed-token/program/src/transfer2/*.rs : Transfer2 instruction (discriminator: 101) supports batch operations including Compress, Decompress, and CompressAndClose with multi-mint support and sum checks

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
📚 Learning: 2025-11-24T18:01:54.689Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:54.689Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLOSE_TOKEN_ACCOUNT.md : Close Token Account documentation must cover closing decompressed token accounts with rent distribution

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
📚 Learning: 2025-12-07T03:17:42.199Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-12-07T03:17:42.199Z
Learning: Applies to program-libs/account-checks/**/*.rs : Use AccountInfoTrait abstraction for unified account handling across both solana-program and pinocchio SDKs

Applied to files:

  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:58:50.237Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/ACCOUNT_CHECKS.md:0-0
Timestamp: 2025-11-24T17:58:50.237Z
Learning: Applies to program-libs/account-checks/docs/program-libs/account-checks/src/checks.rs : Use generic `AccountInfoTrait` parameter for all account validation functions to enable compatibility with both Solana and Pinocchio runtimes

Applied to files:

  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:54:33.614Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/anchor/README.md:0-0
Timestamp: 2025-11-24T17:54:33.614Z
Learning: Implement the Compressed Token Program interface for creating and using compressed tokens on Solana with ZK Compression

Applied to files:

  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: All compressed token account implementations must reference and comply with the account layout specifications in programs/compressed-token/program/docs/ACCOUNTS.md

Applied to files:

  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:58:10.392Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:10.392Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In src/merkle_tree.rs, implement BatchedMerkleTreeAccount::update_tree_from_address_queue method for batch address append operations on AddressV2 trees. The method must verify ZKP proving correctness of: old_root + queue addresses → new_root using indexed Merkle tree insertion, update tree root, increment tree sequence_number, increment tree next_index by zkp_batch_size, mark ZKP batch as inserted, transition batch state to Inserted when all ZKP batches complete, and zero out bloom filter when current batch is 50% inserted.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/rollover_{state,address}_tree.rs : Trees must support rollover when reaching capacity (2^height leaves) by creating a new tree and marking the old tree as rolled over, preserving old tree roots

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:10.392Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:10.392Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In src/merkle_tree.rs, implement BatchedMerkleTreeAccount::update_tree_from_input_queue method for batch nullify operations on StateV2 trees. The method must verify ZKP proving correctness of: old_root + queue nullifiers → new_root, update tree root, increment tree sequence_number, increment tree nullifier_next_index by zkp_batch_size, mark ZKP batch as inserted, transition batch state to Inserted when all ZKP batches complete, and zero out bloom filter when current batch is 50% inserted.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:39.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/QUEUE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:39.230Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Store compressed account hashes in `BatchedQueueAccount` value vectors for immediate proof-by-index access before tree insertion

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:02:15.670Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:15.670Z
Learning: When forester PDA is present, `check_forester()` must validate epoch registration and eligibility, track work, and require network fee; when absent, validate that authority matches the tree's designated forester (for private trees)

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:35.079Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:35.079Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : Transition batch state to `Inserted` when all ZKP batches are complete and increment `pending_batch_index` to switch to other batch

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:10.392Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:10.392Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : Batch nullify operations must check that tree type is TreeType::StateV2 before processing, verify batch has ready ZKP batches (num_full_zkp_batches > num_inserted_zkp_batches), and reject if batch is already in Inserted state.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:20.711Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_ADDRESS_TREE.md:0-0
Timestamp: 2025-11-24T17:56:20.711Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_address_tree.rs : Set tree_type to `TreeType::AddressV2` (5) and associated_queue to Pubkey::default() for address trees in `src/initialize_address_tree.rs`. Address trees have no separate output queue - the address queue is integrated into the tree account.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Initialize a state Merkle tree with a `TreeType::StateV2` (4) tree type, storing tree roots, root history, and integrated input queue (bloom filters + hash chains for nullifiers) in the `BatchedMerkleTreeAccount` with discriminator b`BatchMta` [66, 97, 116, 99, 104, 77, 116, 97]

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:14.561Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:14.561Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In `BatchedMerkleTreeAccount::insert_nullifier_into_queue`, verify tree type is `TreeType::StateV2` before allowing nullifier insertion; reject address trees

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:02.558Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_ADDRESS_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:02.558Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In `BatchedMerkleTreeAccount::insert_address_into_queue`, verify that the tree type is `TreeType::AddressV2` before proceeding with address insertion. Reject state trees with `MerkleTreeMetadataError::InvalidTreeType`.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:10.392Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:10.392Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : Batch address append operations must check that tree type is TreeType::AddressV2 before processing, verify tree capacity constraint (tree.next_index + zkp_batch_size <= tree_capacity), verify batch has ready ZKP batches (num_full_zkp_batches > num_inserted_zkp_batches), and reject if batch is already in Inserted state.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/error.rs : PropagateHasher errors from light-hasher module with 7xxx code range in error handling

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:39.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/QUEUE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:39.230Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Check `tree_capacity` (2^height) against new insertions to prevent overflow in `BatchedQueueAccount`

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_rent_and_balance` function to determine compressibility by checking if account balance covers required rent for epochs since last claim, returning (bool, u64) tuple.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Accounts become compressible when they lack rent for the current epoch plus the next epoch (compressibility window).

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `get_last_funded_epoch` function to determine the last epoch number covered by rent payments.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-12-07T18:09:57.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-12-07T18:09:57.230Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : CompressibleConfig rent_sponsor PDA and compression_authority PDA must be derived separately using `get_rent_sponsor_seeds()` and `get_compression_authority_seeds()` helper methods with version-specific seeds

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:24.369Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:24.369Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Insert Into Output Queue: Inserts a compressed account hash into the output queue's currently processing batch by calling `BatchedQueueAccount::insert_into_current_batch` with hash_chain_value and current_slot parameters, updating value vec, hash chain, and managing batch state transitions in src/queue.rs

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:39.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/QUEUE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:39.230Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Use two value vectors (`[ZeroCopyVecU64<[u8; 32]>; 2]`), one per batch, to store compressed account hashes in `BatchedQueueAccount`

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:14.561Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:14.561Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In `BatchedMerkleTreeAccount::insert_nullifier_into_queue`, insert compressed_account_hash into bloom filter (NOT the nullifier) for non-inclusion checks in subsequent transactions

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:14.561Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:14.561Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In `BatchedMerkleTreeAccount::insert_nullifier_into_queue`, perform non-inclusion check to ensure compressed_account_hash does not exist in any bloom filter to prevent double-spending

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:02.558Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_ADDRESS_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:02.558Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : After inserting an address into the batch, check if `num_inserted_elements == batch_size`. If true, transition batch state from `Fill` to `Full`, increment `currently_processing_batch_index` to switch to the other batch, and update `pending_batch_index` to mark this batch ready for tree update.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:24.369Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:24.369Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Transition batch state from `Fill` to `Full` and increment currently_processing_batch_index when num_inserted_elements reaches batch_size in the output queue

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:35.079Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:35.079Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : Batch must have ready ZKP batches for insertion: verify `num_full_zkp_batches > num_inserted_zkp_batches`; error with `BatchNotReady` (14301) if not ready

Applied to files:

  • forester/src/epoch_manager.rs
🧬 Code graph analysis (4)
forester/src/main.rs (1)
forester/src/errors.rs (1)
  • channel (208-212)
forester/src/lib.rs (1)
forester/src/compressible/subscriber.rs (2)
  • new (36-46)
  • new (175-185)
forester/tests/test_compressible_ctoken.rs (2)
forester/src/compressible/subscriber.rs (2)
  • new (36-46)
  • new (175-185)
forester/src/compressible/state.rs (1)
  • new (59-63)
forester/src/compressible/subscriber.rs (2)
forester/src/compressible/state.rs (1)
  • new (59-63)
forester/src/compressible/bootstrap.rs (1)
  • pubkey_str (54-54)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: Test program-libs-slow
  • GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
  • GitHub Check: programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test", "cargo...
  • GitHub Check: programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-prog...
  • GitHub Check: Forester e2e test

Comment on lines +241 to +285
fn handle_log_notification(&self, response: RpcResponse<RpcLogsResponse>) {
let logs_response = response.value;

// Skip failed transactions
if logs_response.err.is_some() {
debug!("Skipping failed transaction {}", logs_response.signature);
return;
}

// Parse logs looking for compress_and_close entries
let mut removed_count = 0;
for log in &logs_response.logs {
// Look for our log prefix: "Program log: compress_and_close:<pubkey>"
// The actual log format is "Program log: compress_and_close:<pubkey>"
if let Some(pubkey_str) = log
.strip_prefix("Program log: ")
.and_then(|s| s.strip_prefix(COMPRESS_AND_CLOSE_LOG_PREFIX))
{
match Pubkey::from_str(pubkey_str) {
Ok(pubkey) => {
if self.tracker.remove(&pubkey).is_some() {
debug!(
"Removed closed account {} from tracker (compress_and_close log)",
pubkey
);
removed_count += 1;
}
}
Err(e) => {
error!(
"Invalid pubkey in compress_and_close log '{}': {}",
pubkey_str, e
);
}
}
}
}

if removed_count > 0 {
info!(
"Removed {} closed accounts from transaction {}",
removed_count, logs_response.signature
);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for the log format in the registry program source
rg -n "compress_and_close:" --type rust

Repository: Lightprotocol/light-protocol

Length of output: 1734


Log parsing is robust but tightly coupled to log format.

The log parsing logic correctly:

  1. Skips failed transactions
  2. Strips the "Program log: " prefix before checking for the close prefix
  3. Handles invalid pubkey parsing with error logging
  4. Tracks removed accounts for batch logging

The log format "Program log: compress_and_close:<pubkey>" is an implicit contract with the registry program (emitted via msg!() in programs/registry/src/compressible/compress_and_close.rs). If the registry changes its log format, this will silently stop working. Consider adding a metric or periodic health check to verify the subscriber is still receiving expected events.

Comment on lines +930 to +946

if self.compressible_tracker.is_some() && self.config.compressible_config.is_some() {
let compression_tree_accounts = TreeAccounts {
merkle_tree: solana_sdk::pubkey::Pubkey::default(),
queue: solana_sdk::pubkey::Pubkey::default(),
tree_type: TreeType::Unknown,
is_rolledover: false,
};
let tree_schedule = TreeForesterSchedule::new_with_schedule(
&compression_tree_accounts,
slot,
&epoch_info.forester_epoch_pda,
&epoch_info.epoch_pda,
)?;
epoch_info.trees.insert(0, tree_schedule);
debug!("Added compression tree to epoch {}", epoch_info.epoch.epoch);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Compression tree scheduling uses TreeType::Unknown as a marker.

This pattern uses TreeType::Unknown with default pubkeys to represent a synthetic "compression tree" in the schedule. While functional, this semantic overloading could confuse future maintainers who expect Unknown to mean "unrecognized type."

Consider introducing a dedicated TreeType::Compression variant or documenting this convention prominently. For now, should_skip_tree at line 2263 correctly returns false for Unknown, ensuring compression is never skipped.

🤖 Prompt for AI Agents
In forester/src/epoch_manager.rs around lines 930 to 946, the code uses
TreeType::Unknown as a marker for synthetic compression trees which overloads
the meaning of Unknown; change this by adding a dedicated TreeType::Compression
enum variant (and update any serialization/deserialization, From/Into,
Display/Debug impls and pattern matches) and replace TreeType::Unknown with
TreeType::Compression when constructing the compression_tree_accounts; also
update should_skip_tree and any match arms that rely on Unknown so semantics
remain correct, run CI/tests to ensure no other match exhaustiveness or
(de)serialization breaks.

Comment on lines +56 to +64
// Emit logs for closed accounts (used by forester to track closures)
for idx in &indices {
if let Ok(source_account) = transfer2_accounts
.packed_accounts
.get_u8(idx.source_index, "source_account")
{
msg!("compress_and_close:{}", source_account.key);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Logs emitted before operation completes, risking false-positive tracking.

The closure logs are emitted before the actual invoke_signed CPI call (lines 84-88). If the CPI fails for any reason (e.g., validation errors, insufficient compute, failed constraints), the forester LogSubscriber will have already received closure events for accounts that were never actually closed. This creates a dangerous inconsistency between the forester's tracked state and the actual on-chain state.

Move the logging loop to execute after the successful CPI call:

-    // Emit logs for closed accounts (used by forester to track closures)
-    for idx in &indices {
-        if let Ok(source_account) = transfer2_accounts
-            .packed_accounts
-            .get_u8(idx.source_index, "source_account")
-        {
-            msg!("compress_and_close:{}", source_account.key);
-        }
-    }
-
     let instruction = compress_and_close_ctoken_accounts_with_indices(
         ctx.accounts.authority.key(),
         authority_index,
         destination_index,
         &indices,
         &transfer2_accounts.packed_accounts,
     )?;
 
     // Prepare signer seeds for compression_authority PDA
     let version_bytes = ctx.accounts.compressible_config.version.to_le_bytes();
     let compression_authority_bump = ctx.accounts.compressible_config.compression_authority_bump;
     let signer_seeds = &[
         b"compression_authority".as_slice(),
         version_bytes.as_slice(),
         &[compression_authority_bump],
     ];
 
     // Execute CPI with compression_authority PDA as signer
     anchor_lang::solana_program::program::invoke_signed(
         &instruction,
         transfer2_accounts.to_account_infos().as_slice(),
         &[signer_seeds],
     )?;
+
+    // Emit logs for closed accounts (used by forester to track closures)
+    for idx in &indices {
+        if let Ok(source_account) = transfer2_accounts
+            .packed_accounts
+            .get_u8(idx.source_index, "source_account")
+        {
+            msg!("compress_and_close:{}", source_account.key);
+        }
+    }
 
     Ok(())
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Emit logs for closed accounts (used by forester to track closures)
for idx in &indices {
if let Ok(source_account) = transfer2_accounts
.packed_accounts
.get_u8(idx.source_index, "source_account")
{
msg!("compress_and_close:{}", source_account.key);
}
}
🤖 Prompt for AI Agents
In programs/registry/src/compressible/compress_and_close.rs around lines 56-64
(and noting the CPI call at ~84-88), the loop that emits "compress_and_close"
logs currently runs before the invoke_signed CPI, which can produce
false-positive closure events if the CPI fails; move that entire logging loop so
it runs immediately after the invoke_signed call and only when the CPI returns
Ok, preserving the same indices and transfer2_accounts variables and scopes;
ensure no early returns or error paths execute the logging and keep the log
format unchanged so forester receives events only for actually completed
closures.

Comment on lines +57 to +64
for idx in &indices {
if let Ok(source_account) = transfer2_accounts
.packed_accounts
.get_u8(idx.source_index, "source_account")
{
msg!("compress_and_close:{}", source_account.key);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Silent error handling could cause missed closure tracking events.

The if let Ok(...) pattern silently skips any account that fails retrieval via get_u8. Since these logs are explicitly used by the forester to track closures (as noted in the comment), silently dropping failed retrievals means the forester could miss accounts that were actually closed if the index references were malformed or if account access failed for other reasons.

Consider whether this silent failure is acceptable for your monitoring requirements. If the forester must track all closures reliably, you should either:

  1. Log a warning when retrieval fails (to aid debugging), or
  2. Propagate the error to fail fast if an invalid index is provided

Apply this diff if you want to log retrieval failures for observability:

     // Emit logs for closed accounts (used by forester to track closures)
     for idx in &indices {
-        if let Ok(source_account) = transfer2_accounts
+        match transfer2_accounts
             .packed_accounts
             .get_u8(idx.source_index, "source_account")
         {
-            msg!("compress_and_close:{}", source_account.key);
+            Ok(source_account) => {
+                msg!("compress_and_close:{}", source_account.key);
+            }
+            Err(e) => {
+                msg!("compress_and_close:failed_to_retrieve_account_at_index:{}", idx.source_index);
+            }
         }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for idx in &indices {
if let Ok(source_account) = transfer2_accounts
.packed_accounts
.get_u8(idx.source_index, "source_account")
{
msg!("compress_and_close:{}", source_account.key);
}
}
for idx in &indices {
match transfer2_accounts
.packed_accounts
.get_u8(idx.source_index, "source_account")
{
Ok(source_account) => {
msg!("compress_and_close:{}", source_account.key);
}
Err(e) => {
msg!("compress_and_close:failed_to_retrieve_account_at_index:{}", idx.source_index);
}
}
}
🤖 Prompt for AI Agents
In programs/registry/src/compressible/compress_and_close.rs around lines 57 to
64, the current if let Ok(...) silently ignores failures from
transfer2_accounts.packed_accounts.get_u8(...), which can hide missing closure
events; change the code to handle the Err branch: match on the Result and on Ok
log the source_account.key as before, and on Err call msg! to emit a warning
including the offending index and the error (or alternatively return/propagate
the error if you want fail-fast behavior); this preserves existing behavior for
successful reads while making retrieval failures observable for the forester.

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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
forester/src/epoch_manager.rs (1)

2257-2265: Consider adding test coverage for TreeType::Unknown handling.

The function correctly returns false for Unknown, ensuring compression trees are never skipped. However, the existing tests don't cover this case. A simple addition would strengthen confidence:

+    #[test]
+    fn test_should_skip_tree_unknown_never_skipped() {
+        // Even with all skip flags enabled, Unknown (compression) should never be skipped
+        let config = create_test_config_with_skip_flags(true, true, true, true);
+        assert!(!should_skip_tree(&config, &TreeType::Unknown));
+    }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d64a75 and 6f2821f.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock and included by none
  • xtask/src/create_ctoken_account.rs is excluded by none and included by none
📒 Files selected for processing (13)
  • forester/Cargo.toml (1 hunks)
  • forester/src/compressible/compressor.rs (5 hunks)
  • forester/src/compressible/config.rs (1 hunks)
  • forester/src/compressible/mod.rs (1 hunks)
  • forester/src/compressible/state.rs (0 hunks)
  • forester/src/compressible/subscriber.rs (3 hunks)
  • forester/src/epoch_manager.rs (9 hunks)
  • forester/src/lib.rs (3 hunks)
  • forester/src/main.rs (1 hunks)
  • forester/tests/e2e_test.rs (1 hunks)
  • forester/tests/test_batch_append_spent.rs (1 hunks)
  • forester/tests/test_compressible_ctoken.rs (3 hunks)
  • programs/registry/src/compressible/compress_and_close.rs (1 hunks)
💤 Files with no reviewable changes (1)
  • forester/src/compressible/state.rs
🧰 Additional context used
📓 Path-based instructions (3)
programs/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests in programs must not depend on light-test-utils; integration tests must be located in program-tests/

Files:

  • programs/registry/src/compressible/compress_and_close.rs
forester/src/main.rs

📄 CodeRabbit inference engine (forester/README.md)

Required configuration must include: --rpc-url, --ws-rpc-url, --indexer-url, --prover-url, --payer, and --derivation parameters

Files:

  • forester/src/main.rs
forester/**/*e2e*.rs

📄 CodeRabbit inference engine (forester/README.md)

forester/**/*e2e*.rs: Test environment variables should use TEST_MODE to specify 'local' or 'devnet' mode (default: devnet)
Test feature flags TEST_V1_STATE, TEST_V2_STATE, TEST_V1_ADDRESS, and TEST_V2_ADDRESS should default to true and control which test scenarios run
Devnet mode tests require PHOTON_RPC_URL, PHOTON_WSS_RPC_URL, PHOTON_INDEXER_URL, PHOTON_PROVER_URL, and PHOTON_API_KEY environment variables
Local validator mode tests should automatically spawn a local validator, start a local prover service, and use predefined local URLs (localhost:8899 for RPC, localhost:8784 for indexer)
Tests should automatically skip minting tokens, executing transactions, and root verification for disabled test types

Files:

  • forester/tests/e2e_test.rs
🧠 Learnings (98)
📓 Common learnings
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:54.689Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLOSE_TOKEN_ACCOUNT.md : Close Token Account documentation must cover closing decompressed token accounts with rent distribution
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-07T03:17:28.794Z
Learning: Use compressible token account extensions that allow accounts to be compressed back into compressed state with rent payment mechanisms
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Account closure must distribute lamports according to: Solana rent exemption → returned to user, completed epoch rent → rent recipient, partial epoch rent → user, compression incentive → forester node
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: All compressed token account implementations must reference and comply with the account layout specifications in programs/compressed-token/program/docs/ACCOUNTS.md
📚 Learning: 2025-11-24T18:02:15.670Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:15.670Z
Learning: Applies to programs/registry/src/account_compression_cpi/*.rs : Create wrapper instruction module at `src/account_compression_cpi/new_operation.rs` with `NewOperationContext` struct defining required accounts

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T18:02:15.670Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:15.670Z
Learning: Applies to programs/registry/src/account_compression_cpi/mod.rs : Export new wrapper modules in `account_compression_cpi/mod.rs` using `pub mod new_operation;` and `pub use new_operation::*;`, then import in `lib.rs`

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/mod.rs
  • forester/src/main.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: Applies to programs/compressed-token/program/src/close_token_account.rs : Close token account instruction must return rent exemption to rent recipient if compressible and remaining lamports to destination account

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Implement account compressibility states in the following order: Funded (rent for current + 1 epoch) → Compressible (lacks rent for current + 1 epoch) → Claimable (funded but past epochs unclaimed)

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/mod.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Account closure must distribute lamports according to: Solana rent exemption → returned to user, completed epoch rent → rent recipient, partial epoch rent → user, compression incentive → forester node

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/lib.rs
  • forester/src/main.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:02:15.670Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:15.670Z
Learning: Applies to programs/registry/src/account_compression_cpi/*.rs : Implement `process_new_operation()` function in wrapper module to handle PDA signer setup, account mapping, and CPI execution

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/variant_enum.rs : Account variant enum (`CompressedAccountVariant`) generation and `CompressedAccountData` wrapper struct should be implemented in `variant_enum.rs`

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/mod.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/config.rs : CompressibleConfig account structure must support serialization via Anchor, Pinocchio, and Borsh formats for Light Registry program integration

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/mod.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:21.501Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/ERRORS.md:0-0
Timestamp: 2025-11-24T18:00:21.501Z
Learning: Applies to program-libs/compressible/docs/program-libs/compressible/src/**/*.rs : InvalidState (Error Code 19002): For account creation, ensure CompressibleConfig state is `Active` (1). For other operations (claim, withdraw, compress & close), ensure config state is not `Inactive` (0). Validate config state using `config.validate_active()` for creation and `config.validate_not_inactive()` for other operations.

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
📚 Learning: 2025-11-24T17:59:54.233Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/PACKED_ACCOUNTS.md:0-0
Timestamp: 2025-11-24T17:59:54.233Z
Learning: Applies to program-libs/account-checks/docs/program-libs/account-checks/src/**/*.rs : Provide descriptive names in ProgramPackedAccounts error messages (e.g., 'token_mint' instead of 'account')

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: Applies to programs/compressed-token/program/src/ctoken_transfer.rs : CTokenTransfer instruction (discriminator: 3) must implement SPL-compatible transfers between decompressed accounts

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/compressor.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: Applies to programs/compressed-token/program/src/transfer2/*.rs : Transfer2 instruction (discriminator: 101) supports batch operations including Compress, Decompress, and CompressAndClose with multi-mint support and sum checks

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Charge rollover fee when creating output compressed accounts (insertion into output queue), not on tree operations

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:01:54.689Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:54.689Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLOSE_TOKEN_ACCOUNT.md : Close Token Account documentation must cover closing decompressed token accounts with rent distribution

Applied to files:

  • programs/registry/src/compressible/compress_and_close.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement default initialization for CToken V1 config in CompressibleConfig structure

Applied to files:

  • forester/src/compressible/config.rs
  • forester/src/main.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:53:53.971Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: forester/README.md:0-0
Timestamp: 2025-11-24T17:53:53.971Z
Learning: Applies to forester/src/**/*{transaction,batch}*.rs : Transaction V1 processing should configure `--max-concurrent-sends 50`, `--legacy-ixs-per-tx 1`, `--transaction-max-concurrent-batches 20`, `--cu-limit 1000000`, and `--enable-priority-fees false` by default

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Define bloom filter configuration for input queue: bloom_filter_capacity (u64, default batch_size * 8) and bloom_filter_num_iters (u64, default 3 for test and 10 for production)

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Define batch size parameters in `InitStateTreeAccountsInstructionData` struct: input_queue_batch_size (u64, default 15,000), output_queue_batch_size (u64, default 15,000), input_queue_zkp_batch_size (u64, default 500), and output_queue_zkp_batch_size (u64, default 500)

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-12-07T18:09:57.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-12-07T18:09:57.230Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : CompressibleConfig PDA must be derived using seeds `[b"compressible_config", version.to_le_bytes()]` with the stored bump seed for deterministic account address generation in Light Protocol

Applied to files:

  • forester/src/compressible/config.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Validate that ZKP batch sizes must be 10 or 500 (only supported circuit sizes)

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-12-07T18:09:57.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-12-07T18:09:57.230Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : When deserializing CompressibleConfig accounts, skip the 8-byte discriminator `[180, 4, 231, 26, 220, 144, 55, 168]` before deserialization in zero-copy implementations using bytemuck::pod_from_bytes

Applied to files:

  • forester/src/compressible/config.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Validate that bloom filter capacity must be divisible by 8 and must be >= batch_size * 8

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:56:20.711Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_ADDRESS_TREE.md:0-0
Timestamp: 2025-11-24T17:56:20.711Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_address_tree.rs : ZKP batch sizes for address trees must be 10 or 250 in `src/initialize_address_tree.rs`. Only these circuit sizes are supported for address trees.

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:56:20.711Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_ADDRESS_TREE.md:0-0
Timestamp: 2025-11-24T17:56:20.711Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_address_tree.rs : Validate bloom_filter_capacity is divisible by 8 in `src/initialize_address_tree.rs`. Capacity must be >= batch_size * 8.

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Initialize output queue with 2 alternating batches, each with batch_size = output_queue_batch_size and zkp_batch_size = output_queue_zkp_batch_size

Applied to files:

  • forester/src/compressible/config.rs
  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:53:53.971Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: forester/README.md:0-0
Timestamp: 2025-11-24T17:53:53.971Z
Learning: Applies to forester/src/**/*{pool,connection,rpc}*.rs : RPC pool settings should use `--rpc-pool-size 10` (default), `--rpc-pool-connection-timeout-secs 15`, and `--rpc-pool-idle-timeout-secs 300` for optimal connection pooling

Applied to files:

  • forester/src/compressible/config.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run batched tree transfer test using `cargo test-sbf -p compressed-token-test -- test_transfer_with_photon_and_batched_tree` and apply retry logic in CI (max 3 attempts, 5s delay) due to known flakiness

Applied to files:

  • forester/tests/test_batch_append_spent.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/instructions.rs : Compress/decompress instruction handlers and context struct generation should be implemented in `instructions.rs`, with compress using PDA-only and decompress supporting full PDA + ctoken

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/pack_unpack.rs : Pubkey compression logic and `PackedXxx` struct generation with Pack/Unpack trait implementations should be in `pack_unpack.rs`

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/compressible/mod.rs
  • forester/src/main.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement state validation methods (`validate_active`, `validate_not_inactive`) on CompressibleConfig account structure

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/mod.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run account-compression tests using `cargo test-sbf -p account-compression-test` to test core account compression program (Merkle tree management)

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/decompress_context.rs : Decompression trait implementation (`DecompressContext`) with account accessors, PDA/token separation logic, and token processing delegation should be in `decompress_context.rs`

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/mod.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Compute and store hashed pubkeys by hashing and truncating to 31 bytes for bn254 field compatibility in both queue and tree accounts

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/Cargo.toml : Depend on light-compressed-account crate for compressed account types and utilities

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/compressible/mod.rs
📚 Learning: 2025-11-24T17:57:53.312Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/TREE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:53.312Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/*.rs : When deserializing BatchedMerkleTreeAccount in Solana programs, use `BatchedMerkleTreeAccount::state_from_account_info()` for state trees and `BatchedMerkleTreeAccount::address_from_account_info()` for address trees

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:20.711Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_ADDRESS_TREE.md:0-0
Timestamp: 2025-11-24T17:56:20.711Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_address_tree.rs : `InitAddressTreeAccountsInstructionData` struct in `src/initialize_address_tree.rs` must include: height (u32, default 40), index (u64), root_history_capacity (u32, default 200), input_queue_batch_size (u64, default 15,000), input_queue_zkp_batch_size (u64, default 250), bloom_filter_capacity (u64, default batch_size * 8), bloom_filter_num_iters (u64, default 3 for test/10 for production), program_owner (Option<Pubkey>), forester (Option<Pubkey>), rollover_threshold (Option<u64>, default 95%), network_fee (Option<u64>, default 10,000 lamports), and close_threshold (Option<u64>).

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Use `check_account_balance_is_rent_exempt` function from `light-account-checks` to verify rent exemption for both queue_account and merkle_tree_account during initialization

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:59:03.485Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/ACCOUNT_INFO_TRAIT.md:0-0
Timestamp: 2025-11-24T17:59:03.485Z
Learning: Applies to program-libs/account-checks/docs/program-libs/account-checks/src/account_info/solana.rs : Use `std::cell::Ref` and `std::cell::RefMut` for DataRef and DataRefMut associated types when implementing AccountInfoTrait for solana-program SDK

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:57:53.312Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/TREE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:53.312Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/*.rs : Account validation for state trees must check: (1) account ownership by Light account compression program, (2) account discriminator is `BatchMta`, and (3) tree type is `STATE_MERKLE_TREE_TYPE_V2` (4)

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: State and instruction data structures must be defined in the separate 'light-ctoken-interface' crate (program-libs/ctoken-types/) to allow SDKs to import types without pulling in program dependencies

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Define tree configuration parameters in `InitStateTreeAccountsInstructionData` struct: height (u32, default 32), index (u64), and root_history_capacity (u32, default 200)

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:57:39.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/QUEUE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:39.230Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Validate account ownership by Light account compression program using `check_owner` from `light-account-checks` when deserializing `BatchedQueueAccount` with `output_from_account_info`

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:59:03.485Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/ACCOUNT_INFO_TRAIT.md:0-0
Timestamp: 2025-11-24T17:59:03.485Z
Learning: Applies to program-libs/account-checks/docs/program-libs/account-checks/src/account_info/{solana,pinocchio}.rs : Implement AccountInfoTrait with SDK-specific Pubkey types: `solana_pubkey::Pubkey` for solana-program feature and `[u8; 32]` raw bytes for pinocchio feature

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-12-07T18:09:57.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-12-07T18:09:57.230Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : CompressibleConfig account state in Solana programs must validate active state using `validate_active()` method before allowing new compressible token account creation

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/mod.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:35.079Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:35.079Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In `src/merkle_tree.rs`, implement `BatchedMerkleTreeAccount::update_tree_from_output_queue_account` method that batch appends values from output queue to state Merkle tree with ZKP verification, verifying proof of old_root + queue_values → new_root

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Set output queue account discriminator to b`queueacc` (8 bytes) and initialize queue metadata with QueueType::OutputStateV2

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Associate output queue with merkle_tree_account pubkey in queue metadata and calculate rollover_fee based on rollover_threshold, height, and total rent (merkle_tree_rent + additional_bytes_rent + queue_rent)

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Initialize an output queue account as `BatchedQueueAccount` with `QueueType::OutputStateV2`, temporary storage for compressed account hashes before tree insertion with immediate spending capability via proof-by-index, using discriminator b`queueacc` [113, 117, 101, 117, 101, 97, 99, 99]

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/merkle_tree.rs : Tree updates from output queue must use BatchedMerkleTreeAccount::update_tree_from_output_queue_account method with ZKP verification

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Associate state tree with queue_account pubkey in tree metadata and set rollover_fee to 0 (charged on queue insertion, not tree operations)

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/merkle_tree.rs : Tree updates from input queue must use update_tree_from_input_queue function for state trees and update_tree_from_address_queue for address trees with ZKP verification

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:35.079Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:35.079Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : BatchedMerkleTreeAccount must be of type `TreeType::StateV2` when updating tree from output queue

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/initialize_state_tree.rs : State tree initialization must create two Solana accounts: BatchedMerkleTreeAccount with integrated input queue and separate BatchedQueueAccount

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-11-24T18:02:15.670Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:15.670Z
Learning: Applies to programs/registry/src/lib.rs : In wrapper instruction handler in `lib.rs`, load account metadata, determine work units, call `check_forester()`, then call the processing function

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: Applies to programs/compressed-token/program/src/create_token_account.rs : Create token account instructions (CreateTokenAccount, CreateAssociatedCTokenAccount, CreateAssociatedTokenAccountIdempotent) require ACTIVE config validation only

Applied to files:

  • forester/src/compressible/compressor.rs
  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:58:35.079Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:35.079Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : In `src/queue.rs`, define BatchedQueueAccount layout and implement `mark_as_inserted_in_merkle_tree` method to increment `num_inserted_zkp_batches` and transition batch state to `Inserted` when all ZKP batches are complete

Applied to files:

  • forester/src/compressible/compressor.rs
📚 Learning: 2025-12-07T03:17:28.794Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-07T03:17:28.794Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/Cargo.toml : Use path references in Cargo.toml dependencies pointing to `/Users/ananas/dev/light-protocol2/sdk-libs/` for light-ctoken-sdk, light-ctoken-types, light-sdk, light-sdk-types, and light-program-test

Applied to files:

  • forester/Cargo.toml
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run compressed token core tests using `cargo test-sbf -p compressed-token-test --test ctoken`, `--test v1`, `--test mint`, and `--test transfer2`

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run Light system program compression tests using `cargo test-sbf -p system-test -- test_with_compression` and `cargo test-sbf -p system-test --test test_re_init_cpi_account` to test compressed account operations

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
📚 Learning: 2025-12-07T03:17:28.794Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-07T03:17:28.794Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/{lib,main}.rs : Clone AccountInfo structs when building CPI builder pattern account structs to avoid borrow checker issues

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
📚 Learning: 2025-12-07T18:09:57.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-12-07T18:09:57.230Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Anchor deserialization of CompressibleConfig must use `AccountDeserialize::try_deserialize()` which automatically validates the discriminator to prevent invalid account type mismatches

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/mod.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/rent.rs : Implement rent calculation functions including `rent_curve_per_epoch`, `calculate_rent_and_balance`, `claimable_lamports`, and `calculate_close_lamports` in rent.rs

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement PDA derivation methods (`derive_pda`, `derive_v1_config_pda`) on CompressibleConfig for account discovery

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
  • forester/src/compressible/mod.rs
  • forester/src/compressible/subscriber.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `claimable_lamports` function to return None if account is compressible, otherwise return Some(amount) for completed epochs only (excluding current ongoing epoch).

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_close_lamports` function to return (u64, u64) tuple splitting lamports between rent recipient and user, with rent recipient receiving completed epochs and user receiving partial epoch remainder.

Applied to files:

  • forester/tests/test_compressible_ctoken.rs
  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/mod.rs : Module declaration should be kept in `mod.rs`

Applied to files:

  • forester/src/compressible/mod.rs
  • forester/src/main.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/traits.rs : Core trait implementations (`HasCompressionInfo`, `CompressAs`, `Compressible`) should be defined in `traits.rs`

Applied to files:

  • forester/src/main.rs
📚 Learning: 2025-12-07T03:17:42.199Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-12-07T03:17:42.199Z
Learning: Applies to program-libs/account-checks/**/*.rs : Use AccountInfoTrait abstraction for unified account handling across both solana-program and pinocchio SDKs

Applied to files:

  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:58:50.237Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/ACCOUNT_CHECKS.md:0-0
Timestamp: 2025-11-24T17:58:50.237Z
Learning: Applies to program-libs/account-checks/docs/program-libs/account-checks/src/checks.rs : Use generic `AccountInfoTrait` parameter for all account validation functions to enable compatibility with both Solana and Pinocchio runtimes

Applied to files:

  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:54:33.614Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/anchor/README.md:0-0
Timestamp: 2025-11-24T17:54:33.614Z
Learning: Implement the Compressed Token Program interface for creating and using compressed tokens on Solana with ZK Compression

Applied to files:

  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-12-07T18:10:14.595Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-07T18:10:14.595Z
Learning: All compressed token account implementations must reference and comply with the account layout specifications in programs/compressed-token/program/docs/ACCOUNTS.md

Applied to files:

  • forester/src/compressible/subscriber.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/queue.rs : Output queues must store compressed account hashes in value vectors (one per batch) enabling access by leaf index before tree insertion

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:10.392Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:10.392Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In src/merkle_tree.rs, implement BatchedMerkleTreeAccount::update_tree_from_address_queue method for batch address append operations on AddressV2 trees. The method must verify ZKP proving correctness of: old_root + queue addresses → new_root using indexed Merkle tree insertion, update tree root, increment tree sequence_number, increment tree next_index by zkp_batch_size, mark ZKP batch as inserted, transition batch state to Inserted when all ZKP batches complete, and zero out bloom filter when current batch is 50% inserted.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/rollover_{state,address}_tree.rs : Trees must support rollover when reaching capacity (2^height leaves) by creating a new tree and marking the old tree as rolled over, preserving old tree roots

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:10.392Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:10.392Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In src/merkle_tree.rs, implement BatchedMerkleTreeAccount::update_tree_from_input_queue method for batch nullify operations on StateV2 trees. The method must verify ZKP proving correctness of: old_root + queue nullifiers → new_root, update tree root, increment tree sequence_number, increment tree nullifier_next_index by zkp_batch_size, mark ZKP batch as inserted, transition batch state to Inserted when all ZKP batches complete, and zero out bloom filter when current batch is 50% inserted.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:39.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/QUEUE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:39.230Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Store compressed account hashes in `BatchedQueueAccount` value vectors for immediate proof-by-index access before tree insertion

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:14.561Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:14.561Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In `BatchedMerkleTreeAccount::insert_nullifier_into_queue`, verify tree type is `TreeType::StateV2` before allowing nullifier insertion; reject address trees

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:02:15.670Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:15.670Z
Learning: When forester PDA is present, `check_forester()` must validate epoch registration and eligibility, track work, and require network fee; when absent, validate that authority matches the tree's designated forester (for private trees)

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:35.079Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:35.079Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : Transition batch state to `Inserted` when all ZKP batches are complete and increment `pending_batch_index` to switch to other batch

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:10.392Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:10.392Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : Batch nullify operations must check that tree type is TreeType::StateV2 before processing, verify batch has ready ZKP batches (num_full_zkp_batches > num_inserted_zkp_batches), and reject if batch is already in Inserted state.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:20.711Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_ADDRESS_TREE.md:0-0
Timestamp: 2025-11-24T17:56:20.711Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_address_tree.rs : Set tree_type to `TreeType::AddressV2` (5) and associated_queue to Pubkey::default() for address trees in `src/initialize_address_tree.rs`. Address trees have no separate output queue - the address queue is integrated into the tree account.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Initialize a state Merkle tree with a `TreeType::StateV2` (4) tree type, storing tree roots, root history, and integrated input queue (bloom filters + hash chains for nullifiers) in the `BatchedMerkleTreeAccount` with discriminator b`BatchMta` [66, 97, 116, 99, 104, 77, 116, 97]

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:02.558Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_ADDRESS_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:02.558Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In `BatchedMerkleTreeAccount::insert_address_into_queue`, verify that the tree type is `TreeType::AddressV2` before proceeding with address insertion. Reject state trees with `MerkleTreeMetadataError::InvalidTreeType`.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:10.392Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:10.392Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : Batch address append operations must check that tree type is TreeType::AddressV2 before processing, verify tree capacity constraint (tree.next_index + zkp_batch_size <= tree_capacity), verify batch has ready ZKP batches (num_full_zkp_batches > num_inserted_zkp_batches), and reject if batch is already in Inserted state.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-12-06T00:49:21.983Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.983Z
Learning: Applies to program-libs/compressible/src/error.rs : PropagateHasher errors from light-hasher module with 7xxx code range in error handling

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:39.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/QUEUE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:39.230Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Check `tree_capacity` (2^height) against new insertions to prevent overflow in `BatchedQueueAccount`

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_rent_and_balance` function to determine compressibility by checking if account balance covers required rent for epochs since last claim, returning (bool, u64) tuple.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Accounts become compressible when they lack rent for the current epoch plus the next epoch (compressibility window).

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `get_last_funded_epoch` function to determine the last epoch number covered by rent payments.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-12-07T18:09:57.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-12-07T18:09:57.230Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : CompressibleConfig rent_sponsor PDA and compression_authority PDA must be derived separately using `get_rent_sponsor_seeds()` and `get_compression_authority_seeds()` helper methods with version-specific seeds

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:24.369Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:24.369Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Insert Into Output Queue: Inserts a compressed account hash into the output queue's currently processing batch by calling `BatchedQueueAccount::insert_into_current_batch` with hash_chain_value and current_slot parameters, updating value vec, hash chain, and managing batch state transitions in src/queue.rs

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:39.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/QUEUE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:39.230Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Use two value vectors (`[ZeroCopyVecU64<[u8; 32]>; 2]`), one per batch, to store compressed account hashes in `BatchedQueueAccount`

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:14.561Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:14.561Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In `BatchedMerkleTreeAccount::insert_nullifier_into_queue`, insert compressed_account_hash into bloom filter (NOT the nullifier) for non-inclusion checks in subsequent transactions

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:14.561Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_INPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:14.561Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : In `BatchedMerkleTreeAccount::insert_nullifier_into_queue`, perform non-inclusion check to ensure compressed_account_hash does not exist in any bloom filter to prevent double-spending

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:02.558Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_ADDRESS_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:02.558Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : After inserting an address into the batch, check if `num_inserted_elements == batch_size`. If true, transition batch state from `Fill` to `Full`, increment `currently_processing_batch_index` to switch to the other batch, and update `pending_batch_index` to mark this batch ready for tree update.

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:57:24.369Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INSERT_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:57:24.369Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Transition batch state from `Fill` to `Full` and increment currently_processing_batch_index when num_inserted_elements reaches batch_size in the output queue

Applied to files:

  • forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T17:58:35.079Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/UPDATE_FROM_OUTPUT_QUEUE.md:0-0
Timestamp: 2025-11-24T17:58:35.079Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : Batch must have ready ZKP batches for insertion: verify `num_full_zkp_batches > num_inserted_zkp_batches`; error with `BatchNotReady` (14301) if not ready

Applied to files:

  • forester/src/epoch_manager.rs
🧬 Code graph analysis (5)
forester/tests/test_batch_append_spent.rs (1)
forester/src/errors.rs (1)
  • channel (208-212)
forester/tests/test_compressible_ctoken.rs (2)
forester/src/compressible/subscriber.rs (2)
  • new (36-46)
  • new (175-185)
forester/src/compressible/state.rs (1)
  • new (59-63)
forester/src/lib.rs (1)
forester/src/compressible/subscriber.rs (2)
  • new (36-46)
  • new (175-185)
forester/src/main.rs (1)
forester/src/errors.rs (1)
  • channel (208-212)
forester/tests/e2e_test.rs (1)
forester/src/errors.rs (1)
  • channel (208-212)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test", "cargo...

Comment on lines +89 to +103
// FIXME: Use latest active state tree after updating lookup tables
// rpc.get_latest_active_state_trees()
// .await
// .map_err(|e| anyhow::anyhow!("Failed to get state tree info: {}", e))?;
// let output_tree_info = rpc
// .get_random_state_tree_info()
// .map_err(|e| anyhow::anyhow!("Failed to get state tree info: {}", e))?;

let output_tree_info = TreeInfo {
tree: pubkey!("bmt1LryLZUMmF7ZtqESaw7wifBXLfXHQYoE4GAmrahU"),
queue: pubkey!("oq1na8gojfdUhsfCpyjNt6h4JaDWtHf1yQj4koBWfto"),
cpi_context: Some(pubkey!("cpi15BoVPKgEPw5o8wc2T816GE7b378nMXnhH3Xbq4y")),
tree_type: TreeType::StateV2,
next_tree_info: None,
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the file and surrounding context
head -n 120 forester/src/compressible/compressor.rs | tail -n 40

Repository: Lightprotocol/light-protocol

Length of output: 1768


🏁 Script executed:

# Search for TreeInfo struct definition and usage patterns
rg "TreeInfo" --type rust -B 2 -A 2 | head -n 100

Repository: Lightprotocol/light-protocol

Length of output: 6846


🏁 Script executed:

# Look for get_latest_active_state_trees and get_random_state_tree_info
rg "get_latest_active_state_trees|get_random_state_tree_info" --type rust

Repository: Lightprotocol/light-protocol

Length of output: 2948


🏁 Script executed:

# Check for open issues or tracking related to dynamic tree lookup
git log --oneline --all | grep -i "tree\|lookup\|dynamic" | head -n 20

Repository: Lightprotocol/light-protocol

Length of output: 1500


🏁 Script executed:

# Search for environment configs or test-specific markers
fd "env" -t f | grep -i config
rg "test\|TEST\|dev\|DEV" forester/src/compressible/compressor.rs | head -n 20

Repository: Lightprotocol/light-protocol

Length of output: 54


🏁 Script executed:

# Search for issues or PRs related to dynamic tree lookup or lookup tables
rg "lookup table|dynamic.*tree" --type rust -i | head -n 30

Repository: Lightprotocol/light-protocol

Length of output: 2632


🏁 Script executed:

# Check recent git history for this specific file
git log --oneline -20 -- forester/src/compressible/compressor.rs

Repository: Lightprotocol/light-protocol

Length of output: 87


🏁 Script executed:

# Look for issue tracking or comments about this FIXME
rg "FIXME.*tree|lookup table" --type rust -B 2 -A 2

Repository: Lightprotocol/light-protocol

Length of output: 4813


🏁 Script executed:

# Check if forester is test-only or production code
head -n 50 forester/Cargo.toml | tail -n 20

Repository: Lightprotocol/light-protocol

Length of output: 770


🏁 Script executed:

# Check if there's a GitHub issues file or tracking
find . -name "*.md" -type f | xargs grep -l "lookup table\|forester" | head -5

Repository: Lightprotocol/light-protocol

Length of output: 300


🏁 Script executed:

# Examine the full context around the FIXME to understand the blocking reason
sed -n '80,110p' forester/src/compressible/compressor.rs

Repository: Lightprotocol/light-protocol

Length of output: 1368


🏁 Script executed:

# Check if get_latest_active_state_trees is actually implemented or just a stub
rg -A 10 "async fn get_latest_active_state_trees" --type rust

Repository: Lightprotocol/light-protocol

Length of output: 2632


🏁 Script executed:

# Check if forester is built/deployed as production or test-only
grep -E "^\[.*test.*\]|^\[.*dev.*\]" forester/Cargo.toml

Repository: Lightprotocol/light-protocol

Length of output: 90


Hardcoded TreeInfo blocks production deployment pending lookup table infrastructure updates.

The hardcoded pubkeys will only work with this specific environment's state trees. While get_latest_active_state_trees() and get_random_state_tree_info() are implemented in the RPC client, this code remains on hardcoded values due to incomplete lookup table integration (as noted in the FIXME).

This must be resolved before deploying to any environment with different state tree addresses. Ensure there's a tracking issue for completing the lookup table infrastructure work.

Comment on lines +241 to +286
fn handle_log_notification(&self, response: RpcResponse<RpcLogsResponse>) {
let logs_response = response.value;

// Skip failed transactions
if logs_response.err.is_some() {
debug!("Skipping failed transaction {}", logs_response.signature);
return;
}

// Parse logs looking for compress_and_close entries
let mut removed_count = 0;
for log in &logs_response.logs {
// Look for our log prefix: "Program log: compress_and_close:<pubkey>"
// The actual log format is "Program log: compress_and_close:<pubkey>"
if let Some(pubkey_str) = log
.strip_prefix("Program log: ")
.and_then(|s| s.strip_prefix(COMPRESS_AND_CLOSE_LOG_PREFIX))
{
match Pubkey::from_str(pubkey_str) {
Ok(pubkey) => {
if self.tracker.remove(&pubkey).is_some() {
debug!(
"Removed closed account {} from tracker (compress_and_close log)",
pubkey
);
removed_count += 1;
}
}
Err(e) => {
error!(
"Invalid pubkey in compress_and_close log '{}': {}",
pubkey_str, e
);
}
}
}
}

if removed_count > 0 {
info!(
"Removed {} closed accounts from transaction {}",
removed_count, logs_response.signature
);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider trimming whitespace when parsing pubkeys from logs.

The current implementation extracts the pubkey string directly from the log without trimming whitespace. If the registry program's log format includes any trailing whitespace or newlines, Pubkey::from_str() will fail.

Consider adding .trim() to handle potential whitespace:

             if let Some(pubkey_str) = log
                 .strip_prefix("Program log: ")
                 .and_then(|s| s.strip_prefix(COMPRESS_AND_CLOSE_LOG_PREFIX))
             {
-                match Pubkey::from_str(pubkey_str) {
+                match Pubkey::from_str(pubkey_str.trim()) {
                     Ok(pubkey) => {

This makes the parser more robust against formatting variations.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn handle_log_notification(&self, response: RpcResponse<RpcLogsResponse>) {
let logs_response = response.value;
// Skip failed transactions
if logs_response.err.is_some() {
debug!("Skipping failed transaction {}", logs_response.signature);
return;
}
// Parse logs looking for compress_and_close entries
let mut removed_count = 0;
for log in &logs_response.logs {
// Look for our log prefix: "Program log: compress_and_close:<pubkey>"
// The actual log format is "Program log: compress_and_close:<pubkey>"
if let Some(pubkey_str) = log
.strip_prefix("Program log: ")
.and_then(|s| s.strip_prefix(COMPRESS_AND_CLOSE_LOG_PREFIX))
{
match Pubkey::from_str(pubkey_str) {
Ok(pubkey) => {
if self.tracker.remove(&pubkey).is_some() {
debug!(
"Removed closed account {} from tracker (compress_and_close log)",
pubkey
);
removed_count += 1;
}
}
Err(e) => {
error!(
"Invalid pubkey in compress_and_close log '{}': {}",
pubkey_str, e
);
}
}
}
}
if removed_count > 0 {
info!(
"Removed {} closed accounts from transaction {}",
removed_count, logs_response.signature
);
}
}
}
fn handle_log_notification(&self, response: RpcResponse<RpcLogsResponse>) {
let logs_response = response.value;
// Skip failed transactions
if logs_response.err.is_some() {
debug!("Skipping failed transaction {}", logs_response.signature);
return;
}
// Parse logs looking for compress_and_close entries
let mut removed_count = 0;
for log in &logs_response.logs {
// Look for our log prefix: "Program log: compress_and_close:<pubkey>"
// The actual log format is "Program log: compress_and_close:<pubkey>"
if let Some(pubkey_str) = log
.strip_prefix("Program log: ")
.and_then(|s| s.strip_prefix(COMPRESS_AND_CLOSE_LOG_PREFIX))
{
match Pubkey::from_str(pubkey_str.trim()) {
Ok(pubkey) => {
if self.tracker.remove(&pubkey).is_some() {
debug!(
"Removed closed account {} from tracker (compress_and_close log)",
pubkey
);
removed_count += 1;
}
}
Err(e) => {
error!(
"Invalid pubkey in compress_and_close log '{}': {}",
pubkey_str, e
);
}
}
}
}
if removed_count > 0 {
info!(
"Removed {} closed accounts from transaction {}",
removed_count, logs_response.signature
);
}
}
🤖 Prompt for AI Agents
In forester/src/compressible/subscriber.rs around lines 241 to 286, the code
extracts the pubkey substring from the log and passes it directly to
Pubkey::from_str, which fails if the log contains trailing whitespace/newlines;
update the parsing to trim whitespace (e.g., call .trim() on the extracted
pubkey_str before handing it to Pubkey::from_str) so the pubkey is validated
against a trimmed string and the error branch only triggers for truly invalid
pubkeys.

Comment on lines +930 to +946

if self.compressible_tracker.is_some() && self.config.compressible_config.is_some() {
let compression_tree_accounts = TreeAccounts {
merkle_tree: solana_sdk::pubkey::Pubkey::default(),
queue: solana_sdk::pubkey::Pubkey::default(),
tree_type: TreeType::Unknown,
is_rolledover: false,
};
let tree_schedule = TreeForesterSchedule::new_with_schedule(
&compression_tree_accounts,
slot,
&epoch_info.forester_epoch_pda,
&epoch_info.epoch_pda,
)?;
epoch_info.trees.insert(0, tree_schedule);
debug!("Added compression tree to epoch {}", epoch_info.epoch.epoch);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Using TreeType::Unknown as a sentinel for compression works but is implicit.

The synthetic tree with TreeType::Unknown and default pubkeys signals "run compression" rather than representing an actual tree. This is functional but relies on implicit knowledge:

  1. should_skip_tree returns false for Unknown (line 2263)
  2. dispatch_tree_processing routes Unknown to dispatch_compression (lines 1583-1590)
  3. The default pubkeys are never actually used

Consider adding a doc comment here explaining this pattern, or introducing a dedicated TreeType::Compression variant if the light_compressed_account crate is under your control.

🤖 Prompt for AI Agents
In forester/src/epoch_manager.rs around lines 930 to 946, the code constructs a
synthetic compression tree using TreeType::Unknown and default pubkeys which is
a sentinel value; make this explicit to avoid implicit behavior: either add a
short doc comment above this block explaining that TreeType::Unknown + default
pubkeys is intentionally used as a sentinel to trigger compression (not a real
tree), listing the dependent functions (should_skip_tree and
dispatch_tree_processing) and that pubkeys are unused, or (preferable if you can
change the crate) add a new TreeType::Compression variant in the
light_compressed_account crate and use that here and update the match sites so
dispatch_tree_processing handles Compression explicitly; implement the doc
comment if crate change is not possible.

Comment on lines +56 to +64
// Emit logs for closed accounts (used by forester to track closures)
for idx in &indices {
if let Ok(source_account) = transfer2_accounts
.packed_accounts
.get_u8(idx.source_index, "source_account")
{
msg!("compress_and_close:{}", source_account.key);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Logs emitted before CPI success could mislead LogSubscriber.

These logs are emitted before the invoke_signed CPI call at line 84. If the CPI fails, the logs will still have been written but the accounts won't actually be closed. The LogSubscriber listening to these logs would incorrectly remove accounts from its tracker.

Consider either:

  1. Moving log emission to after successful CPI completion (though this may not be possible in on-chain programs since the transaction succeeds or fails atomically), or
  2. Documenting that LogSubscriber should only trust logs from confirmed transactions

Also, silently ignoring get_u8 errors (via if let Ok(...)) may hide configuration issues—consider logging a warning for failed lookups.

🤖 Prompt for AI Agents
programs/registry/src/compressible/compress_and_close.rs lines 56-64: logs for
closed accounts are emitted before the CPI at line 84 and may mislead
subscribers if the CPI fails; change the code to defer emitting msg! until after
the CPI returns successfully (i.e., call invoke_signed, check its Result, and
only then iterate indices and emit the msg! per closed account), and also avoid
silently swallowing get_u8 errors—on Err from get_u8 emit a warning msg! (or
return an error if appropriate) so configuration/lookup failures are visible.

@sergeytimoshin sergeytimoshin merged commit 156529d into main Dec 10, 2025
33 checks passed
@sergeytimoshin sergeytimoshin deleted the sergey/add-default-tree-each-epoch branch December 10, 2025 02:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants