Skip to content

feat: add API key support to prover client#1912

Merged
sergeytimoshin merged 4 commits intomainfrom
sergey/prover-api-key
Aug 18, 2025
Merged

feat: add API key support to prover client#1912
sergeytimoshin merged 4 commits intomainfrom
sergey/prover-api-key

Conversation

@sergeytimoshin
Copy link
Contributor

@sergeytimoshin sergeytimoshin commented Aug 17, 2025

Summary by CodeRabbit

  • New Features

    • Added optional API-key authentication for prover requests and per-operation prover endpoints (append, update, address-append) with sensible fallbacks.
    • CLI adds flags/env vars to configure per-operation prover URLs and the prover API key.
  • Configuration

    • External services config extended to include per-operation prover URLs and an optional prover_api_key.
  • Tests

    • E2E and other tests updated to handle separate Photon and Prover API keys and new prover URL fields.
  • Documentation

    • Changelogs/READMEs reformatted and package notes updated.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 17, 2025

Walkthrough

Adds optional prover API key support and splits prover endpoints by operation. CLI/config gain per-operation prover URLs and an API key; BatchContext and processor wiring are updated to carry those fields; instruction-stream builders and ProofClient are updated to accept and send an X-API-Key header when provided. Tests and docs updated accordingly.

Changes

Cohort / File(s) Summary
Prover client auth
prover/client/src/proof_client.rs
Add api_key: Option<String> to ProofClient; with_config(...) accepts api_key; HTTP requests include X-API-Key header when present.
Instruction builders (Rust utils)
forester-utils/src/instructions/address_batch_update.rs, forester-utils/src/instructions/state_batch_append.rs, forester-utils/src/instructions/state_batch_nullify.rs
Add and propagate prover_api_key: Option<String> in public configs/signatures; ProofClient::with_config(..., prover_api_key) used when constructing client.
Processor v2 wiring
forester/src/processor/v2/common.rs, forester/src/processor/v2/state.rs, forester/src/processor/v2/address.rs
Replace single prover_url with prover_append_url, prover_update_url, prover_address_append_url and prover_api_key: Option<String> on BatchContext; call sites pass appropriate URL and API key into instruction-stream builders.
Epoch manager
forester/src/epoch_manager.rs
Build BatchContext with per-operation prover URLs (fallback default http://127.0.0.1:3001) and prover_api_key, then call process_batched_operations as before.
CLI and config
forester/src/cli.rs, forester/src/config.rs
Add prover_append_url, prover_update_url, prover_address_append_url, and prover_api_key to StartArgs and ExternalServicesConfig; start config populates URLs from overrides or falls back to prover_url; API key wired from args/env.
Tests
forester/tests/e2e_test.rs, forester/tests/priority_fee_test.rs, forester/tests/test_utils.rs
Split API key helpers into get_photon_api_key() and get_prover_api_key(); plumb prover_api_key and new prover URL fields through test StartArgs/ExternalServicesConfig; defaults set to None.
JS docs/changelogs
js/compressed-token/CHANGELOG.md, js/compressed-token/README.md, js/stateless.js/CHANGELOG.md, js/stateless.js/README.md
Documentation and changelog text/formatting updates (no runtime code changes in this PR).

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI / Config
  participant EM as EpochManager
  participant Proc as Processor V2
  participant Utils as forester-utils (streams)
  participant PC as ProofClient
  participant Prover as Prover Service

  CLI->>EM: StartArgs (prover_* URLs, prover_api_key)
  EM->>Proc: BatchContext {append/update/address URLs, prover_api_key}
  Proc->>Utils: get_*_instruction_stream(..., url, prover_api_key, ...)
  Utils->>PC: ProofClient::with_config(url, ..., prover_api_key)
  PC->>Prover: HTTP request (+ X-API-Key if provided)
  Prover-->>PC: Job/status responses
  PC-->>Utils: Proof data / job status
  Utils-->>Proc: Instruction stream
  Proc-->>EM: Batched instructions
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • ananas-block
  • SwenSchaeferjohann

Poem

A whisk of keys, a hop of URLs three,
I thump my foot: “Add headers, please!”
Streams now flow with secret spice,
Append, update, address—so nice.
To the prover burrow I boldly seek,
With X-API-Key—squeak squeak! 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

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

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ac366be and 3ddc79c.

📒 Files selected for processing (3)
  • forester/tests/e2e_test.rs (3 hunks)
  • forester/tests/priority_fee_test.rs (1 hunks)
  • forester/tests/test_utils.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • forester/tests/test_utils.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Forester e2e test
  • GitHub Check: stateless-js-v1
  • GitHub Check: cli-v2
  • GitHub Check: cli-v1
  • GitHub Check: Test concurrent-merkle-tree
  • GitHub Check: Test sdk-libs
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: Test program-libs-slow
  • GitHub Check: Test program-libs-fast
  • GitHub Check: lint
  • GitHub Check: stateless-js-v2
🔇 Additional comments (3)
forester/tests/priority_fee_test.rs (1)

41-44: New prover endpoint fields defaulting to None look correct

Providing None for the new optional prover fields keeps this test isolated from prover routing and maintains backward compatibility with StartArgs construction.

forester/tests/e2e_test.rs (2)

199-204: Config wiring for new fields and API keys is correct

Passing both photon_api_key and prover_api_key through ExternalServicesConfig is the right place and matches the new client wiring.


467-468: LightClientConfig now using get_photon_api_key() — LGTM

The rename from get_api_key to get_photon_api_key is reflected here and matches the updated signature.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sergey/prover-api-key

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Status, Documentation and Community

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

rpc_pool: ctx.rpc_pool.clone(),
merkle_tree_pubkey: ctx.merkle_tree,
prover_url: ctx.prover_url.clone(),
prover_url: construct_prover_url(&ctx.prover_url, "/address-append"),
Copy link
Contributor

@SwenSchaeferjohann SwenSchaeferjohann Aug 17, 2025

Choose a reason for hiding this comment

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

this is supposed to have the endpoint hardcoded here? @sergeytimoshin

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right, I'll clean it up.

@sergeytimoshin sergeytimoshin marked this pull request as draft August 18, 2025 12:57
@sergeytimoshin sergeytimoshin marked this pull request as ready for review August 18, 2025 13:18
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🔭 Outside diff range comments (1)
forester/tests/test_utils.rs (1)

82-90: Add per-operation prover URLs to ExternalServicesConfig in tests

The ExternalServicesConfig struct in forester/src/config.rs now includes three new fields—prover_append_url, prover_update_url, and prover_address_append_url. The initializer in forester/tests/test_utils.rs (around line 82) only sets prover_url, so it will fail to compile. Update that block to:

         external_services: ExternalServicesConfig {
             rpc_url: "http://localhost:8899".to_string(),
             ws_rpc_url: Some("ws://localhost:8900".to_string()),
             indexer_url: Some("http://localhost:8784".to_string()),
             prover_url: Some("http://localhost:3001".to_string()),
+            prover_append_url: Some("http://localhost:3001".to_string()),
+            prover_update_url: Some("http://localhost:3001".to_string()),
+            prover_address_append_url: Some("http://localhost:3001".to_string()),
             prover_api_key: None,
             photon_api_key: None,
             pushgateway_url: None,
             pagerduty_routing_key: None,

• Apply the same additions in other test initializers (e.g. priority_fee_test.rs, legacy/test_utils.rs, etc.).
• If you prefer, you can replace the explicit fields with ..Default::default() to cover all missing entries.

🧹 Nitpick comments (12)
js/stateless.js/README.md (3)

35-37: Bulleted example links normalized; consider adding API key usage note

Formatting looks consistent. Given this PR adds prover API key support end-to-end, should we add a brief note or link here to an example showing API key configuration/usage in the JS client (if applicable to stateless.js)?

I can draft a succinct bullet with a link to the relevant docs or an example repo section once you confirm where API key setup is documented.


44-46: Nit: “stacktraces” → “stack traces”; minor clarity

Small wording fix for readability.

Apply this diff:

- - A description or context of any errors you are encountering with stacktraces if available.
+ - A description or context of any errors you are encountering, with stack traces if available.

60-63: Combine wrapped bullet into a single line for cleaner rendering

Avoiding soft-wrapped list items improves readability and prevents accidental formatting issues in some renderers.

Apply this diff:

- - 🐞 For bugs or feature requests, please open an
-   [issue](https://github.com/lightprotocol/light-protocol/issues/new).
- - 🔒 For security vulnerabilities, please follow the [security policy](https://github.com/Lightprotocol/light-protocol/blob/main/SECURITY.md).
+ - 🐞 For bugs or feature requests, please open an [issue](https://github.com/lightprotocol/light-protocol/issues/new).
+ - 🔒 For security vulnerabilities, please follow the [security policy](https://github.com/Lightprotocol/light-protocol/blob/main/SECURITY.md).
js/compressed-token/README.md (1)

41-43: Nit: add terminal punctuation and fix “stacktraces”

Minor readability polish for the help checklist.

Apply this diff:

- - A detailed description of what you're trying to achieve
- - Source code, if possible
- - The text of any errors you encountered, with stacktraces if available
+ - A detailed description of what you're trying to achieve.
+ - Source code, if possible.
+ - The text of any errors you encountered, with stack traces if available.
prover/client/src/proof_client.rs (2)

164-174: Attach X-API-Key on POST: correct; consider a small helper to DRY

Header injection is right. To avoid duplication and ensure future requests also carry the header, wrap it in a helper.

Apply this diff to simplify here:

-        let mut request = self
-            .client
-            .post(&url)
-            .header("Content-Type", "application/json");
-
-        if let Some(api_key) = &self.api_key {
-            request = request.header("X-API-Key", api_key);
-        }
-
-        request
+        self.with_auth(
+            self.client
+                .post(&url)
+                .header("Content-Type", "application/json"),
+        )
             .body(inputs_json.to_string())
             .send()

And add this helper somewhere in impl ProofClient:

impl ProofClient {
    fn with_auth(&self, req: reqwest::RequestBuilder) -> reqwest::RequestBuilder {
        if let Some(ref api_key) = self.api_key {
            req.header("X-API-Key", api_key)
        } else {
            req
        }
    }
}

383-389: Attach X-API-Key on GET status: mirror POST and reuse helper

This mirrors the POST path correctly. If you adopt the helper above, this becomes more concise and harder to miss in future additions.

Apply this diff:

-        let mut request = self.client.get(status_url);
-
-        if let Some(api_key) = &self.api_key {
-            request = request.header("X-API-Key", api_key);
-        }
-
-        let response = request.send().await.map_err(|e| {
+        let response = self.with_auth(self.client.get(status_url)).send().await.map_err(|e| {
             error!("Failed to send status request for job {}: {}", job_id, e);
             ProverClientError::ProverServerError(format!("Failed to check job status: {}", e))
         })?;
js/compressed-token/CHANGELOG.md (1)

61-78: Fix nested list indentation (markdownlint MD007) and minor style nits

Indent nested bullets by two spaces for consistency and to satisfy MD007.

Apply this diff:

-- new type: TokenPoolInfo
-- Instruction Changes:
-    - `compress`, `mintTo`, `approveAndMintTo`, `compressSplTokenAccount` now require valid TokenPoolInfo
-    - `decompress` now requires an array of one or more TokenPoolInfos.
-    - `decompress`, `transfer` now do not allow state tree overrides.
+- New type: TokenPoolInfo
+- Instruction Changes:
+  - `compress`, `mintTo`, `approveAndMintTo`, `compressSplTokenAccount` now require valid `TokenPoolInfo`
+  - `decompress` now requires an array of one or more `TokenPoolInfo`s.
+  - `decompress`, `transfer` now do not allow state tree overrides.
 
-- Action Changes:
-    - Removed optional tokenProgramId: PublicKey
-    - removed optional merkleTree: PublicKey
-    - removed optional outputStateTree: PublicKey
-    - added optional stateTreeInfo: StateTreeInfo
-    - added optional tokenPoolInfo: TokenPoolInfo
+- Action Changes:
+  - Removed optional `tokenProgramId: PublicKey`
+  - Removed optional `merkleTree: PublicKey`
+  - Removed optional `outputStateTree: PublicKey`
+  - Added optional `stateTreeInfo: StateTreeInfo`
+  - Added optional `tokenPoolInfo: TokenPoolInfo`
 
-- new instructions:
-    - `approve`, `revoke`: delegated transfer support.
-    - `addTokenPools`: you can now register additional token pool pdas. Use
-      this if you need very high concurrency.
+- New instructions:
+  - `approve`, `revoke`: delegated transfer support.
+  - `addTokenPools`: you can now register additional token pool PDAs. Use this if you need very high concurrency.
js/stateless.js/CHANGELOG.md (1)

166-172: Fix list indentation and a few style nits

Adjust nested bullet indentation to two spaces (MD007) and keep naming consistent.

Apply this diff:

-- ActiveTreeBundle is now a tuple of `tree`, `queue`, `cpiContext`, and `treeType`. `treeType` is a new enum ensuring forward compatibility.
-- Updated LUT addresses for Mainnet and Devnet:
-    - stateTreeLookupTableMainnet = '7i86eQs3GSqHjN47WdWLTCGMW6gde1q96G2EVnUyK2st';
-    - nullifiedStateTreeLookupTableMainnet = 'H9QD4u1fG7KmkAzn2tDXhheushxFe1EcrjGGyEFXeMqT';
-    - stateTreeLookupTableDevnet = '8n8rH2bFRVA6cSGNDpgqcKHCndbFCT1bXxAQG89ejVsh';
-    - nullifiedStateTreeLookupTableDevnet = '5dhaJLBjnVBQFErr8oiCJmcVsx3Zj6xDekGB2zULPsnP';
+- ActiveTreeBundle is now a tuple of `tree`, `queue`, `cpiContext`, and `treeType`. `treeType` is a new enum ensuring forward compatibility.
+- Updated LUT addresses for Mainnet and Devnet:
+  - stateTreeLookupTableMainnet = '7i86eQs3GSqHjN47WdWLTCGMW6gde1q96G2EVnUyK2st';
+  - nullifiedStateTreeLookupTableMainnet = 'H9QD4u1fG7KmkAzn2tDXhheushxFe1EcrjGGyEFXeMqT';
+  - stateTreeLookupTableDevnet = '8n8rH2bFRVA6cSGNDpgqcKHCndbFCT1bXxAQG89ejVsh';
+  - nullifiedStateTreeLookupTableDevnet = '5dhaJLBjnVBQFErr8oiCJmcVsx3Zj6xDekGB2zULPsnP';
@@
-- Multiple State Tree support. Allows you to pass non-default state tree pubkeys to actions and instructions. Comes out of the box with public state trees.
-    - `pickRandomStateTreeAndQueue`
-    - `getLightStateTreeInfo`
+- Multiple State Tree support. Allows you to pass non-default state tree pubkeys to actions and instructions. Comes out of the box with public state trees.
+  - `pickRandomStateTreeAndQueue`
+  - `getLightStateTreeInfo`

Also applies to: 187-190

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

28-36: Public config now carries API key — mind downstream Debug/logging.

Adding pub prover_api_key: Option<String> is correct for capability. Ensure any Debug/trace on configs redacts this since it’s sensitive.

forester/src/epoch_manager.rs (1)

1188-1224: BatchContext wiring: fallbacks & API key propagation verified

  • Call sites for get_nullify_instruction_stream and get_append_instruction_stream have been updated to use the new prover-_* fields.
  • No lingering uses of the old prover_url field were found.

Two optional, low-risk improvements:

  • Extract the default URL into a module-level const &str to eliminate repeated String allocations.
  • Add a debug-level log of which prover endpoint is selected for each operation to simplify troubleshooting.

Example cleanup:

-        let default_prover_url = "http://127.0.0.1:3001".to_string();
+        const DEFAULT_PROVER_URL: &str = "http://127.0.0.1:3001";
         let batch_context = BatchContext {
             // ...
             prover_append_url: self
                 .config
                 .external_services
                 .prover_append_url
                 .clone()
-                .unwrap_or_else(|| default_prover_url.clone()),
+                .unwrap_or_else(|| DEFAULT_PROVER_URL.to_string()),
             prover_update_url: self
                 .config
                 .external_services
                 .prover_update_url
                 .clone()
-                .unwrap_or_else(|| default_prover_url.clone()),
+                .unwrap_or_else(|| DEFAULT_PROVER_URL.to_string()),
             prover_address_append_url: self
                 .config
                 .external_services
                 .prover_address_append_url
                 .clone()
-                .unwrap_or_else(|| default_prover_url.clone()),
+                .unwrap_or_else(|| DEFAULT_PROVER_URL.to_string()),
         };

Please manually verify that no other code paths still reference a single prover_url.

forester-utils/src/instructions/state_batch_append.rs (2)

130-131: Avoid unnecessary String clones when constructing ProofClient

Both prover_url and prover_api_key are only used to build the client and not reused later in this scope. You can avoid allocations by moving them (or by passing string slices if with_config supports it).

Option A (preferred if with_config takes owned Strings):

-        let proof_client = Arc::new(ProofClient::with_config(prover_url.clone(), polling_interval, max_wait_time, prover_api_key.clone()));
+        let proof_client = Arc::new(ProofClient::with_config(prover_url, polling_interval, max_wait_time, prover_api_key));

Option B (if with_config accepts string slices):

-        let proof_client = Arc::new(ProofClient::with_config(prover_url.clone(), polling_interval, max_wait_time, prover_api_key.clone()));
+        let proof_client = Arc::new(ProofClient::with_config(
+            prover_url.as_str(),
+            polling_interval,
+            max_wait_time,
+            prover_api_key.as_deref(),
+        ));

If capture semantics with async_stream::stream! make moving awkward, another low-impact alternative is to build the client once outside the stream block (after the early returns) and clone the Arc inside:

Add (outside the stream, e.g., after Line 88):

let proof_client = Arc::new(ProofClient::with_config(
    prover_url,
    polling_interval,
    max_wait_time,
    prover_api_key,
));

Then remove the client construction at this line and keep using:

let client = Arc::clone(&proof_client);

46-57: Signature change confirmed—call-sites updated; consider docs, changelog & optional refactor

I’ve verified that all calls to get_append_instruction_stream (e.g. in forester/src/processor/v2/state.rs) have been updated to include the new prover_api_key argument. With that in place, here are the remaining non-breaking recommendations:

• Add rustdoc for the new prover_api_key, noting that None omits the header and that it’s treated as a secret (avoid logging).
• If this function is part of your public API surface, update the changelog/semver entry to document the added parameter.
• Optional refactor: bundle (prover_url, prover_api_key, polling_interval, max_wait_time) into a ProverClientConfig struct to prevent future signature churn and improve readability.

pub struct ProverClientConfig {
    pub url: String,
    pub api_key: Option<String>,
    pub polling_interval: Duration,
    pub max_wait_time: Duration,
}
📜 Review details

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

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1eb02d9 and ac366be.

📒 Files selected for processing (17)
  • forester-utils/src/instructions/address_batch_update.rs (4 hunks)
  • forester-utils/src/instructions/state_batch_append.rs (2 hunks)
  • forester-utils/src/instructions/state_batch_nullify.rs (2 hunks)
  • forester/src/cli.rs (1 hunks)
  • forester/src/config.rs (3 hunks)
  • forester/src/epoch_manager.rs (2 hunks)
  • forester/src/processor/v2/address.rs (1 hunks)
  • forester/src/processor/v2/common.rs (1 hunks)
  • forester/src/processor/v2/state.rs (2 hunks)
  • forester/tests/e2e_test.rs (3 hunks)
  • forester/tests/priority_fee_test.rs (1 hunks)
  • forester/tests/test_utils.rs (1 hunks)
  • js/compressed-token/CHANGELOG.md (3 hunks)
  • js/compressed-token/README.md (2 hunks)
  • js/stateless.js/CHANGELOG.md (2 hunks)
  • js/stateless.js/README.md (2 hunks)
  • prover/client/src/proof_client.rs (5 hunks)
🧰 Additional context used
🪛 LanguageTool
js/compressed-token/README.md

[grammar] ~41-~41: There might be a mistake here.
Context: ...ription of what you're trying to achieve - Source code, if possible - The text of a...

(QB_NEW_EN)


[grammar] ~42-~42: There might be a mistake here.
Context: ...ng to achieve - Source code, if possible - The text of any errors you encountered, ...

(QB_NEW_EN)

js/stateless.js/README.md

[style] ~41-~41: Consider using a less common alternative to make your writing sound more unique and professional.
Context: ...shooting Have a question or a problem? Feel free to ask in the [Light](https://discord.gg/C...

(FEEL_FREE_TO_STYLE_ME)


[grammar] ~62-~62: There might be a mistake here.
Context: ...tprotocol/light-protocol/issues/new). - 🔒 For security vulnerabilities, please f...

(QB_NEW_EN)


[grammar] ~62-~62: There might be a mistake here.
Context: ...l/light-protocol/blob/main/SECURITY.md). ## Additional Resources - [Light Protocol R...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ... Resources - Light Protocol Repository - [ZK Compression Official Documentation](h...

(QB_NEW_EN)

js/compressed-token/CHANGELOG.md

[grammar] ~3-~3: There might be a mistake here.
Context: ...g a non-payer mint and freeze authority. - More efficient computebudgets for action...

(QB_NEW_EN)


[grammar] ~4-~4: There might be a mistake here.
Context: ...re efficient computebudgets for actions. - Better DX: Parameter lookup in call sign...

(QB_NEW_EN)


[grammar] ~61-~61: There might be a mistake here.
Context: ... ### Overview - new type: TokenPoolInfo - Instruction Changes: - compress, `...

(QB_NEW_EN)


[grammar] ~67-~67: There might be a mistake here.
Context: ...state tree overrides. - Action Changes: - Removed optional tokenProgramId: PublicK...

(QB_NEW_EN)


[grammar] ~74-~74: There might be a mistake here.
Context: ...Info: TokenPoolInfo - new instructions: - approve, revoke: delegated transfer support. ...

(QB_NEW_EN)

js/stateless.js/CHANGELOG.md

[grammar] ~39-~39: There might be a mistake here.
Context: ...hanges - Renamed ActiveTreeBundle to StateTreeInfo - Updated StateTreeInfo internal structu...

(QB_NEW_EN)


[grammar] ~40-~40: There might be a mistake here.
Context: ...ted StateTreeInfo internal structure: { tree: PublicKey, queue: PublicKey, cpiContext: PublicKey | null, treeType: TreeType } - Replaced pickRandomTreeAndQueue with `...

(QB_NEW_EN)


[grammar] ~41-~41: There might be a mistake here.
Context: ... Replaced pickRandomTreeAndQueue with selectStateTreeInfo - Use selectStateTreeInfo for tree selec...

(QB_NEW_EN)


[grammar] ~167-~167: There might be a mistake here.
Context: ...ed LUT addresses for Mainnet and Devnet: - stateTreeLookupTableMainnet = '7i86eQs3G...

(QB_NEW_EN)


[grammar] ~168-~168: There might be a mistake here.
Context: ...s3GSqHjN47WdWLTCGMW6gde1q96G2EVnUyK2st'; - nullifiedStateTreeLookupTableMainnet = '...

(QB_NEW_EN)


[grammar] ~169-~169: There might be a mistake here.
Context: ...1fG7KmkAzn2tDXhheushxFe1EcrjGGyEFXeMqT'; - stateTreeLookupTableDevnet = '8n8rH2bFRV...

(QB_NEW_EN)


[grammar] ~170-~170: There might be a mistake here.
Context: ...bFRVA6cSGNDpgqcKHCndbFCT1bXxAQG89ejVsh'; - nullifiedStateTreeLookupTableDevnet = '5...

(QB_NEW_EN)


[grammar] ~195-~195: There might be a mistake here.
Context: ...amId explicitly. is backward compatible with boolean flag for t22. ### Deprecated ...

(QB_NEW_EN)

🪛 markdownlint-cli2 (0.17.2)
js/compressed-token/CHANGELOG.md

63-63: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


64-64: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


65-65: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


68-68: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


69-69: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


70-70: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


71-71: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


72-72: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


75-75: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


76-76: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)

js/stateless.js/CHANGELOG.md

168-168: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


169-169: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


170-170: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


171-171: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


188-188: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


189-189: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Forester e2e test
  • GitHub Check: cli-v2
  • GitHub Check: stateless-js-v2
  • GitHub Check: Test program-libs-fast
  • GitHub Check: Test concurrent-merkle-tree
  • GitHub Check: Test sdk-libs
  • GitHub Check: lint
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: Test program-libs-slow
  • GitHub Check: stateless-js-v1
  • GitHub Check: cli-v1
🔇 Additional comments (22)
js/stateless.js/README.md (1)

66-67: LGTM on resource links

Link text and targets look correct and consistent with the rest of the document.

js/compressed-token/README.md (1)

31-32: Formatting-only change LGTM

The switch to standard bullets improves readability. No content changes.

prover/client/src/proof_client.rs (1)

54-55: API key plumbing into ProofClient fully verified

  • All ProofClient::with_config calls now include the new api_key argument:
    • forester-utils/src/instructions/address_batch_update.rs:54
    • forester-utils/src/instructions/state_batch_nullify.rs:129
    • forester-utils/src/instructions/state_batch_append.rs:130
  • No legacy 3-argument invocations remain (all report commas=3, i.e. four parameters).
  • The request header uses "X-API-Key" consistently in proof_client.rs (lines 170 and 386).

Everything looks correct—no further changes needed.

js/stateless.js/CHANGELOG.md (1)

39-43: Breaking-changes bullets LGTM

Renames and replacements are clearly listed and consistent with the migration guide.

forester/src/processor/v2/address.rs (1)

30-35: Good: per-operation endpoint + API-key plumbed (resolves “hardcoded endpoint” concern).

Switching to ctx.prover_address_append_url and threading ctx.prover_api_key into AddressUpdateConfig looks correct and aligns with the new split endpoints design. This resolves the earlier feedback about hardcoding the endpoint.

forester/tests/priority_fee_test.rs (1)

41-41: LGTM: explicit None keeps the test isolated.

Setting prover_api_key: None is appropriate for this test and shouldn’t affect behavior due to fallback handling elsewhere.

forester/tests/e2e_test.rs (3)

117-123: Rename to get_photon_api_key is clear and consistent.

Returning None for Local and Some(PHOTON_API_KEY) for Devnet matches the intended test behavior. No issues spotted.


194-201: Config wiring for prover_api_key and photon_api_key is correct.

Passing both keys through ExternalServicesConfig mirrors production config. Looks good.


464-465: LightClientConfig initialization updated to use photon API key.

Using get_photon_api_key() for the third parameter matches the new signature expectation and keeps Local behavior intact.

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

39-51: API key threaded into stream builder signature cleanly.

Extending stream_instruction_data to accept prover_api_key keeps the surface area minimal and avoids global state. Looks good.


325-337: Correct: passing config.prover_api_key into stream builder.

This completes the end-to-end plumbing needed for authenticated prover calls. No issues.


54-55: No raw API key logging in ProofClient – resolved

Verified across the codebase that ProofClient::with_config only sets the X-API-Key header when Some(key) and contains no log/debug/trace calls exposing the raw key.

forester/src/config.rs (2)

211-236: Nice fallback behavior preserves backward compatibility.

Defaulting operation-specific prover URLs to prover_url when omitted is the right call for existing deployments. The mapping looks correct.


301-304: Status config zeroes API-related fields — correct for read-only mode.

Explicitly setting the new prover fields to None makes status calls environment-agnostic. LGTM.

forester/src/cli.rs (3)

37-43: Per-operation append URL: looks good.

Clear naming and helpful fallback hint. This aligns with downstream usage in BatchContext and state append stream.


44-50: Per-operation update URL: looks good.

Consistent with nullify/update flow in state processing; fallback wording matches the config behavior.


51-57: Address-append URL: looks good.

Consistent naming and help text. Downstream address pipeline can pick this up cleanly.

forester/src/processor/v2/common.rs (1)

43-47: BatchContext now models per-operation endpoints + API key: good foundation.

Public fields are clear and map 1:1 to the new CLI/config. Downstream state/address processors can select the right endpoint.

forester-utils/src/instructions/state_batch_nullify.rs (2)

46-55: API key plumbed into nullify stream: signature change looks sound.

The new optional prover_api_key parameter is in a sensible position after prover_url and matches how state.rs calls it.


128-130: Forward API key to ProofClient configuration: correct usage.

Constructing a single Arc per stream prevents redundant clients and properly carries the X-API-Key header downstream.

forester/src/processor/v2/state.rs (2)

32-37: Nullify path uses update URL + API key: correct.

The parameter order matches the updated function signature in forester-utils, and correctly uses the update endpoint.


59-64: Append path uses append URL + API key: correct.

Consistent with per-operation endpoint design and ProofClient expectations.

Comment on lines +58 to +60
#[arg(long, env = "FORESTER_PROVER_API_KEY")]
pub prover_api_key: Option<String>,

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid leaking prover_api_key in logs/debug output.

StartArgs derives Debug, which can unintentionally log the API key. Redact the value and hide env values in help/error output.

Apply this diff to avoid exposing the key in Clap output and improve UX:

-    #[arg(long, env = "FORESTER_PROVER_API_KEY")]
+    #[arg(long, env = "FORESTER_PROVER_API_KEY", hide_env_values = true, value_name = "PROVER_API_KEY")]
     pub prover_api_key: Option<String>,

Additionally, consider replacing the auto-derived Debug for StartArgs with a manual Debug that redacts secrets (outside the shown hunk). Example:

impl std::fmt::Debug for StartArgs {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("StartArgs")
            .field("rpc_url", &self.rpc_url)
            .field("push_gateway_url", &self.push_gateway_url)
            .field("pagerduty_routing_key", &self.pagerduty_routing_key.as_ref().map(|_| "<redacted>"))
            .field("ws_rpc_url", &self.ws_rpc_url)
            .field("indexer_url", &self.indexer_url)
            .field("prover_url", &self.prover_url)
            .field("prover_append_url", &self.prover_append_url)
            .field("prover_update_url", &self.prover_update_url)
            .field("prover_address_append_url", &self.prover_address_append_url)
            .field("prover_api_key", &self.prover_api_key.as_ref().map(|_| "<redacted>"))
            // ... add remaining fields as needed
            .finish()
    }
}

Or use a secret wrapper type to enforce redaction at the type level.

🤖 Prompt for AI Agents
In forester/src/cli.rs around lines 58–60, the prover_api_key field is declared
with #[arg(long, env = "FORESTER_PROVER_API_KEY")] which can expose the secret
via Clap help/error output and the auto-derived Debug; update the arg attribute
to hide environment values (e.g., add hide_env_values = true) so the env value
is not printed, and replace the auto-derived Debug for StartArgs with a manual
Debug implementation that redacts prover_api_key (e.g., display "<redacted>"
when Some) or use a secret wrapper type so the API key is never shown in logs or
help output.

Comment on lines +38 to 42
pub prover_append_url: Option<String>,
pub prover_update_url: Option<String>,
pub prover_address_append_url: Option<String>,
pub prover_api_key: Option<String>,
pub photon_api_key: Option<String>,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Security: ExternalServicesConfig derives Debug and now includes secrets — redact or remove.

ExternalServicesConfig derives Debug while holding prover_api_key and photon_api_key. Any accidental debug log will leak credentials. Redact these in Debug or stop deriving Debug.

Apply a custom Debug impl that redacts secrets:

// Replace: #[derive(Debug, Clone)]
#[derive(Clone)]
pub struct ExternalServicesConfig {
    // ... fields unchanged ...
}

// Add this impl nearby
impl std::fmt::Debug for ExternalServicesConfig {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ExternalServicesConfig")
            .field("rpc_url", &self.rpc_url)
            .field("ws_rpc_url", &self.ws_rpc_url)
            .field("indexer_url", &self.indexer_url)
            .field("prover_url", &self.prover_url)
            .field("prover_append_url", &self.prover_append_url)
            .field("prover_update_url", &self.prover_update_url)
            .field("prover_address_append_url", &self.prover_address_append_url)
            .field("prover_api_key", &"<REDACTED>")
            .field("photon_api_key", &"<REDACTED>")
            .field("pushgateway_url", &self.pushgateway_url)
            .field("pagerduty_routing_key", &self.pagerduty_routing_key)
            .field("rpc_rate_limit", &self.rpc_rate_limit)
            .field("photon_rate_limit", &self.photon_rate_limit)
            .field("send_tx_rate_limit", &self.send_tx_rate_limit)
            .finish()
    }
}

Alternatively, use a secrecy type (e.g., secrecy::SecretString) for keys, which redacts Debug output by default.

🤖 Prompt for AI Agents
In forester/src/config.rs around lines 38-42, ExternalServicesConfig currently
derives Debug while containing prover_api_key and photon_api_key; remove the
Debug derive and either implement a custom std::fmt::Debug that prints all
non-secret fields but replaces prover_api_key and photon_api_key with
"<REDACTED>", or change those two fields to a secrecy wrapper type (e.g.,
secrecy::SecretString) which already redacts Debug output; update the struct
attribute to #[derive(Clone)] and add the custom Debug impl (or change types)
nearby, ensuring any existing uses that relied on the derived Debug are updated
accordingly.

Comment on lines +124 to +129
fn get_prover_api_key() -> Option<String> {
match TestMode::from_env() {
TestMode::Local => None,
TestMode::Devnet => Some(get_env_var("PROVER_API_KEY")),
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Potential env var naming drift: PROVER_API_KEY vs FORESTER_PROVER_API_KEY.

This test uses PROVER_API_KEY, while other parts of the repo/PR (and prior notes) mention FORESTER_PROVER_API_KEY. Inconsistent naming will cause CI/test flakiness across environments.

Run this script to inventory usages and confirm a single, consistent env var name:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Env var references (PROVER_API_KEY | FORESTER_PROVER_API_KEY | PHOTON_API_KEY):"
rg -n -C1 -P 'env::var\("(PROVER_API_KEY|FORESTER_PROVER_API_KEY|PHOTON_API_KEY)"\)'

echo
echo "All occurrences of prover_api_key symbol:"
rg -n -C2 '\bprover_api_key\b'

echo
echo "StartArgs definition and field list (to confirm CLI wiring):"
rg -n -C3 -U 'struct\s+StartArgs\b.*?{' || true

echo
echo "Look for any docs or README references to prover API key to ensure consistency:"
rg -n -C2 -i 'prover api key|PROVER_API_KEY|FORESTER_PROVER_API_KEY|photon api key|PHOTON_API_KEY' || true

Length of output: 27268


Align env var names for prover API key across code, tests, and docs
The CLI is wired to FORESTER_PROVER_API_KEY, but in forester/tests/e2e_test.rs we still call get_env_var("PROVER_API_KEY"). This mismatch (and the equivalent one for PHOTON_API_KEY) will break in CI when only the FORESTER_… vars are set. Update as follows:

• In forester/tests/e2e_test.rs, change get_prover_api_key to use "FORESTER_PROVER_API_KEY":

 fn get_prover_api_key() -> Option<String> {
     match TestMode::from_env() {
         TestMode::Local => None,
-        TestMode::Devnet => Some(get_env_var("PROVER_API_KEY")),
+        TestMode::Devnet => Some(get_env_var("FORESTER_PROVER_API_KEY")),
     }
 }

• Likewise, in the same file update get_photon_api_key to "FORESTER_PHOTON_API_KEY":

 fn get_photon_api_key() -> Option<String> {
     match TestMode::from_env() {
         TestMode::Local => None,
-        TestMode::Devnet => Some(get_env_var("PHOTON_API_KEY")),
+        TestMode::Devnet => Some(get_env_var("FORESTER_PHOTON_API_KEY")),
     }
 }

• Update forester/README.md examples to consistently reference FORESTER_PROVER_API_KEY and FORESTER_PHOTON_API_KEY instead of the unprefixed names.

These fixes will ensure the env-var wiring is uniform and tests won’t silently fail in CI.

📝 Committable suggestion

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

Suggested change
fn get_prover_api_key() -> Option<String> {
match TestMode::from_env() {
TestMode::Local => None,
TestMode::Devnet => Some(get_env_var("PROVER_API_KEY")),
}
}
// forester/tests/e2e_test.rs
fn get_prover_api_key() -> Option<String> {
match TestMode::from_env() {
TestMode::Local => None,
TestMode::Devnet => Some(get_env_var("FORESTER_PROVER_API_KEY")),
}
}
fn get_photon_api_key() -> Option<String> {
match TestMode::from_env() {
TestMode::Local => None,
TestMode::Devnet => Some(get_env_var("FORESTER_PHOTON_API_KEY")),
}
}
🤖 Prompt for AI Agents
In forester/tests/e2e_test.rs around lines 124 to 129, the test helper uses the
unprefixed env var names ("PROVER_API_KEY" and similarly "PHOTON_API_KEY") while
the CLI and CI expect the FORESTER_ prefixed names, causing CI failures; update
get_prover_api_key to call get_env_var("FORESTER_PROVER_API_KEY") and update
get_photon_api_key to call get_env_var("FORESTER_PHOTON_API_KEY") accordingly,
then also update forester/README.md examples to reference
FORESTER_PROVER_API_KEY and FORESTER_PHOTON_API_KEY so docs, tests, and CLI use
the same env var names.

Comment on lines +3 to +6
- `CreateMint` action now allows passing a non-payer mint and freeze authority.
- More efficient computebudgets for actions.
- Better DX: Parameter lookup in call signatures of CompressedTokenProgram instructions
- QoL: improved typedocs.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix minor wording/typos

  • “computebudgets” → “compute budgets”
  • “typedocs” → “TypeDoc comments”

Apply this diff:

-- More efficient computebudgets for actions.
-— QoL: improved typedocs.
+- More efficient compute budgets for actions.
+- QoL: improved TypeDoc comments.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 LanguageTool

[grammar] ~3-~3: There might be a mistake here.
Context: ...g a non-payer mint and freeze authority. - More efficient computebudgets for action...

(QB_NEW_EN)


[grammar] ~4-~4: There might be a mistake here.
Context: ...re efficient computebudgets for actions. - Better DX: Parameter lookup in call sign...

(QB_NEW_EN)

🤖 Prompt for AI Agents
In js/compressed-token/CHANGELOG.md around lines 3 to 6, fix the minor
wording/typos: change “computebudgets” to “compute budgets” and change
“typedocs” to “TypeDoc comments” so the bullet list reads with the corrected
terms; update only those words preserving the rest of the lines and punctuation.

Comment on lines +116 to 119
- `selectMinCompressedTokenAccountsForTransfer` and
`selectMinCompressedTokenAccountsForTransferorPartial` now accept an optional
`maxInputs` parameter, defaulting to 4.

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Typo: method name casing

Looks like a stray typo in the method name (“TransferorPartial”). Should be TransferOrPartial to match the casing used elsewhere.

Apply this diff:

-  `selectMinCompressedTokenAccountsForTransferorPartial` now accept an optional
+  `selectMinCompressedTokenAccountsForTransferOrPartial` now accept an optional
📝 Committable suggestion

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

Suggested change
- `selectMinCompressedTokenAccountsForTransfer` and
`selectMinCompressedTokenAccountsForTransferorPartial` now accept an optional
`maxInputs` parameter, defaulting to 4.
- `selectMinCompressedTokenAccountsForTransfer` and
`selectMinCompressedTokenAccountsForTransferOrPartial` now accept an optional
`maxInputs` parameter, defaulting to 4.
🤖 Prompt for AI Agents
In js/compressed-token/CHANGELOG.md around lines 116 to 119, the method name
casing contains a typo "TransferorPartial"; update the text to use the correct
casing "TransferOrPartial" so it matches the rest of the codebase and other
references, i.e., replace "selectMinCompressedTokenAccountsForTransferorPartial"
with "selectMinCompressedTokenAccountsForTransferOrPartial".

### Changed

- `createMint`action now lets you pass tokenprogramId explicitly. is backward compatible with boolean flag for t22.
- `createMint`action now lets you pass tokenprogramId explicitly. is backward compatible with boolean flag for t22.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix spacing/casing and sentence capitalization

Minor doc polish.

Apply this diff:

-- `createMint`action now lets you pass tokenprogramId explicitly. is backward compatible with boolean flag for t22.
+- `createMint` action now lets you pass `tokenProgramId` explicitly. This is backward compatible with the boolean flag for t22.
📝 Committable suggestion

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

Suggested change
- `createMint`action now lets you pass tokenprogramId explicitly. is backward compatible with boolean flag for t22.
- `createMint` action now lets you pass `tokenProgramId` explicitly. This is backward compatible with the boolean flag for t22.
🧰 Tools
🪛 LanguageTool

[grammar] ~195-~195: There might be a mistake here.
Context: ...amId explicitly. is backward compatible with boolean flag for t22. ### Deprecated ...

(QB_NEW_EN)

🤖 Prompt for AI Agents
In js/stateless.js/CHANGELOG.md around line 195, the changelog entry has
spacing/casing and sentence-capitalization issues; add a space after the closing
backtick so it reads "`createMint` action", change "tokenprogramId" to
"tokenProgramId" (camelCase), and capitalize the start of the second sentence so
it reads "Is backward compatible..." (or preferably merge into a single sentence
with proper punctuation: "...explicitly and is backward compatible with the
boolean flag for t22.").

@sergeytimoshin sergeytimoshin merged commit 4174716 into main Aug 18, 2025
21 of 24 checks passed
@sergeytimoshin sergeytimoshin deleted the sergey/prover-api-key branch August 18, 2025 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants