Run the contribution container with:
docker run \
--rm \ # Clean up container after run
-it \ # Run interactive with tty
-v phase2:/workspace \ # Mount the phase2 volume to /workspace in container
<OCI repository>/contributor # Container image nameThis uses a volume that outlives the container to store the contribution in case the process gets interrupted, once your contribution is complete and you have saved your transcript hash you can remove it with docker volume rm phase2.
Circuits are contributed to in parallel, one process per CPU core by default. Each process holds a whole circuit in memory, so on a machine with a lot of cores relative to RAM this can run out of memory. Cap the number of circuits processed at once with the MAX_PARALLELISM environment variable:
docker run \
--rm \
-it \
-e MAX_PARALLELISM=2 \ # Contribute to at most 2 circuits at a time
-v phase2:/workspace \
<OCI repository>/contributorEnter the challenge code given to you by your coordinator when you see:
Enter challenge code:Enter a name that your contribution will be known under, this does not have to be your real name
Enter your name or alias:Enter some entropy when you see the following, you can mash your keyboard or use some other source of randomness:
Enter some random text:Wait for your contribution to complete
Save your contribution transcript hash, you can post this on eg. Twitter, Lens to attest to your contribution on completion of the ceremony. Consult your coordinator if you have questions. It will look like:
Transcript hash, SAVE THIS VALUE:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /workspace/response/transcript.json
You can share or publish this value for people to verify your contribution to the ceremonySend your response code back to the coordinator along with your transcript hash, it will look like:
SEND CROC RESPONSE CODE TO COORDINATOR
Sending 2 files and 1 folders (10 MB)
Code is: xxxx-xxxx-xxxx-xxxx
On the other computer run:
(For Windows)
croc xxxx-xxxx-xxxx-xxxx
(For Linux/macOS)
CROC_SECRET="xxxx-xxxx-xxxx-xxxx" crocYour coordinator will verify your contribution.
Prepare your initial directory structure, you need the phase1 ptau file, your circuit r1cs and initial zkey files. They need to be in a directory as following:
workspace
├── contributions
│ └── 0000
│ ├── circuit1.zkey
│ └── circuit2.zkey
├── phase1.ptau
└── r1cs
├── circuit1.r1cs
└── circuit2.r1cs
Build the coordinator OCI container in coordinator/Dockerfile, eg. with Docker:
docker build -t coordinator . # Build container image with name 'coordinator'The container expects the ceremony folder to be mounted to /workspace whenever it is run.
Circuits are verified in parallel, one process per CPU core by default. Verification holds the phase1 ptau alongside the circuit in memory, so it is the most memory hungry step of the ceremony. Pass -e MAX_PARALLELISM=<n> to any of the commands below to cap how many circuits are processed at once if you run out of memory.
Perform initial setup and verification:
docker run \
--rm \ # Clean up container after run
-it \ # Run interactive with tty
-v ${PWD}:/workspace \ # Mount current directory to /workspace in container
coordinator \ # Container image name, change if you've built it with a different name
init # CommandSend challenge to contributor:
docker run \
--rm \ # Clean up container after run
-it \ # Run interactive with tty
-v ${PWD}:/workspace \ # Mount current directory to /workspace in container
coordinator \ # Container image name, change if you've built it with a different name
send # CommandIt will output a challenge code (xxxx-xxxx-xxxx-xxxx in the example output), send the challenge code to the contributor.
Example output:
SEND CROC CHALLENGE CODE TO CONTRIBUTOR:
Sending 2 files and 1 folders (10 MB)
Code is: xxxx-xxxx-xxxx-xxxx
On the other computer run:
(For Windows)
croc xxxx-xxxx-xxxx-xxxx
(For Linux/macOS)
CROC_SECRET="xxxx-xxxx-xxxx-xxxx" crocWhen the contributor has finished their contribution, run the receive command to receive and verify their contribution.
docker run \
--rm \ # Clean up container after run
-it \ # Run interactive with tty
-v ${PWD}:/workspace \ # Mount current directory to /workspace in container
coordinator \ # Container image name, change if you've built it with a different name
receive # CommandEnter contributor's response code:
Enter response code:Repeat for each contributor.
The final format will differ depending on the use case for your circuits, included in this repo is an example export script that calculates per-circuit IPFS folders. You will need to fork and edit it to suit your needs.
Build the exporter OCI container in exporter-example/Dockerfile, eg. with Docker:
docker build -t exporter . # Build container image with name 'exporter'Beacon application and artifact compression also run one process per CPU core by default, and both hold whole artifacts in memory. Pass -e MAX_PARALLELISM=<n> to cap this as with the other containers.
Export the results of the ceremony with:
docker run \
--rm \ # Clean up container after run
-it \ # Run interactive with tty
-v ${PWD}:/workspace \ # Mount current directory to /workspace in container
exporter \ # Container image name, change if you've built it with a different name
export # CommandEnter the beacon hash you're using for the ceremony (in hex, no leading 0x), this will usually be a block hash of some pre-determined block:
Enter beacon hash:
You will end up with a finalized ceremony workspace that looks like:
workspace
├── contributions
│ ├── 0000
│ │ ├── circuit1.zkey
│ │ └── circuit2.zkey
⋮ ⋮
⋮ ⋮
│ └── XXXX
│ ├── circuit1.zkey
│ ├── circuit2.zkey
│ └── transcript.json
├── export
│ ├── circuits
│ │ ├── circuit1
│ │ │ ├── r1cs.br
│ │ │ ├── vkey.json
│ │ │ └── zkey.br
│ │ └── circuit2
│ │ ├── r1cs.br
│ │ ├── vkey.json
│ │ └── zkey.br
│ └── transcripts
│ ├── 0000.json
⋮ ⋮
⋮ ⋮
│ ├── XXXX.json
│ └── log.json
├── log.json
├── phase1.ptau
└── r1cs
├── circuit1.r1cs
└── circuit2.r1cs
Calculate the IPFS hash of artifacts
docker run \
--rm \ # Clean up container after run
-it \ # Run interactive with tty
-v ${PWD}:/workspace \ # Mount current directory to /workspace in container
exporter \ # Container image name, change if you've built it with a different name
ipfs # CommandYou can now pin the export folder to IPFS to store both individual circuit artifacts and the ceremony output.