Skip to content

refactor: remove orphaned shielded nullifier-changes subsystem#3823

Merged
QuantumExplorer merged 4 commits into
v3.1-devfrom
claude/nullifier-changes-cleanup
Jun 10, 2026
Merged

refactor: remove orphaned shielded nullifier-changes subsystem#3823
QuantumExplorer merged 4 commits into
v3.1-devfrom
claude/nullifier-changes-cleanup

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Jun 9, 2026

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

Follow-up cleanup to #3819. That PR made the shielded (Orchard) wallet detect spends by matching nullifiers already present in the note scan, and removed the client-side consumption of the nullifier-sync RPCs. This PR removes the now-orphaned server-side nullifier-changes machinery, which has no remaining consumer.

This is a pre-release v12 shielded-pool change — no deployed network depends on the prior behavior.

What was done?

Removed the nullifier-changes subsystem (recent + compacted change logs, and the trunk/branch nullifier-set scan):

  • rs-drive — the recent/compacted changes trees + trunk/branch scan: store_nullifiers / fetch_nullifiers / fetch_compacted_nullifiers / compact_nullifiers / cleanup_expired_nullifier_compactions, prove_* (×4), verify_* (×4); the grovedb changes-tree structure (shielded pool 8 → 5 children); and the per-block changes write (store_nullifiers_for_block, dropped from insert_nullifiers).
  • rs-drive-abci — the cleanup_recent_block_storage_nullifiers block event (+ its call in run_block_proposal), the 4 query handlers, and their service.rs methods + query/shielded/mod.rs declarations.
  • dapi-grpc — the 4 RPCs (getRecentNullifierChanges, getRecentCompactedNullifierChanges, getNullifiersTrunkState, getNullifiersBranchState) + their messages from platform.proto, the build.rs versioned-message arrays, and the regenerated nodejs/web/python/objc/java clients.
  • rs-platform-version — the nullifier-changes method/query/verify/prove versions (across every drive_versions/vN.rs + mocks).

Kept, unchanged:

  • The permanent consensus nullifier SETinsert_nullifiers / has_nullifier / validate_nullifiers / getShieldedNullifiers — the authority for double-spend prevention.
  • The sibling address-balance saved_block_transactions subsystem (still in use; shares the version struct, so only the nullifier fields were removed).

98 files: 40 deleted, 58 modified.

⚠️ Consensus-critical — please review carefully

This changes the shielded pool grovedb subtree structure (8 → 5 children → app-hash differs) and the estimated-cost metering. Verified invariants:

  • The permanent nullifier set [64] is still created in the pool structure and still written by insert_nullifiers_v0 (only the changes-write call was removed).
  • The cost-weight change matches the new layout: count_sum_trees 1→0 (recent), non_sum_trees 5→3 (dropped compacted + expiration), permanent-nullifiers weight unchanged, subtree count 7→4, balanced Merk depth still 3.
  • The commitment-tree (Sinsemilla) anchor and spend-path nullifier enforcement are untouched.

How Has This Been Tested?

Local (CI runners are congested):

  • cargo check --workspace clean; cargo fmt --all; cargo clippy on the touched crates — no warnings.
  • cargo test -p drive --lib shielded147 passed; insert_nullifiers / has_nullifier pass.
  • cargo test -p drive-abci --lib identity_create_from_shielded5 passed.
  • cargo test -p platform-version7 passed.
  • Proto clients regenerated via the pinned rvolosatovs/protoc:4.0.0 codegen; the 4 RPCs are gone from all generated clients.

Pre-existing failures (NOT caused by this PR): cargo test -p drive-abci --lib shielded has 12 shielded_transfer/unshield failures — a minimum-shielded-fee calibration drift (test funding amounts vs the current fee schedule, e.g. funding 130548800 < min 131425600). These reproduce byte-identically on the clean base tree; the min-fee is driven by SHIELDED_STORAGE_BYTES_PER_ACTION + proof cost, which this PR does not touch. (This is also why v3.1-dev's own Tests CI is currently red.)

Breaking Changes

None for any deployed network — pre-release v12 (shielded pool not active anywhere). The on-chain shielded pool subtree structure changes (loses the recent/compacted/expiration trees), so the app-hash differs and dev/test state must be rebuilt (no migration — acceptable pre-release). The permanent nullifier set, double-spend enforcement, and the commitment-tree anchor are unchanged. Not consensus-breaking per the consensus-only ! convention.

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

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Removed Features
    • Removed four non-shielded nullifier query endpoints from the Platform API: getNullifiersTrunkState, getNullifiersBranchState, getRecentNullifierChanges, and getRecentCompactedNullifierChanges.
    • Removed server-side storage, compaction, and proof generation for non-shielded nullifiers.
    • Shielded nullifier functionality remains available via the getShieldedNullifiers endpoint.

After #3819 the wallet detects spends via the note scan, so the server-side
nullifier-CHANGES machinery has no remaining consumer. This removes it entirely.

Removed:
- rs-drive: the recent + compacted nullifier-changes trees and the trunk/branch
  nullifier-set scan — store/fetch/compact/cleanup ops, prove_* (x4), verify_* (x4),
  the grovedb changes-tree structure (shielded pool 8 -> 5 children), and the
  per-block changes write (store_nullifiers_for_block, dropped from insert_nullifiers).
- rs-drive-abci: the cleanup_recent_block_storage_nullifiers block event, the 4 query
  handlers + their service.rs methods + shielded/mod.rs declarations.
- dapi-grpc: the 4 RPCs (getRecentNullifierChanges, getRecentCompactedNullifierChanges,
  getNullifiersTrunkState, getNullifiersBranchState) + their messages from platform.proto,
  build.rs versioned-message arrays, and the regenerated nodejs/web/python/objc/java clients.
- rs-platform-version: the nullifier-changes method/query/verify/prove versions (kept the
  sibling address-balance fields in DriveSavedBlockTransactionsMethodVersions).

Kept (unchanged):
- The permanent consensus nullifier SET: insert_nullifiers / has_nullifier /
  validate_nullifiers / getShieldedNullifiers — double-spend prevention.
- The address-balance saved_block_transactions subsystem (still in use).

Pre-release v12 shielded pool: the pool subtree structure changes (app-hash differs;
dev/test state rebuilds), but the permanent nullifier set, the commitment-tree anchor,
and double-spend enforcement are unchanged. Estimated-cost weights updated to match the
new 5-child layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@QuantumExplorer QuantumExplorer requested a review from shumkov as a code owner June 9, 2026 12:26
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 986edb69-e457-4457-a5b1-505c8e2b6366

📥 Commits

Reviewing files that changed from the base of the PR and between f862ab8 and 692b312.

📒 Files selected for processing (1)
  • .github/grpc-queries-cache.json

📝 Walkthrough

Walkthrough

The PR removes non-shielded nullifier RPCs, generated client bindings, Rust query/proof/storage/verification paths, and related platform-version fields. It also updates shielded pool structure metadata, storage wiring, and remaining address-balance/notes-count versioning.

Changes

Remove non-shielded nullifier surface

Layer / File(s) Summary
Proto contract and generated client pruning
packages/dapi-grpc/build.rs, packages/dapi-grpc/protos/platform/v0/platform.proto, packages/dapi-grpc/clients/platform/v0/*, .github/grpc-queries-cache.json
getNullifiers* and recent nullifier change RPCs, their message types, and the generated client/service declarations are removed across Java, Objective-C, Python, web, and proto sources.
Service routing and execution wiring removal
packages/rs-dapi-client/src/transport/grpc.rs, packages/rs-dapi/src/services/platform_service/mod.rs, packages/rs-drive-abci/src/query/service.rs, packages/rs-drive-abci/src/query/shielded/mod.rs, packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs, packages/rs-sdk/src/sdk.rs
Nullifier request transport, platform-service delegations, query handlers, shielded query modules, cleanup calls, and SDK freshness handling are removed or narrowed.
Drive shielded storage and module surface reduction
packages/rs-drive/src/drive/shielded/*, packages/rs-drive/src/util/batch/drive_op_batch/shielded.rs, packages/rs-drive/src/verify/shielded/*
Nullifier storage, fetch, compaction, proof, verify, and query modules are deleted; shielded pool insertion and batch conversion now operate without per-block nullifier sync storage and use the reduced subtree layout.
Version structs and constants realignment
packages/rs-platform-version/src/version/*, packages/rs-drive/src/drive/shielded/estimated_costs.rs, packages/rs-drive/src/drive/shielded/paths.rs, packages/rs-drive/src/drive/shielded/has_nullifier/v0/mod.rs, packages/rs-platform-version/src/version/protocol_version.rs, packages/rs-platform-version/src/version/mocks/*
Method-version and query-version structs/consts drop nullifier-specific fields, add address-balance/notes-count fields, and update related tests, docs, and cost metadata.

Sequence Diagram(s)

Not applicable.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~90+ minutes

Possibly related PRs

  • dashpay/platform#3506 — Removes and tests code in packages/rs-drive/src/drive/shielded/nullifiers/types.rs, which is directly affected by this PR.
  • dashpay/platform#3819 — Covers the same non-shielded nullifier API surface removal across shared platform layers.
  • dashpay/platform#3801 — Updates the shielded pool subtree structure using the same insertion helper touched here.

Suggested labels

ready for final review

Suggested reviewers

  • shumkov

Poem

🐇 I hop through trees of notes and light,
The nullifier paths fade out of sight.
New balances and counts now softly gleam,
In shielded burrows, a tidier stream.
Thump-thump! The code has changed just right.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/nullifier-changes-cleanup

@codecov

codecov Bot commented Jun 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.06%. Comparing base (f347f89) to head (692b312).
⚠️ Report is 6 commits behind head on v3.1-dev.

Additional details and impacted files
@@             Coverage Diff              @@
##           v3.1-dev    #3823      +/-   ##
============================================
+ Coverage     87.04%   87.06%   +0.02%     
============================================
  Files          2677     2639      -38     
  Lines        329918   327034    -2884     
============================================
- Hits         287182   284739    -2443     
+ Misses        42736    42295     -441     
Components Coverage Δ
dpp 87.41% <ø> (ø)
drive 86.03% <100.00%> (+0.04%) ⬆️
drive-abci 89.30% <ø> (+<0.01%) ⬆️
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value 92.20% <ø> (ø)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier 49.55% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

QuantumExplorer and others added 2 commits June 9, 2026 18:32
The shielded-gated outgoing-notes load path in platform-wallet-ffi returned
`String.into()` / `format!(...).into()` as its error, but `PersistenceError`
does not implement `From<String>`, so the crate failed to compile under the
`shielded` feature (E0277). Construct `PersistenceError::backend(...)` to match
the surrounding error sites. Regression from #3819 (only triggered with the
`shielded` feature, which the congested CI on that PR didn't exercise).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

✅ DashSDKFFI.xcframework built for this PR.

SwiftPM (host the zip at a stable URL, then use):

.binaryTarget(
  name: "DashSDKFFI",
  url: "https://your.cdn.example/DashSDKFFI.xcframework.zip",
  checksum: "3650cf50c5329639ff31e658677769af871a157e61600ee5ca393176f8d58497"
)

Xcode manual integration:

  • Download 'DashSDKFFI.xcframework' artifact from the run link above.
  • Drag it into your app target (Frameworks, Libraries & Embedded Content) and set Embed & Sign.
  • If using the Swift wrapper package, point its binaryTarget to the xcframework location or add the package and place the xcframework at the expected path.

Drops the 4 removed RPCs (getNullifiersTrunkState, getNullifiersBranchState,
getRecentNullifierChanges, getRecentCompactedNullifierChanges) from
.github/grpc-queries-cache.json. The cache is committed as regenerated by
check-grpc-coverage.py against the updated proto (which also picked up 3 queries
now detected as implemented), so the post-merge coverage run produces no diff —
the workflow's auto-commit is disabled, so a stale cache would otherwise stay
perpetually dirty.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@QuantumExplorer

Copy link
Copy Markdown
Member Author

Reviewed

@QuantumExplorer QuantumExplorer merged commit 4fcb4f3 into v3.1-dev Jun 10, 2026
40 checks passed
@QuantumExplorer QuantumExplorer deleted the claude/nullifier-changes-cleanup branch June 10, 2026 10:11
@QuantumExplorer QuantumExplorer added this to the v4.0.0 milestone Jun 10, 2026
QuantumExplorer added a commit that referenced this pull request Jun 10, 2026
…ness

Resolves the modify/delete conflicts from #3823 (which removed the shielded
nullifier-changes subsystem) by accepting the deletions: the shielded half of
this fix (prove/verify_compacted_nullifier_changes) is moot now that the
subsystem no longer exists. The PR is hereby rescoped to the address-balance
boundary-authentication fix only (fetch_compacted_address_balances,
verify_compacted_address_balance_changes, queries.rs, and the shared
util/common compacted_key helper — still used by 4 address-balance modules).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant