Skip to content

fix: isolate native BLS binding errors by OS thread - #7825

Closed
PastaPastaPasta wants to merge 1 commit into
dashpay:developfrom
PastaPastaPasta:codex/security-bls-error-ownership
Closed

PastaPastaPasta wants to merge 1 commit into
dashpay:developfrom
PastaPastaPasta:codex/security-bls-error-ownership

Conversation

@PastaPastaPasta

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

Concurrent consumers of the bundled Go or Rust BLS bindings can overwrite a process-global native error string while another call copies its borrowed error pointer. This creates shared-storage races and can report another thread's error. Dash Core calls the native C++ API directly; daemon impact has not been established.

What was done?

Give each native OS thread its own last-error string in both bridges. Pin all 12 Go error-returning entrypoints from the native operation through the owned error copy, with balanced deferred unlocking. Rust already calls and copies synchronously on one thread. Document the borrowed getter lifetime and add ordinary, channel-serialized ownership regressions plus concurrent public Go correctness checks.

How Has This Been Tested?

On Apple Silicon/macOS, using the existing Dash depends prefix and one build job:

  • Native make -C src/dashbls -j1 and full runtest: 1,417 assertions across 17 cases passed.
  • Actual Go bridge focused ownership/concurrent tests, full go test -p 1 -count=1 ./..., and go vet -p 1 ./... passed, linked against this worktree's native archives.
  • Actual Rust/C/native sys suite (three integration tests) and safe crate suite (23 tests) passed in an exact-source disposable copy. Build-only setup restored the matching ignored Relic CMake template and constrained the existing hardcoded CMake parallelism to one job.
  • Serialized Go and Rust ownership tests failed after restoring global error storage, with the first thread reading the second thread's G2 error, and passed with TLS restored. Rust required a clean rebuild to invalidate cached native objects; the initial cached comparison was discarded. Concurrent stress was run only on the fixed candidate.
  • Exported C function/getter symbols in the changed native objects and public header signatures matched baseline. C++ TLS variable/helper symbols change; no general binary compatibility claim is made.
  • Normal make -j1, Core bls_tests, whitespace lint, Go/Rust formatting and diff checks passed.

The Go stress table covers four entrypoints; all 12 pinning sites were inspected independently. Rust's ownership regression exercises the sys API, while the unchanged safe copier was inspected and its existing suite passed. No TSan result, reliable crash, memory disclosure, deployed consumer reachability, or daemon exploit is claimed.

Breaking Changes

Exported C function signatures remain unchanged. Raw C consumers must retrieve and copy an error on the native thread that produced it, before another failure on that thread or thread exit. Direct C++ consumers of gErrMsg must use the matching thread_local declaration and recompile the bridge objects together.

Checklist:

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone

This pull request was created by Codex.

@coderabbitai

coderabbitai Bot commented Oct 7, 2026

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3516a617-93a2-4cb4-aa34-7686b0f30622
📥 Commits

Reviewing files that changed from the base of the PR and between f35a24c and df45987.

📒 Files selected for processing (14)
  • src/dashbls/go-bindings/blschia.cpp
  • src/dashbls/go-bindings/blschia.h
  • src/dashbls/go-bindings/elements.go
  • src/dashbls/go-bindings/error.go
  • src/dashbls/go-bindings/error.h
  • src/dashbls/go-bindings/error_test.go
  • src/dashbls/go-bindings/privatekey.go
  • src/dashbls/go-bindings/schemes.go
  • src/dashbls/go-bindings/threshold.go
  • src/dashbls/rust-bindings/bls-dash-sys/bindings.rs
  • src/dashbls/rust-bindings/bls-dash-sys/c-bindings/blschia.cpp
  • src/dashbls/rust-bindings/bls-dash-sys/c-bindings/blschia.h
  • src/dashbls/rust-bindings/bls-dash-sys/c-bindings/error.h
  • src/dashbls/rust-bindings/bls-dash-sys/tests/error_messages.rs

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review.


Walkthrough

The native Go and Rust C bindings now store BLS error messages per OS thread. The Go bindings lock the goroutine to its current OS thread during C binding calls. Comments describe the thread scope and pointer validity of GetLastErrorMsg. Go and Rust tests check error-message ownership across threads and exercise valid and invalid inputs.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant G1ElementFromBytes
  participant GoRuntime
  participant CBinding
  participant gErrMsg
  participant errFromC
  G1ElementFromBytes->>GoRuntime: LockOSThread
  G1ElementFromBytes->>CBinding: Convert bytes
  CBinding->>gErrMsg: Store error on current OS thread
  CBinding-->>G1ElementFromBytes: Return conversion result
  G1ElementFromBytes->>errFromC: Copy thread-local error
  G1ElementFromBytes->>GoRuntime: UnlockOSThread
Loading

Merge Risk: ⚪ Minimal · up to df459

This change makes native BLS error messages per-thread, so concurrent failures no longer overwrite each other's messages. No actionable merge-blocking risk is identified in the supplied changes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 68.75% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 16 functions across 14 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: isolating native BLS binding errors by OS thread.
Description check ✅ Passed The description explains the error-storage change, Go and Rust binding behavior, compatibility considerations, and reported tests. It is directly related to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@thepastaclaw

thepastaclaw commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

✅ Final review complete — no blockers (commit df45987) · triage: normal

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Final validation — Phase 1 + Phase 2

Static verification at df45987 found no actionable in-scope defects: both native bridges consistently use thread-local error storage, all 12 Go error-copying entrypoints retain balanced OS-thread pinning, and Rust copies errors synchronously. The license-header nitpick is dropped because existing tests in the same directory already use the headerless pattern. No builds or tests were run; the supplied CI snapshot reports successful container builds and formatting checks, with both manifest jobs still queued.

Review provenance

Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: dash-core-commit-history); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)

  • Triage: normal by gpt-6.1-sol (effort low) — The change requires reasoning about native thread-local error lifetimes and Go OS-thread pinning across 12 entrypoints, but does not alter cryptographic algorithms, signatures, or key handling.
  • Phase 1 reviewers: muse-spark-1.3-contributor — general (completed, effort xhigh); agent phase1-reviewer
  • Phase 1 model: muse-spark-1.3-contributor — not quota-gated; passed over gemini-3.8-flash-high (antigravity below 15% reserve: weekly 15% left, 5h 100% left), glm-5.3-flash (not used above high effort; tier asks max)
  • Fresh verifier: gpt-6.1-sol — final-verifier; agent sol-verifier
  • Phase 2 reviewers: gpt-6.1-sol — general (completed, effort high); agent phase2-reviewer, gpt-6.1-sol — dash-core-commit-history (completed, effort high); agent phase2-reviewer

@PastaPastaPasta

Copy link
Copy Markdown
Member Author

Moved this library-only change to dashpay/bls-signatures#135, following the vendor-ownership review on #7813 (review). All 14 changed files match the reviewed patch byte-for-byte. The upstream native suite (1,417 assertions), actual Go tests/vet, Rust sys (3 cases), and safe Rust suite (23 cases) pass; independent transfer review approved.

Closing this direct vendor-edit PR as superseded. Dash should receive the accepted upstream library change through its normal vendor import. The upstream PR is linked and watched here.


🤖 Posted autonomously by Codex on behalf of pasta.

@thepastaclaw thepastaclaw removed the pastaclaw:approved thepastaclaw's latest review approved this PR label Oct 7, 2026
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