# DAVINCI contracts

Solidity contracts of the [DAVINCI](https://davinci.vote) voting protocol. Organizers create
voting processes in the `ProcessRegistry`, and sequencers settle each batch of votes and the
final tally on it with zero-knowledge proofs.

[![test](https://github.com/vocdoni/davinci-contracts/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/vocdoni/davinci-contracts/actions/workflows/test.yml)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)

In production beta on OP Mainnet on development trusted setups. The protocol is
described in the [whitepaper](https://whitepaper.vocdoni.io).

## Overview

An organizer registers a process with its census, ballot mode, timing, metadata and the public
key ballots are encrypted to. Voters send encrypted ballots to a sequencer
([davinci-sequencer](https://github.com/vocdoni/davinci-sequencer)), which groups them into
batches and proves each state transition with
[davinci-zkvm](https://github.com/vocdoni/davinci-zkvm) as a ZisK PLONK. The sequencer settles it
with `submitStateTransition` in a blob transaction: the EIP-4844 blobs publish the new state,
and the registry checks the proof, the chain of state roots, the census root and that the blobs
are the ones the proof covers. Settlement is permissionless, so any sequencer can settle any
process.

Voting ends at `startTime + duration`. Batches still in flight keep settling during a short
grace window, and once it closes the tally is published over the final state root. With a
sequencer key it comes with a second PLONK from the zkVM results guest (`setProcessResults`).
With a key from a [davinci-dkg](https://github.com/vocdoni/davinci-dkg) committee (`DKG_AUTOMATIC` or `DKG_LOCKED` key mode), the committee threshold-decrypts it (`requestResultsDecryption`, then `finalizeResultsFromDKG`). With a `COUNCIL` key mode, an invite-only Council ceremony from [davinci-dkg-council](https://github.com/vocdoni/davinci-dkg-council) holds the key; the ceremony's organizer opens decryption, unlocking every process bound to it at once.

| Contract | Role |
|---|---|
| [`ProcessRegistry`](src/ProcessRegistry.sol) | Processes and their lifecycle, transition settlement, results. |
| [`ZiskVerifier`](src/verifiers/ZiskVerifier.sol) | ZisK PLONK verifier, vendored from the ZisK snark setup. |
| [`DavinciDKGAdapter`](src/DavinciDKGAdapter.sol) | The registry's link to davinci-dkg (`DKG_AUTOMATIC` / `DKG_LOCKED` key modes), created by the registry when a DKG manager is configured. |
| [`CouncilAdapter`](src/CouncilAdapter.sol) | The registry's link to davinci-dkg-council (`COUNCIL` key mode), created by the registry when a Council manager is configured. |
| [`src/libraries/`](src/libraries) | Genesis root, SHA-256 sparse Merkle tree, public values, blobs, process ids, BabyJubJub forms. |
| [`src/interfaces/`](src/interfaces) | `IProcessRegistry`, `IZiskVerifier`, `ICensusValidator` (on-chain censuses), `src/interfaces/dkg/` (the davinci-dkg subset the DKG adapter calls) and `src/interfaces/council/` (the Council manager subset the Council adapter calls). |

## Deployments

### OP Mainnet, registry of 2026-10-23 (pre-production)

OP Mainnet (chain id 10), deployed and verified on 2026-10-23 by the dedicated deployer
`0x5eb38f2D16CEaabFF6a63C17505a14b45624f537` at block 158592889 (transaction
`0x95ad9863f1078ddf81995e2f5a4b29584033307c5e252567db5201571ffe0fa9`), in L1-blob mode, on the
davinci-zkvm v0.5.0 pins, copied with the verifier and the grace settings from the 2026-10-21 registry
(`PINS_FROM_REGISTRY`), with a new davinci-dkg suite. [`deployments/10.json`](deployments/10.json) holds the
verified record; `verify_deployment.py` passed 32 checks with 0 failures, and the sources are verified on
Optimistic Etherscan. The ballot key is the pre-production phase-2 ceremony of davinci-circom
v1.3.0. Process ids start with `e1b56c76`.

| Contract | Address |
|---|---|
| `ProcessRegistry` | [`0xc916F985CbCdbEb25A0EE6950361cf7Dd9Fbe35a`](https://optimistic.etherscan.io/address/0xc916F985CbCdbEb25A0EE6950361cf7Dd9Fbe35a#code) |
| `DavinciDKGAdapter` | [`0xdb2C3653d59e9693ea3186AE4d4A34b3379A68f7`](https://optimistic.etherscan.io/address/0xdb2C3653d59e9693ea3186AE4d4A34b3379A68f7#code) |
| davinci-dkg `DKGManager` | [`0x401381a9711b473baf8757404b5514537a5216d7`](https://optimistic.etherscan.io/address/0x401381a9711b473baf8757404b5514537a5216d7#code) |
| `CouncilAdapter` | [`0x798dD4fE9DE224ffD7bF1081FD8D0C273a6e8860`](https://optimistic.etherscan.io/address/0x798dD4fE9DE224ffD7bF1081FD8D0C273a6e8860#code) |
| Council manager | [`0x281b84dee6305083cc719187e4a2737d61b4396e`](https://optimistic.etherscan.io/address/0x281b84dee6305083cc719187e4a2737d61b4396e#code) |
| `L1BlobVerifier` | [`0x3B95BC14F43ed8Addb83F84D10A949De74eE7529`](https://optimistic.etherscan.io/address/0x3B95BC14F43ed8Addb83F84D10A949De74eE7529#code) (reads `L1Block` `0x4200000000000000000000000000000000000015`; reused) |
| `ZiskVerifier` | [`0x35Ad4cBc4C77a2Bc69B07e68f2535Da5C6d07AB7`](https://optimistic.etherscan.io/address/0x35Ad4cBc4C77a2Bc69B07e68f2535Da5C6d07AB7#code) (reused); runtime code hash `0xadab570d3e3a4c172d0c75e5aef5d06098b94d70a9c8ff76af239a90fdcadcc1` |

| Immutable | Value |
|---|---|
| `batchProgramVK` | `0x4b1a527e284af96fa0c3543e9e9b18746a6494edd99c309e58d96a804e3041dc` |
| `resultsProgramVK` | `0xce964acdd53329fc49ede57f5ea288f044950e136be119287fd0021390689dc4` |
| `rootCVadcopFinal` | `0x6b2490fba336fb00f0c8719a961de309a8db6f43a9bfb7575ca5f014d609b265` |
| `ballotVKHash` | `0x67e8e6b47ea32cf144d6e72886f02b95ed068b157f9d4ccc8e97f335858e4963` |
| `defaultGrace` / `graceFloor` / `graceCeil` | 300 / 240 / 600 s |
| `graceMaxTotal` | 1800 s |
| `noticeMin` | 60 s |
| DA mode | L1 blobs |

### OP Mainnet, protocol v5.1 registry of 2026-10-21 (retired)

OP Mainnet (chain id 10), deployed and verified on 2026-10-21 by the dedicated deployer
`0x5eb38f2D16CEaabFF6a63C17505a14b45624f537` at block 158487281 (transaction
`0xb1f224f680c4c9b0940dc60eb93b5f487e806b4cf3799c4b6ef8cf3c49b235bb`), in L1-blob mode, on the
davinci-zkvm v0.5.0 pins. [`deployments/10-0x02d6c284234b4ce75fab3085cf3f1ba4b7262b97.json`](deployments/10-0x02d6c284234b4ce75fab3085cf3f1ba4b7262b97.json) holds the verified record;
`verify_deployment.py` passed 27 checks with 0 failures, and the sources are verified on
Optimistic Etherscan. The ballot key is the pre-production phase-2 ceremony of davinci-circom
v1.3.0. Process ids start with `e8d4e286`.

| Contract | Address |
|---|---|
| `ProcessRegistry` | [`0x02D6c284234B4CE75faB3085cF3f1ba4b7262B97`](https://optimistic.etherscan.io/address/0x02D6c284234B4CE75faB3085cF3f1ba4b7262B97#code) |
| `DavinciDKGAdapter` | [`0xffAC853E7B93CE6148b1A551A40aFd88DE517863`](https://optimistic.etherscan.io/address/0xffAC853E7B93CE6148b1A551A40aFd88DE517863#code) |
| davinci-dkg `DKGManager` | [`0x9e799a1d22710056e62c849e3ffe19dd01db2d41`](https://optimistic.etherscan.io/address/0x9e799a1d22710056e62c849e3ffe19dd01db2d41#code) |
| `CouncilAdapter` | [`0xe07BE522a8fE9d1cf85DCA5Eefbe663055D35127`](https://optimistic.etherscan.io/address/0xe07BE522a8fE9d1cf85DCA5Eefbe663055D35127#code) |
| Council manager | [`0x281b84dee6305083cc719187e4a2737d61b4396e`](https://optimistic.etherscan.io/address/0x281b84dee6305083cc719187e4a2737d61b4396e#code) |
| `L1BlobVerifier` | [`0x3B95BC14F43ed8Addb83F84D10A949De74eE7529`](https://optimistic.etherscan.io/address/0x3B95BC14F43ed8Addb83F84D10A949De74eE7529#code) (reads `L1Block` `0x4200000000000000000000000000000000000015`; reused) |
| `ZiskVerifier` | [`0x35Ad4cBc4C77a2Bc69B07e68f2535Da5C6d07AB7`](https://optimistic.etherscan.io/address/0x35Ad4cBc4C77a2Bc69B07e68f2535Da5C6d07AB7#code) (reused); runtime code hash `0xadab570d3e3a4c172d0c75e5aef5d06098b94d70a9c8ff76af239a90fdcadcc1` |

| Immutable | Value |
|---|---|
| `batchProgramVK` | `0x4b1a527e284af96fa0c3543e9e9b18746a6494edd99c309e58d96a804e3041dc` |
| `resultsProgramVK` | `0xce964acdd53329fc49ede57f5ea288f044950e136be119287fd0021390689dc4` |
| `rootCVadcopFinal` | `0x6b2490fba336fb00f0c8719a961de309a8db6f43a9bfb7575ca5f014d609b265` |
| `ballotVKHash` | `0x67e8e6b47ea32cf144d6e72886f02b95ed068b157f9d4ccc8e97f335858e4963` |
| `defaultGrace` / `graceFloor` / `graceCeil` | 300 / 240 / 600 s |
| `graceMaxTotal` | 1800 s |
| `noticeMin` | 60 s |
| DA mode | L1 blobs |

### OP Mainnet, protocol v5 registry (retired)

OP Mainnet (chain id 10), deployed and verified on 2026-10-19 by the dedicated deployer
`0x5eb38f2D16CEaabFF6a63C17505a14b45624f537` at block 158414417 (transaction
`0xdc71c0e5f98c9aa5c0b29059727c4e2e55c481a4e41c4df125c3bde5233132f3`), in L1-blob mode, on the
davinci-zkvm v0.4.1 pins. [`deployments/10-0x6f500a3e3a161ecb3c19a034bfb6a6ac3b71abe6.json`](deployments/10-0x6f500a3e3a161ecb3c19a034bfb6a6ac3b71abe6.json) holds the verified record;
`verify_deployment.py` passed 27 checks with 0 failures, and the sources are verified on
Optimistic Etherscan. The ballot key is the pre-production phase-2 ceremony (davinci-circom
v1.2.0). Process ids start with `3c3e0777`.

| Contract | Address |
|---|---|
| `ProcessRegistry` | [`0x6F500A3e3A161EcB3C19A034bFB6a6Ac3b71abE6`](https://optimistic.etherscan.io/address/0x6F500A3e3A161EcB3C19A034bFB6a6Ac3b71abE6#code) |
| `DavinciDKGAdapter` | [`0x51aB0BB6A455e7f027f3b09b8F1Ea0634806f390`](https://optimistic.etherscan.io/address/0x51aB0BB6A455e7f027f3b09b8F1Ea0634806f390#code) |
| davinci-dkg `DKGManager` | [`0x9e799a1d22710056e62c849e3ffe19dd01db2d41`](https://optimistic.etherscan.io/address/0x9e799a1d22710056e62c849e3ffe19dd01db2d41#code) |
| `CouncilAdapter` | [`0xC2f51d01E16b61d75eAD2e5b88d139739067af17`](https://optimistic.etherscan.io/address/0xC2f51d01E16b61d75eAD2e5b88d139739067af17#code) |
| Council manager | [`0x281b84dee6305083cc719187e4a2737d61b4396e`](https://optimistic.etherscan.io/address/0x281b84dee6305083cc719187e4a2737d61b4396e#code) |
| `L1BlobVerifier` | [`0x3B95BC14F43ed8Addb83F84D10A949De74eE7529`](https://optimistic.etherscan.io/address/0x3B95BC14F43ed8Addb83F84D10A949De74eE7529#code) (reads `L1Block` `0x4200000000000000000000000000000000000015`; reused) |
| `ZiskVerifier` | [`0x35Ad4cBc4C77a2Bc69B07e68f2535Da5C6d07AB7`](https://optimistic.etherscan.io/address/0x35Ad4cBc4C77a2Bc69B07e68f2535Da5C6d07AB7#code) (reused); runtime code hash `0xadab570d3e3a4c172d0c75e5aef5d06098b94d70a9c8ff76af239a90fdcadcc1` |

| Immutable | Value |
|---|---|
| `batchProgramVK` | `0x1e4a74a1c6fb1cd1874d80895e1e075930837955efb4a135539016f7cdead2a8` |
| `resultsProgramVK` | `0xde55d751582e510bf378d4eec0d98ee3fa5817a50b77bc0e5ce560035e29e4e9` |
| `rootCVadcopFinal` | `0x6b2490fba336fb00f0c8719a961de309a8db6f43a9bfb7575ca5f014d609b265` |
| `ballotVKHash` | `0x7caffddcd7ea38439cbb45789b810d8eafceca65cff93dbeaae409b2bf64e219` |
| `defaultGrace` / `graceFloor` / `graceCeil` | 300 / 240 / 600 s |
| `graceMaxTotal` | 1800 s |
| `noticeMin` | 60 s |
| DA mode | L1 blobs |

### OP Mainnet, registry with the DKG and Council adapters (retired)

OP Mainnet (chain id 10), deployed 2026-10-15 by the dedicated deployer
`0x5eb38f2D16CEaabFF6a63C17505a14b45624f537` from commit `338ac77` at block 158245426, in L1-blob
mode. Retired on 2026-10-19 by the protocol v5 registry above; its record is
[`deployments/10-0x64d4.json`](deployments/10-0x64d4.json). `verify_deployment.py` passed 32
checks. Source verification on Optimistic Etherscan is pending. It reuses the
`ZiskVerifier`, the `L1BlobVerifier`, the 4 pins and the grace settings of the previous OP
registry below.

| Contract | Address |
|---|---|
| `ProcessRegistry` | `0x64d41aD49009204E8dAcc153Fc98a5Ee14cB6916` |
| `DavinciDKGAdapter` | `0x0c1E7120FaBf95fDe294839A78780334d27cfCff` |
| davinci-dkg `DKGManager` | `0x9e799a1d22710056e62c849e3ffe19dd01db2d41` (block 158245366) |
| davinci-dkg `DKGAppManager` | `0x1e7f0bec007828e2e0a1a469d9d3e148888fc39a` |
| `CouncilAdapter` | `0xa5A1e4B204976709EB545Af0189211c41e20193d` |
| Council manager | `0x281b84dee6305083cc719187e4a2737d61b4396e` (davinci-dkg-council, development trusted setup, `circuits-v1`, block 158245395) |
| `L1BlobVerifier` | `0x3B95BC14F43ed8Addb83F84D10A949De74eE7529` (reads `L1Block` `0x4200000000000000000000000000000000000015`; reused) |
| `ZiskVerifier` | `0x35Ad4cBc4C77a2Bc69B07e68f2535Da5C6d07AB7` (reused) |

The pins and grace settings are those of the table in the next section (grace 300 / 240 / 600 /
1800 / 60 s). The Council manager runs on a development trusted setup: whoever holds that setup's
toxic waste can forge dealings, so treat COUNCIL processes as a beta.

### OP Mainnet, ZisK 1.3.2 registry (retired)

OP Mainnet (chain id 10), on the davinci-zkvm ZisK 1.3.2-alpha pins. Deployed 2026-10-13 from
commit `fd79251` at block 158164175. Retired on 2026-10-15: it has no DKG or Council adapter and
sequencers use a newer registry; its record is
[`deployments/10-0x7bfa.json`](deployments/10-0x7bfa.json). It has its own `ZiskVerifier` (the 1.3.0 verifier hard-codes the old `rootCVadcopFinal`).
`L1BlobVerifier` is reused.

| Contract | Address |
|---|---|
| `ProcessRegistry` | `0x7bfa68879f118C98B864FB52d2aD3a112eF1558F` |
| `L1BlobVerifier` | `0x3B95BC14F43ed8Addb83F84D10A949De74eE7529` (reads `L1Block` `0x4200000000000000000000000000000000000015`; reused) |
| `ZiskVerifier` | `0x35Ad4cBc4C77a2Bc69B07e68f2535Da5C6d07AB7`; runtime code hash `0xadab570d3e3a4c172d0c75e5aef5d06098b94d70a9c8ff76af239a90fdcadcc1` |

| Immutable | Value |
|---|---|
| `batchProgramVK` | `0xe39e460085ecddecf365649a61183a71c0fe778aa9c06fd2aa1a6c43cddb988b` |
| `resultsProgramVK` | `0x394694558f39d0b2da0bbb09322333a0f567ee8d16bea2f354543a086587d167` |
| `rootCVadcopFinal` | `0x6b2490fba336fb00f0c8719a961de309a8db6f43a9bfb7575ca5f014d609b265` |
| `ballotVKHash` | `0xbf1e6590bb1ba883d601c4d7d1c6fa2722a78590716874019db6d68fc776bb0e` |
| `defaultGrace` / `graceFloor` / `graceCeil` | 300 / 240 / 600 s |
| `graceMaxTotal` | 1800 s |
| `noticeMin` | 60 s |

No DKG or Council adapter.

### OP Mainnet, L1-blob mode (v0.2.0 registry, retired)

OP Mainnet (chain id 10), deployed 2026-10-13 from commit `44fdca1` at block 158155408, on the
davinci-zkvm v0.2.0 program vks. The registry settles transitions on OP while their blobs live in
Ethereum blob transactions, checked by its `L1BlobVerifier` against OP's `L1Block` predeploy
([settlement.md](docs/settlement.md#l1-blob-mode)). [`deployments/10-0xC5f8.json`](deployments/10-0xC5f8.json)
holds the verified record. Not source-verified on an explorer yet. It is retired: it
stays on the v0.2.0 vks and ZisK 1.3.0, and sequencers use the registry with the adapters above.

| Contract | Address |
|---|---|
| `ProcessRegistry` | `0xC5f88160a1Df51A3Ee56b970b12B8308799c05A7` |
| `L1BlobVerifier` | `0x3B95BC14F43ed8Addb83F84D10A949De74eE7529` (reads `L1Block` `0x4200000000000000000000000000000000000015`; reused) |
| `ZiskVerifier` | `0x6781FFF50D615CB3F331CCD3Bdad3416d4ce0d5c` (reused; same code hash as Gnosis') |

| Immutable | Value |
|---|---|
| `batchProgramVK` | `0xa0ad5c4c7e39d4a7007933158181418a752e6c1563a211af84c579640db435fa` |
| `resultsProgramVK` | `0xe693589453ecaee63eba697c48d4c5321a714bb18c2d84a97437b3f368578f68` |
| `rootCVadcopFinal` | `0x05006517b6ccde5da4d890587ba62845b5af8a307c00e87d4b9d05099b16dc80` |
| `ballotVKHash` | `0xbf1e6590bb1ba883d601c4d7d1c6fa2722a78590716874019db6d68fc776bb0e` |
| `defaultGrace` / `graceFloor` / `graceCeil` | 300 / 240 / 600 s |
| `graceMaxTotal` | 1800 s |
| `noticeMin` | 60 s |

No DKG or Council adapter.

### OP Mainnet, first registry

`ProcessRegistry` `0x8b63fAE96948D69CF92Eb40e4EE0fCE40962267d` (block 158125136), deployed
2026-10-12 from commit `e7de916` with the same verifiers, the Gnosis pins below and grace 180 /
150 / 600 / 1800 / 60 s. Retired: its v0.1 vks and 150 s floor; its record is
[`deployments/10-0x8b63.json`](deployments/10-0x8b63.json).

### Gnosis Chain production beta

Gnosis Chain (chain id 100), deployed 2026-10-07 from commit `4e4f6c8` at block 48,633,301.
Gnosis Chain is retired (2026-10-13): sequencers from v0.6.0 on prove under the v0.2.0 vks and follow OP Mainnet.
Every contract is source-verified on Gnosisscan, Blockscout and Sourcify, and
[`deployments/100.json`](deployments/100.json) holds the verified record:

| Contract | Address |
|---|---|
| `ProcessRegistry` | `0x20b96e465CA7C3536B9C733571ec1eCf42b2eA21` |
| `DavinciDKGAdapter` | `0xB74270Af067Bd75e30cC0cc6D24786EbD6816919` |
| davinci-dkg `DKGManager` | `0xC6Fb38c42ed3FB35D363a702218746d5C7Da36BF` (the redeploy that binds application ids to their registrant, [vocdoni/davinci-dkg#14](https://github.com/vocdoni/davinci-dkg/issues/14)) |
| `CouncilAdapter` | `0x33e91518521Feb5D2A14928563dc6930Bc2F0755` |
| Council manager | `0x2f5b110864cbad4017fe8ac59111812278f5f71f` (development trusted setup, `circuits-v1`) |
| `ZiskVerifier` | `0x150547716bD6f15D872508b66b2ae7ce17677C9C` (reused from the registry below) |

It reuses the previous registry's verifier and copies its pins and grace settings
(`PINS_FROM_REGISTRY`), so the pins table below covers both. The Council manager runs on
a development trusted setup: whoever holds that setup's toxic waste can forge dealings, so
treat COUNCIL processes as a beta.

### Gnosis Chain, previous registry

Gnosis Chain (chain id 100), built from commit `9b03f18`. Retired on 2026-10-07: it stays on
chain, but sequencers and SDKs use the production beta registry above.

| Contract | Address |
|---|---|
| `ZiskVerifier` | `0x150547716bD6f15D872508b66b2ae7ce17677C9C` |
| `ProcessRegistry` | `0x6702e0141B6b72bCF8C1bdff20A82A35C5502E7D` |
| `DavinciDKGAdapter` | `0xE9559c78E7ff8c19937A0657a092A221E90CCBC3` |
| davinci-dkg `DKGManager` | `0x9999F38Ff8Bf959E98Ddd5D4551f82775219c01B` |

Both Gnosis registries (and the first OP one) are pinned to:

| Immutable | Value |
|---|---|
| `batchProgramVK` | `0x6cfc89d562d0b22f04478a5c15b390433eb52f1b03147030b183076260da7a10` |
| `resultsProgramVK` | `0x7bc8c5e9235548386a44b1885732a2a7ffb1badddc8c7fba599d07ece47be794` |
| `rootCVadcopFinal` | `0x05006517b6ccde5da4d890587ba62845b5af8a307c00e87d4b9d05099b16dc80` |
| `ballotVKHash` | `0xbf1e6590bb1ba883d601c4d7d1c6fa2722a78590716874019db6d68fc776bb0e` |
| `defaultGrace` / `graceFloor` / `graceCeil` | 180 / 150 / 600 s |
| `graceMaxTotal` | 1800 s |
| `noticeMin` | 60 s |

[docs/verification.md](docs/verification.md) shows how to check the deployment against the
source.

## Quick start

A local chain with the contracts deployed and pinned to the davinci-zkvm release. It needs
Docker, and [Foundry](https://getfoundry.sh/) for `cast`:

```bash
git clone --recurse-submodules https://github.com/vocdoni/davinci-contracts.git
cd davinci-contracts
docker compose --profile local up -d
docker compose --profile local logs -f deploy-local   # waits for the deployment
cast call 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 "batchProgramVK()(bytes32)" --rpc-url http://localhost:8545
```

anvil listens on port 8545 with chain id 31337. `ZiskVerifier` is at
`0x5FbDB2315678afecb367f032d93F642f64180aa3` and `ProcessRegistry` at
`0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512`. `docker compose --profile local down` removes the
chain.

## Usage

### Creating a process

The organizer asks the registry for its next process id, gets the election key for that id from
a sequencer, and calls `newProcess`. On the Quick start chain, with a davinci-sequencer on its
default port:

```bash
RPC=http://localhost:8545
REGISTRY=0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
ORGANIZER_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80  # anvil account 0
SEQUENCER=http://localhost:9090

PID=$(cast call $REGISTRY "getNextProcessId(address)(bytes31)" \
  $(cast wallet address $ORGANIZER_KEY) --rpc-url $RPC)
KEY=$(curl -s -X POST $SEQUENCER/processes/keys -H 'Content-Type: application/json' \
  -d "{\"processId\":\"$PID\"}")

CENSUS_ROOT=0x2a3f0c1d9e8b7a6f5e4d3c2b1a09f8e7d6c5b4a3928170f6e5d4c3b2a1908f7e  # lean-IMT root
printf '{"title":"Example"}' > metadata.json  # serve it at the metadata URI
METADATA_HASH=0x$(sha256sum metadata.json | cut -d' ' -f1)

cast send $REGISTRY "newProcess(uint8,uint256,uint256,uint256,\
(bool,uint8,uint8,uint8,uint256,uint256,uint256,uint256),(uint8,bytes32,address,string,bool),\
string,bytes32,(uint256,uint256),(uint8,bytes12,uint256,uint256,uint256,uint256,uint256))" \
  0 0 3600 1000 \
  "(false,3,1,1,1,0,1,0)" \
  "(1,$CENSUS_ROOT,0x0000000000000000000000000000000000000000,https://example.org/census,false)" \
  https://example.org/metadata.json $METADATA_HASH \
  "($(echo $KEY | jq -r .x),$(echo $KEY | jq -r .y))" \
  "(0,0x000000000000000000000000,0,0,0,0,0)" \
  --private-key $ORGANIZER_KEY --rpc-url $RPC
```

The arguments, in order: status `READY` (0), start now (0), one hour, at most 1000 voters; a
ballot of three fields worth 0 or 1 with at most one set; an off-chain Merkle census (origin 1)
with its root and URI; the metadata URI and the SHA-256 of the exact bytes served there; the
election key; and all-zero DKG parameters, which select sequencer mode. For the other census
origins, the DKG key modes and every rule the registry enforces, see
[docs/registry.md](docs/registry.md#creating-a-process).

### Managing a process

The organizer can pause, resume, end or cancel a process with `setProcessStatus`, and until the
end time change its duration (`setProcessDuration`, shortening only with `noticeMin` seconds of
notice), grace window (`setProcessGrace`), voter cap (`setProcessMaxVoters`) and census root
(`setProcessCensus`, dynamic off-chain censuses only). The metadata (`setProcessMetadata`) can
change only before the start time.
Batches keep settling after the end until `getProcessGraceEnd(processId)`, and results are
accepted from then on.

### Settling transitions and results

These calls are permissionless and made by sequencers:

- `submitStateTransition(processId, publicValues, proofBytes, commitments, ys, kzgProofs)`, sent
  as a blob transaction carrying the transition's blobs;
- `setProcessResults(processId, publicValues, proofBytes)` in sequencer mode;
- `requestResultsDecryption(processId, accumulator, siblings)` and then
  `finalizeResultsFromDKG(processId)` in the DKG modes, plus `revealProcessKey` for
  `DKG_LOCKED`.

[docs/settlement.md](docs/settlement.md) lists what each one checks.

### Reading state

`getProcess(processId)` returns the whole process: status, times, census, ballot mode, key,
`latestStateRoot`, voter counts and, once published, `result`. The registry emits an event for
every change (`ProcessCreated`, `ProcessStatusChanged`, `ProcessStateTransitioned`,
`ProcessResultsSet` and others), so a process can be followed from the log alone:

```bash
cast call $REGISTRY "getProcessGraceEnd(bytes31)(uint256)" $PID --rpc-url $RPC
cast logs --address $REGISTRY "ProcessStateTransitioned(bytes31 indexed,address indexed,bytes32,bytes32,uint256,uint256,uint256)" $PID --from-block 0 --rpc-url $RPC
```

Contracts can call the registry through [`IProcessRegistry`](src/interfaces/IProcessRegistry.sol)
and the types in [`DAVINCITypes`](src/libraries/DAVINCITypes.sol). Applications can use the
generated bindings: TypeChain types in `typechain-types/` and Go bindings in `golang-types/`
(package `contracts`). The npm package `@vocdoni/davinci-contracts` is cut from the `release`
branch and can lag the contracts described here; `npm install && npm run prepare` builds the
types of this checkout into `dist/`.

### Deploying

`./deploy_all.sh` deploys `ZiskVerifier` and `ProcessRegistry` with the settings in `.env`
(see [`.env.example`](.env.example)):

| Variable | Value |
|---|---|
| `PRIVATE_KEY`, `RPC_URL`, `CHAIN_ID` | deployer key and target chain |
| `BATCH_PROGRAM_VK`, `RESULTS_PROGRAM_VK` | program vks of the davinci-zkvm vote-batch and results guests |
| `ROOT_C_VADCOP_FINAL` | root of the ZisK setup; must match the vendored verifier |
| `BALLOT_VK_HASH` | hash of the ballot proof verification key |
| `ZISK_VERIFIER` | optional deployed `ZiskVerifier` to reuse |
| `PINS_FROM_REGISTRY` | optional live registry to inherit `ZISK_VERIFIER`, the four pins and the grace settings from |
| `DKG_MANAGER` | optional davinci-dkg manager; enables the DKG key modes |
| `COUNCIL_MANAGER` | optional Council manager; enables the `COUNCIL` key mode |
| `GRACE_DEFAULT`, `GRACE_FLOOR`, `GRACE_CEIL`, `GRACE_MAX_TOTAL`, `NOTICE_MIN` | optional grace window and notice settings, in seconds (180, 150, 600, 1800, 60) |
| `EXPECT_GRACE` | optional `DEFAULT,FLOOR,CEIL,MAX_TOTAL,NOTICE` in seconds the registry must read back (e.g. `300,240,600,1800,60`); a misspelled `GRACE_*` silently keeps its default |

It then checks the deployment against the build with `script/verify_deployment.py` and writes
the verified record to `deployments/<chain id>.json`. Sequencers refuse a registry pinned to
other values than the davinci-zkvm release they run; the current ones are in the
[deployments table](#deployments).
[docs/deployment.md](docs/deployment.md) covers source verification, several chains, Docker and
DKG support.

## Documentation

- [docs/registry.md](docs/registry.md): process ids, lifecycle, grace window, creation
  parameters, census origins, key modes, organizer controls, reading state and events.
- [docs/settlement.md](docs/settlement.md): what `submitStateTransition` and the results calls
  check.
- [docs/errors.md](docs/errors.md): every custom error and when it is raised.
- [docs/deployment.md](docs/deployment.md): constructor, configuration, local and public
  deployments.
- [docs/verification.md](docs/verification.md): checking a live deployment against the source.
- [docs/development.md](docs/development.md): tests, fixtures, bindings, linters.
- [CHANGELOG.md](CHANGELOG.md): interface changes.

## Development

```bash
git clone --recurse-submodules https://github.com/vocdoni/davinci-contracts.git
cd davinci-contracts
forge build
forge test
```

[docs/development.md](docs/development.md) describes the test suites, how the Go-generated
fixtures are regenerated, the bindings and the linters.

## License

GNU Affero General Public License v3.0, see [LICENSE.md](LICENSE.md). Source files carry their
own SPDX identifiers.
