To start creating proofs for signatures, we need to generate a proving/verification key for the circuit

Single signature

For a single signature, you can ignore the machine setup instructions and the installing a patched version of node in the next section. Use the circuit verify.circom for a single signature verification

Batch of 50 signatures

Batch of 50 signatures generates ~129 million constraints, which lead to a large R1CS file, a large proving key size, and longer proving time

We use a r6i.32xlarge instance with Ubuntu 20.04 on AWS with 1000 Gb of storage and an addition 1000 Gb used as swap space.


Basic depdendencies

To get started, let's first install dependencies

sudo apt update
sudo apt install build-essential libgmp-dev libsodium-dev nasm tmux python3 g++ make nlohmann-json3-dev -y

Swap space

Then let's assign the swap space and increase the maximum memory map areas a process can have

sudo mkswap -f /dev/nvme1n1
sudo swapon /dev/nvme1n1
sudo sh -c 'echo "vm.max_map_count=10000000" >>/etc/sysctl.conf'
sudo sh -c 'echo 10000000 > /proc/sys/vm/max_map_count'

Install Rust and NVM

Then we can install rust and nvm to configure our environment

curl --proto '=https' --tlsv1.2 -sSf | sh
source $HOME/.cargo/env

curl -o- | bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/" ] && \. "$NVM_DIR/"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
nvm install --lts --default

Install Circom, SnarkJS, Rapidsnark

git clone
cd circom
cargo build --release
cargo install --path circom
npm install -g snarkjs
git clone
cd rapidsnark
npm install
git submodule init
git submodule update
npx task createFieldSources
npx task buildProver
alias rapidsnark="$HOME/rapidsnark/build/prover"

Install patched version of node

git clone
cd node

patch -p1 <<EOL
index 0097683120..d35fd6e68d 100644
--- a/deps/v8/src/api/
+++ b/deps/v8/src/api/
@@ -7986,7 +7986,7 @@ void BigInt::ToWordsArray(int* sign_bit, int* word_count,
 void Isolate::ReportExternalAllocationLimitReached() {
   i::Heap* heap = reinterpret_cast<i::Isolate*>(this)->heap();
   if (heap->gc_state() != i::Heap::NOT_IN_GC) return;
-  heap->ReportExternalMemoryPressure();
+  // heap->ReportExternalMemoryPressure();

 HeapProfiler* Isolate::GetHeapProfiler() {
diff --git a/deps/v8/src/objects/ b/deps/v8/src/objects/
index bd9f39b7d3..c7d7e58ef3 100644
--- a/deps/v8/src/objects/
+++ b/deps/v8/src/objects/
@@ -34,7 +34,7 @@ constexpr bool kUseGuardRegions = false;
 // address space limits needs to be smaller.
 constexpr size_t kAddressSpaceLimit = 0x8000000000L;  // 512 GiB
 #elif V8_TARGET_ARCH_64_BIT
-constexpr size_t kAddressSpaceLimit = 0x10100000000L;  // 1 TiB + 4 GiB
+constexpr size_t kAddressSpaceLimit = 0x40100000000L;  // 4 TiB + 4 GiB
 constexpr size_t kAddressSpaceLimit = 0xC0000000;  // 3 GiB

make -j16
alias nodex="~/node/out/Release/node --trace-gc --trace-gc-ignore-scavenger --max-old-space-size=2048000 --initial-old-space-size=2048000 --no-global-gc-scheduling --no-incremental-marking --max-semi-space-size=1024 --initial-heap-size=2048000 --expose-gc"

Clone and compile circuit

git clone
npm run prepare
time npm run verifier:build
cd build/verify_50_256_cpp
make -j4

Perform Phase 2 setup, contribution and apply beacon

Change directory to subfolder in build

time nodex $SNARKJS groth16 setup ../verify50_256.r1cs ~/powersOfTau28_hez_final.ptau verify50_256_0.zkey
time echo "Rainbow bridge magic" | nodex $SNARKJS zkey contribute verify50_256_0.zkey verify50_256_1.zkey --name="Electron Labs"
time nodex $SNARKJS zkey beacon verify50_256_1.zkey verify50_256.zkey 0102030405060708090a0b0c0d0e0f101112231415161718221a1b1c1d1e1f 10 -n="Final Beacon phase2"


Change instances

Since the major resource expensive part is done, you can upload the c++ build files, the r1cs and the proving key to an S3 bucket. You can then terminate this instance and use a much cheaper one, we recommend an m5.8xlarge. You can go with an even cheaper machine with less resources, but will increase proof time because you'll have to compensate memory requirements with swap space