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  }