Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions scripts/compile-circuits.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/bash
set -e

# ==============================================================================
# compile-circuits.sh
# Automated Circom compilation pipeline to generate WASM and zkey files
# ==============================================================================

echo "Starting Circom compilation pipeline..."

ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
CIRCUITS_DIR="$ROOT_DIR/zk-proof-service/circuits"
BUILD_DIR="$ROOT_DIR/zk-proof-service/build"
PTAU_DIR="$ROOT_DIR/zk-proof-service/ptau"

# The standard powers of tau file
PTAU_FILE="$PTAU_DIR/pot12_final.ptau"
PTAU_URL="https://hermez.s3-eu-west-1.amazonaws.com/powersOfTau28_hez_final_12.ptau"

mkdir -p "$BUILD_DIR"
mkdir -p "$PTAU_DIR"

if [ ! -f "$PTAU_FILE" ]; then
echo "Downloading Powers of Tau file..."
curl -L -o "$PTAU_FILE" "$PTAU_URL"
else
echo "Powers of Tau file already exists."
fi

# Ensure circom is installed
if ! command -v circom &> /dev/null; then
echo "Error: circom could not be found. Please install it to compile circuits."
exit 1
fi

for circuit_file in "$CIRCUITS_DIR"/*.circom; do
[ -e "$circuit_file" ] || continue

filename=$(basename "$circuit_file")
circuit_name="${filename%.circom}"

echo "Compiling $circuit_name..."

# 1. Compile the circuit (generates WASM, R1CS, and Symbol file)
circom "$circuit_file" --r1cs --wasm --sym -o "$BUILD_DIR"

# 2. Setup Groth16 (generate initial zkey)
echo "Running groth16 setup..."
npx snarkjs groth16 setup "$BUILD_DIR/$circuit_name.r1cs" "$PTAU_FILE" "$BUILD_DIR/${circuit_name}_0000.zkey"

# 3. Contribute to the phase 2 ceremony (creates final zkey)
echo "Contributing to phase 2..."
npx snarkjs zkey contribute "$BUILD_DIR/${circuit_name}_0000.zkey" "$BUILD_DIR/${circuit_name}_final.zkey" --name="AutomatedBuild" -v -e="$(head -c 32 /dev/urandom | base64)"

# 4. Export verification key
echo "Exporting verification key..."
npx snarkjs zkey export verificationkey "$BUILD_DIR/${circuit_name}_final.zkey" "$BUILD_DIR/${circuit_name}_verification_key.json"

# 5. Generate Solidity verifier
echo "Generating Solidity verifier..."
npx snarkjs zkey export solidityverifier "$BUILD_DIR/${circuit_name}_final.zkey" "$BUILD_DIR/${circuit_name}Verifier.sol"

# NOTE: Soroban verifiers can be generated using a Rust-based toolchain
# (e.g. from snarkjs output). This pipeline acts as the foundation.

echo "$circuit_name successfully compiled and artifacts generated."
done

echo "Circom compilation pipeline completed successfully."
20 changes: 20 additions & 0 deletions zk-proof-service/lib/circom-fuzzer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,23 @@ describe('circom-fuzzer static signal analysis', () => {
expect(underConstrained).toEqual([]);
});
});

describe('automated circuit constraint verification', () => {
it('runs automated circuit constraint verification during test execution on all circuits', async () => {
const { auditCircuits } = require('./circom-fuzzer');
const fs = require('fs');
const path = require('path');

const circuitsDir = path.join(__dirname, '../circuits');
const circuitFiles = fs.readdirSync(circuitsDir)
.filter((f) => f.endsWith('.circom'))
.map((f) => path.join(circuitsDir, f));

// Skip if there are no circuits, otherwise expect auditCircuits to pass without throwing
if (circuitFiles.length > 0) {
await expect(
auditCircuits(circuitFiles.map((file) => ({ file, fuzzRounds: 5 })))
).resolves.toBeDefined();
}
}, 60000); // Allow longer timeout for circuit verification
});