# nationality-in-v1: key ceremony transcript

Everything below is also in `circuit.json` (field `ceremony`). Times are UTC.

| | |
|---|---|
| Circuit | `nationality-in-v1` = zk-kit `setMembership_b16_d8_n` (setMembership, {"bits":16,"depth":8,"nonce":true}), 2,414 constraints |
| circuitId | `0xbd9e44ea613d973a0c384ec4b6430bbad1dea1e2cc38ea1afd85f825f88fc2ca` = keccak256("nationality-in-v1") |
| Public signals | `commitment`, `root`, `nonce` |
| vkHash | `0xcc46974ca56304b8a4cd40fbf758be844420d36ccded5a29efd08e454732d80c` = keccak256(JCS(verification_key.json)) |
| ceremonyContributions (registry) | 1 |

## Phase 1: public Powers of Tau

The PSE Perpetual Powers of Tau (80 participants, closed with a pre-announced Ethereum randao
beacon), response 0080 prepared for phase 2 and truncated to 2^13.

| | |
|---|---|
| URL | https://pse-trusted-setup-ppot.s3.eu-central-1.amazonaws.com/pot28_0080/ppot_0080_13.ptau |
| Size | 9,530,514 bytes |
| blake2b-512 | `bf0c2d498f1197ad04ec0dbfcdda6df6348cbd793759f1f986e5cdf1a4100842293dfad6b8961f64b7ba35c162b5c821c4c097a52f3a639b55b0e765ec311b44` |
| sha256 | `ccee28086e4b81d81a6e16fdee054d1dbd5276362e2662d4205d31de45cb930f` |
| Header power | 2^13 (read from the file header) |
| S3 ETag | `bb54c403a93fabdabb99520b9fd94f56-2` (last modified Tue, 09 Apr 2024 07:06:01 GMT); multipart ETag recomputed with 8 MiB parts: matches |
| Downloaded | 2026-09-27T02:44:12.606Z |

PSE publishes no hash list for the prepared files, so the checks above are what could be made: the
header, the byte count, and the S3 multipart ETag recomputed from the bytes (a transport check, not
an authenticity check). snarkjs's full powers-of-tau verification was not run: it did not finish in
10 minutes even for the 2^8 file on the build machine. Download the file yourself and compare the
blake2b-512 before you rely on it.

## Phase 2

1. **Initial key** `_0000` = snarkjs `zkey new` of `nationality-in-v1.r1cs` on the phase-1 file. It is
   deterministic; anyone can recreate it (1,451,776 bytes, blake2b-512
   `6a7280d6795d539a49e1fa401ad032c931dee468e14f1d5932722fe544f33cf3a3bba325c4e044659e5fbfcee467d0dc753ca1d33200794f1c282f1bded6984b`).
2. **Contribution #1: Super Wallet (SeoulLabs) phase-2 contribution**, 2026-09-27T02:44:26.194Z to 2026-09-27T02:44:26.609Z.
   Contribution hash:

   ```
   06d9de6cfbb25250fe9a3bdb93d8941c90e7de2176872316a13de09906b991bf1dfa0ab42ae6b4c5ba0961486d7191d39e65c18d5a2905c184d70f41faf1e9bc
   ```

   Entropy: 64 bytes from the operating system CSPRNG (`node:crypto` randomBytes), passed in
   memory to snarkjs, which mixes in its own random bytes. It was not written to disk, a log or a
   terminal, and the process has exited. All six production circuits were contributed in one run
   that finished at 2026-09-27T02:44:49.737Z.
3. **Beacon.** The rule, fixed in `zk-kit/scripts/production-ceremony.ts` before the run: after
   every contribution has finished, take the latest Xphere mainnet block whose timestamp is later
   than that moment, and apply its hash with 2^10 iterations (snarkjs `zkey beacon`).

   | | |
   |---|---|
   | Chain | Xphere mainnet, chain id 20250217 (read from https://en-hkg.x-phere.com) |
   | Block | 49677068 |
   | Block hash | `0x004d454b466cfbe88eedad46ef160b140124683eab1432b108a54b3111fac37a` |
   | Block time | 2026-09-27T02:44:58.000Z (fetched 2026-09-27T02:44:57.539Z) |
   | Iterations | 2^10 |
   | Beacon contribution hash | `9f69f8e9fdab79f69099d0bebc9f85c2b075787915936e8f9c9bafd1c99d02fbe8767c5c2d18de7b37c89fa9a952c7abc4623b2fe4053ece8290dd96cf8a31ce` |

   Check the block: `curl -s -X POST -H 'content-type: application/json' --data '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["0x2f6030c",false]}' https://en-hkg.x-phere.com`
   and compare `hash`, or open https://xp.tamsa.io/block/49677068.

## What this ceremony does and does not give you

A Groth16 phase 2 is sound if **at least one** contributor destroyed their randomness. This key has
**one** contributor, Super Wallet, so its soundness rests on Super Wallet having done so. The public
beacon makes the final key depend on a value nobody knew when the contribution was made, but it is
public and adds no secret: it does not replace a second, independent contributor. The block number
was not announced in advance; the rule for picking it was fixed in the script, and the block came
after the contribution. The registry records `ceremonyContributions = 1` as it is.

**An institution that wants to add its own contribution** takes `nationality-in-v1.zkey` (this key; the
contribution chain inside it continues), checks it with `zk-kit verify-ceremony`, runs
`zk-kit contribute`, and hands the result back; Super Wallet then applies a new, pre-announced
beacon with `zk-kit finalize`. The result is a new key and therefore a new circuit id,
`nationality-in-v2`, registered alongside this one with ceremonyContributions = 2. A
key is never swapped in under an existing circuit id.

## Result

| | |
|---|---|
| verifyFromR1cs (r1cs + phase-1 file + zkey) | OK |
| Circuit hash (snarkjs) | `2be1a9dc8a635faed929be11b6748676f08efcd72aeff2f875cd590d6eff5ef4451b0b3302e325011ebf8737372e8ebb7c9a1a7a321a04a14bc20418cc26fc8b` |
| `nationality-in-v1.zkey` | 1,452,681 bytes, sha256 `56a8b98b721bffa3bbc354397c3dc2bd599ee57a038b505c7aae5d662f0d4e12`, blake2b-512 `d0d11aaa682e7e4c62a2e6b99021da017ee67e8381ef0d80227d884f5d35ea1665ce567090abf9a7fede8a32e257257d9534939a9c16547d8cf448c40f60242c` |
| `nationality-in-v1.r1cs` | 1,132,764 bytes, sha256 `3ec32d1296f3b0b72e7d081e55398dc2036e49cf4c094bc133e9c95519fc450e` |
| `nationality-in-v1.wasm` | 1,981,214 bytes, sha256 `fc47762e930730d15a87572709a5d2c5b46082ab665bf57c8f3029ca3930d319` |
| vkHash | `0xcc46974ca56304b8a4cd40fbf758be844420d36ccded5a29efd08e454732d80c` |
| Verifier.sol runtime keccak256 (solc 0.8.24, optimizer 200, paris) | `0x11a67443d27eaff0575ccd3ec45489fc01f519ad59d704039f81652bba56df47` |

## Check it yourself

```sh
npm install /path/to/zk-kit          # or: npm install snarkjs@0.7.6 and use snarkjs directly
npx zk-kit ptau --power 13 --public --out ppot_0080_13.ptau   # compare blake2b512 above
npx zk-kit verify-ceremony --r1cs nationality-in-v1.r1cs --ptau ppot_0080_13.ptau --zkey nationality-in-v1.zkey
# prints: zkey VALID, then #1 Super Wallet (SeoulLabs) phase-2 contribution: 06d9de6cfbb25250...
#                             #2 Xphere mainnet block 49677068 beacon [beacon 004d454b466cfbe8..., 2^10 iterations]
```
