added circom code

Signed-off-by: Anubha Jain <jainanubha80@gmail.com>
This commit is contained in:
Anubha Jain
2024-11-21 16:52:00 +05:30
committed by tanmoy
parent 1d58f731a2
commit 8002f006fc
17 changed files with 914 additions and 0 deletions

10
circom/.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
/input/
/output/
/powersoftau/
/circuits/benchmark/
/result/
**/__pycache__
/node_modules/
package-lock.json
env/
powersoftau

40
circom/README.md Normal file
View File

@@ -0,0 +1,40 @@
# Benchmark Circuits
[![Circom Badge](https://img.shields.io/badge/circuits-circom-black)](https://github.com/iden3/circom)
[![Snarkjs Badge](https://img.shields.io/badge/proof_system-snarkjs-yellow)](https://github.com/iden3/snarkjs)
![Python Badge](https://img.shields.io/badge/compile-python-green)
This repository is dedicated to a powerful and user-friendly framework designed for testing various circuits using Circom. Our main objective is to simplify the testing process, allowing developers to easily add new circuits and conduct reliable tests.
**Key features of the framework:**
1. **Extensibility:** The framework is highly extensible. To add new circuits, simply follow a few clear rules and place the circuits in the `circuits/base` folder. Additionally, provide a commented `main` file following the appropriate formatting.
2. **Easy Customization:** You can effortlessly customize circuit values using Python. Just make the necessary changes in the files `test_circuits.py` to adapt it to the new circuit.
**Getting Started:**
1. Clone this repository to your local system.
2. Add new circuits to the `circuits/base` folder.
3. Modify the `main` line of the circuit with the correct formatting and values to be customized in Python.
4. Edit the files `test_circuits.py` to adapt it to the new circuit, updating the circuit name, powersoftau, and other parameters as needed.
5. Run the benchmark to ensure the circuit functions correctly.
**Troubleshooting**
If you get any error, take care of properly set the following parameters:
* In `scripts/compile_circuit.sh`, properly set `CIRCOMLIB_PATH` path. If `circomlib` is not installed, run: `npm install circomlib`.
* In `test_circuits.py`, properly set `POT` variable with the path to the `*.ptau` file (download it from [here](https://github.com/iden3/snarkjs#7-prepare-phase-2)). It should be in `poweroftau` directory but it can be elsewhere.
* In `scripts/proving_system/prover.sh`, properly set `RAPIDSNARK` variable with the path to the `build/prover` executable. For information on how to install Rapidsnark visit [here](https://github.com/iden3/rapidsnark)
**Contributions are Welcome:**
[![MIT License](https://img.shields.io/badge/License-MIT-red.svg)](https://choosealicense.com/licenses/mit/)
We are open to contributions from the community to improve this framework and make it even more useful. Feel free to open issues, propose enhancements, or submit pull requests.
Thank you for choosing our framework. We hope it simplifies your Circom testing work and contributes to your success in developing secure and efficient circuits.

View File

@@ -0,0 +1,19 @@
pragma circom 2.0.3;
// Fibonacci with custom starting numbers
template Fibonacci(n) {
assert(n >= 2);
signal input in[2];
signal output out;
signal fib[n+1];
fib[0] <== in[0];
fib[1] <== in[1];
for (var i = 2; i <= n; i++) {
fib[i] <== fib[i-2] + fib[i-1];
}
out <== fib[n];
}
//MAIN component main = Fibonacci(NUM);

View File

@@ -0,0 +1,63 @@
pragma circom 2.0.0;
include "../../node_modules/circomlib/circuits/switcher.circom";
include "../../node_modules/circomlib/circuits/poseidon.circom";
include "../../node_modules/circomlib/circuits/bitify.circom";
template Mkt2VerifierLevel() {
signal input sibling;
signal input low;
signal input selector;
signal output root;
component sw = Switcher();
component hash = Poseidon(2);
sw.sel <== selector;
sw.L <== low;
sw.R <== sibling;
log(sw.outL);
log(sw.outR);
hash.inputs[0] <== sw.outL;
hash.inputs[1] <== sw.outR;
root <== hash.out;
}
template Mkt2Verifier(nLevels) {
signal input key;
signal input value;
signal input root;
signal input siblings[nLevels];
component hashV = Poseidon(1);
hashV.inputs[0] <== value;
component n2b = Num2Bits(nLevels);
component levels[nLevels];
n2b.in <== key;
for (var i=nLevels-1; i>=0; i--) {
levels[i] = Mkt2VerifierLevel();
levels[i].sibling <== siblings[i];
levels[i].selector <== n2b.out[i];
if (i==nLevels-1) {
levels[i].low <== hashV.out;
}
else {
levels[i].low <== levels[i+1].root;
}
}
root === levels[0].root;
}
//MAIN component main = Mkt2Verifier(NUM);

View File

@@ -0,0 +1,52 @@
pragma circom 2.0.0;
include "../../node_modules/circomlib/circuits/poseidon.circom";
template SpongeHash(inputs_length){
signal input in[inputs_length];
signal output hash;
var k = 0;
var hash_blocks = (inputs_length\15) + 1;
var block_index = 0;
component poseidon_hash[hash_blocks];
signal inside_hash[hash_blocks];
signal frame[hash_blocks][16];
for (var i=0; i<inputs_length; i++) {
frame[block_index][k] <== in[i];
if (k == 15){
//* START POSEIDON HASH
poseidon_hash[block_index] = Poseidon(16);
for (var j=0; j<16; j++)
poseidon_hash[block_index].inputs[j] <== frame[block_index][j];
inside_hash[block_index] <== poseidon_hash[block_index].out;
block_index++;
//*/ END POSEIDON HASH
frame[block_index][0] <== inside_hash[block_index - 1];
k = 1;
} else
k++;
}
if (inputs_length%16 != 0){
//* START POSEIDON HASH
poseidon_hash[block_index] = Poseidon(16);
for (var j=0; j<16; j++)
poseidon_hash[block_index].inputs[j] <== j<k ? frame[block_index][j] : 0;
hash <== poseidon_hash[block_index].out;
//*/ END POSEIDON HASH
}else
hash <== frame[block_index][0];
}
//MAIN component main = SpongeHash(NUM);

View File

@@ -0,0 +1,39 @@
pragma circom 2.0.3;
include "../node_modules/circomlib/circuits/sha256/sha256.circom";
include "../node_modules/circomlib/circuits/bitify.circom";
/**
* Wrapper around SHA256 to support bytes as input instead of bits
* @param n The number of input bytes
* @input in The input bytes
* @output out The SHA256 output of the n input bytes, in bytes
*/
template Sha256Bytes(n) {
signal input in[n];
signal output out[32];
component byte_to_bits[n];
for (var i = 0; i < n; i++) {
byte_to_bits[i] = Num2Bits(8);
byte_to_bits[i].in <== in[i];
}
component sha256 = Sha256(n*8);
for (var i = 0; i < n; i++) {
for (var j = 0; j < 8; j++) {
sha256.in[i*8+j] <== byte_to_bits[i].out[7-j];
}
}
component bits_to_bytes[32];
for (var i = 0; i < 32; i++) {
bits_to_bytes[i] = Bits2Num(8);
for (var j = 0; j < 8; j++) {
bits_to_bytes[i].in[7-j] <== sha256.out[i*8+j];
}
out[i] <== bits_to_bytes[i].out;
}
}
//MAIN component main = Sha256Bytes(NUM);

15
circom/package.json Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "benchmark_circuits",
"version": "1.0.0",
"description": "This repository contains the benchmark for circom circuits. In order to understand the time and memory consumption a report csv file is generated for each circuit. The report contains the following information:",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"circomlib": "^2.0.5",
"circomlibjs": "^0.0.8"
}
}

4
circom/requirements.txt Normal file
View File

@@ -0,0 +1,4 @@
tensorflow
numpy
pandas
psutil

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# This script is used to execute the circuits in the circuit directory
#check if passed the correct number of arguments, one that is circom file name
echo "In compile_circuit.sh command file"
if [ $# -lt 2 ]; then
echo "Usage: $0 <circom file name> <input file name> [--nodejs]"
echo "[--nodejs] is optional, if not passed, the script will use Cpp to generate the witness"
exit 1
fi
#define the base path for the circuit library
CIRCOMLIB_PATH=./node_modules
#get the file name without the extension
filename=$(basename -- "$1")
CIRCOM_FILENAME=${filename%.*}
echo "Compiling circuit [${CIRCOM_FILENAME}] ..."
# Create the output directory if it doesn't exist
mkdir -p output/compiled_circuit > /dev/null
mkdir -p output/compiled_circuit/compiled_${CIRCOM_FILENAME} > /dev/null
# Compile the circuits in the circuit directory
circom ${1} --r1cs --c --wasm --output output/compiled_circuit/compiled_${CIRCOM_FILENAME} -l ${CIRCOMLIB_PATH} -l ./circuits/base
# Generate the witness
if [[ $* == *--nodejs* ]]; then
echo "Compiling with [NodeJS] ..."
cd output/compiled_circuit/compiled_${CIRCOM_FILENAME}/${CIRCOM_FILENAME}_js
node generate_witness.js ${CIRCOM_FILENAME}.wasm /home/anubha/zkProjectEncodeG12/circom/${2} ../${CIRCOM_FILENAME}_witness.wtns
else
echo "Compiling with [Cpp] ..."
cd output/compiled_circuit/compiled_${CIRCOM_FILENAME}/${CIRCOM_FILENAME}_cpp
make
./${CIRCOM_FILENAME} ../../../../${2} ../${CIRCOM_FILENAME}_witness.wtns
fi
echo "Witness generated [${CIRCOM_FILENAME}_witness.wtns]"

View File

@@ -0,0 +1,18 @@
if [ $# -ne 1 ]; then
echo "Usage: ./prover.sh <circuit_name>"
exit 1
fi
CIRCUIT_NAME=$1
CIRCUIT_DIR=$(readlink -f ./output/compiled_circuit/compiled_${CIRCUIT_NAME})
WITNESS="${CIRCUIT_DIR}/${CIRCUIT_NAME}_witness.wtns"
RAPIDSNARK=/bin/prover
cd output/snarkjs_circuit/${CIRCUIT_NAME}
if [ -f "$RAPIDSNARK" ]; then
${RAPIDSNARK} circuit_final.zkey ${WITNESS} proof.json public.json
else
echo "RapidSnark not found, using snarkjs instead."
snarkjs groth16 prove circuit_final.zkey ${WITNESS} proof.json public.json
fi

View File

@@ -0,0 +1,22 @@
if [ $# -ne 2 ]; then
echo "Usage: ./setup_prover.sh <circuit_name> <pot_file>"
exit 1
fi
CIRCUIT_NAME=$1
POT=$(readlink -f ${2})
CIRCUIT_DIR=$(readlink -f ./output/compiled_circuit/compiled_${CIRCUIT_NAME})
R1CS="${CIRCUIT_DIR}/${CIRCUIT_NAME}.r1cs"
mkdir -p output/snarkjs_circuit > /dev/null
mkdir -p output/snarkjs_circuit/${CIRCUIT_NAME} > /dev/null
cd output/snarkjs_circuit/${CIRCUIT_NAME}
snarkjs groth16 setup ${R1CS} ${POT} circuit_final.zkey
snarkjs zkey export verificationkey circuit_final.zkey verification_key.json

View File

@@ -0,0 +1,23 @@
#!/bin/bash
if [ $# -lt 1 ]; then
echo "Usage: ./verifier.sh <circuit_name> [--generate-contract <contract_name>]"
exit 1
fi
VERIFICATION_KEY=$(readlink -f ./output/snarkjs_circuit/${1}/verification_key.json)
PUBLIC=$(readlink -f ./output/snarkjs_circuit/${1}/public.json)
PROOF=$(readlink -f ./output/snarkjs_circuit/${1}/proof.json)
snarkjs groth16 verify ${VERIFICATION_KEY} ${PUBLIC} ${PROOF}
if [ "$2" == "--generate-contract" ]; then
if [ -z "$3" ]; then
echo "Missing contract name after --generate-contract option."
exit 1
fi
CONTRACT_NAME="$3"
ZKEY=$(readlink -f ./output/snarkjs_circuit/${1}/circuit_final.zkey)
snarkjs zkey export solidityverifier ${ZKEY} ./output/snarkjs_circuit/${1}/Verifier_${CONTRACT_NAME}.sol
fi

295
circom/scripts/util.py Executable file
View File

@@ -0,0 +1,295 @@
#!/usr/bin/env python3
from csv import DictWriter
import json
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
import numpy as np
import pandas as pd
from math import sqrt
import random
import subprocess
import psutil
import re
import hashlib
def measure_command(command, time = True, memory = True):
"""
Measure the time and memory usage of a specified command.
:param command: The command to execute and measure.
:param time: True if you want to measure time, False otherwise.
:param memory: True if you want to measure memory usage, False otherwise.
:return: A tuple containing the elapsed time (if time=True) and memory usage (if memory=True).
"""
command = f'/usr/bin/time -p -f "%e %M" {command} > /dev/null'
# print("command: ",command)
if memory:
init_swap_used = psutil.swap_memory().used
max_swap_used = init_swap_used
# print("after memory check")
process = subprocess.Popen(command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
if memory:
while process.poll() is None:
max_swap_used = max(max_swap_used, psutil.swap_memory().used)
# print("After second memory check")
command_output = process.communicate()[1].decode('utf-8')
print("command_output: \n",command_output)
# print("after command output")
t,mem = command_output.split('\n')[0].split(' ')
t = float(t)
if memory:
swap = (max_swap_used-init_swap_used)/1024
m = float(mem)+(swap if swap > 0 else 0)
return t if time else None, m if memory else None
def measure_pagefault_time_command(command, password=None):
"""
Measure the time and number of page faults of a specified command.
:param command: The command to execute and measure.
:param password: The password to pass to the command, if it necessitates sudo privileges.
:return: A tuple containing the elapsed time and number of page faults.
"""
command = f'/usr/bin/time -p -f "%e %F %P %W %M" {command}'
print(command)
if password is not None:
command = f'echo "{password}" | sudo -S {command}'
process = subprocess.Popen(command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
command_output = process.communicate()[1].decode('utf-8')
time, pagefaults, cpu_percentage, swap_out, mem = command_output.split('\n')[0].split(' ') if (len(command_output.split(": ")) == 1) else command_output.split(": ")[1].split('\n')[0].split(' ')
return float(time), int(pagefaults), cpu_percentage, int(swap_out), mem
def generate_circuit(info, circuit_template, id = None):
"""
Generate a circuit from a template
:param info: dictionary with the information to replace in the template
:param circuit_template: path to the template
:param id: id of the circuit
"""
out_circuit = circuit_template.split('/')[-1].split('.')[0]
print("out_circuit: {}",out_circuit)
os.makedirs('circuits/benchmark',exist_ok=True)
with open(circuit_template, 'r') as infile:
circuit = infile.read()
for k,v in info.items():
circuit = circuit.replace(k, str(v))
circuit = circuit.replace('//MAIN', '')
id = f'_{id}' if id is not None else ''
out_path = f'circuits/benchmark/{out_circuit}{id}.circom'
print("out_path: {}",out_path)
with open(out_path, 'w') as outfile:
outfile.write(circuit)
return out_path
def append_to_csv(row,csv_path):
"""
Append a row to a csv file if it exists, otherwise create it
:param row: dictionary with the row to append
:param csv_path: path to the csv file
"""
with open(csv_path, 'a+', newline='') as csv_file:
dict_writer = DictWriter(csv_file, fieldnames=list(row.keys()))
if 0 == os.stat(csv_path).st_size:
dict_writer.writeheader()
dict_writer.writerow(row)
def generate_input(output_path, size):
"""
Generate a random input for a circuit of a given size
:param output_path: path to the output file
:param size: size of the input
"""
json_input = {'in':[str(random.randint(0, 255)) for _ in range(size)] }
os.makedirs('input',exist_ok=True)
with open(output_path, 'w') as outfile:
json.dump(json_input, outfile)
def generate_input_fibonnaci(output_path):
"""
Generate a random input for a circuit of a given size
:param output_path: path to the output file
:param size: size of the input
"""
json_input = {'in':['1','1'] }
os.makedirs('input',exist_ok=True)
with open(output_path, 'w') as outfile:
json.dump(json_input, outfile)
def generate_input_merkle(output_path,chosen_key_index,chosen_key,merkle_root,merkle_proof):
"""
Generate a random input for a circuit of a given size
:param output_path: path to the output file
:param size: size of the input
"""
json_input = {'key': chosen_key_index,
'value': chosen_key,
'root': merkle_root,
'siblings': merkle_proof
}
os.makedirs('input',exist_ok=True)
with open(output_path, 'w') as outfile:
json.dump(json_input, outfile)
def compute_input(GB):
"""
Compute the size of the input from a line, built with linear regression,
measuring the number constraints from the input size
:param GB: the amount of available memory
"""
# Read data from the CSV file
data = pd.read_csv('./scripts/benchmark_circuits_resize.csv')
# Extract 'INPUT SIZE' and 'CONSTRAINTS' columns from the DataFrame
input_size = data['INPUT SIZE']
constraints = data['CONSTRAINTS']
# Perform linear regression
slope, intercept = np.polyfit(input_size, constraints, 1)
best_constraints = 8388608 * GB / 8.996896768
return int(sqrt(abs(best_constraints / slope - intercept))), int(best_constraints)
def extract_contraints(r1cs_file):
infos = subprocess.check_output(f'snarkjs r1cs info {r1cs_file}',shell=True).decode('utf-8')
return int(re.search(r'# of Constraints: (\d+)',infos).group(1))
def resize_image(image, height, width):
"""
Resize an image to the given dimensions.
:param image_path: Path to the image to resize.
:param height: Height of the resized image.
:param width: Width of the resized image.
:return: the resized image.
"""
original_height, original_width, _ = image.shape
if (original_height-1) % (height-1) != 0 or (original_width-1) % (width-1) != 0:
divisors_h = [v+1 for v in range(1, (original_height - 1)//2) if (original_height - 1) % v == 0]
divisors_w = [v+1 for v in range(1, (original_width - 1)//2) if (original_width - 1) % v == 0]
raise ValueError(f"The image cannot be resized to the given dimensions.\n The height must be one of this numbers: {divisors_h}\
\n The width must be one of this numbers: {divisors_w}")
return (
(
tf.compat.v1.image.resize(
image,
[height, width],
align_corners=True,
method=tf.image.ResizeMethod.BILINEAR,
)
)
.numpy()
.round()
.astype(np.uint8)
)
def generate_random_image(height, width = None):
"""
Generate a random image.
:param height: Height of the image.
:param width: Width of the image.
:return: the random image.
"""
if width is None:
width = height
rimg = np.random.randint(0, 256, size=(height, width, 3), dtype=np.uint8)
return rimg
def generate_resize_input(output_path, f_height,f_width,r_height,r_width):
"""
Generate a random input that fits the cirtuit for the resize operation check.
:param output_path: Path to the output file.
:param f_height: Height of the full image.
:param f_width: Width of the full image.
:param r_height: Height of the resized image.
:param r_width: Width of the resized image.
"""
img = generate_random_image(f_height,f_width)
rsz = resize_image(img,r_height,r_width)
json_input = {'full_image':img.astype(str).tolist(), 'resize_image':rsz.astype(str).tolist() }
os.makedirs('input',exist_ok=True)
with open(output_path, 'w') as outfile:
json.dump(json_input, outfile)
def create_merkle_tree(arr, n_levels):
extended_len = 1 << n_levels
h_arr = []
for i in range(extended_len):
if i < len(arr):
h_arr.append(hashlib.sha256(str(arr[i]).encode()).hexdigest())
else:
h_arr.append(0)
return __merkelize(h_arr)
def __merkelize(arr):
if len(arr) == 1:
return arr
h_arr = []
for i in range(len(arr) // 2):
combined = str(arr[2 * i]) + str(arr[2 * i + 1])
h_arr.append(hashlib.sha256(combined.encode()).hexdigest())
m = __merkelize(h_arr)
return m + arr
def generate_merkle_proof(m, key, n_levels):
if n_levels == 0:
return []
extended_len = 1 << n_levels
top_siblings = generate_merkle_proof(m, key >> 1, n_levels - 1)
cur_sibling = m[extended_len - 1 + (key ^ 1)]
return top_siblings + [cur_sibling]
def validate_merkle_proof(F, hash_fn, key, value, root, proof):
h = hash_fn([value])
for i in range(len(proof) - 1, -1, -1):
if (1 << (len(proof) - 1 - i)) & key:
h = hash_fn([proof[i], h])
else:
h = hash_fn([h, proof[i]])
return F.eq(root, h)
if __name__ == '__main__':
raise ValueError('This script is not meant to be executed directly')

61
circom/test_fibonacci.py Normal file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/python3.10
from scripts.util import extract_contraints, generate_circuit, generate_input, generate_input_fibonnaci, measure_command
def test_circuit(circuit_name, input_path,pot_path,verbose=True,time = True, memory = True):
# print("inside test_circuit")
r1cs_path = 'output/compiled_circuit/compiled_{}/{}.r1cs'
# print("r1cs_path: ",r1cs_path)
t_c,m_c = measure_command(f'./scripts/compile_circuit.sh ./circuits/benchmark/{circuit_name}.circom {input_path} --nodejs',time,memory)
if verbose:
print(f'[{circuit_name}] Compile Circuit: {"" if t_c is None else f"{t_c} seconds"} {"" if m_c is None else f"{m_c} KB"}')
constraints = extract_contraints(r1cs_path.format(circuit_name,circuit_name))
if verbose:
print(f'[{circuit_name}] Constraints: {constraints}')
# print("before setup prover")
t_sp,m_sp = measure_command(f'./scripts/proving_system/setup_prover.sh {circuit_name} {pot_path}',time,memory)
if verbose:
print(f'[{circuit_name}] Setup Prover: {"" if t_sp is None else f"{t_sp} seconds"} {"" if m_sp is None else f"{m_sp} KB"}')
# print("after setup prover")
# print("before prove")
t_p,m_p = measure_command(f'./scripts/proving_system/prover.sh {circuit_name} ',time,memory)
if verbose:
print(f'[{circuit_name}] Prover: {"" if t_p is None else f"{t_p} seconds"} {"" if m_p is None else f"{m_p} KB"}')
# print("after prove")
t_v,m_v = measure_command(f'./scripts/proving_system/verifier.sh {circuit_name}',time,memory)
if verbose:
print(f'[{circuit_name}] Verifier: {"" if t_v is None else f"{t_v} seconds"} {"" if m_v is None else f"{m_v} KB"}')
return {'CIRCUIT':circuit_name,
'INPUT SIZE':input_path.split('_')[-1].split('.')[0],
'CONSTRAINTS':constraints,
'COMPILE_TIME':t_c,
'COMPILE_MEMORY':m_c,
'SETUP_TIME':t_sp,
'SETUP_MEMORY':m_sp,
'PROVER_TIME':t_p,
'PROVER_MEMORY':m_p,
'VERIFIER_TIME':t_v,
'VERIFIER_MEMORY':m_v}
if __name__ == '__main__':
# test fibonacci circuit
TIME, MEMORY = True, True
POT = './powersoftau/28pot.ptau'
NUM = 100000
circuit_name = f'fibonacci'
# print("before generate_circuit")
generate_circuit({'NUM':NUM},f'./circuits/base/{circuit_name}.circom',id=NUM)
# print("after generate_circuit")
# print("before generate_input")
generate_input_fibonnaci(f'./input/input_fibonacci.json')
# print("after generate_input")
# print("before test_circuit")
measures = test_circuit(f'{circuit_name}_{NUM}',f'/input/input_fibonacci.json',POT,time=TIME,memory=MEMORY)
print("measures: ",measures)

84
circom/test_merkle.py Normal file
View File

@@ -0,0 +1,84 @@
#!/usr/bin/python3.10
import random
# import node_modules.circomlib.test as nt
# from node_modules.circomlib.test.eddsa import buildEddsa
from scripts.util import extract_contraints, generate_circuit, generate_input, measure_command, create_merkle_tree, generate_merkle_proof, validate_merkle_proof, generate_input_merkle
def test_circuit(circuit_name, input_path,pot_path,verbose=True,time = True, memory = True):
# print("inside test_circuit")
r1cs_path = 'output/compiled_circuit/compiled_{}/{}.r1cs'
# print("r1cs_path: ",r1cs_path)
t_c,m_c = measure_command(f'./scripts/compile_circuit.sh ./circuits/benchmark/{circuit_name}.circom {input_path} --nodejs',time,memory)
if verbose:
print(f'[{circuit_name}] Compile Circuit: {"" if t_c is None else f"{t_c} seconds"} {"" if m_c is None else f"{m_c} KB"}')
constraints = extract_contraints(r1cs_path.format(circuit_name,circuit_name))
if verbose:
print(f'[{circuit_name}] Constraints: {constraints}')
# print("before setup prover")
t_sp,m_sp = measure_command(f'./scripts/proving_system/setup_prover.sh {circuit_name} {pot_path}',time,memory)
if verbose:
print(f'[{circuit_name}] Setup Prover: {"" if t_sp is None else f"{t_sp} seconds"} {"" if m_sp is None else f"{m_sp} KB"}')
# print("after setup prover")
# print("before prove")
t_p,m_p = measure_command(f'./scripts/proving_system/prover.sh {circuit_name} ',time,memory)
if verbose:
print(f'[{circuit_name}] Prover: {"" if t_p is None else f"{t_p} seconds"} {"" if m_p is None else f"{m_p} KB"}')
# print("after prove")
t_v,m_v = measure_command(f'./scripts/proving_system/verifier.sh {circuit_name}',time,memory)
if verbose:
print(f'[{circuit_name}] Verifier: {"" if t_v is None else f"{t_v} seconds"} {"" if m_v is None else f"{m_v} KB"}')
return {'CIRCUIT':circuit_name,
'INPUT SIZE':input_path.split('_')[-1].split('.')[0],
'CONSTRAINTS':constraints,
'COMPILE_TIME':t_c,
'COMPILE_MEMORY':m_c,
'SETUP_TIME':t_sp,
'SETUP_MEMORY':m_sp,
'PROVER_TIME':t_p,
'PROVER_MEMORY':m_p,
'VERIFIER_TIME':t_v,
'VERIFIER_MEMORY':m_v}
if __name__ == '__main__':
# test sha256 circuit given the size of an image as input
TIME, MEMORY = True, True
POT = './powersoftau/28pot.ptau'
NUM = 3
# Generate a random array of BigInt-like numbers
def random_array(length):
return [int(random.random() * 10 ** 45) for _ in range(length)]
# Create the array of secret keys
secret_keys = random_array(2 ** NUM)
# Choose a random key from the array
chosen_key = random.choice(secret_keys)
# Get the index of the chosen key
chosen_key_index = secret_keys.index(chosen_key)
# Print the index of the chosen key
print(chosen_key_index)
circuit_name = f'merkle'
# print("before generate_circuit")
generate_circuit({'NUM':NUM},f'./circuits/base/{circuit_name}.circom',id=NUM)
# print("after generate_circuit")
# print("before generate_input")
# eddsa = nt.eddsa.buildEddsa()
# field = eddsa.baby_jub.F
# hash_function = eddsa.poseidon
merkle_tree = create_merkle_tree(secret_keys, NUM)
merkle_root = merkle_tree[0]
merkle_proof = generate_merkle_proof(merkle_tree, chosen_key_index, NUM)
print("merkle_root: ",merkle_root)
print("merkle_proof: ",merkle_proof)
generate_input_merkle(f'./input/input_merkle_{NUM}.json',chosen_key_index,chosen_key,merkle_root,merkle_proof)
# print("after generate_input")
# print("before test_circuit")
measures = test_circuit(f'{circuit_name}_{NUM}',f'/input/input_merkle_{NUM}.json',POT,time=TIME,memory=MEMORY)
print("measures: ",measures)

61
circom/test_poseidon.py Normal file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/python3.10
from scripts.util import extract_contraints, generate_circuit, generate_input, measure_command
def test_circuit(circuit_name, input_path,pot_path,verbose=True,time = True, memory = True):
# print("inside test_circuit")
r1cs_path = 'output/compiled_circuit/compiled_{}/{}.r1cs'
# print("r1cs_path: ",r1cs_path)
t_c,m_c = measure_command(f'./scripts/compile_circuit.sh ./circuits/benchmark/{circuit_name}.circom {input_path} --nodejs',time,memory)
if verbose:
print(f'[{circuit_name}] Compile Circuit: {"" if t_c is None else f"{t_c} seconds"} {"" if m_c is None else f"{m_c} KB"}')
constraints = extract_contraints(r1cs_path.format(circuit_name,circuit_name))
if verbose:
print(f'[{circuit_name}] Constraints: {constraints}')
# print("before setup prover")
t_sp,m_sp = measure_command(f'./scripts/proving_system/setup_prover.sh {circuit_name} {pot_path}',time,memory)
if verbose:
print(f'[{circuit_name}] Setup Prover: {"" if t_sp is None else f"{t_sp} seconds"} {"" if m_sp is None else f"{m_sp} KB"}')
# print("after setup prover")
# print("before prove")
t_p,m_p = measure_command(f'./scripts/proving_system/prover.sh {circuit_name} ',time,memory)
if verbose:
print(f'[{circuit_name}] Prover: {"" if t_p is None else f"{t_p} seconds"} {"" if m_p is None else f"{m_p} KB"}')
# print("after prove")
t_v,m_v = measure_command(f'./scripts/proving_system/verifier.sh {circuit_name}',time,memory)
if verbose:
print(f'[{circuit_name}] Verifier: {"" if t_v is None else f"{t_v} seconds"} {"" if m_v is None else f"{m_v} KB"}')
return {'CIRCUIT':circuit_name,
'INPUT SIZE':input_path.split('_')[-1].split('.')[0],
'CONSTRAINTS':constraints,
'COMPILE_TIME':t_c,
'COMPILE_MEMORY':m_c,
'SETUP_TIME':t_sp,
'SETUP_MEMORY':m_sp,
'PROVER_TIME':t_p,
'PROVER_MEMORY':m_p,
'VERIFIER_TIME':t_v,
'VERIFIER_MEMORY':m_v}
if __name__ == '__main__':
# test sha256 circuit given the size of an image as input
TIME, MEMORY = True, True
POT = './powersoftau/28pot.ptau'
NUM = 10240
circuit_name = f'poseidon_sponge'
# print("before generate_circuit")
generate_circuit({'NUM':NUM},f'./circuits/base/{circuit_name}.circom',id=NUM)
# print("after generate_circuit")
# print("before generate_input")
generate_input(f'./input/input_{NUM}.json',NUM)
# print("after generate_input")
# print("before test_circuit")
measures = test_circuit(f'{circuit_name}_{NUM}',f'/input/input_{NUM}.json',POT,time=TIME,memory=MEMORY)
print("measures: ",measures)

61
circom/test_sha256.py Executable file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/python3.10
from scripts.util import extract_contraints, generate_circuit, generate_input, measure_command
def test_circuit(circuit_name, input_path,pot_path,verbose=True,time = True, memory = True):
# print("inside test_circuit")
r1cs_path = 'output/compiled_circuit/compiled_{}/{}.r1cs'
# print("r1cs_path: ",r1cs_path)
t_c,m_c = measure_command(f'./scripts/compile_circuit.sh ./circuits/benchmark/{circuit_name}.circom {input_path} --nodejs',time,memory)
if verbose:
print(f'[{circuit_name}] Compile Circuit: {"" if t_c is None else f"{t_c} seconds"} {"" if m_c is None else f"{m_c} KB"}')
constraints = extract_contraints(r1cs_path.format(circuit_name,circuit_name))
if verbose:
print(f'[{circuit_name}] Constraints: {constraints}')
# print("before setup prover")
t_sp,m_sp = measure_command(f'./scripts/proving_system/setup_prover.sh {circuit_name} {pot_path}',time,memory)
if verbose:
print(f'[{circuit_name}] Setup Prover: {"" if t_sp is None else f"{t_sp} seconds"} {"" if m_sp is None else f"{m_sp} KB"}')
# print("after setup prover")
# print("before prove")
t_p,m_p = measure_command(f'./scripts/proving_system/prover.sh {circuit_name} ',time,memory)
if verbose:
print(f'[{circuit_name}] Prover: {"" if t_p is None else f"{t_p} seconds"} {"" if m_p is None else f"{m_p} KB"}')
# print("after prove")
t_v,m_v = measure_command(f'./scripts/proving_system/verifier.sh {circuit_name}',time,memory)
if verbose:
print(f'[{circuit_name}] Verifier: {"" if t_v is None else f"{t_v} seconds"} {"" if m_v is None else f"{m_v} KB"}')
return {'CIRCUIT':circuit_name,
'INPUT SIZE':input_path.split('_')[-1].split('.')[0],
'CONSTRAINTS':constraints,
'COMPILE_TIME':t_c,
'COMPILE_MEMORY':m_c,
'SETUP_TIME':t_sp,
'SETUP_MEMORY':m_sp,
'PROVER_TIME':t_p,
'PROVER_MEMORY':m_p,
'VERIFIER_TIME':t_v,
'VERIFIER_MEMORY':m_v}
if __name__ == '__main__':
# test sha256 circuit given the size of an image as input
TIME, MEMORY = True, True
POT = './powersoftau/28pot.ptau'
NUM = 2048
circuit_name = f'sha256_bytes'
# print("before generate_circuit")
generate_circuit({'NUM':NUM},f'./circuits/base/{circuit_name}.circom',id=NUM)
# print("after generate_circuit")
# print("before generate_input")
generate_input(f'./input/input_{NUM}.json',NUM)
# print("after generate_input")
# print("before test_circuit")
measures = test_circuit(f'{circuit_name}_{NUM}',f'/input/input_{NUM}.json',POT,time=TIME,memory=MEMORY)
print("measures: ",measures)