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