Closed wzmuda closed 8 months ago
Hi,
Yes, Compile()
can mutate the circuit - this happens for example when we use field emulation where we compute the overflows. You should by default instantiate different Circuit
instances for compilation and witness assignment.
There is another issue if you use already assigned Circuit
for compile and witness assignment. When you have set X=3
by doing circuit := commitmentCircuit{X: 3}
, then the compiler can deduce that in this circuit X
is a constant and perform different logic (for R1CS we encode the value as a constant and in PLONK we use another selector). Now, if you try to assign witness to the same variable, then witness assignment doesn't work as the variable is optimized out.
If you want to be able to always assign X
as a witness, then you should not compile with X
set to non-nil value.
For example, see KZG recursion examples:
Description
When
frontend.Compile(..., &circuit)
is called on acircuit := myCircuitDefinition{ ... }
object, subsequent call tofrontend.NewWitness(&circuit, ...)
panics withcan't set fr.Element from type expr.Term
. I prepared a test case illustrating the problem. The test fails for every curve. I believe it shouldn't fail regardless the order in whichCompile()
andNewWitness()
are called.Here's the code snippet in case the link above stops working one day:
Expected Behavior
The proposed test case doesn't fail. It doesn't matter if
NewWitness()
is called before or afterCompile()
.Actual Behavior
The proposed test case fails.
NewWitness()
must be called beforeCompile()
to avoid gnark panicking.Possible Fix
Steps to Reproduce
backend/plonk/plonk_test.go
Compile()
andNewWitness()
are calledContext
I was writing a simple application proving and verifying a trivial circuit using Plonk and KZG. I was getting
panic()
inNewWitness
so I played around and I noticed that the problem goes away if I generate private witness before I compile the circuit.To be frank I'm not 100% sure this is a bug. Another way to avoid the problem is to call
Compile()
on one instance of the circuit (e.g. on an empty one, like&myCircuitDefinition{}
) andNewWitness()
on another. On the other hand I don't see a reasonCompile()
would mutate the object so I guess this may be a bug.Your Environment