github.com/theQRL/go-zond@v0.1.1/tests/fuzzers/bn256/bn256_fuzz.go (about) 1 // Copyright 2018 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 //go:build gofuzz 18 // +build gofuzz 19 20 package bn256 21 22 import ( 23 "bytes" 24 "fmt" 25 "io" 26 "math/big" 27 28 "github.com/consensys/gnark-crypto/ecc/bn254" 29 cloudflare "github.com/theQRL/go-zond/crypto/bn256/cloudflare" 30 google "github.com/theQRL/go-zond/crypto/bn256/google" 31 ) 32 33 func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1, *bn254.G1Affine) { 34 _, xc, err := cloudflare.RandomG1(input) 35 if err != nil { 36 // insufficient input 37 return nil, nil, nil 38 } 39 xg := new(google.G1) 40 if _, err := xg.Unmarshal(xc.Marshal()); err != nil { 41 panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err)) 42 } 43 xs := new(bn254.G1Affine) 44 if err := xs.Unmarshal(xc.Marshal()); err != nil { 45 panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err)) 46 } 47 return xc, xg, xs 48 } 49 50 func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *bn254.G2Affine) { 51 _, xc, err := cloudflare.RandomG2(input) 52 if err != nil { 53 // insufficient input 54 return nil, nil, nil 55 } 56 xg := new(google.G2) 57 if _, err := xg.Unmarshal(xc.Marshal()); err != nil { 58 panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err)) 59 } 60 xs := new(bn254.G2Affine) 61 if err := xs.Unmarshal(xc.Marshal()); err != nil { 62 panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err)) 63 } 64 return xc, xg, xs 65 } 66 67 // FuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries. 68 func FuzzAdd(data []byte) int { 69 input := bytes.NewReader(data) 70 xc, xg, xs := getG1Points(input) 71 if xc == nil { 72 return 0 73 } 74 yc, yg, ys := getG1Points(input) 75 if yc == nil { 76 return 0 77 } 78 // Ensure both libs can parse the second curve point 79 // Add the two points and ensure they result in the same output 80 rc := new(cloudflare.G1) 81 rc.Add(xc, yc) 82 83 rg := new(google.G1) 84 rg.Add(xg, yg) 85 86 tmpX := new(bn254.G1Jac).FromAffine(xs) 87 tmpY := new(bn254.G1Jac).FromAffine(ys) 88 rs := new(bn254.G1Affine).FromJacobian(tmpX.AddAssign(tmpY)) 89 90 if !bytes.Equal(rc.Marshal(), rg.Marshal()) { 91 panic("add mismatch: cloudflare/google") 92 } 93 94 if !bytes.Equal(rc.Marshal(), rs.Marshal()) { 95 panic("add mismatch: cloudflare/gnark") 96 } 97 return 1 98 } 99 100 // FuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare 101 // libraries. 102 func FuzzMul(data []byte) int { 103 input := bytes.NewReader(data) 104 pc, pg, ps := getG1Points(input) 105 if pc == nil { 106 return 0 107 } 108 // Add the two points and ensure they result in the same output 109 remaining := input.Len() 110 if remaining == 0 { 111 return 0 112 } 113 if remaining > 128 { 114 // The evm only ever uses 32 byte integers, we need to cap this otherwise 115 // we run into slow exec. A 236Kb byte integer cause oss-fuzz to report it as slow. 116 // 128 bytes should be fine though 117 return 0 118 } 119 buf := make([]byte, remaining) 120 input.Read(buf) 121 122 rc := new(cloudflare.G1) 123 rc.ScalarMult(pc, new(big.Int).SetBytes(buf)) 124 125 rg := new(google.G1) 126 rg.ScalarMult(pg, new(big.Int).SetBytes(buf)) 127 128 rs := new(bn254.G1Jac) 129 psJac := new(bn254.G1Jac).FromAffine(ps) 130 rs.ScalarMultiplication(psJac, new(big.Int).SetBytes(buf)) 131 rsAffine := new(bn254.G1Affine).FromJacobian(rs) 132 133 if !bytes.Equal(rc.Marshal(), rg.Marshal()) { 134 panic("scalar mul mismatch: cloudflare/google") 135 } 136 if !bytes.Equal(rc.Marshal(), rsAffine.Marshal()) { 137 panic("scalar mul mismatch: cloudflare/gnark") 138 } 139 return 1 140 } 141 142 func FuzzPair(data []byte) int { 143 input := bytes.NewReader(data) 144 pc, pg, ps := getG1Points(input) 145 if pc == nil { 146 return 0 147 } 148 tc, tg, ts := getG2Points(input) 149 if tc == nil { 150 return 0 151 } 152 153 // Pair the two points and ensure they result in the same output 154 clPair := cloudflare.Pair(pc, tc).Marshal() 155 gPair := google.Pair(pg, tg).Marshal() 156 if !bytes.Equal(clPair, gPair) { 157 panic("pairing mismatch: cloudflare/google") 158 } 159 cPair, err := bn254.Pair([]bn254.G1Affine{*ps}, []bn254.G2Affine{*ts}) 160 if err != nil { 161 panic(fmt.Sprintf("gnark/bn254 encountered error: %v", err)) 162 } 163 164 // gnark uses a different pairing algorithm which might produce 165 // different but also correct outputs, we need to scale the output by s 166 167 u, _ := new(big.Int).SetString("0x44e992b44a6909f1", 0) 168 u_exp2 := new(big.Int).Exp(u, big.NewInt(2), nil) // u^2 169 u_6_exp2 := new(big.Int).Mul(big.NewInt(6), u_exp2) // 6*u^2 170 u_3 := new(big.Int).Mul(big.NewInt(3), u) // 3*u 171 inner := u_6_exp2.Add(u_6_exp2, u_3) // 6*u^2 + 3*u 172 inner.Add(inner, big.NewInt(1)) // 6*u^2 + 3*u + 1 173 u_2 := new(big.Int).Mul(big.NewInt(2), u) // 2*u 174 s := u_2.Mul(u_2, inner) // 2*u(6*u^2 + 3*u + 1) 175 176 gRes := new(bn254.GT) 177 if err := gRes.SetBytes(clPair); err != nil { 178 panic(err) 179 } 180 gRes = gRes.Exp(*gRes, s) 181 if !bytes.Equal(cPair.Marshal(), gRes.Marshal()) { 182 panic("pairing mismatch: cloudflare/gnark") 183 } 184 185 return 1 186 }