Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 191 additions & 0 deletions CHIPs/chip-0058.md

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions assets/chip-0058/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Parallel voting CHIP: companion documents

**Purpose:** These Markdown files accompany **[chip-0058.md](../../CHIPs/chip-0058.md)** in `CHIPs/`. They live here under **`assets/chip-0058/`** with the pedagogical PNG figures (`figure_1.png`, `figure_2.png`) so everything ships as one CHIP asset bundle.

**Reference implementation (executable spec):** [DIG-Network/chia-scaled-parallel-voting](https://github.com/DIG-Network/chia-scaled-parallel-voting), branch `main` (Rue puzzles, compiled CLVM, SDK, CLI, WASM, tests).

---

## Document map

| Document | Contents |
| -------- | -------- |
| [chip-0058.md](../../CHIPs/chip-0058.md) | Main CHIP text: preamble, abstract, motivation, specification summary, reference implementation, security, copyright |
| [chip-protocol-flow.md](./chip-protocol-flow.md) | Phases 0–5 (ceremony through exit); *Implementation* pointers into the reference repo |
| [chip-ceremony.md](./chip-ceremony.md) | Ceremony singleton, marker coin, voucher, inner-action table |
| [chip-election-coins.md](./chip-election-coins.md) | Election, Ballot, Registration, and Voting coins; inner actions and lineage |
| [chip-witnesses-encoding.md](./chip-witnesses-encoding.md) | Merkle rules, vote modes, `vote_message`, eight public inputs, announcements |
| [chip-groth16-clvm.md](./chip-groth16-clvm.md) | Groth16 + CLVM finalize path, soundness intuition, **informative** BLS12-377 note, figures |

**Tests and vectors:** see **Test plan** in [chip-0058.md](../../CHIPs/chip-0058.md) and [`sdk/tests/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/sdk/tests) in the reference implementation.
65 changes: 65 additions & 0 deletions assets/chip-0058/chip-ceremony.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Ceremony layer (companion to CHIP draft)

**What this doc is:** the **Ceremony Singleton** and its helper coins (marker, voucher): state, deploy fields, and what **`contribute`** / **`finalize`** actually require. High-level flow is [chip-protocol-flow.md](./chip-protocol-flow.md) Phase 0; election binding is summarized in [chip-0058.md](../../CHIPs/chip-0058.md) (Specification).

**Code:** [DIG-Network/chia-scaled-parallel-voting](https://github.com/DIG-Network/chia-scaled-parallel-voting) on `main`.

---

## State (`CeremonyState`)

**Five on-chain fields** (see [`puzzles/ceremony_singleton/shared.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_singleton/shared.rue) and `CeremonyState` in [`sdk/src/state.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/state.rs)):

| Field | Meaning |
|--------|---------|
| `contribution_count` | Number of accepted `contribute` spends. |
| `last_contribution_hash` | Hash of latest public contribution payload; equals `vk_seed` before first contribution. |
| `finalized` | Set by `finalize`; further `contribute` rejected. |
| `vk_hash` | `sha256(VK bytes)`; zero until finalize. |
| `marker_root` | Merkle root over **sorted** per-contribution marker coin ids; zero until finalize. |

---

## Deploy curries (minimum)

**You need at least:** `START_BLOCK_HEIGHT`, `CEREMONY_LENGTH_BLOCKS`, `MIN_PARTICIPANTS`, `MAX_VOTERS`, `vk_seed`, `CEREMONY_COIN_MOD_HASH`, `CEREMONY_VOUCHER_MOD_HASH`. Exact layouts live under [`puzzles/ceremony_singleton/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/puzzles/ceremony_singleton); the two inner spend paths are [`contribute.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_singleton/contribute.rue) and [`finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_singleton/finalize.rue).

---

## Inner actions

| Action | Requirements | Source (`main`) |
|--------|----------------|-----------------|
| **`contribute`** | Rejected if `finalized` is set. Allowed only while `START_BLOCK_HEIGHT ≤ height < START_BLOCK_HEIGHT + CEREMONY_LENGTH_BLOCKS`. `prev_contribution_hash` **MUST** equal current `last_contribution_hash` (first contributor uses `vk_seed`). `AggSigUnsafe` **MUST** bind the domain-separated ceremony contribution message (string **MUST** match reference implementation). Creates a **Ceremony Marker Coin** with **even** output amount so the singleton outer has exactly one odd `CreateCoin` (recreation). Increments `contribution_count` and updates `last_contribution_hash`. Large parameters: committed by hash on-chain; payloads recovered off-chain from spends and memos. | [`contribute.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_singleton/contribute.rue) |
| **`finalize`** | Only after `height ≥ START_BLOCK_HEIGHT + CEREMONY_LENGTH_BLOCKS`. Requires `finalized` unset and `contribution_count ≥ MIN_PARTICIPANTS`. Sets `finalized`, `vk_hash`, `marker_root` from solution. Mints **Ceremony Voucher** and summary marker(s) with VK-related memos. **Not** authenticated by a designated key: first valid spend wins. Verifiers **SHOULD** independently derive or verify `vk_hash` and `marker_root` from marker chain before relying on an election. | [`finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_singleton/finalize.rue) |

**Off-chain / tests:** [`sdk/src/actors/ceremony.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/actors/ceremony.rs), [`sdk/src/ceremony/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/sdk/src/ceremony). Examples: [`sdk/tests/ceremony_contribute_e2e.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/tests/ceremony_contribute_e2e.rs), [`sdk/tests/ceremony_deploy_e2e.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/tests/ceremony_deploy_e2e.rs), more under [`sdk/tests/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/sdk/tests).

---

## Ceremony Marker Coin

- **Source:** [`puzzles/ceremony_coin/marker.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_coin/marker.rue).
- **Curried:** `CEREMONY_LAUNCHER_ID`, `PARTICIPANT_PUBKEY`, `CONTRIBUTION_HASH`, `PREV_CONTRIBUTION_HASH`.
- **Created by** ceremony `contribute` only. Even amount (reference: 2 mojos) for singleton morph rules.
- **Spend:** may return no conditions; coin remains an on-chain commitment until removed.
- **Discovery:** launcher id as hint for indexers.

---

## Ceremony Voucher Coin

- **Source:** [`puzzles/ceremony_singleton/ceremony_voucher.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_singleton/ceremony_voucher.rue).
- **Minted only** from ceremony [`finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_singleton/finalize.rue).
- Anyone-can-spend with self-recreation at same puzzle hash and amount so **many** election deploys can reuse one ceremony.
- **`CANONICAL_MSG`:**

`sha256("chip:ceremony:voucher" || vk_hash || max_voters_u64_be8 || ceremony_launcher_id)`

Election deploy **SHOULD** co-spend the voucher and assert this announcement.

**Contributions MUST NOT** be voucher-gated; the contribution window is **permissionless** at the puzzle level. Allow-lists are deployment policy only.

---

Companion index: [README.md](./README.md).
101 changes: 101 additions & 0 deletions assets/chip-0058/chip-election-coins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Election, Ballot, Registration, and Voting coins (companion to CHIP draft)

**What this doc is:** **puzzle-level** detail for election-facing coins: fields, inner actions, and where **`finalize`** is *not* allowed. Lifecycle order lives in [chip-protocol-flow.md](./chip-protocol-flow.md). CHIP-0050 routing for singleton inners: [`puzzles/action.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/action.rue).

**Code:** [DIG-Network/chia-scaled-parallel-voting](https://github.com/DIG-Network/chia-scaled-parallel-voting) on `main`.

---

## Election state (`ElectionState`)

| Field | Description |
|--------|-------------|
| `registration_merkle_root` | Root of registration sparse Merkle tree (voters + weights). |
| `registration_count` | Registered voter count. |
| `registration_vote_weight` | Sum of locked CAT weight. |
| `election_start_height` | Block height at election genesis. |
| `ceremony_launcher_id` | Ceremony Singleton launcher for this VK. |
| `max_voters` | Capacity upper bound (with `TREE_DEPTH`). |
| `vk_hash` | SHA-256 of Groth16 verification key bytes. |
| `vote_mode_lock` | `0xFF…FF` (32 bytes): each ballot chooses `vote_options_root`; otherwise all ballots **MUST** use that fixed restricted root. |

Shared types and election constants: [`puzzles/election/shared.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/election/shared.rue).

**Deploy curries** (VK, IC, threshold pack, `MAX_SIGNERS`, `election_launcher_id`, CHIP-0050 action roots) **MUST** stay consistent across all Ballot Coins from `createBallot`.

This CHIP does **not** specify an on-chain XCH fee in `register` or `accumulated_fees` on the singleton.

**Ballot close time** is **`VOTE_CLOSE_HEIGHT`** on each Ballot Coin, not one global election timer.

---

## Election Singleton: inner actions

| Action | Behavior |
|--------|----------|
| **`register`** | Empty SPT slot proof; leaf `sha256(pubkey || locked_cat_mojos_be8)` (8-byte BE mojos); voter signature; increment counts and weight; mint Registration CAT with empty per-ballot tree; `release_destination` unset. |
| **`createBallot`** | **Only** path for valid Ballot Coin lineage. Forward VK, IC, threshold, `MAX_SIGNERS`, ids; **snapshot** `registration_merkle_root` and `registration_vote_weight` for Groth16 public inputs; set `vote_close_height`, `vote_options_root`, outcome domain. `ElectionState` counts do not change solely from creating a ballot. Reference: **2-mojo** launcher eve for morph safety. |
| **`deregister`** | Leaf → `EMPTY_LEAF_HASH`; deregister announcement; decrement counts and weight. |

*Rue:* [`register.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/election/register.rue), [`create_ballot.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/election/create_ballot.rue), [`deregister.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/election/deregister.rue). *Deploy / orchestration:* [`sdk/src/actors/deployer.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/actors/deployer.rs).

`finalize`, `oracle`, `announce_finalization` **MUST NOT** appear on the Election Singleton; they belong on the Ballot Coin.

---

## Ballot Coin

**State:** `(finalized, vote_outcome, agg_signers)`.

Inner action Merkle **MUST** be exactly `{ finalize, oracle, announce_finalization }` (helpers in [`puzzles/ballot_coin/shared.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/shared.rue)).

**`finalize` curries:** VK, IC, `BALLOT_LAUNCHER_ID`, `ELECTION_LAUNCHER_ID`, `VOTE_CLOSE_HEIGHT`, `VOTE_OPTIONS_ROOT`, `VOTE_THRESHOLD_NUM`, `VOTE_THRESHOLD_DEN`, `REGISTRATION_MERKLE_ROOT_SNAPSHOT`, `REGISTRATION_VOTE_WEIGHT_SNAPSHOT`. **8** public inputs; **9** IC points.

| Action | Behavior |
|--------|----------|
| **`finalize`** | `height ≥ VOTE_CLOSE_HEIGHT`; Groth16 on eight scalars; `bls_verify` on canonical `vote_message`; recreate with `finalized = true` and outcome fields. |
| **`oracle`** | Recreate unchanged; **open** announcement binds `VOTE_CLOSE_HEIGHT` and `VOTE_OPTIONS_ROOT`; **closed** includes `vote_outcome`, `agg_signers`. `mint_voting_coin` / `update_vote` **MUST** assert oracle (Groth16 does not bind close height). |
| **`announce_finalization`** | After finalize, permissionless re-announce for late consumers. |

*Rue:* [`finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue), [`oracle.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/oracle.rue), [`announce_finalization.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/announce_finalization.rue). *Ballot actor:* [`sdk/src/actors/ballot.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/actors/ballot.rs).

---

## Registration Coin

**State:** `(voter_pubkey, election_launcher_id, voted_ballots_root, release_destination)`.

| Action | Behavior |
|--------|----------|
| **`mint_voting_coin`** | Assert Ballot `oracle` (open). Restricted mode: prove `vote_data` ∈ `vote_options_root`. Non-membership + insert `sha256(ballot_launcher_id)` in per-ballot tree; mint 1-mojo Voting CAT. Fail if `release_destination` set. |
| **`release`** | Assert Election `deregister` announcement; set `release_destination`. Gated by deregister, **not** ballot finalize. |

*Rue:* [`mint_voting_coin.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/registration_coin/mint_voting_coin.rue), [`release.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/registration_coin/release.rue); shared: [`registration_coin/shared.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/registration_coin/shared.rue).

---

## Voting Coin

**State:** `(voter_pubkey, ballot_launcher_id, vote_data, registration_coin_id)`; 1 mojo lineage token; stake on Registration Coin.

| Action | Behavior |
|--------|----------|
| **`update_vote`** | Assert Ballot `oracle` (open); height checks per reference; restricted mode proofs if needed; BLS memo for `vote_message`; **does not** spend Election Singleton. |

*Rue:* [`update_vote.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/voting_coin/update_vote.rue), [`voting_coin/shared.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/voting_coin/shared.rue) (`vote_message` preimage). *Voter actor:* [`sdk/src/actors/voter.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/actors/voter.rs).

Witness builders **MUST** use the **current** Voting Coin tip per `(registration_coin_id, ballot_launcher_id)`.

---

## Lineage (normative)

- Registration ← `register` (Election Singleton).
- Ballot ← `createBallot` only.
- Voting ← `mint_voting_coin` (Registration Coin).

**Compiled bytecode** (run [`build.sh`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/build.sh) / [`build.ps1`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/build.ps1)): [`puzzles/compiled/election/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/puzzles/compiled/election), [`ballot_coin/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/puzzles/compiled/ballot_coin), [`registration_coin/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/puzzles/compiled/registration_coin), [`voting_coin/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/puzzles/compiled/voting_coin). **Loader:** [`sdk/src/puzzles.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/puzzles.rs). **Finalize bundles:** [`sdk/src/actors/aggregator.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/actors/aggregator.rs).

---

Companion index: [README.md](./README.md).
Loading