github.com/phillinzzz/newBsc@v1.1.6/eth/handler_diff_test.go (about) 1 // Copyright 2015 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 eth 18 19 import ( 20 "crypto/rand" 21 "math/big" 22 "testing" 23 "time" 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/eth/downloader" 32 "github.com/phillinzzz/newBsc/eth/protocols/diff" 33 "github.com/phillinzzz/newBsc/ethdb" 34 "github.com/phillinzzz/newBsc/p2p" 35 "github.com/phillinzzz/newBsc/p2p/enode" 36 "github.com/phillinzzz/newBsc/params" 37 "github.com/phillinzzz/newBsc/rlp" 38 ) 39 40 // testBackend is a mock implementation of the live Ethereum message handler. Its 41 // purpose is to allow testing the request/reply workflows and wire serialization 42 // in the `eth` protocol without actually doing any data processing. 43 type testBackend struct { 44 db ethdb.Database 45 chain *core.BlockChain 46 txpool *core.TxPool 47 48 handler *handler 49 } 50 51 // newTestBackend creates an empty chain and wraps it into a mock backend. 52 func newTestBackend(blocks int) *testBackend { 53 return newTestBackendWithGenerator(blocks) 54 } 55 56 // newTestBackend creates a chain with a number of explicitly defined blocks and 57 // wraps it into a mock backend. 58 func newTestBackendWithGenerator(blocks int) *testBackend { 59 signer := types.HomesteadSigner{} 60 // Create a database pre-initialize with a genesis block 61 db := rawdb.NewMemoryDatabase() 62 (&core.Genesis{ 63 Config: params.TestChainConfig, 64 Alloc: core.GenesisAlloc{testAddr: {Balance: big.NewInt(100000000000000000)}}, 65 }).MustCommit(db) 66 67 chain, _ := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil) 68 generator := func(i int, block *core.BlockGen) { 69 // The chain maker doesn't have access to a chain, so the difficulty will be 70 // lets unset (nil). Set it here to the correct value. 71 block.SetCoinbase(testAddr) 72 73 // We want to simulate an empty middle block, having the same state as the 74 // first one. The last is needs a state change again to force a reorg. 75 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), common.Address{0x01}, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testKey) 76 if err != nil { 77 panic(err) 78 } 79 block.AddTxWithChain(chain, tx) 80 } 81 bs, _ := core.GenerateChain(params.TestChainConfig, chain.Genesis(), ethash.NewFaker(), db, blocks, generator) 82 if _, err := chain.InsertChain(bs); err != nil { 83 panic(err) 84 } 85 txpool := newTestTxPool() 86 87 handler, _ := newHandler(&handlerConfig{ 88 Database: db, 89 Chain: chain, 90 TxPool: txpool, 91 Network: 1, 92 Sync: downloader.FullSync, 93 BloomCache: 1, 94 }) 95 handler.Start(100) 96 97 txconfig := core.DefaultTxPoolConfig 98 txconfig.Journal = "" // Don't litter the disk with test journals 99 100 return &testBackend{ 101 db: db, 102 chain: chain, 103 txpool: core.NewTxPool(txconfig, params.TestChainConfig, chain), 104 handler: handler, 105 } 106 } 107 108 // close tears down the transaction pool and chain behind the mock backend. 109 func (b *testBackend) close() { 110 b.txpool.Stop() 111 b.chain.Stop() 112 b.handler.Stop() 113 } 114 115 func (b *testBackend) Chain() *core.BlockChain { return b.chain } 116 117 func (b *testBackend) RunPeer(peer *diff.Peer, handler diff.Handler) error { 118 // Normally the backend would do peer mainentance and handshakes. All that 119 // is omitted and we will just give control back to the handler. 120 return handler(peer) 121 } 122 func (b *testBackend) PeerInfo(enode.ID) interface{} { panic("not implemented") } 123 124 func (b *testBackend) Handle(*diff.Peer, diff.Packet) error { 125 panic("data processing tests should be done in the handler package") 126 } 127 128 type testPeer struct { 129 *diff.Peer 130 131 net p2p.MsgReadWriter // Network layer reader/writer to simulate remote messaging 132 app *p2p.MsgPipeRW // Application layer reader/writer to simulate the local side 133 } 134 135 // newTestPeer creates a new peer registered at the given data backend. 136 func newTestPeer(name string, version uint, backend *testBackend) (*testPeer, <-chan error) { 137 // Create a message pipe to communicate through 138 app, net := p2p.MsgPipe() 139 140 // Start the peer on a new thread 141 var id enode.ID 142 rand.Read(id[:]) 143 144 peer := diff.NewPeer(version, p2p.NewPeer(id, name, nil), net) 145 errc := make(chan error, 1) 146 go func() { 147 errc <- backend.RunPeer(peer, func(peer *diff.Peer) error { 148 149 return diff.Handle((*diffHandler)(backend.handler), peer) 150 }) 151 }() 152 return &testPeer{app: app, net: net, Peer: peer}, errc 153 } 154 155 // close terminates the local side of the peer, notifying the remote protocol 156 // manager of termination. 157 func (p *testPeer) close() { 158 p.Peer.Close() 159 p.app.Close() 160 } 161 162 func TestHandleDiffLayer(t *testing.T) { 163 t.Parallel() 164 165 blockNum := 1024 166 waitInterval := 100 * time.Millisecond 167 backend := newTestBackend(blockNum) 168 defer backend.close() 169 170 peer, _ := newTestPeer("peer", diff.Diff1, backend) 171 defer peer.close() 172 173 tests := []struct { 174 DiffLayer *types.DiffLayer 175 Valid bool 176 }{ 177 {DiffLayer: &types.DiffLayer{ 178 BlockHash: common.Hash{0x1}, 179 Number: 1025, 180 }, Valid: true}, 181 {DiffLayer: &types.DiffLayer{ 182 BlockHash: common.Hash{0x2}, 183 Number: 3073, 184 }, Valid: false}, 185 {DiffLayer: &types.DiffLayer{ 186 BlockHash: common.Hash{0x3}, 187 Number: 500, 188 }, Valid: false}, 189 } 190 191 for _, tt := range tests { 192 bz, _ := rlp.EncodeToBytes(tt.DiffLayer) 193 194 p2p.Send(peer.app, diff.DiffLayerMsg, diff.DiffLayersPacket{rlp.RawValue(bz)}) 195 } 196 time.Sleep(waitInterval) 197 for idx, tt := range tests { 198 diff := backend.chain.GetUnTrustedDiffLayer(tt.DiffLayer.BlockHash, "") 199 if (tt.Valid && diff == nil) || (!tt.Valid && diff != nil) { 200 t.Errorf("test: %d, diff layer handle failed", idx) 201 } 202 } 203 }