Expose PCZT and wallet internals for governance signing#1
Closed
greg0x wants to merge 1 commit into
Closed
Conversation
External governance protocols (shielded voting) need to: - Replace the Orchard bundle in a PCZT after constructing a custom governance action (Pczt::set_orchard) - Read back the spend_auth_sig after a hardware wallet signs the PCZT, so the signature can be threaded into a ZK delegation proof - Serialize an orchard::pczt::Bundle into the PCZT wire format from outside the crate (Bundle::serialize_from) - Construct an ephemeral SqliteShardStore from a raw connection to build Merkle witnesses without going through WalletDb (SqliteShardStore::from_connection)
Author
|
Superseded: retargeting to maint/zcash_client_sqlite-0.19.x (orchard 0.11 compatibility) |
greg0x
added a commit
that referenced
this pull request
Mar 12, 2026
The AsyncThrowingStream closures used bare `try` inside unstructured Tasks with no do/catch. When Rust rejected the empty placeholder witness, the error was silently swallowed and the continuation was never finished — freezing the UI at step 7/8. Wrap both proof stream bodies (ZKP #1 and #2) in do/catch so errors propagate via continuation.finish(throwing:). Also provide non-empty placeholder witness data so the stub accepts it.
greg0x
pushed a commit
that referenced
this pull request
Mar 12, 2026
greg0x
pushed a commit
that referenced
this pull request
Mar 12, 2026
Replace stub delegation proof with real Halo2 prover. The combined build_and_prove_delegation() loads wallet notes, Merkle witnesses, and IMT exclusion proofs, then generates a real delegation circuit proof. Key changes: - Implement build_and_prove_delegation in librustvoting (replaces build_delegation_witness + generate_delegation_proof stubs) - Add reqwest blocking client for IMT server exclusion proof fetching - Expose ImtProvider trait and ImtProofData for external consumers - Merge FullNoteData into NoteInfo (single type across Rust/FFI/Swift) - Remove legacy ProofResult type - Remove dead WitnessBuilt phase variant - Fix store_proof to use INSERT...ON CONFLICT (was silently discarding proof bytes due to missing row) - Fix wallet notes query ordering to match witness ordering by position - Update XCFramework bindings and documentation
greg0x
pushed a commit
that referenced
this pull request
Mar 12, 2026
Real ZKP #1 delegation proof + cleanup
greg0x
pushed a commit
that referenced
this pull request
Mar 12, 2026
…cash#69) * Ballot scaling in ZKP #1: convert zatoshi to ballot count Replace the minimum-weight check (condition 8) with ballot scaling that floor-divides v_total by 12,500,000 to produce num_ballots. Condition 7 now hashes num_ballots into the VAN commitment instead of the raw v_total. Circuit constraints for condition 8: - num_ballots * BALLOT_DIVISOR + remainder == v_total - remainder < 2^24 (via shift-by-2^6 into 30-bit lookup check) - 0 < num_ballots <= 2^30 (via nb_minus_one 30-bit range check) Adds MulChip (c = a * b gate) used for the reconstruction constraint and the remainder bit-shift. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Apply ballot scaling to VAN hashes in ZKP #2 and librustvoting ZKP #1 now hashes num_ballots (not raw zatoshi) into VAN commitments. Update all downstream VAN hash callers to match: - vote_proof/builder.rs: convert total_note_value to num_ballots before VAN integrity hashing and share splitting - governance.rs: construct_van now divides total_weight by BALLOT_DIVISOR - Update test values to use weights >= 12,500,000 (one ballot minimum) - Freeze new known-answer VAN test vector Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
greg0x
added a commit
that referenced
this pull request
Mar 12, 2026
The existing voting_flow test calls the orchard builder directly. This new test exercises the production library stack: VotingDb persistence, TreeClient HTTP sync from chain, witness generation, and ZKP #2 proof generation — all through the librustvoting and vote-commitment-tree-client APIs. Changes: - Make derive_spending_key public in librustvoting so tests can derive a SpendingKey from the same hotkey seed used in production - Parametrize build_delegation_bundle_for_test to accept an optional SpendingKey (for seed-derived key consistency between ZKP #1 and #2) - Add librustvoting + vote-commitment-tree-client deps to e2e-tests with the necessary [patch.crates-io] entries
greg0x
pushed a commit
that referenced
this pull request
Mar 12, 2026
Two early-return guards in VotingStore set delegationProofStatus = .complete without calling startDelegationProof, meaning no ZKP #1 was generated, no delegation TX submitted, and no VAN position stored for software-wallet users. Now witnessVerificationCompleted and delegationApproved both route non-Keystone users through startDelegationProof, which already handles the full pipeline (proof generation, delegation TX submission, tree growth polling, VAN storage).
greg0x
added a commit
that referenced
this pull request
Mar 12, 2026
The helper server's background tree sync loop would sync past share positions before they were marked for witness retention, causing "no witness for position X" errors for every share. This happened because shares arrive ~40s after the tree has already been synced (the test spends that time generating ZKP #1 and #2). TreeSync now tracks marked positions separately and provides witness_or_resync() which rebuilds the tree from scratch with all marked positions if the fast path fails. The API handler also marks positions eagerly on share arrival. Moved the helper server default port from 9090 to 9091 to avoid conflicting with the chain's gRPC server. Updated e2e test defaults to use 127.0.0.1 (avoids macOS IPv6 resolution issues) and port 1318 (matches init.sh).
greg0x
added a commit
that referenced
this pull request
Mar 12, 2026
Rewrote voting_flow_librustvoting.rs to exercise the complete path: delegation (ZKP #1) → cast-vote (ZKP #2) → helper server (ZKP #3) → tally accumulation → auto-tally finalization → result verification. Previously the test generated ZKP #3 inline and submitted reveal-share directly to the chain. Now it sends share payloads to the helper server, which handles tree sync, witness generation, ZKP #3 proof, and chain submission — matching the production Zashi flow. Key fixes: use the chain's EA public key (from ~/.zallyd/ea.pk) instead of generating a random keypair, which was preventing auto-tally decryption. Reduced the default vote window from 480s to 180s since the helper server processes shares much faster than inline ZKP #3 generation.
greg0x
added a commit
that referenced
this pull request
Mar 12, 2026
canConfirmVote was hardcoded to true. Now it checks isDelegationReady (ZKP #1 complete) and !isSubmittingVote (no vote in-flight). Vote buttons are disabled with 50% opacity until both conditions are met. The proposal detail view now shows contextual states: - "Preparing voting credentials..." while ZKP #1 is generating - "Submitting vote..." spinner while on-chain pipeline runs - Error banner with message when submission fails - "Vote recorded" checkmark only after on-chain confirmation The confirmation overlay also distinguishes between waiting for delegation vs waiting for a previous vote submission.
greg0x
added a commit
that referenced
this pull request
Mar 12, 2026
The admin UI uses stub values for nc_root and nullifier_imt_root, which causes ZKP #1 to fail because the Merkle roots don't match the real chain state. This test fetches the real Sinsemilla-based nc_root from lightwalletd (via grpcurl) and the real nullifier IMT root from the IMT server, then creates a round that Zashi can actually delegate to. Requires a running local chain with a confirmed ceremony, grpcurl, and a reachable IMT server. Configurable via ZASHI_SNAPSHOT_HEIGHT, ZASHI_LIGHTWALLETD, ZASHI_IMT_URL, and ZASHI_VOTE_WINDOW_SECS env vars.
greg0x
added a commit
that referenced
this pull request
Mar 12, 2026
The admin UI was creating voting rounds with SHA-256(orchard_frontier) as nc_root, which never matches the real Sinsemilla-based root that Zashi computes — causing all delegation proofs (ZKP #1) to fail. This adds a Rust FFI function (zally_extract_nc_root) that parses the hex-encoded orchard frontier from lightwalletd's TreeState and computes the real Merkle root using MerkleHashOrchard. The Go chain binary calls this via CGo, replacing the placeholder. The admin UI now fetches real snapshot data (nc_root, nullifier IMT root, blockhash) from GET /zally/v1/snapshot-data/{height} before creating a round, falling back to stubs if the endpoint is unavailable. Includes temporary [zkp1-verify] debug logging in ffi.rs for the ongoing proof verification debugging.
greg0x
added a commit
that referenced
this pull request
Mar 12, 2026
The manual commitment_tree_root() in sdk/circuits was always placing the running digest on the left when combining with parent nodes. But when a parent is Some, it represents the completed *left* subtree — the digest (right subtree) should go on the right side of combine(). This caused the chain's snapshot-data endpoint to return a different nc_root than zcash_client_backend (used by Zashi and librustvoting), making delegation proofs (ZKP #1) fail verification on-chain even though the proof was generated correctly. Added mainnet regression tests at height 3245500 to both the sdk/circuits and nullifier-ingest implementations, pinned against the known-correct value from zcash_client_backend.
greg0x
pushed a commit
that referenced
this pull request
Mar 12, 2026
Sequential packing algorithm sorts notes by value DESC and fills bundles of up to 4 notes each, dropping bundles below BALLOT_DIVISOR (0.125 ZEC). Eligible weight is quantized per-bundle to match VAN circuit constraints. Multi-bundle delegation and voting: each bundle gets its own ZKP #1 proof, delegation TX, VAN position, and per-proposal vote submission. Keystone signing loops through bundles sequentially. UX improvements: - Show proposals immediately instead of blank spinner during tree state fetch - Unified progress banner (witness preparation → delegation proof %) - Countdown timer on proposal detail view - No flash of status banners on cached round resume Safety fixes: - proof_generated requires VAN positions (not just proofs) for all bundles - canConfirmVote gates on bundleCount > 0 to prevent resume race - Share delegation retry (3 attempts, 2s delay) restored - DB migration bumped to v3 for new bundles-based schema
greg0x
pushed a commit
that referenced
this pull request
Mar 12, 2026
- Add sentinel injection (k*2^250 for k=0..16) to pir-export to satisfy circuit gap-width constraint (#3) - Change Tier 2 empty-leaf padding from Fp::zero() to -Fp::one() so trailing entries sort after real leaves, fixing binary search (#2) - Make TierServer::answer_query() return Result with input validation (length checks, alignment) instead of panicking on malformed requests; handlers return HTTP 400 on error (#1) - Replace unwrap/assert with fallible returns in pir-client and Tier0Data::from_bytes (#4)
greg0x
pushed a commit
that referenced
this pull request
Mar 12, 2026
greg0x
pushed a commit
that referenced
this pull request
Mar 12, 2026
The vote proof circuit was regenerating IPA params and proving/verifying keys on every call (~30s on device). Add a process-level OnceLock cache matching the pattern ZKP #1 already uses for the delegation circuit. Made-with: Cursor
p0mvn
pushed a commit
that referenced
this pull request
Apr 3, 2026
…14868de..23f0768ea 23f0768ea Release lightwallet-protocol v0.4.0 41156c767 Merge pull request #11 from zcash/feature/get_mempool_tx_pools 7c130e883 Add `lightwalletProtocolVersion` field to `LightdInfo` struct. edbb726d7 Apply suggestion from code review 38fddd73b Apply suggestions from code review 0250f2720 Add pool type filtering to `GetMempoolTx` argument. 54ccaadd5 Change semantics of pool-based pruning of compact transactions from "may prune" to "must prune". b0667ec99 Merge pull request #9 from zcash/2025-11-doc-TransparentAddressBlockFilter f3fea7bd4 doc: TransparentAddressBlockFilter doesn't include mempool a67dd323a Merge pull request #8 from zcash/2025-11-lightdinfo-upgrade-info 11da4b7e3 add next upgrade info to LightdInfo structure (GetLightdInfo) 42cd8f720 Transparent data docs update (#7) c0cf957ac Merge pull request #5 from zcash/2025-11-comments 912fc3609 Minor clarification in GetBlockRange documentation. 6b03f2cce Documentation (comments) only d978256a2 Merge pull request #1 from zcash/compact_tx_transparent 7eeb82e7c Merge pull request #4 from zcash/add_changelog a95359dc9 Apply suggestions from code review 592b637a8 Add transparent data to the `CompactBlock` format. 9d1fb2c41 Add a CHANGELOG.md that documents the evolution of the light client protocol. 180717dfa Merge pull request #3 from zcash/merge_librustzcash_history 450bd4181 Merge the history of the .proto files from `librustzcash` for complete history preservation. a4859d11d Move protobuf files into place for use in `zcash/lightwallet-protocol` 2e66cdd9e Update zcash_client_backend/proto/service.proto eda012519 fix comment f838d10ad Add gRPC LightdInfo Donation Address db12c0415 Merge pull request zcash#1473 from nuttycom/wallet/enrichment_queue 698feba96 Apply suggestions from code review 20ce57ab3 zcash_client_backend: Add `block_height` argument to `decrypt_and_store_transaction` a6dea1da8 Merge pull request zcash#1482 from zancas/doc_tweak 4d2d45fc9 fix incorrect doc-comment e826f4740 update CompactBlock doc-comment, to cover non-Sapling shielded notes, and addresses e9a6c00bf Various documentation improvements 988bc7214 Merge pull request zcash#872 from nuttycom/feature/pre_dag_sync-suggest_scan_ranges 58d07d469 Implement `suggest_scan_ranges` and `update_chain_tip` a9222b338 Address comments from code review. e20310857 Rename proto::compact::{BlockMetadata => ChainMetadata} ac63418c5 Reorganize Sapling and Orchard note commitment tree sizes in CompactBlock. 0fdca14f1 zcash_client_backend: Add note commitment tree sizes to `CompactBlock` serialization. 2a0c2b8b7 zcash_client_backend: Add gRPC bindings behind feature flag 1342f0480 zcash_client_backend: Address compact_formats.proto comments 68aa4e01b zcash_client_backend: Bring in latest `compact_formats.proto` e712eb1bc Add prevHash field to CompactBlock 440384c3e Build protobufs for compact formats git-subtree-dir: zcash_client_backend/lightwallet-protocol git-subtree-split: 23f0768ea4471b63285f3c0e9b6fbb361674aa2b
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Shielded voting requires building governance-specific PCZTs and extracting
signatures from hardware wallet (Keystone) signing flows. The upstream PCZT
crate keeps several types and methods crate-private that governance protocols
need access to.
Changes
pczt crate:
Pczt::set_orchard()— replace the Orchard bundle after constructing acustom governance action (1-zatoshi self-spend carrying delegation metadata)
Spend::spend_auth_sig()— public getter so governance code can extract thesignature after Keystone signs the PCZT, threading it into the ZK delegation
proof
Bundle::serialize_from()—pub(crate)→pubso governance code canserialize an
orchard::pczt::Bundleinto wire formatzcash_client_sqlite crate:
SqliteShardStore::from_connection()—pub(crate)→pubso governancecode can construct an ephemeral shard store from a raw SQLite connection to
build Merkle witnesses without going through
WalletDbNotes
shielded_sighash()andapply_orchard_signature()which we also need — those are already available.zcash/librustzcashonce reviewed internally.