github.com/phillinzzz/newBsc@v1.1.6/tests/fuzzers/les/les-fuzzer.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 les 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "io" 23 "math/big" 24 25 "github.com/phillinzzz/newBsc/common" 26 "github.com/phillinzzz/newBsc/consensus/ethash" 27 "github.com/phillinzzz/newBsc/core" 28 "github.com/phillinzzz/newBsc/core/rawdb" 29 "github.com/phillinzzz/newBsc/core/types" 30 "github.com/phillinzzz/newBsc/core/vm" 31 "github.com/phillinzzz/newBsc/crypto" 32 l "github.com/phillinzzz/newBsc/les" 33 "github.com/phillinzzz/newBsc/params" 34 "github.com/phillinzzz/newBsc/rlp" 35 "github.com/phillinzzz/newBsc/trie" 36 ) 37 38 var ( 39 bankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 40 bankAddr = crypto.PubkeyToAddress(bankKey.PublicKey) 41 bankFunds = new(big.Int).Mul(big.NewInt(100), big.NewInt(params.Ether)) 42 43 testChainLen = 256 44 testContractCode = common.Hex2Bytes("606060405260cc8060106000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806360cd2685146041578063c16431b914606b57603f565b005b6055600480803590602001909190505060a9565b6040518082815260200191505060405180910390f35b60886004808035906020019091908035906020019091905050608a565b005b80600060005083606481101560025790900160005b50819055505b5050565b6000600060005082606481101560025790900160005b5054905060c7565b91905056") 45 46 chain *core.BlockChain 47 addrHashes []common.Hash 48 txHashes []common.Hash 49 50 chtTrie *trie.Trie 51 bloomTrie *trie.Trie 52 chtKeys [][]byte 53 bloomKeys [][]byte 54 ) 55 56 func makechain() (bc *core.BlockChain, addrHashes, txHashes []common.Hash) { 57 db := rawdb.NewMemoryDatabase() 58 gspec := core.Genesis{ 59 Config: params.TestChainConfig, 60 Alloc: core.GenesisAlloc{bankAddr: {Balance: bankFunds}}, 61 GasLimit: 100000000, 62 } 63 genesis := gspec.MustCommit(db) 64 signer := types.HomesteadSigner{} 65 blocks, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, testChainLen, 66 func(i int, gen *core.BlockGen) { 67 var ( 68 tx *types.Transaction 69 addr common.Address 70 ) 71 nonce := uint64(i) 72 if i%4 == 0 { 73 tx, _ = types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), 200000, big.NewInt(0), testContractCode), signer, bankKey) 74 addr = crypto.CreateAddress(bankAddr, nonce) 75 } else { 76 addr = common.BigToAddress(big.NewInt(int64(i))) 77 tx, _ = types.SignTx(types.NewTransaction(nonce, addr, big.NewInt(10000), params.TxGas, big.NewInt(params.GWei), nil), signer, bankKey) 78 } 79 gen.AddTx(tx) 80 addrHashes = append(addrHashes, crypto.Keccak256Hash(addr[:])) 81 txHashes = append(txHashes, tx.Hash()) 82 }) 83 bc, _ = core.NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 84 if _, err := bc.InsertChain(blocks); err != nil { 85 panic(err) 86 } 87 return 88 } 89 90 func makeTries() (chtTrie *trie.Trie, bloomTrie *trie.Trie, chtKeys, bloomKeys [][]byte) { 91 chtTrie, _ = trie.New(common.Hash{}, trie.NewDatabase(rawdb.NewMemoryDatabase())) 92 bloomTrie, _ = trie.New(common.Hash{}, trie.NewDatabase(rawdb.NewMemoryDatabase())) 93 for i := 0; i < testChainLen; i++ { 94 // The element in CHT is <big-endian block number> -> <block hash> 95 key := make([]byte, 8) 96 binary.BigEndian.PutUint64(key, uint64(i+1)) 97 chtTrie.Update(key, []byte{0x1, 0xf}) 98 chtKeys = append(chtKeys, key) 99 100 // The element in Bloom trie is <2 byte bit index> + <big-endian block number> -> bloom 101 key2 := make([]byte, 10) 102 binary.BigEndian.PutUint64(key2[2:], uint64(i+1)) 103 bloomTrie.Update(key2, []byte{0x2, 0xe}) 104 bloomKeys = append(bloomKeys, key2) 105 } 106 return 107 } 108 109 func init() { 110 chain, addrHashes, txHashes = makechain() 111 chtTrie, bloomTrie, chtKeys, bloomKeys = makeTries() 112 } 113 114 type fuzzer struct { 115 chain *core.BlockChain 116 pool *core.TxPool 117 118 chainLen int 119 addr, txs []common.Hash 120 nonce uint64 121 122 chtKeys [][]byte 123 bloomKeys [][]byte 124 chtTrie *trie.Trie 125 bloomTrie *trie.Trie 126 127 input io.Reader 128 exhausted bool 129 } 130 131 func newFuzzer(input []byte) *fuzzer { 132 return &fuzzer{ 133 chain: chain, 134 chainLen: testChainLen, 135 addr: addrHashes, 136 txs: txHashes, 137 chtTrie: chtTrie, 138 bloomTrie: bloomTrie, 139 chtKeys: chtKeys, 140 bloomKeys: bloomKeys, 141 nonce: uint64(len(txHashes)), 142 pool: core.NewTxPool(core.DefaultTxPoolConfig, params.TestChainConfig, chain), 143 input: bytes.NewReader(input), 144 } 145 } 146 147 func (f *fuzzer) read(size int) []byte { 148 out := make([]byte, size) 149 if _, err := f.input.Read(out); err != nil { 150 f.exhausted = true 151 } 152 return out 153 } 154 155 func (f *fuzzer) randomByte() byte { 156 d := f.read(1) 157 return d[0] 158 } 159 160 func (f *fuzzer) randomBool() bool { 161 d := f.read(1) 162 return d[0]&1 == 1 163 } 164 165 func (f *fuzzer) randomInt(max int) int { 166 if max == 0 { 167 return 0 168 } 169 if max <= 256 { 170 return int(f.randomByte()) % max 171 } 172 var a uint16 173 if err := binary.Read(f.input, binary.LittleEndian, &a); err != nil { 174 f.exhausted = true 175 } 176 return int(a % uint16(max)) 177 } 178 179 func (f *fuzzer) randomX(max int) uint64 { 180 var a uint16 181 if err := binary.Read(f.input, binary.LittleEndian, &a); err != nil { 182 f.exhausted = true 183 } 184 if a < 0x8000 { 185 return uint64(a%uint16(max+1)) - 1 186 } 187 return (uint64(1)<<(a%64+1) - 1) & (uint64(a) * 343897772345826595) 188 } 189 190 func (f *fuzzer) randomBlockHash() common.Hash { 191 h := f.chain.GetCanonicalHash(uint64(f.randomInt(3 * f.chainLen))) 192 if h != (common.Hash{}) { 193 return h 194 } 195 return common.BytesToHash(f.read(common.HashLength)) 196 } 197 198 func (f *fuzzer) randomAddrHash() []byte { 199 i := f.randomInt(3 * len(f.addr)) 200 if i < len(f.addr) { 201 return f.addr[i].Bytes() 202 } 203 return f.read(common.HashLength) 204 } 205 206 func (f *fuzzer) randomCHTTrieKey() []byte { 207 i := f.randomInt(3 * len(f.chtKeys)) 208 if i < len(f.chtKeys) { 209 return f.chtKeys[i] 210 } 211 return f.read(8) 212 } 213 214 func (f *fuzzer) randomBloomTrieKey() []byte { 215 i := f.randomInt(3 * len(f.bloomKeys)) 216 if i < len(f.bloomKeys) { 217 return f.bloomKeys[i] 218 } 219 return f.read(10) 220 } 221 222 func (f *fuzzer) randomTxHash() common.Hash { 223 i := f.randomInt(3 * len(f.txs)) 224 if i < len(f.txs) { 225 return f.txs[i] 226 } 227 return common.BytesToHash(f.read(common.HashLength)) 228 } 229 230 func (f *fuzzer) BlockChain() *core.BlockChain { 231 return f.chain 232 } 233 234 func (f *fuzzer) TxPool() *core.TxPool { 235 return f.pool 236 } 237 238 func (f *fuzzer) ArchiveMode() bool { 239 return false 240 } 241 242 func (f *fuzzer) AddTxsSync() bool { 243 return false 244 } 245 246 func (f *fuzzer) GetHelperTrie(typ uint, index uint64) *trie.Trie { 247 if typ == 0 { 248 return f.chtTrie 249 } else if typ == 1 { 250 return f.bloomTrie 251 } 252 return nil 253 } 254 255 type dummyMsg struct { 256 data []byte 257 } 258 259 func (d dummyMsg) Decode(val interface{}) error { 260 return rlp.DecodeBytes(d.data, val) 261 } 262 263 func (f *fuzzer) doFuzz(msgCode uint64, packet interface{}) { 264 enc, err := rlp.EncodeToBytes(packet) 265 if err != nil { 266 panic(err) 267 } 268 version := f.randomInt(3) + 2 // [LES2, LES3, LES4] 269 peer, closeFn := l.NewFuzzerPeer(version) 270 defer closeFn() 271 fn, _, _, err := l.Les3[msgCode].Handle(dummyMsg{enc}) 272 if err != nil { 273 panic(err) 274 } 275 fn(f, peer, func() bool { return true }) 276 } 277 278 func Fuzz(input []byte) int { 279 // We expect some large inputs 280 if len(input) < 100 { 281 return -1 282 } 283 f := newFuzzer(input) 284 if f.exhausted { 285 return -1 286 } 287 for !f.exhausted { 288 switch f.randomInt(8) { 289 case 0: 290 req := &l.GetBlockHeadersPacket{ 291 Query: l.GetBlockHeadersData{ 292 Amount: f.randomX(l.MaxHeaderFetch + 1), 293 Skip: f.randomX(10), 294 Reverse: f.randomBool(), 295 }, 296 } 297 if f.randomBool() { 298 req.Query.Origin.Hash = f.randomBlockHash() 299 } else { 300 req.Query.Origin.Number = uint64(f.randomInt(f.chainLen * 2)) 301 } 302 f.doFuzz(l.GetBlockHeadersMsg, req) 303 304 case 1: 305 req := &l.GetBlockBodiesPacket{Hashes: make([]common.Hash, f.randomInt(l.MaxBodyFetch+1))} 306 for i := range req.Hashes { 307 req.Hashes[i] = f.randomBlockHash() 308 } 309 f.doFuzz(l.GetBlockBodiesMsg, req) 310 311 case 2: 312 req := &l.GetCodePacket{Reqs: make([]l.CodeReq, f.randomInt(l.MaxCodeFetch+1))} 313 for i := range req.Reqs { 314 req.Reqs[i] = l.CodeReq{ 315 BHash: f.randomBlockHash(), 316 AccKey: f.randomAddrHash(), 317 } 318 } 319 f.doFuzz(l.GetCodeMsg, req) 320 321 case 3: 322 req := &l.GetReceiptsPacket{Hashes: make([]common.Hash, f.randomInt(l.MaxReceiptFetch+1))} 323 for i := range req.Hashes { 324 req.Hashes[i] = f.randomBlockHash() 325 } 326 f.doFuzz(l.GetReceiptsMsg, req) 327 328 case 4: 329 req := &l.GetProofsPacket{Reqs: make([]l.ProofReq, f.randomInt(l.MaxProofsFetch+1))} 330 for i := range req.Reqs { 331 if f.randomBool() { 332 req.Reqs[i] = l.ProofReq{ 333 BHash: f.randomBlockHash(), 334 AccKey: f.randomAddrHash(), 335 Key: f.randomAddrHash(), 336 FromLevel: uint(f.randomX(3)), 337 } 338 } else { 339 req.Reqs[i] = l.ProofReq{ 340 BHash: f.randomBlockHash(), 341 Key: f.randomAddrHash(), 342 FromLevel: uint(f.randomX(3)), 343 } 344 } 345 } 346 f.doFuzz(l.GetProofsV2Msg, req) 347 348 case 5: 349 req := &l.GetHelperTrieProofsPacket{Reqs: make([]l.HelperTrieReq, f.randomInt(l.MaxHelperTrieProofsFetch+1))} 350 for i := range req.Reqs { 351 switch f.randomInt(3) { 352 case 0: 353 // Canonical hash trie 354 req.Reqs[i] = l.HelperTrieReq{ 355 Type: 0, 356 TrieIdx: f.randomX(3), 357 Key: f.randomCHTTrieKey(), 358 FromLevel: uint(f.randomX(3)), 359 AuxReq: uint(2), 360 } 361 case 1: 362 // Bloom trie 363 req.Reqs[i] = l.HelperTrieReq{ 364 Type: 1, 365 TrieIdx: f.randomX(3), 366 Key: f.randomBloomTrieKey(), 367 FromLevel: uint(f.randomX(3)), 368 AuxReq: 0, 369 } 370 default: 371 // Random trie 372 req.Reqs[i] = l.HelperTrieReq{ 373 Type: 2, 374 TrieIdx: f.randomX(3), 375 Key: f.randomCHTTrieKey(), 376 FromLevel: uint(f.randomX(3)), 377 AuxReq: 0, 378 } 379 } 380 } 381 f.doFuzz(l.GetHelperTrieProofsMsg, req) 382 383 case 6: 384 req := &l.SendTxPacket{Txs: make([]*types.Transaction, f.randomInt(l.MaxTxSend+1))} 385 signer := types.HomesteadSigner{} 386 for i := range req.Txs { 387 var nonce uint64 388 if f.randomBool() { 389 nonce = uint64(f.randomByte()) 390 } else { 391 nonce = f.nonce 392 f.nonce += 1 393 } 394 req.Txs[i], _ = types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(10000), params.TxGas, big.NewInt(1000000000*int64(f.randomByte())), nil), signer, bankKey) 395 } 396 f.doFuzz(l.SendTxV2Msg, req) 397 398 case 7: 399 req := &l.GetTxStatusPacket{Hashes: make([]common.Hash, f.randomInt(l.MaxTxStatus+1))} 400 for i := range req.Hashes { 401 req.Hashes[i] = f.randomTxHash() 402 } 403 f.doFuzz(l.GetTxStatusMsg, req) 404 } 405 } 406 return 0 407 }