Skip to content

Add support for shielded voting#2212

Open
greg0x wants to merge 10 commits intozcash:maint/zcash_client_sqlite-0.19.xfrom
valargroup:shielded-voting-wallet-support
Open

Add support for shielded voting#2212
greg0x wants to merge 10 commits intozcash:maint/zcash_client_sqlite-0.19.xfrom
valargroup:shielded-voting-wallet-support

Conversation

@greg0x
Copy link
Copy Markdown

@greg0x greg0x commented Mar 13, 2026

Overview

Shielded Voting — Integration Architecture Changes Proposal

PCZT changes (pczt crate)

  • Spend::spend_auth_sig getter — read back the hardware wallet signature after signing, so it can be threaded into a ZK delegation proof
  • Signer::shielded_sighash() getter — expose the cached sighash (already on upstream main, backported here)

Wallet changes (zcash_client_sqlite crate)

Two new governance-specific methods on WalletDb (inherent, not on wallet traits — these don't belong in the general-purpose API):

  • get_orchard_notes_at_snapshot(account, height) — returns all Orchard notes received at or before snapshot_height and unspent as of that height. Backward-looking query for voting snapshots, unlike select_unspent_notes which is forward-looking (based on tx expiry).

  • generate_orchard_witnesses_at_frontier(positions, frontier, height) — copies wallet shard data to an ephemeral in-memory database, inserts the lightwalletd frontier as a checkpoint, and generates Merkle witnesses at the snapshot anchor. The wallet DB is strictly read-only.

Context

Governance protocols need to construct Orchard-only PCZTs for hardware wallet signing, query wallet notes at a historical snapshot, and generate witnesses anchored at that snapshot's frontier (even if the wallet has synced past it). These changes cleanly separate concerns: librustzcash owns the wallet domain, the voting library owns the voting domain, and the SDK wires them together.

Closes #2232.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds governance-oriented wallet and PCZT capabilities needed to support “shielded voting”, including snapshot-time note selection and witness generation anchored at a historical Orchard frontier.

Changes:

  • Add WalletDb::get_orchard_notes_at_snapshot to query Orchard notes received/unspent as of a snapshot height.
  • Add WalletDb::generate_orchard_witnesses_at_frontier to generate Orchard witnesses anchored at an external (lightwalletd) frontier via an ephemeral in-memory shard store.
  • Expose PCZT getters needed for downstream proof/signature plumbing (Spend::spend_auth_sig, Signer::shielded_sighash).

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
zcash_client_sqlite/src/wallet/orchard.rs Adds snapshot-height Orchard note query for voting.
zcash_client_sqlite/src/wallet/commitment_tree.rs Adds witness generation at a historical frontier using an in-memory copied shard store.
zcash_client_sqlite/src/lib.rs Exposes new governance-specific WalletDb inherent methods.
zcash_client_sqlite/CHANGELOG.md Documents new wallet APIs.
pczt/src/roles/signer/mod.rs Adds getter for cached shielded sighash.
pczt/src/orchard.rs Adds getter for Orchard spend auth signature.
pczt/CHANGELOG.md Documents new PCZT getters.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@greg0x greg0x force-pushed the shielded-voting-wallet-support branch 6 times, most recently from e44bcf2 to 55fb1ed Compare March 24, 2026 22:20
Shielded voting protocols need to:

- Read back the spend_auth_sig after a hardware wallet signs the PCZT,
  so the signature can be threaded into a ZK delegation proof
- Access the cached shielded sighash from the Signer role

Changes:
- Add Spend::spend_auth_sig getter (via getset)
- Add Signer::shielded_sighash() getter

Co-Authored-By: Claude Code <noreply@anthropic.com>
@greg0x greg0x force-pushed the shielded-voting-wallet-support branch from 55fb1ed to 7144a23 Compare March 24, 2026 22:22
WalletDb gains two new methods (not on traits — governance-specific):

- get_orchard_notes_at_snapshot(account, height): returns all Orchard
  notes received at or before snapshot_height and unspent as of that
  height. Backward-looking query for voting snapshots, unlike
  select_unspent_notes which is forward-looking.

- generate_orchard_witnesses_at_frontier(positions, frontier, height):
  copies wallet shard data to ephemeral in-memory DB, inserts the
  lightwalletd frontier as a checkpoint, and generates Merkle witnesses.
  Wallet DB is strictly read-only.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@greg0x greg0x force-pushed the shielded-voting-wallet-support branch from 7144a23 to e0ff19d Compare March 24, 2026 22:26
p0mvn added 8 commits April 10, 2026 13:11
…ation

The previous approach bundled witness generation inside zcash_client_sqlite,
but the voting crate needs full control over the ephemeral tree lifecycle
(shard copying, frontier insertion, checkpoint management) to handle
error recovery and progress reporting at the FFI boundary.

Replace the monolithic `generate_orchard_witnesses_at_frontier` method
with three focused primitives that let the caller compose its own
witness pipeline:

- `WalletDb::conn()` — access to the underlying connection for shard
  data queries
- `create_orchard_tree_tables(conn)` — stand up the Orchard tree schema
  in any connection (e.g. in-memory), reusing the canonical DDL
- `SqliteShardStore::from_connection` made `pub` — construct a shard
  store over any connection that has the right schema

Made-with: Cursor
Expose commitment-tree primitives instead of monolithic witness generation
…ss generation"

This reverts merge commit 6858db4 (PR #23).

The approach of exposing individual commitment-tree primitives
(conn(), create_orchard_tree_tables, pub from_connection) is being
reconsidered. Revert to restore the previous API surface on the
shielded-voting-wallet-support branch.

Made-with: Cursor
…for-voting

Revert "Expose commitment-tree primitives instead of monolithic witness generation"
The "snapshot" naming was too specific to voting. These methods query
notes and generate witnesses at an arbitrary past height, so rename
them accordingly:

- get_orchard_notes_at_snapshot → get_orchard_notes_at_historical_height
- generate_orchard_witnesses_at_frontier → generate_orchard_witnesses_at_historical_height

Extract create_tree_tables / copy_tree_data helpers from the monolithic
witness-generation function for readability.

Made-with: Cursor
…orical-height

Rename governance APIs from snapshot/frontier to historical-height
…notes_at_historical_height

Make it explicit that the query returns only unspent notes. The method
already filtered to notes unspent as of the given height; the old name
didn't convey that.

Made-with: Cursor
Rename get_orchard_notes_at_historical_height to get_unspent_orchard_notes_at_historical_height
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.

3 participants