# repaid-loans-over-v1: key ceremony transcript

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

| | |
|---|---|
| Circuit | `repaid-loans-over-v1` = zk-kit `threshold_b8_n` (threshold, {"bits":8,"nonce":true}), 265 constraints |
| circuitId | `0x59a707d0a433d966efaba9aa83e3c139827c5c5d0895fce5968e20319524f9c9` = keccak256("repaid-loans-over-v1") |
| Public signals | `commitment`, `threshold`, `nonce` |
| vkHash | `0xbe28707434613d81d81f5ee40a2ae0d7d815a974da534c304070429d6a2b12be` = 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^9.

| | |
|---|---|
| URL | https://pse-trusted-setup-ppot.s3.eu-central-1.amazonaws.com/pot28_0080/ppot_0080_09.ptau |
| Size | 683,154 bytes |
| blake2b-512 | `33ccbcacd7c43238b540f8dd7f68b4acac6be3a1fe2e695d55aea291172d30ddc8056c2851f5660b5e795550f300660042072254813d1558dc4d5a7192eae9b6` |
| sha256 | `67e59e346767e179a5bd88b4789a56ce376708244c01a32b520ee208dbfb2595` |
| Header power | 2^9 (read from the file header) |
| S3 ETag | `69d89d14fb047514a1eb6c82ffd5a718` (last modified Tue, 09 Apr 2024 07:02:55 GMT); md5 matches |
| Downloaded | 2026-09-27T06:12:41.730Z |

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 `repaid-loans-over-v1.r1cs` on the phase-1 file. It is
   deterministic; anyone can recreate it (166,464 bytes, blake2b-512
   `ad01057716c7ce55a8fbf63872d6c3ed8e8ee0eddd1e851d0393261a2a5c77687130e6e4f212e1be9f389a65e09f45d54258c8a2e6f711ebef7e99e2cb0d0269`).
2. **Contribution #1: Super Wallet (SeoulLabs) phase-2 contribution**, 2026-09-27T06:13:00.122Z to 2026-09-27T06:13:00.190Z.
   Contribution hash:

   ```
   24b92a39044a2bba61f0f880bb892866cdd219bcf102c51445089094b0a9122a43dc9f5cb578a628b016a8986724c146b9d4ff2f4f32eff57f109976f072feb9
   ```

   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 seven circuits of ceremony batch 2 were contributed in one
   run that finished at 2026-09-27T06:13:03.218Z.
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 | 49689564 |
   | Block hash | `0xf881b8862fb95d63b2269b5a6e6ae228156d78250e72c9c7129901b460d820de` |
   | Block time | 2026-09-27T06:13:14.000Z (fetched 2026-09-27T06:13:13.528Z) |
   | Iterations | 2^10 |
   | Beacon contribution hash | `185d349f509a7869903487da52f281d712b8cae372d30adcdcc9c792cb8f91f324331793ff6542547a5c1c16c38825d146b07b65bbc32e8432dfbaf9b45abfe7` |

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

## 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 `repaid-loans-over-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,
`repaid-loans-over-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) | `c9b1a80d34d1070532598d43b6fa64c85ad891fd8816dbb5ae71c3781d1818013bc6946d8f896796162b777d176f6f677d416b99ded0fdf96c06cdaeea34067a` |
| `repaid-loans-over-v1.zkey` | 167,369 bytes, sha256 `fc03ac0eaec3459c5a9d4fb1baec5dc69aa90a8d8da5bbfb7d27f1e132bd1fcd`, blake2b-512 `31e01783126bd2e037c582bf08f19d688a09a2cdd326ad817743ef3c889a46a5bb75f4c1244b650026332fea8c7c3a989ef75f9e017ea111c3bb66f0250271e3` |
| `repaid-loans-over-v1.r1cs` | 119,188 bytes, sha256 `46056a2805f0321bc8f13c5e77d12d6afa76cd1b03df6b6833ffb5f8c9d998e2` |
| `repaid-loans-over-v1.wasm` | 1,752,497 bytes, sha256 `6939e38f01d38fa46a1404fc18d7adfbb26cc74e0ed94cc11e18cb2fb522c42a` |
| vkHash | `0xbe28707434613d81d81f5ee40a2ae0d7d815a974da534c304070429d6a2b12be` |
| Verifier.sol runtime keccak256 (solc 0.8.24, optimizer 200, paris) | `0x4730e8b179e4f2cfddd5adbd1c4fd8fbfedf8fe452a21738e7d67edbf4555a3d` |

## 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 9 --public --out ppot_0080_9.ptau   # compare blake2b512 above
npx zk-kit verify-ceremony --r1cs repaid-loans-over-v1.r1cs --ptau ppot_0080_9.ptau --zkey repaid-loans-over-v1.zkey
# prints: zkey VALID, then #1 Super Wallet (SeoulLabs) phase-2 contribution: 24b92a39044a2bba...
#                             #2 Xphere mainnet block 49689564 beacon [beacon f881b8862fb95d63..., 2^10 iterations]
```
