Skip to content

Commit 6e2fc62

Browse files
authored
fix: KZG proof verification for edge cases (#1567)
1 parent 97c0892 commit 6e2fc62

File tree

2 files changed

+54
-32
lines changed

2 files changed

+54
-32
lines changed

std/commitments/kzg/verifier.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,14 +426,15 @@ func (v *Verifier[FR, G1El, G2El, GTEl]) CheckOpeningProof(commitment Commitment
426426

427427
// [f(a)]G1 + [-a]([H(α)]G₁) = [f(a) - a*H(α)]G₁
428428
pointNeg := v.scalarApi.Neg(&point)
429-
totalG1, err := v.curve.MultiScalarMul([]*G1El{&vk.G1, &proof.Quotient}, []*emulated.Element[FR]{&proof.ClaimedValue, pointNeg})
429+
// we use complete arithmetic to allow verifying commitment to 0 polynomial.
430+
totalG1, err := v.curve.MultiScalarMul([]*G1El{&vk.G1, &proof.Quotient}, []*emulated.Element[FR]{&proof.ClaimedValue, pointNeg}, algopts.WithCompleteArithmetic())
430431
if err != nil {
431432
return fmt.Errorf("check opening proof: %w", err)
432433
}
433434

434435
// [f(a) - a*H(α)]G₁ + [-f(α)]G₁ = [f(a) - f(α) - a*H(α)]G₁
435436
commitmentNeg := v.curve.Neg(&commitment.G1El)
436-
totalG1 = v.curve.Add(totalG1, commitmentNeg)
437+
totalG1 = v.curve.AddUnified(totalG1, commitmentNeg)
437438

438439
// e([f(a)-f(α)-a*H(α)]G₁], G₂).e([H(α)]G₁, [α]G₂) == 1
439440
if err := v.pairing.PairingCheck(

std/commitments/kzg/verifier_test.go

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -110,39 +110,60 @@ func TestKZGVerificationEmulated2(t *testing.T) {
110110
srs, err := kzg_bls12381.NewSRS(kzgSize, alpha)
111111
assert.NoError(err)
112112

113-
f := make([]fr_bls12381.Element, polynomialSize)
114-
for i := range f {
115-
f[i].SetRandom()
116-
}
117-
118-
com, err := kzg_bls12381.Commit(f, srs.Pk)
119-
assert.NoError(err)
120-
121-
var point fr_bls12381.Element
122-
point.SetRandom()
123-
proof, err := kzg_bls12381.Open(f, point, srs.Pk)
124-
assert.NoError(err)
113+
check := func(assert *test.Assert, f fr_bls12381.Vector, point fr_bls12381.Element) {
114+
com, err := kzg_bls12381.Commit(f, srs.Pk)
115+
assert.NoError(err)
116+
proof, err := kzg_bls12381.Open(f, point, srs.Pk)
117+
assert.NoError(err)
118+
if err = kzg_bls12381.Verify(&com, &proof, point, srs.Vk); err != nil {
119+
t.Fatal("verify proof", err)
120+
}
121+
wCmt, err := ValueOfCommitment[sw_bls12381.G1Affine](com)
122+
assert.NoError(err)
123+
wVk, err := ValueOfVerifyingKey[sw_bls12381.G1Affine, sw_bls12381.G2Affine](srs.Vk)
124+
assert.NoError(err)
125+
wProof, err := ValueOfOpeningProof[sw_bls12381.ScalarField, sw_bls12381.G1Affine](proof)
126+
assert.NoError(err)
127+
wPt, err := ValueOfScalar[sw_bls12381.ScalarField](point)
128+
assert.NoError(err)
125129

126-
if err = kzg_bls12381.Verify(&com, &proof, point, srs.Vk); err != nil {
127-
t.Fatal("verify proof", err)
130+
assignment := KZGVerificationCircuit[sw_bls12381.ScalarField, sw_bls12381.G1Affine, sw_bls12381.G2Affine, sw_bls12381.GTEl]{
131+
VerifyingKey: wVk,
132+
Commitment: wCmt,
133+
OpeningProof: wProof,
134+
Point: wPt,
135+
}
136+
assert.CheckCircuit(&KZGVerificationCircuit[sw_bls12381.ScalarField, sw_bls12381.G1Affine, sw_bls12381.G2Affine, sw_bls12381.GTEl]{}, test.WithValidAssignment(&assignment))
128137
}
129138

130-
wCmt, err := ValueOfCommitment[sw_bls12381.G1Affine](com)
131-
assert.NoError(err)
132-
wProof, err := ValueOfOpeningProof[sw_bls12381.ScalarField, sw_bls12381.G1Affine](proof)
133-
assert.NoError(err)
134-
wVk, err := ValueOfVerifyingKey[sw_bls12381.G1Affine, sw_bls12381.G2Affine](srs.Vk)
135-
assert.NoError(err)
136-
wPt, err := ValueOfScalar[sw_bls12381.ScalarField](point)
137-
assert.NoError(err)
138-
139-
assignment := KZGVerificationCircuit[sw_bls12381.ScalarField, sw_bls12381.G1Affine, sw_bls12381.G2Affine, sw_bls12381.GTEl]{
140-
VerifyingKey: wVk,
141-
Commitment: wCmt,
142-
OpeningProof: wProof,
143-
Point: wPt,
144-
}
145-
assert.CheckCircuit(&KZGVerificationCircuit[sw_bls12381.ScalarField, sw_bls12381.G1Affine, sw_bls12381.G2Affine, sw_bls12381.GTEl]{}, test.WithValidAssignment(&assignment))
139+
assert.Run(func(assert *test.Assert) {
140+
f := make(fr_bls12381.Vector, polynomialSize)
141+
f.MustSetRandom()
142+
var point fr_bls12381.Element
143+
point.MustSetRandom()
144+
check(assert, f, point)
145+
})
146+
assert.Run(func(assert *test.Assert) {
147+
f := make(fr_bls12381.Vector, polynomialSize)
148+
var point fr_bls12381.Element
149+
point.MustSetRandom()
150+
check(assert, f, point)
151+
}, "case=zero_polynomial")
152+
assert.Run(func(assert *test.Assert) {
153+
f := make(fr_bls12381.Vector, polynomialSize)
154+
f.MustSetRandom()
155+
var point fr_bls12381.Element
156+
point.SetZero()
157+
check(assert, f, point)
158+
}, "case=zero_point")
159+
assert.Run(func(assert *test.Assert) {
160+
f := make(fr_bls12381.Vector, polynomialSize)
161+
f.MustSetRandom()
162+
f[0].SetZero()
163+
var point fr_bls12381.Element
164+
point.SetZero()
165+
check(assert, f, point)
166+
}, "case=zero_first_coeff_zero_point")
146167
}
147168

148169
func TestKZGVerificationEmulated3(t *testing.T) {

0 commit comments

Comments
 (0)