Closed readygo67 closed 8 months ago
I think this issue is that we currently do not support non-commitment version of the proofs to be verified in-circuit. It is related to some optimizations we have which use incomplete formulas and leading to unexpected results when one of the points in a multi-scalar multiplication is zero. In case we do not have commitments there is such an input (a polynomial commitment to the commitment wire).
I'll keep it open, rewording.
Thanks for reporting.
@yelhousni confirmed that it was still about BN254-over-BN254 even when the circuit has a commitment. Will investigate.
It was a problem with short-hash construction for recursion. It is fixed in https://github.com/Consensys/gnark/pull/1008.
Thanks for reporting.
great work!
Description
In plonk recursion, if the inner /outer circuit both use BN254 curve, outer circuit prove fail, the failure message is listed below. If inner/outer circuit use different curve, prove success.
Expected Behavior
Prove success
Actual Behavior
Prove failed with constraint is not satisfied.
Steps to Reproduce
func (c InnerCircuitNative) Define(api frontend.API) error { // prove that PQ == N res := api.Mul(c.P, c.Q) api.AssertIsEqual(res, c.N) // we must also enforce that P != 1 and Q != 1 api.AssertIsDifferent(c.P, 1) api.AssertIsDifferent(c.Q, 1) return nil }
// computeInnerProof computes the proof for the inner circuit we want to verify // recursively. In this example the PLONK keys are generated on the fly, but // in practice should be genrated once and using MPC. func computeInnerProof(field, outer *big.Int) (constraint.ConstraintSystem, native_plonk.VerifyingKey, witness.Witness, native_plonk.Proof) { innerCcs, err := frontend.Compile(field, scs.NewBuilder, &InnerCircuitNative{}) if err != nil { panic(err) } // NB! UNSAFE! Use MPC. srs, srsLagrange, err := unsafekzg.NewSRS(innerCcs) if err != nil { panic(err) }
}
// OuterCircuit is the generic outer circuit which can verify PLONK proofs // using field emulation or 2-chains of curves. type OuterCircuit[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GtEl algebra.GtElementT] struct { Proof plonk.Proof[FR, G1El, G2El] VerifyingKey plonk.VerifyingKey[FR, G1El, G2El]
gnark:"-"
// constant verification key InnerWitness plonk.Witness[FR]gnark:",public"
}func (c *OuterCircuit[FR, G1El, G2El, GtEl]) Define(api frontend.API) error { verifier, err := plonk.NewVerifierFR, G1El, G2El, GtEl if err != nil { return fmt.Errorf("new verifier: %w", err) } err = verifier.AssertProof(c.VerifyingKey, c.Proof, c.InnerWitness) return err }
func TestPlonkRecursion_BN254_BN254(t *testing.T) { // compute the proof which we want to verify recursively innerCcs, innerVK, innerWitness, innerProof := computeInnerProof(ecc.BN254.ScalarField(), ecc.BN254.ScalarField())
}