github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/tests/fuzzers/bls12381/precompile_fuzzer.go (about) 1 // Copyright 2020 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 package bls 18 19 import ( 20 "bytes" 21 "fmt" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/core/vm" 25 ) 26 27 const ( 28 blsG1Add = byte(10) 29 blsG1Mul = byte(11) 30 blsG1MultiExp = byte(12) 31 blsG2Add = byte(13) 32 blsG2Mul = byte(14) 33 blsG2MultiExp = byte(15) 34 blsPairing = byte(16) 35 blsMapG1 = byte(17) 36 blsMapG2 = byte(18) 37 ) 38 39 func FuzzG1Add(data []byte) int { return fuzz(blsG1Add, data) } 40 func FuzzG1Mul(data []byte) int { return fuzz(blsG1Mul, data) } 41 func FuzzG1MultiExp(data []byte) int { return fuzz(blsG1MultiExp, data) } 42 func FuzzG2Add(data []byte) int { return fuzz(blsG2Add, data) } 43 func FuzzG2Mul(data []byte) int { return fuzz(blsG2Mul, data) } 44 func FuzzG2MultiExp(data []byte) int { return fuzz(blsG2MultiExp, data) } 45 func FuzzPairing(data []byte) int { return fuzz(blsPairing, data) } 46 func FuzzMapG1(data []byte) int { return fuzz(blsMapG1, data) } 47 func FuzzMapG2(data []byte) int { return fuzz(blsMapG2, data) } 48 49 func checkInput(id byte, inputLen int) bool { 50 switch id { 51 case blsG1Add: 52 return inputLen == 256 53 case blsG1Mul: 54 return inputLen == 160 55 case blsG1MultiExp: 56 return inputLen%160 == 0 57 case blsG2Add: 58 return inputLen == 512 59 case blsG2Mul: 60 return inputLen == 288 61 case blsG2MultiExp: 62 return inputLen%288 == 0 63 case blsPairing: 64 return inputLen%384 == 0 65 case blsMapG1: 66 return inputLen == 64 67 case blsMapG2: 68 return inputLen == 128 69 } 70 panic("programmer error") 71 } 72 73 // The fuzzer functions must return 74 // 1 if the fuzzer should increase priority of the 75 // given input during subsequent fuzzing (for example, the input is lexically 76 // correct and was parsed successfully); 77 // -1 if the input must not be added to corpus even if gives new coverage; and 78 // 0 otherwise 79 // other values are reserved for future use. 80 func fuzz(id byte, data []byte) int { 81 // Even on bad input, it should not crash, so we still test the gas calc 82 precompile := vm.PrecompiledContractsBLS[common.BytesToAddress([]byte{id})] 83 gas := precompile.RequiredGas(data) 84 if !checkInput(id, len(data)) { 85 return 0 86 } 87 // If the gas cost is too large (25M), bail out 88 if gas > 25*1000*1000 { 89 return 0 90 } 91 cpy := make([]byte, len(data)) 92 copy(cpy, data) 93 _, err := precompile.Run(cpy) 94 if !bytes.Equal(cpy, data) { 95 panic(fmt.Sprintf("input data modified, precompile %d: %x %x", id, data, cpy)) 96 } 97 if err != nil { 98 return 0 99 } 100 return 1 101 }