From 3c6d6f7ee8bd21384e2bece4e1b5d330d899bfa5 Mon Sep 17 00:00:00 2001
From: Marius van der Wijden <m.vanderwijden@live.de>
Date: Thu, 2 Jun 2022 13:13:28 +0200
Subject: [PATCH] tests/fuzzers/bls12381: Add BLST to fuzzing support (#24249)

* tests/fuzzers/bls12381: added blst library

* go.mod: added blst dependency

* tests/fuzzers/bls12381: stuff

* tests/fuzzers/bls12381: added blst to pairing fuzzer
---
 go.mod                                  |  1 +
 go.sum                                  |  6 +++
 tests/fuzzers/bls12381/bls12381_fuzz.go | 64 ++++++++++++++++++++-----
 3 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/go.mod b/go.mod
index 9e6afee91..11c46e58d 100644
--- a/go.mod
+++ b/go.mod
@@ -58,6 +58,7 @@ require (
 	github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
 	github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4
 	github.com/stretchr/testify v1.7.0
+	github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344 // indirect
 	github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
 	github.com/tklauser/go-sysconf v0.3.5 // indirect
 	github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
diff --git a/go.sum b/go.sum
index 0d793209b..135d85275 100644
--- a/go.sum
+++ b/go.sum
@@ -384,6 +384,12 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/supranational/blst v0.3.6 h1:a24cPQB0qYpXPMZx177aapCM50/YrTMt/TKAUa7TzdM=
+github.com/supranational/blst v0.3.6/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
+github.com/supranational/blst v0.3.7 h1:QObqTzlW30Z947JMe0MH12mVhFOxgtDapuWvPvCEGDE=
+github.com/supranational/blst v0.3.7/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
+github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344 h1:m+8fKfQwCAy1QjzINvKe/pYtLjo2dl59x2w9YSEJxuY=
+github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
 github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
diff --git a/tests/fuzzers/bls12381/bls12381_fuzz.go b/tests/fuzzers/bls12381/bls12381_fuzz.go
index b283ed11f..c511c6501 100644
--- a/tests/fuzzers/bls12381/bls12381_fuzz.go
+++ b/tests/fuzzers/bls12381/bls12381_fuzz.go
@@ -30,19 +30,20 @@ import (
 	"github.com/consensys/gnark-crypto/ecc/bls12-381/fp"
 	"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
 	"github.com/ethereum/go-ethereum/crypto/bls12381"
+	blst "github.com/supranational/blst/bindings/go"
 )
 
 func FuzzCrossPairing(data []byte) int {
 	input := bytes.NewReader(data)
 
 	// get random G1 points
-	kpG1, cpG1, err := getG1Points(input)
+	kpG1, cpG1, blG1, err := getG1Points(input)
 	if err != nil {
 		return 0
 	}
 
 	// get random G2 points
-	kpG2, cpG2, err := getG2Points(input)
+	kpG2, cpG2, blG2, err := getG2Points(input)
 	if err != nil {
 		return 0
 	}
@@ -63,6 +64,15 @@ func FuzzCrossPairing(data []byte) int {
 		panic("pairing mismatch gnark / geth ")
 	}
 
+	var b []byte
+	ctx := blst.PairingCtx(false, b)
+	// compute pairing using blst
+	blst.PairingRawAggregate(ctx, blG2, blG1)
+	blstResult := blst.PairingAsFp12(ctx)
+	if !(bytes.Equal(blstResult.ToBendian(), bls12381.NewGT().ToBytes(kResult))) {
+		panic("pairing mismatch blst / geth ")
+	}
+
 	return 1
 }
 
@@ -70,13 +80,13 @@ func FuzzCrossG1Add(data []byte) int {
 	input := bytes.NewReader(data)
 
 	// get random G1 points
-	kp1, cp1, err := getG1Points(input)
+	kp1, cp1, bl1, err := getG1Points(input)
 	if err != nil {
 		return 0
 	}
 
 	// get random G1 points
-	kp2, cp2, err := getG1Points(input)
+	kp2, cp2, bl2, err := getG1Points(input)
 	if err != nil {
 		return 0
 	}
@@ -96,6 +106,11 @@ func FuzzCrossG1Add(data []byte) int {
 		panic("G1 point addition mismatch gnark / geth ")
 	}
 
+	bl3 := blst.P1AffinesAdd([]*blst.P1Affine{bl1, bl2})
+	if !(bytes.Equal(cp.Marshal(), bl3.Serialize())) {
+		panic("G1 point addition mismatch blst / geth ")
+	}
+
 	return 1
 }
 
@@ -103,13 +118,13 @@ func FuzzCrossG2Add(data []byte) int {
 	input := bytes.NewReader(data)
 
 	// get random G2 points
-	kp1, cp1, err := getG2Points(input)
+	kp1, cp1, bl1, err := getG2Points(input)
 	if err != nil {
 		return 0
 	}
 
 	// get random G2 points
-	kp2, cp2, err := getG2Points(input)
+	kp2, cp2, bl2, err := getG2Points(input)
 	if err != nil {
 		return 0
 	}
@@ -129,6 +144,11 @@ func FuzzCrossG2Add(data []byte) int {
 		panic("G2 point addition mismatch gnark / geth ")
 	}
 
+	bl3 := blst.P2AffinesAdd([]*blst.P2Affine{bl1, bl2})
+	if !(bytes.Equal(cp.Marshal(), bl3.Serialize())) {
+		panic("G1 point addition mismatch blst / geth ")
+	}
+
 	return 1
 }
 
@@ -148,7 +168,7 @@ func FuzzCrossG1MultiExp(data []byte) int {
 			break
 		}
 		// get a random G1 point as basis
-		kp1, cp1, err := getG1Points(input)
+		kp1, cp1, _, err := getG1Points(input)
 		if err != nil {
 			break
 		}
@@ -183,11 +203,11 @@ func FuzzCrossG1MultiExp(data []byte) int {
 	return 1
 }
 
-func getG1Points(input io.Reader) (*bls12381.PointG1, *gnark.G1Affine, error) {
+func getG1Points(input io.Reader) (*bls12381.PointG1, *gnark.G1Affine, *blst.P1Affine, error) {
 	// sample a random scalar
 	s, err := randomScalar(input, fp.Modulus())
 	if err != nil {
-		return nil, nil, err
+		return nil, nil, nil, err
 	}
 
 	// compute a random point
@@ -206,14 +226,23 @@ func getG1Points(input io.Reader) (*bls12381.PointG1, *gnark.G1Affine, error) {
 		panic("bytes(gnark.G1) != bytes(geth.G1)")
 	}
 
-	return kp, cp, nil
+	// marshal gnark point -> blst point
+	var p1 *blst.P1Affine
+	var scalar *blst.Scalar
+	scalar.Deserialize(s.Bytes())
+	p1.From(scalar)
+	if !bytes.Equal(p1.Serialize(), cpBytes) {
+		panic("bytes(blst.G1) != bytes(geth.G1)")
+	}
+
+	return kp, cp, p1, nil
 }
 
-func getG2Points(input io.Reader) (*bls12381.PointG2, *gnark.G2Affine, error) {
+func getG2Points(input io.Reader) (*bls12381.PointG2, *gnark.G2Affine, *blst.P2Affine, error) {
 	// sample a random scalar
 	s, err := randomScalar(input, fp.Modulus())
 	if err != nil {
-		return nil, nil, err
+		return nil, nil, nil, err
 	}
 
 	// compute a random point
@@ -232,7 +261,16 @@ func getG2Points(input io.Reader) (*bls12381.PointG2, *gnark.G2Affine, error) {
 		panic("bytes(gnark.G2) != bytes(geth.G2)")
 	}
 
-	return kp, cp, nil
+	// marshal gnark point -> blst point
+	var p2 *blst.P2Affine
+	var scalar *blst.Scalar
+	scalar.Deserialize(s.Bytes())
+	p2.From(scalar)
+	if !bytes.Equal(p2.Serialize(), cpBytes) {
+		panic("bytes(blst.G2) != bytes(geth.G2)")
+	}
+
+	return kp, cp, p2, nil
 }
 
 func randomScalar(r io.Reader, max *big.Int) (k *big.Int, err error) {