github.com/pixichain/go-pixicoin@v0.0.0-20220708132717-27ba739265ff/les/handler_test.go (about)

     1  // Copyright 2016 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  	"math/big"
    22  	"math/rand"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/ethereum/go-ethereum/common"
    27  	"github.com/ethereum/go-ethereum/core"
    28  	"github.com/ethereum/go-ethereum/core/types"
    29  	"github.com/ethereum/go-ethereum/crypto"
    30  	"github.com/ethereum/go-ethereum/eth/downloader"
    31  	"github.com/ethereum/go-ethereum/ethdb"
    32  	"github.com/ethereum/go-ethereum/light"
    33  	"github.com/ethereum/go-ethereum/p2p"
    34  	"github.com/ethereum/go-ethereum/params"
    35  	"github.com/ethereum/go-ethereum/rlp"
    36  	"github.com/ethereum/go-ethereum/trie"
    37  )
    38  
    39  func expectResponse(r p2p.MsgReader, msgcode, reqID, bv uint64, data interface{}) error {
    40  	type resp struct {
    41  		ReqID, BV uint64
    42  		Data      interface{}
    43  	}
    44  	return p2p.ExpectMsg(r, msgcode, resp{reqID, bv, data})
    45  }
    46  
    47  func testCheckProof(t *testing.T, exp *light.NodeSet, got light.NodeList) {
    48  	if exp.KeyCount() > len(got) {
    49  		t.Errorf("proof has fewer nodes than expected")
    50  		return
    51  	}
    52  	if exp.KeyCount() < len(got) {
    53  		t.Errorf("proof has more nodes than expected")
    54  		return
    55  	}
    56  	for _, node := range got {
    57  		n, _ := exp.Get(crypto.Keccak256(node))
    58  		if !bytes.Equal(n, node) {
    59  			t.Errorf("proof contents mismatch")
    60  			return
    61  		}
    62  	}
    63  }
    64  
    65  // Tests that block headers can be retrieved from a remote chain based on user queries.
    66  func TestGetBlockHeadersLes1(t *testing.T) { testGetBlockHeaders(t, 1) }
    67  
    68  func TestGetBlockHeadersLes2(t *testing.T) { testGetBlockHeaders(t, 2) }
    69  
    70  func testGetBlockHeaders(t *testing.T, protocol int) {
    71  	db, _ := ethdb.NewMemDatabase()
    72  	pm := newTestProtocolManagerMust(t, false, downloader.MaxHashFetch+15, nil, nil, nil, db)
    73  	bc := pm.blockchain.(*core.BlockChain)
    74  	peer, _ := newTestPeer(t, "peer", protocol, pm, true)
    75  	defer peer.close()
    76  
    77  	// Create a "random" unknown hash for testing
    78  	var unknown common.Hash
    79  	for i := range unknown {
    80  		unknown[i] = byte(i)
    81  	}
    82  	// Create a batch of tests for various scenarios
    83  	limit := uint64(MaxHeaderFetch)
    84  	tests := []struct {
    85  		query  *getBlockHeadersData // The query to execute for header retrieval
    86  		expect []common.Hash        // The hashes of the block whose headers are expected
    87  	}{
    88  		// A single random block should be retrievable by hash and number too
    89  		{
    90  			&getBlockHeadersData{Origin: hashOrNumber{Hash: bc.GetBlockByNumber(limit / 2).Hash()}, Amount: 1},
    91  			[]common.Hash{bc.GetBlockByNumber(limit / 2).Hash()},
    92  		}, {
    93  			&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 1},
    94  			[]common.Hash{bc.GetBlockByNumber(limit / 2).Hash()},
    95  		},
    96  		// Multiple headers should be retrievable in both directions
    97  		{
    98  			&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3},
    99  			[]common.Hash{
   100  				bc.GetBlockByNumber(limit / 2).Hash(),
   101  				bc.GetBlockByNumber(limit/2 + 1).Hash(),
   102  				bc.GetBlockByNumber(limit/2 + 2).Hash(),
   103  			},
   104  		}, {
   105  			&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true},
   106  			[]common.Hash{
   107  				bc.GetBlockByNumber(limit / 2).Hash(),
   108  				bc.GetBlockByNumber(limit/2 - 1).Hash(),
   109  				bc.GetBlockByNumber(limit/2 - 2).Hash(),
   110  			},
   111  		},
   112  		// Multiple headers with skip lists should be retrievable
   113  		{
   114  			&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3},
   115  			[]common.Hash{
   116  				bc.GetBlockByNumber(limit / 2).Hash(),
   117  				bc.GetBlockByNumber(limit/2 + 4).Hash(),
   118  				bc.GetBlockByNumber(limit/2 + 8).Hash(),
   119  			},
   120  		}, {
   121  			&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true},
   122  			[]common.Hash{
   123  				bc.GetBlockByNumber(limit / 2).Hash(),
   124  				bc.GetBlockByNumber(limit/2 - 4).Hash(),
   125  				bc.GetBlockByNumber(limit/2 - 8).Hash(),
   126  			},
   127  		},
   128  		// The chain endpoints should be retrievable
   129  		{
   130  			&getBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1},
   131  			[]common.Hash{bc.GetBlockByNumber(0).Hash()},
   132  		}, {
   133  			&getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64()}, Amount: 1},
   134  			[]common.Hash{bc.CurrentBlock().Hash()},
   135  		},
   136  		// Ensure protocol limits are honored
   137  		/*{
   138  			&getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true},
   139  			bc.GetBlockHashesFromHash(bc.CurrentBlock().Hash(), limit),
   140  		},*/
   141  		// Check that requesting more than available is handled gracefully
   142  		{
   143  			&getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3},
   144  			[]common.Hash{
   145  				bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(),
   146  				bc.GetBlockByNumber(bc.CurrentBlock().NumberU64()).Hash(),
   147  			},
   148  		}, {
   149  			&getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true},
   150  			[]common.Hash{
   151  				bc.GetBlockByNumber(4).Hash(),
   152  				bc.GetBlockByNumber(0).Hash(),
   153  			},
   154  		},
   155  		// Check that requesting more than available is handled gracefully, even if mid skip
   156  		{
   157  			&getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3},
   158  			[]common.Hash{
   159  				bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(),
   160  				bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1).Hash(),
   161  			},
   162  		}, {
   163  			&getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true},
   164  			[]common.Hash{
   165  				bc.GetBlockByNumber(4).Hash(),
   166  				bc.GetBlockByNumber(1).Hash(),
   167  			},
   168  		},
   169  		// Check that non existing headers aren't returned
   170  		{
   171  			&getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1},
   172  			[]common.Hash{},
   173  		}, {
   174  			&getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() + 1}, Amount: 1},
   175  			[]common.Hash{},
   176  		},
   177  	}
   178  	// Run each of the tests and verify the results against the chain
   179  	var reqID uint64
   180  	for i, tt := range tests {
   181  		// Collect the headers to expect in the response
   182  		headers := []*types.Header{}
   183  		for _, hash := range tt.expect {
   184  			headers = append(headers, bc.GetHeaderByHash(hash))
   185  		}
   186  		// Send the hash request and verify the response
   187  		reqID++
   188  		cost := peer.GetRequestCost(GetBlockHeadersMsg, int(tt.query.Amount))
   189  		sendRequest(peer.app, GetBlockHeadersMsg, reqID, cost, tt.query)
   190  		if err := expectResponse(peer.app, BlockHeadersMsg, reqID, testBufLimit, headers); err != nil {
   191  			t.Errorf("test %d: headers mismatch: %v", i, err)
   192  		}
   193  	}
   194  }
   195  
   196  // Tests that block contents can be retrieved from a remote chain based on their hashes.
   197  func TestGetBlockBodiesLes1(t *testing.T) { testGetBlockBodies(t, 1) }
   198  
   199  func TestGetBlockBodiesLes2(t *testing.T) { testGetBlockBodies(t, 2) }
   200  
   201  func testGetBlockBodies(t *testing.T, protocol int) {
   202  	db, _ := ethdb.NewMemDatabase()
   203  	pm := newTestProtocolManagerMust(t, false, downloader.MaxBlockFetch+15, nil, nil, nil, db)
   204  	bc := pm.blockchain.(*core.BlockChain)
   205  	peer, _ := newTestPeer(t, "peer", protocol, pm, true)
   206  	defer peer.close()
   207  
   208  	// Create a batch of tests for various scenarios
   209  	limit := MaxBodyFetch
   210  	tests := []struct {
   211  		random    int           // Number of blocks to fetch randomly from the chain
   212  		explicit  []common.Hash // Explicitly requested blocks
   213  		available []bool        // Availability of explicitly requested blocks
   214  		expected  int           // Total number of existing blocks to expect
   215  	}{
   216  		{1, nil, nil, 1},         // A single random block should be retrievable
   217  		{10, nil, nil, 10},       // Multiple random blocks should be retrievable
   218  		{limit, nil, nil, limit}, // The maximum possible blocks should be retrievable
   219  		//{limit + 1, nil, nil, limit},                                  // No more than the possible block count should be returned
   220  		{0, []common.Hash{bc.Genesis().Hash()}, []bool{true}, 1},      // The genesis block should be retrievable
   221  		{0, []common.Hash{bc.CurrentBlock().Hash()}, []bool{true}, 1}, // The chains head block should be retrievable
   222  		{0, []common.Hash{{}}, []bool{false}, 0},                      // A non existent block should not be returned
   223  
   224  		// Existing and non-existing blocks interleaved should not cause problems
   225  		{0, []common.Hash{
   226  			{},
   227  			bc.GetBlockByNumber(1).Hash(),
   228  			{},
   229  			bc.GetBlockByNumber(10).Hash(),
   230  			{},
   231  			bc.GetBlockByNumber(100).Hash(),
   232  			{},
   233  		}, []bool{false, true, false, true, false, true, false}, 3},
   234  	}
   235  	// Run each of the tests and verify the results against the chain
   236  	var reqID uint64
   237  	for i, tt := range tests {
   238  		// Collect the hashes to request, and the response to expect
   239  		hashes, seen := []common.Hash{}, make(map[int64]bool)
   240  		bodies := []*types.Body{}
   241  
   242  		for j := 0; j < tt.random; j++ {
   243  			for {
   244  				num := rand.Int63n(int64(bc.CurrentBlock().NumberU64()))
   245  				if !seen[num] {
   246  					seen[num] = true
   247  
   248  					block := bc.GetBlockByNumber(uint64(num))
   249  					hashes = append(hashes, block.Hash())
   250  					if len(bodies) < tt.expected {
   251  						bodies = append(bodies, &types.Body{Transactions: block.Transactions(), Uncles: block.Uncles()})
   252  					}
   253  					break
   254  				}
   255  			}
   256  		}
   257  		for j, hash := range tt.explicit {
   258  			hashes = append(hashes, hash)
   259  			if tt.available[j] && len(bodies) < tt.expected {
   260  				block := bc.GetBlockByHash(hash)
   261  				bodies = append(bodies, &types.Body{Transactions: block.Transactions(), Uncles: block.Uncles()})
   262  			}
   263  		}
   264  		reqID++
   265  		// Send the hash request and verify the response
   266  		cost := peer.GetRequestCost(GetBlockBodiesMsg, len(hashes))
   267  		sendRequest(peer.app, GetBlockBodiesMsg, reqID, cost, hashes)
   268  		if err := expectResponse(peer.app, BlockBodiesMsg, reqID, testBufLimit, bodies); err != nil {
   269  			t.Errorf("test %d: bodies mismatch: %v", i, err)
   270  		}
   271  	}
   272  }
   273  
   274  // Tests that the contract codes can be retrieved based on account addresses.
   275  func TestGetCodeLes1(t *testing.T) { testGetCode(t, 1) }
   276  
   277  func TestGetCodeLes2(t *testing.T) { testGetCode(t, 2) }
   278  
   279  func testGetCode(t *testing.T, protocol int) {
   280  	// Assemble the test environment
   281  	db, _ := ethdb.NewMemDatabase()
   282  	pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
   283  	bc := pm.blockchain.(*core.BlockChain)
   284  	peer, _ := newTestPeer(t, "peer", protocol, pm, true)
   285  	defer peer.close()
   286  
   287  	var codereqs []*CodeReq
   288  	var codes [][]byte
   289  
   290  	for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ {
   291  		header := bc.GetHeaderByNumber(i)
   292  		req := &CodeReq{
   293  			BHash:  header.Hash(),
   294  			AccKey: crypto.Keccak256(testContractAddr[:]),
   295  		}
   296  		codereqs = append(codereqs, req)
   297  		if i >= testContractDeployed {
   298  			codes = append(codes, testContractCodeDeployed)
   299  		}
   300  	}
   301  
   302  	cost := peer.GetRequestCost(GetCodeMsg, len(codereqs))
   303  	sendRequest(peer.app, GetCodeMsg, 42, cost, codereqs)
   304  	if err := expectResponse(peer.app, CodeMsg, 42, testBufLimit, codes); err != nil {
   305  		t.Errorf("codes mismatch: %v", err)
   306  	}
   307  }
   308  
   309  // Tests that the transaction receipts can be retrieved based on hashes.
   310  func TestGetReceiptLes1(t *testing.T) { testGetReceipt(t, 1) }
   311  
   312  func TestGetReceiptLes2(t *testing.T) { testGetReceipt(t, 2) }
   313  
   314  func testGetReceipt(t *testing.T, protocol int) {
   315  	// Assemble the test environment
   316  	db, _ := ethdb.NewMemDatabase()
   317  	pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
   318  	bc := pm.blockchain.(*core.BlockChain)
   319  	peer, _ := newTestPeer(t, "peer", protocol, pm, true)
   320  	defer peer.close()
   321  
   322  	// Collect the hashes to request, and the response to expect
   323  	hashes, receipts := []common.Hash{}, []types.Receipts{}
   324  	for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ {
   325  		block := bc.GetBlockByNumber(i)
   326  
   327  		hashes = append(hashes, block.Hash())
   328  		receipts = append(receipts, core.GetBlockReceipts(db, block.Hash(), block.NumberU64()))
   329  	}
   330  	// Send the hash request and verify the response
   331  	cost := peer.GetRequestCost(GetReceiptsMsg, len(hashes))
   332  	sendRequest(peer.app, GetReceiptsMsg, 42, cost, hashes)
   333  	if err := expectResponse(peer.app, ReceiptsMsg, 42, testBufLimit, receipts); err != nil {
   334  		t.Errorf("receipts mismatch: %v", err)
   335  	}
   336  }
   337  
   338  // Tests that trie merkle proofs can be retrieved
   339  func TestGetProofsLes1(t *testing.T) { testGetProofs(t, 1) }
   340  
   341  func TestGetProofsLes2(t *testing.T) { testGetProofs(t, 2) }
   342  
   343  func testGetProofs(t *testing.T, protocol int) {
   344  	// Assemble the test environment
   345  	db, _ := ethdb.NewMemDatabase()
   346  	pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
   347  	bc := pm.blockchain.(*core.BlockChain)
   348  	peer, _ := newTestPeer(t, "peer", protocol, pm, true)
   349  	defer peer.close()
   350  
   351  	var (
   352  		proofreqs []ProofReq
   353  		proofsV1  [][]rlp.RawValue
   354  	)
   355  	proofsV2 := light.NewNodeSet()
   356  
   357  	accounts := []common.Address{testBankAddress, acc1Addr, acc2Addr, {}}
   358  	for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ {
   359  		header := bc.GetHeaderByNumber(i)
   360  		root := header.Root
   361  		trie, _ := trie.New(root, db)
   362  
   363  		for _, acc := range accounts {
   364  			req := ProofReq{
   365  				BHash: header.Hash(),
   366  				Key:   crypto.Keccak256(acc[:]),
   367  			}
   368  			proofreqs = append(proofreqs, req)
   369  
   370  			switch protocol {
   371  			case 1:
   372  				var proof light.NodeList
   373  				trie.Prove(crypto.Keccak256(acc[:]), 0, &proof)
   374  				proofsV1 = append(proofsV1, proof)
   375  			case 2:
   376  				trie.Prove(crypto.Keccak256(acc[:]), 0, proofsV2)
   377  			}
   378  		}
   379  	}
   380  	// Send the proof request and verify the response
   381  	switch protocol {
   382  	case 1:
   383  		cost := peer.GetRequestCost(GetProofsV1Msg, len(proofreqs))
   384  		sendRequest(peer.app, GetProofsV1Msg, 42, cost, proofreqs)
   385  		if err := expectResponse(peer.app, ProofsV1Msg, 42, testBufLimit, proofsV1); err != nil {
   386  			t.Errorf("proofs mismatch: %v", err)
   387  		}
   388  	case 2:
   389  		cost := peer.GetRequestCost(GetProofsV2Msg, len(proofreqs))
   390  		sendRequest(peer.app, GetProofsV2Msg, 42, cost, proofreqs)
   391  		msg, err := peer.app.ReadMsg()
   392  		if err != nil {
   393  			t.Errorf("Message read error: %v", err)
   394  		}
   395  		var resp struct {
   396  			ReqID, BV uint64
   397  			Data      light.NodeList
   398  		}
   399  		if err := msg.Decode(&resp); err != nil {
   400  			t.Errorf("reply decode error: %v", err)
   401  		}
   402  		if msg.Code != ProofsV2Msg {
   403  			t.Errorf("Message code mismatch")
   404  		}
   405  		if resp.ReqID != 42 {
   406  			t.Errorf("ReqID mismatch")
   407  		}
   408  		if resp.BV != testBufLimit {
   409  			t.Errorf("BV mismatch")
   410  		}
   411  		testCheckProof(t, proofsV2, resp.Data)
   412  	}
   413  }
   414  
   415  func TestTransactionStatusLes2(t *testing.T) {
   416  	db, _ := ethdb.NewMemDatabase()
   417  	pm := newTestProtocolManagerMust(t, false, 0, nil, nil, nil, db)
   418  	chain := pm.blockchain.(*core.BlockChain)
   419  	config := core.DefaultTxPoolConfig
   420  	config.Journal = ""
   421  	txpool := core.NewTxPool(config, params.TestChainConfig, chain)
   422  	pm.txpool = txpool
   423  	peer, _ := newTestPeer(t, "peer", 2, pm, true)
   424  	defer peer.close()
   425  
   426  	var reqID uint64
   427  
   428  	test := func(tx *types.Transaction, send bool, expStatus txStatus) {
   429  		reqID++
   430  		if send {
   431  			cost := peer.GetRequestCost(SendTxV2Msg, 1)
   432  			sendRequest(peer.app, SendTxV2Msg, reqID, cost, types.Transactions{tx})
   433  		} else {
   434  			cost := peer.GetRequestCost(GetTxStatusMsg, 1)
   435  			sendRequest(peer.app, GetTxStatusMsg, reqID, cost, []common.Hash{tx.Hash()})
   436  		}
   437  		if err := expectResponse(peer.app, TxStatusMsg, reqID, testBufLimit, []txStatus{expStatus}); err != nil {
   438  			t.Errorf("transaction status mismatch")
   439  		}
   440  	}
   441  
   442  	signer := types.HomesteadSigner{}
   443  
   444  	// test error status by sending an underpriced transaction
   445  	tx0, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey)
   446  	test(tx0, true, txStatus{Status: core.TxStatusUnknown, Error: core.ErrUnderpriced})
   447  
   448  	tx1, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), bigTxGas, big.NewInt(100000000000), nil), signer, testBankKey)
   449  	test(tx1, false, txStatus{Status: core.TxStatusUnknown}) // query before sending, should be unknown
   450  	test(tx1, true, txStatus{Status: core.TxStatusPending})  // send valid processable tx, should return pending
   451  	test(tx1, true, txStatus{Status: core.TxStatusPending})  // adding it again should not return an error
   452  
   453  	tx2, _ := types.SignTx(types.NewTransaction(1, acc1Addr, big.NewInt(10000), bigTxGas, big.NewInt(100000000000), nil), signer, testBankKey)
   454  	tx3, _ := types.SignTx(types.NewTransaction(2, acc1Addr, big.NewInt(10000), bigTxGas, big.NewInt(100000000000), nil), signer, testBankKey)
   455  	// send transactions in the wrong order, tx3 should be queued
   456  	test(tx3, true, txStatus{Status: core.TxStatusQueued})
   457  	test(tx2, true, txStatus{Status: core.TxStatusPending})
   458  	// query again, now tx3 should be pending too
   459  	test(tx3, false, txStatus{Status: core.TxStatusPending})
   460  
   461  	// generate and add a block with tx1 and tx2 included
   462  	gchain, _ := core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), db, 1, func(i int, block *core.BlockGen) {
   463  		block.AddTx(tx1)
   464  		block.AddTx(tx2)
   465  	})
   466  	if _, err := chain.InsertChain(gchain); err != nil {
   467  		panic(err)
   468  	}
   469  	// wait until TxPool processes the inserted block
   470  	for i := 0; i < 10; i++ {
   471  		if pending, _ := txpool.Stats(); pending == 1 {
   472  			break
   473  		}
   474  		time.Sleep(100 * time.Millisecond)
   475  	}
   476  	if pending, _ := txpool.Stats(); pending != 1 {
   477  		t.Fatalf("pending count mismatch: have %d, want 1", pending)
   478  	}
   479  
   480  	// check if their status is included now
   481  	block1hash := core.GetCanonicalHash(db, 1)
   482  	test(tx1, false, txStatus{Status: core.TxStatusIncluded, Lookup: &core.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 0}})
   483  	test(tx2, false, txStatus{Status: core.TxStatusIncluded, Lookup: &core.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 1}})
   484  
   485  	// create a reorg that rolls them back
   486  	gchain, _ = core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), db, 2, func(i int, block *core.BlockGen) {})
   487  	if _, err := chain.InsertChain(gchain); err != nil {
   488  		panic(err)
   489  	}
   490  	// wait until TxPool processes the reorg
   491  	for i := 0; i < 10; i++ {
   492  		if pending, _ := txpool.Stats(); pending == 3 {
   493  			break
   494  		}
   495  		time.Sleep(100 * time.Millisecond)
   496  	}
   497  	if pending, _ := txpool.Stats(); pending != 3 {
   498  		t.Fatalf("pending count mismatch: have %d, want 3", pending)
   499  	}
   500  	// check if their status is pending again
   501  	test(tx1, false, txStatus{Status: core.TxStatusPending})
   502  	test(tx2, false, txStatus{Status: core.TxStatusPending})
   503  }