github.com/theQRL/go-zond@v0.2.1/tests/fuzzers/snap/fuzz_handler.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 package snap 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "fmt" 23 "math/big" 24 "time" 25 26 fuzz "github.com/google/gofuzz" 27 "github.com/theQRL/go-zond/common" 28 "github.com/theQRL/go-zond/consensus/beacon" 29 "github.com/theQRL/go-zond/core" 30 "github.com/theQRL/go-zond/core/rawdb" 31 "github.com/theQRL/go-zond/core/vm" 32 "github.com/theQRL/go-zond/p2p" 33 "github.com/theQRL/go-zond/p2p/enode" 34 "github.com/theQRL/go-zond/params" 35 "github.com/theQRL/go-zond/rlp" 36 "github.com/theQRL/go-zond/zond/protocols/snap" 37 ) 38 39 var trieRoot common.Hash 40 41 func getChain() *core.BlockChain { 42 ga := make(core.GenesisAlloc, 1000) 43 var a = make([]byte, 20) 44 var mkStorage = func(k, v int) (common.Hash, common.Hash) { 45 var kB = make([]byte, 32) 46 var vB = make([]byte, 32) 47 binary.LittleEndian.PutUint64(kB, uint64(k)) 48 binary.LittleEndian.PutUint64(vB, uint64(v)) 49 return common.BytesToHash(kB), common.BytesToHash(vB) 50 } 51 storage := make(map[common.Hash]common.Hash) 52 for i := 0; i < 10; i++ { 53 k, v := mkStorage(i, i) 54 storage[k] = v 55 } 56 for i := 0; i < 1000; i++ { 57 binary.LittleEndian.PutUint64(a, uint64(i+0xff)) 58 acc := core.GenesisAccount{Balance: big.NewInt(int64(i))} 59 if i%2 == 1 { 60 acc.Storage = storage 61 } 62 ga[common.BytesToAddress(a)] = acc 63 } 64 gspec := &core.Genesis{ 65 Config: params.TestChainConfig, 66 Alloc: ga, 67 } 68 _, blocks, _ := core.GenerateChainWithGenesis(gspec, beacon.NewFaker(), 2, func(i int, gen *core.BlockGen) {}) 69 cacheConf := &core.CacheConfig{ 70 TrieCleanLimit: 0, 71 TrieDirtyLimit: 0, 72 TrieTimeLimit: 5 * time.Minute, 73 TrieCleanNoPrefetch: true, 74 SnapshotLimit: 100, 75 SnapshotWait: true, 76 } 77 trieRoot = blocks[len(blocks)-1].Root() 78 bc, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), cacheConf, gspec, beacon.NewFaker(), vm.Config{}, nil) 79 if _, err := bc.InsertChain(blocks); err != nil { 80 panic(err) 81 } 82 return bc 83 } 84 85 type dummyBackend struct { 86 chain *core.BlockChain 87 } 88 89 func (d *dummyBackend) Chain() *core.BlockChain { return d.chain } 90 func (d *dummyBackend) RunPeer(*snap.Peer, snap.Handler) error { return nil } 91 func (d *dummyBackend) PeerInfo(enode.ID) interface{} { return "Foo" } 92 func (d *dummyBackend) Handle(*snap.Peer, snap.Packet) error { return nil } 93 94 type dummyRW struct { 95 code uint64 96 data []byte 97 writeCount int 98 } 99 100 func (d *dummyRW) ReadMsg() (p2p.Msg, error) { 101 return p2p.Msg{ 102 Code: d.code, 103 Payload: bytes.NewReader(d.data), 104 ReceivedAt: time.Now(), 105 Size: uint32(len(d.data)), 106 }, nil 107 } 108 109 func (d *dummyRW) WriteMsg(msg p2p.Msg) error { 110 d.writeCount++ 111 return nil 112 } 113 114 func doFuzz(input []byte, obj interface{}, code int) int { 115 if len(input) > 1024*4 { 116 return -1 117 } 118 bc := getChain() 119 defer bc.Stop() 120 backend := &dummyBackend{bc} 121 fuzz.NewFromGoFuzz(input).Fuzz(obj) 122 var data []byte 123 switch p := obj.(type) { 124 case *snap.GetTrieNodesPacket: 125 p.Root = trieRoot 126 data, _ = rlp.EncodeToBytes(obj) 127 default: 128 data, _ = rlp.EncodeToBytes(obj) 129 } 130 cli := &dummyRW{ 131 code: uint64(code), 132 data: data, 133 } 134 peer := snap.NewFakePeer(65, "gazonk01", cli) 135 err := snap.HandleMessage(backend, peer) 136 switch { 137 case err == nil && cli.writeCount != 1: 138 panic(fmt.Sprintf("Expected 1 response, got %d", cli.writeCount)) 139 case err != nil && cli.writeCount != 0: 140 panic(fmt.Sprintf("Expected 0 response, got %d", cli.writeCount)) 141 } 142 return 1 143 } 144 145 // To run a fuzzer, do 146 // $ CGO_ENABLED=0 go-fuzz-build -func FuzzTrieNodes 147 // $ go-fuzz 148 149 func FuzzARange(input []byte) int { 150 return doFuzz(input, &snap.GetAccountRangePacket{}, snap.GetAccountRangeMsg) 151 } 152 func FuzzSRange(input []byte) int { 153 return doFuzz(input, &snap.GetStorageRangesPacket{}, snap.GetStorageRangesMsg) 154 } 155 func FuzzByteCodes(input []byte) int { 156 return doFuzz(input, &snap.GetByteCodesPacket{}, snap.GetByteCodesMsg) 157 } 158 func FuzzTrieNodes(input []byte) int { 159 return doFuzz(input, &snap.GetTrieNodesPacket{}, snap.GetTrieNodesMsg) 160 }