PR #853proposed changes toZIP 340

Coin Voting ZIP

status → Draftby hhanh00 · updated 2026-05-17zip-0340.md @ d006de1e7a · upstream 4699a8d518view on GitHub ↗

Unofficial preview — the proposed text below is rendered from the pull request head and is not part of the canonical ZIP set.


title: Coin Voting breaks: false tags: coin_voting

Coin Voting

This ZIP describes a mechanism for the organization of coin-weighted election.

Use Case

A person or organization, referred as the Election Board (EB) decides to request the opinion of the zcash holders (ZH) on a particular topic. The EB defines the parameters of the referendum:

  • when it starts (snapshot height) and stops (closing height)
  • An optional lockdown period before it closes
  • the question asked
  • the criteria for aggregating the votes

They publically ask the ZH to participate by sending them ballots. They verify and tally the votes following the aggregation method (typicall linear, but it could be quadratic or something else). Then they publish the outcome.

The final result of the election is a list of valid ballots that have:

  • a value in ZEC
  • a message

The content of the message depends on the type of referendum. The acceptable options should be defined by EB. For example, for a yes/no question, it could simply be a value of 0 or 1.

The EB could decide to accept write-in votes too. The format of the message is not part of this ZIP.

The value of the ballot MUST be an amount of ZEC that the ZH can spend at the snapshot height.

The ZH is not obligated to vote with all the ZEC that they have. But it MUST be impossible to use the same coins to vote twice on the same election.

It MUST be possible to use the same ZEC on DIFFERENT elections.

See Privacy section on important caveats regarding concurrent voting.

Other Uses Cases

Airdrop

This ZIP can be used to perform air-drops. An organization that wants to give their tokens/coins based on an amount of ZEC can organize an election. The ballots contain the ZH's address where they want to receive the airdrop.

Proof of Balance

In this case, the ZH sends an empty message because the ballot value is all that matters.

Requirements

Participants / Actors

Election Board

The Election Board (EB) is the entity in charge of organizing the election (E).

  • The EB MUST have a website secured by https that clearly reflects their identity.
  • They MUST make their announcements through their website.
  • The EB SHOULD have a forum for election related discussions
  • The EB MUST set the election parameters described in a later section
  • The EB MUST publish the election parameters on their website
  • The election parameters are immutable. If the EB wants to make a modification, another election MUST be created

Voter (ZH)

Anyone who has spending authority of ZEC (either transparent or shielded) can participate.

  • Ballots MUST have a ZEC value
  • Ballots MUST have a message in the format defined by the Election
  • Ballots MUST include a proof of spending authority for the amount specified, valid at the snapshot height
  • Ballots MUST not prevent the ZH from spending the coins in a transaction
  • Coins spent before the snapshot height MUST not be eligible for voting
  • Voting MUST not disclose information that would allow someone to use the coins themselves (in a transaction or an election)
  • Ballots MUST follow the format specified in the section Ballot
  • ZEC held in transparent t3 addresses CANNOT be used. They introduce most complexity and are not used much

Notes:

  • Having coins on an exchange such as Binance, Bitfinex, etc. does not allow you to vote because the coins are under their custody
  • The EB MAY set special rules for the election. For example, there MAY be a fee for casting a vote or a minimum ZEC requirement

Privacy

:::danger If the coins used for voting for a given election are not moved before voting for another election, it is possible to link the votes. :::

  1. Transparent inputs are in clear
  2. Shielded inputs reveal their nullifier

The total value is also revealed since it is the weight of the vote.

To mitigate this issue, the user SHOULD be offered to move their coins after a vote. However, if multiple elections are carried out concurrently with similar snapshot heights, it will be impossible for a Voter to participate in both without linking their votes.

A possible solution is suggested in Air drops, Proof-of-Balance, and Stake-weighted Polling

Alternatively, homomorphic encryption could be used in order to tally the votes without decrypting them individually. However, this would be less flexible than the above.

Workflow

The election E is carried in several sequential phases.

  1. The EB publishes the E parameters and advertise the E
  2. Each V prepares his/her ballot and send it to the EB
  3. The EB returns a receipt to the V
  4. The E enters a lockdown period
  5. The E closes and the results are published
sequenceDiagram
    EB->>Public: Publish Election
    Note over V,EB: When snapshot height reached
    loop every Voter, concurrently
    V->>EB: Ballot
    EB-->>V: Receipt
    end

    Note over V,EB: When lockdown height reached
    EB->>Public: List of Ballot ID
    Note over V,EB: When expiration height reached
    loop every Voter, concurrently
    V->>EB: Ballot Decryption Key
    end
    EB->>Public: Publish Decrypted Ballots, E results

Ballots

The message part of a Ballot is encrypted with the V key. The decryption key is sent to the EB after the lockdown period. The EB validates the ballot coin value and returns a receipt. The Receipt contains a signature from the EB.

Lockdown Period / Ballot List commitment

The lockdown period is optional but RECOMMENDED.

It gives time for the Voters to check that their ballot is recorded by the EB publicly and that no additional ballots are added after their opening.

If a V does not see their ballot on the list, they MUST contact the EB and resolve the dispute. Their receipt has the EB signature and proves the integrity of the ballot. Failure to recognize a valid ballot is a serious breach of trust.

Counting

After the lockdown period, V MUST send their decryption key to the EB.

EB decrypts the vote and updates the tally.

Finally EB publishes the results for everyone to see.

The encrypted ballots and their decryption keys are published for verification.

Verification

  • Check that the ballot hashes correspond to the ballot published
  • For each ballot,
  1. Check the validity of the signatures and the zkps
  2. Compute the coin value
  3. Decrypt the vote
  4. Tally the vote weighted by the coin value

Specifications

The communication uses binary messages in protobuf format.

EB

  • URL:
    • MUST be https
    • MUST identify the organization
  • Name
    • MUST be unique to organization
  • start_height
  • snapshot height
  • lockdown height
  • closing height
  • the EB public key

Example:

url = "https://election.methyl.cc"
name = "Test Election 2024"
start_height = 2397000
snapshot_height = 2462430
lockdown_height = 2460000
closing_height = 2460000
msg_size = 64
public= "788ff50468e2c095d97f8249e27eef3afe8a07712988a475583eb89494d64abe"
cmx_root = "063121a1fed23f154e18d9dfc70a13867f295207fd3c59d0e3f86615b857d332"
nf_root = "5341fe36634580cdf8862a106dab2cf7bd39f67d171a2877995babb435a5ee0e"

Only notes received and unspent between the start_height and the snapshot height are eligible.

The start_height defaults to the Sapling activation height.

In addition, the EB MUST define a message in protobuf format. The message MUST have a fixed size.

public is defined in the section Message Encryption

Example:

message BallotContent {
    uint8 candidate = 1;
}

From the E definition, the E domain is calculated as

domain = Blake2b-256(b"Zcash_WCV_domain", E)

The E domain is included in the ballot and ensures that ballots cannot be replayed.

Ballot

syntax = "proto3";
package proof_balance;
// Protobuf does not support fixed size arrays
// This type MUST be 32 byte-long
message b256 {
    bytes b = 1;
}

// A ballot is made of 2 parts, 
// the data part is non malleable and is used to calculate the sighash
// the witness part has the signatures and the zkp
message Ballot {
    BallotData data = 1;
    Witness witness = 2;
}

message Header {
    uint32 version = 1; // version = 1
    b256 domain = 2; // Election Domain
}

message BallotData {
    Header header = 1;
    TransparentData tdata = 2; // transparent inputs
    ShieldedData zdata = 3; // sapling inputs
    ShieldedData odata = 4; // orchard inputs
    EncMessage enc_message = 5; // encrypted vote
}

message EncMessage {
    bytes epk = 1;
    bytes data = 2;
    bytes tag = 3;
}

message Witness {
    TransparentWitness twitness = 1; // transparent sigs
    SaplingWitness zwitness = 2; // sapling sigs & zkp
    OrchardWitness owitness = 3; // orchard sigs & zkp
}

// Transparent Input, i.e UTXO
message TxIn {
    b256 txid = 1;    // prev txout
    uint32 vout = 2;  // index of the output
}

message TransparentData {
    repeated TxIn txin = 1;
}

// See section 7.3 and 7.5 of [protocol doc]
message Spend {
    b256 commitment_value = 1;
    b256 nullifier = 2;
    b256 rk = 3;
}

message ShieldedData {
    // b256 anchor = 1; // MUST be the anchor at snapshot height
    repeated Spend spends = 2;
    uint64 valuebalance = 3;
}

message Signature {
    bytes b = 1; // 64 bytes, r, s
}

message TransparentProof {
    b256 pk = 1;
    Signature signature = 2;
}

message TransparentWitness {
    repeated TransparentProof proofs = 1;
}

message SaplingSpendProof {
    bytes zkproof = 1; // 192 bytes
    Signature signature = 2;
}

message SaplingWitness {
    repeated SaplingSpendProof proofs = 1;
    Signature binding_signature = 2;
}

message OrchardWitness {
    repeated Signature signatures = 1;
    bytes zkproof = 2; // 2720 + 2272 * nOrchard
    Signature binding_signature = 3;
}

message ElectionId {
    string name = 1;
}

message ElectionInfo {
    string url = 1;
    string name = 2;
    uint32 start_height = 3;
    uint32 snapshot_height = 4;
    uint32 lockdown_height = 5;
    uint32 closing_height = 6;
    string pk = 7;
    uint32 msg_size = 8;
    bytes cmx_root = 9;
    bytes nf_root = 10;
}

message ProofDomain {
    bytes domain = 1;
}

message Proof {
    bytes cv = 1;
    bytes nullifier = 2;
    bytes rk = 3;
    bytes proof = 4;
}

Ballot Hash / Sighash

For the signatures, the sighash is the blake2b-256 hash of the serialization of the ballot data (in protobuf 3) with personalization string Zcash_WCV___Hash.

hash = Blake2b-256("Zcash_WCVSigHash", BallotData).

Message Encryption

The EB MUST sign the ballot sighash with a ed25519 signing key and return a receipt as a bech32m encoded signature with hrp pob-receipt-

The Voter MUST add a message in the format specified by the EB. The message is encrypted into EncMessage.

  • epk is a 32 byte public key on x25519
  • the Voter reveals his own ed25519 signing key after the vote closes
  • the EB converts the key to a x25519 secret key
  • the EB uses DH to calculate a shared key KA
  • SymKey = Blake2b-256(KA, perso="Zcash_ProofBlnce")
  • SymKey is used with Chacha20-Poly1305 to decrypt the message
  • The tag MUST match the decrypted tag

Rationale: This design allows the use of ed25519 SSH keys for both Voter and EB.

:::warning The Voter SHOULD not reuse the signing key! :::

POC

The POC is for a modified version specific to Orchard that uses nullifiers scoped by elections.

Poll/Election Setup

The EB (Election Board) generates an openssh ed25519 signing key

openssl genpkey -algorithm ed25519 -out poller.pem

:::info The key MAY be reused. It is used for signing ballot receipts. It is RECOMMENDED to use a different key per election. :::

The EB chooses a event properties

url = "https://election.methyl.cc"
name = "Test Election 2024"
start_height = 2397000
snapshot_height = 2462430
lockdown_height = 2460000
closing_height = 2460000
msg_size = 64
public= "788ff50468e2c095d97f8249e27eef3afe8a07712988a475583eb89494d64abe"
cmx_root = "063121a1fed23f154e18d9dfc70a13867f295207fd3c59d0e3f86615b857d332"
nf_root = "5341fe36634580cdf8862a106dab2cf7bd39f67d171a2877995babb435a5ee0e"

The public key MUST match the EB signing key.

The cmx_root and nf_root are OPTIONAL but if present MUST match the hashes calculated by building the reference data.

:::info If the snapshot height is not in the past, it is impossible to calculate the tree roots. :::

The EB publishes the election.toml file so that voters can download it.

Voter Send their Ballots

Once the snapshot height is reached and before the lockdown height, voters can submit their vote.

They have to follow the steps:

  • generate an openssh ed25519 key;
  • download block data for the range from start height to snapshot height;
  • build reference data, i.e. cmx and nf Merkle trees;
  • copy their wallet file zec.db from Ywallet. The vote does not have to use this wallet app as long as it has the note data:
    • d, pkd,
    • v,
    • rseed,
    • ρ, ψ
    • note position
  • create the proof with a ballot message;
  • submit the ballot to the EB;
  • wait until the election reaches the closing height.
>> load-identity voter.pem
c76a89174ed64479c5f567b955ce27ce998568e72a044de80b0ebe748d826b3c
>> download https://lwd1.zcash-infra.com:9067
>> build-reference-data
Root cmxs: 5de18172c1c9d2a526a9c73067e75dfbe1ac4e774e1bfec9a31ee178db98a635
Root nfs: 12d4776996da7929255bccfcb21c99853d840c4008da547b113c4c857eec3d29
>> create-proof pob.bin 1 "Vote for BOB!"
5c70068567d0b8d52e4dcfc395a67dc83fd6bdf9c65a835b41d2bfeb776480fb
cmx anchor: 5de18172c1c9d2a526a9c73067e75dfbe1ac4e774e1bfec9a31ee178db98a635
nf  anchor: 12d4776996da7929255bccfcb21c99853d840c4008da547b113c4c857eec3d29

EB Collects Votes

The EB collects votes and verifies the validity of the ZKP, spending signatures and binding signature. It also checks that the root hashes match and that the nullifiers are not used.

If everything is fine, the EB returns a receipt that is a signature on the sighash of the ballot.

>> load-identity poller.pem
3f8a41af400aa0197594a7b5c2e21bb6307753840a8513b28b816aad43fb30c0
>> init-db
>> verify-proof pob.bin
ZK Proof verified!
Spending Signature verified!
Binding Signature verified!
Verified 0.05000000 ZEC
Receipt: pob-receipt-1djsvezm3wep2ganwd4upzawxsgz60hq2e86cqkv4djmusut4fjzzvzu2ut5z3uda4eedvff6anlmzz3k48d7ugxsrs0gxfn36nscvqqzn4js8

At this point, the ballot is verified and its amount can be accounted for but the vote payload is not revealed.

:::info The EB publishes the ballot hashes and receipts on their website. :::

Opening Votes

Voters uploads their signing key to the EB.

>> load-identity voter.pem
c76a89174ed64479c5f567b955ce27ce998568e72a044de80b0ebe748d826b3c
>> open-proof pob.bin
5c70068567d0b8d52e4dcfc395a67dc83fd6bdf9c65a835b41d2bfeb776480fb
Decrypted message: Vote for BOB!

:::info The EB counts the votes and publishes the results :::

Audit

:::info The EB publishes all ballots and their opening keys for verification by auditors. :::

Changes

index.html +98 −109
@@ -24,121 +24,110 @@ <p>To start contributing, first read <a href="zip-0000">ZIP 0</a> which documents the ZIP process. Then clone <a href="https://github.com/zcash/zips">this repo</a> from GitHub, and start adding your draft ZIP, formatted either as reStructuredText or as Markdown.</p> <p>For example, if using reStructuredText, use a filename matching <code>draft-*.rst</code>. Use <code>make</code> to check that you are using correct <a href="https://docutils.sourceforge.io/rst.html">reStructuredText</a> or <a href="https://pandoc.org/MANUAL.html#pandocs-markdown">Markdown</a> syntax, and double-check the generated <code>draft-*.html</code> file before filing a Pull Request. See <a href="protocol/README">here</a> for the project dependencies.</p> </section> - <section id="nu5-zips"><h2><span class="section-heading">NU5 ZIPs</span><span class="section-anchor"> <a rel="bookmark" href="#nu5-zips"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> - <p>This is the list of ZIPs relevant to the NU5 Upgrade, which <a href="https://z.cash/upgrade/nu5/">activated on 31st May 2022</a>:</p> - <ul> - <li><a href="zip-0032">ZIP 32: Shielded Hierarchical Deterministic Wallets</a> (updated)</li> - <li><a href="zip-0203">ZIP 203: Transaction Expiry</a> (updated)</li> - <li><a href="zip-0209">ZIP 209: Prohibit Negative Shielded Chain Value Pool Balances</a> (updated)</li> - <li><a href="zip-0212">ZIP 212: Allow Recipient to Derive Ephemeral Secret from Note Plaintext</a> (updated)</li> - <li><a href="zip-0213">ZIP 213: Shielded Coinbase</a> (updated)</li> - <li><a href="zip-0216">ZIP 216: Require Canonical Jubjub Point Encodings</a></li> - <li><a href="zip-0221">ZIP 221: FlyClient - Consensus-Layer Changes</a> (updated)</li> - <li><a href="zip-0224">ZIP 224: Orchard Shielded Protocol</a></li> - <li><a href="zip-0225">ZIP 225: Version 5 Transaction Format</a></li> - <li><a href="zip-0239">ZIP 239: Relay of Version 5 Transactions</a></li> - <li><a href="zip-0244">ZIP 244: Transaction Identifier Non-Malleability</a></li> - <li><a href="zip-0252">ZIP 252: Deployment of the NU5 Network Upgrade</a></li> - <li><a href="zip-0316">ZIP 316: Unified Addresses and Unified Viewing Keys</a></li> - <li><a href="zip-0401">ZIP 401: Addressing Mempool Denial-of-Service</a> (clarified)</li> - </ul> - </section> <section id="license"><h2><span class="section-heading">License</span><span class="section-anchor"> <a rel="bookmark" href="#license"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <p>Unless otherwise stated in this repository’s individual files, the contents of this repository are released under the terms of the MIT license. See <a href="COPYING">COPYING</a> for more information or see <a href="https://opensource.org/licenses/MIT">https://opensource.org/licenses/MIT</a> .</p> </section> <section id="index-of-zips"><h2><span class="section-heading">Index of ZIPs</span><span class="section-anchor"> <a rel="bookmark" href="#index-of-zips"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <embed><table> <tr> <th>ZIP</th> <th>Title</th> <th>Status</th> </tr> - <tr> <td>0</td> <td class="left"><a href="zip-0000">ZIP Process</a></td> <td>Active</td> - <tr> <td><span class="reserved">1</span></td> <td class="left"><a class="reserved" href="zip-0001">Network Upgrade Policy and Scheduling</a></td> <td>Reserved</td> - <tr> <td><span class="reserved">2</span></td> <td class="left"><a class="reserved" href="zip-0002">Design Considerations for Network Upgrades</a></td> <td>Reserved</td> - <tr> <td>32</td> <td class="left"><a href="zip-0032">Shielded Hierarchical Deterministic Wallets</a></td> <td>Final</td> - <tr> <td><span class="reserved">76</span></td> <td class="left"><a class="reserved" href="zip-0076">Transaction Signature Validation before Overwinter</a></td> <td>Reserved</td> - <tr> <td>143</td> <td class="left"><a href="zip-0143">Transaction Signature Validation for Overwinter</a></td> <td>Final</td> - <tr> <td>155</td> <td class="left"><a href="zip-0155">addrv2 message</a></td> <td>Proposed</td> - <tr> <td>173</td> <td class="left"><a href="zip-0173">Bech32 Format</a></td> <td>Final</td> - <tr> <td>200</td> <td class="left"><a href="zip-0200">Network Upgrade Mechanism</a></td> <td>Final</td> - <tr> <td>201</td> <td class="left"><a href="zip-0201">Network Peer Management for Overwinter</a></td> <td>Final</td> - <tr> <td>202</td> <td class="left"><a href="zip-0202">Version 3 Transaction Format for Overwinter</a></td> <td>Final</td> - <tr> <td>203</td> <td class="left"><a href="zip-0203">Transaction Expiry</a></td> <td>Final</td> - <tr> <td><span class="reserved">204</span></td> <td class="left"><a class="reserved" href="zip-0204">Zcash P2P Network Protocol</a></td> <td>Reserved</td> - <tr> <td>205</td> <td class="left"><a href="zip-0205">Deployment of the Sapling Network Upgrade</a></td> <td>Final</td> - <tr> <td>206</td> <td class="left"><a href="zip-0206">Deployment of the Blossom Network Upgrade</a></td> <td>Final</td> - <tr> <td>207</td> <td class="left"><a href="zip-0207">Funding Streams</a></td> <td>Final</td> - <tr> <td>208</td> <td class="left"><a href="zip-0208">Shorter Block Target Spacing</a></td> <td>Final</td> - <tr> <td>209</td> <td class="left"><a href="zip-0209">Prohibit Negative Shielded Chain Value Pool Balances</a></td> <td>Final</td> - <tr> <td><strike>210</strike></td> <td class="left"><strike><a href="zip-0210">Sapling Anchor Deduplication within Transactions</a></strike></td> <td>Withdrawn</td> - <tr> <td>211</td> <td class="left"><a href="zip-0211">Disabling Addition of New Value to the Sprout Chain Value Pool</a></td> <td>Final</td> - <tr> <td>212</td> <td class="left"><a href="zip-0212">Allow Recipient to Derive Ephemeral Secret from Note Plaintext</a></td> <td>Final</td> - <tr> <td>213</td> <td class="left"><a href="zip-0213">Shielded Coinbase</a></td> <td>Final</td> - <tr> <td>214</td> <td class="left"><a href="zip-0214">Consensus rules for a Zcash Development Fund</a></td> <td>Final</td> - <tr> <td>215</td> <td class="left"><a href="zip-0215">Explicitly Defining and Modifying Ed25519 Validation Rules</a></td> <td>Final</td> - <tr> <td>216</td> <td class="left"><a href="zip-0216">Require Canonical Jubjub Point Encodings</a></td> <td>Final</td> - <tr> <td><span class="reserved">217</span></td> <td class="left"><a class="reserved" href="zip-0217">Aggregate Signatures</a></td> <td>Reserved</td> - <tr> <td><span class="reserved">219</span></td> <td class="left"><a class="reserved" href="zip-0219">Disabling Addition of New Value to the Sapling Chain Value Pool</a></td> <td>Reserved</td> - <tr> <td><strike>220</strike></td> <td class="left"><strike><a href="zip-0220">Zcash Shielded Assets</a></strike></td> <td>Withdrawn</td> - <tr> <td>221</td> <td class="left"><a href="zip-0221">FlyClient - Consensus-Layer Changes</a></td> <td>Final</td> - <tr> <td>222</td> <td class="left"><a href="zip-0222">Transparent Zcash Extensions</a></td> <td>Draft</td> - <tr> <td>224</td> <td class="left"><a href="zip-0224">Orchard Shielded Protocol</a></td> <td>Final</td> - <tr> <td>225</td> <td class="left"><a href="zip-0225">Version 5 Transaction Format</a></td> <td>Final</td> - <tr> <td>226</td> <td class="left"><a href="zip-0226">Transfer and Burn of Zcash Shielded Assets</a></td> <td>Draft</td> - <tr> <td>227</td> <td class="left"><a href="zip-0227">Issuance of Zcash Shielded Assets</a></td> <td>Draft</td> - <tr> <td><span class="reserved">228</span></td> <td class="left"><a class="reserved" href="zip-0228">Asset Swaps for Zcash Shielded Assets</a></td> <td>Reserved</td> - <tr> <td>230</td> <td class="left"><a href="zip-0230">Version 6 Transaction Format</a></td> <td>Draft</td> - <tr> <td><span class="reserved">231</span></td> <td class="left"><a class="reserved" href="zip-0231">Decouple Memos from Transaction Outputs</a></td> <td>Reserved</td> - <tr> <td>239</td> <td class="left"><a href="zip-0239">Relay of Version 5 Transactions</a></td> <td>Final</td> - <tr> <td>243</td> <td class="left"><a href="zip-0243">Transaction Signature Validation for Sapling</a></td> <td>Final</td> - <tr> <td>244</td> <td class="left"><a href="zip-0244">Transaction Identifier Non-Malleability</a></td> <td>Final</td> - <tr> <td>245</td> <td class="left"><a href="zip-0245">Transaction Identifier Digests & Signature Validation for Transparent Zcash Extensions</a></td> <td>Draft</td> - <tr> <td>250</td> <td class="left"><a href="zip-0250">Deployment of the Heartwood Network Upgrade</a></td> <td>Final</td> - <tr> <td>251</td> <td class="left"><a href="zip-0251">Deployment of the Canopy Network Upgrade</a></td> <td>Final</td> - <tr> <td>252</td> <td class="left"><a href="zip-0252">Deployment of the NU5 Network Upgrade</a></td> <td>Final</td> - <tr> <td>300</td> <td class="left"><a href="zip-0300">Cross-chain Atomic Transactions</a></td> <td>Proposed</td> - <tr> <td>301</td> <td class="left"><a href="zip-0301">Zcash Stratum Protocol</a></td> <td>Final</td> - <tr> <td>302</td> <td class="left"><a href="zip-0302">Standardized Memo Field Format</a></td> <td>Draft</td> - <tr> <td><span class="reserved">303</span></td> <td class="left"><a class="reserved" href="zip-0303">Sprout Payment Disclosure</a></td> <td>Reserved</td> - <tr> <td>304</td> <td class="left"><a href="zip-0304">Sapling Address Signatures</a></td> <td>Draft</td> - <tr> <td><span class="reserved">305</span></td> <td class="left"><a class="reserved" href="zip-0305">Best Practices for Hardware Wallets supporting Sapling</a></td> <td>Reserved</td> - <tr> <td><span class="reserved">306</span></td> <td class="left"><a class="reserved" href="zip-0306">Security Considerations for Anchor Selection</a></td> <td>Reserved</td> - <tr> <td>307</td> <td class="left"><a href="zip-0307">Light Client Protocol for Payment Detection</a></td> <td>Draft</td> - <tr> <td>308</td> <td class="left"><a href="zip-0308">Sprout to Sapling Migration</a></td> <td>Final</td> - <tr> <td><span class="reserved">309</span></td> <td class="left"><a class="reserved" href="zip-0309">Blind Off-chain Lightweight Transactions (BOLT)</a></td> <td>Reserved</td> - <tr> <td>310</td> <td class="left"><a href="zip-0310">Security Properties of Sapling Viewing Keys</a></td> <td>Draft</td> - <tr> <td><span class="reserved">311</span></td> <td class="left"><a class="reserved" href="zip-0311">Sapling Payment Disclosure</a></td> <td>Reserved</td> - <tr> <td><span class="reserved">312</span></td> <td class="left"><a class="reserved" href="zip-0312">Shielded Multisignatures using FROST</a></td> <td>Reserved</td> - <tr> <td><strike>313</strike></td> <td class="left"><strike><a href="zip-0313">Reduce Conventional Transaction Fee to 1000 zatoshis</a></strike></td> <td>Obsolete</td> - <tr> <td><span class="reserved">314</span></td> <td class="left"><a class="reserved" href="zip-0314">Privacy upgrades to the Zcash light client protocol</a></td> <td>Reserved</td> - <tr> <td><span class="reserved">315</span></td> <td class="left"><a class="reserved" href="zip-0315">Best Practices for Wallet Handling of Multiple Pools</a></td> <td>Reserved</td> - <tr> <td>316</td> <td class="left"><a href="zip-0316">Unified Addresses and Unified Viewing Keys</a></td> <td>Revision 0: Final, Revision 1: Proposed</td> - <tr> <td>317</td> <td class="left"><a href="zip-0317">Proportional Transfer Fee Mechanism</a></td> <td>Active</td> - <tr> <td><span class="reserved">318</span></td> <td class="left"><a class="reserved" href="zip-0318">Associated Payload Encryption</a></td> <td>Reserved</td> - <tr> <td><span class="reserved">319</span></td> <td class="left"><a class="reserved" href="zip-0319">Options for Shielded Pool Retirement</a></td> <td>Reserved</td> - <tr> <td>320</td> <td class="left"><a href="zip-0320">Defining an Address Type to which funds can only be sent from Transparent Addresses</a></td> <td>Draft</td> - <tr> <td>321</td> <td class="left"><a href="zip-0321">Payment Request URIs</a></td> <td>Proposed</td> - <tr> <td><span class="reserved">322</span></td> <td class="left"><a class="reserved" href="zip-0322">Generic Signed Message Format</a></td> <td>Reserved</td> - <tr> <td><span class="reserved">323</span></td> <td class="left"><a class="reserved" href="zip-0323">Specification of getblocktemplate for Zcash</a></td> <td>Reserved</td> - <tr> <td><span class="reserved">332</span></td> <td class="left"><a class="reserved" href="zip-0332">Wallet Recovery from zcashd HD Seeds</a></td> <td>Reserved</td> - <tr> <td><span class="reserved">339</span></td> <td class="left"><a class="reserved" href="zip-0339">Wallet Recovery Words</a></td> <td>Reserved</td> - <tr> <td>400</td> <td class="left"><a href="zip-0400">Wallet.dat format</a></td> <td>Draft</td> - <tr> <td>401</td> <td class="left"><a href="zip-0401">Addressing Mempool Denial-of-Service</a></td> <td>Active</td> - <tr> <td><span class="reserved">402</span></td> <td class="left"><a class="reserved" href="zip-0402">New Wallet Database Format</a></td> <td>Reserved</td> - <tr> <td><span class="reserved">403</span></td> <td class="left"><a class="reserved" href="zip-0403">Verification Behaviour of zcashd</a></td> <td>Reserved</td> - <tr> <td><span class="reserved">416</span></td> <td class="left"><a class="reserved" href="zip-0416">Support for Unified Addresses in zcashd</a></td> <td>Reserved</td> - <tr> <td><strike>1001</strike></td> <td class="left"><strike><a href="zip-1001">Keep the Block Distribution as Initially Defined — 90% to Miners</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1002</strike></td> <td class="left"><strike><a href="zip-1002">Opt-in Donation Feature</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1003</strike></td> <td class="left"><strike><a href="zip-1003">20% Split Evenly Between the ECC and the Zcash Foundation, and a Voting System Mandate</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1004</strike></td> <td class="left"><strike><a href="zip-1004">Miner-Directed Dev Fund</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1005</strike></td> <td class="left"><strike><a href="zip-1005">Zcash Community Funding System</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1006</strike></td> <td class="left"><strike><a href="zip-1006">Development Fund of 10% to a 2-of-3 Multisig with Community-Involved Third Entity</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1007</strike></td> <td class="left"><strike><a href="zip-1007">Enforce Development Fund Commitments with a Legal Charter</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1008</strike></td> <td class="left"><strike><a href="zip-1008">Fund ECC for Two More Years</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1009</strike></td> <td class="left"><strike><a href="zip-1009">Five-Entity Strategic Council</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1010</strike></td> <td class="left"><strike><a href="zip-1010">Compromise Dev Fund Proposal With Diverse Funding Streams</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1011</strike></td> <td class="left"><strike><a href="zip-1011">Decentralize the Dev Fee</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1012</strike></td> <td class="left"><strike><a href="zip-1012">Dev Fund to ECC + ZF + Major Grants</a></strike></td> <td>Obsolete</td> - <tr> <td><strike>1013</strike></td> <td class="left"><strike><a href="zip-1013">Keep It Simple, Zcashers: 10% to ECC, 10% to ZF</a></strike></td> <td>Obsolete</td> - <tr> <td>1014</td> <td class="left"><a href="zip-1014">Establishing a Dev Fund for ECC, ZF, and Major Grants</a></td> <td>Active</td> - <tr> <td>guide</td> <td class="left"><a href="zip-guide">{Something Short and To the Point}</a></td> <td>Draft</td> + <tr> <td>0</td> <td class="left"><a href="./zip-0000">ZIP Process</a></td> <td>Active</td> + <tr> <td><span class="reserved">1</span></td> <td class="left"><a class="reserved" href="./zip-0001">Network Upgrade Policy and Scheduling</a></td> <td>Reserved</td> + <tr> <td><span class="reserved">2</span></td> <td class="left"><a class="reserved" href="./zip-0002">Design Considerations for Network Upgrades</a></td> <td>Reserved</td> + <tr> <td>32</td> <td class="left"><a href="./zip-0032">Shielded Hierarchical Deterministic Wallets</a></td> <td>Final</td> + <tr> <td><span class="reserved">76</span></td> <td class="left"><a class="reserved" href="./zip-0076">Transaction Signature Validation before Overwinter</a></td> <td>Reserved</td> + <tr> <td>143</td> <td class="left"><a href="./zip-0143">Transaction Signature Validation for Overwinter</a></td> <td>Final</td> + <tr> <td>155</td> <td class="left"><a href="./zip-0155">addrv2 message</a></td> <td>Proposed</td> + <tr> <td>173</td> <td class="left"><a href="./zip-0173">Bech32 Format</a></td> <td>Final</td> + <tr> <td>200</td> <td class="left"><a href="./zip-0200">Network Upgrade Mechanism</a></td> <td>Final</td> + <tr> <td>201</td> <td class="left"><a href="./zip-0201">Network Peer Management for Overwinter</a></td> <td>Final</td> + <tr> <td>202</td> <td class="left"><a href="./zip-0202">Version 3 Transaction Format for Overwinter</a></td> <td>Final</td> + <tr> <td>203</td> <td class="left"><a href="./zip-0203">Transaction Expiry</a></td> <td>Final</td> + <tr> <td><span class="reserved">204</span></td> <td class="left"><a class="reserved" href="./zip-0204">Zcash P2P Network Protocol</a></td> <td>Reserved</td> + <tr> <td>205</td> <td class="left"><a href="./zip-0205">Deployment of the Sapling Network Upgrade</a></td> <td>Final</td> + <tr> <td>206</td> <td class="left"><a href="./zip-0206">Deployment of the Blossom Network Upgrade</a></td> <td>Final</td> + <tr> <td>207</td> <td class="left"><a href="./zip-0207">Funding Streams</a></td> <td>Final</td> + <tr> <td>208</td> <td class="left"><a href="./zip-0208">Shorter Block Target Spacing</a></td> <td>Final</td> + <tr> <td>209</td> <td class="left"><a href="./zip-0209">Prohibit Negative Shielded Chain Value Pool Balances</a></td> <td>Final</td> + <tr> <td><strike>210</strike></td> <td class="left"><strike><a href="./zip-0210">Sapling Anchor Deduplication within Transactions</a></strike></td> <td>Withdrawn</td> + <tr> <td>211</td> <td class="left"><a href="./zip-0211">Disabling Addition of New Value to the Sprout Chain Value Pool</a></td> <td>Final</td> + <tr> <td>212</td> <td class="left"><a href="./zip-0212">Allow Recipient to Derive Ephemeral Secret from Note Plaintext</a></td> <td>Final</td> + <tr> <td>213</td> <td class="left"><a href="./zip-0213">Shielded Coinbase</a></td> <td>Final</td> + <tr> <td>214</td> <td class="left"><a href="./zip-0214">Consensus rules for a Zcash Development Fund</a></td> <td>Final</td> + <tr> <td>215</td> <td class="left"><a href="./zip-0215">Explicitly Defining and Modifying Ed25519 Validation Rules</a></td> <td>Final</td> + <tr> <td>216</td> <td class="left"><a href="./zip-0216">Require Canonical Jubjub Point Encodings</a></td> <td>Final</td> + <tr> <td><span class="reserved">217</span></td> <td class="left"><a class="reserved" href="./zip-0217">Aggregate Signatures</a></td> <td>Reserved</td> + <tr> <td><span class="reserved">219</span></td> <td class="left"><a class="reserved" href="./zip-0219">Disabling Addition of New Value to the Sapling Chain Value Pool</a></td> <td>Reserved</td> + <tr> <td><strike>220</strike></td> <td class="left"><strike><a href="./zip-0220">Zcash Shielded Assets</a></strike></td> <td>Withdrawn</td> + <tr> <td>221</td> <td class="left"><a href="./zip-0221">FlyClient - Consensus-Layer Changes</a></td> <td>Final</td> + <tr> <td>222</td> <td class="left"><a href="./zip-0222">Transparent Zcash Extensions</a></td> <td>Draft</td> + <tr> <td>224</td> <td class="left"><a href="./zip-0224">Orchard Shielded Protocol</a></td> <td>Final</td> + <tr> <td>225</td> <td class="left"><a href="./zip-0225">Version 5 Transaction Format</a></td> <td>Final</td> + <tr> <td>226</td> <td class="left"><a href="./zip-0226">Transfer and Burn of Zcash Shielded Assets</a></td> <td>Draft</td> + <tr> <td>227</td> <td class="left"><a href="./zip-0227">Issuance of Zcash Shielded Assets</a></td> <td>Draft</td> + <tr> <td><span class="reserved">228</span></td> <td class="left"><a class="reserved" href="./zip-0228">Asset Swaps for Zcash Shielded Assets</a></td> <td>Reserved</td> + <tr> <td>230</td> <td class="left"><a href="./zip-0230">Version 6 Transaction Format</a></td> <td>Draft</td> + <tr> <td><span class="reserved">231</span></td> <td class="left"><a class="reserved" href="./zip-0231">Decouple Memos from Transaction Outputs</a></td> <td>Reserved</td> + <tr> <td>239</td> <td class="left"><a href="./zip-0239">Relay of Version 5 Transactions</a></td> <td>Final</td> + <tr> <td>243</td> <td class="left"><a href="./zip-0243">Transaction Signature Validation for Sapling</a></td> <td>Final</td> + <tr> <td>244</td> <td class="left"><a href="./zip-0244">Transaction Identifier Non-Malleability</a></td> <td>Final</td> + <tr> <td>245</td> <td class="left"><a href="./zip-0245">Transaction Identifier Digests & Signature Validation for Transparent Zcash Extensions</a></td> <td>Draft</td> + <tr> <td>250</td> <td class="left"><a href="./zip-0250">Deployment of the Heartwood Network Upgrade</a></td> <td>Final</td> + <tr> <td>251</td> <td class="left"><a href="./zip-0251">Deployment of the Canopy Network Upgrade</a></td> <td>Final</td> + <tr> <td>252</td> <td class="left"><a href="./zip-0252">Deployment of the NU5 Network Upgrade</a></td> <td>Final</td> + <tr> <td><span class="reserved">253</span></td> <td class="left"><a class="reserved" href="./zip-0253">Deployment of the NU6 Network Upgrade</a></td> <td>Reserved</td> + <tr> <td>300</td> <td class="left"><a href="./zip-0300">Cross-chain Atomic Transactions</a></td> <td>Proposed</td> + <tr> <td>301</td> <td class="left"><a href="./zip-0301">Zcash Stratum Protocol</a></td> <td>Final</td> + <tr> <td>302</td> <td class="left"><a href="./zip-0302">Standardized Memo Field Format</a></td> <td>Draft</td> + <tr> <td><span class="reserved">303</span></td> <td class="left"><a class="reserved" href="./zip-0303">Sprout Payment Disclosure</a></td> <td>Reserved</td> + <tr> <td>304</td> <td class="left"><a href="./zip-0304">Sapling Address Signatures</a></td> <td>Draft</td> + <tr> <td><span class="reserved">305</span></td> <td class="left"><a class="reserved" href="./zip-0305">Best Practices for Hardware Wallets supporting Sapling</a></td> <td>Reserved</td> + <tr> <td><span class="reserved">306</span></td> <td class="left"><a class="reserved" href="./zip-0306">Security Considerations for Anchor Selection</a></td> <td>Reserved</td> + <tr> <td>307</td> <td class="left"><a href="./zip-0307">Light Client Protocol for Payment Detection</a></td> <td>Draft</td> + <tr> <td>308</td> <td class="left"><a href="./zip-0308">Sprout to Sapling Migration</a></td> <td>Final</td> + <tr> <td><span class="reserved">309</span></td> <td class="left"><a class="reserved" href="./zip-0309">Blind Off-chain Lightweight Transactions (BOLT)</a></td> <td>Reserved</td> + <tr> <td>310</td> <td class="left"><a href="./zip-0310">Security Properties of Sapling Viewing Keys</a></td> <td>Draft</td> + <tr> <td><span class="reserved">311</span></td> <td class="left"><a class="reserved" href="./zip-0311">Sapling Payment Disclosure</a></td> <td>Reserved</td> + <tr> <td><span class="reserved">312</span></td> <td class="left"><a class="reserved" href="./zip-0312">Shielded Multisignatures using FROST</a></td> <td>Reserved</td> + <tr> <td><strike>313</strike></td> <td class="left"><strike><a href="./zip-0313">Reduce Conventional Transaction Fee to 1000 zatoshis</a></strike></td> <td>Obsolete</td> + <tr> <td><span class="reserved">314</span></td> <td class="left"><a class="reserved" href="./zip-0314">Privacy upgrades to the Zcash light client protocol</a></td> <td>Reserved</td> + <tr> <td><span class="reserved">315</span></td> <td class="left"><a class="reserved" href="./zip-0315">Best Practices for Wallet Handling of Multiple Pools</a></td> <td>Reserved</td> + <tr> <td>316</td> <td class="left"><a href="./zip-0316">Unified Addresses and Unified Viewing Keys</a></td> <td>Revision 0: Final, Revision 1: Proposed</td> + <tr> <td>317</td> <td class="left"><a href="./zip-0317">Proportional Transfer Fee Mechanism</a></td> <td>Active</td> + <tr> <td><span class="reserved">318</span></td> <td class="left"><a class="reserved" href="./zip-0318">Associated Payload Encryption</a></td> <td>Reserved</td> + <tr> <td><span class="reserved">319</span></td> <td class="left"><a class="reserved" href="./zip-0319">Options for Shielded Pool Retirement</a></td> <td>Reserved</td> + <tr> <td>320</td> <td class="left"><a href="./zip-0320">Defining an Address Type to which funds can only be sent from Transparent Addresses</a></td> <td>Proposed</td> + <tr> <td>321</td> <td class="left"><a href="./zip-0321">Payment Request URIs</a></td> <td>Proposed</td> + <tr> <td><span class="reserved">322</span></td> <td class="left"><a class="reserved" href="./zip-0322">Generic Signed Message Format</a></td> <td>Reserved</td> + <tr> <td><span class="reserved">323</span></td> <td class="left"><a class="reserved" href="./zip-0323">Specification of getblocktemplate for Zcash</a></td> <td>Reserved</td> + <tr> <td>324</td> <td class="left"><a href="./zip-0324">URI-Encapsulated Payments</a></td> <td>Draft</td> + <tr> <td><span class="reserved">332</span></td> <td class="left"><a class="reserved" href="./zip-0332">Wallet Recovery from zcashd HD Seeds</a></td> <td>Reserved</td> + <tr> <td><span class="reserved">339</span></td> <td class="left"><a class="reserved" href="./zip-0339">Wallet Recovery Words</a></td> <td>Reserved</td> + <tr> <td>340</td> <td class="left"><a href="./zip-0340.md"></a></td> <td></td> + <tr> <td>400</td> <td class="left"><a href="./zip-0400">Wallet.dat format</a></td> <td>Draft</td> + <tr> <td>401</td> <td class="left"><a href="./zip-0401">Addressing Mempool Denial-of-Service</a></td> <td>Active</td> + <tr> <td><span class="reserved">402</span></td> <td class="left"><a class="reserved" href="./zip-0402">New Wallet Database Format</a></td> <td>Reserved</td> + <tr> <td><span class="reserved">403</span></td> <td class="left"><a class="reserved" href="./zip-0403">Verification Behaviour of zcashd</a></td> <td>Reserved</td> + <tr> <td><span class="reserved">416</span></td> <td class="left"><a class="reserved" href="./zip-0416">Support for Unified Addresses in zcashd</a></td> <td>Reserved</td> + <tr> <td><strike>1001</strike></td> <td class="left"><strike><a href="./zip-1001">Keep the Block Distribution as Initially Defined — 90% to Miners</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1002</strike></td> <td class="left"><strike><a href="./zip-1002">Opt-in Donation Feature</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1003</strike></td> <td class="left"><strike><a href="./zip-1003">20% Split Evenly Between the ECC and the Zcash Foundation, and a Voting System Mandate</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1004</strike></td> <td class="left"><strike><a href="./zip-1004">Miner-Directed Dev Fund</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1005</strike></td> <td class="left"><strike><a href="./zip-1005">Zcash Community Funding System</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1006</strike></td> <td class="left"><strike><a href="./zip-1006">Development Fund of 10% to a 2-of-3 Multisig with Community-Involved Third Entity</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1007</strike></td> <td class="left"><strike><a href="./zip-1007">Enforce Development Fund Commitments with a Legal Charter</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1008</strike></td> <td class="left"><strike><a href="./zip-1008">Fund ECC for Two More Years</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1009</strike></td> <td class="left"><strike><a href="./zip-1009">Five-Entity Strategic Council</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1010</strike></td> <td class="left"><strike><a href="./zip-1010">Compromise Dev Fund Proposal With Diverse Funding Streams</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1011</strike></td> <td class="left"><strike><a href="./zip-1011">Decentralize the Dev Fee</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1012</strike></td> <td class="left"><strike><a href="./zip-1012">Dev Fund to ECC + ZF + Major Grants</a></strike></td> <td>Obsolete</td> + <tr> <td><strike>1013</strike></td> <td class="left"><strike><a href="./zip-1013">Keep It Simple, Zcashers: 10% to ECC, 10% to ZF</a></strike></td> <td>Obsolete</td> + <tr> <td>1014</td> <td class="left"><a href="./zip-1014">Establishing a Dev Fund for ECC, ZF, and Major Grants</a></td> <td>Active</td> + <tr> <td>guide</td> <td class="left"><a href="./zip-guide">{Something Short and To the Point}</a></td> <td>Draft</td> +</table></embed></section> + <section id="drafts-without-assigned-zip-numbers"><h2><span class="section-heading">Drafts without assigned ZIP numbers</span><span class="section-anchor"> <a rel="bookmark" href="#drafts-without-assigned-zip-numbers"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <p>These are works-in-progress, and may never be assigned ZIP numbers if their ideas become obsoleted or abandoned. Do not assume that these drafts will exist in perpetuity; instead assume that they will either move to a numbered ZIP, or be deleted.</p> + <embed><table> + <tr> <th>Title</th> </tr> </table></embed></section> </section> </body>
protocol/blossom.pdf +0 −0

Diff not cached — view on GitHub.

protocol/canopy.pdf +0 −0

Diff not cached — view on GitHub.

protocol/heartwood.pdf +0 −0

Diff not cached — view on GitHub.

protocol/nu5.pdf +0 −0

Diff not cached — view on GitHub.

protocol/protocol.pdf +0 −0

Diff not cached — view on GitHub.

protocol/sapling.pdf +0 −0

Diff not cached — view on GitHub.

zip-0216.html +2 −2
@@ -29,9 +29,9 @@ <span class="math">\(u\!\)</span> -coordinate is zero, there are two encodings that will be accepted:</p> <pre data-language="rust"><span class="c1">// Fix the sign of `u` if necessary</span> -<span class="kd">let</span><span class="w"> </span><span class="n">flip_sign</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Choice</span>::<span class="n">from</span><span class="p">((</span><span class="n">u</span><span class="p">.</span><span class="n">to_bytes</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">sign</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span> +<span class="kd">let</span><span class="w"> </span><span class="n">flip_sign</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Choice</span><span class="p">::</span><span class="n">from</span><span class="p">((</span><span class="n">u</span><span class="p">.</span><span class="n">to_bytes</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">sign</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span> <span class="kd">let</span><span class="w"> </span><span class="n">u_negated</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="n">u</span><span class="p">;</span> -<span class="kd">let</span><span class="w"> </span><span class="n">final_u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Fq</span>::<span class="n">conditional_select</span><span class="p">(</span><span class="o">&amp;</span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">u_negated</span><span class="p">,</span><span class="w"> </span><span class="n">flip_sign</span><span class="p">);</span></pre> +<span class="kd">let</span><span class="w"> </span><span class="n">final_u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Fq</span><span class="p">::</span><span class="n">conditional_select</span><span class="p">(</span><span class="o">&amp;</span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">u_negated</span><span class="p">,</span><span class="w"> </span><span class="n">flip_sign</span><span class="p">);</span></pre> <p>This code accepts either sign bit, because <code>u_negated == u</code>.</p> <p>There are two points on the Jubjub curve with <span class="math">\(u\!\)</span>
zip-0253.html +17 −0
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> +<head> + <title>ZIP 253: Deployment of the NU6 Network Upgrade</title> + <meta charset="utf-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="css/style.css"></head> +<body> + <section> + <pre>ZIP: 253 +Title: Deployment of the NU6 Network Upgrade +Owners: Daira-Emma Hopwood &lt;daira-emma@electriccoin.co&gt; +Status: Reserved +Category: Consensus / Network +Discussions-To: &lt;<a href="https://github.com/zcash/zips/issues/806">https://github.com/zcash/zips/issues/806</a>&gt;</pre> + </section> +</body> +</html> \ No newline at end of file
zip-0316.html +10 −2
@@ -165,8 +165,16 @@ <li>Revision 1: This version adds support for <a href="#must-understand-typecodes">MUST-understand Typecodes</a> and <a href="#address-expiration-metadata">Address Expiration Metadata</a>. It also drops the restriction that a UA/UVK must contain at least one shielded Item.</li> </ul> <p>A Revision 0 UA/UVK is distinguished from a Revision 1 UA/UVK by its Human-Readable Part, as follows.</p> - <p>Let <em>prefix</em> be: * “<code>u</code>”, if this is a UA/UVK prior to <a href="#revision-1">Revision 1</a>; * “<code>ur</code>”, if this is a UA/UVK from <a href="#revision-1">Revision 1</a> onward.</p> - <p>The Human-Readable Parts (as defined in <a id="footnote-reference-10" class="footnote_reference" href="#bip-0350">36</a>) of Unified Addresses are defined as: * <em>prefix</em>, for Unified Addresses on Mainnet; * <em>prefix</em> || “<code>test</code>”, for Unified Addresses on Testnet.</p> + <p>Let <em>prefix</em> be:</p> + <ul> + <li>“<code>u</code>”, if this is a UA/UVK prior to <a href="#revision-1">Revision 1</a>;</li> + <li>“<code>ur</code>”, if this is a UA/UVK from <a href="#revision-1">Revision 1</a> onward.</li> + </ul> + <p>The Human-Readable Parts (as defined in <a id="footnote-reference-10" class="footnote_reference" href="#bip-0350">36</a>) of Unified Addresses are defined as:</p> + <ul> + <li><em>prefix</em>, for Unified Addresses on Mainnet;</li> + <li><em>prefix</em> || “<code>test</code>”, for Unified Addresses on Testnet.</li> + </ul> <p>The Human-Readable Parts of Unified Viewing Keys are defined as:</p> <ul> <li><em>prefix</em> || “<code>ivk</code>” for Unified Incoming Viewing Keys on Mainnet;</li>
zip-0320.html +1 −1
@@ -12,7 +12,7 @@ Owners: Daira-Emma Hopwood &lt;daira@electriccoin.co&gt; Kris Nuttycombe &lt;kris@nutty.land&gt; Credits: Hanh -Status: Draft +Status: Proposed Category: Standards / Wallet Created: 2024-01-12 License: MIT
zip-0324.html +32 −32
@@ -25,16 +25,16 @@ Category: Standards / Wallet Created: 2019-07-17 License: MIT</pre> - <section id="terminology"><h2><span class="section-heading">Terminology</span><span class="section-anchor"> <a rel="bookmark" href="#terminology"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="terminology"><h2><span class="section-heading">Terminology</span><span class="section-anchor"> <a rel="bookmark" href="#terminology"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <p>The key words "MUST", "MUST NOT", "SHOULD", and "MAY" in this document are to be interpreted as described in BCP 14 <a id="footnote-reference-1" class="footnote_reference" href="#bcp14">1</a> when, and only when, they appear in all capitals.</p> <p>Zcash protocol terms are as defined in the Zcash Protocol Specification. <a id="footnote-reference-2" class="footnote_reference" href="#protocol">3</a></p> <p id="applink">By “applink” we mean a platform mechanism for triggering local applications using HTTPS links, such as App Links <a id="footnote-reference-3" class="footnote_reference" href="#app-links">5</a> on Android, Universal Links <a id="footnote-reference-4" class="footnote_reference" href="#universal-links">6</a> on iOS, or App URI handlers <a id="footnote-reference-5" class="footnote_reference" href="#app-uri-handlers">7</a> on Windows.</p> </section> - <section id="abstract"><h2><span class="section-heading">Abstract</span><span class="section-anchor"> <a rel="bookmark" href="#abstract"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="abstract"><h2><span class="section-heading">Abstract</span><span class="section-anchor"> <a rel="bookmark" href="#abstract"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <p>This proposal specifies a mechanism for sending Zcash payments via any unmodified (secure) messaging service, e.g., Signal or WhatsApp. The sender need not know the recipient's address and the recipient need not have a Zcash wallet already installed. Payments occur via an ordinary text/WhatsApp/Signal message containing a URI. The URI encodes the secret spending key of an ephemeral Zcash “wallet address”, to which the funds have been transferred. Anyone who learns the URI can accept this payment, by a “finalization” process which uses the key given in the URI to transfer the encapsulated funds to their own wallet. After the payment is finalized, via a suitable on-chain transaction by the recipient, it becomes irrevocable.</p> <p>The proposal specifies the syntax and semantics of URI-Encapsulated Payments, the workflow of generating and handling them, and requisite infrastructure.</p> <p>At its core, a URI encapsulated payment communicates the existence of a transaction (specifically a note committing to an amount of funds) to a receiving client. The URI encodes the amount of the payment and a key used to derive all necessary randomness for note construction including the address and secret key needed to spend it.</p> - <section id="usage-story"><h3><span class="section-heading">Usage Story</span><span class="section-anchor"> <a rel="bookmark" href="#usage-story"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="usage-story"><h3><span class="section-heading">Usage Story</span><span class="section-anchor"> <a rel="bookmark" href="#usage-story"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>Alice wants to send a 1.23 ZEC payment to Bob. She doesn't have Bob's Zcash address — and Bob may not even have a wallet or have heard of Zcash! However, she does have some end-to-end encrypted channel to Bob on a secure messaging app, such as Signal or WhatsApp. She instructs her own Zcash wallet to send 1.23 ZEC on that channel. Her wallet then automatically generates a new ephemeral Zcash address and sends 1.23001 ZEC to this address. It then constructs a payment URI containing the secret key corresponding to the ephemeral address, and sends it to Bob via the secure messaging app.</p> <p>Bob receives the message, which looks as follows:</p> <blockquote> @@ -45,15 +45,15 @@ <p>Bob clicks the link. His Zcash mobile wallet app (which is already installed and has configured itself as a handler for URLs of that form) shows up, and tells Bob that a payment of 1.23 ZEC awaits him. The wallet app confirms the existence of the pertinent transactions on the blockchain, and then offers to finalize the payment. Bob clicks the “Finalize” button, and his wallet app generates a transaction moving the money to his own address (using the extra 0.00001 ZEC he has received to pay the transaction fee). When this transaction is confirmed on-chain, Alice's and Bob's wallets both indicate that the payment is finalized, and thus Bob can send the funds to other parties.</p> </section> </section> - <section id="motivation"><h2><span class="section-heading">Motivation</span><span class="section-anchor"> <a rel="bookmark" href="#motivation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="motivation"><h2><span class="section-heading">Motivation</span><span class="section-anchor"> <a rel="bookmark" href="#motivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <p>This proposal enables sending of funds without exposing users to the notion of payment addresses and their secure distribution. Instead, funds can be sent using any pre-existing communication channel, by a single message sent unidirectionally from the sender to the recipient. This message conveys all the information needed to obtain control of the funds, compactly expressed as a textual URI.</p> <p>Consequently, all functionality related to contact discovery and secure-channel establishment can be delegated to the message app(s) with which the user is already familiar, and in which the user has already established communication channels to many of their contacts.</p> <p>Moreover, funds can be sent to users who have not yet installed wallet software and who do not yet have a payment address. The recipient can collect the funds at any later time by installing suitable software.</p> <p>Additionally, the proposal greatly improves the scalability of Zcash. If a recipient only receives URI payments, they need not scan the blockchain or delegate their view keys to a third party to do so.</p> <p>Finally, this avoids the fat-finger problem of sending funds to the wrong address. The user sends funds via a known contact on, e.g., WhatsApp, who they have a relationship with or at least can confirm the recipient's identity. Moreover, even once funds are sent via a URI, they can be recovered if the other party does not claim them.</p> <p>The proposal is complementary to ZIP 321 <a id="footnote-reference-6" class="footnote_reference" href="#zip-0321">4</a>, which will standardize <em>Payment Request URIs</em> using which the payment <em>recipient</em> can convey their persistent payment address to the <em>sender</em>, for subsequent fund transfers (to be done using the normal on-chain mechanism rather than the encapsulated payments described in the current proposal).</p> </section> - <section id="requirements"><h2><span class="section-heading">Requirements</span><span class="section-anchor"> <a rel="bookmark" href="#requirements"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="requirements"><h2><span class="section-heading">Requirements</span><span class="section-anchor"> <a rel="bookmark" href="#requirements"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <p>This proposal's specification of URI-Encapsulated Payments, and the intended protocols for using them, is meant to fulfill the following requirements:</p> <ul> <li>The protocol must not require the sender of a payment to stay online until the recipient receives the URI (let alone finalizes the payment).</li> @@ -66,15 +66,15 @@ <li>Don't lose funds, even if wallets crash, or everything but the sending wallet master secret is lost.</li> </ul> </section> - <section id="non-requirements"><h2><span class="section-heading">Non-requirements</span><span class="section-anchor"> <a rel="bookmark" href="#non-requirements"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="non-requirements"><h2><span class="section-heading">Non-requirements</span><span class="section-anchor"> <a rel="bookmark" href="#non-requirements"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <ul> <li>It is outside the scope of this proposal to establish a secure communication channel for transmission of URI-Encapsulated Payments, or to protect the parties' devices from security compromise.</li> <li>Finalizing the payment may involve significant wait times, on the scale of minutes, as the requisite on-chain transactions are generated, mined and confirmed. This proposal does not try to solve this (though it does try to avoid imposing significant additional delays, and it does address how the intermediate state is conveyed to the user).</li> </ul> </section> - <section id="specification"><h2><span class="section-heading">Specification</span><span class="section-anchor"> <a rel="bookmark" href="#specification"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="specification"><h2><span class="section-heading">Specification</span><span class="section-anchor"> <a rel="bookmark" href="#specification"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <p>A Payment-Encapsulating URI represents the capability to claim the Zcash funds from specific on-chain transactions, as long as they're unspent. See <a href="#usage-story">Usage Story</a> for an example.</p> - <section id="syntax"><h3><span class="section-heading">Syntax</span><span class="section-anchor"> <a rel="bookmark" href="#syntax"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="syntax"><h3><span class="section-heading">Syntax</span><span class="section-anchor"> <a rel="bookmark" href="#syntax"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>A Payment-Encapsulating URI is a Universal Resource Locator (URL), as defined in RFC 3986 <a id="footnote-reference-7" class="footnote_reference" href="#rfc3986">2</a>, of the following form.</p> <p>Scheme: <code>https</code></p> <p>Host: <code>pay.withzcash.com</code></p> @@ -87,7 +87,7 @@ <li><code>key=</code> is a 256-bit random number encoded with Bech32 as specified in Section 5.6.9 of the Zcash Protocol Specification <a id="footnote-reference-8" class="footnote_reference" href="#protocol">3</a>). MUST be present.</li> </ul> </section> - <section id="semantics"><h3><span class="section-heading">Semantics</span><span class="section-anchor"> <a rel="bookmark" href="#semantics"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="semantics"><h3><span class="section-heading">Semantics</span><span class="section-anchor"> <a rel="bookmark" href="#semantics"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>The values of <code>key</code> and <code>amount</code> deterministically imply a unique <em>payment note</em> corresponding to this URI, which is a Zcash Sapling note that carries the given amount and is spendable by a Sapling spending key derived from <code>key</code>. The derivation of this note is done by the following procedure:</p> <p><em>DerivePaymentNote(key,amount)</em>:</p> <ul> @@ -119,7 +119,7 @@ <p>The recipient's wallet software SHOULD convey to the user that the <code>desc</code> value is merely a claim made by the party who sent the URI, and may be tentative, inaccurate or malicious.</p> <p>In particular, the recipient's wallet software SHOULD convey to the user that the amount of ZEC they can successfully transfer to their wallet may be different than that given by the <code>amount</code> parameter, and may change (possibly to zero), until the finalization process has been completed.</p> </section> - <section id="centralized-deployment"><h3><span class="section-heading">Centralized Deployment</span><span class="section-anchor"> <a rel="bookmark" href="#centralized-deployment"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="centralized-deployment"><h3><span class="section-heading">Centralized Deployment</span><span class="section-anchor"> <a rel="bookmark" href="#centralized-deployment"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>The owner of the <code>withzcash.com</code> domain name MUST NOT create a DNS record for the <code>pay.withzcash.com</code> domain name, nor a TLS certificate for it. All feasible means SHOULD be taken to ensure this, and to prevent unintended transfer of ownership or control over the <code>withzcash.com</code> domain name. (See <a href="#rationale-for-uri-format">Rationale for URI Format</a> and <a href="#security-considerations">Security Considerations</a> below for discussion.)</p> <p><a href="#applink">Applink</a> mechanisms let domain name owners provide a whitelist, specifying which apps are authorized to handle URLs with that domain name. This is implemented by serving suitable files at well-known paths on the web server of that domain or, in the case of a subdomain, its parent domain. Thus, the owner of the <code>withzcash.com</code> domain effectively controls the whitelist of apps that may be launched by users' platform to handle URI-Encapsulated Payments (see <a href="#security-considerations">Security Considerations</a>). This whitelist should protect users from installing rogue apps that intercept incoming payments. Thus, the domain owner MUST do the following:</p> <ul> @@ -136,17 +136,17 @@ <li>Strive for the whitelist to include all apps that would not place the user at any greater security risk than reputable state-of-the-art wallet apps.</li> </ul> </section> - <section id="testing"><h3><span class="section-heading">Testing</span><span class="section-anchor"> <a rel="bookmark" href="#testing"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="testing"><h3><span class="section-heading">Testing</span><span class="section-anchor"> <a rel="bookmark" href="#testing"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>For testing purposes, all of the above specification is duplicated for the Zcash testnet network, substituting <code>TAZ</code> (Zcash testnet coins) for <code>ZEC</code> and <code>testzcash.com</code> for <code>withzcash.com</code>.</p> <p>A separate “testnet whitelist” MUST be maintained by the owner of the <code>testzcash.com</code> domain name, with a separate policy that SHOULD allow any legitimate third-party developer to add their work-in-progress wallet for testing purposes. Integrity and availability MAY be looser.</p> <p>Wallets apps MAY support just one type of payments (ZEC or TAZ), and if they support both then they MUST keep separate accounting and must clearly distinguish the type when payments or balances are conveyed to users.</p> </section> </section> - <section id="lifecycle-specification"><h2><span class="section-heading">Lifecycle Specification</span><span class="section-anchor"> <a rel="bookmark" href="#lifecycle-specification"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="lifecycle-specification"><h2><span class="section-heading">Lifecycle Specification</span><span class="section-anchor"> <a rel="bookmark" href="#lifecycle-specification"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <p>The lifecycle of a Payment-Encapsulating URI consists of several stages, which in the usual case culminate in the funds being irrevocably deposited into the recipient's personal wallet irrevocably:</p> - <section id="generating-the-notes-and-uri"><h3><span class="section-heading">Generating the notes and URI</span><span class="section-anchor"> <a rel="bookmark" href="#generating-the-notes-and-uri"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="generating-the-notes-and-uri"><h3><span class="section-heading">Generating the notes and URI</span><span class="section-anchor"> <a rel="bookmark" href="#generating-the-notes-and-uri"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>The sender's Zcash wallet app creates an ephemeral spending key, sends ZEC funds to the payment addressed derived from that key, and creates a Payment-Encapsulating URI that contains this ephemeral spending key and the newly-generated note commitments.</p> - <section id="ephemeral-key-derivation"><h4><span class="section-heading">Ephemeral key derivation</span><span class="section-anchor"> <a rel="bookmark" href="#ephemeral-key-derivation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h4> + <section id="ephemeral-key-derivation"><h4><span class="section-heading">Ephemeral key derivation</span><span class="section-anchor"> <a rel="bookmark" href="#ephemeral-key-derivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h4> <p>The ephemeral keys within payment URIs are derived deterministically from the same seed as the main wallet. This ensures that if a wallet is recovered from backup, sent-but-unfinalized payments can be reclaimed.</p> <p>The derivation mechanism is as follows:</p> <ul> @@ -159,17 +159,17 @@ </ul> </section> </section> - <section id="uri-transmission"><h3><span class="section-heading">URI Transmission</span><span class="section-anchor"> <a rel="bookmark" href="#uri-transmission"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="uri-transmission"><h3><span class="section-heading">URI Transmission</span><span class="section-anchor"> <a rel="bookmark" href="#uri-transmission"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>The sender conveys the Payment-Encapsulating URI to the intended recipient, over some secure channel (e.g., an end-to-end encrypted messaging platform such as Signal, WhatsApp or Magic Wormhole; or a QR code scanned in person).</p> <p>If transmitted via a human-readable medium, such as a messaging app, the Payment-Encapsulating URI MAY be accompanied by a contextual explanation that the URI encapsulates a payment, and a suggested action by the recipient to complete the process (see Usage Story above for an example).</p> <p>When sent via a human-readable medium that consists of discrete messages, the message that contains the URI SHOULD NOT contain any payment-specific or manually-entered information outside the URI itself, since this information may not be visible to the recipient (see “Message Rendering” below).</p> <p>From this point, and until finalization or cancellation (see below), from the sender's perspective the payment is “in progress”; it SHOULD be conveyed as such to the sender; and MUST NOT be conveyed as “finalized” or other phrasing that conveys successful completion.</p> </section> - <section id="message-rendering"><h3><span class="section-heading">Message Rendering</span><span class="section-anchor"> <a rel="bookmark" href="#message-rendering"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="message-rendering"><h3><span class="section-heading">Message Rendering</span><span class="section-anchor"> <a rel="bookmark" href="#message-rendering"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>The recipient's device renders the Payment-Encapsulating URI, or an indication of its arrival, along with the aforementioned contextual explanation (if any). The user has the option of “opening” the URI (i.e., by clicking it), which results in the device opening a Zcash wallet app, using the local platforms app link mechanism.</p> <p>A messaging app MAY recognize URI-Encapsulated Payments, and render them in a way that conveys their nature more clearly than raw URI strings. If the messaging medium consists of discrete messages, and a message contains one or more URI-Encapsulated Payments, then the messaging app MAY assume that all other content in that message is automatically generated and contains no payment-specific or manually-generated information, and thus may be discarded during rendering.</p> </section> - <section id="payment-rendering-and-blockchain-lookup"><h3><span class="section-heading">Payment Rendering and Blockchain Lookup</span><span class="section-anchor"> <a rel="bookmark" href="#payment-rendering-and-blockchain-lookup"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="payment-rendering-and-blockchain-lookup"><h3><span class="section-heading">Payment Rendering and Blockchain Lookup</span><span class="section-anchor"> <a rel="bookmark" href="#payment-rendering-and-blockchain-lookup"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>The recipient's Zcash wallet app SHOULD present the payment amount and MAY present the description, as conveyed in the URI, along with an indication of the tentative nature of this information.</p> <p>In parallel, the wallet app SHOULD retrieve the relevant transactions from the Zcash blockchain, by looking up the transaction given by the <code>cmu</code> parameter (this MAY use an efficient index, perhaps assisted by a server), and check whether:</p> <ul> @@ -186,22 +186,22 @@ <p>Within the <em>Pending</em> state, the wallet app MAY also consider “0 confirmations” transactions (i.e., transactions that have been broadcast on the node network but are neither mined nor expired), and convey their existence to the user. These do not suffice for entering the <em>Ready-to-finalize</em> state (since unmined notes cannot be immediately spent.)</p> <p>The aforementioned conditions may change over time (e.g., the transactions may be spent by someone else in the interim), so the status SHOULD be updated periodically.</p> </section> - <section id="finalization"><h3><span class="section-heading">Finalization</span><span class="section-anchor"> <a rel="bookmark" href="#finalization"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="finalization"><h3><span class="section-heading">Finalization</span><span class="section-anchor"> <a rel="bookmark" href="#finalization"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>When the recipient chooses to finalize the payment, the wallet app generates transactions that spends the aforementioned notes (using the ephemeral spending key) and send these Zcash funds to the user's own persistent payment address. These transactions carry the default expiry time (currently 100 blocks).</p> <p>The recipient's wallet app SHOULD convey the payment status as “Finalizing…” starting at the time that the uses initiates the finalization process. It MAY in addition convey the specific action done or event waited.</p> <p>The sender's wallet SHOULD convey the payment status as “Finalizing…” as soon as it detects that relevant transactions have been broadcast on the peer-to-peer network, or mined to the blockchain.</p> <p>Once these transactions are confirmed (to an extent considered satisfactory by the local wallet app; currently 10 confirmations is common practice), their status SHOULD be conveyed as “Finalized”, by both the sender's wallet app and the recipient's wallet app. Both wallets MUST NOT convey the payment as “finalized”, or other phrasing that conveys irrevocability, until this point.</p> <p>If these transactions expire unmined, or are otherwise rendered irrevocably invalidated (e.g., by a rollback), then both wallets' status SHOULD convey this, and the recipient's wallet SHOULD revert to the “Payment Rendering and Blockchain Lookup” stage above.</p> </section> - <section id="payment-cancellation"><h3><span class="section-heading">Payment Cancellation</span><span class="section-anchor"> <a rel="bookmark" href="#payment-cancellation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="payment-cancellation"><h3><span class="section-heading">Payment Cancellation</span><span class="section-anchor"> <a rel="bookmark" href="#payment-cancellation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>At any time prior to the payment being finalized, the sender is capable of cancelling the payment, by themselves finalizing the payment into their own wallet (thereby “clawing back” the funds). If the wallet has not yet sent, for inclusion in the blockchain, any of the transactions associated with the ephemeral spending key, then cancellation can also be done by discarding these transactions or aborting their generation. The sender's wallet app SHOULD offer this feature, and in this case, MUST appropriately handle the race condition where the recipient initiated finalization concurrently.</p> <p>Cancellation requires the sender to know the ephemeral spending key. If the sender has lost this state, it can be recovered deterministically (see <a href="#recovery-from-wallet-crash">Recovery From Wallet Crash</a>, below).</p> </section> - <section id="status-view"><h3><span class="section-heading">Status View</span><span class="section-anchor"> <a rel="bookmark" href="#status-view"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="status-view"><h3><span class="section-heading">Status View</span><span class="section-anchor"> <a rel="bookmark" href="#status-view"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>Wallet apps SHOULD let the user view the status of all payments they have generated, as well as all inbound payment (i.e., URI-Encapsulated Payments that have been sent to the app, e.g., by invocation from messaging apps). The status includes the available metadata, and the payment's current state. When pertinent, the wallet app SHOULD offer the ability to finalize any <em>Pending</em> inbound payment, and MAY offer the ability to cancel any outbound payment.</p> <p>Wallet apps SHOULD actively alert the user (e.g., via status notifications) if a payment that they sent has not been finalized within a reasonable time period (e.g., 1 week), and offer to cancel the payment.</p> </section> - <section id="recovery-from-wallet-crash"><h3><span class="section-heading">Recovery From Wallet Crash</span><span class="section-anchor"> <a rel="bookmark" href="#recovery-from-wallet-crash"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="recovery-from-wallet-crash"><h3><span class="section-heading">Recovery From Wallet Crash</span><span class="section-anchor"> <a rel="bookmark" href="#recovery-from-wallet-crash"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>When recovering from a backed-up wallet phrase, wallet implementations already need to scan the entire chain (from the wallet's birthday) to find transactions that were received by or sent from the wallet. Simultaneously with this, the wallet may recover state about previously-created payment URIs, and regain access to non-finalized funds.</p> <p>We define a “gap limit” <em>N</em>, similar to the “address gap limit” in BIP 44. If a wallet implementation observes <em>N</em> sequentially-derived payment URIs that have no corresponding on-chain note, they may safely expect that no payment URIs beyond that point have ever been derived.</p> <p>Given that both the derivation of a payment URI and the action of “filling” it with a note are performed by the same entity (and in most cases sequentially), it is unlikely that there would be a significantly large gap in payment URI usage. As a balance between the cost of scanning multiple <code>ivk</code>s, and the likelihood of missing on-chain funds due to out-of-order payment URI generation, we specify a standard gap limit of <code>N = 3</code>.</p> @@ -222,7 +222,7 @@ <p>For this recovery process to succeed, wallet implementations MUST fund payment URIs with a Sapling spending key in the wallet. Alternatively, wallet implementations MAY include the set of payment URI <code>ivk</code>s within the set of <code>ivk</code>s they are using for normal chain scanning, but this will slow down the recovery process by a factor of 4 (for a gap limit of <code>N = 3</code>, and a wallet with one Sapling account).</p> </section> </section> - <section id="security-considerations"><h2><span class="section-heading">Security Considerations</span><span class="section-anchor"> <a rel="bookmark" href="#security-considerations"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="security-considerations"><h2><span class="section-heading">Security Considerations</span><span class="section-anchor"> <a rel="bookmark" href="#security-considerations"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <ul> <li>Anyone who intercepts the URI-Encapsulated Payments may steal the encapsulated funds. Therefore, URI-Encapsulated Payments should be sent over a secure channel, and should be kept secret from anyone but the intended recipient. <ul> @@ -244,8 +244,8 @@ <li>Usage of URI-Encapsulated Payments may train users to, generally, click on other types of URI/URL links sent in other messaging contexts. Malicious links sent via unauthenticated messaging channels (e.g., emails and SMS texts) are a common attack vector, used for exploiting vulnerabilities in the apps triggered to handle these links. Even though the fault for vulnerabilities lies with those other apps, and even though this ZIP uses deep link URIs in the way intended, there are none the less these negative externalities to encouraging such use.</li> </ul> </section> - <section id="design-decisions-and-rationale"><h2><span class="section-heading">Design Decisions and Rationale</span><span class="section-anchor"> <a rel="bookmark" href="#design-decisions-and-rationale"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> - <section id="rationale-for-uri-format"><h3><span class="section-heading">Rationale for URI Format</span><span class="section-anchor"> <a rel="bookmark" href="#rationale-for-uri-format"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="design-decisions-and-rationale"><h2><span class="section-heading">Design Decisions and Rationale</span><span class="section-anchor"> <a rel="bookmark" href="#design-decisions-and-rationale"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="rationale-for-uri-format"><h3><span class="section-heading">Rationale for URI Format</span><span class="section-anchor"> <a rel="bookmark" href="#rationale-for-uri-format"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>The URI format <code>https://pay.withzcash.com:65536/v1#...</code> was chosen to allow automatic triggering of wallet software on mobile devices, using the platform's <a href="#applink">applink</a> mechanism, while minimizing the risk of payment information being intercepted by third parties. The latter is prevented by a defense in depth, where any of the following suffices to prevent the payment information from being exposed over the network:</p> <ul> <li>The <code>pay.withzcash.com</code> domain should not resolve.</li> @@ -263,7 +263,7 @@ </ol> <p>Another option, which can be added to any of the above, is to add a confirmation code outside the URI that needs to be manually entered by the user into the wallet app, so that merely intercepting the URI link would not suffice. This does not seem to significantly reduce risk in the scenarios considered, and so deemed to not justify the reduced usability.</p> </section> - <section id="identifying-notes"><h3><span class="section-heading">Identifying Notes</span><span class="section-anchor"> <a rel="bookmark" href="#identifying-notes"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="identifying-notes"><h3><span class="section-heading">Identifying Notes</span><span class="section-anchor"> <a rel="bookmark" href="#identifying-notes"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>The recipient's wallet needs to identify the notes related to the payment (and the on-chain transactions that contain them), in order to verify their validity and then (during the finalization process) spend them.</p> <p><strong>The following is out of date, and reflects an earlier design choice (“0”), while we have transitioned to a different choice (“4”). To be revised.</strong></p> <p>In the above description, we explicitly list the notes involved in the payment (which are easily mapped to the transactions containing them, using a suitable index). This results in long URIs when multiple notes are involved (e.g., when using the aforementioned “powers-of-2 amounts” technique).</p> @@ -280,16 +280,16 @@ <h1>System Message: INFO/1 (zip-0324.rst line 355)</h1> <p>Enumerated list start value not ordinal-1: "0" (ordinal 0)</p> </div> </section> - <section id="additional-rationale"><h3><span class="section-heading">Additional rationale</span><span class="section-anchor"> <a rel="bookmark" href="#additional-rationale"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="additional-rationale"><h3><span class="section-heading">Additional rationale</span><span class="section-anchor"> <a rel="bookmark" href="#additional-rationale"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <ol type="1"> <li>The metadata (amount and description) is provided within the URI. An alternative would be to encode the description in the encrypted memo fields of the associated shielded transactions, and compute the amount from those transactions. However, in that case the metadata would not be available for presentation to the user until the transactions have been retrieved from the blockchain.</li> <li>We support multiple spending keys and multiple notes in one URI, because these payments may be speculatively generated and mined before the payment amount is determined (to allow payments with no latency). For example, the sending wallets may pre-generate transactions for powers-of-2 amounts, and then include only a subset of them in the URI, totalling to the desired amount.</li> <li>We do not include the sender or receiver's identity in the URI, because the sending wallet many not know the name of who it is sending to (or even from). Moreover there is the risk that fraudulent sender/recipient information could be used. If necessitated by circumstances (e.g., the FinCEN "Travel Rule" <a id="footnote-reference-15" class="footnote_reference" href="#fincen-travel-rule">8</a>), claimed sender and recipient identity can be included in <code>desc</code> parameter.</li> </ol> </section> </section> - <section id="open-questions"><h2><span class="section-heading">Open Questions</span><span class="section-anchor"> <a rel="bookmark" href="#open-questions"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> - <section id="uri-usability"><h3><span class="section-heading">URI Usability</span><span class="section-anchor"> <a rel="bookmark" href="#uri-usability"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="open-questions"><h2><span class="section-heading">Open Questions</span><span class="section-anchor"> <a rel="bookmark" href="#open-questions"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="uri-usability"><h3><span class="section-heading">URI Usability</span><span class="section-anchor"> <a rel="bookmark" href="#uri-usability"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>The URI could be changed in several ways due to usability concerns:</p> <ol type="1"> <li>It may be desirable to prevent the <code>amount</code> and <code>desc</code> parameters from being human readable. This is to discourage people from just looking at the URI, seeing the numbers and text, and mistakenly thinking this is already a confirmation of successful receipt (without going through the finalization process).</li> @@ -302,15 +302,15 @@ <h1>System Message: INFO/1 (zip-0324.rst line 355)</h1> </li> </ol> </section> - <section id="note-retrieval"><h3><span class="section-heading">Note retrieval</span><span class="section-anchor"> <a rel="bookmark" href="#note-retrieval"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="note-retrieval"><h3><span class="section-heading">Note retrieval</span><span class="section-anchor"> <a rel="bookmark" href="#note-retrieval"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>Ideally: a lightweight wallet can receive the funds with the assistance of a more powerful node, with minimal information leakage to that node (e.g., using simple lookups queries that can be implemented via Private Information Retrieval). The open question is how to do this given that most practical PIR are for retrieving an index out of an array, not a key from a key value standpoint.</p> </section> - <section id="other-questions"><h3><span class="section-heading">Other Questions</span><span class="section-anchor"> <a rel="bookmark" href="#other-questions"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> + <section id="other-questions"><h3><span class="section-heading">Other Questions</span><span class="section-anchor"> <a rel="bookmark" href="#other-questions"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3> <p>Should senders delay admitting a generated transaction by a random amount to prevent traffic analysis (i.e., so the messaging service operator cannot correlate messages with on-chain transactions)?</p> <p>Consider the behavior in case a chain reorgs invalidates a sent payment. Should we specify a Merkle root or block hash to help detect this reason for payment failure? Or have some servers that maintain a cache of payments that were invalidated by reorgs?</p> </section> </section> - <section id="references"><h2><span class="section-heading">References</span><span class="section-anchor"> <a rel="bookmark" href="#references"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="references"><h2><span class="section-heading">References</span><span class="section-anchor"> <a rel="bookmark" href="#references"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <table id="bcp14" class="footnote"> <tbody> <tr> @@ -376,7 +376,7 @@ <h1>System Message: INFO/1 (zip-0324.rst line 355)</h1> </tbody> </table> </section> - <section id="publication-blockers"><h2><span class="section-heading">Publication Blockers</span><span class="section-anchor"> <a rel="bookmark" href="#publication-blockers"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> + <section id="publication-blockers"><h2><span class="section-heading">Publication Blockers</span><span class="section-anchor"> <a rel="bookmark" href="#publication-blockers"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2> <ul> <li>Clean up semantics.</li> <li>Clean up rationale.</li>
zip-0340.html +438 −0
@@ -0,0 +1,438 @@ +<!DOCTYPE html> +<html> +<head> + <title>ZIP 340</title> + <meta charset="utf-8" /> + <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js?config=TeX-AMS-MML_HTMLorMML"></script> + <meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="css/style.css"> +</head> +<body> +<h1 id="coin-voting">Coin Voting</h1> +<p>This ZIP describes a mechanism for the organization of coin-weighted +election.</p> +<h2 id="use-case">Use Case</h2> +<p>A person or organization, referred as the Election Board (EB) decides +to request the opinion of the zcash holders (ZH) on a particular topic. +The EB defines the parameters of the referendum: - when it starts +(snapshot height) and stops (closing height) - An optional lockdown +period before it closes - the question asked - the criteria for +aggregating the votes</p> +<p>They publically ask the ZH to participate by sending them ballots. +They verify and tally the votes following the aggregation method +(typicall linear, but it could be quadratic or something else). Then +they publish the outcome.</p> +<p>The final result of the election is a list of valid ballots that +have: - a value in ZEC - a message</p> +<p>The content of the message depends on the type of referendum. The +acceptable options should be defined by EB. For example, for a yes/no +question, it could simply be a value of 0 or 1.</p> +<p>The EB could decide to accept write-in votes too. The format of the +message is not part of this ZIP.</p> +<p>The value of the ballot MUST be an amount of ZEC that the ZH can +spend at the snapshot height.</p> +<p>The ZH is not obligated to vote with all the ZEC that they have. But +it MUST be impossible to use the same coins to vote twice on the same +election.</p> +<p>It MUST be possible to use the same ZEC on DIFFERENT elections.</p> +<p><strong>See Privacy section on important caveats regarding concurrent +voting.</strong></p> +<h2 id="other-uses-cases">Other Uses Cases</h2> +<h3 id="airdrop">Airdrop</h3> +<p>This ZIP can be used to perform air-drops. An organization that wants +to give their tokens/coins based on an amount of ZEC can organize an +election. The ballots contain the ZH’s address where they want to +receive the airdrop.</p> +<h3 id="proof-of-balance">Proof of Balance</h3> +<p>In this case, the ZH sends an empty message because the ballot value +is all that matters.</p> +<h1 id="requirements">Requirements</h1> +<h2 id="participants-actors">Participants / Actors</h2> +<h3 id="election-board">Election Board</h3> +<p>The Election Board (EB) is the entity in charge of organizing the +election (E). - The EB MUST have a website secured by https that clearly +reflects their identity. - They MUST make their announcements through +their website. - The EB SHOULD have a forum for election related +discussions - The EB MUST set the election parameters described in a +later section - The EB MUST publish the election parameters on their +website - The election parameters are immutable. If the EB wants to make +a modification, another election MUST be created</p> +<h3 id="voter-zh">Voter (ZH)</h3> +<p>Anyone who has <em>spending authority</em> of ZEC (either transparent +or shielded) can participate.</p> +<ul> +<li>Ballots MUST have a ZEC value</li> +<li>Ballots MUST have a message in the format defined by the +Election</li> +<li>Ballots MUST include a proof of spending authority for the amount +specified, valid at the snapshot height</li> +<li>Ballots MUST not prevent the ZH from spending the coins in a +transaction</li> +<li>Coins spent before the snapshot height MUST not be eligible for +voting</li> +<li>Voting MUST not disclose information that would allow someone to use +the coins themselves (in a transaction or an election)</li> +<li>Ballots MUST follow the format specified in the section Ballot</li> +<li>ZEC held in transparent t3 addresses CANNOT be used. They introduce +most complexity and are not used much</li> +</ul> +<p>Notes: - Having coins on an exchange such as Binance, Bitfinex, etc. +does not allow you to vote because the coins are under their custody - +The EB MAY set special rules for the election. For example, there MAY be +a fee for casting a vote or a minimum ZEC requirement</p> +<h2 id="privacy">Privacy</h2> +<div class="danger"> +<p>If the coins used for voting for a given election are not moved +before voting for another election, it is possible to link the +votes.</p> +</div> +<ol type="1"> +<li>Transparent inputs are in clear</li> +<li>Shielded inputs reveal their nullifier</li> +</ol> +<p>The total value is also revealed since it is the weight of the +vote.</p> +<p>To mitigate this issue, the user SHOULD be offered to move their +coins after a vote. However, if multiple elections are carried out +concurrently with similar snapshot heights, it will be impossible for a +Voter to participate in both without linking their votes.</p> +<p>A possible solution is suggested in <a +href="https://hackmd.io/ujald5ElTMumppM7juk2WA?both">Air drops, +Proof-of-Balance, and Stake-weighted Polling</a></p> +<p>Alternatively, homomorphic encryption could be used in order to tally +the votes without decrypting them individually. However, this would be +less flexible than the above.</p> +<h2 id="workflow">Workflow</h2> +<p>The election E is carried in several sequential phases.</p> +<ol type="1"> +<li>The EB publishes the E parameters and advertise the E</li> +<li>Each V prepares his/her ballot and send it to the EB</li> +<li>The EB returns a receipt to the V</li> +<li>The E enters a lockdown period</li> +<li>The E closes and the results are published</li> +</ol> +<pre class="mermaid"><code>sequenceDiagram + EB-&gt;&gt;Public: Publish Election + Note over V,EB: When snapshot height reached + loop every Voter, concurrently + V-&gt;&gt;EB: Ballot + EB--&gt;&gt;V: Receipt + end + + Note over V,EB: When lockdown height reached + EB-&gt;&gt;Public: List of Ballot ID + Note over V,EB: When expiration height reached + loop every Voter, concurrently + V-&gt;&gt;EB: Ballot Decryption Key + end + EB-&gt;&gt;Public: Publish Decrypted Ballots, E results</code></pre> +<h2 id="ballots">Ballots</h2> +<p>The message part of a Ballot is encrypted with the V key. The +decryption key is sent to the EB after the lockdown period. The EB +validates the ballot coin value and returns a receipt. The Receipt +contains a signature from the EB.</p> +<h2 id="lockdown-period-ballot-list-commitment">Lockdown Period / Ballot +List commitment</h2> +<p>The lockdown period is optional but RECOMMENDED.</p> +<p>It gives time for the Voters to check that their ballot is recorded +by the EB publicly and that no additional ballots are added after their +opening.</p> +<p>If a V does not see their ballot on the list, they MUST contact the +EB and resolve the dispute. Their receipt has the EB signature and +proves the integrity of the ballot. Failure to recognize a valid ballot +is a serious breach of trust.</p> +<h2 id="counting">Counting</h2> +<p>After the lockdown period, V MUST send their decryption key to the +EB.</p> +<p>EB decrypts the vote and updates the tally.</p> +<p>Finally EB publishes the results for everyone to see.</p> +<p>The encrypted ballots and their decryption keys are published for +verification.</p> +<h2 id="verification">Verification</h2> +<ul> +<li>Check that the ballot hashes correspond to the ballot published</li> +<li>For each ballot,</li> +</ul> +<ol type="1"> +<li>Check the validity of the signatures and the zkps</li> +<li>Compute the coin value</li> +<li>Decrypt the vote</li> +<li>Tally the vote weighted by the coin value</li> +</ol> +<h1 id="specifications">Specifications</h1> +<p>The communication uses binary messages in protobuf format.</p> +<h2 id="eb">EB</h2> +<ul> +<li>URL: +<ul> +<li>MUST be https</li> +<li>MUST identify the organization</li> +</ul></li> +<li>Name +<ul> +<li>MUST be unique to organization</li> +</ul></li> +<li>start_height</li> +<li>snapshot height</li> +<li>lockdown height</li> +<li>closing height</li> +<li>the EB public key</li> +</ul> +<p>Example:</p> +<pre class="toml="><code>url = &quot;https://election.methyl.cc&quot; +name = &quot;Test Election 2024&quot; +start_height = 2397000 +snapshot_height = 2462430 +lockdown_height = 2460000 +closing_height = 2460000 +msg_size = 64 +public= &quot;788ff50468e2c095d97f8249e27eef3afe8a07712988a475583eb89494d64abe&quot; +cmx_root = &quot;063121a1fed23f154e18d9dfc70a13867f295207fd3c59d0e3f86615b857d332&quot; +nf_root = &quot;5341fe36634580cdf8862a106dab2cf7bd39f67d171a2877995babb435a5ee0e&quot;</code></pre> +<p>Only notes received and unspent between the start_height and the +snapshot height are eligible.</p> +<p>The start_height defaults to the Sapling activation height.</p> +<p>In addition, the EB MUST define a message in protobuf format. The +message MUST have a fixed size.</p> +<p><code>public</code> is defined in the section Message Encryption</p> +<p>Example:</p> +<div class="sourceCode" id="cb3"><pre +class="sourceCode proto"><code class="sourceCode protobuf"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">message</span> BallotContent {</span> +<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> uint8 candidate = <span class="dv">1</span>;</span> +<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div> +<p>From the E definition, the E domain is calculated as</p> +<p><code>domain = Blake2b-256(b"Zcash_WCV_domain", E)</code></p> +<p>The E domain is included in the ballot and ensures that ballots +cannot be replayed.</p> +<h2 id="ballot">Ballot</h2> +<pre class="protobuf="><code>syntax = &quot;proto3&quot;; +package proof_balance; +// Protobuf does not support fixed size arrays +// This type MUST be 32 byte-long +message b256 { + bytes b = 1; +} + +// A ballot is made of 2 parts, +// the data part is non malleable and is used to calculate the sighash +// the witness part has the signatures and the zkp +message Ballot { + BallotData data = 1; + Witness witness = 2; +} + +message Header { + uint32 version = 1; // version = 1 + b256 domain = 2; // Election Domain +} + +message BallotData { + Header header = 1; + TransparentData tdata = 2; // transparent inputs + ShieldedData zdata = 3; // sapling inputs + ShieldedData odata = 4; // orchard inputs + EncMessage enc_message = 5; // encrypted vote +} + +message EncMessage { + bytes epk = 1; + bytes data = 2; + bytes tag = 3; +} + +message Witness { + TransparentWitness twitness = 1; // transparent sigs + SaplingWitness zwitness = 2; // sapling sigs &amp; zkp + OrchardWitness owitness = 3; // orchard sigs &amp; zkp +} + +// Transparent Input, i.e UTXO +message TxIn { + b256 txid = 1; // prev txout + uint32 vout = 2; // index of the output +} + +message TransparentData { + repeated TxIn txin = 1; +} + +// See section 7.3 and 7.5 of [protocol doc] +message Spend { + b256 commitment_value = 1; + b256 nullifier = 2; + b256 rk = 3; +} + +message ShieldedData { + // b256 anchor = 1; // MUST be the anchor at snapshot height + repeated Spend spends = 2; + uint64 valuebalance = 3; +} + +message Signature { + bytes b = 1; // 64 bytes, r, s +} + +message TransparentProof { + b256 pk = 1; + Signature signature = 2; +} + +message TransparentWitness { + repeated TransparentProof proofs = 1; +} + +message SaplingSpendProof { + bytes zkproof = 1; // 192 bytes + Signature signature = 2; +} + +message SaplingWitness { + repeated SaplingSpendProof proofs = 1; + Signature binding_signature = 2; +} + +message OrchardWitness { + repeated Signature signatures = 1; + bytes zkproof = 2; // 2720 + 2272 * nOrchard + Signature binding_signature = 3; +} + +message ElectionId { + string name = 1; +} + +message ElectionInfo { + string url = 1; + string name = 2; + uint32 start_height = 3; + uint32 snapshot_height = 4; + uint32 lockdown_height = 5; + uint32 closing_height = 6; + string pk = 7; + uint32 msg_size = 8; + bytes cmx_root = 9; + bytes nf_root = 10; +} + +message ProofDomain { + bytes domain = 1; +} + +message Proof { + bytes cv = 1; + bytes nullifier = 2; + bytes rk = 3; + bytes proof = 4; +} +</code></pre> +<h3 id="ballot-hash-sighash">Ballot Hash / Sighash</h3> +<p>For the signatures, the sighash is the blake2b-256 hash of the +serialization of the ballot data (in protobuf 3) with personalization +string <code>Zcash_WCV___Hash</code>.</p> +<p><code>hash = Blake2b-256("Zcash_WCVSigHash", BallotData)</code>.</p> +<h2 id="message-encryption">Message Encryption</h2> +<p>The EB MUST sign the ballot sighash with a ed25519 signing key and +return a receipt as a bech32m encoded signature with hrp +<code>pob-receipt-</code></p> +<p>The Voter MUST add a message in the format specified by the EB. The +message is encrypted into EncMessage. - epk is a 32 byte public key on +x25519 - the Voter reveals his own ed25519 signing key after the vote +closes - the EB converts the key to a x25519 secret key - the EB uses DH +to calculate a shared key KA - SymKey = Blake2b-256(KA, +perso=“Zcash_ProofBlnce”) - SymKey is used with Chacha20-Poly1305 to +decrypt the message - The tag MUST match the decrypted tag</p> +<p>Rationale: This design allows the use of ed25519 SSH keys for both +Voter and EB.</p> +<div class="warning"> +<p>The Voter SHOULD not reuse the signing key!</p> +</div> +<h1 id="poc">POC</h1> +<p>The POC is for a modified version specific to Orchard that uses +nullifiers scoped by elections.</p> +<h2 id="pollelection-setup">Poll/Election Setup</h2> +<p>The EB (Election Board) generates an openssh ed25519 signing key</p> +<pre class="bash="><code>openssl genpkey -algorithm ed25519 -out poller.pem</code></pre> +<div class="info"> +<p>The key MAY be reused. It is used for signing ballot receipts. It is +RECOMMENDED to use a different key per election.</p> +</div> +<p>The EB chooses a event properties</p> +<pre class="toml="><code>url = &quot;https://election.methyl.cc&quot; +name = &quot;Test Election 2024&quot; +start_height = 2397000 +snapshot_height = 2462430 +lockdown_height = 2460000 +closing_height = 2460000 +msg_size = 64 +public= &quot;788ff50468e2c095d97f8249e27eef3afe8a07712988a475583eb89494d64abe&quot; +cmx_root = &quot;063121a1fed23f154e18d9dfc70a13867f295207fd3c59d0e3f86615b857d332&quot; +nf_root = &quot;5341fe36634580cdf8862a106dab2cf7bd39f67d171a2877995babb435a5ee0e&quot;</code></pre> +<p>The public key MUST match the EB signing key.</p> +<p>The <code>cmx_root</code> and <code>nf_root</code> are OPTIONAL but +if present MUST match the hashes calculated by building the reference +data.</p> +<div class="info"> +<p>If the snapshot height is not in the past, it is impossible to +calculate the tree roots.</p> +</div> +<p>The EB publishes the <code>election.toml</code> file so that voters +can download it.</p> +<h2 id="voter-send-their-ballots">Voter Send their Ballots</h2> +<p>Once the snapshot height is reached and before the lockdown height, +voters can submit their vote.</p> +<p>They have to follow the steps: - generate an openssh ed25519 key; - +download block data for the range from start height to snapshot height; +- build reference data, i.e. cmx and nf Merkle trees; - copy their +wallet file <code>zec.db</code> from Ywallet. The vote does not have to +use this wallet app as long as it has the note data: - d, pkd, - v, - +rseed, - <span class="math inline"><em>ρ</em></span>, <span +class="math inline"><em>ψ</em></span> - note position - create the proof +with a ballot message; - submit the ballot to the EB; - wait until the +election reaches the closing height.</p> +<pre><code>&gt;&gt; load-identity voter.pem +c76a89174ed64479c5f567b955ce27ce998568e72a044de80b0ebe748d826b3c +&gt;&gt; download https://lwd1.zcash-infra.com:9067 +&gt;&gt; build-reference-data +Root cmxs: 5de18172c1c9d2a526a9c73067e75dfbe1ac4e774e1bfec9a31ee178db98a635 +Root nfs: 12d4776996da7929255bccfcb21c99853d840c4008da547b113c4c857eec3d29 +&gt;&gt; create-proof pob.bin 1 &quot;Vote for BOB!&quot; +5c70068567d0b8d52e4dcfc395a67dc83fd6bdf9c65a835b41d2bfeb776480fb +cmx anchor: 5de18172c1c9d2a526a9c73067e75dfbe1ac4e774e1bfec9a31ee178db98a635 +nf anchor: 12d4776996da7929255bccfcb21c99853d840c4008da547b113c4c857eec3d29</code></pre> +<h2 id="eb-collects-votes">EB Collects Votes</h2> +<p>The EB collects votes and verifies the validity of the ZKP, spending +signatures and binding signature. It also checks that the root hashes +match and that the nullifiers are not used.</p> +<p>If everything is fine, the EB returns a receipt that is a signature +on the sighash of the ballot.</p> +<pre><code>&gt;&gt; load-identity poller.pem +3f8a41af400aa0197594a7b5c2e21bb6307753840a8513b28b816aad43fb30c0 +&gt;&gt; init-db +&gt;&gt; verify-proof pob.bin +ZK Proof verified! +Spending Signature verified! +Binding Signature verified! +Verified 0.05000000 ZEC +Receipt: pob-receipt-1djsvezm3wep2ganwd4upzawxsgz60hq2e86cqkv4djmusut4fjzzvzu2ut5z3uda4eedvff6anlmzz3k48d7ugxsrs0gxfn36nscvqqzn4js8</code></pre> +<p>At this point, the ballot is verified and its amount can be accounted +for but the vote payload is not revealed.</p> +<div class="info"> +<p>The EB publishes the ballot hashes and receipts on their website.</p> +</div> +<h2 id="opening-votes">Opening Votes</h2> +<p>Voters uploads their signing key to the EB.</p> +<pre><code>&gt;&gt; load-identity voter.pem +c76a89174ed64479c5f567b955ce27ce998568e72a044de80b0ebe748d826b3c +&gt;&gt; open-proof pob.bin +5c70068567d0b8d52e4dcfc395a67dc83fd6bdf9c65a835b41d2bfeb776480fb +Decrypted message: Vote for BOB!</code></pre> +<div class="info"> +<p>The EB counts the votes and publishes the results</p> +</div> +<h2 id="audit">Audit</h2> +<div class="info"> +<p>The EB publishes all ballots and their opening keys for verification +by auditors.</p> +</div> +</body> +</html>
zip-0340.md +537 −0
@@ -0,0 +1,537 @@ +--- +title: Coin Voting +breaks: false +tags: coin_voting +--- + +# Coin Voting + +This ZIP describes a mechanism for the organization of +coin-weighted election. + +## Use Case + +A person or organization, referred as the Election Board (EB) +decides to request the opinion of the zcash holders (ZH) +on a particular topic. The EB defines the parameters of the +referendum: +- when it starts (snapshot height) and stops (closing height) +- An optional lockdown period before it closes +- the question asked +- the criteria for aggregating the votes + +They publically ask the ZH to participate by sending them ballots. +They verify and tally the votes following the aggregation method (typicall linear, but it could be quadratic or something else). Then they publish the outcome. + +The final result of the election is a list of valid ballots that have: +- a value in ZEC +- a message + +The content of the message depends on the type of referendum. +The acceptable options should be defined by EB. For example, for a +yes/no question, it could simply be a value of 0 or 1. + +The EB could decide to accept write-in votes too. The format of the +message is not part of this ZIP. + +The value of the ballot MUST be an amount of ZEC that the ZH +can spend at the snapshot height. + +The ZH is not obligated to vote with all the ZEC that they have. +But it MUST be impossible to use the same coins to vote +twice on the same election. + +It MUST be possible to use the same ZEC on DIFFERENT elections. + +**See Privacy section on important caveats regarding concurrent +voting.** + +## Other Uses Cases + +### Airdrop +This ZIP can be used to perform air-drops. An organization +that wants to give their tokens/coins based on an amount +of ZEC can organize an election. The ballots contain +the ZH's address where they want to receive the airdrop. + +### Proof of Balance +In this case, the ZH sends an empty message because the +ballot value is all that matters. + +# Requirements + +## Participants / Actors + +### Election Board + +The Election Board (EB) is the entity in charge of organizing +the election (E). +- The EB MUST have a website secured by https that clearly +reflects their identity. +- They MUST make their announcements +through their website. +- The EB SHOULD have a forum for election related discussions +- The EB MUST set the election parameters described in a later +section +- The EB MUST publish the election parameters on their website +- The election parameters are immutable. If the EB +wants to make a modification, another election MUST be created + +### Voter (ZH) + +Anyone who has *spending authority* of ZEC +(either transparent or shielded) can +participate. + +- Ballots MUST have a ZEC value +- Ballots MUST have a message in the format defined by the Election +- Ballots MUST include a proof of spending authority for the +amount specified, valid at the snapshot height +- Ballots MUST not prevent the ZH from spending the coins in a transaction +- Coins spent before the snapshot height MUST not be eligible for voting +- Voting MUST not disclose information that would allow someone +to use the coins themselves (in a transaction or an election) +- Ballots MUST follow the format specified in the section Ballot +- ZEC held in transparent t3 addresses CANNOT be used. They introduce +most complexity and are not used much + +Notes: +- Having coins on an exchange such as Binance, Bitfinex, etc. +does not allow you to vote because the coins are under their custody +- The EB MAY set special rules for the election. For example, +there MAY be a fee for casting a vote or a minimum ZEC requirement + +## Privacy +:::danger +If the coins used for voting for a given election are not moved +before voting for another election, it is possible to link +the votes. +::: + +1. Transparent inputs are in clear +1. Shielded inputs reveal their nullifier + +The total value is also revealed since it is the weight +of the vote. + +To mitigate this issue, the user SHOULD be offered to move +their coins after a vote. However, if multiple elections +are carried out concurrently with similar snapshot +heights, it will be impossible for a Voter to participate +in both without linking their votes. + +A possible solution is suggested in +[Air drops, Proof-of-Balance, and Stake-weighted Polling](https://hackmd.io/ujald5ElTMumppM7juk2WA?both) + +Alternatively, homomorphic encryption could be used in +order to tally the votes without decrypting them individually. +However, this would be less flexible than the above. + +## Workflow + +The election E is carried in several sequential phases. + +1. The EB publishes the E parameters and advertise the E +1. Each V prepares his/her ballot and send it to the EB +1. The EB returns a receipt to the V +1. The E enters a lockdown period +1. The E closes and the results are published + +```mermaid +sequenceDiagram + EB->>Public: Publish Election + Note over V,EB: When snapshot height reached + loop every Voter, concurrently + V->>EB: Ballot + EB-->>V: Receipt + end + + Note over V,EB: When lockdown height reached + EB->>Public: List of Ballot ID + Note over V,EB: When expiration height reached + loop every Voter, concurrently + V->>EB: Ballot Decryption Key + end + EB->>Public: Publish Decrypted Ballots, E results +``` + +## Ballots + +The message part of a Ballot is encrypted with the V key. +The decryption key is sent to the EB after the lockdown period. +The EB validates the ballot coin value and returns a receipt. +The Receipt contains a signature from the EB. + +## Lockdown Period / Ballot List commitment +The lockdown period is optional but RECOMMENDED. + +It gives time for the Voters to check that their ballot is +recorded by the EB publicly and that no additional ballots are +added after their opening. + +If a V does not see their ballot on the list, they MUST +contact the EB and resolve the dispute. Their receipt +has the EB signature and proves the integrity of the ballot. +Failure to recognize a valid ballot is a serious breach +of trust. + +## Counting + +After the lockdown period, V MUST send their +decryption key to the EB. + +EB decrypts the vote and updates the tally. + +Finally EB publishes the results for everyone to see. + +The encrypted ballots and their decryption keys are published +for verification. + +## Verification + +- Check that the ballot hashes correspond to the ballot published +- For each ballot, +1. Check the validity of the signatures and the zkps +1. Compute the coin value +1. Decrypt the vote +1. Tally the vote weighted by the coin value + +# Specifications + +The communication uses binary messages in protobuf format. + +## EB + +- URL: + - MUST be https + - MUST identify the organization +- Name + - MUST be unique to organization +- start_height +- snapshot height +- lockdown height +- closing height +- the EB public key + +Example: +```toml= +url = "https://election.methyl.cc" +name = "Test Election 2024" +start_height = 2397000 +snapshot_height = 2462430 +lockdown_height = 2460000 +closing_height = 2460000 +msg_size = 64 +public= "788ff50468e2c095d97f8249e27eef3afe8a07712988a475583eb89494d64abe" +cmx_root = "063121a1fed23f154e18d9dfc70a13867f295207fd3c59d0e3f86615b857d332" +nf_root = "5341fe36634580cdf8862a106dab2cf7bd39f67d171a2877995babb435a5ee0e" +``` + +Only notes received and unspent between the start_height and the snapshot height +are eligible. + +The start_height defaults to the Sapling activation height. + +In addition, the EB MUST define a message in protobuf format. +The message MUST have a fixed size. + +`public` is defined in the section Message Encryption + +Example: +```proto +message BallotContent { + uint8 candidate = 1; +} +``` + +From the E definition, the E domain is calculated as + +`domain = Blake2b-256(b"Zcash_WCV_domain", E)` + +The E domain is included in the ballot and ensures that +ballots cannot be replayed. + +## Ballot + +```protobuf= +syntax = "proto3"; +package proof_balance; +// Protobuf does not support fixed size arrays +// This type MUST be 32 byte-long +message b256 { + bytes b = 1; +} + +// A ballot is made of 2 parts, +// the data part is non malleable and is used to calculate the sighash +// the witness part has the signatures and the zkp +message Ballot { + BallotData data = 1; + Witness witness = 2; +} + +message Header { + uint32 version = 1; // version = 1 + b256 domain = 2; // Election Domain +} + +message BallotData { + Header header = 1; + TransparentData tdata = 2; // transparent inputs + ShieldedData zdata = 3; // sapling inputs + ShieldedData odata = 4; // orchard inputs + EncMessage enc_message = 5; // encrypted vote +} + +message EncMessage { + bytes epk = 1; + bytes data = 2; + bytes tag = 3; +} + +message Witness { + TransparentWitness twitness = 1; // transparent sigs + SaplingWitness zwitness = 2; // sapling sigs & zkp + OrchardWitness owitness = 3; // orchard sigs & zkp +} + +// Transparent Input, i.e UTXO +message TxIn { + b256 txid = 1; // prev txout + uint32 vout = 2; // index of the output +} + +message TransparentData { + repeated TxIn txin = 1; +} + +// See section 7.3 and 7.5 of [protocol doc] +message Spend { + b256 commitment_value = 1; + b256 nullifier = 2; + b256 rk = 3; +} + +message ShieldedData { + // b256 anchor = 1; // MUST be the anchor at snapshot height + repeated Spend spends = 2; + uint64 valuebalance = 3; +} + +message Signature { + bytes b = 1; // 64 bytes, r, s +} + +message TransparentProof { + b256 pk = 1; + Signature signature = 2; +} + +message TransparentWitness { + repeated TransparentProof proofs = 1; +} + +message SaplingSpendProof { + bytes zkproof = 1; // 192 bytes + Signature signature = 2; +} + +message SaplingWitness { + repeated SaplingSpendProof proofs = 1; + Signature binding_signature = 2; +} + +message OrchardWitness { + repeated Signature signatures = 1; + bytes zkproof = 2; // 2720 + 2272 * nOrchard + Signature binding_signature = 3; +} + +message ElectionId { + string name = 1; +} + +message ElectionInfo { + string url = 1; + string name = 2; + uint32 start_height = 3; + uint32 snapshot_height = 4; + uint32 lockdown_height = 5; + uint32 closing_height = 6; + string pk = 7; + uint32 msg_size = 8; + bytes cmx_root = 9; + bytes nf_root = 10; +} + +message ProofDomain { + bytes domain = 1; +} + +message Proof { + bytes cv = 1; + bytes nullifier = 2; + bytes rk = 3; + bytes proof = 4; +} + +``` + +### Ballot Hash / Sighash + +For the signatures, the sighash is the blake2b-256 +hash of the serialization of the ballot data (in protobuf 3) +with personalization string `Zcash_WCV___Hash`. + +`hash = Blake2b-256("Zcash_WCVSigHash", BallotData)`. + +## Message Encryption + +The EB MUST sign the ballot sighash with a ed25519 signing key and return +a receipt as a bech32m encoded signature with hrp `pob-receipt-` + +The Voter MUST add a message in the format specified by the EB. +The message is encrypted into EncMessage. +- epk is a 32 byte public key on x25519 +- the Voter reveals his own ed25519 signing key after the vote closes +- the EB converts the key to a x25519 secret key +- the EB uses DH to calculate a shared key KA +- SymKey = Blake2b-256(KA, perso="Zcash_ProofBlnce") +- SymKey is used with Chacha20-Poly1305 to decrypt the message +- The tag MUST match the decrypted tag + +Rationale: This design allows the use of ed25519 SSH keys for both Voter and EB. + +:::warning +The Voter SHOULD not reuse the signing key! +::: + + +# POC + +The POC is for a modified version specific to Orchard that uses +nullifiers scoped by elections. + +## Poll/Election Setup + +The EB (Election Board) generates an openssh ed25519 signing key + +```bash= +openssl genpkey -algorithm ed25519 -out poller.pem +``` + +:::info +The key MAY be reused. It is used for signing ballot receipts. +It is RECOMMENDED to use a different key per election. +::: + +The EB chooses a event properties + +```toml= +url = "https://election.methyl.cc" +name = "Test Election 2024" +start_height = 2397000 +snapshot_height = 2462430 +lockdown_height = 2460000 +closing_height = 2460000 +msg_size = 64 +public= "788ff50468e2c095d97f8249e27eef3afe8a07712988a475583eb89494d64abe" +cmx_root = "063121a1fed23f154e18d9dfc70a13867f295207fd3c59d0e3f86615b857d332" +nf_root = "5341fe36634580cdf8862a106dab2cf7bd39f67d171a2877995babb435a5ee0e" +``` + +The public key MUST match the EB signing key. + +The `cmx_root` and `nf_root` are OPTIONAL but if present +MUST match the hashes calculated by building the reference data. + +:::info +If the snapshot height is not in the past, it is impossible +to calculate the tree roots. +::: + +The EB publishes the `election.toml` file so that voters can download it. + +## Voter Send their Ballots + +Once the snapshot height is reached and before the lockdown height, +voters can submit their vote. + +They have to follow the steps: +- generate an openssh ed25519 key; +- download block data for the range from start height to snapshot height; +- build reference data, i.e. cmx and nf Merkle trees; +- copy their wallet file `zec.db` from Ywallet. The vote does not +have to use this wallet app as long as it has the note data: + - d, pkd, + - v, + - rseed, + - $\rho$, $\psi$ + - note position +- create the proof with a ballot message; +- submit the ballot to the EB; +- wait until the election reaches the closing height. + +``` +>> load-identity voter.pem +c76a89174ed64479c5f567b955ce27ce998568e72a044de80b0ebe748d826b3c +>> download https://lwd1.zcash-infra.com:9067 +>> build-reference-data +Root cmxs: 5de18172c1c9d2a526a9c73067e75dfbe1ac4e774e1bfec9a31ee178db98a635 +Root nfs: 12d4776996da7929255bccfcb21c99853d840c4008da547b113c4c857eec3d29 +>> create-proof pob.bin 1 "Vote for BOB!" +5c70068567d0b8d52e4dcfc395a67dc83fd6bdf9c65a835b41d2bfeb776480fb +cmx anchor: 5de18172c1c9d2a526a9c73067e75dfbe1ac4e774e1bfec9a31ee178db98a635 +nf anchor: 12d4776996da7929255bccfcb21c99853d840c4008da547b113c4c857eec3d29 +``` + +## EB Collects Votes + +The EB collects votes and verifies the validity of the ZKP, spending +signatures and binding signature. It also checks that the root hashes +match and that the nullifiers are not used. + +If everything is fine, the EB returns a receipt that is a +signature on the sighash of the ballot. + +``` +>> load-identity poller.pem +3f8a41af400aa0197594a7b5c2e21bb6307753840a8513b28b816aad43fb30c0 +>> init-db +>> verify-proof pob.bin +ZK Proof verified! +Spending Signature verified! +Binding Signature verified! +Verified 0.05000000 ZEC +Receipt: pob-receipt-1djsvezm3wep2ganwd4upzawxsgz60hq2e86cqkv4djmusut4fjzzvzu2ut5z3uda4eedvff6anlmzz3k48d7ugxsrs0gxfn36nscvqqzn4js8 +``` + +At this point, the ballot is verified and its amount can be accounted +for but the vote payload is not revealed. + +:::info +The EB publishes the ballot hashes and receipts on their website. +::: + +## Opening Votes + +Voters uploads their signing key to the EB. + +``` +>> load-identity voter.pem +c76a89174ed64479c5f567b955ce27ce998568e72a044de80b0ebe748d826b3c +>> open-proof pob.bin +5c70068567d0b8d52e4dcfc395a67dc83fd6bdf9c65a835b41d2bfeb776480fb +Decrypted message: Vote for BOB! +``` + +:::info +The EB counts the votes and publishes the results +::: + +## Audit + +:::info +The EB publishes all ballots and their opening keys for verification +by auditors. +:::