Skip to content

fix: omit unrelated co-signer balances from group burn proofs - #5324

Merged
QuantumExplorer merged 3 commits into
v5.0-devfrom
shumkov/audit-v5-t2-burn-proof-fix
Oct 7, 2026
Merged

QuantumExplorer merged 3 commits into
v5.0-devfrom
shumkov/audit-v5-t2-burn-proof-fix

Conversation

@shumkov

@shumkov shumkov commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Basic explanation

What this does: Group-burn co-signers receive verified action status and power with no remaining token balance; proposers keep their verified balance, including zero.

Value: Clients stop displaying an unrelated co-signer balance or reporting a verification error solely because the closing co-signer owns no tokens.

Risks: Low: this is client proof interpretation only. Client binaries need updating; node execution, proof bytes and consensus are unchanged.

Issue being fixed or feature implemented

A no-history group burn debits the proposer, but the existing proof also queries the current signer. Returning that balance to a non-proposer labels an unrelated account balance as the burn result; requiring it after closure fails when that co-signer has no token balance.

What was done?

  • Correct the shared verifier body used by both v0 and v1: non-proposers return the exact signer/status root and None for token balance. Proposer, standalone and history paths retain their existing behavior.
  • Preserve v1 owner-credit root comparison and Tenderdash quorum/app-hash binding; no protocol tables, prover, proof-format changes or SDK generation guard.
  • Document Rust Option / WASM undefined and wallet FFI empty-balances JSON semantics; cover actual consumer conversion arms and JS getters.
  • Group status proves recorded participation; it does not add a cryptographic pre/post burn-balance receipt. A separate proved balance query remains a height-pinned snapshot.

In-place changes to shipped generations

verify_state_transition_was_executed_with_proof/v0 contains the shared body used by verifier v0 (protocol tables through PV13) and v1 (PV14). Production block validation and execution never call this client verifier, so changing its optional result/error cannot change transition acceptance, fees, stored state, consensus roots or replay at any protocol version. This follows the client-verifier exception used in #5314; protocol selection and proof generation are untouched.

How Has This Been Tested?

On macOS/arm64 with sccache retained and two Cargo jobs:

  • Real red before fix on 1742775f6163: both v0/v1 funded co-signers returned Some(50) instead of None, and absent closing co-signers returned IncorrectProof; using the final committed 11-test file: six behavioral failures, five passing controls. The restored fix then passed all 11; the test-file SHA256 was identical in both runs.
  • cargo test -p drive --lib group_burn --jobs 2: 11 passed, none ignored. Covers both verifier dispatch paths, A=10/B=50-or-absent/burn=3, exact signer/stored roots, ledger balances/supply, active/mixed groups, proposer 7 and zero, history/standalone controls, wrong action/group/signer and owner-credit root mismatch.
  • cargo test -p drive --lib verify::group::verify_action_signers_total_power::v0::status_tests --jobs 2: 9 passed, none ignored.
  • cargo test -p dash-sdk -p wasm-sdk -p platform-wallet-ffi --lib group_burn --jobs 2: 6 passed, none ignored; Rust Option, WASM native conversion, closed co-signer empty JSON and proposer zero.
  • cargo test -p drive-proof-verifier --lib should_reject_a_verified_result_root --jobs 2: 1 passed; valid signed-root control rejects an altered app hash.
  • cargo check -p drive --no-default-features --features verify --jobs 2: passed.
  • wasm32 group_burn_wasm_tests using wasm-bindgen-test-runner: 3 passed, none ignored. Actual JS getters return undefined for a closed co-signer, BigInt 7/0 for proposers, and wasm-dpp2 forwards no raw balance. Target C compiler was Homebrew LLVM; sccache stayed enabled.
  • cargo clippy -p drive -p drive-proof-verifier -p dash-sdk -p wasm-sdk -p platform-wallet-ffi --all-features --all-targets --jobs 2 -- -D warnings: passed.
  • cargo fmt --all --check and git diff --check: passed.

Final-SHA paired Opus review approved b79c8cfdd2 with no unresolved must-fix findings and verified the repeatable red/green evidence. Thepastaclaw approved the same head, CodeRabbit completed its full review with no actionable comments, and the final refresh found zero unresolved review threads.

Selected CI passed on b79c8cfdd25332ac5341aca9f7516c72364588cb: Tests attempt 3 completed successfully, including Rust nextest (18,660 passed; 1,381 skipped), Swift SDK build/tests, JS/WASM/Evo tests, functional tests, Dashmate E2E and both browser shards. Kotlin attempt 3 also passed its native build, unit tests and emulator FFI smoke. The prior Rust job timed out compiling; the coordinator's one timeout retry passed without source or workflow changes.

Workflow conditions skipped Rust-wallet tests, ARM64 image validation, Evo SDK lint, shielded tests, doctests, full chain simulations and coverage phases; these are not reported as passes. Ivan's personal review/hygiene gate and the required FFI code-owner approval remain open. Direct Rust verification and wasm-dpp2 JS forwarding are covered above. The existing wasm-drive-verify group-result display is Unknown with no balance field; extending that API is outside this fix.

Breaking Changes

None in protocol or API shape. Updated clients intentionally receive no co-signer token balance for active and closed group burns; this does not mean zero or failed execution.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed
  • If I added or changed GroveDB structure, I described it in the area's structure.rs, regenerated grovedb-structure.json, and checked the structure viewer link posted on this pull request

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

PR Hygiene · b79c8cf

  • Bots — coderabbitai ✓ · thepastaclaw ✓
  • Self-review — post /self-reviewed
  • Reviewer requests paused — your 5 review slots are occupied; this PR is excluded from reviewers' queues. Required approvals still count without a slot.
  • Build green
  • Approvals
    • files with no dedicated owner — you own it
    • rs-drive — you own it
    • rs-platform-wallet-ffi (packages/rs-platform-wallet-ffi/src/tokens/burn.rs) — HashEngineering or ZocoLini or llbartekll or romchornyi
    • rust-sdk — you own it
    • js-wasm-sdk — you own it

When every merge requirement is met, the PR Hygiene check passes. Reviewer limits do not block merging; other required GitHub checks and protections still apply.

Summary by CodeRabbit

  • Bug Fixes
    • Corrected verification for grouped token burns without history, including cases where the signer is a co-signer rather than the proposer.
    • Proofs tied to a different root are rejected.
  • Token Burns
    • Burn results now distinguish an absent co-signer balance from a zero balance. Co-signers may receive no balance value, while proposer results continue to report their remaining balance, including zero.
    • Wallet, SDK, and JavaScript results consistently reflect these balance values.

Return verified signer power/status with no token balance for non-proposer
group burns in the shared client verifier used by v0 and v1. Preserve
proposer balances (including zero), history results, and the signer root
used by owner-credit and quorum/app-hash verification.

Document Option/undefined semantics and test SDK, WASM, and wallet FFI
forwarding, including closed co-signers returning empty balances JSON.
No prover, proof format, protocol table, or consensus execution changes.

Test would have caught this in CI: ✖ before fix, ✔ after.
Funded and absent closers failed in both generations on 1742775:
Some(50) instead of None, and IncorrectProof after a successful burn.
The same regressions pass after the fix; 11 focused Drive and 9 status
tests pass, along with 6 native consumer tests. Remaining compile/CI
verification is tracked in the draft PR.
@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: dashpay/platform/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e79bc954-4bd9-4ae5-8487-17cd8d3c796c
📥 Commits

Reviewing files that changed from the base of the PR and between 1742775 and b79c8cf.

📒 Files selected for processing (6)
  • packages/rs-drive-proof-verifier/src/verify.rs
  • packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/group_burn_tests.rs
  • packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs
  • packages/rs-platform-wallet-ffi/src/tokens/burn.rs
  • packages/rs-sdk/src/platform/tokens/transitions/burn.rs
  • packages/wasm-sdk/src/state_transitions/token.rs

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


📝 Walkthrough

Walkthrough

The changes update grouped token burn proof results so co-signers can have no reported balance while proposer balances remain available. SDK, FFI, and WASM conversions preserve the distinction between an absent balance and zero. A separate test checks vote signature verification against the supplied state root.

Changes

Vote state-root verification

Layer / File(s) Summary
Test vote signatures against the supplied root
packages/rs-drive-proof-verifier/src/verify.rs
Adds a regression test that accepts the matching root and expects InvalidSignature when the supplied root differs.

Grouped token burn proof results

Layer / File(s) Summary
Preserve signer-specific balances in proof verification
packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs
For group burns without history, non-proposers receive the signer verification result without a token balance. Proposers still have their balance verified.
Cover grouped-burn proof cases
packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/group_burn_tests.rs, packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs
Tests cover signer and action states, history, balances, supply, authenticated roots, proof-scope mismatches, and protocol versions 13 and latest.
Preserve optional balances in SDK results
packages/rs-sdk/src/platform/tokens/transitions/burn.rs
The SDK conversion preserves group-action status and distinguishes an absent balance from zero. Tests cover active and closed actions.
Expose optional balances through FFI and WASM
packages/rs-platform-wallet-ffi/src/tokens/burn.rs, packages/wasm-sdk/src/state_transitions/token.rs
The FFI serializes absent balances as {} and supplied balances, including zero, under the caller ID. WASM exposes absent balances as undefined and supplied balances as BigInt.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~40 minutes

Change: Bug fix

Suggested reviewers: quantumexplorer

Merge Risk: ⚪ Minimal · up to b79c8

The described proof results preserve the distinction between an absent co-signer balance and zero across the client interfaces. No issue identified here prevents merge after normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 79.41% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 34 functions across 6 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: omitting unrelated co-signer balances from group burn proofs.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • 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.

@github-actions github-actions Bot added this to the v5.0.0 milestone Oct 7, 2026
@thepastaclaw

thepastaclaw commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

✅ Final review complete — no blockers (commit b79c8cf) · triage: normal · Phase 2 only (queue backlog)

Documentation only; no behavior change, so a red/green regression test is not applicable.
Documentation and test module placement only; no behavior change, so an additional red/green regression test is not applicable.
@shumkov
shumkov marked this pull request as ready for review October 7, 2026 16:40
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Waiting for bot review — coderabbitai not yet · thepastaclaw ✓. Wait for the missing reviews, or a writer can post /skip-bots to proceed without them; blocking findings still need addressing.
Full checklist in the description.

@github-actions github-actions Bot added the waiting-bots Waiting for the review bots to report on this head label Oct 7, 2026

@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 2 only (queue backlog)

The shared v0/v1 client verifier correctly returns authenticated group status and power without an unrelated co-signer token balance, while preserving proposer balances—including zero—and existing owner-credit and Tenderdash root binding. The in-place change does not alter consensus execution or proof generation, and regression coverage exercises both verifier generations and downstream Rust, WASM, and wallet FFI conversions; no in-scope defects were found. This assessment is static only: tests were not run, and the supplied CI snapshot still shows queued/pending checks, skipped build/test suites, and failed PR-title checks.

Review provenance

Source: reviewer 1: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: architecture-layering); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: ffi-engineer); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: platform-versioning); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 6: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)

  • Triage: normal by gpt-6.1-sol (effort low) — The diff changes client proof-result interpretation and cross-language balance conversion with substantial regression coverage, but does not make large or intricate changes to consensus, funds movement, or cryptographic verification.
  • Phase 1 reviewers: not run (skipped for throughput: 16 PRs queued, above the 10 limit)
  • 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 — architecture-layering (completed, effort high); agent phase2-reviewer, gpt-6.1-sol — ffi-engineer (completed, effort high); agent phase2-reviewer, gpt-6.1-sol — platform-versioning (completed, effort high); agent phase2-reviewer, gpt-6.1-sol — rust-quality (completed, effort high); agent phase2-reviewer, gpt-6.1-sol — security-auditor (completed, effort high); agent phase2-reviewer

@shumkov

shumkov commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Bots are done — your move: post /self-reviewed.
Full checklist in the description.

@github-actions github-actions Bot added waiting-self-review Waiting for the author to post /self-reviewed and removed waiting-bots Waiting for the review bots to report on this head labels Oct 7, 2026
@QuantumExplorer

Copy link
Copy Markdown
Member

Seems fine

@QuantumExplorer
QuantumExplorer merged commit 8187374 into v5.0-dev Oct 7, 2026
100 of 106 checks passed
@QuantumExplorer
QuantumExplorer deleted the shumkov/audit-v5-t2-burn-proof-fix branch October 7, 2026 20:38
@QuantumExplorer QuantumExplorer mentioned this pull request Oct 13, 2026
8 of 26 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-self-review Waiting for the author to post /self-reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants