Skip to content

Conversation

@Scratch-net
Copy link
Contributor

@Scratch-net Scratch-net commented Dec 20, 2025

Note

Implements on-demand ZK circuit initialization and tightens protocol success validation.

  • Add client/zkprover.go: algorithm ID/cipher mapping, init-state tracking, SetZKInitCallback, InitAlgorithmWithTracking, and EnsureAlgorithmInitialized; invoked from client/oprf.go before Prove
  • Update lib/libreclaim.go: expose SetZKInitCallback, GetAlgorithmID, GetCipherName, IsAlgorithmInitialized; route init via tracking wrapper; bridge C callback; add CGO shims
  • Update demos (demo_lib, demo_standalone): set up lazy-loading callbacks that load circuit files and initialize algorithms on demand; adjust LDFLAGS path
  • Change result success in client/results_build.go to transcripts.BothReceived && validation.AttestationValidation.OverallValid && c.responseProcessingSuccessful; update error messages accordingly
  • Switch JSONPath lib to github.com/reclaimprotocol/jsonpathplus-go/v2 and bump deps in go.mod/go.sum

Written by Cursor Bugbot for commit 7eecbcf. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • New Features

    • On‑demand (lazy) loading of ZK circuits and algorithms with a callback-driven initialization path.
    • Public ways to register/init algorithms and query their initialization status from the API.
  • Bug Fixes

    • Guard added to prevent proof generation when an algorithm is not initialized.
    • Result-building error logic narrowed to rely on attestation validation outcomes.
  • Chores

    • Switched from eager to deferred algorithm setup to reduce startup work and updated dependency versions.

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

@coderabbitai
Copy link

coderabbitai bot commented Dec 20, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Introduces lazy-loading for ZK circuit initialization with client-side algorithm constants and tracking, a CGO callback bridge for on-demand loading, demo updates to resolve circuit paths and load PK/R1CS files at runtime, and a guard in proof generation to ensure algorithm initialization before creating ZK proofs.

Changes

Cohort / File(s) Summary
Client ZK init & guards
client/zkprover.go, client/oprf.go
Add algorithm constants, bidirectional cipher↔ID mappings, a ZKInitCallback type, RWMutex-protected initialization tracking, APIs to register/query/mark init state, InitAlgorithmWithTracking wrapper, and EnsureAlgorithmInitialized used by generateZKProof.
CGO / library bridge
lib/libreclaim.go
Add C callback type and registration (SetZKInitCallback), Go wrapper invoking C callback, export GetAlgorithmID/GetCipherName/IsAlgorithmInitialized, and route InitAlgorithm through client.InitAlgorithmWithTracking.
Demo — lazy-loading & C interop updates
demo_lib/main.go, demo_standalone/main.go
Replace GoSlice with LibGoSlice, add zk_init_callback_t and exported goZKInitCallback, introduce circuitConfig registry and circuitsDir resolution, and switch from eager initialization to setupZKLazyLoading/zkInitCallback that loads PK/R1CS from disk and initializes algorithms on-demand.
Result building logic change
client/results_build.go
Change success/error evaluation to rely on validation.AttestationValidation.OverallValid (and transcripts.BothReceived / response processing) instead of previous combined signature/validation flags.
Dependency & import updates
go.mod, providers/json_positioned.go
Bump multiple module versions in go.mod and update import path for jsonpath to .../v2 in providers/json_positioned.go.

Sequence Diagram

sequenceDiagram
    participant Caller as Proof Generation
    participant Client as client.EnsureAlgorithmInitialized
    participant State as Algorithm State (RWMutex map)
    participant Callback as Registered Init Callback (Go/C)
    participant FileIO as Disk (PK/R1CS)
    participant Init as InitAlgorithmWithTracking

    Caller->>Client: EnsureAlgorithmInitialized(cipher)
    Client->>Client: Resolve cipher -> algorithmID
    Client->>State: IsAlgorithmInitialized(ID)?
    alt already initialized
        State-->>Client: true
        Client-->>Caller: proceed
    else not initialized
        State-->>Client: false
        Client->>Callback: invoke init callback(ID)
        Callback->>FileIO: load provingKey & r1cs
        FileIO-->>Callback: return data
        Callback->>Init: InitAlgorithmWithTracking(ID, provingKey, r1cs)
        Init->>Init: call underlying InitAlgorithm
        Init->>State: MarkAlgorithmInitialized(ID)
        Init-->>Callback: success/failure
        alt success
            Callback-->>Client: true
            Client-->>Caller: proceed
        else failure
            Callback-->>Client: false
            Client-->>Caller: error
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 I waited by the circuit gate,
Files on demand, not early, not late.
A CGO tap, a gentle nudge—hooray!
Keys stream in and proofs find their way.
I hop in joy: lazy-load saved the day.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[FEAT] lazy-loading circuits' accurately describes the main feature introduced: a lazy-loading mechanism for zero-knowledge circuits that is added across client, library, and demo components.
Docstring Coverage ✅ Passed Docstring coverage is 90.91% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch lazy-circuits

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b45e31e and 7eecbcf.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (2)
  • go.mod
  • providers/json_positioned.go
⏰ 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). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (3)
go.mod (2)

33-90: Broad indirect dependency refresh detected.

Multiple indirect dependencies have been updated across cloud, crypto, telemetry, and Google API packages. While these are indirect dependencies and typically managed automatically, be aware of the scope of changes for troubleshooting potential issues.


14-14: All dependency versions are valid and stable with no known vulnerabilities.

The updated dependencies have been verified:

  • github.com/go-acme/lego/v4 v4.30.1 — stable, prior CVE-2025-54799 fixed in v4.25.2
  • github.com/reclaimprotocol/jsonpathplus-go/v2 v2.0.1 (major version upgrade) — stable, no known advisories
  • github.com/reclaimprotocol/xpath-go v1.4.0 — stable, no known advisories
  • golang.org/x/crypto v0.46.0 — stable, includes fixes for prior CVEs (CVE-2025-22869, CVE-2025-47914, CVE-2025-58181)
  • google.golang.org/protobuf v1.36.11 — stable, no known vulnerabilities
providers/json_positioned.go (1)

9-9: The upgrade to jsonpathplus-go v2 is compatible with the current codebase. The v2.0.1 API maintains the top-level Query(path, jsonStr) function being used at line 22, and the code has already been adapted to handle v2's breaking change regarding object property indexing (key–value range tracking instead of value-only ranges). The findKeyValueRange() function and its integration in findNodeBySegments() explicitly implement the v2 semantics, as evidenced by the key–value range handling logic at lines 50–61 and 136–143.


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

❤️ Share

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

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

This PR is being reviewed by Cursor Bugbot

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Copy link

@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: 3

🧹 Nitpick comments (1)
demo_lib/main.go (1)

59-94: Code duplication: circuitConfig and circuitsRegistry are duplicated across files.

The same circuitConfig struct and circuitsRegistry map are defined identically in demo_lib/main.go, demo_standalone/main.go, and partially in client/zkprover.go. Consider extracting this into a shared package to maintain a single source of truth for circuit configuration.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9dd8289 and 6a7d4da.

📒 Files selected for processing (5)
  • client/oprf.go (1 hunks)
  • client/zkprover.go (1 hunks)
  • demo_lib/main.go (3 hunks)
  • demo_standalone/main.go (3 hunks)
  • lib/libreclaim.go (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
client/oprf.go (1)
client/zkprover.go (1)
  • EnsureAlgorithmInitialized (106-130)
demo_standalone/main.go (4)
client/zkprover.go (5)
  • CHACHA20_OPRF (15-15)
  • AES_128_OPRF (16-16)
  • AES_256_OPRF (17-17)
  • InitAlgorithmWithTracking (95-101)
  • SetZKInitCallback (57-63)
demo_lib/main.go (3)
  • CHACHA20_OPRF (61-61)
  • AES_128_OPRF (62-62)
  • AES_256_OPRF (63-63)
client/logger.go (1)
  • GetLogger (12-31)
lib/libreclaim.go (1)
  • SetZKInitCallback (331-357)
client/zkprover.go (1)
lib/libreclaim.go (5)
  • SetZKInitCallback (331-357)
  • IsAlgorithmInitialized (376-378)
  • GetAlgorithmID (360-364)
  • GetCipherName (367-373)
  • InitAlgorithm (285-323)
⏰ 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). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (12)
demo_lib/main.go (1)

196-203: LGTM: Graceful fallback on lazy loading setup failure.

The main function properly handles the case where lazy loading setup fails by logging a warning and continuing execution. This is appropriate for a demo application.

client/oprf.go (1)

314-319: LGTM: Clean integration of lazy initialization.

The lazy initialization check is correctly placed before ZK proof generation. The error handling properly wraps the underlying error with context, and the change aligns well with the new EnsureAlgorithmInitialized function in client/zkprover.go.

demo_standalone/main.go (2)

27-46: Good: Uses constants from impl package instead of redeclaring.

Unlike demo_lib/main.go, this file correctly references impl.CHACHA20_OPRF, impl.AES_128_OPRF, and impl.AES_256_OPRF from the shared prover package, which helps maintain consistency.


170-174: Appropriate behavior: Fatal error on lazy loading setup failure.

For a standalone demo application, failing fast with log.Fatalf when ZK lazy loading setup fails is appropriate, as the application cannot function without this capability.

lib/libreclaim.go (3)

30-44: Consider thread-safety of C global callback pointer.

The g_zk_init_callback C static variable is read and written without synchronization on the C side. While the Go side uses proper locking (zkInitCallbackLock in client/zkprover.go), concurrent calls to SetZKInitCallback and invoke_zk_init_callback from multiple threads could race on the C side.

If this library is used in a multi-threaded context where the callback might be set while proving is in progress, consider adding synchronization.


315-316: LGTM: Proper delegation to tracking wrapper and callback chain.

The InitAlgorithm function correctly delegates to client.InitAlgorithmWithTracking, and the cZKInitCallback wrapper properly bridges the Go-C boundary by invoking the stored C callback.

Also applies to: 325-328


330-357: LGTM: SetZKInitCallback properly wires Go and C callbacks.

The function correctly:

  1. Initializes the logger if needed
  2. Stores the C callback via the internal setter
  3. Wires up the Go-side callback to invoke the C callback
  4. Clears both callbacks when passed nil
client/zkprover.go (5)

46-51: LGTM: Thread-safe global state management.

The use of separate sync.RWMutex instances for the callback (zkInitCallbackLock) and initialization state (initializedLock) is appropriate and provides correct synchronization for concurrent access.


20-38: LGTM: Bidirectional cipher name mapping.

The cipherToAlgorithmID and algorithmIDToCipher maps provide clean bidirectional lookup between cipher names and algorithm IDs. The cipher names appear to follow a consistent naming convention.


94-101: LGTM: Clean wrapper for initialization with tracking.

InitAlgorithmWithTracking correctly wraps the underlying prover.InitAlgorithm call and marks the algorithm as initialized only on success.


103-129: Confirm TOCTOU vulnerability between IsAlgorithmInitialized check and callback invocation.

The race condition is real: concurrent callers can both see IsAlgorithmInitialized return false and invoke the callback for the same algorithm simultaneously. Since no lock guards the gap between the check (line 112) and callback invocation (line 124), both goroutines will call cb(algorithmID)InitAlgorithmWithTrackingprover.InitAlgorithm concurrently.

This is acceptable only if prover.InitAlgorithm is idempotent and handles double-initialization safely. Otherwise, consider:

  • Using sync.Once per algorithm to ensure single initialization
  • Holding a lock during both the check and callback invocation
  • Double-checking the initialized state after acquiring a lock

10-18: Ensure algorithm ID constants are synchronized with upstream github.com/reclaimprotocol/zk-symmetric-crypto/gnark/libraries/prover/impl package.

These constants are duplicated locally from the upstream impl package. Verify that CHACHA20, AES_128, AES_256, CHACHA20_OPRF, AES_128_OPRF, and AES_256_OPRF maintain the same values (0-5 respectively) in the external dependency to prevent subtle mismatches during proving operations.

Copy link

@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: 1

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a7d4da and b45e31e.

📒 Files selected for processing (1)
  • client/results_build.go (1 hunks)
⏰ 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). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (1)
client/results_build.go (1)

23-24: Improved error message specificity.

The updated error handling provides clearer feedback with "Attestation validation failed" instead of separate checks for signatures and general validation. This aligns well with the consolidated validation approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants