World ID is a privacy-preserving proof of personhood protocol that leverages the Semaphore protocol in order to prove inclusion of members in a merkle tree where each identity commitment was generated by an orb and its corresponding private key is stored on our users' phones. In the Semaphore protocol implementation there are individual sequential insertions. Individual insertions for big merkle trees are very expensive and therefore economically unfeasible at the World ID userbase scale (currently nearing 2M). In order to resolve that issue we developed custom circuits written in gnark in order to do batch insertions into the Semaphore merkle tree. This gnark circuit leverages the groth16 proof system on the bn254 curve and requires a custom trusted setup ceremony to be made in order to achieve verifier soundness.
For the phase 1 contribution (a.k.a powers of tau ceremony) we are using the Perpetual Powers of Tau ceremony (up to the 54th contribution) through the s3 hosted bucket in the snarkjs repo README. We built a deserializer from the .ptau format into the .ph1 format used by gnark and initialized a phase 2 using a fork (semaphore-mtb-setup) of a ceremony coordinator wrapper on top of gnark built by the zkbnb team.
AWS m5.16xlarge instance
- 256 GiB RAM
- 64 cores
- 500 GiB Volume
The chain of comands that has been performed before the first contribution.
git clone https://github.com/worldcoin/semaphore-mtb-setup
git clone https://github.com/worldcoin/semaphore-mtbDownload the trusted setup ceremony coordinator tool and the powers of tau files.
cd semaphore-mtb-setup && go build -v
# Download Powers of Tau files for each respective circuit
# !!! Bucket has been deleted
wget https://storage.googleapis.com/zkevm/ptau/powersOfTau28_hez_final_20.ptau
mv powersOfTau28_hez_final_20.ptau 20.ptau
wget https://storage.googleapis.com/zkevm/ptau/powersOfTau28_hez_final_23.ptau
mv powersOfTau28_hez_final_23.ptau 23.ptau
wget https://storage.googleapis.com/zkevm/ptau/powersOfTau28_hez_final_26.ptau
mv powersOfTau28_hez_final_26.ptau 26.ptau
# Convert .ptau format into .ph1
./semaphore-mtb-setup p1i 20.ptau 20.ph1
./semaphore-mtb-setup p1i 23.ptau 23.ph1
./semaphore-mtb-setup p1i 26.ptau 26.ph1
# go up a folder
cd ../Generate r1cs representation of the necessary sizes of the Semaphore Merkle Tree Batcher (SMTB):
- Tree depth: 30, Batch size: 10
- constraints: 725439
- powers of Tau needed: 20
- Tree depth: 30, Batch size: 100
- constraints: 6305289
- powers of Tau needed: 23
- Tree depth: 30, Batch size: 1000
- constraints: 60375789
- powers of Tau needed: 26
cd semaphore-mtb && go build -v
# requires quite a bit of compute
./gnark-mbu r1cs --batch-size 10 --tree-depth 30 --output b10t30.r1cs
./gnark-mbu r1cs --batch-size 100 --tree-depth 30 --output b100t30.r1cs
./gnark-mbu r1cs --batch-size 1000 --tree-depth 30 --output b1000t30.r1cs
# move the r1cs files into the coordinator folder
mv b10t30.r1cs b100t30.r1cs b1000t30.r1cs ../semaphore-mtb-setup/
# go up a folder
cd ../Initialize the phase 2 of the setup (the slowest process):
# make folders for each phase 2
mkdir b10 b100 b1000
cd semaphore-mtb-setup
# initialize each respective phase2
./semaphore-mtb-setup p2n 20.ph1 b10t30.r1cs b10t30c0.ph2
mv b10t30c0.ph2 srs.lag evals ../b10/
./semaphore-mtb-setup p2n 23.ph1 b100t30.r1cs b100t30c0.ph2
mv b100t30c0.ph2 srs.lag evals ../b100/
./semaphore-mtb-setup p2n 26.ph1 b1000t30.r1cs b1000t30c0.ph2
mv b1000t30c0.ph2 srs.lag evals ../b1000/- Go (using 1.20.5)
- Git
- > 16 GiB RAM
- Good connectivity (to upload and download files fast to s3)
- The more cores the better (shorter contribution time)
- > 10 GiB storage
Download the corresponding files for contributions (presigned AWS S3 bucket urls)
Contribution time (on aws m5.16xlarge 256GiB RAM <4GB used - the more cores the better): b10: 5-10sec (50MB file) b100: < 5 min (419MB file) b1000: 20-30 min (3.5GB file)
You will receive pre-signed URLs from dcbuilder.eth for a GET request of a .ph2 file off of AWS S3 of the form:
https://<S3_BUCKET>.s3.amazonaws.com/?AWSAccessKeyId=<ACCESS_KEY_ID>&Signature=&Expires=<EXPIRY_TIME>
Submit a GET request using:
curl --output b10t30cXX.ph2 <PRESIGNED_URL>
curl --output b100t30cXX.ph2 <PRESIGNED_URL>
curl --output b1000t30cXX.ph2 <PRESIGNED_URL>
where XX is the current contribution number.
Download and build the semaphore-mtb-setup coordinator tool to perform the contribution:
git clone https://github.com/worldcoin/semaphore-mtb-setup
cd semaphore-mtb-setup
go build -v
Perform the contribution for each individual .ph2 file and increase the XX counter by one. Each command will output a contribution hash, please copy each of these down into a file of the format <NAME/PSEUDONYM>_CONTRIBUTION.txt and prepend each value with the corresponding batch size of the .ph2 file you contributed to (b10, b100 or b1000). Please also share via a message what NAME or PSEUDONYM you selected since it is required to generate a pre-signed S3 upload URL.
./semaphore-mtb-setup p2c b10t30cXX.ph2 b10t30c(XX + 1).ph2
./semaphore-mtb-setup p2c b100t30cXX.ph2 b100t30c(XX + 1).ph2
./semaphore-mtb-setup p2c b100t30cXX.ph2 b100t30c(XX + 1).ph2
You will also receive pre-signed URLs to upload your contribution to the S3 bucket, after your contributions are done and you have the output files, upload them using the following commands:
curl -v -T b10t30c(XX + 1).ph2 <PRESIGNED_URL>
curl -v -T b100t30c(XX + 1).ph2 <PRESIGNED_URL>
curl -v -T b1000t30c(XX + 1).ph2 <PRESIGNED_URL>
curl -v -T <NAME/PSEUDONYM>_CONTRIBUTION.txt <PRESIGNED_URL>
NOTE: if your file is above 5GiB (shouldn't ever get to that) the request will fail. If that happens, please reach out.
Congratulations! You have successfully contributed to our phase 2 trusted setup ceremony!
- contribution hash:
b0b44102bf1201e83bffb1cb0c492cfb93421656c4d2d113840bb904a48936c5 - generated file:
b10t30c01.ph2
- contribution hash:
ed4570a3668448102b8f0fa2c47cdd592281a7dd30e568f112ec784b5f1d96e2 - generated file:
b10t30c02.ph2
- contribution hash:
1a0925e14d4c3035d8ee5d288e376e723299b712181b4e34b59a337ebe08761a - generated file:
b10t30c03.ph2
- contribution hash:
c3092354da6c45b43a81e410364972d635ee563d46c24db77e1dc171f440a9ca - generated file:
b10t30c04.ph2
- contribution hash:
d4e581570bbe53ffa9e08cc93816f48486cfd756df50894de74ac1845ae07feb - generated file:
b10t30c05.ph2
- contribution hash:
7f13b7d526ec05775c9646908da8d99a35f48777fa341f8c25adf099135bb162 - generated file:
b10t30c06.ph2
- contribution hash:
e4ce787995a6c97b8be12f418ae3c026e26f84ad3d433e3fe6f33d3449d08c91 - generated file:
b10t30c07.ph2
- contribution hash:
807552014597a0c51e4e0f2e9b989be7633d8a050906a894cab226bc2a85333d - generated file:
b10t30c08.ph2
- contribution hash:
e0e690b8acf0dfd8bed0c65c55c1507fd261ac5eb86ef7f111d04b9a35b81587 - generated file:
b10t30c09.ph2
- contribution hash:
43c7cb5dd53447967cfe531ac2120948efd90fa5c80eb3b80fb340df452d7e18 - generated file:
b10t30c10.ph2
- contribution hash:
66e1845efd543078218a92fd575478bd2f71d64b16a3bf427f5032dcc479a808 - generated file:
b100t30c01.ph2
- contribution hash:
b136004f834e6a4db35a5def1050d2aed0b4d41df57cbeb4577eb5c5997f9995 - generated file:
b10t30c02.ph2
- contribution hash:
be313375479fa2ce7097129bb187f16df3211dba4e395acdd84e946fb4ae1e4b - generated file:
b100t30c03.ph2
- contribution hash:
30fac7bc6ff5f2bc24991dd5e6537e203714459c1e6d31c241d512490e966dde - generated file:
b100t30c04.ph2
- contribution hash:
e53e7eae98d270b44e25ac8b413e1dcf45a13062c51cb45e6faad089a25d8511 - generated file:
b100t30c05.ph2
- contribution hash:
c202ab3e6a3e29041b1e3781cb1ffdbae7683541d32a91d8d92454b2ce0508c2 - generated file:
b100t30c06.ph2
- contribution hash:
10b5376bfbe4e6235a8b7f9b000699063ee8c5c9626e98dc70ed594f5c2e0326 - generated file:
b100t30c07.ph2
- contribution hash:
e2b20b3379496da808a502df477b47846e7c6375a40e84e81730cf5d15142e44 - generated file:
b100t30c08.ph2
- contribution hash:
6ac522c33145afcbcd05291834f13b0b83833578ca1a13e4ef91a33a187f23e2 - generated file:
b100t30c09.ph2
- contribution hash:
3a4112517f6b9082c6d8faf1091164bcd4f818aeb7e53cb8ec2f5aa1eabdd05d - generated file:
b100t30c10.ph2
- contribution hash:
6a1d0b08bf79fe564cd701e9af70bb5f3936f668869f529e83d8ecb1a3d474b3 - generated file:
b1000t30c01.ph2
- contribution hash:
d263eafd25ba809748390850966fd689379311033de6d4fc2de69acebb247d2b - generated file:
b10t30c02.ph2
- contribution hash:
1b5bb5f54d1126398b723ae4f42f86d9659550d57af262e67b9f8a6ddc7d926e - generated file:
b1000t30c03.ph2
- contribution hash:
9155ac2cc06510ffb63ac9a8c01284bf533183542054a94d735d358cc42cdca4 - generated file:
b1000t30c04.ph2
- contribution hash:
463c17a0c8ed79c56f4579d1eef02beac8edc91549fc9abae51c08e76b8bb4e9 - generated file:
b1000t30c05.ph2
- contribution hash:
dc8992e6d8bf5f9ed4b0cf9e98f582c0594d5775f315446c7ed1e94d3020e787 - generated file:
b10t30c06.ph2
- contribution hash:
1c512817cc55404489dc0184d7d049e6906f8282c542c17d9817a2bdab8ab524 - generated file:
b1000t30c07.ph2
- contribution hash:
606a17d757c56171416c81dcd79171369e6ff651020d0dba0d7c98fa31ce78ca - generated file:
b1000t30c08.ph2
- contribution hash:
dca70be8175332c8f3afe78018eecb5c205fef05fc0f177577dfed3bdb562304 - generated file:
b1000t30c09.ph2
- contribution hash:
34e92e61360b5e36d44736a8b2b6687c7557985e0acccd770b63de1b710c4506 - generated file:
b1000t30c10.ph2