add cross fuzzer for g2 multiexp

This commit is contained in:
Jared Wasinger 2024-11-08 18:17:26 +09:00
parent 6c3db71f7f
commit da561aa24a
3 changed files with 74 additions and 0 deletions

View file

@ -212,6 +212,10 @@ compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
FuzzCrossG2Add fuzz_cross_g2_add \
$repo/tests/fuzzers/bls12381/bls12381_test.go
compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
FuzzCrossG2MultiExp fuzz_cross_g2_multiexp \
$repo/tests/fuzzers/bls12381/bls12381_test.go
compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
FuzzCrossPairing fuzz_cross_pairing\
$repo/tests/fuzzers/bls12381/bls12381_test.go

View file

@ -275,6 +275,57 @@ func fuzzCrossG2Mul(data []byte) int {
return 1
}
func fuzzCrossG2MultiExp(data []byte) int {
var (
input = bytes.NewReader(data)
gnarkScalars []fr.Element
gnarkPoints []gnark.G2Affine
blstScalars []*blst.Scalar
blstPoints []*blst.P2Affine
)
// n random scalars (max 17)
for i := 0; i < 17; i++ {
// note that geth/crypto/bls12381 works only with scalars <= 32bytes
s, err := randomScalar(input, fr.Modulus())
if err != nil {
break
}
// get a random G1 point as basis
cp1, bl1, err := getG2Points(input)
if err != nil {
break
}
gnarkScalar := new(fr.Element).SetBigInt(s)
gnarkScalars = append(gnarkScalars, *gnarkScalar)
gnarkPoints = append(gnarkPoints, *cp1)
blstScalar := new(blst.Scalar).FromBEndian(common.LeftPadBytes(s.Bytes(), 32))
blstScalars = append(blstScalars, blstScalar)
blstPoints = append(blstPoints, bl1)
}
if len(gnarkScalars) == 0 || len(gnarkScalars) != len(gnarkPoints) {
return 0
}
// gnark multi exp
cp := new(gnark.G2Affine)
cp.MultiExp(gnarkPoints, gnarkScalars, ecc.MultiExpConfig{})
expectedGnark := multiExpG2Gnark(gnarkPoints, gnarkScalars)
if !bytes.Equal(cp.Marshal(), expectedGnark.Marshal()) {
panic("g1 multi exponentiation mismatch")
}
// blst multi exp
expectedBlst := blst.P2AffinesMult(blstPoints, blstScalars, 256).ToAffine()
if !bytes.Equal(cp.Marshal(), expectedBlst.Serialize()) {
panic("g1 multi exponentiation mismatch, gnark/blst")
}
return 1
}
func getG1Points(input io.Reader) (*gnark.G1Affine, *blst.P1Affine, error) {
// sample a random scalar
s, err := randomScalar(input, fp.Modulus())
@ -344,3 +395,16 @@ func multiExpG1Gnark(gs []gnark.G1Affine, scalars []fr.Element) gnark.G1Affine {
}
return res
}
// multiExpG1Gnark is a naive implementation of G1 multi-exponentiation
func multiExpG2Gnark(gs []gnark.G2Affine, scalars []fr.Element) gnark.G2Affine {
res := gnark.G2Affine{}
for i := 0; i < len(gs); i++ {
tmp := new(gnark.G2Affine)
sb := scalars[i].Bytes()
scalarBytes := new(big.Int).SetBytes(sb[:])
tmp.ScalarMultiplication(&gs[i], scalarBytes)
res.Add(&res, tmp)
}
return res
}

View file

@ -27,6 +27,12 @@ func FuzzCrossPairing(f *testing.F) {
})
}
func FuzzCrossG2MultiExp(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
fuzzCrossG2MultiExp(data)
})
}
func FuzzCrossG1Add(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
fuzzCrossG1Add(data)