github.com/phillinzzz/newBsc@v1.1.6/tests/fuzzers/bls12381/bls12381_fuzz.go (about)

     1  // Copyright 2021 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // +build gofuzz
    18  
    19  package bls
    20  
    21  import (
    22  	"bytes"
    23  	"crypto/rand"
    24  	"fmt"
    25  	"io"
    26  	"math/big"
    27  
    28  	gnark "github.com/consensys/gnark-crypto/ecc/bls12-381"
    29  	"github.com/consensys/gnark-crypto/ecc/bls12-381/fp"
    30  	"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
    31  	"github.com/phillinzzz/newBsc/crypto/bls12381"
    32  )
    33  
    34  func FuzzCrossPairing(data []byte) int {
    35  	input := bytes.NewReader(data)
    36  
    37  	// get random G1 points
    38  	kpG1, cpG1, err := getG1Points(input)
    39  	if err != nil {
    40  		return 0
    41  	}
    42  
    43  	// get random G2 points
    44  	kpG2, cpG2, err := getG2Points(input)
    45  	if err != nil {
    46  		return 0
    47  	}
    48  
    49  	// compute pairing using geth
    50  	engine := bls12381.NewPairingEngine()
    51  	engine.AddPair(kpG1, kpG2)
    52  	kResult := engine.Result()
    53  
    54  	// compute pairing using gnark
    55  	cResult, err := gnark.Pair([]gnark.G1Affine{*cpG1}, []gnark.G2Affine{*cpG2})
    56  	if err != nil {
    57  		panic(fmt.Sprintf("gnark/bls12381 encountered error: %v", err))
    58  	}
    59  
    60  	// compare result
    61  	if !(bytes.Equal(cResult.Marshal(), bls12381.NewGT().ToBytes(kResult))) {
    62  		panic("pairing mismatch gnark / geth ")
    63  	}
    64  
    65  	return 1
    66  }
    67  
    68  func FuzzCrossG1Add(data []byte) int {
    69  	input := bytes.NewReader(data)
    70  
    71  	// get random G1 points
    72  	kp1, cp1, err := getG1Points(input)
    73  	if err != nil {
    74  		return 0
    75  	}
    76  
    77  	// get random G1 points
    78  	kp2, cp2, err := getG1Points(input)
    79  	if err != nil {
    80  		return 0
    81  	}
    82  
    83  	// compute kp = kp1 + kp2
    84  	g1 := bls12381.NewG1()
    85  	kp := bls12381.PointG1{}
    86  	g1.Add(&kp, kp1, kp2)
    87  
    88  	// compute cp = cp1 + cp2
    89  	_cp1 := new(gnark.G1Jac).FromAffine(cp1)
    90  	_cp2 := new(gnark.G1Jac).FromAffine(cp2)
    91  	cp := new(gnark.G1Affine).FromJacobian(_cp1.AddAssign(_cp2))
    92  
    93  	// compare result
    94  	if !(bytes.Equal(cp.Marshal(), g1.ToBytes(&kp))) {
    95  		panic("G1 point addition mismatch gnark / geth ")
    96  	}
    97  
    98  	return 1
    99  }
   100  
   101  func FuzzCrossG2Add(data []byte) int {
   102  	input := bytes.NewReader(data)
   103  
   104  	// get random G2 points
   105  	kp1, cp1, err := getG2Points(input)
   106  	if err != nil {
   107  		return 0
   108  	}
   109  
   110  	// get random G2 points
   111  	kp2, cp2, err := getG2Points(input)
   112  	if err != nil {
   113  		return 0
   114  	}
   115  
   116  	// compute kp = kp1 + kp2
   117  	g2 := bls12381.NewG2()
   118  	kp := bls12381.PointG2{}
   119  	g2.Add(&kp, kp1, kp2)
   120  
   121  	// compute cp = cp1 + cp2
   122  	_cp1 := new(gnark.G2Jac).FromAffine(cp1)
   123  	_cp2 := new(gnark.G2Jac).FromAffine(cp2)
   124  	cp := new(gnark.G2Affine).FromJacobian(_cp1.AddAssign(_cp2))
   125  
   126  	// compare result
   127  	if !(bytes.Equal(cp.Marshal(), g2.ToBytes(&kp))) {
   128  		panic("G2 point addition mismatch gnark / geth ")
   129  	}
   130  
   131  	return 1
   132  }
   133  
   134  func FuzzCrossG1MultiExp(data []byte) int {
   135  	var (
   136  		input        = bytes.NewReader(data)
   137  		gethScalars  []*big.Int
   138  		gnarkScalars []fr.Element
   139  		gethPoints   []*bls12381.PointG1
   140  		gnarkPoints  []gnark.G1Affine
   141  	)
   142  	// n random scalars (max 17)
   143  	for i := 0; i < 17; i++ {
   144  		// note that geth/crypto/bls12381 works only with scalars <= 32bytes
   145  		s, err := randomScalar(input, fr.Modulus())
   146  		if err != nil {
   147  			break
   148  		}
   149  		// get a random G1 point as basis
   150  		kp1, cp1, err := getG1Points(input)
   151  		if err != nil {
   152  			break
   153  		}
   154  		gethScalars = append(gethScalars, s)
   155  		var gnarkScalar = &fr.Element{}
   156  		gnarkScalar = gnarkScalar.SetBigInt(s).FromMont()
   157  		gnarkScalars = append(gnarkScalars, *gnarkScalar)
   158  
   159  		gethPoints = append(gethPoints, new(bls12381.PointG1).Set(kp1))
   160  		gnarkPoints = append(gnarkPoints, *cp1)
   161  	}
   162  	if len(gethScalars) == 0{
   163  		return 0
   164  	}
   165  	// compute multi exponentiation
   166  	g1 := bls12381.NewG1()
   167  	kp := bls12381.PointG1{}
   168  	if _, err := g1.MultiExp(&kp, gethPoints, gethScalars); err != nil {
   169  		panic(fmt.Sprintf("G1 multi exponentiation errored (geth): %v", err))
   170  	}
   171  	// note that geth/crypto/bls12381.MultiExp mutates the scalars slice (and sets all the scalars to zero)
   172  
   173  	// gnark multi exp
   174  	cp := new(gnark.G1Affine)
   175  	cp.MultiExp(gnarkPoints, gnarkScalars)
   176  
   177  	// compare result
   178  	if !(bytes.Equal(cp.Marshal(), g1.ToBytes(&kp))) {
   179  		panic("G1 multi exponentiation mismatch gnark / geth ")
   180  	}
   181  
   182  	return 1
   183  }
   184  
   185  func getG1Points(input io.Reader) (*bls12381.PointG1, *gnark.G1Affine, error) {
   186  	// sample a random scalar
   187  	s, err := randomScalar(input, fp.Modulus())
   188  	if err != nil {
   189  		return nil, nil, err
   190  	}
   191  
   192  	// compute a random point
   193  	cp := new(gnark.G1Affine)
   194  	_, _, g1Gen, _ := gnark.Generators()
   195  	cp.ScalarMultiplication(&g1Gen, s)
   196  	cpBytes := cp.Marshal()
   197  
   198  	// marshal gnark point -> geth point
   199  	g1 := bls12381.NewG1()
   200  	kp, err := g1.FromBytes(cpBytes)
   201  	if err != nil {
   202  		panic(fmt.Sprintf("Could not marshal gnark.G1 -> geth.G1: %v", err))
   203  	}
   204  	if !bytes.Equal(g1.ToBytes(kp), cpBytes) {
   205  		panic("bytes(gnark.G1) != bytes(geth.G1)")
   206  	}
   207  
   208  	return kp, cp, nil
   209  }
   210  
   211  func getG2Points(input io.Reader) (*bls12381.PointG2, *gnark.G2Affine, error) {
   212  	// sample a random scalar
   213  	s, err := randomScalar(input, fp.Modulus())
   214  	if err != nil {
   215  		return nil, nil, err
   216  	}
   217  
   218  	// compute a random point
   219  	cp := new(gnark.G2Affine)
   220  	_, _, _, g2Gen := gnark.Generators()
   221  	cp.ScalarMultiplication(&g2Gen, s)
   222  	cpBytes := cp.Marshal()
   223  
   224  	// marshal gnark point -> geth point
   225  	g2 := bls12381.NewG2()
   226  	kp, err := g2.FromBytes(cpBytes)
   227  	if err != nil {
   228  		panic(fmt.Sprintf("Could not marshal gnark.G2 -> geth.G2: %v", err))
   229  	}
   230  	if !bytes.Equal(g2.ToBytes(kp), cpBytes) {
   231  		panic("bytes(gnark.G2) != bytes(geth.G2)")
   232  	}
   233  
   234  	return kp, cp, nil
   235  }
   236  
   237  func randomScalar(r io.Reader, max *big.Int) (k *big.Int, err error) {
   238  	for {
   239  		k, err = rand.Int(r, max)
   240  		if err != nil || k.Sign() > 0 {
   241  			return
   242  		}
   243  	}
   244  }