diff --git a/CHIPs/chip-0058.md b/CHIPs/chip-0058.md
new file mode 100644
index 00000000..9247eee1
--- /dev/null
+++ b/CHIPs/chip-0058.md
@@ -0,0 +1,191 @@
+| CHIP Number | 0058 |
+| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Title | Parallel voting at scale: off-chain proofs, on-chain finality |
+| Description | Standard for large-scale on-chain elections on Chia: an Election Singleton orchestrates registration and ballot issuance; Registration, Ballot, and Voting Coins separate enrollment from parallel votes and from per-ballot finalize (Groth16 + `bls_verify` on the Ballot Coin) with off-chain aggregation and proving. |
+| Author | Michael Taylor (on behalf of [DIG Network](https://github.com/DIG-Network)) |
+| Editor | [Dan Perry](https://github.com/danieljperry) |
+| Comments-URI | [CHIPs repo, PR #202](https://github.com/Chia-Network/chips/pull/202) |
+| Status | Review |
+| Category | Standards Track |
+| Sub-Category | Primitive |
+| Created | 2026-05-04 |
+| Requires | [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md) (CLVM BLS / curve operations for Groth16 verification); [CHIP-0050](https://github.com/Yakuhito/chips/blob/b23ed49e00164cbc62b9b6ae4d48071930c5b1d2/CHIPs/chip-0050.md) (action layer; see [PR #165](https://github.com/Chia-Network/chips/pull/165)) |
+| Replaces | None |
+| Superseded-By | |
+
+**Reference implementation (open source):** This CHIP is implemented in **[DIG-Network/chia-parallel-voting](https://github.com/DIG-Network/chia-parallel-voting)** on branch **`main`** ([puzzles/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/puzzles), [sdk/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/sdk), [cli/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/cli), [wasm/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/wasm), [app/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/app)). When this CHIP ships in the Chia chips repo, the Markdown **companion files** in the same directory are [README.md](./README.md), [chip-protocol-flow.md](./chip-protocol-flow.md), and the other `chip-*.md` files linked there; executable artifacts remain in the reference repository.
+
+## Abstract
+
+This CHIP defines a standard for decentralized, permissionless voting at scale on the Chia blockchain, with a practical target on the order of twenty thousand voters. There is no known theoretical upper bound; what you hit first in practice is off-chain computation and proving, not a hard chain limit.
+
+BLS is the workhorse for aggregating voter _signatures_, but BLS alone is not enough to aggregate _votes_ in a trustless setting: it does not, by itself, bind the voter threshold, how many voters backed a given result, or how many voters were registered for the election. This CHIP requires all three kinds of commitment (BLS aggregate, quorum threshold, and the registered-voter bound) to line up at finalize.
+
+The novel piece here is the realization that Groth16 circuits can produce cryptographic commitments today’s CLVM can verify. For a **fixed circuit**, the proof the coin checks is **constant size in CLVM** (it does not grow with how many voters contributed off-chain), and it still binds threshold, registration scope, and the BLS aggregate. Whoever submits the aggregation for finalization cannot fake a passing proof. If the finalize spend proves the required threshold voted and the correct BLS aggregate is in the bundle, the vote finalizes on-chain.
+
+## Motivation
+
+On Chia, a naive voting design often hits a **singleton parallelization** problem: to make the vote outcome actionable inside CLVM, many designs force every voter update through the **Ballot Box Singleton** (one tally coin everyone has to spend). In a decentralized setup that behaves like **at most one tally step per block**, so counting twenty thousand votes can mean **twenty thousand blocks** of wall-clock time, and the problem gets worse as the quorum grows.
+
+The usual shortcut is **semi-permissioned**: one operator key aggregates off-chain and posts the result to the **Ballot Box Singleton**. That trades the bottleneck for **trust and uptime**: participants depend on that party to show up and behave; anything that might move serious value on the outcome inherits a **single point of failure**.
+
+This CHIP defines a **permissionless** pattern that keeps registration and ballot issuance on the **Election Singleton**’s **slow lane**, pushes per-voter work onto **parallel coins**, and runs **per-ballot finalize** (Groth16 + BLS verification on the **Ballot Coin**) without wedging the whole election behind a **Ballot Box Singleton** again. The goal is to make **large-scale on-chain elections** on Chia realistic enough that richer **governance** can be built on the base layer.
+
+The same shape is meant to support **DIG Network**: an L2-style stack on Chia where validators **attest** to L2 blocks and **anchor** them on L1 without a designated aggregator key.
+
+It also points toward **production DAO governance** (for example CAT-weighted votes) and, longer term, **Chia Vault** spend paths that can take an **announcement** from a finalized ballot and treat it as authorization for a vault action.
+
+## Backwards Compatibility
+
+This CHIP does not propose any changes to CLVM.
+
+## Specification
+
+This section defines the on-chain artifacts, state, and spend rules needed for interoperable implementations. Election and Ballot singletons **MUST** route inner actions through the [CHIP-0050](https://github.com/Yakuhito/chips/blob/b23ed49e00164cbc62b9b6ae4d48071930c5b1d2/CHIPs/chip-0050.md) action layer where applicable. Groth16 verification and `bls_verify` **MUST** use the capabilities and encodings described in [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md). **End-to-end phase ordering** (ceremony through exit): [chip-protocol-flow.md](./chip-protocol-flow.md). **Puzzle tables and encodings** live in the companion documents linked under **Companion documents** below.
+
+### Protocol partitioning
+
+Throughput is preserved by separating three classes of spends:
+
+1. **Election singleton**: Handles `register`, `createBallot`, and `deregister` only (Rue: [register.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/election/register.rue), [create_ballot.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/election/create_ballot.rue), [deregister.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/election/deregister.rue); action layer [action.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/action.rue)). Enrollment is intentionally singleton-bound; it occurs once per voter and is not on the hot path for each vote.
+2. **Parallel voting**: `mint_voting_coin` ([mint_voting_coin.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/registration_coin/mint_voting_coin.rue)) and `update_vote` ([update_vote.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/voting_coin/update_vote.rue)) **MUST NOT** require spending the Election Singleton, so many voters can update distinct coins in the same block, within mempool and consensus limits.
+3. **Ballot Coin**: Each ballot carries `finalize` ([finalize.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue)), `oracle` ([oracle.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/ballot_coin/oracle.rue)), and `announce_finalization` ([announce_finalization.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/ballot_coin/announce_finalization.rue)). Ballot finalization **MUST NOT** spend the Election Singleton, so delayed or disputed finalization on one ballot does not block registration, ballot creation, or deregistration on the election.
+
+### Coin roles
+
+**Election-facing:**
+
+- **Election Singleton**: Orchestrates voter registration, mints Ballot Coin lineages via `createBallot` only, and authorizes `deregister` for collateral release. It does not perform vote finalization; that responsibility is entirely on the Ballot Coin.
+- **Registration Coin**: Escrows the voter’s CAT, represents membership in the election registration Merkle tree, and maintains a per-registration sparse tree of ballot launcher ids to enforce one Voting Coin lineage per ballot.
+- **Ballot Coin**: Per ballot: `vote_close_height`, `vote_options_root`, inherited VK/IC and threshold parameters, and state `(finalized, vote_outcome, agg_signers)`.
+- **Voting Coin**: Carries `vote_data` and BLS material for aggregation for one (voter, ballot) pair; it is created and updated without spending the Election Singleton.
+
+**Ceremony-facing (separate lineage from elections):**
+
+- **Ceremony Singleton**: Accepts `contribute` during a configured height window, then `finalize` after the window closes. On-chain state includes `vk_hash`, `marker_root` (Merkle root over sorted contribution marker coin ids), and `finalized`. Reference: [puzzles/ceremony_singleton/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/puzzles/ceremony_singleton).
+- **Ceremony Marker Coin**: Created per accepted `contribute`; puzzle [marker.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/ceremony_coin/marker.rue). Curries launcher id, participant public key, contribution hash, and previous contribution hash. The puzzle may produce no conditions when spent, leaving an on-chain commitment until removed.
+- **Ceremony Voucher Coin**: Created only in ceremony `finalize`; [ceremony_voucher.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/ceremony_singleton/ceremony_voucher.rue). Anyone-can-spend with self-recreation so multiple election deploys can anchor to the same ceremony. Election deploy **SHOULD** co-spend the voucher and assert its announcement to bind `vk_hash`, `max_voters`, and `ceremony_launcher_id`.
+- **Finalize summary output**: Additional coin(s) or outputs with memos (including VK bytes) for indexers using launcher hints.
+
+**Election lineage (normative):**
+
+- Registration Coin **MUST** descend from `register` on the Election Singleton.
+- Ballot Coin **MUST** descend from `createBallot` only. The reference implementation uses a 2-mojo launcher eve to satisfy singleton outer morph constraints; compatible implementations **SHOULD** match that pattern unless an equivalent approach is fully validated.
+- Voting Coin **MUST** descend from `mint_voting_coin` on a Registration Coin that proves election membership.
+
+The ceremony graph is independent. Elections reference it through `ceremony_launcher_id`, `vk_hash`, and (recommended) voucher co-spend at deploy.
+
+### Companion documents (normative detail)
+
+Tables of inner actions, Merkle slot and leaf rules, announcement preimages, Groth16 public-input ordering, and pinned constants are maintained as **companion** Markdown files alongside this CHIP so the Specification stays readable as a protocol overview:
+
+| Document | Contents |
+| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| [chip-protocol-flow.md](./chip-protocol-flow.md) | Phases 0–5; _Implementation:_ links into [puzzles/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/puzzles), [sdk/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/sdk), [cli/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/cli) in the reference repo |
+| [chip-ceremony.md](./chip-ceremony.md) | Ceremony marker, voucher, inner-action table (**Source** column), Rue / SDK cites |
+| [chip-election-coins.md](./chip-election-coins.md) | Per-role Rue and actor links after each subsection |
+| [chip-witnesses-encoding.md](./chip-witnesses-encoding.md) | Merkle rules, `vote_message`, public inputs; [merkle_utils.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/merkle_utils.rue), [circuit.rs](https://github.com/DIG-Network/chia-parallel-voting/blob/main/sdk/src/prover/circuit.rs), [finalize.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue) |
+| [chip-groth16-clvm.md](./chip-groth16-clvm.md) | CLVM Groth16 walkthrough tied to [finalize.rue](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue) and [circuit.rs](https://github.com/DIG-Network/chia-parallel-voting/blob/main/sdk/src/prover/circuit.rs); figures in reference [assets/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/assets) |
+
+An implementation **MUST** conform to this Specification and to any **MUST** / **MUST NOT** requirement in those companions where the companion text is marked normative. **Companion index:** [README.md](./README.md).
+
+### Election and ballots (summary)
+
+The **Election Singleton** stores eight fields (`registration_merkle_root`, `registration_count`, `registration_vote_weight`, `election_start_height`, `ceremony_launcher_id`, `max_voters`, `vk_hash`, `vote_mode_lock`). Deploy-time curries carry VK, IC, threshold pack, `MAX_SIGNERS`, launcher ids, and CHIP-0050 action roots and **MUST** stay consistent on every Ballot Coin minted by `createBallot`. Inner actions are **`register`**, **`createBallot`**, and **`deregister`** only; **`createBallot`** is the **only** valid ancestry for a Ballot Coin and snapshots registration root and total weight for finalize-time proofs. **`finalize`**, **`oracle`**, and **`announce_finalization`** belong on the Ballot Coin, not the Election singleton.
+
+This CHIP does **not** specify an on-chain XCH registration fee on `register` or an `accumulated_fees` field on the singleton. Ballot end time is **`VOTE_CLOSE_HEIGHT`** on each Ballot Coin, not a single global election timer. Full state and action tables: [chip-election-coins.md](./chip-election-coins.md).
+
+### Ceremony (summary)
+
+The **Ceremony Singleton** accepts **`contribute`** during a configured height window, then **`finalize`** after the window when enough participants have contributed. It seals **`vk_hash`** and **`marker_root`**, mints a **Ceremony Voucher** (and summary outputs with VK material for indexers), and forms a lineage **independent** of elections. Elections bind to the ceremony via **`ceremony_launcher_id`** and **`vk_hash`**; election deploy **SHOULD** co-spend the voucher and assert **`CANONICAL_MSG`**. Full tables and preimage: [chip-ceremony.md](./chip-ceremony.md).
+
+### Witnesses, proofs, and encodings (summary)
+
+Off-chain actors enumerate registrations and Voting Coins, verify lineage, aggregate BLS over the canonical **`vote_message`**, and build a Groth16 witness. On-chain **`finalize`** on the Ballot Coin verifies Groth16 and BLS aggregate verification via [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md) pairing opcodes; any actor may submit a valid bundle. **`mint_voting_coin`** and **`update_vote`** assert the Ballot **`oracle`** so close height and vote mode are pinned where Groth16 public inputs do not carry them. For **how Groth16 meets CLVM**, **on-chain verification cost vs off-chain proving cost**, and an **informative note on BLS12-377 vs 381** (hypothetical future CLVM; not required today), see [chip-groth16-clvm.md](./chip-groth16-clvm.md). Sparse tree definitions, vote modes, the eight ordered public inputs, VK byte length, and announcement strings: [chip-witnesses-encoding.md](./chip-witnesses-encoding.md).
+
+The keywords **MUST**, **MUST NOT**, **SHOULD**, and **MAY** in this Specification and in the linked companion documents are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119.html).
+
+## Test plan
+
+Interoperability is exercised by the open-source reference implementation ([DIG-Network/chia-parallel-voting](https://github.com/DIG-Network/chia-parallel-voting), branch `main`). Reviewers **SHOULD** treat failures there as specification or implementation drift until puzzles, circuit, and tests agree.
+
+**Automated tests** (Rust, under [`sdk/tests/`](https://github.com/DIG-Network/chia-parallel-voting/tree/main/sdk/tests)):
+
+| Area | Examples |
+| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
+| Ceremony | `ceremony_contribute_e2e`, `ceremony_deploy_e2e`, `ceremony_5_contributions_e2e` |
+| Deploy, registration, ballots | `register_action_e2e`, `voter_register_full_flow`, `create_ballot_e2e`, `create_ballot_action_isolated`, `launch_ballot_e2e` |
+| Voting | `voter_cast_vote_e2e`, `voter_cast_vote_two_voters_e2e`, `voter_revote_e2e`, `voter_double_vote_e2e`, `voter_revote_oracle_required_e2e` |
+| Finalize | `finalize_per_ballot_e2e`, `finalize_one_third_threshold_e2e` |
+| Collateral / deregister | `voter_release_collateral_e2e`, `voter_release_after_cast_e2e`, `aggregator_sync_after_deregister_e2e` |
+| Merkle / constants / parity | `m5r_merkle_gate_e2e`, `chip_spec_compliance`, `deployer_aggregator_eve_hash_parity_e2e`, `puzzle_constants` |
+| Broader harness | `integration`, `live_orchestration_e2e`, `actor_functions_e2e`, `ballot_reader_e2e`, `find_current_singleton_propagation_lag_e2e` |
+
+**Bytecode fixtures:** After `build.sh` / `build.ps1`, compiled CLVM lives under [`puzzles/compiled/`](https://github.com/DIG-Network/chia-parallel-voting/tree/main/puzzles/compiled) and is loaded via [`sdk/src/puzzles.rs`](https://github.com/DIG-Network/chia-parallel-voting/blob/main/sdk/src/puzzles.rs). Groth16 proofs in tests are generated by the reference prover ([`sdk/src/prover/`](https://github.com/DIG-Network/chia-parallel-voting/tree/main/sdk/src/prover)), not from pinned hex blobs in this document set.
+
+**Live-chain integration:** [`cli/src/bin/live_integration_test.rs`](https://github.com/DIG-Network/chia-parallel-voting/blob/main/cli/src/bin/live_integration_test.rs) builds the `chip-voting-live-test` binary (full election lifecycle with on-chain confirmations). [`wasm/integration-tests/`](https://github.com/DIG-Network/chia-parallel-voting/tree/main/wasm/integration-tests) holds Node scripts that exercise the WASM bundle against a live node (notably [`live_integration.mjs`](https://github.com/DIG-Network/chia-parallel-voting/blob/main/wasm/integration-tests/live_integration.mjs)).
+
+## Reference Implementation
+
+Normative bytecode and the Groth16 circuit live in **[chia-parallel-voting](https://github.com/DIG-Network/chia-parallel-voting)** (`main`):
+
+| Layer | Location |
+| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Rue → CLVM puzzles | [puzzles/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/puzzles); build [puzzles/compiled/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/puzzles/compiled) via [build.sh](https://github.com/DIG-Network/chia-parallel-voting/blob/main/build.sh) / [build.ps1](https://github.com/DIG-Network/chia-parallel-voting/blob/main/build.ps1) |
+| Puzzle hashes / hex loader | [sdk/src/puzzles.rs](https://github.com/DIG-Network/chia-parallel-voting/blob/main/sdk/src/puzzles.rs) |
+| Actors (deployer, voter, aggregator, ballot, ceremony) | [sdk/src/actors/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/sdk/src/actors) |
+| Groth16 circuit + prover | [sdk/src/prover/circuit.rs](https://github.com/DIG-Network/chia-parallel-voting/blob/main/sdk/src/prover/circuit.rs), [sdk/src/prover/proof.rs](https://github.com/DIG-Network/chia-parallel-voting/blob/main/sdk/src/prover/proof.rs) |
+| Merkle / witness helpers | [sdk/src/merkle.rs](https://github.com/DIG-Network/chia-parallel-voting/blob/main/sdk/src/merkle.rs) |
+| CLI | [cli/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/cli); binary `chip-voting`. **Live-chain:** `chip-voting-live-test` (see row below). |
+| Live-chain integration (real network) | [cli/src/bin/live_integration_test.rs](https://github.com/DIG-Network/chia-parallel-voting/blob/main/cli/src/bin/live_integration_test.rs) (`cargo run --bin chip-voting-live-test`, full lifecycle with confirmations); [wasm/integration-tests/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/wasm/integration-tests) (Node: [`live_integration.mjs`](https://github.com/DIG-Network/chia-parallel-voting/blob/main/wasm/integration-tests/live_integration.mjs) and related scripts against WASM + a live node) |
+| WASM + browser UI | [wasm/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/wasm), [app/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/app) |
+| Integration / E2E tests (simulator, in-repo) | [sdk/tests/](https://github.com/DIG-Network/chia-parallel-voting/tree/main/sdk/tests) |
+
+Workspace: [Cargo.toml](https://github.com/DIG-Network/chia-parallel-voting/blob/main/Cargo.toml). Overview: [README.md](https://github.com/DIG-Network/chia-parallel-voting/blob/main/README.md).
+
+## Security
+
+### Security goals
+
+For a correctly deployed election, when the **configured quorum** (rational threshold over **registered weight**, as enforced in the reference circuit and Groth16 proof) is met by voters attesting to the same outcome, the protocol aims to ensure:
+
+- **Finalize soundness:** No one can produce an accepted **`finalize`** spend that claims an outcome and signer aggregate **unless** (i) the Groth16 verification equation passes for the curried VK and the public inputs reconstructed on-chain, and (ii) the aggregate BLS signature verifies for the canonical **`vote_message`** and the supplied **`agg_signers`** (see [chip-groth16-clvm.md](./chip-groth16-clvm.md)).
+- **Binding to ballot and election context:** Public inputs and scalar bindings in [`finalize.rue`](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue) tie the proof to **`BALLOT_LAUNCHER_ID`**, snapshotted registration root and weight, threshold pack, and **`vote_message`** (which itself binds **`vote_outcome`**, ballot id, and election id). A valid proof for one ballot **cannot** be replayed as another without changing on-chain curried values and breaking verification.
+- **Registration-gated voting:** **`mint_voting_coin`** and **`update_vote`** assert the Ballot **`oracle`** in its **open** form so **`VOTE_CLOSE_HEIGHT`** and **`vote_options_root`** are committed on-chain alongside spend-time checks; combined with registration and per-ballot trees (see [chip-witnesses-encoding.md](./chip-witnesses-encoding.md)), only voters enrolled in the election’s registration Merkle tree can obtain a valid voting lineage for a ballot.
+
+### Trust boundaries and assumptions
+
+| Boundary | Assumption |
+| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Chia base layer** | Validators execute CLVM correctly; block timestamps and inclusion rules behave as in Chia consensus. Standard mempool fees apply. |
+| **CHIP-0011 / CHIP-0050** | Pairing-based opcodes and encodings are correct and stable as specified; action-layer routing on the Election and Ballot singletons is used as in this CHIP’s puzzles (see **Requires** in the preamble table). |
+| **Groth16 SRS** | Soundness holds for the **published verification key** bound by **`vk_hash`** (and, when used, ceremony voucher binding per [chip-ceremony.md](./chip-ceremony.md)). If the ceremony is compromised or **`vk_hash`** does not match the intended circuit, **finalize soundness fails** independently of puzzle logic. |
+| **Ceremony `finalize`** | The ceremony’s **`finalize`** spend is **not** authenticated by a designated on-chain key; the first valid spend wins. Operators **MUST** independently verify **`vk_hash`**, **`marker_root`**, and contribution transcripts against their security policy **before** trusting an election that references the ceremony. |
+| **Off-chain aggregator** | **Anyone** may assemble and submit a **`finalize`** bundle. Safety does not rely on the aggregator being honest; an honest aggregator is a **liveness / UX** convenience. A malicious aggregator cannot forge a passing **`finalize`** without breaking Groth16 or BLS assumptions above. |
+| **Deploy-time parameters** | **`VOTE_THRESHOLD_NUM` / `DEN`**, **`MAX_SIGNERS`**, **`vote_mode_lock`**, CAT policy, and ceremony caps are chosen by deployers; buggy or adversarial **configuration** (e.g. threshold ≥ 1, wrong VK) is **out of scope** for puzzle soundness. |
+
+### Threats and mitigations (selected)
+
+- **Forged finalization**: Mitigated by on-chain Groth16 + aggregate **BLS** verification and scalar re-derivation in **`finalize`** (see [chip-groth16-clvm.md](./chip-groth16-clvm.md)).
+- **Cross-ballot or cross-election replay of proofs**: Mitigated by **`ballot_launcher_id`**, snapshotted roots, and **`vote_message`** binding **election** and **ballot** launcher ids in public inputs and hashes.
+- **Voting after close or wrong vote options**: Mitigated by asserting the Ballot **`oracle`** announcement that pins **`VOTE_CLOSE_HEIGHT`** and **`VOTE_OPTIONS_ROOT`** for **`mint_voting_coin`** / **`update_vote`**; **`finalize`** enforces **height ≥ `VOTE_CLOSE_HEIGHT`**.
+- **Registration spam**: Not fully prevented by this CHIP: mitigations are **economic** (CAT collateral, fees) and **operational** (issuer policy). There is **no** normative on-chain XCH registration fee in this CHIP.
+- **Censorship**: Block producers or mempools can delay any spend; **`finalize`** is permissionless, so **censorship of finalization** is a **liveness** risk, not a soundness gap. **Registration** and ballot creation are singleton-bound and more exposed to ordering / censorship.
+- **Privacy**: Votes and outcomes are **visible on-chain** (coins, memos, announcements). This CHIP does **not** provide ballot secrecy or receipt-freeness.
+- **Wallet / signing layer**: Incorrect client software, weak key storage, or wallets that do not expose required signing APIs (e.g. unsafe / CHIP-0002-style spends for full dApp flows) can strand users or leak keys; that layer is **not** specified here.
+
+### Dependency surface
+
+Implementations rely on [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md) for curve arithmetic underlying Groth16 and BLS verification in CLVM, and on [CHIP-0050](https://github.com/Yakuhito/chips/blob/b23ed49e00164cbc62b9b6ae4d48071930c5b1d2/CHIPs/chip-0050.md) for structured inner spends on singletons. Changes or bugs in those standards affect this protocol in the same way as for other CHIP-0050 coins.
+
+### Residual risks and review notes
+
+- **Circuit–puzzle drift:** The R1CS in [`sdk/src/prover/circuit.rs`](https://github.com/DIG-Network/chia-parallel-voting/blob/main/sdk/src/prover/circuit.rs) **MUST** stay aligned with [`finalize.rue`](https://github.com/DIG-Network/chia-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue) public-input ordering; shipping a mismatched pair breaks all finalizations for that VK.
+- **Ceremony transparency:** Organizations **SHOULD** publish ceremony parameters, participant lists, and reproducible **`vk_hash`** checks where governance requires it.
+- **Proving time, emulation, future 377:** Large electorates mostly stress **off-chain proof generation**; that is a **liveness / ops** concern, not finalize soundness. The expensive pattern is **emulating heavier BLS12-381 arithmetic inside the BLS12-381 scalar circuit** (**field emulation**; **k = 10** as shorthand for a deep emulation tower in this stack), so proving can be **slow** while **`finalize`** stays a short on-chain check. **Informative only:** **BLS12-377** pairings in CLVM alongside **381** could allow **Groth16 on 377** with **`bls_verify`** still on **381**; the **377/381 cycle** supports **L2-style anchoring** without **381-inside-381** emulation. Details: [chip-groth16-clvm.md](./chip-groth16-clvm.md).
+
+**Out of scope for this CHIP:** Incentive design for aggregators, bridge or L2 composition, formal verification of the circuit, and legal or regulatory classification of votes.
+
+## Copyright
+
+Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
diff --git a/assets/chip-0058/README.md b/assets/chip-0058/README.md
new file mode 100644
index 00000000..36cc372c
--- /dev/null
+++ b/assets/chip-0058/README.md
@@ -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.
diff --git a/assets/chip-0058/chip-ceremony.md b/assets/chip-0058/chip-ceremony.md
new file mode 100644
index 00000000..8ffcd928
--- /dev/null
+++ b/assets/chip-0058/chip-ceremony.md
@@ -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).
diff --git a/assets/chip-0058/chip-election-coins.md b/assets/chip-0058/chip-election-coins.md
new file mode 100644
index 00000000..35a759cb
--- /dev/null
+++ b/assets/chip-0058/chip-election-coins.md
@@ -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).
diff --git a/assets/chip-0058/chip-groth16-clvm.md b/assets/chip-0058/chip-groth16-clvm.md
new file mode 100644
index 00000000..5b6add10
--- /dev/null
+++ b/assets/chip-0058/chip-groth16-clvm.md
@@ -0,0 +1,107 @@
+# Groth16, CLVM, and ballot finalization (companion to CHIP draft)
+
+**What this doc is:** how **Ballot Coin `finalize`** checks a Groth16 proof plus aggregate **BLS** in CLVM ([CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md)), **why** that combination is sound, and **informative** context on prover cost and a possible **BLS12-377** future. **Threshold intuition:** PNG figures below (`figure_1.png`, `figure_2.png`) sit in this same `assets/chip-0058/` folder (mirrored in the reference repo’s [`assets/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/assets)); they are **not** literal CRS diagrams.
+
+**Code:** [DIG-Network/chia-scaled-parallel-voting](https://github.com/DIG-Network/chia-scaled-parallel-voting) on `main`. **Public-input order and Merkle rules:** [chip-witnesses-encoding.md](./chip-witnesses-encoding.md). **Spec overview:** [chip-0058.md](../../CHIPs/chip-0058.md).
+
+---
+
+## What CLVM contributes
+
+**CLVM is not a general ZK virtual machine.** Under [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md) it exposes **BLS12-381** curve opcodes: enough for the **Groth16 verifier** as a fixed pairing-product check, and for **`bls_verify`** on aggregated signatures.
+
+**Ballot `finalize`** ([`puzzles/ballot_coin/finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue)) does the following in order:
+
+1. Rebuilds the **Groth16 instance** from the proof \((A,B,C)\), the **verification key** \((\alpha,\beta,\gamma,\delta)\) and **input commitment** points **IC[0..8]** curried at deploy.
+2. Derives eight **scalar inputs** \(s_1,\ldots,s_8\) from **on-chain-visible** data (registration snapshot, weights, `vote_message`, threshold pack, ballot id, num/den) and compares them to scalars supplied in the spend, so the proof cannot be replayed against a different ballot or election snapshot.
+3. Computes **vk_input** \(= \mathrm{IC}_0 + \sum_{i=1}^{8} \mathrm{IC}_i \cdot s_i\) in G1 (same linear structure as standard Groth16 IC).
+4. Uses **`bls_pairing_identity`** to assert the usual Groth16 pairing product holds for \((A,B,C)\), **vk_input**, and **VK** (i.e. the CLVM checks a **constant-size proof** in time that depends on **pairing cost**, not on the number of voters).
+5. Separately runs **`bls_pairing_identity`** with **`g2_map`** on **`vote_message`** so the aggregate signature is bound to the same outcome message the circuit and announcements use.
+
+**Bottom line:** Groth16 proves off-chain that the voting R1CS holds for those public inputs; CLVM reruns the verifier equation on the VK and scalars reconstructed from chain state.
+
+---
+
+## What the circuit proves (off-chain) vs what the chain checks (on-chain)
+
+| Layer | Responsibility |
+|--------|----------------|
+| **R1CS + Groth16 (prover)** | Produces a proof that the circuit’s constraints are satisfied for the **committed** public inputs (e.g. that a **quorum / majority** relation over registered weight and the claimed signer set is consistent with the circuit definition (see comments in [`sdk/src/prover/circuit.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/prover/circuit.rs)). **Proof bytes ↔ arkworks:** [`sdk/src/prover/proof.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/prover/proof.rs). |
+| **Ballot `finalize` (CLVM)** | Verifies the Groth16 proof with **CHIP-0011** pairings in [`finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue); **re-derives** \(s_1..s_8\) from curried and solution fields; verifies **BLS aggregation** over **`vote_message`**. |
+| **Registration / Voting puzzles** | Enroll voters in the registration SPT ([`register.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/election/register.rue)), pin per-ballot **oracle** ([`oracle.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/oracle.rue); mint/update: [`mint_voting_coin.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/registration_coin/mint_voting_coin.rue), [`update_vote.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/voting_coin/update_vote.rue)), and keep voting state off the Election singleton’s hot path. |
+
+**Why both Groth16 and `bls_verify`?** BLS aggregation gives a compact signature over **`vote_message`** tied to **`agg_signers`**. It does not, by itself, prove statements about **global** registration roots, **weights**, or **threshold arithmetic** inside a single cheap opcode. The circuit is where those predicates live as R1CS; Groth16 compresses that check to **three curve points and a handful of pairings** on-chain. The **oracle** spend on the Ballot Coin is still needed where the proof does not encode every pin (e.g. **`VOTE_CLOSE_HEIGHT`** and **`VOTE_OPTIONS_ROOT`** for mint/update).
+
+**Finalize bundle assembly (off-chain):** [`sdk/src/actors/aggregator.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/actors/aggregator.rs). Example tests: [`sdk/tests/finalize_per_ballot_e2e.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/tests/finalize_per_ballot_e2e.rs), [`finalize_one_third_threshold_e2e.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/tests/finalize_one_third_threshold_e2e.rs).
+
+---
+
+## Why proving hurts today, and what BLS12-377 could change (informative)
+
+**Informative only.** This section does not change interoperability requirements: ballot **`finalize`** still **MUST** verify Groth16 and **`bls_verify`** on **BLS12-381** per [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md). Discussion of **BLS12-377** below is **not** part of that requirement set.
+
+**On-chain verification is the small, predictable part.** The puzzle takes a proof bundle and runs the pairing checks. That work stays **flat** for scale in the usual sense: `finalize` is not replaying tens of thousands of per-voter updates on chain.
+
+**Off-chain proving is usually the expensive part.** The circuit stays in the **BLS12-381** Groth16 world, but many statements do not **fit** the scalar field natively, so the R1CS ends up **emulating heavier BLS12-381 arithmetic inside the BLS12-381 scalar circuit**. That pattern is called **field emulation**; in this protocol’s circuit stack it shows up as **tower-style** gadgets, with **k = 10** used here as shorthand for “deep emulation tower,” not as a normative constant for implementations. **Result:** proof generation can be **slow**, while **checking** the proof on chain stays comparatively cheap.
+
+**BLS12-377 is the “what if CLVM grew a second pairing?” case.** **BLS12-377** and **BLS12-381** form a **cycle**: the curves are set up so a proof system can move between them instead of emulating **381** inside **381** forever. **If** consensus ever added **BLS12-377** pairing opcodes alongside today’s **381** surface, a plausible layout is **Groth16 verification on 377** in `finalize` with **voter BLS and `bls_verify` still on 381**. That split is the usual pattern people point at for **recursive proofs** and **L2-style consensus**: do the heavy batch proof on one side of the cycle, anchor the result on L1 on the other.
+
+**Not part of this CHIP:** nothing here **requires** **377**. The goal is to document **where prover time goes today** and **what extra CLVM curve support could change later**.
+
+---
+
+## Why the on-chain scalar bindings matter
+
+**The VK fixes the circuit; the public inputs fix the election/ballot instance.** If the prover’s scalars do not match what the puzzle recomputes from chain fields, **vk_input** is wrong and the pairing check fails.
+
+Groth16’s **verification key** is tied to a **fixed circuit shape** and a **ceremony-produced** structured reference string. In [`finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue), the prover supplies **Scalars** \(s_1,\ldots,s_8\); the puzzle **recomputes** the expected scalars from:
+
+- `REGISTRATION_MERKLE_ROOT_SNAPSHOT`, `REGISTRATION_VOTE_WEIGHT_SNAPSHOT` (snapshotted at `createBallot`; [`create_ballot.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/election/create_ballot.rue)),
+- `agg_signers`, `vote_message`, `threshold_pack(VOTE_THRESHOLD_NUM, VOTE_THRESHOLD_DEN)`, `BALLOT_LAUNCHER_ID`,
+- and the raw field encodings for num/den,
+
+and **asserts equality** with the proof’s public scalars (hashes mod \(r\) where specified in the puzzle). Any mismatch means **vk_input** does not match what the prover used, and **pairing verification fails**. That is what prevents **cross-ballot replay** or **changing** the registration commitment **after** the ballot was created.
+
+---
+
+## Trusted setup and `vk_hash`
+
+**Groth16 needs a circuit-specific CRS / VK.** This CHIP assumes a **multi-party ceremony** (see [chip-ceremony.md](./chip-ceremony.md); puzzles [`puzzles/ceremony_singleton/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/puzzles/ceremony_singleton)) yields a **verification key** whose **SHA-256** is **`vk_hash`** on the Election Singleton. Implementations **must** treat **`vk_hash`** and voucher binding as part of the trust model: a malicious VK breaks soundness regardless of CLVM correctness.
+
+---
+
+## Figures (pedagogical intuition)
+
+**Not protocol diagrams.** The PNGs hosted with the reference implementation (`figure_1.png`, `figure_2.png` under [`assets/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/assets)) are **not** literal CLVM opcode or Groth16 CRS pictures. They illustrate **why a threshold can pin an outcome** before one talks about pairings: with **too few** contributions, many “curves” are still consistent with the observed data; with **enough** contributions, the aggregate constraint set can **lock** the relevant commitment. **τ** in the figures (“where the proof value is read”) is a visual stand-in for **evaluating a committed polynomial / SRS at a secret point** (the same *flavor* of idea that makes polynomial-based SNARKs work) without replacing the formal definition of Groth16.
+
+### Figure 1: below threshold (ambiguous)
+
+
+
+ Figure 1: Too few signers leave the curve ambiguous (pedagogical).
+
+
+*Interpretation:* Until enough voters (by weight / quorum rule) are committed inside the proof’s statement, an adversary could still be consistent with **multiple** outcomes or weights, analogous to **many** degree-(\(n\)-1) curves through **too few** points.
+
+### Figure 2: threshold met (curve locked)
+
+
+
+ Figure 2: Enough signers lock a single curve; τ is where the proof value is read (pedagogical).
+
+
+*Interpretation:* Once the threshold relation enforced in the circuit holds, the **public inputs** pin down the instance; Groth16 then proves that instance in zero knowledge (witness privacy is secondary here; **soundness** of the vote outcome + quorum claim is primary).
+
+---
+
+Companion index: [README.md](./README.md).
diff --git a/assets/chip-0058/chip-protocol-flow.md b/assets/chip-0058/chip-protocol-flow.md
new file mode 100644
index 00000000..0ba389e4
--- /dev/null
+++ b/assets/chip-0058/chip-protocol-flow.md
@@ -0,0 +1,101 @@
+# Protocol flow (companion to CHIP draft)
+
+**What this doc is:** the **end-to-end story** in order: ceremony, deploy, register, vote, finalize, exit. [chip-0058.md](../../CHIPs/chip-0058.md) stays the spec summary; here you get **which lane each spend lives in** and **where to read code** in [**chia-scaled-parallel-voting**](https://github.com/DIG-Network/chia-scaled-parallel-voting) on `main`.
+
+**Related:** deeper tables live in [chip-ceremony.md](./chip-ceremony.md), [chip-election-coins.md](./chip-election-coins.md), [chip-witnesses-encoding.md](./chip-witnesses-encoding.md), [chip-groth16-clvm.md](./chip-groth16-clvm.md).
+
+---
+
+## Lanes (reminder)
+
+**Three spend classes** keep registration and per-ballot finality from blocking each other.
+
+| Lane | Spends | Role |
+|------|--------|------|
+| **Election singleton** | `register`, `createBallot`, `deregister` | Enrollment, ballot issuance, collateral release authorization. Serialized by design for registration. |
+| **Parallel voting** | `mint_voting_coin`, `update_vote` | Do **not** require the Election Singleton; many voters can progress in the same block (within chain limits). |
+| **Per-ballot** | Ballot Coin: `oracle`, `finalize`, `announce_finalization` | Vote mechanics and finality; does **not** spend the Election Singleton. |
+
+---
+
+## Phase 0: Ceremony (trusted setup)
+
+**Goal:** produce a Groth16 **VK** the election can bind to (`vk_hash`), with on-chain markers so people can audit contributions.
+
+1. Deploy the **Ceremony Singleton** with window, `MIN_PARTICIPANTS`, `MAX_VOTERS`, `vk_seed`, and mod hashes for marker / voucher puzzles (see [chip-ceremony.md](./chip-ceremony.md)).
+2. During `[start, start + length)`, participants submit **`contribute`** spends. Each accepted contribution creates a **Ceremony Marker Coin** and advances linear `last_contribution_hash` state.
+3. After the window closes, **`finalize`** may run when `contribution_count ≥ MIN_PARTICIPANTS`. This seals `vk_hash`, `marker_root`, mints the **Ceremony Voucher** and summary outputs with VK material in memos.
+4. Off-chain, verifiers walk markers / spends, verify contribution proofs, and derive the Groth16 VK. Before trusting an election, **independently check** `vk_hash` (and related) against chain data; `finalize` has no single designated signer.
+
+*Implementation:* [`puzzles/ceremony_singleton/contribute.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_singleton/contribute.rue), [`finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_singleton/finalize.rue); marker [`puzzles/ceremony_coin/marker.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_coin/marker.rue); voucher [`ceremony_voucher.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ceremony_singleton/ceremony_voucher.rue). Rust: [`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).
+
+---
+
+## Phase 1: Election deploy
+
+**Goal:** spin up the **Election Singleton** bound to the ceremony’s VK (and ideally the voucher message).
+
+5. Launch the **Election Singleton** with eight-field `ElectionState`, curried VK/IC, threshold pack, `MAX_SIGNERS`, CHIP-0050 action Merkle roots, etc.
+6. **Recommended:** co-spend the **Ceremony Voucher** in the deploy bundle and assert its `CANONICAL_MSG` so the election is bound to `(vk_hash, max_voters, ceremony_launcher_id)` (see [chip-ceremony.md](./chip-ceremony.md)).
+
+*Implementation:* [`sdk/src/actors/deployer.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/actors/deployer.rs); election puzzles [`puzzles/election/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/puzzles/election); CHIP-0050 routing [`puzzles/action.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/action.rue).
+
+---
+
+## Phase 2: Registration and ballots (slow lane)
+
+**Goal:** add voters to the registration tree and mint **Ballot Coins** with snapshotted roots for finalize.
+
+7. Voters call **`register`** on the Election Singleton (one registration coin per voter, CAT staked, registration SPT updated).
+8. The operator calls **`createBallot`** to mint each **Ballot Coin** (2-mojo launcher pattern in reference). Ballots carry `vote_close_height`, `vote_options_root`, and **snapshots** of registration root + total weight for Groth16 public inputs at finalize.
+
+*Implementation:* [`puzzles/election/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). Actors: [`sdk/src/actors/voter.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/actors/voter.rs), [`ballot.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/actors/ballot.rs).
+
+---
+
+## Phase 3: Voting (parallel lane)
+
+**Goal:** cast or change votes without touching the Election Singleton.
+
+9. To cast or change a vote: **`mint_voting_coin`** (first time for that ballot from this registration) or **`update_vote`** on the **Voting Coin**. Both assert the Ballot Coin **`oracle`** (open) so close height and vote mode are pinned on-chain.
+10. BLS signatures over the canonical **`vote_message`** are supplied for off-chain aggregation (e.g. memos); see [chip-witnesses-encoding.md](./chip-witnesses-encoding.md).
+
+*Implementation:* [`puzzles/registration_coin/mint_voting_coin.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/registration_coin/mint_voting_coin.rue), [`puzzles/voting_coin/update_vote.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/voting_coin/update_vote.rue); open oracle spend [`puzzles/ballot_coin/oracle.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/oracle.rue).
+
+---
+
+## Phase 4: Finalize (per-ballot lane)
+
+**Goal:** prove quorum / threshold off-chain; verify Groth16 + aggregate BLS on the **Ballot Coin**.
+
+11. Off-chain: an **aggregator** collects Voting Coins and registrations, builds witness, runs **Groth16** prover, aggregates BLS (`sdk`: [`sdk/src/actors/aggregator.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/actors/aggregator.rs), [`sdk/src/prover/circuit.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/prover/circuit.rs), [`proof.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/prover/proof.rs)).
+12. On-chain: **`finalize`** on the Ballot Coin checks Groth16 and aggregate BLS via [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md) pairing opcodes ([`puzzles/ballot_coin/finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue)), then commits `vote_outcome` and `agg_signers`. Intuition and the **informative** 377 note: [chip-groth16-clvm.md](./chip-groth16-clvm.md).
+13. Optionally **`announce_finalization`** ([`announce_finalization.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/announce_finalization.rue)) so downstream logic can assert finality in a later block.
+
+Example tests: [`sdk/tests/finalize_per_ballot_e2e.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/tests/finalize_per_ballot_e2e.rs), [`finalize_one_third_threshold_e2e.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/tests/finalize_one_third_threshold_e2e.rs).
+
+---
+
+## Phase 5: Exit (slow lane)
+
+**Goal:** clear registration and unlock collateral; **not** the same thing as ballot finalize.
+
+14. **`deregister`** on the Election Singleton clears the voter from the registration SPT and emits the deregister announcement ([`puzzles/election/deregister.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/election/deregister.rue)).
+15. **`release`** on the **Registration Coin** (typically same bundle) consumes that announcement and sets `release_destination`; collateral unlock follows puzzle finalizer rules; **not** tied to ballot finalization ([`puzzles/registration_coin/release.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/registration_coin/release.rue)).
+
+**Full-network E2E harness:** [`cli/src/bin/live_integration_test.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/cli/src/bin/live_integration_test.rs).
+
+---
+
+## Cross-reference
+
+| Topic | Document |
+|--------|----------|
+| Ceremony puzzles, voucher, markers | [chip-ceremony.md](./chip-ceremony.md) |
+| Election / Ballot / Registration / Voting coins and inner actions | [chip-election-coins.md](./chip-election-coins.md) |
+| Merkle trees, vote modes, `vote_message`, public inputs, announcements | [chip-witnesses-encoding.md](./chip-witnesses-encoding.md) |
+| Groth16 + CLVM / CHIP-0011, finalize soundness, `assets/` figures | [chip-groth16-clvm.md](./chip-groth16-clvm.md) |
+
+---
+
+Companion index: [README.md](./README.md).
diff --git a/assets/chip-0058/chip-witnesses-encoding.md b/assets/chip-0058/chip-witnesses-encoding.md
new file mode 100644
index 00000000..20a5d5a9
--- /dev/null
+++ b/assets/chip-0058/chip-witnesses-encoding.md
@@ -0,0 +1,95 @@
+# Witnesses, Merkle trees, vote modes, and encodings (companion to CHIP draft)
+
+**What this doc is:** the **bytes and hashes** everything agrees on: registration SPT, per-ballot trees, `vote_message`, the **eight** public inputs in order, and announcement strings. Overview stays in [chip-0058.md](../../CHIPs/chip-0058.md) § Specification. **Groth16 vs CLVM (and why proving can hurt):** [chip-groth16-clvm.md](./chip-groth16-clvm.md).
+
+**Code:** [DIG-Network/chia-scaled-parallel-voting](https://github.com/DIG-Network/chia-scaled-parallel-voting) on `main`.
+
+---
+
+## Sparse Merkle trees
+
+**Puzzle and SDK both use the same hashing rules**; see [`puzzles/merkle_utils.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/merkle_utils.rue) and shared headers ([`election/shared.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/election/shared.rue), [`registration_coin/shared.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/registration_coin/shared.rue)). Off-chain construction: [`sdk/src/merkle.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/merkle.rs).
+
+### Registration tree (reference `TREE_DEPTH = 32`)
+
+- **Slot:** first four bytes of `sha256(pubkey)` as big-endian `u32`.
+- **Occupied leaf:** `sha256(pubkey || locked_cat_mojos_be8)`.
+- **Empty leaf:** `EMPTY_LEAF_HASH = sha256(0x00 × 48)` = **0x17b0761f87b081d5cf10757ccc89f12be355c70e2e29df288b65b30710dcbcd1**.
+- **Internal node:** `sha256(left || right)`; **not** the CLVM `0x02` serialized-tree prefix.
+
+### Per-registration ballot tree
+
+- **Leaf:** `sha256(ballot_launcher_id)`.
+- **Slot (reference):** `sha256(ballot_launcher_id) mod 2^32`.
+- **Depth:** **32** in reference. Any change requires matching the Groth16 circuit ([`sdk/src/prover/circuit.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/prover/circuit.rs)) and puzzle definitions under [`puzzles/registration_coin/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/puzzles/registration_coin), [`puzzles/election/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/puzzles/election).
+
+---
+
+## Vote modes
+
+- **Unrestricted:** `vote_options_root` is 32 zero bytes; any `vote_data` subject to other checks.
+- **Restricted:** `vote_options_root` is root of sorted Merkle tree of allowed outcomes; [`mint_voting_coin.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/registration_coin/mint_voting_coin.rue) and [`update_vote.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/voting_coin/update_vote.rue) **MUST** include inclusion proofs when restricted.
+
+If `vote_mode_lock` on the Election Singleton is not all `0xFF`, every ballot **MUST** use that locked root.
+
+---
+
+## Canonical vote message
+
+`vote_message = sha256(vote_outcome || ballot_launcher_id || election_launcher_id)`
+
+All implementations (puzzles, aggregator, circuit) **MUST** use this exact preimage order. The voting puzzle defines the same ordering in [`voting_coin/shared.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/voting_coin/shared.rue); the ballot finalize verifier recomputes it in [`ballot_coin/finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue).
+
+---
+
+## Groth16 public inputs (ordered)
+
+**Eight scalars** committed as public inputs to the circuit ([`sdk/src/prover/circuit.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/prover/circuit.rs)); **ordering MUST match** the header comments in [`finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue):
+
+1. `registration_merkle_root` (witness-time)
+2. `registration_vote_weight`
+3. `agg_signers`
+4. `vote_message`
+5. `threshold_pack`
+6. `ballot_launcher_id`
+7. `vote_threshold_num` (field element)
+8. `vote_threshold_den` (field element)
+
+Threshold **num** / **den** as public inputs allow one VK (fixed `MAX_SIGNERS`) to support multiple rational quorum fractions.
+
+**VK size (reference):** **768** bytes (`336 + 9 × 48`). Proof serialization: [`sdk/src/prover/proof.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/prover/proof.rs).
+
+---
+
+## Off-chain vs on-chain
+
+- **Off-chain:** Enumerate registrations and Voting Coins; verify lineage; weighted quorum; BLS aggregation; Groth16 witness and proof (aggregator: [`sdk/src/actors/aggregator.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/actors/aggregator.rs)).
+- **On-chain:** Ballot `finalize` in [`finalize.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/finalize.rue) verifies Groth16 and `bls_verify`. Any actor may submit a valid finalize bundle; incentives are out of scope for this CHIP.
+
+---
+
+## Pinned constants (reference interop)
+
+- `TREE_DEPTH = 32`
+- `MAX_SIGNERS = 20_000`
+- `PUBLIC_INPUT_COUNT = 8`
+- `EMPTY_LEAF_HASH` as above
+
+These align with the circuit and [`sdk/src/puzzles.rs`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/sdk/src/puzzles.rs). **Bytecode** is emitted under [`puzzles/compiled/`](https://github.com/DIG-Network/chia-scaled-parallel-voting/tree/main/puzzles/compiled) after [`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).
+
+---
+
+## Announcement preimages
+
+String layouts and helpers appear in [`puzzles/ballot_coin/shared.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/shared.rue) and the oracle spend [`oracle.rue`](https://github.com/DIG-Network/chia-scaled-parallel-voting/blob/main/puzzles/ballot_coin/oracle.rue).
+
+| Source | Preimage |
+|--------|----------|
+| Ballot oracle (open) | `"ballot_oracle_open" || ballot_launcher_id || vote_close_height_u32_be || vote_options_root` |
+| Ballot oracle (closed) | open preimage || `vote_outcome || agg_signers` |
+| Ballot finalized | `"ballot_finalized" || ballot_launcher_id || vote_outcome || agg_signers` |
+| Deregister | `"deregister" || voter_pubkey` |
+
+---
+
+Companion index: [README.md](./README.md).
diff --git a/assets/chip-0058/figure_1.png b/assets/chip-0058/figure_1.png
new file mode 100644
index 00000000..4ad5f699
Binary files /dev/null and b/assets/chip-0058/figure_1.png differ
diff --git a/assets/chip-0058/figure_2.png b/assets/chip-0058/figure_2.png
new file mode 100644
index 00000000..c08a0eaa
Binary files /dev/null and b/assets/chip-0058/figure_2.png differ