Skip to content

Align delegation circuit with ZIP spec (dom, value=1, remove is_real)#8

Closed
czarcas7ic wants to merge 1 commit into
mainfrom
adam/zip-spec-delegation-alignment
Closed

Align delegation circuit with ZIP spec (dom, value=1, remove is_real)#8
czarcas7ic wants to merge 1 commit into
mainfrom
adam/zip-spec-delegation-alignment

Conversation

@czarcas7ic

@czarcas7ic czarcas7ic commented Mar 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Three changes to align with zcash/zips#1199 review:

  • Change 1: Governance nullifier → alternate nullifier with explicit dom public input (14th instance field). dom = Poseidon("governance authorization", vote_round_id) derived out-of-circuit. In-circuit: Poseidon(nk, dom, real_nf) with ConstantLength<3>.
  • Change 2: Dummy signed note value 0 → 1 to match PCZT construction (ZIP §Dummy Signed Note).
  • Change 3: Replace is_note_real with v * (root - anchor) = 0 — Orchard's standard dummy note mechanism (ZIP §Note Padding). Removes condition 15.

Merge order

This PR has no dependencies. Merge first (librustvoting and vote-sdk PRs depend on these changes)

//! - **Condition 12** (×5): Private nullifier derivation.
//! - **Condition 13** (×5): IMT non-membership.
//! - **Condition 14** (×5): Governance nullifier publication.
//! - **Condition 15** (×5): Padded-note zero-value enforcement.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Condition 15 is subsumed by condition 10's new gating: v * (root - anchor) = 0. Any note with v > 0 must pass the Merkle check, so a prover can't inflate weight with a fake padded note. Notes with v = 0 contribute nothing to ballot scaling. This matches Orchard's standard dummy note mechanism.

/// Gov null offsets indexed by note slot.
const GOV_NULL_OFFSETS: [usize; 5] = [GOV_NULL_1, GOV_NULL_2, GOV_NULL_3, GOV_NULL_4, GOV_NULL_5];
/// Public input offset for the nullifier domain.
const DOM: usize = 13;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

0: nf_signed
1: rk_x
2: rk_y
3: cmx_new
4: van_comm
5: vote_round_id
6: nc_root
7: nf_imt_root
8–12: gov_null_1..5
13: dom ← appended at the end

Comment on lines +532 to 533
// nf_imt_root. Not gated — dummy notes check too.
("imt_root = nf_imt_root", imt_root - nf_imt_root),

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Important, we don't skip imt check, same as before

Three changes to align with zcash/zips#1199:

1. Governance nullifier → alternate nullifier with explicit dom public
   input (14th instance field). dom = Poseidon("governance authorization",
   vote_round_id) derived out-of-circuit. In-circuit: Poseidon(nk, dom,
   real_nf) with ConstantLength<3>.

2. Dummy signed note value 0 → 1 to match PCZT construction.

3. Replace is_note_real with v * (root - anchor) = 0 (Orchard standard
   dummy note mechanism). Remove condition 15.
@czarcas7ic czarcas7ic closed this Mar 23, 2026
@czarcas7ic czarcas7ic force-pushed the adam/zip-spec-delegation-alignment branch from f91cc75 to beba9ef Compare March 23, 2026 06:17
@greg0x

greg0x commented Mar 24, 2026

Copy link
Copy Markdown
Contributor
CleanShot 2026-03-24 at 17 24 29@2x CleanShot 2026-03-24 at 17 24 47@2x

this would have been a rough review ... :D

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