github.com/cryptotooltop/go-ethereum@v0.0.0-20231103184714-151d1922f3e5/tests/fuzzers/bn256/bn256_fuzz.go (about)

     1  // Copyright 2018 Péter Szilágyi. All rights reserved.
     2  // Use of this source code is governed by a BSD-style license that can be found
     3  // in the LICENSE file.
     4  
     5  //go:build gofuzz
     6  // +build gofuzz
     7  
     8  package bn256
     9  
    10  import (
    11  	"bytes"
    12  	"fmt"
    13  	"io"
    14  	"math/big"
    15  
    16  	"github.com/consensys/gnark-crypto/ecc/bn254"
    17  
    18  	cloudflare "github.com/scroll-tech/go-ethereum/crypto/bn256/cloudflare"
    19  	google "github.com/scroll-tech/go-ethereum/crypto/bn256/google"
    20  )
    21  
    22  func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1, *bn254.G1Affine) {
    23  	_, xc, err := cloudflare.RandomG1(input)
    24  	if err != nil {
    25  		// insufficient input
    26  		return nil, nil, nil
    27  	}
    28  	xg := new(google.G1)
    29  	if _, err := xg.Unmarshal(xc.Marshal()); err != nil {
    30  		panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err))
    31  	}
    32  	xs := new(bn254.G1Affine)
    33  	if err := xs.Unmarshal(xc.Marshal()); err != nil {
    34  		panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err))
    35  	}
    36  	return xc, xg, xs
    37  }
    38  
    39  func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *bn254.G2Affine) {
    40  	_, xc, err := cloudflare.RandomG2(input)
    41  	if err != nil {
    42  		// insufficient input
    43  		return nil, nil, nil
    44  	}
    45  	xg := new(google.G2)
    46  	if _, err := xg.Unmarshal(xc.Marshal()); err != nil {
    47  		panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err))
    48  	}
    49  	xs := new(bn254.G2Affine)
    50  	if err := xs.Unmarshal(xc.Marshal()); err != nil {
    51  		panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err))
    52  	}
    53  	return xc, xg, xs
    54  }
    55  
    56  // FuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries.
    57  func FuzzAdd(data []byte) int {
    58  	input := bytes.NewReader(data)
    59  	xc, xg, xs := getG1Points(input)
    60  	if xc == nil {
    61  		return 0
    62  	}
    63  	yc, yg, ys := getG1Points(input)
    64  	if yc == nil {
    65  		return 0
    66  	}
    67  	// Ensure both libs can parse the second curve point
    68  	// Add the two points and ensure they result in the same output
    69  	rc := new(cloudflare.G1)
    70  	rc.Add(xc, yc)
    71  
    72  	rg := new(google.G1)
    73  	rg.Add(xg, yg)
    74  
    75  	tmpX := new(bn254.G1Jac).FromAffine(xs)
    76  	tmpY := new(bn254.G1Jac).FromAffine(ys)
    77  	rs := new(bn254.G1Affine).FromJacobian(tmpX.AddAssign(tmpY))
    78  
    79  	if !bytes.Equal(rc.Marshal(), rg.Marshal()) {
    80  		panic("add mismatch: cloudflare/google")
    81  	}
    82  
    83  	if !bytes.Equal(rc.Marshal(), rs.Marshal()) {
    84  		panic("add mismatch: cloudflare/gnark")
    85  	}
    86  	return 1
    87  }
    88  
    89  // FuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare
    90  // libraries.
    91  func FuzzMul(data []byte) int {
    92  	input := bytes.NewReader(data)
    93  	pc, pg, ps := getG1Points(input)
    94  	if pc == nil {
    95  		return 0
    96  	}
    97  	// Add the two points and ensure they result in the same output
    98  	remaining := input.Len()
    99  	if remaining == 0 {
   100  		return 0
   101  	}
   102  	if remaining > 128 {
   103  		// The evm only ever uses 32 byte integers, we need to cap this otherwise
   104  		// we run into slow exec. A 236Kb byte integer cause oss-fuzz to report it as slow.
   105  		// 128 bytes should be fine though
   106  		return 0
   107  	}
   108  	buf := make([]byte, remaining)
   109  	input.Read(buf)
   110  
   111  	rc := new(cloudflare.G1)
   112  	rc.ScalarMult(pc, new(big.Int).SetBytes(buf))
   113  
   114  	rg := new(google.G1)
   115  	rg.ScalarMult(pg, new(big.Int).SetBytes(buf))
   116  
   117  	rs := new(bn254.G1Jac)
   118  	psJac := new(bn254.G1Jac).FromAffine(ps)
   119  	rs.ScalarMultiplication(psJac, new(big.Int).SetBytes(buf))
   120  	rsAffine := new(bn254.G1Affine).FromJacobian(rs)
   121  
   122  	if !bytes.Equal(rc.Marshal(), rg.Marshal()) {
   123  		panic("scalar mul mismatch: cloudflare/google")
   124  	}
   125  	if !bytes.Equal(rc.Marshal(), rsAffine.Marshal()) {
   126  		panic("scalar mul mismatch: cloudflare/gnark")
   127  	}
   128  	return 1
   129  }
   130  
   131  func FuzzPair(data []byte) int {
   132  	input := bytes.NewReader(data)
   133  	pc, pg, ps := getG1Points(input)
   134  	if pc == nil {
   135  		return 0
   136  	}
   137  	tc, tg, ts := getG2Points(input)
   138  	if tc == nil {
   139  		return 0
   140  	}
   141  
   142  	// Pair the two points and ensure they result in the same output
   143  	clPair := cloudflare.Pair(pc, tc).Marshal()
   144  	gPair := google.Pair(pg, tg).Marshal()
   145  	if !bytes.Equal(clPair, gPair) {
   146  		panic("pairing mismatch: cloudflare/google")
   147  	}
   148  
   149  	cPair, err := bn254.Pair([]bn254.G1Affine{*ps}, []bn254.G2Affine{*ts})
   150  	if err != nil {
   151  		panic(fmt.Sprintf("gnark/bn254 encountered error: %v", err))
   152  	}
   153  	if !bytes.Equal(clPair, cPair.Marshal()) {
   154  		panic("pairing mismatch: cloudflare/gnark")
   155  	}
   156  
   157  	return 1
   158  }