feat: state updates via single pipeline + StagingTree#2078
feat: state updates via single pipeline + StagingTree#2078sergeytimoshin merged 54 commits intomainfrom
Conversation
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (1)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including You can disable this status message by setting the WalkthroughAdds a per-tree V2 state supervisor pipeline (supervisors, proof workers, TxSender), integrates supervisor lifecycle into EpochManager, extends BatchContext with prover configuration and eligibility timing, replaces legacy v2 stream processors, and adds indexer/API V2 models and calls for fetching V2 queue elements. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant EpochMgr as EpochManager
participant Supervisor as StateSupervisor
participant Indexer as Indexer (get_queue_elements_v2)
participant ProofPool as ProofWorkerPool
participant TxSender as TxSender
participant Prover as Prover Service
participant Solana as Solana/RPC
EpochMgr->>Supervisor: process_v2(epoch_info, tree_accounts, queue_update, eligibility_end)
activate Supervisor
Supervisor->>Indexer: get_queue_elements_v2(options)
Indexer-->>Supervisor: StateQueueDataV2 / AddressQueueDataV2
loop per batch
Supervisor->>ProofPool: enqueue ProofJob(seq, inputs)
end
ProofPool->>Prover: generate_proof(inputs_json)
Prover-->>ProofPool: ProofResult(seq, instruction, optional_root)
ProofPool->>TxSender: deliver ProofResult
activate TxSender
TxSender->>TxSender: buffer & assemble BatchInstruction (ordered by seq)
TxSender->>Solana: send_transaction_batch(batch)
Solana-->>TxSender: signature / new_root
TxSender->>Supervisor: report processed count
deactivate TxSender
Supervisor->>EpochMgr: return processed
deactivate Supervisor
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Areas needing extra attention:
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 19
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
prover/client/src/proof_client.rs (1)
535-559: Reconsider logging full circuit inputs and prefer structured tracing fieldsThe new
debug!("!! generate_batch_*_proof {:?}", circuit_inputs);lines will dump the entireBatchAppendsCircuitInputs/BatchUpdateCircuitInputsstructures, which (per the ZKP docs) can be large and may contain protocol‑sensitive values (roots, hash chains, nullifiers). This can bloat logs and risk exposing more internal state than needed outside local debugging sessions. I’d recommend either:
- Switching to structured tracing fields and a clearer message, e.g.
debug!(?circuit_inputs, "generate_batch_append_proof inputs");, and/or- Gating this behind a feature flag / config and considering truncation or redaction of large or sensitive fields.
The rename to
circuit_inputsand use ofupdate_inputs_string(&circuit_inputs)otherwise looks consistent and keeps the proof generation flow intact. Based on learnings, these inputs mirror full batch ZKP public/private data, so being deliberate about how much of them you emit is important.forester/tests/e2e_test.rs (1)
855-888: Fixed 3s sleeps per V2 iteration can make this test extremely slow and still raceyWith
iterations = batch_size * 2in V2 mode, twosleep(Duration::from_millis(3000)).awaitcalls per loop can easily push this test into multi‑minute runtimes (or more, depending onoutput_queue_batch_size), and it still relies on wall‑clock timing rather than protocol/indexer state.Consider instead:
- gating on a meaningful condition (e.g. indexer slot, queue indices, or a
WorkReportthreshold) betweencompress/transfersteps, and/or- capping
iterationsor the per‑iteration delay for tests (e.g. use a small test batch size and shorter wait, or backoff based on progress).This will keep CI more predictable and avoid adding a brittle time‑based dependency to the V2 path.
forester/src/epoch_manager.rs (1)
1745-1832: Supervisor lifecycle management handles epoch staleness correctlyThe
get_or_create_state_supervisormethod properly:
- Checks if an existing supervisor matches the current epoch
- Removes stale supervisors from previous epochs with logging
- Creates and registers new supervisors when needed
The pattern of extracting supervisor status before modifying the
DashMap(lines 1751-1762) correctly avoids borrowing issues.However, consider extracting the
default_prover_urlandBatchContextconstruction to reduce duplication with theAddressV2path inprocess_v2:+ fn default_prover_url() -> String { + "http://127.0.0.1:3001".to_string() + }
There was a problem hiding this comment.
Actionable comments posted: 19
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
forester/tests/e2e_test.rs (1)
876-888: Hard-coded delays warrant documentation and extraction.These 3-second sleeps add significant test execution time (6 seconds per iteration). If they're compensating for indexer sync delays or avoiding race conditions, this should be:
- Documented with a comment explaining the purpose
- Extracted to a named constant (e.g.,
const V2_OPERATION_DELAY_MS: u64 = 3000;)- Ideally replaced with a condition-based wait like
wait_for_indexerused elsewhereAre these delays addressing a specific timing issue, or are they temporary debugging aids?
+ // Wait for indexer to sync after compress operation + const V2_OPERATION_DELAY_MS: u64 = 3000; - sleep(Duration::from_millis(3000)).await; + sleep(Duration::from_millis(V2_OPERATION_DELAY_MS)).await; let batch_transfer_sig = transfer::<true, R>( // ... ).await; println!("{} v2 transfer: {:?}", i, batch_transfer_sig); + // Wait for indexer to sync after transfer operation - sleep(Duration::from_millis(3000)).await; + sleep(Duration::from_millis(V2_OPERATION_DELAY_MS)).await;forester/src/epoch_manager.rs (1)
1807-1808: Hardcoded prover timeouts may not suit all environments.
prover_polling_interval: Duration::from_secs(1)andprover_max_wait_time: Duration::from_secs(600)are hardcoded. For production or high-throughput scenarios, these might need tuning.Consider making these configurable via
ForesterConfig:- prover_polling_interval: Duration::from_secs(1), - prover_max_wait_time: Duration::from_secs(600), + prover_polling_interval: self.config.prover_polling_interval + .unwrap_or(Duration::from_secs(1)), + prover_max_wait_time: self.config.prover_max_wait_time + .unwrap_or(Duration::from_secs(600)),
There was a problem hiding this comment.
Actionable comments posted: 3
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
forester/src/processor/v2/common.rs(10 hunks)forester/src/processor/v2/state/proof_worker.rs(1 hunks)prover/client/src/proof.rs(2 hunks)
🧰 Additional context used
🧠 Learnings (100)
📓 Common learnings
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.
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
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/**/*.rs : Use BatchedMerkleTreeAccount for state trees with integrated input queue (for nullifiers) and separate BatchedQueueAccount for output operations
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: Prover server (prover/server/) must generate ZK proofs for batch operations (append, nullify, address append)
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.
📚 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:
prover/client/src/proof.rsforester/src/processor/v2/state/proof_worker.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:
prover/client/src/proof.rsforester/src/processor/v2/state/proof_worker.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:
prover/client/src/proof.rsforester/src/processor/v2/state/proof_worker.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:
prover/client/src/proof.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:
prover/client/src/proof.rsforester/src/processor/v2/state/proof_worker.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:
prover/client/src/proof.rs
📚 Learning: 2025-11-24T18:01:14.087Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Derive PDA addresses using `derive_pda` and `derive_v1_config_pda` functions for CToken account configuration
Applied to files:
prover/client/src/proof.rs
📚 Learning: 2025-11-24T18:01:42.343Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:42.343Z
Learning: Applies to programs/compressed-token/program/src/{claim,transfer2}/**/*.rs : Rent authority can only compress accounts when is_compressible() returns true; lamport distribution on close is: rent → rent_sponsor, unutilized → destination
Applied to files:
prover/client/src/proof.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:
prover/client/src/proof.rsforester/src/processor/v2/state/proof_worker.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:
prover/client/src/proof.rsforester/src/processor/v2/state/proof_worker.rs
📚 Learning: 2025-11-24T18:00:13.178Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-11-24T18:00:13.178Z
Learning: Applies to program-libs/compressible/docs/**/*program*.rs : Use zero-copy deserialization with `bytemuck::pod_from_bytes` in program instruction handlers for CompressibleConfig, skipping the 8-byte discriminator
Applied to files:
prover/client/src/proof.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:
prover/client/src/proof.rs
📚 Learning: 2025-11-24T17:54:20.982Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/zero-copy-derive/README.md:0-0
Timestamp: 2025-11-24T17:54:20.982Z
Learning: Applies to program-libs/zero-copy-derive/**/*.rs : Apply #[derive(ZeroCopyEq)] macro to structs to derive PartialEq comparing ZeroCopy representation with original struct
Applied to files:
prover/client/src/proof.rs
📚 Learning: 2025-11-24T17:54:20.982Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/zero-copy-derive/README.md:0-0
Timestamp: 2025-11-24T17:54:20.982Z
Learning: Applies to program-libs/zero-copy-derive/**/*.rs : Apply #[derive(ZeroCopy)] macro to structs to derive ZeroCopyAt trait for zero-copy serialization
Applied to files:
prover/client/src/proof.rs
📚 Learning: 2025-11-24T17:54:20.982Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/zero-copy-derive/README.md:0-0
Timestamp: 2025-11-24T17:54:20.982Z
Learning: Applies to program-libs/zero-copy-derive/**/*.rs : Nested structs in zero-copy serialization must also derive #[derive(ZeroCopy)]
Applied to files:
prover/client/src/proof.rs
📚 Learning: 2025-11-24T17:54:20.982Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/zero-copy-derive/README.md:0-0
Timestamp: 2025-11-24T17:54:20.982Z
Learning: Applies to program-libs/zero-copy-derive/**/*.rs : Use Option<T> for optional values in zero-copy structs; Option<u16>, Option<u32>, and Option<u64> are optimized
Applied to files:
prover/client/src/proof.rs
📚 Learning: 2025-11-24T18:01:14.087Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Use Anchor serialization for CompressibleConfig account structures in Rust programs
Applied to files:
prover/client/src/proof.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:
prover/client/src/proof.rsforester/src/processor/v2/common.rs
📚 Learning: 2025-11-24T18:00:13.178Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-11-24T18:00:13.178Z
Learning: Applies to program-libs/compressible/docs/**/programs/**/*.rs : Use Anchor's `AccountDeserialize::try_deserialize` for CompressibleConfig when Anchor feature is enabled, which includes automatic discriminator validation
Applied to files:
prover/client/src/proof.rs
📚 Learning: 2025-11-24T18:00:13.178Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-11-24T18:00:13.178Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Use CompressibleConfig discriminator `[180, 4, 231, 26, 220, 144, 55, 168]` for account validation in Solana programs and clients
Applied to files:
prover/client/src/proof.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:
prover/client/src/proof.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:
prover/client/src/proof.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:
prover/client/src/proof.rs
📚 Learning: 2025-11-24T18:00:13.178Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-11-24T18:00:13.178Z
Learning: Applies to program-libs/compressible/docs/program-libs/compressible/src/config.rs : CompressibleConfig struct must use `#[repr(C)]` for proper memory layout with fixed field ordering: version (u16, 2 bytes), state (u8, 1 byte), bump (u8, 1 byte), update_authority (Pubkey, 32 bytes), withdrawal_authority (Pubkey, 32 bytes), rent_sponsor (Pubkey, 32 bytes), compression_authority (Pubkey, 32 bytes), rent_sponsor_bump (u8, 1 byte), compression_authority_bump (u8, 1 byte), rent_config (RentConfig, 8 bytes), address_space ([Pubkey; 4], 128 bytes), and _place_holder ([u8; 32], 32 bytes) for total of 256 bytes
Applied to files:
prover/client/src/proof.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 : Verify ZKP batch append proof using `verify_batch_append_with_proofs(zkp_batch_size, public_input_hash, proof)` and error with `ProofVerificationFailed` (13006) if verification fails
Applied to files:
prover/client/src/proof.rsforester/src/processor/v2/state/proof_worker.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/processor/v2/state/proof_worker.rsforester/src/processor/v2/common.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/**/*prover*.rs : Prover V2 endpoints should be configurable via `--prover-append-url`, `--prover-update-url`, `--prover-address-append-url`, and `--prover-api-key` parameters
Applied to files:
forester/src/processor/v2/state/proof_worker.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/**/*.rs : Tree updates must require zero-knowledge proofs proving batch operation correctness with public inputs: old root, new root, hash chain, and for appends: start_index (output queue) or next_index (address queue)
Applied to files:
forester/src/processor/v2/state/proof_worker.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/processor/v2/state/proof_worker.rsforester/src/processor/v2/common.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/**/*.rs : Input queues (nullifier queue for state trees, address queue for address trees) must use bloom filters for non-inclusion proofs
Applied to files:
forester/src/processor/v2/state/proof_worker.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: Prover server (prover/server/) must generate ZK proofs for batch operations (append, nullify, address append)
Applied to files:
forester/src/processor/v2/state/proof_worker.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/**/*.rs : Use BatchedMerkleTreeAccount for state trees with integrated input queue (for nullifiers) and separate BatchedQueueAccount for output operations
Applied to files:
forester/src/processor/v2/state/proof_worker.rsforester/src/processor/v2/common.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/processor/v2/state/proof_worker.rsforester/src/processor/v2/common.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:
forester/src/processor/v2/state/proof_worker.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/main.rs : Required configuration must include: `--rpc-url`, `--ws-rpc-url`, `--indexer-url`, `--prover-url`, `--payer`, and `--derivation` parameters
Applied to files:
forester/src/processor/v2/state/proof_worker.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/processor/v2/state/proof_worker.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/processor/v2/state/proof_worker.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` (src/merkle_tree.rs), create nullifier using `Hash(compressed_account_hash, leaf_index, tx_hash)`
Applied to files:
forester/src/processor/v2/state/proof_worker.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/processor/v2/state/proof_worker.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/prover/server/prover/v2/batch_append_circuit.go : Batch append circuit implementation at `prover/server/prover/v2/batch_append_circuit.go` must verify that batch append is correct by: (1) verifying public input hash matches Hash([old_root, new_root, leaves_hash_chain, start_index]), (2) verifying leaves_hash_chain matches hash chain of all new leaves, (3) for each position checking if old_leaf is zero (insert new leaf) or non-zero (keep old nullifier), (4) providing Merkle proof for old_leaf and computing root update, (5) verifying final computed root equals new_root
Applied to files:
forester/src/processor/v2/state/proof_worker.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/processor/v2/state/proof_worker.rsforester/src/processor/v2/common.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 merkle tree simulation tests using `RUST_LOG=light_prover_client=debug cargo test -p batched-merkle-tree-test -- --test test_simulate_transactions` to enable logging
Applied to files:
forester/src/processor/v2/state/proof_worker.rsforester/src/processor/v2/common.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/processor/v2/common.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/processor/v2/common.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/processor/v2/common.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/merkle_tree_metadata.rs : Define `BatchedMerkleTreeMetadata` structure in `src/merkle_tree_metadata.rs`. Include tree_type, associated_queue, rollover_fee calculation, access_metadata (owner, program_owner, forester), rollover_metadata (index, rollover_fee, rollover_threshold, network_fee, close_threshold, additional_bytes), hashed_pubkey, next_index, and sequence_number fields.
Applied to files:
forester/src/processor/v2/common.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 `insert_into_current_queue_batch` helper, handle batch state transitions: if state is `Fill`, proceed; if state is `Inserted`, verify bloom filter is zeroed, clear hash chain stores, transition to `Fill`, and reset batch metadata; if state is `Full`, return `BatchedMerkleTreeError::BatchNotReady` (error code 14301).
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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/merkle_tree.rs : Store `BatchedMerkleTreeAccount` layout in src/merkle_tree.rs and `BatchedMerkleTreeMetadata` in src/merkle_tree_metadata.rs
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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`, when batch state is `Inserted`, verify bloom filter is zeroed before clearing hash chain stores and transitioning to `Fill` state
Applied to files:
forester/src/processor/v2/common.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 : Zero out input queue bloom filter when all conditions are met: (1) current batch is ≥50% full (`num_inserted_elements >= batch_size / 2`), (2) current batch NOT in `Inserted` state, (3) previous batch in `Inserted` state, (4) previous batch bloom filter not already zeroed, (5) at least one tree update since batch completion (`batch.sequence_number != current_tree.sequence_number`)
Applied to files:
forester/src/processor/v2/common.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`, transition batch state from `Fill` to `Full` when `num_inserted_elements == batch_size`, and switch `currently_processing_batch_index` to the other batch
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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/processor/v2/common.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/processor/v2/common.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/processor/v2/common.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 : State tree nullifier insertion must use the BatchedMerkleTreeAccount::insert_nullifier_into_queue method
Applied to files:
forester/src/processor/v2/common.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 : When attempting to reuse a batch in the `Inserted` state before its bloom filter has been zeroed by the forester, return `BatchedMerkleTreeError::BloomFilterNotZeroed` (error code 14312).
Applied to files:
forester/src/processor/v2/common.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 : Zero overlapping roots in cyclic buffer by starting at `oldest_root_index = root_history.first_index()`, zeroing `num_remaining_roots` consecutive roots with wrapping, and verifying ended at `first_safe_root_index = batch.root_index + 1`
Applied to files:
forester/src/processor/v2/common.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 : Overlapping roots in history must be zeroed when clearing bloom filters to prevent inclusion proofs of nullified values
Applied to files:
forester/src/processor/v2/common.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 : Root history is accessed via `root_history.last()` to retrieve the latest root. Validity proofs pick roots by index from root history since proofs need a static root value to verify against
Applied to files:
forester/src/processor/v2/common.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 root_history_capacity is at least equal to (input_queue_batch_size / input_queue_zkp_batch_size) in `src/initialize_address_tree.rs`. This ensures sufficient space for roots generated by address queue operations.
Applied to files:
forester/src/processor/v2/common.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 root history as a cyclic buffer with capacity = root_history_capacity, with first entry = zero bytes for tree height
Applied to files:
forester/src/processor/v2/common.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 : After successful ZKP verification, increment tree `sequence_number` by 1 (tracks number of tree updates) and append `new_root` to `root_history` cyclic buffer
Applied to files:
forester/src/processor/v2/common.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 : Calculate overlapping roots for zeroing using: overlapping if `batch.sequence_number > current_tree.sequence_number`; compute `num_remaining_roots = batch.sequence_number - current_tree.sequence_number`; verify `num_remaining_roots < root_history.len()` and error with `CannotZeroCompleteRootHistory` (14313) if violated
Applied to files:
forester/src/processor/v2/common.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 : Initialize root history as cyclic buffer with capacity=root_history_capacity and first entry = `ADDRESS_TREE_INIT_ROOT_40` in `src/initialize_address_tree.rs`.
Applied to files:
forester/src/processor/v2/common.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 root_history_capacity >= (output_queue_batch_size / output_queue_zkp_batch_size) + (input_queue_batch_size / input_queue_zkp_batch_size) to ensure sufficient space for roots generated by both input and output operations
Applied to files:
forester/src/processor/v2/common.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 access control parameters: program_owner (Option<Pubkey>), forester (Option<Pubkey>) for non-Light foresters, and owner (Pubkey passed as function parameter)
Applied to files:
forester/src/processor/v2/common.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 zero-copy deserialization for all `BatchedQueueAccount` operations
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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/processor/v2/common.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 : Implement two hash chain stores (`[ZeroCopyVecU64<[u8; 32]>; 2]`), one per batch, each with `batch_size / zkp_batch_size` hash chains storing Poseidon hashes of ZKP batches in `BatchedQueueAccount`
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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/queue.rs : Store `BatchedQueueAccount` layout and `BatchedQueueMetadata` in src/queue.rs
Applied to files:
forester/src/processor/v2/common.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 : When a batch is in `Inserted` state, clear the value vec and hash chain stores, advance batch state to `Fill`, and reset batch metadata before allowing new insertions
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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/processor/v2/common.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/processor/v2/common.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`, reject insertions when batch is in `Full` state with error code 14301
Applied to files:
forester/src/processor/v2/common.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 queue insertion must use BatchedQueueAccount::insert_into_current_batch method
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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 : When inserting an address into the current batch, call the bloom filter's insert method which must: insert the address into the bloom filter, perform a non-inclusion check across all bloom filters (returning `BatchedMerkleTreeError::NonInclusionCheckFailed` error code 14311 if address already exists), update the hash chain with `Poseidon(prev_hash_chain, address)`, and increment the batch's element counter.
Applied to files:
forester/src/processor/v2/common.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 : Address tree address insertion must use the BatchedMerkleTreeAccount::insert_address_into_queue method
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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 queue type is `OUTPUT_STATE_QUEUE_TYPE_V2` when deserializing `BatchedQueueAccount`
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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: `BatchedQueueAccount` is always an output queue of type `OutputStateV2`; input queues are integrated into `BatchedMerkleTreeAccount`
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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 : When all ZKP batches for a batch are inserted, set batch sequence_number to tree_sequence_number + root_history_capacity and store root_index to identify the root that must not exist when bloom filter is zeroed.
Applied to files:
forester/src/processor/v2/common.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 : After successful ZKP verification, increment tree `next_index` by `zkp_batch_size` (represents leaf index for next insertion)
Applied to files:
forester/src/processor/v2/common.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 : When all ZKP batches of a batch are inserted, set batch `sequence_number = tree_sequence_number + root_history_capacity` (threshold when root at root_index is overwritten) and set `root_index` to identify root that must not exist when bloom filter is zeroed
Applied to files:
forester/src/processor/v2/common.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 : Mark ZKP batch as inserted by calling `mark_as_inserted_in_merkle_tree` on queue batch to increment `num_inserted_zkp_batches`
Applied to files:
forester/src/processor/v2/common.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/**/*.rs : Each ZKP batch has a hash chain storing the Poseidon hash of all values in that ZKP batch, used as public inputs for ZKP verification
Applied to files:
forester/src/processor/v2/common.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 : Create public input hash as `Hash([old_root, new_root, leaves_hash_chain, start_index])` using old_root from tree root history and start_index from tree next_index
Applied to files:
forester/src/processor/v2/common.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: In client code, deserialize output queues using `BatchedQueueAccount::output_from_bytes(&mut account_data)?` from the `light_batched_merkle_tree::queue` module
Applied to files:
forester/src/processor/v2/common.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/**/*.rs : In Solana programs, deserialize output queues using `BatchedQueueAccount::output_from_account_info(account_info)?` from the `light_batched_merkle_tree::queue` module
Applied to files:
forester/src/processor/v2/common.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/queue.rs : Use `get_output_queue_account_size` function from src/queue.rs to calculate queue account size based on output_queue_batch_size and output_queue_zkp_batch_size
Applied to files:
forester/src/processor/v2/common.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 discriminator is `queueacc` (bytes: [113, 117, 101, 117, 101, 97, 99, 99]) using `check_discriminator` from `light-account-checks` when deserializing `BatchedQueueAccount`
Applied to files:
forester/src/processor/v2/common.rs
⏰ 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). (9)
- GitHub Check: Forester e2e test
- GitHub Check: Test program-libs-slow
- GitHub Check: Test batched-merkle-tree-simulate
- GitHub Check: Test program-libs-fast
- GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
- 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: programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test --test v1", "cargo-...
- GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
forester/src/polling/queue_poller.rs (1)
116-130: Lowering channel‑full log todebugis reasonable; consider complementary observability.Treating a full per‑tree channel as a
debug!(rather thanwarn!) makes sense if brief saturation is expected under normal load and updates are cheap to re‑poll. The drop semantics are unchanged and look intentional.To avoid losing sight of chronically back‑pressured trees, consider adding a counter/metric or a throttled higher‑level log (e.g., once per N drops per tree) so persistent starvation is still visible in production telemetry without spamming logs.
♻️ Duplicate comments (2)
forester/src/processor/v2/state/supervisor.rs (1)
428-435: Use.expect()for safer unwrap after conditional initialization.Lines 428 and 475 use
.unwrap()onstaging_treeafter it's been initialized inbuild_staging_tree. While logically safe, this pattern is fragile during refactoring. A past review suggested using.expect()with a clear message:- let staging = self.staging_tree.as_mut().unwrap(); + let staging = self.staging_tree.as_mut() + .expect("staging_tree must be initialized before building jobs");This provides better context if the invariant is ever violated.
Also applies to: 475-482
forester/src/processor/v2/mod.rs (1)
25-35: Clear tree type dispatch with proper delegation.The explicit match branches cleanly separate concerns:
AddressV2continues using theBatchProcessorapproachStateV2correctly defers to theStateSupervisoractor (the trace log helps with debugging)- Default returns
Ok(0)for unsupported typesOne small observation: the default branch silently returns for types like
StateV1,AddressV1, andUnknown. A past review suggested adding a trace log here—if you want visibility during debugging, consider:- _ => Ok(0), + other => { + trace!("Skipping unsupported tree type for batched operations: {:?}", other); + Ok(0) + }Otherwise, the dispatch logic is sound.
| #[derive(Debug, Clone)] | ||
| pub struct ProverConfig { | ||
| pub append_url: String, | ||
| pub update_url: String, | ||
| pub address_append_url: String, | ||
| pub api_key: Option<String>, | ||
| pub polling_interval: Duration, | ||
| pub max_wait_time: Duration, | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Add documentation for ProverConfig fields.
The ProverConfig struct introduces several fields that would benefit from doc comments explaining their purpose:
- What operations do
append_url,update_url, andaddress_append_urlcorrespond to? - What is the expected format/usage of
api_key? - What do
polling_intervalandmax_wait_timecontrol in the proof generation flow?
Consider adding doc comments:
+/// Configuration for remote prover service integration.
#[derive(Debug, Clone)]
pub struct ProverConfig {
+ /// URL endpoint for batch append proof generation
pub append_url: String,
+ /// URL endpoint for batch update proof generation
pub update_url: String,
+ /// URL endpoint for address append proof generation
pub address_append_url: String,
+ /// Optional API key for prover service authentication
pub api_key: Option<String>,
+ /// Interval between polling for proof completion
pub polling_interval: Duration,
+ /// Maximum time to wait for proof generation before timeout
pub max_wait_time: Duration,
}🤖 Prompt for AI Agents
In forester/src/processor/v2/common.rs around lines 34 to 42, the ProverConfig
fields lack documentation; add concise doc comments for each field explaining
their purpose and expected formats: document that append_url is the endpoint to
submit new proofs/append operations, update_url is the endpoint to update
existing proofs or metadata, address_append_url is a specialized endpoint for
appending address-specific proof data, api_key is an optional bearer/API token
(format example: "Bearer <token>" or raw token) used for authenticating
requests, polling_interval is the duration between checks when waiting for
asynchronous proof generation, and max_wait_time is the maximum duration to wait
before timing out the proof generation flow; keep comments short, idiomatic Rust
doc style (///) and clarify units where relevant (e.g., seconds/milliseconds)
and any edge behavior (e.g., zero disables polling).
| let forester_end = context | ||
| .forester_eligibility_end_slot | ||
| .load(Ordering::Relaxed); | ||
| let eligibility_end_slot = if forester_end > 0 { | ||
| forester_end | ||
| } else { | ||
| context.epoch_phases.active.end | ||
| }; | ||
| let slots_remaining = eligibility_end_slot.saturating_sub(current_slot); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Document the eligibility slot convention and consider atomic ordering.
The code uses 0 as a sentinel value to indicate "forester-specific eligibility not set," but this convention is implicit:
let forester_end = context.forester_eligibility_end_slot.load(Ordering::Relaxed);
let eligibility_end_slot = if forester_end > 0 {
forester_end
} else {
context.epoch_phases.active.end
};Two observations:
-
Undocumented convention: Consider adding a comment or constant to clarify that
0means "use epoch-level eligibility." For example:// A value of 0 indicates no forester-specific eligibility limit; fall back to epoch active phase end -
Atomic ordering: While
Ordering::Relaxedis likely sufficient for reading a monotonically increasing slot value, usingOrdering::Acquirewould provide stronger guarantees about visibility of writes from other threads. In a multi-threaded forester with dynamic eligibility updates, this could prevent subtle race conditions.
Apply this diff to use a more conservative ordering:
- let forester_end = context
- .forester_eligibility_end_slot
- .load(Ordering::Relaxed);
+ // Load with Acquire ordering to ensure visibility of concurrent updates
+ let forester_end = context
+ .forester_eligibility_end_slot
+ .load(Ordering::Acquire);And add a similar change at lines 213-215 in send_transaction_batch.
🤖 Prompt for AI Agents
In forester/src/processor/v2/common.rs around lines 130 to 138, the code uses 0
as an implicit sentinel for "no forester-specific eligibility" and reads the
atomic with Ordering::Relaxed; add a short comment (or a named constant)
clarifying that 0 means "use epoch active phase end" and replace the atomic load
Ordering::Relaxed with Ordering::Acquire to provide stronger cross-thread
visibility; also apply the same Ordering::Acquire change (and add the same
comment/constant) at lines ~213-215 in send_transaction_batch so both reads use
the documented sentinel and conservative atomic ordering.
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (2)
forester/src/processor/v2/state/supervisor.rs (2)
410-518: Consider extracting shared logic between build_append_job and build_nullify_job.Both methods share significant structural similarities:
- Slicing batch data using
batch_range- Computing
hashchain_idx- Accessing
staging_treewith the same error pattern- Calling
staging.process_batch_updates- Retrieving leaves hashchain
- Constructing circuit inputs
- Calling
finish_jobBased on coding guidelines, ...
You could extract the common pattern into a helper that accepts closures or an enum to handle the phase-specific differences (array sources, circuit input types). This would improve maintainability and reduce the risk of divergent behavior if one method is updated but the other isn't.
Example structure:
fn build_batch_job<F, I>( &mut self, batch_idx: usize, state_queue: &StateQueueDataV2, start: usize, get_batch_data: F, build_inputs: I, ) -> crate::Result<Option<ProofJob>> where F: FnOnce(&StateQueueDataV2, Range<usize>) -> BatchData, I: FnOnce(BatchTreeUpdateResult, ...) -> ProofInput, { // Common logic here }
221-228: TxSender initialized with stale root before indexer sync.
TxSender::spawnreceivesself.current_rootat line 221, but this value is only updated from the indexer insideenqueue_batchesat lines 330 or 371 (called at line 228). On first run,current_rootwill be[0u8; 32].Since
last_seen_rootinTxSenderis used primarily for logging root transitions, this doesn't cause functional issues—but it means the first proof result will always log a root change from zero, which could be confusing during debugging.Consider either:
- Fetching and setting
current_rootbefore spawningTxSender- Passing a sentinel value (or Option) to indicate "not yet initialized"
- Accepting the current behavior and adding a comment explaining why it's acceptable
Based on past reviews, this appears to be an accepted trade-off, but explicit documentation would help future maintainers.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
forester/src/processor/v2/state/supervisor.rs(1 hunks)
🧰 Additional context used
🧠 Learnings (45)
📓 Common learnings
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.
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: Prover server (prover/server/) must generate ZK proofs for batch operations (append, nullify, address append)
📚 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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/**/*.rs : Use BatchedMerkleTreeAccount for state trees with integrated input queue (for nullifiers) and separate BatchedQueueAccount for output operations
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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 queue type is `OUTPUT_STATE_QUEUE_TYPE_V2` when deserializing `BatchedQueueAccount`
Applied to files:
forester/src/processor/v2/state/supervisor.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 access control parameters: program_owner (Option<Pubkey>), forester (Option<Pubkey>) for non-Light foresters, and owner (Pubkey passed as function parameter)
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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,merkle_tree_metadata}.rs : Trees must maintain a cyclic buffer of recent roots (default: 200) enabling validity proofs for recently spent compressed accounts
Applied to files:
forester/src/processor/v2/state/supervisor.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 root_history_capacity is at least equal to (input_queue_batch_size / input_queue_zkp_batch_size) in `src/initialize_address_tree.rs`. This ensures sufficient space for roots generated by address queue operations.
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/**/*.rs : Error handling must use BatchedMerkleTreeError enum from errors.rs with u32 error codes in the 14301-14312 range
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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`, when batch state is `Inserted`, verify bloom filter is zeroed before clearing hash chain stores and transitioning to `Fill` state
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Verify tree capacity constraint before tree update: `tree.next_index + zkp_batch_size <= tree_capacity`; error with `TreeIsFull` (14310) if violated
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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 : Zero overlapping roots in cyclic buffer by starting at `oldest_root_index = root_history.first_index()`, zeroing `num_remaining_roots` consecutive roots with wrapping, and verifying ended at `first_safe_root_index = batch.root_index + 1`
Applied to files:
forester/src/processor/v2/state/supervisor.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 : When all ZKP batches of a batch are inserted, set batch `sequence_number = tree_sequence_number + root_history_capacity` (threshold when root at root_index is overwritten) and set `root_index` to identify root that must not exist when bloom filter is zeroed
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Root history is accessed via `root_history.last()` to retrieve the latest root. Validity proofs pick roots by index from root history since proofs need a static root value to verify against
Applied to files:
forester/src/processor/v2/state/supervisor.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 : State trees must initialize with zero bytes root for the specified height and have a separate BatchedQueueAccount for output operations
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Overlapping roots in history must be zeroed when clearing bloom filters to prevent inclusion proofs of nullified values
Applied to files:
forester/src/processor/v2/state/supervisor.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/prover/server/prover/v2/batch_append_circuit.go : Batch append circuit implementation at `prover/server/prover/v2/batch_append_circuit.go` must verify that batch append is correct by: (1) verifying public input hash matches Hash([old_root, new_root, leaves_hash_chain, start_index]), (2) verifying leaves_hash_chain matches hash chain of all new leaves, (3) for each position checking if old_leaf is zero (insert new leaf) or non-zero (keep old nullifier), (4) providing Merkle proof for old_leaf and computing root update, (5) verifying final computed root equals new_root
Applied to files:
forester/src/processor/v2/state/supervisor.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 : After successful ZKP verification, increment tree `next_index` by `zkp_batch_size` (represents leaf index for next insertion)
Applied to files:
forester/src/processor/v2/state/supervisor.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/**/*.rs : Tree updates must require zero-knowledge proofs proving batch operation correctness with public inputs: old root, new root, hash chain, and for appends: start_index (output queue) or next_index (address queue)
Applied to files:
forester/src/processor/v2/state/supervisor.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/prover/server/prover/v2/batch_address_append_circuit.go : Batch address append ZKP verification must validate that public_input_hash equals Hash([old_root, new_root, leaves_hash_chain, start_index]), for each address in batch perform two Merkle updates (low leaf update to maintain sorted linked list + new leaf insertion at start_index + i), verify new address fits between low_value and low_next_value, and assert new leaf position must be empty (old_leaf = 0).
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Always increment `queue_next_index` by 1 after successfully inserting an address. This value serves as a sequence number for indexers to track address insertion order.
Applied to files:
forester/src/processor/v2/state/supervisor.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/prover/server/prover/v2/batch_append_circuit.go : Batch append circuit must handle nullifiers in output queue by checking if position contains non-zero old_leaf (nullifier already inserted) and keeping old leaf instead of overwriting, since input and output queues are independent
Applied to files:
forester/src/processor/v2/state/supervisor.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 `insert_into_current_queue_batch` helper, handle batch state transitions: if state is `Fill`, proceed; if state is `Inserted`, verify bloom filter is zeroed, clear hash chain stores, transition to `Fill`, and reset batch metadata; if state is `Full`, return `BatchedMerkleTreeError::BatchNotReady` (error code 14301).
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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 : State tree nullifier insertion must use the BatchedMerkleTreeAccount::insert_nullifier_into_queue method
Applied to files:
forester/src/processor/v2/state/supervisor.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 value vectors (2 vectors, one per batch with capacity = batch_size each) and hash chain stores (2 vectors with capacity = batch_size / zkp_batch_size each)
Applied to files:
forester/src/processor/v2/state/supervisor.rs
🧬 Code graph analysis (1)
forester/src/processor/v2/state/supervisor.rs (5)
forester/src/processor/v2/state/helpers.rs (2)
fetch_batches(34-77)fetch_zkp_batch_size(12-32)forester/src/processor/v2/state/proof_worker.rs (3)
spawn_proof_workers(57-95)new(26-28)async_channel(75-75)forester/src/processor/v2/state/tx_sender.rs (2)
spawn(37-52)e(110-110)prover/client/src/proof_types/batch_append/proof_inputs.rs (1)
new(32-111)prover/client/src/proof_types/batch_update/proof_inputs.rs (1)
new(41-111)
⏰ 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). (7)
- GitHub Check: Test program-libs-fast
- 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 (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-prog...
- GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
- GitHub Check: programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test", "cargo...
|
|
||
| let leaves_hashchain = | ||
| Self::get_leaves_hashchain(&batch.leaves_hash_chains, hashchain_idx)?; | ||
| let start_index = leaf_indices.first().copied().unwrap_or(0) as u32; |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Lossy cast from u64 to u32 without validation.
leaf_indices contains u64 values cast to u32 using as, which truncates if the value exceeds u32::MAX. While tree heights are bounded (default 26 → max index ~67M, well within u32), using as for potentially lossy conversions without explicit validation or documentation is not ideal for defensive coding.
Consider using try_from with error handling:
- let start_index = leaf_indices.first().copied().unwrap_or(0) as u32;
+ let start_index = u32::try_from(leaf_indices.first().copied().unwrap_or(0))
+ .map_err(|_| anyhow!("Leaf index exceeds u32::MAX"))?;Alternatively, add a comment explaining why the cast is safe based on tree height constraints.
🤖 Prompt for AI Agents
In forester/src/processor/v2/state/supervisor.rs around line 445, the code
performs a direct cast from u64 to u32 with `as`, which can silently truncate
large values; replace the lossy cast with a checked conversion (e.g., use
u32::try_from(start_index_u64) and handle the Result or propagate an error) or,
if you can prove by invariants that values never exceed u32::MAX, add a clear
comment stating the bound and replace the cast with an assert or expect that
documents the invariant (so the conversion is explicit and fails loudly if
violated).
| let new_root = result.new_root; | ||
| let leaves_hashchain = | ||
| Self::get_leaves_hashchain(&batch.leaves_hash_chains, hashchain_idx)?; | ||
| let path_indices: Vec<u32> = leaf_indices.iter().map(|idx| *idx as u32).collect(); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Same lossy cast pattern as in build_append_job.
Converting u64 leaf indices to u32 using as can truncate values silently. While safe for typical tree heights, this pattern repeats the same issue flagged at line 445.
Apply the same defensive conversion pattern:
- let path_indices: Vec<u32> = leaf_indices.iter().map(|idx| *idx as u32).collect();
+ let path_indices: Vec<u32> = leaf_indices
+ .iter()
+ .map(|idx| u32::try_from(*idx).map_err(|_| anyhow!("Leaf index exceeds u32::MAX")))
+ .collect::<crate::Result<Vec<_>>>()?;🤖 Prompt for AI Agents
In forester/src/processor/v2/state/supervisor.rs around line 503, the code
performs a lossy cast from u64 to u32 with `as`, which can silently truncate
large values; replace the cast with a checked conversion using u32::try_from (or
idx.try_into()) and propagate or handle the error (return a Result or map to a
specific error) the same way you did at line 445 so conversion failures are
detected instead of silently truncating.
There was a problem hiding this comment.
Actionable comments posted: 3
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)
2327-2343: Fix the pipeline failure: missing ProverConfig fields in test.The test configuration is missing the new
prover_polling_intervalandprover_max_wait_timefields added toExternalServicesConfig.Apply this diff to fix the test configuration:
external_services: ExternalServicesConfig { rpc_url: "http://localhost:8899".to_string(), ws_rpc_url: None, indexer_url: None, prover_url: None, prover_append_url: None, prover_update_url: None, prover_address_append_url: None, prover_api_key: None, + prover_polling_interval: None, + prover_max_wait_time: None, photon_api_key: None, photon_grpc_url: None, pushgateway_url: None, pagerduty_routing_key: None, rpc_rate_limit: None, photon_rate_limit: None, send_tx_rate_limit: None, },
♻️ Duplicate comments (2)
forester/src/processor/v2/state/supervisor.rs (2)
425-425: Simplifyhashchain_idxcalculation.Since
start = batch_idx * zkp_batch_size, the divisionstart / self.zkp_batch_sizealways equalsbatch_idx. The current expression works but adds unnecessary indirection:- let hashchain_idx = start / self.zkp_batch_size as usize; + let hashchain_idx = batch_idx;This makes the relationship to the hash chain store clearer and removes a division operation.
445-445: Consider defensive conversion forstart_index.The cast
leaf_indices.first().copied().unwrap_or(0) as u32can silently truncate if the leaf index exceedsu32::MAX. While tree height 32 limits indices to ~4 billion (withinu32range), using explicit conversion documents the invariant:- let start_index = leaf_indices.first().copied().unwrap_or(0) as u32; + let start_index = u32::try_from(leaf_indices.first().copied().unwrap_or(0)) + .expect("Leaf index within u32 range for height-32 tree");This fails loudly if the invariant is ever violated rather than silently truncating.
| fn build_batch_context( | ||
| &self, | ||
| epoch_info: &Epoch, | ||
| tree_accounts: &TreeAccounts, | ||
| queue_update: Option<&QueueUpdateMessage>, | ||
| ) -> Result<usize> { | ||
| input_queue_hint: Option<u64>, | ||
| output_queue_hint: Option<u64>, | ||
| forester_slot: Option<&ForesterSlot>, | ||
| ) -> BatchContext<R> { | ||
| let default_prover_url = "http://127.0.0.1:3001".to_string(); | ||
|
|
||
| let (input_queue_hint, output_queue_hint) = if let Some(update) = queue_update { | ||
| match update.queue_type { | ||
| light_compressed_account::QueueType::InputStateV2 => { | ||
| (Some(update.queue_size), None) | ||
| } | ||
| light_compressed_account::QueueType::OutputStateV2 => { | ||
| (None, Some(update.queue_size)) | ||
| } | ||
| _ => (None, None), | ||
| } | ||
| } else { | ||
| (None, None) | ||
| }; | ||
|
|
||
| let batch_context = BatchContext { | ||
| let eligibility_end = forester_slot.map(|s| s.end_solana_slot).unwrap_or(0); | ||
| BatchContext { | ||
| rpc_pool: self.rpc_pool.clone(), | ||
| authority: self.config.payer_keypair.insecure_clone(), | ||
| authority: self.authority.clone(), | ||
| derivation: self.config.derivation_pubkey, | ||
| epoch: epoch_info.epoch, | ||
| merkle_tree: tree_accounts.merkle_tree, | ||
| output_queue: tree_accounts.queue, | ||
| prover_append_url: self | ||
| .config | ||
| .external_services | ||
| .prover_append_url | ||
| .clone() | ||
| .unwrap_or_else(|| default_prover_url.clone()), | ||
| prover_update_url: self | ||
| .config | ||
| .external_services | ||
| .prover_update_url | ||
| .clone() | ||
| .unwrap_or_else(|| default_prover_url.clone()), | ||
| prover_address_append_url: self | ||
| .config | ||
| .external_services | ||
| .prover_address_append_url | ||
| .clone() | ||
| .unwrap_or_else(|| default_prover_url.clone()), | ||
| prover_api_key: self.config.external_services.prover_api_key.clone(), | ||
| prover_polling_interval: Duration::from_secs(1), | ||
| prover_max_wait_time: Duration::from_secs(600), | ||
| prover_config: ProverConfig { | ||
| append_url: self | ||
| .config | ||
| .external_services | ||
| .prover_append_url | ||
| .clone() | ||
| .unwrap_or_else(|| default_prover_url.clone()), | ||
| update_url: self | ||
| .config | ||
| .external_services | ||
| .prover_update_url | ||
| .clone() | ||
| .unwrap_or_else(|| default_prover_url.clone()), | ||
| address_append_url: self | ||
| .config | ||
| .external_services | ||
| .prover_address_append_url | ||
| .clone() | ||
| .unwrap_or_else(|| default_prover_url.clone()), | ||
| api_key: self.config.external_services.prover_api_key.clone(), | ||
| polling_interval: self | ||
| .config | ||
| .external_services | ||
| .prover_polling_interval | ||
| .unwrap_or(Duration::from_secs(1)), | ||
| max_wait_time: self | ||
| .config | ||
| .external_services | ||
| .prover_max_wait_time | ||
| .unwrap_or(Duration::from_secs(600)), | ||
| }, | ||
| ops_cache: self.ops_cache.clone(), | ||
| epoch_phases: epoch_info.phases.clone(), | ||
| slot_tracker: self.slot_tracker.clone(), | ||
| input_queue_hint, | ||
| output_queue_hint, | ||
| }; | ||
| num_proof_workers: self.config.transaction_config.max_concurrent_batches, | ||
| forester_eligibility_end_slot: Arc::new(AtomicU64::new(eligibility_end)), | ||
| } | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
LGTM: Good consolidation of BatchContext construction.
The build_batch_context helper successfully eliminates the duplication flagged in past reviews. The prover configuration properly reads from config with sensible defaults.
Optional refinement: Consider extracting the default prover URL ("http://127.0.0.1:3001") as a module-level constant for easier maintenance:
const DEFAULT_PROVER_URL: &str = "http://127.0.0.1:3001";🤖 Prompt for AI Agents
In forester/src/epoch_manager.rs around lines 1755 to 1811, extract the literal
default prover URL "http://127.0.0.1:3001" into a module-level constant (e.g.,
DEFAULT_PROVER_URL: &str) and replace the local let default_prover_url = ...
with references to that constant; update the .unwrap_or_else(||
default_prover_url.clone()) calls to use the constant (ensuring proper String
conversion where needed) so the default value is defined once at top-level for
easier maintenance.
| async fn process_v2( | ||
| &self, | ||
| epoch_info: &Epoch, | ||
| tree_accounts: &TreeAccounts, | ||
| queue_update: Option<&QueueUpdateMessage>, | ||
| forester_slot_details: &ForesterSlot, | ||
| ) -> Result<usize> { | ||
| match tree_accounts.tree_type { | ||
| TreeType::StateV2 => { | ||
| if let Some(update) = queue_update { | ||
| let supervisor = self | ||
| .get_or_create_state_supervisor(epoch_info, tree_accounts) | ||
| .await?; | ||
|
|
||
| supervisor | ||
| .ask(v2::state::UpdateEligibility { | ||
| end_slot: forester_slot_details.end_solana_slot, | ||
| }) | ||
| .send() | ||
| .await | ||
| .map_err(|e| { | ||
| anyhow!( | ||
| "Failed to send UpdateEligibility to StateSupervisor for tree {}: {}", | ||
| tree_accounts.merkle_tree, | ||
| e | ||
| ) | ||
| })?; | ||
|
|
||
| let work = v2::state::QueueWork { | ||
| queue_type: update.queue_type, | ||
| queue_size: update.queue_size, | ||
| }; | ||
|
|
||
| Ok(supervisor | ||
| .ask(v2::state::ProcessQueueUpdate { queue_work: work }) | ||
| .send() | ||
| .await | ||
| .map_err(|e| { | ||
| anyhow!( | ||
| "Failed to send message to StateSupervisor for tree {}: {}", | ||
| tree_accounts.merkle_tree, | ||
| e | ||
| ) | ||
| })?) | ||
| } else { | ||
| Ok(0) | ||
| } | ||
| } | ||
| TreeType::AddressV2 => { | ||
| let input_queue_hint = queue_update.map(|u| u.queue_size); | ||
| let batch_context = self.build_batch_context( | ||
| epoch_info, | ||
| tree_accounts, | ||
| input_queue_hint, | ||
| None, | ||
| Some(forester_slot_details), | ||
| ); | ||
|
|
||
| process_batched_operations(batch_context, tree_accounts.tree_type) | ||
| .await | ||
| .map_err(|e| anyhow!("Failed to process V2 operations: {}", e)) | ||
| } | ||
| _ => { | ||
| warn!( | ||
| "Unsupported tree type for V2 processing: {:?}", | ||
| tree_accounts.tree_type | ||
| ); | ||
| Ok(0) | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
LGTM: Well-structured V2 processing with actor-based StateV2 and direct AddressV2 paths.
The StateV2 path correctly obtains or creates a long-lived supervisor actor and sends it eligibility and work messages. The AddressV2 path builds a per-slot context with forester eligibility and processes directly. Error messages include tree pubkeys for debugging.
Minor optimization opportunity: UpdateEligibility is sent on every call even if end_slot hasn't changed. If this becomes a performance concern, consider tracking the last-sent end_slot to avoid redundant updates. However, the current approach is simpler and the message overhead is negligible.
🤖 Prompt for AI Agents
In forester/src/epoch_manager.rs around lines 1861 to 1931, avoid sending
UpdateEligibility every time when the end_slot hasn't changed: add a
last_sent_end_slot tracker (either on the StateSupervisor struct or in
EpochManager keyed by merkle_tree) and check it before sending
UpdateEligibility; only send if forester_slot_details.end_solana_slot !=
last_sent_end_slot, then update the tracker after a successful send. Make the
tracker concurrency-safe (e.g., AtomicU64 or a Mutex-protected map) and ensure
failure paths do not update the tracker so retries remain possible.
| self.context | ||
| .forester_eligibility_end_slot | ||
| .store(msg.end_slot, std::sync::atomic::Ordering::Relaxed); | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider using Ordering::Release for eligibility store.
The load side in common.rs uses Ordering::Acquire. For proper happens-before semantics, the store should use Ordering::Release to pair with the acquire load:
self.context
.forester_eligibility_end_slot
- .store(msg.end_slot, std::sync::atomic::Ordering::Relaxed);
+ .store(msg.end_slot, std::sync::atomic::Ordering::Release);With Relaxed store and Acquire load, you get the atomicity guarantee but not the visibility ordering. In practice this may work fine since the slot value is monotonically increasing, but Release/Acquire pairing is the correct pattern for cross-thread communication.
🤖 Prompt for AI Agents
In forester/src/processor/v2/state/supervisor.rs around lines 126 to 129, the
code stores forester_eligibility_end_slot with Ordering::Relaxed which pairs
with an Acquire load elsewhere; change the store to use
std::sync::atomic::Ordering::Release to establish proper happens-before
visibility for the Acquire load in common.rs, keeping the rest of the logic
unchanged.
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
forester/src/epoch_manager.rs(15 hunks)
🧰 Additional context used
🧠 Learnings (43)
📓 Common learnings
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.
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/**/*.rs : Use BatchedMerkleTreeAccount for state trees with integrated input queue (for nullifiers) and separate BatchedQueueAccount for output operations
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
📚 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: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 access control parameters: program_owner (Option<Pubkey>), forester (Option<Pubkey>) for non-Light foresters, and owner (Pubkey passed as function parameter)
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/**/*.rs : Use BatchedMerkleTreeAccount for state trees with integrated input queue (for nullifiers) and separate BatchedQueueAccount for output operations
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 : BatchedMerkleTreeAccount must be of type `TreeType::StateV2` when updating tree from output queue
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 : 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/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/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 state Merkle tree account discriminator to b`BatchMta` (8 bytes) and initialize tree metadata with TreeType::StateV2 (4)
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: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: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 : Verify queue and tree association by matching pubkeys; error with `MerkleTreeAndQueueNotAssociated` (14001) if they don't match
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/**/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/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: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: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: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-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/**/*.rs : Use BatchedMerkleTreeAccount with integrated input queue (for addresses) for address trees without a separate output queue 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 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/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/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: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: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 : State tree nullifier insertion must use the BatchedMerkleTreeAccount::insert_nullifier_into_queue method
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-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/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/**/*prover*.rs : Prover V2 endpoints should be configurable via `--prover-append-url`, `--prover-update-url`, `--prover-address-append-url`, and `--prover-api-key` parameters
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-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/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 : Validate queue type is `OUTPUT_STATE_QUEUE_TYPE_V2` when deserializing `BatchedQueueAccount`
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/queue.rs : Store `BatchedQueueAccount` layout and `BatchedQueueMetadata` in src/queue.rs
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/**/queue.rs : Output queue insertion must use BatchedQueueAccount::insert_into_current_batch method
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 : Implement two hash chain stores (`[ZeroCopyVecU64<[u8; 32]>; 2]`), one per batch, each with `batch_size / zkp_batch_size` hash chains storing Poseidon hashes of ZKP batches in `BatchedQueueAccount`
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: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/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 zero-copy deserialization for all `BatchedQueueAccount` operations
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 : When a batch is in `Inserted` state, clear the value vec and hash chain stores, advance batch state to `Fill`, and reset batch metadata before allowing new insertions
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: Call `check_forester()` to validate authority and track work performed, passing account metadata, authority key, target account key, forester PDA, and work units
Applied to files:
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/main.rs : Required configuration must include: `--rpc-url`, `--ws-rpc-url`, `--indexer-url`, `--prover-url`, `--payer`, and `--derivation` parameters
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: Wrapper instruction Account context must include: optional `registered_forester_pda` (mutable), `authority` signer, `cpi_authority` PDA with seeds, `registered_program_pda`, `account_compression_program`, `log_wrapper` for events, and `target_account` (mutable)
Applied to files:
forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:01:14.087Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Implement state validation methods (`validate_active`, `validate_not_inactive`) for CompressibleConfig account state verification
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 : Set output queue account discriminator to b`queueacc` (8 bytes) and initialize queue metadata with QueueType::OutputStateV2
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 : 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/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: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/epoch_manager.rs
🧬 Code graph analysis (1)
forester/src/epoch_manager.rs (4)
forester/src/processor/v2/mod.rs (1)
process_batched_operations(20-36)forester/src/polling/queue_poller.rs (1)
new(68-76)forester/src/slot_tracker.rs (2)
new(25-35)update(37-44)forester/src/processor/v2/state/tx_sender.rs (2)
spawn(37-52)e(110-110)
⏰ 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: Test program-libs-fast
- GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
- GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
- GitHub Check: programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-prog...
🔇 Additional comments (5)
forester/src/epoch_manager.rs (5)
71-73: Wiring ofStateSupervisorMapandauthorityintoEpochManagerlooks consistentThe new
StateSupervisorMap<R>alias,state_supervisorsfield, andauthority: Arc<Keypair>are initialized and cloned correctly, and they’re plumbed throughEpochManager::newwithout changing external behavior. This gives you a single shared signer for all V2 batch contexts and per-tree supervisors, which matches how V1 already usesconfig.payer_keypair.No issues from a correctness or concurrency standpoint here; the Arc-wrapped map and keypair are appropriate for the async usage patterns in this module.
Based on learnings, this aligns with the documented need for per-tree state supervisors and dedicated prover endpoints in the forester README.
Also applies to: 102-119, 121-140, 143-194
1261-1267: Improved logging for light-slot processingIncluding the epoch and Solana slot window in the
process_light_slotlog line makes it much easier to correlate behavior with protocol phases and epoch state. No functional issues here.
1555-1576: V2 dispatch separation for StateV2 vs AddressV2 is well-structuredRouting V2 trees through
process_v2and then:
- Using a long-lived
StateSupervisorforTreeType::StateV2, withQueueWork { queue_type, queue_size }and a separateUpdateEligibilitymessage per slot window, and- Building a fresh
BatchContextand delegating toprocess_batched_operationsonly forTreeType::AddressV2,matches the intended architecture where StateV2 uses the actor-based pipeline and AddressV2 stays direct. The
Ok(0)behavior when there is noqueue_updateor when the tree type is unsupported is a sane fallback and keeps metrics consistent with the calling code.Based on learnings, this division aligns with the docs that state trees use separate input/output queues and address trees use the integrated address queue plus ZKP-based batch append.
Also applies to: 1861-1930
1755-1811: BatchContext / ProverConfig construction and eligibility slot handlingThe new
build_batch_contextcorrectly centralizes all V2 configuration:
- Prover URLs and API key are sourced from
ForesterConfig.external_serviceswith sensible defaults, matching the CLI/README expectations for--prover-append-url,--prover-update-url, and--prover-address-append-url.num_proof_workersis tied totransaction_config.max_concurrent_batches, reusing an existing concurrency knob.forester_eligibility_end_slotis initialized fromforester_slot.end_solana_slotfor AddressV2 and to0for StateV2 (where it will instead be driven byUpdateEligibility).This is a clean consolidation of the V2 runtime configuration. Just ensure that downstream consumers treat an
eligibility_end_slotof0as “no limit / not yet set”, so StateV2 supervisors don’t accidentally short-circuit work before the firstUpdateEligibility.Based on learnings, this matches the documented need to bound work to the assigned forester slots for V2 pipelines.
2343-2345: Tests updated for new prover timing configurationExtending
ExternalServicesConfigin the test helper withprover_polling_interval: Noneandprover_max_wait_time: Nonekeeps the tests compiling and ensures they exercise the default durations wired inbuild_batch_context.This is the right minimal change on the test side.
There was a problem hiding this comment.
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/config.rs (1)
172-183: RevisitTransactionConfig::default().max_concurrent_batches = 60vs documented V1 defaultsThe default
max_concurrent_batcheshas been set to60here. Retrieved guidance for V1 transaction processing mentions a default of--transaction-max-concurrent-batches 20for stable operation. As per coding guidelines, transaction V1 defaults are tuned to avoid overloading Solana RPC and downstream services.A few points to double‑check:
TransactionConfig::default()is used innew_for_statusand may be used in other call sites; raising this default to 60 could:
- Increase concurrent load in any code paths that rely on the default rather than CLI overrides.
- Diverge from the documented operational baseline (20), which might surprise operators.
If the intent is to raise concurrency only for specific V2 flows (or only in
forester start), consider:
- Keeping the struct default at 20 and overriding to 60 explicitly where you need the higher concurrency, or
- Updating the docs / README / CLI default description to reflect the new 60 default, if this is an intentional global change.
Example to keep the documented default:
impl Default for TransactionConfig { fn default() -> Self { Self { legacy_ixs_per_tx: 1, - max_concurrent_batches: 60, + max_concurrent_batches: 20, max_concurrent_sends: 50, cu_limit: 1_000_000, enable_priority_fees: false, tx_cache_ttl_seconds: 15, ops_cache_ttl_seconds: 180, } } }Please confirm which behavior you want so code, CLI defaults, and docs stay aligned. Based on learnings, this default is part of the recommended V1 operational profile.
♻️ Duplicate comments (5)
forester/src/processor/v2/state/supervisor.rs (5)
416-416: Simplify hashchain_idx calculation.Since
start = batch_idx * zkp_batch_size, dividing byzkp_batch_sizejust givesbatch_idx. The current expression adds unnecessary indirection.- let hashchain_idx = start / self.zkp_batch_size as usize; + let hashchain_idx = batch_idx;
436-436: Consider defensive conversion for leaf indices.The
as u32cast silently truncates if the value exceedsu32::MAX. While safe for typical tree heights (height 32 → max index ~4B fits in u32), usingtry_fromwith error handling would be more defensive.- let start_index = leaf_indices.first().copied().unwrap_or(0) as u32; + let start_index = u32::try_from(leaf_indices.first().copied().unwrap_or(0)) + .map_err(|_| anyhow!("Leaf index {} exceeds u32::MAX", leaf_indices.first().unwrap_or(&0)))?;
494-494: Same lossy cast pattern as build_append_job.This line also uses
as u32for the conversion. If you apply defensive conversion at line 436, apply the same pattern here for consistency.- let path_indices: Vec<u32> = leaf_indices.iter().map(|idx| *idx as u32).collect(); + let path_indices: Vec<u32> = leaf_indices + .iter() + .map(|idx| u32::try_from(*idx).map_err(|_| anyhow!("Leaf index {} exceeds u32::MAX", idx))) + .collect::<crate::Result<Vec<_>>>()?;
468-468: Apply same hashchain_idx simplification.This is the same pattern as line 416.
- let hashchain_idx = start / self.zkp_batch_size as usize; + let hashchain_idx = batch_idx;
126-129: UseOrdering::Releasefor proper cross-thread visibility.The load side in
common.rsusesOrdering::Acquire. For correct happens-before semantics, the store should useOrdering::Release. WithRelaxedstore andAcquireload, you get atomicity but not the visibility ordering guarantee that ensures the reader sees all writes that happened before this store.self.context .forester_eligibility_end_slot - .store(msg.end_slot, std::sync::atomic::Ordering::Relaxed); + .store(msg.end_slot, std::sync::atomic::Ordering::Release);
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
forester/package.json(1 hunks)forester/src/config.rs(4 hunks)forester/src/processor/v2/state/supervisor.rs(1 hunks)
🧰 Additional context used
🧠 Learnings (76)
📓 Common learnings
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.
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/**/*.rs : Use BatchedMerkleTreeAccount for state trees with integrated input queue (for nullifiers) and separate BatchedQueueAccount for output operations
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
📚 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/**/*e2e*.rs : Devnet mode tests require `PHOTON_RPC_URL`, `PHOTON_WSS_RPC_URL`, `PHOTON_INDEXER_URL`, `PHOTON_PROVER_URL`, and `PHOTON_API_KEY` environment variables
Applied to files:
forester/package.json
📚 Learning: 2025-11-24T18:03:13.950Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T18:03:13.950Z
Learning: Forester end-to-end tests should be run with `TEST_MODE=local cargo test --package forester e2e_test`
Applied to files:
forester/package.json
📚 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/**/*e2e*.rs : Test environment variables should use `TEST_MODE` to specify 'local' or 'devnet' mode (default: devnet)
Applied to files:
forester/package.json
📚 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/**/*e2e*.rs : 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
Applied to files:
forester/package.json
📚 Learning: 2025-11-24T18:03:13.950Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T18:03:13.950Z
Learning: Set LIGHT_PROTOCOL_VERSION environment variable to V1 or V2 when running JavaScript/TypeScript tests
Applied to files:
forester/package.json
📚 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/**/.env.example : Copy the example environment file with `cp .env.example .env` before configuring Forester
Applied to files:
forester/package.json
📚 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/**/*e2e*.rs : Tests should automatically skip minting tokens, executing transactions, and root verification for disabled test types
Applied to files:
forester/package.json
📚 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 E2E extended tests after building the small compressed token program using `pnpm --filter lightprotocol/programs run build-compressed-token-small` followed by `cargo test-sbf -p e2e-test -- --test test_10_all`
Applied to files:
forester/package.json
📚 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: All Forester configuration can be provided via command-line arguments or environment variables in the format `FORESTER_<OPTION_NAME>`
Applied to files:
forester/package.json
📚 Learning: 2025-11-24T18:02:25.027Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:25.027Z
Learning: Supporting library unit tests must be run using: cargo test -p light-program-test, cargo test -p light-client, cargo test -p light-sparse-merkle-tree, cargo test -p light-compressed-token-types, and cargo test -p light-compressed-token-sdk
Applied to files:
forester/package.json
📚 Learning: 2025-11-24T18:02:25.027Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:25.027Z
Learning: SDK core library unit tests must be run with: cargo test -p light-sdk-macros, cargo test -p light-sdk-macros --all-features, cargo test -p light-sdk, and cargo test -p light-sdk --all-features
Applied to files:
forester/package.json
📚 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 registry tests using `cargo test-sbf -p registry-test` to test protocol configuration and forester registration
Applied to files:
forester/package.json
📚 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 merkle tree simulation tests using `RUST_LOG=light_prover_client=debug cargo test -p batched-merkle-tree-test -- --test test_simulate_transactions` to enable logging
Applied to files:
forester/package.json
📚 Learning: 2025-11-24T18:02:25.027Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:25.027Z
Learning: Token SDK tests must run with command: cargo test-sbf -p sdk-token-test
Applied to files:
forester/package.json
📚 Learning: 2025-11-24T18:02:25.027Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:25.027Z
Learning: Anchor SDK Rust tests must run with command: cargo test-sbf -p sdk-anchor-test
Applied to files:
forester/package.json
📚 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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/**/*.rs : Use BatchedMerkleTreeAccount for state trees with integrated input queue (for nullifiers) and separate BatchedQueueAccount for output operations
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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 queue type is `OUTPUT_STATE_QUEUE_TYPE_V2` when deserializing `BatchedQueueAccount`
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.rsforester/src/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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.rsforester/src/config.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,merkle_tree_metadata}.rs : Trees must maintain a cyclic buffer of recent roots (default: 200) enabling validity proofs for recently spent compressed accounts
Applied to files:
forester/src/processor/v2/state/supervisor.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 root_history_capacity is at least equal to (input_queue_batch_size / input_queue_zkp_batch_size) in `src/initialize_address_tree.rs`. This ensures sufficient space for roots generated by address queue operations.
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.rsforester/src/config.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/**/*.rs : Error handling must use BatchedMerkleTreeError enum from errors.rs with u32 error codes in the 14301-14312 range
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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`, when batch state is `Inserted`, verify bloom filter is zeroed before clearing hash chain stores and transitioning to `Fill` state
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Verify tree capacity constraint before tree update: `tree.next_index + zkp_batch_size <= tree_capacity`; error with `TreeIsFull` (14310) if violated
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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 : Zero overlapping roots in cyclic buffer by starting at `oldest_root_index = root_history.first_index()`, zeroing `num_remaining_roots` consecutive roots with wrapping, and verifying ended at `first_safe_root_index = batch.root_index + 1`
Applied to files:
forester/src/processor/v2/state/supervisor.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 : When all ZKP batches of a batch are inserted, set batch `sequence_number = tree_sequence_number + root_history_capacity` (threshold when root at root_index is overwritten) and set `root_index` to identify root that must not exist when bloom filter is zeroed
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Root history is accessed via `root_history.last()` to retrieve the latest root. Validity proofs pick roots by index from root history since proofs need a static root value to verify against
Applied to files:
forester/src/processor/v2/state/supervisor.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 : State trees must initialize with zero bytes root for the specified height and have a separate BatchedQueueAccount for output operations
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Overlapping roots in history must be zeroed when clearing bloom filters to prevent inclusion proofs of nullified values
Applied to files:
forester/src/processor/v2/state/supervisor.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/prover/server/prover/v2/batch_append_circuit.go : Batch append circuit implementation at `prover/server/prover/v2/batch_append_circuit.go` must verify that batch append is correct by: (1) verifying public input hash matches Hash([old_root, new_root, leaves_hash_chain, start_index]), (2) verifying leaves_hash_chain matches hash chain of all new leaves, (3) for each position checking if old_leaf is zero (insert new leaf) or non-zero (keep old nullifier), (4) providing Merkle proof for old_leaf and computing root update, (5) verifying final computed root equals new_root
Applied to files:
forester/src/processor/v2/state/supervisor.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 : After successful ZKP verification, increment tree `next_index` by `zkp_batch_size` (represents leaf index for next insertion)
Applied to files:
forester/src/processor/v2/state/supervisor.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/**/*.rs : Tree updates must require zero-knowledge proofs proving batch operation correctness with public inputs: old root, new root, hash chain, and for appends: start_index (output queue) or next_index (address queue)
Applied to files:
forester/src/processor/v2/state/supervisor.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/prover/server/prover/v2/batch_address_append_circuit.go : Batch address append ZKP verification must validate that public_input_hash equals Hash([old_root, new_root, leaves_hash_chain, start_index]), for each address in batch perform two Merkle updates (low leaf update to maintain sorted linked list + new leaf insertion at start_index + i), verify new address fits between low_value and low_next_value, and assert new leaf position must be empty (old_leaf = 0).
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Always increment `queue_next_index` by 1 after successfully inserting an address. This value serves as a sequence number for indexers to track address insertion order.
Applied to files:
forester/src/processor/v2/state/supervisor.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/prover/server/prover/v2/batch_append_circuit.go : Batch append circuit must handle nullifiers in output queue by checking if position contains non-zero old_leaf (nullifier already inserted) and keeping old leaf instead of overwriting, since input and output queues are independent
Applied to files:
forester/src/processor/v2/state/supervisor.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 `insert_into_current_queue_batch` helper, handle batch state transitions: if state is `Fill`, proceed; if state is `Inserted`, verify bloom filter is zeroed, clear hash chain stores, transition to `Fill`, and reset batch metadata; if state is `Full`, return `BatchedMerkleTreeError::BatchNotReady` (error code 14301).
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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 : Mark ZKP batch as inserted by calling `mark_as_inserted_in_merkle_tree` on queue batch to increment `num_inserted_zkp_batches`
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Implement two hash chain stores (`[ZeroCopyVecU64<[u8; 32]>; 2]`), one per batch, each with `batch_size / zkp_batch_size` hash chains storing Poseidon hashes of ZKP batches in `BatchedQueueAccount`
Applied to files:
forester/src/processor/v2/state/supervisor.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/**/*.rs : Each ZKP batch has a hash chain storing the Poseidon hash of all values in that ZKP batch, used as public inputs for ZKP verification
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Calculate overlapping roots for zeroing using: overlapping if `batch.sequence_number > current_tree.sequence_number`; compute `num_remaining_roots = batch.sequence_number - current_tree.sequence_number`; verify `num_remaining_roots < root_history.len()` and error with `CannotZeroCompleteRootHistory` (14313) if violated
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Tree height must be fixed at 40 for address trees in `src/initialize_address_tree.rs`. Validate that height equals 40.
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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 tree_capacity = 2^height in output queue metadata
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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 : Initialize next_index to 1 (not 0) in BatchedMerkleTreeAccount in `src/initialize_address_tree.rs`. Index 0 contains pre-initialized sentinel element.
Applied to files:
forester/src/processor/v2/state/supervisor.rs
📚 Learning: 2025-11-24T17:54:20.982Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/zero-copy-derive/README.md:0-0
Timestamp: 2025-11-24T17:54:20.982Z
Learning: Applies to program-libs/zero-copy-derive/**/*.rs : Use Option<T> for optional values in zero-copy structs; Option<u16>, Option<u32>, and Option<u64> are optimized
Applied to files:
forester/src/processor/v2/state/supervisor.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 : State tree nullifier insertion must use the BatchedMerkleTreeAccount::insert_nullifier_into_queue method
Applied to files:
forester/src/processor/v2/state/supervisor.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 value vectors (2 vectors, one per batch with capacity = batch_size each) and hash chain stores (2 vectors with capacity = batch_size / zkp_batch_size each)
Applied to files:
forester/src/processor/v2/state/supervisor.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/**/*prover*.rs : Prover V2 endpoints should be configurable via `--prover-append-url`, `--prover-update-url`, `--prover-address-append-url`, and `--prover-api-key` parameters
Applied to files:
forester/src/config.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/main.rs : Required configuration must include: `--rpc-url`, `--ws-rpc-url`, `--indexer-url`, `--prover-url`, `--payer`, and `--derivation` parameters
Applied to files:
forester/src/config.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/**/*status*.rs : The `forester status` command should support options: `--full`, `--protocol-config`, `--queue`, `--push-gateway-url`, and `--pagerduty-routing-key`
Applied to files:
forester/src/config.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/**/*cache*.rs : Cache settings should support `--tx-cache-ttl-seconds 180` for transaction deduplication and `--ops-cache-ttl-seconds 180` for operations cache
Applied to files:
forester/src/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/config.rs
🪛 GitHub Actions: forester-tests
forester/src/processor/v2/state/supervisor.rs
[error] 17-17: unused import: trace
[error] Cargo build failed due to a compiler error: unused import: trace.
🪛 GitHub Actions: lint
forester/src/processor/v2/state/supervisor.rs
[error] 17-17: Rust compilation error: unused import: trace (compiler error at forester/src/processor/v2/state/supervisor.rs:17:28).
🪛 GitHub Check: Forester e2e test
forester/src/processor/v2/state/supervisor.rs
[failure] 200-200:
unused variable: zkp_batch_size
[failure] 17-17:
unused import: trace
🪛 GitHub Check: lint
forester/src/processor/v2/state/supervisor.rs
[failure] 200-200:
unused variable: zkp_batch_size
[failure] 17-17:
unused import: trace
⏰ 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: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
- GitHub Check: programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-prog...
- GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
- GitHub Check: Test program-libs-slow
- GitHub Check: Test program-libs-fast
- GitHub Check: Test batched-merkle-tree-simulate
🔇 Additional comments (4)
forester/src/processor/v2/state/supervisor.rs (4)
28-57: Clean actor state design.The
StateSupervisorstruct maintains appropriate state for managing the v2 state processing pipeline: staging tree for proof computation, root/index tracking for state synchronization, and configuration. The message types are well-defined.
59-100: Solid actor lifecycle implementation.The
on_startcorrectly fetches the immutablezkp_batch_sizefrom on-chain once, avoiding repeated RPC calls. The initialization pattern is clean and the logging provides good observability.
132-165: Well-factored helper methods.The helper methods provide clean abstractions:
get_leaves_hashchainhas proper error handling with context,batch_rangesafely bounds the slice, andfinish_jobencapsulates state mutation. Good separation of concerns.
293-399: Clear batch processing pipeline.The
enqueue_batchesmethod cleanly separates the Append and Nullify phases, each with its own data extraction and staging tree initialization. The pattern of building the staging tree from indexer data, then iterating to create jobs, is well-structured.
| pub prover_polling_interval: Option<Duration>, | ||
| pub prover_max_wait_time: Option<Duration>, |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Prover polling / max-wait wiring looks correct; consider clarifying zero-value semantics and documenting new knobs
The new prover_polling_interval and prover_max_wait_time fields are cleanly added and correctly wired from StartArgs (ms → Duration::from_millis, secs → Duration::from_secs), and default to None in new_for_status, which is consistent with status-mode not talking to a prover. This shape looks good.
Two follow‑ups worth considering:
-
Zero values from CLI
If a user passes--prover-polling-interval-ms 0or--prover-max-wait-time-secs 0, this will produceDuration::from_millis(0)/Duration::from_secs(0). Depending on how these are consumed, that can mean:- Busy‑polling with no delay, or
- Immediate timeout / no waiting.
If "0" is not a meaningful configuration, it may be safer to normalize it to
Noneor reject it early. For example:
-
prover_polling_interval: args.prover_polling_interval_ms.map(Duration::from_millis), -
prover_max_wait_time: args.prover_max_wait_time_secs.map(Duration::from_secs),
-
prover_polling_interval: args -
.prover_polling_interval_ms -
.filter(|v| *v > 0) -
.map(Duration::from_millis), -
prover_max_wait_time: args -
.prover_max_wait_time_secs -
.filter(|v| *v > 0) -
.map(Duration::from_secs),Or, alternatively, enforce `> 0` at CLI parsing / validation level.
-
Docs / CLI help alignment
Since these are new, it would be good to ensureforester/README.mdand CLI help clearly document:- The units (ms vs secs) and typical ranges.
- Whether
Nonemeans "use internal default behavior" vs "disable polling/timeout".
This will help operators avoid surprising behavior when tuning prover latency vs load. As per coding guidelines, prover-related configuration should be explicitly documented and discoverable from CLI flags.
Also applies to: 246-247, 336-337
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (9)
forester/src/processor/v2/common.rs (2)
1-42: Document ProverConfig and tie it to the prover CLI/config semantics.The new
ProverConfigis central to V2 prover integration but is currently undocumented. Given we configure these endpoints via flags like--prover-append-url,--prover-update-url,--prover-address-append-url, and--prover-api-key(per the forester README learnings), adding concise doc comments will make intent and expected formats obvious for future maintainers and operators.For example:
+/// Configuration for the remote prover service used by V2 state/address workers. #[derive(Debug, Clone)] pub struct ProverConfig { + /// HTTP endpoint for state output-queue → tree append proofs. pub append_url: String, + /// HTTP endpoint for state nullify/update proofs. pub update_url: String, + /// HTTP endpoint for address append proofs. pub address_append_url: String, + /// Optional API key or bearer token for prover authentication. pub api_key: Option<String>, + /// Interval between polling attempts while waiting for proof completion. pub polling_interval: Duration, + /// Maximum time to wait for a proof before giving up. pub max_wait_time: Duration, }This aligns the struct with the documented prover endpoints and makes its usage self-explanatory.
(past nit about missing docs onProverConfigis still applicable; this is the same request, extended with the newer CLI context from the learnings)
32-42: Clarify eligibility sentinel semantics and make the “best-effort” send path intentional.Two related points around the new eligibility logic:
Implicit sentinel for
forester_eligibility_end_slot:
Using0to mean “no forester-specific eligibility; fall back toepoch_phases.active.end” is fine, but it’s implicit. A small comment or named constant would make this much clearer:-const SLOTS_STOP_THRESHOLD: u64 = 1;
+const SLOTS_STOP_THRESHOLD: u64 = 1;
+/// Sentinel meaning "no forester-specific eligibility override"; use epoch active end.
+const NO_FORESTER_ELIGIBILITY_OVERRIDE: u64 = 0;
...
- let forester_end = context
.forester_eligibility_end_slot.load(Ordering::Acquire);- let eligibility_end_slot = if forester_end > 0 {
- let forester_end = context
.forester_eligibility_end_slot.load(Ordering::Acquire);- let eligibility_end_slot = if forester_end > NO_FORESTER_ELIGIBILITY_OVERRIDE {
forester_end
} else {
context.epoch_phases.active.end
};Same pattern can be applied in `send_transaction_batch`. 2. **Best-effort send is currently a no-op in practice:** In `process_stream`, when `slots_remaining < SLOTS_STOP_THRESHOLD`, you: - Log and - Call `send_transaction_batch(...)` in a “best-effort” fashion, then `break`. But `send_transaction_batch` recomputes the same `slots_remaining` using the same `SLOTS_STOP_THRESHOLD` and immediately returns `ForesterError::NotInActivePhase` when this condition holds. That means the best-effort call can never actually send a transaction; it will always be rejected by the inner check. To make this path intentional and easier to reason about, consider one of: - **Option A:** Let `send_transaction_batch` own the stop decision and remove the explicit slot check in `process_stream`, breaking out when you see `ForesterError::NotInActivePhase`. - **Option B:** Use two clearly named thresholds, e.g. `STREAM_STOP_MARGIN` (higher) and `SEND_STOP_MARGIN` (lower), and document that the “best-effort” send uses the stricter margin so it can still succeed in a narrow window. Either way, the goal is to avoid a code path that looks like it might send “one last batch” but can never actually do so under the current thresholds. The use of `Ordering::Acquire` on the atomic loads is good and matches the previous concurrency guidance. Also applies to: 129-144, 198-228, 235-241 </blockquote></details> <details> <summary>forester/src/processor/v2/state/supervisor.rs (7)</summary><blockquote> `461-461`: **Same redundant calculation as in `build_append_job`.** The `hashchain_idx` calculation can be simplified to `batch_idx` for the same reason as in the append case. ```diff - let hashchain_idx = start / self.zkp_batch_size as usize; + let hashchain_idx = batch_idx;
126-129: UseOrdering::Releasefor proper synchronization semantics.The eligibility end slot is loaded with
Ordering::Acquireelsewhere in the codebase. To establish proper happens-before visibility guarantees, the store should useOrdering::Releaserather thanRelaxed.self.context .forester_eligibility_end_slot - .store(msg.end_slot, std::sync::atomic::Ordering::Relaxed); + .store(msg.end_slot, std::sync::atomic::Ordering::Release);
205-212: TxSender receives stale root at spawn time.
TxSender::spawnis called at line 205 withself.current_root, which is still the initial value[0u8; 32]at this point. The actual root from the indexer is only fetched and assigned at lines 314 and 355 insideenqueue_batches, which runs after the spawn at line 212.While
last_seen_rootin TxSender is primarily used for logging, this creates semantic confusion and could mislead debugging. The supervisor'scurrent_rootis updated correctly before jobs are sent, so the functional impact is minimal.Consider either:
- Accepting that the initial logged root will be zero (add a comment explaining this)
- Moving the root update logic before TxSender spawn (more complex refactoring)
409-409: Simplifyhashchain_idxcalculation.Since
start = batch_idx * zkp_batch_size(from the calling loop at line 335), the divisionstart / self.zkp_batch_size as usizemathematically equalsbatch_idx. Usingbatch_idxdirectly would be clearer and avoid the division operation.- let hashchain_idx = start / self.zkp_batch_size as usize; + let hashchain_idx = batch_idx;
133-135: Consider direct field access instead of trivial accessor.The
zkp_batch_size()method simply returnsself.zkp_batch_sizewithout any transformation. Internal methods could access the field directly to reduce indirection.- fn zkp_batch_size(&self) -> u64 { - self.zkp_batch_size - }Then replace calls like
self.zkp_batch_size()withself.zkp_batch_sizethroughout the impl block.
429-429: Use checked conversion instead of lossy cast tou32.Converting
u64leaf indices tou32usingascan silently truncate large values. While tree heights are bounded (typically ≤32, giving max index ~4B, within u32), defensive coding suggests usingtry_fromwith explicit error handling.- let start_index = leaf_indices.first().copied().unwrap_or(0) as u32; + let start_index = u32::try_from(leaf_indices.first().copied().unwrap_or(0)) + .map_err(|_| anyhow!("Leaf index exceeds u32::MAX"))?;Alternatively, document the tree height constraint with a comment justifying the cast safety.
487-487: Use checked conversion forpath_indicesmapping.The
.map(|idx| *idx as u32)pattern performs a lossy cast that can silently truncate values exceedingu32::MAX. Apply the same defensive pattern as suggested forbuild_append_job.- let path_indices: Vec<u32> = leaf_indices.iter().map(|idx| *idx as u32).collect(); + let path_indices: Vec<u32> = leaf_indices + .iter() + .map(|idx| u32::try_from(*idx).map_err(|_| anyhow!("Leaf index exceeds u32::MAX"))) + .collect::<crate::Result<Vec<_>>>()?;
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (4)
forester/src/processor/v2/common.rs (1)
34-42: Add documentation forProverConfigfields.This struct was flagged in a previous review for missing documentation. Adding doc comments would clarify the purpose of each URL endpoint and timing parameter, especially for developers unfamiliar with the prover integration.
forester/src/processor/v2/state/supervisor.rs (3)
126-129: UseOrdering::Releaseto pair withAcquireloads.The corresponding load in
common.rsusesOrdering::Acquire. For proper happens-before semantics, this store should useOrdering::Release:self.context .forester_eligibility_end_slot - .store(msg.end_slot, std::sync::atomic::Ordering::Relaxed); + .store(msg.end_slot, std::sync::atomic::Ordering::Release);With
Relaxedstore andAcquireload, you get atomicity but not guaranteed visibility ordering across threads.
429-429: Lossy cast from u64 to u32 - safe for state trees but consider defensive validation.This cast is safe for state trees (height ≤32, max index fits u32), but using
asfor potentially lossy conversions without validation is fragile if code is refactored to handle larger trees.Consider adding a comment or using
try_fromfor defensive coding:// Safe: state tree height ≤32 guarantees indices fit u32 let start_index = leaf_indices.first().copied().unwrap_or(0) as u32;
409-409: Consider simplifyinghashchain_idxcalculation.Since
start = batch_idx * zkp_batch_size, the expressionstart / self.zkp_batch_sizesimplifies to justbatch_idx. While mathematically correct, the current form adds unnecessary indirection.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
forester/package.json(1 hunks)forester/src/processor/v2/common.rs(10 hunks)forester/src/processor/v2/state/supervisor.rs(1 hunks)
🧰 Additional context used
🧠 Learnings (102)
📓 Common learnings
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.
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/**/*.rs : Use BatchedMerkleTreeAccount for state trees with integrated input queue (for nullifiers) and separate BatchedQueueAccount for output operations
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
📚 Learning: 2025-11-24T18:03:13.950Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T18:03:13.950Z
Learning: Forester end-to-end tests should be run with `TEST_MODE=local cargo test --package forester e2e_test`
Applied to files:
forester/package.json
📚 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/**/*e2e*.rs : Test environment variables should use `TEST_MODE` to specify 'local' or 'devnet' mode (default: devnet)
Applied to files:
forester/package.json
📚 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/**/*e2e*.rs : 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
Applied to files:
forester/package.json
📚 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/**/*prover*.rs : Prover V2 endpoints should be configurable via `--prover-append-url`, `--prover-update-url`, `--prover-address-append-url`, and `--prover-api-key` parameters
Applied to files:
forester/package.jsonforester/src/processor/v2/common.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/**/*e2e*.rs : Devnet mode tests require `PHOTON_RPC_URL`, `PHOTON_WSS_RPC_URL`, `PHOTON_INDEXER_URL`, `PHOTON_PROVER_URL`, and `PHOTON_API_KEY` environment variables
Applied to files:
forester/package.json
📚 Learning: 2025-11-24T18:03:13.950Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T18:03:13.950Z
Learning: Set LIGHT_PROTOCOL_VERSION environment variable to V1 or V2 when running JavaScript/TypeScript tests
Applied to files:
forester/package.json
📚 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 : In test environments, mock Solana rent exemption instead of calling the actual Rent sysvar, using a hardcoded value like 2_282_880 lamports
Applied to files:
forester/package.json
📚 Learning: 2025-11-24T18:02:25.027Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:25.027Z
Learning: Supporting library unit tests must be run using: cargo test -p light-program-test, cargo test -p light-client, cargo test -p light-sparse-merkle-tree, cargo test -p light-compressed-token-types, and cargo test -p light-compressed-token-sdk
Applied to files:
forester/package.json
📚 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 registry tests using `cargo test-sbf -p registry-test` to test protocol configuration and forester registration
Applied to files:
forester/package.json
📚 Learning: 2025-11-24T18:02:25.027Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:25.027Z
Learning: SDK core library unit tests must be run with: cargo test -p light-sdk-macros, cargo test -p light-sdk-macros --all-features, cargo test -p light-sdk, and cargo test -p light-sdk --all-features
Applied to files:
forester/package.json
📚 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 merkle tree simulation tests using `RUST_LOG=light_prover_client=debug cargo test -p batched-merkle-tree-test -- --test test_simulate_transactions` to enable logging
Applied to files:
forester/package.json
📚 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 E2E extended tests after building the small compressed token program using `pnpm --filter lightprotocol/programs run build-compressed-token-small` followed by `cargo test-sbf -p e2e-test -- --test test_10_all`
Applied to files:
forester/package.json
📚 Learning: 2025-11-24T18:02:25.027Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:25.027Z
Learning: Token SDK tests must run with command: cargo test-sbf -p sdk-token-test
Applied to files:
forester/package.json
📚 Learning: 2025-11-24T18:02:25.027Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:25.027Z
Learning: Anchor SDK Rust tests must run with command: cargo test-sbf -p sdk-anchor-test
Applied to files:
forester/package.json
📚 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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/**/*.rs : Use BatchedMerkleTreeAccount for state trees with integrated input queue (for nullifiers) and separate BatchedQueueAccount for output operations
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 queue type is `OUTPUT_STATE_QUEUE_TYPE_V2` when deserializing `BatchedQueueAccount`
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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,merkle_tree_metadata}.rs : Trees must maintain a cyclic buffer of recent roots (default: 200) enabling validity proofs for recently spent compressed accounts
Applied to files:
forester/src/processor/v2/state/supervisor.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 root_history_capacity is at least equal to (input_queue_batch_size / input_queue_zkp_batch_size) in `src/initialize_address_tree.rs`. This ensures sufficient space for roots generated by address queue operations.
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/**/*.rs : Error handling must use BatchedMerkleTreeError enum from errors.rs with u32 error codes in the 14301-14312 range
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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`, when batch state is `Inserted`, verify bloom filter is zeroed before clearing hash chain stores and transitioning to `Fill` state
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 : Verify tree capacity constraint before tree update: `tree.next_index + zkp_batch_size <= tree_capacity`; error with `TreeIsFull` (14310) if violated
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 : Zero overlapping roots in cyclic buffer by starting at `oldest_root_index = root_history.first_index()`, zeroing `num_remaining_roots` consecutive roots with wrapping, and verifying ended at `first_safe_root_index = batch.root_index + 1`
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 : When all ZKP batches of a batch are inserted, set batch `sequence_number = tree_sequence_number + root_history_capacity` (threshold when root at root_index is overwritten) and set `root_index` to identify root that must not exist when bloom filter is zeroed
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 : Root history is accessed via `root_history.last()` to retrieve the latest root. Validity proofs pick roots by index from root history since proofs need a static root value to verify against
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 : State trees must initialize with zero bytes root for the specified height and have a separate BatchedQueueAccount for output operations
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Overlapping roots in history must be zeroed when clearing bloom filters to prevent inclusion proofs of nullified values
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/prover/server/prover/v2/batch_append_circuit.go : Batch append circuit implementation at `prover/server/prover/v2/batch_append_circuit.go` must verify that batch append is correct by: (1) verifying public input hash matches Hash([old_root, new_root, leaves_hash_chain, start_index]), (2) verifying leaves_hash_chain matches hash chain of all new leaves, (3) for each position checking if old_leaf is zero (insert new leaf) or non-zero (keep old nullifier), (4) providing Merkle proof for old_leaf and computing root update, (5) verifying final computed root equals new_root
Applied to files:
forester/src/processor/v2/state/supervisor.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 : After successful ZKP verification, increment tree `next_index` by `zkp_batch_size` (represents leaf index for next insertion)
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/**/*.rs : Tree updates must require zero-knowledge proofs proving batch operation correctness with public inputs: old root, new root, hash chain, and for appends: start_index (output queue) or next_index (address queue)
Applied to files:
forester/src/processor/v2/state/supervisor.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/prover/server/prover/v2/batch_address_append_circuit.go : Batch address append ZKP verification must validate that public_input_hash equals Hash([old_root, new_root, leaves_hash_chain, start_index]), for each address in batch perform two Merkle updates (low leaf update to maintain sorted linked list + new leaf insertion at start_index + i), verify new address fits between low_value and low_next_value, and assert new leaf position must be empty (old_leaf = 0).
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Always increment `queue_next_index` by 1 after successfully inserting an address. This value serves as a sequence number for indexers to track address insertion order.
Applied to files:
forester/src/processor/v2/state/supervisor.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/prover/server/prover/v2/batch_append_circuit.go : Batch append circuit must handle nullifiers in output queue by checking if position contains non-zero old_leaf (nullifier already inserted) and keeping old leaf instead of overwriting, since input and output queues are independent
Applied to files:
forester/src/processor/v2/state/supervisor.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 `insert_into_current_queue_batch` helper, handle batch state transitions: if state is `Fill`, proceed; if state is `Inserted`, verify bloom filter is zeroed, clear hash chain stores, transition to `Fill`, and reset batch metadata; if state is `Full`, return `BatchedMerkleTreeError::BatchNotReady` (error code 14301).
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 : Mark ZKP batch as inserted by calling `mark_as_inserted_in_merkle_tree` on queue batch to increment `num_inserted_zkp_batches`
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 : Implement two hash chain stores (`[ZeroCopyVecU64<[u8; 32]>; 2]`), one per batch, each with `batch_size / zkp_batch_size` hash chains storing Poseidon hashes of ZKP batches in `BatchedQueueAccount`
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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/**/*.rs : Each ZKP batch has a hash chain storing the Poseidon hash of all values in that ZKP batch, used as public inputs for ZKP verification
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 : Calculate overlapping roots for zeroing using: overlapping if `batch.sequence_number > current_tree.sequence_number`; compute `num_remaining_roots = batch.sequence_number - current_tree.sequence_number`; verify `num_remaining_roots < root_history.len()` and error with `CannotZeroCompleteRootHistory` (14313) if violated
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 : Tree height must be fixed at 40 for address trees in `src/initialize_address_tree.rs`. Validate that height equals 40.
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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 tree_capacity = 2^height in output queue metadata
Applied to files:
forester/src/processor/v2/state/supervisor.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/processor/v2/state/supervisor.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/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 : Initialize next_index to 1 (not 0) in BatchedMerkleTreeAccount in `src/initialize_address_tree.rs`. Index 0 contains pre-initialized sentinel element.
Applied to files:
forester/src/processor/v2/state/supervisor.rs
📚 Learning: 2025-11-24T17:54:20.982Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/zero-copy-derive/README.md:0-0
Timestamp: 2025-11-24T17:54:20.982Z
Learning: Applies to program-libs/zero-copy-derive/**/*.rs : Use Option<T> for optional values in zero-copy structs; Option<u16>, Option<u32>, and Option<u64> are optimized
Applied to files:
forester/src/processor/v2/state/supervisor.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 : Verify ZKP batch append proof using `verify_batch_append_with_proofs(zkp_batch_size, public_input_hash, proof)` and error with `ProofVerificationFailed` (13006) if verification fails
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 : State tree nullifier insertion must use the BatchedMerkleTreeAccount::insert_nullifier_into_queue method
Applied to files:
forester/src/processor/v2/state/supervisor.rsforester/src/processor/v2/common.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 value vectors (2 vectors, one per batch with capacity = batch_size each) and hash chain stores (2 vectors with capacity = batch_size / zkp_batch_size each)
Applied to files:
forester/src/processor/v2/state/supervisor.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/merkle_tree_metadata.rs : Define `BatchedMerkleTreeMetadata` structure in `src/merkle_tree_metadata.rs`. Include tree_type, associated_queue, rollover_fee calculation, access_metadata (owner, program_owner, forester), rollover_metadata (index, rollover_fee, rollover_threshold, network_fee, close_threshold, additional_bytes), hashed_pubkey, next_index, and sequence_number fields.
Applied to files:
forester/src/processor/v2/common.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 : Zero out input queue bloom filter when all conditions are met: (1) current batch is ≥50% full (`num_inserted_elements >= batch_size / 2`), (2) current batch NOT in `Inserted` state, (3) previous batch in `Inserted` state, (4) previous batch bloom filter not already zeroed, (5) at least one tree update since batch completion (`batch.sequence_number != current_tree.sequence_number`)
Applied to files:
forester/src/processor/v2/common.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`, transition batch state from `Fill` to `Full` when `num_inserted_elements == batch_size`, and switch `currently_processing_batch_index` to the other batch
Applied to files:
forester/src/processor/v2/common.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 : When attempting to reuse a batch in the `Inserted` state before its bloom filter has been zeroed by the forester, return `BatchedMerkleTreeError::BloomFilterNotZeroed` (error code 14312).
Applied to files:
forester/src/processor/v2/common.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 root history as a cyclic buffer with capacity = root_history_capacity, with first entry = zero bytes for tree height
Applied to files:
forester/src/processor/v2/common.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 : After successful ZKP verification, increment tree `sequence_number` by 1 (tracks number of tree updates) and append `new_root` to `root_history` cyclic buffer
Applied to files:
forester/src/processor/v2/common.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 : Initialize root history as cyclic buffer with capacity=root_history_capacity and first entry = `ADDRESS_TREE_INIT_ROOT_40` in `src/initialize_address_tree.rs`.
Applied to files:
forester/src/processor/v2/common.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 root_history_capacity >= (output_queue_batch_size / output_queue_zkp_batch_size) + (input_queue_batch_size / input_queue_zkp_batch_size) to ensure sufficient space for roots generated by both input and output operations
Applied to files:
forester/src/processor/v2/common.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 client code, use `BatchedMerkleTreeAccount::state_from_bytes()` for state trees and `BatchedMerkleTreeAccount::address_from_bytes()` for address trees
Applied to files:
forester/src/processor/v2/common.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 address trees must check: (1) account ownership by Light account compression program, (2) account discriminator is `BatchMta`, and (3) tree type is `ADDRESS_MERKLE_TREE_TYPE_V2` (5)
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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 access control parameters: program_owner (Option<Pubkey>), forester (Option<Pubkey>) for non-Light foresters, and owner (Pubkey passed as function parameter)
Applied to files:
forester/src/processor/v2/common.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 zero-copy deserialization for all `BatchedQueueAccount` operations
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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/queue.rs : Store `BatchedQueueAccount` layout and `BatchedQueueMetadata` in src/queue.rs
Applied to files:
forester/src/processor/v2/common.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: Prover server (prover/server/) must generate ZK proofs for batch operations (append, nullify, address append)
Applied to files:
forester/src/processor/v2/common.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 : When a batch is in `Inserted` state, clear the value vec and hash chain stores, advance batch state to `Fill`, and reset batch metadata before allowing new insertions
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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`, reject insertions when batch is in `Full` state with error code 14301
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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 : When inserting an address into the current batch, call the bloom filter's insert method which must: insert the address into the bloom filter, perform a non-inclusion check across all bloom filters (returning `BatchedMerkleTreeError::NonInclusionCheckFailed` error code 14311 if address already exists), update the hash chain with `Poseidon(prev_hash_chain, address)`, and increment the batch's element counter.
Applied to files:
forester/src/processor/v2/common.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 : Address tree address insertion must use the BatchedMerkleTreeAccount::insert_address_into_queue method
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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/processor/v2/common.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 : When all ZKP batches for a batch are inserted, set batch sequence_number to tree_sequence_number + root_history_capacity and store root_index to identify the root that must not exist when bloom filter is zeroed.
Applied to files:
forester/src/processor/v2/common.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 : Create public input hash as `Hash([old_root, new_root, leaves_hash_chain, start_index])` using old_root from tree root history and start_index from tree next_index
Applied to files:
forester/src/processor/v2/common.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: In client code, deserialize output queues using `BatchedQueueAccount::output_from_bytes(&mut account_data)?` from the `light_batched_merkle_tree::queue` module
Applied to files:
forester/src/processor/v2/common.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/**/*.rs : In Solana programs, deserialize output queues using `BatchedQueueAccount::output_from_account_info(account_info)?` from the `light_batched_merkle_tree::queue` module
Applied to files:
forester/src/processor/v2/common.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/queue.rs : Use `get_output_queue_account_size` function from src/queue.rs to calculate queue account size based on output_queue_batch_size and output_queue_zkp_batch_size
Applied to files:
forester/src/processor/v2/common.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/processor/v2/common.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 discriminator is `queueacc` (bytes: [113, 117, 101, 117, 101, 97, 99, 99]) using `check_discriminator` from `light-account-checks` when deserializing `BatchedQueueAccount`
Applied to files:
forester/src/processor/v2/common.rs
🧬 Code graph analysis (1)
forester/src/processor/v2/state/supervisor.rs (2)
forester/src/processor/v2/state/helpers.rs (2)
fetch_batches(34-77)fetch_zkp_batch_size(12-32)forester/src/processor/v2/state/tx_sender.rs (2)
spawn(37-52)e(110-110)
⏰ 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). (1)
- GitHub Check: Test batched-merkle-tree-simulate
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
forester/src/epoch_manager.rs (1)
1765-1821: LGTM: Good consolidation, with minor optimization opportunity.The
build_batch_contexthelper successfully eliminates the duplication flagged in past reviews. The prover configuration properly reads from config with sensible defaults.Minor observation: Line 1774 defaults
eligibility_endto 0 when None is provided. While this is acceptable for long-lived supervisors (which receiveUpdateEligibilitymessages later), consider documenting this behavior in a comment for clarity.Optional refinement from past reviews: The
default_prover_url(line 1773) could be extracted as a module-level constant for easier maintenance:const DEFAULT_PROVER_URL: &str = "http://127.0.0.1:3001";
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
forester-utils/src/forester_epoch.rsis excluded by none and included by none
📒 Files selected for processing (1)
forester/src/epoch_manager.rs(21 hunks)
🧰 Additional context used
🧠 Learnings (43)
📓 Common learnings
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.
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/**/*.rs : Use BatchedMerkleTreeAccount for state trees with integrated input queue (for nullifiers) and separate BatchedQueueAccount for output operations
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
📚 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: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/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: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: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/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 : Define access control parameters: program_owner (Option<Pubkey>), forester (Option<Pubkey>) for non-Light foresters, and owner (Pubkey passed as function parameter)
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/**/*.rs : Use BatchedMerkleTreeAccount for state trees with integrated input queue (for nullifiers) and separate BatchedQueueAccount for output operations
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: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 : Verify queue and tree association by matching pubkeys; error with `MerkleTreeAndQueueNotAssociated` (14001) if they don't match
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/**/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/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: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: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-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/**/*.rs : Use BatchedMerkleTreeAccount with integrated input queue (for addresses) for address trees without a separate output queue 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 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/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/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/**/*prover*.rs : Prover V2 endpoints should be configurable via `--prover-append-url`, `--prover-update-url`, `--prover-address-append-url`, and `--prover-api-key` parameters
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-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/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 : Validate queue type is `OUTPUT_STATE_QUEUE_TYPE_V2` when deserializing `BatchedQueueAccount`
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/queue.rs : Store `BatchedQueueAccount` layout and `BatchedQueueMetadata` in src/queue.rs
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/**/queue.rs : Output queue insertion must use BatchedQueueAccount::insert_into_current_batch method
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 : Implement two hash chain stores (`[ZeroCopyVecU64<[u8; 32]>; 2]`), one per batch, each with `batch_size / zkp_batch_size` hash chains storing Poseidon hashes of ZKP batches in `BatchedQueueAccount`
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: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/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 zero-copy deserialization for all `BatchedQueueAccount` operations
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 : When a batch is in `Inserted` state, clear the value vec and hash chain stores, advance batch state to `Fill`, and reset batch metadata before allowing new insertions
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: Call `check_forester()` to validate authority and track work performed, passing account metadata, authority key, target account key, forester PDA, and work units
Applied to files:
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/main.rs : Required configuration must include: `--rpc-url`, `--ws-rpc-url`, `--indexer-url`, `--prover-url`, `--payer`, and `--derivation` parameters
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: Wrapper instruction Account context must include: optional `registered_forester_pda` (mutable), `authority` signer, `cpi_authority` PDA with seeds, `registered_program_pda`, `account_compression_program`, `log_wrapper` for events, and `target_account` (mutable)
Applied to files:
forester/src/epoch_manager.rs
📚 Learning: 2025-11-24T18:01:14.087Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Implement state validation methods (`validate_active`, `validate_not_inactive`) for CompressibleConfig account state verification
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 : Set output queue account discriminator to b`queueacc` (8 bytes) and initialize queue metadata with QueueType::OutputStateV2
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 : Always increment `queue_next_index` by 1 after successfully inserting an address. This value serves as a sequence number for indexers to track address insertion order.
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: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/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: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-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: Use epoch-based accounting (432,000 slots ≈ 2.5 days) instead of continuous time for Light Protocol rent collection
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 : 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/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-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 : Before inserting into the output queue, validate that the tree is not full by checking that next_index < tree_capacity
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/**/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/epoch_manager.rs
🧬 Code graph analysis (1)
forester/src/epoch_manager.rs (3)
forester/src/processor/v2/mod.rs (1)
process_batched_operations(20-36)forester/src/processor/v2/common.rs (2)
new(264-266)e(173-173)forester/src/processor/v2/state/tx_sender.rs (2)
spawn(37-52)e(110-110)
⏰ 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: Test program-libs-fast
🔇 Additional comments (9)
forester/src/epoch_manager.rs (9)
1-73: LGTM: Clean infrastructure additions.The new imports and
StateSupervisorMaptype alias properly support the per-tree supervisor pattern. The type aliasArc<DashMap<Pubkey, (u64, ActorRef<...>)>>clearly expresses that each tree (by pubkey) maps to an epoch number and its supervisor actor reference, with thread-safe concurrent access via DashMap.
103-141: LGTM: Proper field additions with complete Clone implementation.The
authorityandstate_supervisorsfields are appropriately typed and theCloneimplementation correctly clones both Arc-wrapped values. The authority field eliminates repeated keypair access, and the supervisors map enables per-tree actor lifecycle management.
156-194: LGTM: Proper initialization of new fields.The
authorityis initialized fromconfig.payer_keypair.insecure_clone()(line 176) andstate_supervisorsstarts as an emptyDashMap(line 191). Both fields are correctly initialized for their intended usage patterns.
388-400: LGTM: Supervisor cleanup on epoch transition is correct.The code properly kills all supervisor actors and clears the map when a new epoch is detected. Using
.kill()ensures immediate termination, preventing stale supervisors from processing work in the new epoch. This is the right trade-off at epoch boundaries—any in-flight work that fails can be retried in the new epoch.
1187-1189: LGTM: Consecutive eligibility calculation is correct.The code properly calculates
consecutive_endby querying the tree schedule (line 1187-1188) and falls back to the current slot's end if unavailable (line 1189). This allows the V2 processor to understand if the forester has consecutive eligible slots, optimizing batch processing.
1265-1357: LGTM: V1 processing correctly adapted to new signature.The log message now includes the epoch number (line 1266-1270) for better debugging context. The
dispatch_tree_processingcall (line 1317) correctly passesforester_slot_details.end_solana_slotas theconsecutive_eligibility_endparameter—for V1 trees, this is simply the current slot's end since consecutive eligibility is a V2 concept.
1360-1502: LGTM: V2 processing correctly threads consecutive eligibility through the call chain.The
consecutive_eligibility_endparameter is properly added to the function signature (line 1371), logged for debugging (line 1375), and passed todispatch_tree_processing(line 1443). This enables V2 trees to understand their eligibility window and batch work across consecutive slots efficiently.
1554-1587: LGTM: Clean dispatcher refactoring.The signature change from
forester_slot_details: &ForesterSlottoconsecutive_eligibility_end: u64(line 1561) appropriately simplifies the interface. The function now has 7 parameters, warranting the#[allow(clippy::too_many_arguments)](line 1554), but this is acceptable for a dispatcher. V1 processing ignores the parameter while V2 processing correctly uses it (line 1582).
1871-1941: LGTM: Well-structured V2 processing with proper actor-based StateV2 and direct AddressV2 paths.The StateV2 path correctly obtains or creates a long-lived supervisor actor (lines 1881-1883) and sends it eligibility (lines 1885-1897) and work messages (lines 1899-1914). The AddressV2 path builds a per-slot context with forester eligibility (lines 1920-1927) and processes directly (lines 1929-1931). Error messages include tree pubkeys for debugging (lines 1892-1895, 1909-1913).
Minor note:
UpdateEligibilityis sent on every call (line 1885) even ifconsecutive_eligibility_endhasn't changed. If this becomes a performance concern under high load, consider tracking the last-sent end_slot per tree to avoid redundant updates. However, the current approach is simpler and the message overhead is negligible for typical workloads.
| async fn get_or_create_state_supervisor( | ||
| &self, | ||
| epoch_info: &Epoch, | ||
| tree_accounts: &TreeAccounts, | ||
| ) -> Result<ActorRef<v2::state::StateSupervisor<R>>> { | ||
| use dashmap::mapref::entry::Entry; | ||
|
|
||
| let entry = self.state_supervisors.entry(tree_accounts.merkle_tree); | ||
|
|
||
| match entry { | ||
| Entry::Occupied(mut occupied) => { | ||
| let (stored_epoch, supervisor_ref) = occupied.get(); | ||
| if *stored_epoch == epoch_info.epoch { | ||
| Ok(supervisor_ref.clone()) | ||
| } else { | ||
| info!( | ||
| "Removing stale StateSupervisor for tree {} (epoch {} -> {})", | ||
| tree_accounts.merkle_tree, *stored_epoch, epoch_info.epoch | ||
| ); | ||
| // Don't pass forester_slot - StateSupervisor is long-lived across forester slots, | ||
| // so it should use the global active phase end for safety checks | ||
| let batch_context = | ||
| self.build_batch_context(epoch_info, tree_accounts, None, None, None); | ||
| let supervisor = v2::state::StateSupervisor::spawn(batch_context); | ||
| info!( | ||
| "Created StateSupervisor actor for tree {} (epoch {})", | ||
| tree_accounts.merkle_tree, epoch_info.epoch | ||
| ); | ||
| occupied.insert((epoch_info.epoch, supervisor.clone())); | ||
| Ok(supervisor) | ||
| } | ||
| } | ||
| Entry::Vacant(vacant) => { | ||
| // Don't pass forester_slot - StateSupervisor is long-lived across forester slots, | ||
| // so it should use the global active phase end for safety checks | ||
| let batch_context = | ||
| self.build_batch_context(epoch_info, tree_accounts, None, None, None); | ||
| let supervisor = v2::state::StateSupervisor::spawn(batch_context); | ||
| info!( | ||
| "Created StateSupervisor actor for tree {} (epoch {})", | ||
| tree_accounts.merkle_tree, epoch_info.epoch | ||
| ); | ||
| vacant.insert((epoch_info.epoch, supervisor.clone())); | ||
| Ok(supervisor) | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
LGTM: Race condition fixed with DashMap::entry, minor cleanup opportunity.
Using DashMap::entry (line 1830) removes the check-then-insert race condition from earlier reviews, ensuring only one StateSupervisor is spawned per tree/epoch pair. The comments (lines 1842-1843, 1856-1857) helpfully explain why forester_slot isn't passed—supervisors are long-lived across forester slots.
Minor observation: In the epoch-mismatch branch (lines 1838-1851), the code overwrites the stale supervisor without explicitly calling .kill() on it. In normal operation, monitor_epochs kills all supervisors on epoch bumps, so this should be rare. However, if this branch is reached (e.g., in tests or race conditions), the old actor could continue running without a map handle. Consider explicitly terminating the stale supervisor before insertion:
let old_supervisor = occupied.get().1.clone();
old_supervisor.kill();
occupied.insert((epoch_info.epoch, new_supervisor.clone()));🤖 Prompt for AI Agents
In forester/src/epoch_manager.rs around lines 1823 to 1869 the epoch-mismatch
branch replaces a stale StateSupervisor in the DashMap without terminating the
old actor, which can leave the old supervisor running without a map handle;
before inserting the new supervisor, clone and call .kill() on the existing
supervisor reference (and await or handle the result if the kill is async) to
ensure the old actor is terminated, then insert the new (epoch, supervisor) pair
and optionally log the termination outcome for clarity.
Summary by CodeRabbit
New Features
Improvements
Chores
✏️ Tip: You can customize this high-level summary in your review settings.