iden3 / circom Goto Github PK
View Code? Open in Web Editor NEWzkSnark circuit compiler
License: GNU General Public License v3.0
zkSnark circuit compiler
License: GNU General Public License v3.0
In places like
circom/dag/src/json_porting.rs
Line 7 in f307fbc
std::collections::HashMap
on even more places across the workspace. Not sure how much data it's included in there, but what would definitely speed up a lot this is to use hashbrown which supports no-std and should be perfectly compatible.
I can make a PR if you want 😄
(Yes, I have seen #49)
I would love to be able to generate proofs using the BLS12-381
curve. Snarkjs already supports this curve.
Changing the curve for the R1CS file is rather straightforward, since BN128's group order is hardcoded as a string here. I changed it to BLS12-381's group order and checked using snarkjs that the R1CS's curve had changed. It works 🎉
Using the C++ witness generator, calculations for the witness are done in the fr.asm assembly file, and from what I gather using Montgomery representation. Below are the constants defined in the section .data
at the end of the file:
section .data
Fr_q:
dd 0
dd 0x80000000
Fr_rawq:
q dq 0x43e1f593f0000001,0x2833e84879b97091,0xb85045b68181585d,0x30644e72e131a029
half dq 0xa1f0fac9f8000000,0x9419f4243cdcb848,0xdc2822db40c0ac2e,0x183227397098d014
R2 dq 0x1bb8e645ae216da7,0x53fe3ab1e35c59e3,0x8c49833d53bb8085,0x0216d0b17f4e44a5
Fr_R3:
dd 0
dd 0x80000000
Fr_rawR3:
R3 dq 0x5e94d8e1b4bf0040,0x2a489cbe1cfbb6b8,0x893cc664a19fcfed,0x0cf8594b7fcc657c
lboMask dq 0x3fffffffffffffff
np dq 0xc2e1f593efffffff
I understand that q
is BN128's group order and the modulo for all operations and that half = (q-1)/2
(used for comparisons).
R2
and R3
must be Montgomery coefficients, R2
being used for conversion to Montgomery representation and R3
being used for multiplication. However, I do not understand what they actually represent, since they are smaller that q
and are not inverses of one another.
I also do not understand what lboMask
(a mask for the two most significant bits?) and np
are for.
I would love to make a PR to define the prime modulus using a command-line argument for example. I would just need help to understand these last things.
Is it possible to do integer division in circom? For example, something like this would be great:
pragma circom 2.0.0;
function div(a, b) {
var r = a;
var q = 0;
while (r >= b) {
r = r - b;
q = q + 1;
}
return q;
}
template test() {
signal input a;
signal input b;
signal output c;
c <== div(a, b);
}
component main = test();
It will not work because "non quadratic constraint" error. However, I tried other kinds of division algorithm, but still cannot remove such error.
It's much easier to cargo install circom
rather than cloning and building the repo. Please upload to crates.io. The crate name circom
is currently available.
It can be temporally fixed by compling, keeping the arm64 code from the libwabt.a fat binary and compile again
# for commit a9a4a24e4e95debb0230a233c259fac7d3e1e186
cargo build --release
lipo target/release/build/wabt-sys-ccf4f394b6bb7490/out/build/libwabt.a -thin arm64 -output target/release/build/wabt-sys-ccf4f394b6bb7490/out/build/libwabt.a
cargo build --release
It would really help in developing and debugging huge circuits if the log()
function would accept a string label, such as log("myLabel", 0)
An even better improvement would be to allow log
to be variadic, but I'm not sure how hard that would be.
When I compile my circuits, if there is an error, there is always a line in the error message which says "previous errors were found". Is it possible to eventually expand that error message to point to which previous errors?
Hi, I get an error during witness generation
(node:4036550) UnhandledPromiseRejectionWarning: Error: Too many values for input signal in[0]
my input.json is
{
"in[0]" : 2222,
"in[1]" : 2222
}
the circuit is:
pragma circom 2.0.0;
template Main() {
signal output out;
signal input in[2];
out <== in[0]*in[1];
}
component main = Main();
Doesn't this syntax of passing arrays work anymore?
Thanks.
A lot of logging in circuits is primarily used for generating "stack traces" of the execution when generating a witness. Ideally, circom should have a "trace" mode that injects log statements for:
These would then be logged (or traced some other way?) recursively as the witness is generated.
If the -l parameter (include dir) is at the last parameter it doesn't work. If it's at the first one it does.
Example:
This doesn't work:
~/git/zkevm/pil-stark/ [main*] circom --wasm --sym --r1cs --output outdir --prime goldilocks --O1 -l circuits.gl circuit.circom
invalid input file
previous errors were found
But this does:
~/git/zkevm/pil-stark/ [main*] circom --wasm -l circuits.gl --sym --r1cs --output outdir --prime goldilocks --O1 circuit.circom
We are using snarkjs as backend for circom.
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
inputs,
circuitWasmPath,
zkeyPath
)
Variable inputs
have type any
. Every time we changed circom file we need to update inputs structs. However any
make us hard to remember and easy to create error/bugs.
I think we should create function for auto gen inputs/outputs interface of circom. It's help developer easy to test and use circom.
Create new interface command line to generate inputs/outputs interface.
Example
circom merkle_tree.circom --types types.ts
Circom file
include "../../../node_modules/circomlib/circuits/comparators.circom";
template Example() {
signal input first_input;
signal input second_input[100];
signal output first_output;
}
We will generate inputs interface like bellow:
interface ExampleInput {
first_input: bigint;
second_input: bigint[];
}
Samething for outputs interface.
Thank Iden3 for awesome work!
When developing a circuit, an author will likely include many log statements. It would be ideal to have a compilation mode that removes all of these log statements from the output when compiling for production.
Hello everyone~ 😀
Recently, I'm writing circom version of my python functions.
(To make the zk proof of python functions' output)
If I have a python function, I can easily pass the array into and retrieve the array from that function.
def myFunc(in_array):
# Some calculations
return out_array
if __name__ == "__main__":
in_array = [1, 2, 3];
out_array = myFunc(in_array);
However, according to docs, I cannot find examples or somewhere else that talking about passing array into a function.
Currently, I guess that it might be something like this:
function myFunc(in_array) {
// Some calculations
return out_array;
}
template mainFunc() {
signal private input in_array; // A fixed length array
signal private input b;
signal output out;
var out_array = myFunc(in_array);
}
component main = mainFunc();
Thanks for anyone willing to give me the answer or some clues about how I could develop in this situation. 🙏❤
circom2 circuits/c.circom --r1cs --wasm --sym --c
does not spit out a wasm file. The best error message I could find is previous errors were found
. Is this part working at all?
According to https://twitter.com/railgun_project/status/1500966895733850117 they've also had problems that they had to put out a bounty for it.
Also I don't have the best experience working with circom2, a lot of documentation's outdated, makes me sad:(
Hello,
The doc seems to have changed in the last days and the getting started does not seems to work anymore ?
I can notice in the https://docs.circom.io/1.-an-introduction/getting-started the installation of the old circom npm package that is now deprecated in favor of the circom rust compiler.
and some signal private input a;
in the Multiplier example, that don't seem to compile.
I remember trying the getting started that works well last week. When i searched in my history the docs URL was not the same : https://docs.circom.io/getting-started/compiling-circuits/
Do you know what happens ?
Thanks a lot !
pragma circom 2.0.3;
template Hash() {
signal output out;
out <== 256 \ 256;
}
component main = Hash();
When I generate the witness for this circuit with wasm. I get the correct result witness with ["1","1"]. But when I generate it with c, the value is zero ["1", "0"].
The circuits is:
pragma circom 2.0.3;
function add(left_operand, right_operand){
return left_operand + right_operand;
}
template uvm(CODE_SIZE) {
signal input code[CODE_SIZE];
var pc = 0;
var MEM_SIZE = 8;
var memory[MEM_SIZE] = [0,0,0,0,0,0,0,0];
var STACK_SIZE = 8;
var stack[STACK_SIZE] = [0, 0, 0, 0, 0, 0, 0, 0];
var op;
var sp = -1;
while (pc < CODE_SIZE) {
op = code[pc];
pc = pc + 1;
if (pc == 0x0) {
pc = CODE_SIZE;
}
if(op == 0x1){
stack[sp - 1] = add(stack[sp], stack[sp - 1]);
sp = sp - 1;
}
// push
if (op == 0x60) {
if(sp + 1 < STACK_SIZE){
stack[sp + 1] = code[pc];
sp = sp + 1;
pc = pc + 1;
}
}
}
//...
}
circom: 2.0.3
The error:
error[T3001]: Out of bounds exception
┌─ "circuits/vm2.circom":27:13
│
27 │ stack[sp - 1] = add(stack[sp], stack[sp - 1]);
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found here
│
= call trace:
->uvm
previous errors were found
Question: Is this a must to check if sp is -1 at any condition?
The "Getting started" part of the documentation says:
Let us start with the Wasm code. Using the generated Wasm binary and three JavaScript files, we simply need to provide...
—https://github.com/iden3/circom/blob/master/mkdocs/docs/getting-started/computing-the-witness.md
However, the command circom multiplier2.circom --wasm
only produces two JavaScript files:
$ ls -1 multiplier2_js
generate_witness.js
multiplier2.wasm
witness_calculator.js
I would be happy if I could know this was simply a typo.
Just so you know, I'm using circom 2.0.4, and the full content of multiplier2.circom is the following.
pragma circom 2.0.4;
template Multiplier2() {
signal input a;
signal input b;
signal output c;
c <== a*b;
}
component main = Multiplier2();
It seems that the repository does not follow any version tagging strategy.
I believe adding version tags would be helpful for many users given that one may want to pin circom installation to specific a version in order to maintain compatibility with other dependencies.
One example is performing circom installation through Docker.
The "Background" part of the documentation says:
In the figure below, we have defined an
F_7
-arithmetic circuit that performs the operation...—https://github.com/iden3/circom/blob/master/mkdocs/docs/background/background.md
However, no image actually shows up. The reason is that the following link to the image is dead:
https://gblobscdn.gitbook.com/assets%2F-MDt-cjMfCLyy351MraT%2F-MHR5icu-Jxuas-UC7DY%2F-MHR60RuAQK6qNzhOPgE%2Foutput.jpg?alt=media&token=39d3d332-cac5-4546-ab43-9f489241ae50
When running with -O1
(or any optimization level above zero), some signal association is lost due to optimizations. This wouldn't happen with -O0
; however, some large circuits are not able to compile with no optimizations due to size limitations.
Can the symfile keep the signal associations for values optimized away by the compiler?
pragma circom 2.0.0;
function x(inp)
{
var t[4];
t = [1, 2, 3, 4];
return t[inp];
}
template Main()
{
signal input in;
signal s;
signal output out;
s <-- x(in);
out <== 2*s;
}
component main = Main();
For the above circuit, I am able to generate witness using wasm.
But when I try to compile the C++ witness generator for the same, I get the following errors:
g++ -c main.cpp -std=c++11 -O3 -I.
main.cpp:116:2: error: expected declaration before ‘}’ token
116 | }
| ^
main.cpp:117:20: error: expected constructor, destructor, or type conversion before ‘(’ token
117 | Fr_str2element (&v, s.c_str());
| ^
main.cpp:118:5: error: ‘vval’ does not name a type
118 | vval.push_back(v);
| ^~~~
main.cpp:119:3: error: expected declaration before ‘}’ token
119 | } else {
| ^
main.cpp:119:5: error: expected unqualified-id before ‘else’
119 | } else {
| ^~~~
main.cpp:124:1: error: expected declaration before ‘}’ token
124 | }
| ^
main.cpp: In function ‘void loadJson(Circom_CalcWit*, std::string)’:
main.cpp:128:34: error: variable ‘std::ifstream inStream’ has initializer but incomplete type
128 | std::ifstream inStream(filename);
| ^
main.cpp:129:3: error: ‘json’ was not declared in this scope
129 | json j;
| ^~~~
main.cpp:130:15: error: ‘j’ was not declared in this scope
130 | inStream >> j;
| ^
main.cpp:134:8: error: ‘json’ is not a class, namespace, or enumeration
134 | for (json::iterator it = j.begin(); it != j.end(); ++it) {
| ^~~~
main.cpp:134:39: error: ‘it’ was not declared in this scope; did you mean ‘int’?
134 | for (json::iterator it = j.begin(); it != j.end(); ++it) {
| ^~
| int
main.cpp:137:10: error: ‘vector’ is not a member of ‘std’
137 | std::vector<FrElement> v;
| ^~~~~~
main.cpp:6:1: note: ‘std::vector’ is defined in header ‘<vector>’; did you forget to ‘#include <vector>’?
5 | #include "calcwit.hpp"
+++ |+#include <vector>
6 | void Main_0_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather);
main.cpp:137:26: error: expected primary-expression before ‘>’ token
137 | std::vector<FrElement> v;
| ^
main.cpp:137:28: error: ‘v’ was not declared in this scope
137 | std::vector<FrElement> v;
| ^
main.cpp:138:5: error: ‘json2FrElements’ was not declared in this scope
138 | json2FrElements(it.value(),v);
| ^~~~~~~~~~~~~~~
main.cpp:141:21: error: aggregate ‘std::ostringstream errStrStream’ has incomplete type and cannot be defined
141 | std::ostringstream errStrStream;
| ^~~~~~~~~~~~
main.cpp:146:21: error: aggregate ‘std::ostringstream errStrStream’ has incomplete type and cannot be defined
146 | std::ostringstream errStrStream;
| ^~~~~~~~~~~~
main.cpp:155:21: error: aggregate ‘std::ostringstream errStrStream’ has incomplete type and cannot be defined
155 | std::ostringstream errStrStream;
| ^~~~~~~~~~~~
main.cpp: In function ‘int main(int, char**)’:
main.cpp:222:30: error: ‘loadCircuit’ was not declared in this scope
222 | Circom_Circuit *circuit = loadCircuit(datfile);
| ^~~~~~~~~~~
make: *** [Makefile:16: main.o] Error 1
The tutorial here doesn't work on Apple M1.
https://blog.iden3.io/first-zk-proof.html
So does the visual summary in home page of official document here
https://docs.circom.io/
I'm following the tutorials for the simple multiplier here.
https://docs.circom.io/getting-started/computing-the-witness/
The generated cpp files do not support arm64 by default. So I compiled everything using arch -x86_64
. However when I run the compiled file to generate the witness, it gives me
$./multiplier2 input.json witness.wtns
Illegal instruction: 4
Please advise how to fix?
Thanks
Since the snarkjs update, a lot of code in the tutorial has been broken, such as:
// error code:
snarkjs printconstraints -r circuit.r1cs -s circuit.sym
// right code
snarkjs r1cs print circuit.r1cs circuit.sym
// error code:
snarkjs setup -r circuit.r1cs
// right code:
snarkjs plonk setup circuit.r1cs pot12_final.ptau circuit_final.zkey
And the running order of snarkjs is no longer as it is in the tutorial, I'm glad to submit a pr to fix this bug, but I didn't find the repository for this tutorial, please tell me which repository can submit pr, I will solve these problems
happy to help
This is crucial for anyone who wants to use Circom in an automated way, bash scripts for example.
Currently, a workaround is to check that the required files have been generated (the .r1cs
file for instance). This is far from ideal.
I have this piece of code -
template Main(){
signal input in;
signal output out;
component num2bits[4], xor[3];
for(var i=0; i<4; i++)
{
num2bits[i] = Num2Bits(32);
if (i<3) xor[i] = XOR();
}
}
It is causing the compiler to panic while writing the cpp and js files -
template instances: 3
non-linear constraints: 131
linear constraints: 0
public inputs: 0
public outputs: 1
private inputs: 1
private outputs: 0
wires: 139
labels: 144
Written successfully: ./main.r1cs
Written successfully: ./main.sym
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', compiler/src/ir_processing/set_arena_size.rs:41:69
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Although, rewriting the code as following solves the problem -
template Main(){
signal input in;
signal output out;
component num2bits[4], xor[3];
for(var i=0; i<4; i++) num2bits[i] = Num2Bits(32);
for(var i=0; i<3; i++) xor[i] = XOR();
}
In b953bf9, @miguelis made circom forcibly exit on success, which makes many workflows (such as using the circom tool inside a script or when using it in WASM) break. It would probably be fine to forcibly exit with a code if there is an error but never should you forcibly exit with 0
on a success.
I tried removing the exit and circom hits an unreachable
in the code, so more fixes will need to be applied to make the code work correctly.
Hello,
I have the following minimal circuit that uses a hexadecimal number as an input from a json file:
pragma circom 2.0.0;
template POC() {
signal input a;
signal input b;
signal input c;
log(a);
log(b);
log(c);
}
component main = POC();
Using the following json as an input file:
{"a": "0x42", "b": 100, "c": "110"}
The circuit logs the following:
0
100
110
I am fairly certain hexadecimal numbers worked as an input in previous versions of circom. Is this functionality still supported, or is this now the intended behavior?
The docs [1] state that "using <--
and -->
is, in general, dangerous". Could someone please elaborate on the reason behind this statement?
Is it "safer" to use <==
instead of <--
followed by ===
?
Some students in crypto class (myself included) are curious about this. 🤓
[1]
circom/mkdocs/docs/circom-language/signals.md
Line 104 in 86a20b0
Hello,
I have encountered a bug while running this circom implementation of RSA.
You can find a proof of concept circuit and input here. You can reproduce it if you clone the repository and run:
circom poc.circom --c
cd poc_cpp/
make -j 8
./poc ../poc.json w.wtns
Generating a proof with the wasm witness calculator works as expected, and produces a valid proof. But calculating a witness with the cpp circuit crashes and throws the following assertion exception:
./poc ../poc.json w.wtns
poc: fr.cpp:166: void Fr_fail(): Assertion `false' failed.
[1] 249859 IOT instruction (core dumped) ./poc ../poc.json w.wtns
While debugging the issue, I found that it is most likely caused by the use of the array initialized on line 89. I tested a similar implementation that does not use the IsZero()
component, and therefore the array, but does pretty much the same operations as in IsZero()
, and the circuit generates a correct witness.
I initially thought it was connected to the way the index of the array was calculated, because when I log the operation that calculates the array index, it prints "0", while it should print "473". But even with a constant array size, it crashed with the unexpected assertion failed message.
However, I tried substituting the operation that calculates indexes of this array dynamically (var idx = (i - (base_len + 8)) / 8
on line 96) with a constant number that is decreased after each iteration of the loop, and then the incorrect assertion is no longer thrown.
It is worth noting that logging idx
prints the expected value. But I still think it might be related to the -
operation.
Let me know if you need more information.
Thanks in advance.
The following circuit fails with an error on a seemingly unrelated line:
template ItFails() {
signal output out1;
signal output out2;
out1 <== 1;
if ( out1 ) {
out2 <-- 1;
} else {
out2 <-- 1; // ERROR HERE: Exception caused by invalid assignment
}
}
Strangely, compiler doesn't complain at:
template ItFails() {
signal output out1;
signal output out2;
out1 <== 1;
if ( out1 ) {
out2 <-- 1;
}
}
It's unclear whether:
Witness generation fails for the MACI circuit sometimes and sometimes it succeeds with the exact same condition(environments, tools, step). Following logs are printed when it fails:
Illegal instruction (core dumped)
Error: Error executing ./zkeys/ProcessMessages_10-2-1-2_test /tmp/tmp-7501-O0FLciBuSEkX/input.json /tmp/tmp-7501-O0FLciBuSEkX/output.wtns
Run the following script on the new Ubuntu 21.04 instance. When it comes to Ubuntu 20.04, install glibc 2.33
by using this script.
#!/bin/bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
nvm install 16
nvm use 16
sudo apt-get update
sudo apt-get install --yes build-essential libgmp-dev libsodium-dev nlohmann-json3-dev nasm git
# Get rapidsnark
mkdir -p ~/rapidsnark/build
wget -O ~/rapidsnark/build/prover https://maci-devops-zkeys.s3.ap-northeast-2.amazonaws.com/rapidsnark-linux-amd64-1c137
chmod +x ~/rapidsnark/build/prover
# Get circom
mkdir -p ~/.local/bin
wget -O ~/.local/bin/circom https://maci-devops-zkeys.s3.ap-northeast-2.amazonaws.com/circom-linux-amd64-v2.0.3
chmod +x ~/.local/bin/circom
cd ~
git config --global url."https://github.com/".insteadOf git://github.com/
# Install MACI
git clone https://github.com/appliedzkp/maci.git
cd maci
git checkout v1
git reset --hard a069145cc339c92689c3c2793c70b1b93f208572
npm install
npm run bootstrap
npm run build
# Test
cd contracts
npm run compileSol
cd ~/maci/contracts/
nohup npx hardhat node \
--hostname 0.0.0.0 \
--port 8545 > /dev/null 2>&1 &
cd ~/maci/cli
mkdir -p zkeys
wget -O zkeys.tar.gz https://maci-devops.s3.ap-northeast-2.amazonaws.com/zkeys.tar.gz
tar -xzvf zkeys.tar.gz
chmod -R 777 zkeys
node build/index.js deployVkRegistry && \
node build/index.js setVerifyingKeys -s 10 -i 1 -m 2 -v 2 -b 1 \
-p ./zkeys/ProcessMessages_10-2-1-2_test.0.zkey \
-t ./zkeys/TallyVotes_10-1-2_test.0.zkey \
-k 0x8CdaF0CD259887258Bc13a92C0a6dA92698644C0
node build/index.js create \
-r 0x8CdaF0CD259887258Bc13a92C0a6dA92698644C0 && \
node ./build/index.js deployPoll -x 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \
-pk macipk.c974f4f168b79727ac98bfd53a65ea0b4e45dc2552fe73df9f8b51ebb0930330 \
-t 20 -g 25 -mv 25 -i 1 -m 2 -b 1 -v 2 && \
node ./build/index.js signup \
-p macipk.3e7bb2d7f0a1b7e980f1b6f363d1e3b7a12b9ae354c2cd60a9cfa9fd12917391 \
-x 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a && \
node build/index.js publish \
-p macipk.3e7bb2d7f0a1b7e980f1b6f363d1e3b7a12b9ae354c2cd60a9cfa9fd12917391 \
-sk macisk.fd7aa614ec4a82716ffc219c24fd7e7b52a2b63b5afb17e81c22fe21515539c \
-x 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \
-i 1 -v 0 -w 9 -n 1 -o 0
node build/index.js timeTravel -s 30 && \
node build/index.js mergeMessages -x 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a -o 0 && \
node build/index.js mergeSignups -x 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a -o 0 && \
rm -rf proofs tally.json
# Repeat tests until it fails
cat <<EOF | sh -c 'set -e
while true
do
node build/index.js genProofs -x 0xf204a4Ef082f5c04bB89F7D5E6568B796096735a \
-sk macisk.49953af3585856f539d194b46c82f4ed54ec508fb9b882940cbe68bbc57e59e \
-o 0 \
-r ~/rapidsnark/build/prover \
-wp ./zkeys/ProcessMessages_10-2-1-2_test \
-wt ./zkeys/TallyVotes_10-1-2_test \
-zp ./zkeys/ProcessMessages_10-2-1-2_test.0.zkey \
-zt ./zkeys/TallyVotes_10-1-2_test.0.zkey \
-t tally.json \
-f proofs
done'
EOF
OS: Ubuntu 21.04 (x86_64)
Circom: 2.0.3
The following input:
template T() {
component comp = T();
}
component main = T();
causes a stack overflow in the compiler.
I can't find out how the different optimizer settings (O1 and O2) work, other than diving into the code myself. I think it would be helpful to some users to understand how their circuit is being optimized.
Given this simple circuit
template C() {
signal input a;
signal input b;
b === 3;
}
component main = C();
The info of r1cs compiled by old js circom is
[INFO] snarkJS: Curve: bn-128
[INFO] snarkJS: # of Wires: 1
[INFO] snarkJS: # of Constraints: 0
[INFO] snarkJS: # of Private Inputs: 0
[INFO] snarkJS: # of Public Inputs: 0
[INFO] snarkJS: # of Outputs: 0
The info of r1cs compiled by new rust circom is
[INFO] snarkJS: Curve: bn-128
[INFO] snarkJS: # of Wires: 2
[INFO] snarkJS: # of Constraints: 0
[INFO] snarkJS: # of Private Inputs: 2
[INFO] snarkJS: # of Public Inputs: 0
[INFO] snarkJS: # of Outputs: 0
I guess it is better to remove unused signals as the old circom?
I was trying to follow the example from the official documentation https://docs.circom.io/getting-started/computing-the-witness/#computing-the-witness-with-c. I was able to compile the C++ witness calculator on Mac OS thanks to #12. However, when I tried to generate the witness I got an error:
zsh: illegal hardware instruction ./circuit input.json witness.wtns
The code to reproduce the issue is in the repo: alxkzmn/zk-wordle@5690ffc
Steps to reproduce:
cd circuit_cpp
make
./circuit input.json witness.wtns
I've been chasing this issue for a while now, trying to figure out why circom_tester is failing when I'm using temp files for circuits. For some reason, circom is removing a portion of the base file name, and circom_tester assumes a given file name.
echo "pragma circom 2.0.0; template foo () {} component main = foo();" > /tmp/test2021104-13814-o1so8j.x9v4k.circom
circom --wasm --sym --r1cs --output $(mktemp -d) /tmp/test2021104-13814-o1so8j.x9v4k.circom
Note the input file name, which is a format that common temp file generation libraries use (in this case node-temp)
template instances: 1
non-linear constraints: 0
linear constraints: 0
public inputs: 0
public outputs: 0
private inputs: 0
private outputs: 0
wires: 1
labels: 1
Written successfully: /tmp/tmp.xvLoOJQNqm/test2021104-13814-o1so8j.x9v4k.r1cs
Written successfully: /tmp/tmp.xvLoOJQNqm/test2021104-13814-o1so8j.x9v4k.sym
Written successfully: /tmp/tmp.xvLoOJQNqm/test2021104-13814-o1so8j.x9v4k_js/test2021104-13814-o1so8j.x9v4k.wasm
Everything went okay, circom safe
template instances: 1
non-linear constraints: 0
linear constraints: 0
public inputs: 0
public outputs: 0
private inputs: 0
private outputs: 0
wires: 1
labels: 1
Written successfully: /tmp/tmp.xvLoOJQNqm/test2021104-13814-o1so8j.r1cs
Written successfully: /tmp/tmp.xvLoOJQNqm/test2021104-13814-o1so8j.sym
Written successfully: /tmp/tmp.xvLoOJQNqm/test2021104-13814-o1so8j.x9v4k_js/test2021104-13814-o1so8j.wasm
Everything went okay, circom safe
Having a multi-line comment closed with **/
breaks circom, the errors shown may be misleading.
Working example:
pragma circom 2.0.0;
/*
*/
template test() {
signal input in;
signal output out;
out <== in * 2;
}
component main = test();
An example to reproduce the issue:
pragma circom 2.0.0;
/*
**/
template test() {
signal input in;
signal output out;
out <== in * 2;
}
component main = test();
In the example above, the displayed compilation error is error[P1001]: No main specified in the project structure
.
If a comment closed with **/
happens to be inside a template, the compiler seems to think the comment was never closed.
error[P1000]: UnrecognizedEOF { location: 38, expected: ["\"!\"", "\"(\"", "\"-\"", "\"[\"", "\"assert\"", "\"component\"", "\"for\"", "\"if\"", "\"log\"", "\"return\"", "\"signal\"", "\"var\"", "\"while\"", "\"{\"", "\"}\"", "\"~\"", "r#\"0x[0-9A-Fa-f]*\"#", "r#\"[$_]*[a-zA-Z][a-zA-Z$_0-9]*\"#", "r#\"[0-9]+\"#"] }
┌─ "/home/whyamiroot/test.circom":1:1
│
1 │ pragma circom 2.0.0;
│ ^ Invalid syntax
Here's an example to reproduce the error message above:
pragma circom 2.0.0;
template test() {
/*
**/
signal input in;
signal output out;
out <== in * 2;
}
Other conditions that I tried to trigger this issue:
/**/
- doesn't trigger/***/
- triggers// ...
- doesn't trigger with any combination of asterisks and slashes/*
, *
, and */
on separate lines - doesn't triggerEnvironment:
--r1cs --wasm --sym
Hello everyone~ 😀
These days, I have been studying about arithmetic in Circom, in order to implement UQ number with saturation arithmetic.
But some weird outcomes really bothered me.
(1) Why did the relational operator x > y
fail?
var p_minus_one = 21888242871839275222246405745257275088548364400416034343698204186575808495616;
assert(p_minus_one > 0); // I got compiled error msg: error[T3001]: False assert reached
According to the docs, relational operators are based on a math function val(z)
.
In this case, p_minus_one
would be val(p_minus_one) = 2188...5616
, which is literally GLOBAL_FIELD_P
minus integer one.
Hence, the condition p_minus_one > 0
should be hold and passed the assertion.
I believe that there must be something I have not understood, so I inaccurately think about how the above codes work.
(2) Is it available to access GLOBAL_FIELD_P
in Circom language?
It doesn't a big problem.
I can do the some things like the above which just hard-coded numbers.
But I think there must be a more elegant way to achieve this task.
Thanks for anyone willing to reply me or give me the clues. 🙏❤
circom/constraint_generation/src/execute.rs
Line 160 in 7e59274
Got a panic on this kind of code. (I forget to give a value to N). Maybe a better error message is required.
var N;
signal input in[N];
Hi!I'm a novice about circom.
I want to modify GLOBAL_FIELD_P, but don't know how to do it.
Can someone help me with this problem with an example?This is important to my research.
For circuits larger than ~1M constraints, it would be helpful if the witness generation exited with error when it detects a proof that is too large for wasm, and suggests compiling in C++ instead.
Hello circom people! I've tried to find a similar issue or a documentation for my case, but didn't succeed. Please help 🥲
I'm trying to create a simple circuit which has two inputs: secret
(private) and wallet
(public). In this circuit i calculate mimc hash for wallet + secret
and secret
. But when i try to verify it, i get the following error:
[ERROR] snarkJS: Error: Invalid witness length. Circuit: 276, witness: 549
But if i calculate only one hash with single output it works ok. What am i doing wrong?
This is my circuit:
pragma circom 2.0.7;
include "../../node_modules/circomlib/circuits/mimcsponge.circom";
template Hash() {
signal input preimage;
signal output out;
component mimc = MiMCSponge(1, 91, 1); // (nInputs, nRounds, nOutputs)
mimc.k <== 1;
mimc.ins[0] <== preimage;
out <== mimc.outs[0];
}
template Main() {
signal input secret;
signal input wallet;
signal output outs[2];
component walletSecretHash = Hash();
walletSecretHash.preimage <== secret + wallet;
outs[0] <== walletSecretHash.out;
component secretHash = Hash();
secretHash.preimage <== secret;
outs[1] <== secretHash.out;
}
component main {public [wallet]} = Main();
Hello !
I'm trying to verify a commitment of a rescue function. The problem is when I write the commit in the inputs, it's directly modified by the circuit without reasons (the value is less than bn128's elliptic curve group order).
Here is my simple circuit :
pragma circom 2.0.0;
include "./rescue.circom";
template test(){
signal input in;
signal input commit;
signal output out;component hash = rescue(1); hash.entree[0] <== in; out <== hash.sortie;
}
component main {public [commit]} = test();
This is what the public file and the input files looks like :
input : 15522569492626651840248353495983403506074603540762064124302882378518279710261 (commit)
public : 15522569492626651840248353495983403506074603540762064124302882378518279710261 (hash result)
and 15522569492626650996385962682425768945933593965259583670031600469260676104192 (wrong copy of my input)
Can someone tell me if it's an error from me or not?
Thomas
Thanks for this repo! I am very excited to see that you are going to add recursive plonk support.
Can you please share the timeline of adding recursive SNARK support?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.