github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/core/blockchain_test.go (about)

     1  // Copyright 2014 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum 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 Spectrum 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 Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  	"math/rand"
    23  	"sync"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/SmartMeshFoundation/Spectrum/common"
    28  	"github.com/SmartMeshFoundation/Spectrum/consensus/ethash"
    29  	"github.com/SmartMeshFoundation/Spectrum/core/state"
    30  	"github.com/SmartMeshFoundation/Spectrum/core/types"
    31  	"github.com/SmartMeshFoundation/Spectrum/core/vm"
    32  	"github.com/SmartMeshFoundation/Spectrum/crypto"
    33  	"github.com/SmartMeshFoundation/Spectrum/ethdb"
    34  	"github.com/SmartMeshFoundation/Spectrum/params"
    35  )
    36  
    37  // newTestBlockChain creates a blockchain without validation.
    38  func newTestBlockChain(fake bool) *BlockChain {
    39  	db, _ := ethdb.NewMemDatabase()
    40  	gspec := &Genesis{
    41  		Config:     params.TestChainConfig,
    42  		Difficulty: big.NewInt(1),
    43  	}
    44  	gspec.MustCommit(db)
    45  	engine := ethash.NewFullFaker()
    46  	if !fake {
    47  		engine = ethash.NewTester()
    48  	}
    49  	blockchain, err := NewBlockChain(db, gspec.Config, engine, vm.Config{})
    50  	if err != nil {
    51  		panic(err)
    52  	}
    53  	//blockchain.SetValidator(bproc{})
    54  	return blockchain
    55  }
    56  
    57  // Test fork of length N starting from block i
    58  func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) {
    59  	// Copy old chain up to #i into a new db
    60  	db, blockchain2, err := newCanonical(ethash.NewFaker(), i, full)
    61  	if err != nil {
    62  		t.Fatal("could not make new canonical in testFork", err)
    63  	}
    64  	defer blockchain2.Stop()
    65  
    66  	// Assert the chains have the same header/block at #i
    67  	var hash1, hash2 common.Hash
    68  	if full {
    69  		hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash()
    70  		hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash()
    71  	} else {
    72  		hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash()
    73  		hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash()
    74  	}
    75  	if hash1 != hash2 {
    76  		t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1)
    77  	}
    78  	// Extend the newly created chain
    79  	var (
    80  		blockChainB  []*types.Block
    81  		headerChainB []*types.Header
    82  	)
    83  	if full {
    84  		blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed)
    85  		if _, err := blockchain2.InsertChain(blockChainB); err != nil {
    86  			t.Fatalf("failed to insert forking chain: %v", err)
    87  		}
    88  	} else {
    89  		headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, ethash.NewFaker(), db, forkSeed)
    90  		if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil {
    91  			t.Fatalf("failed to insert forking chain: %v", err)
    92  		}
    93  	}
    94  	// Sanity check that the forked chain can be imported into the original
    95  	var tdPre, tdPost *big.Int
    96  
    97  	if full {
    98  		tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash())
    99  		if err := testBlockChainImport(blockChainB, blockchain); err != nil {
   100  			t.Fatalf("failed to import forked block chain: %v", err)
   101  		}
   102  		tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash())
   103  	} else {
   104  		tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash())
   105  		if err := testHeaderChainImport(headerChainB, blockchain); err != nil {
   106  			t.Fatalf("failed to import forked header chain: %v", err)
   107  		}
   108  		tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash())
   109  	}
   110  	// Compare the total difficulties of the chains
   111  	comparator(tdPre, tdPost)
   112  }
   113  
   114  func printChain(bc *BlockChain) {
   115  	for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- {
   116  		b := bc.GetBlockByNumber(uint64(i))
   117  		fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty())
   118  	}
   119  }
   120  
   121  // testBlockChainImport tries to process a chain of blocks, writing them into
   122  // the database if successful.
   123  func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
   124  	for _, block := range chain {
   125  		// Try and process the block
   126  		err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true)
   127  		if err == nil {
   128  			err = blockchain.validator.ValidateBody(blockchain.GetBlockByHash(block.ParentHash()),block)
   129  		}
   130  		if err != nil {
   131  			if err == ErrKnownBlock {
   132  				continue
   133  			}
   134  			return err
   135  		}
   136  		statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache)
   137  		if err != nil {
   138  			return err
   139  		}
   140  		receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{})
   141  		if err != nil {
   142  			blockchain.reportBlock(block, receipts, err)
   143  			return err
   144  		}
   145  		err = blockchain.validator.ValidateState(block, blockchain.GetBlockByHash(block.ParentHash()), statedb, receipts, usedGas)
   146  		if err != nil {
   147  			blockchain.reportBlock(block, receipts, err)
   148  			return err
   149  		}
   150  		blockchain.mu.Lock()
   151  		WriteTd(blockchain.chainDb, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash())))
   152  		WriteBlock(blockchain.chainDb, block)
   153  		statedb.CommitTo(blockchain.chainDb, false)
   154  		blockchain.mu.Unlock()
   155  	}
   156  	return nil
   157  }
   158  
   159  // testHeaderChainImport tries to process a chain of header, writing them into
   160  // the database if successful.
   161  func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error {
   162  	for _, header := range chain {
   163  		// Try and validate the header
   164  		if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil {
   165  			return err
   166  		}
   167  		// Manually insert the header into the database, but don't reorganise (allows subsequent testing)
   168  		blockchain.mu.Lock()
   169  		WriteTd(blockchain.chainDb, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash)))
   170  		WriteHeader(blockchain.chainDb, header)
   171  		blockchain.mu.Unlock()
   172  	}
   173  	return nil
   174  }
   175  
   176  func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) {
   177  	_, err := blockchain.InsertChain(chain)
   178  	if err != nil {
   179  		fmt.Println(err)
   180  		t.FailNow()
   181  	}
   182  	done <- true
   183  }
   184  
   185  func TestLastBlock(t *testing.T) {
   186  	bchain := newTestBlockChain(false)
   187  	defer bchain.Stop()
   188  
   189  	block := makeBlockChain(bchain.CurrentBlock(), 1, ethash.NewFaker(), bchain.chainDb, 0)[0]
   190  	bchain.insert(block)
   191  	if block.Hash() != GetHeadBlockHash(bchain.chainDb) {
   192  		t.Errorf("Write/Get HeadBlockHash failed")
   193  	}
   194  }
   195  
   196  // Tests that given a starting canonical chain of a given size, it can be extended
   197  // with various length chains.
   198  func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) }
   199  func TestExtendCanonicalBlocks(t *testing.T)  { testExtendCanonical(t, true) }
   200  
   201  func testExtendCanonical(t *testing.T, full bool) {
   202  	length := 5
   203  
   204  	// Make first chain starting from genesis
   205  	_, processor, err := newCanonical(ethash.NewFaker(), length, full)
   206  	if err != nil {
   207  		t.Fatalf("failed to make new canonical chain: %v", err)
   208  	}
   209  	defer processor.Stop()
   210  
   211  	// Define the difficulty comparator
   212  	better := func(td1, td2 *big.Int) {
   213  		if td2.Cmp(td1) <= 0 {
   214  			t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1)
   215  		}
   216  	}
   217  	// Start fork from current height
   218  	testFork(t, processor, length, 1, full, better)
   219  	testFork(t, processor, length, 2, full, better)
   220  	testFork(t, processor, length, 5, full, better)
   221  	testFork(t, processor, length, 10, full, better)
   222  }
   223  
   224  // Tests that given a starting canonical chain of a given size, creating shorter
   225  // forks do not take canonical ownership.
   226  func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) }
   227  func TestShorterForkBlocks(t *testing.T)  { testShorterFork(t, true) }
   228  
   229  func testShorterFork(t *testing.T, full bool) {
   230  	length := 10
   231  
   232  	// Make first chain starting from genesis
   233  	_, processor, err := newCanonical(ethash.NewFaker(), length, full)
   234  	if err != nil {
   235  		t.Fatalf("failed to make new canonical chain: %v", err)
   236  	}
   237  	defer processor.Stop()
   238  
   239  	// Define the difficulty comparator
   240  	worse := func(td1, td2 *big.Int) {
   241  		if td2.Cmp(td1) >= 0 {
   242  			t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1)
   243  		}
   244  	}
   245  	// Sum of numbers must be less than `length` for this to be a shorter fork
   246  	testFork(t, processor, 0, 3, full, worse)
   247  	testFork(t, processor, 0, 7, full, worse)
   248  	testFork(t, processor, 1, 1, full, worse)
   249  	testFork(t, processor, 1, 7, full, worse)
   250  	testFork(t, processor, 5, 3, full, worse)
   251  	testFork(t, processor, 5, 4, full, worse)
   252  }
   253  
   254  // Tests that given a starting canonical chain of a given size, creating longer
   255  // forks do take canonical ownership.
   256  func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) }
   257  func TestLongerForkBlocks(t *testing.T)  { testLongerFork(t, true) }
   258  
   259  func testLongerFork(t *testing.T, full bool) {
   260  	length := 10
   261  
   262  	// Make first chain starting from genesis
   263  	_, processor, err := newCanonical(ethash.NewFaker(), length, full)
   264  	if err != nil {
   265  		t.Fatalf("failed to make new canonical chain: %v", err)
   266  	}
   267  	defer processor.Stop()
   268  
   269  	// Define the difficulty comparator
   270  	better := func(td1, td2 *big.Int) {
   271  		if td2.Cmp(td1) <= 0 {
   272  			t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1)
   273  		}
   274  	}
   275  	// Sum of numbers must be greater than `length` for this to be a longer fork
   276  	testFork(t, processor, 0, 11, full, better)
   277  	testFork(t, processor, 0, 15, full, better)
   278  	testFork(t, processor, 1, 10, full, better)
   279  	testFork(t, processor, 1, 12, full, better)
   280  	testFork(t, processor, 5, 6, full, better)
   281  	testFork(t, processor, 5, 8, full, better)
   282  }
   283  
   284  // Tests that given a starting canonical chain of a given size, creating equal
   285  // forks do take canonical ownership.
   286  func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) }
   287  func TestEqualForkBlocks(t *testing.T)  { testEqualFork(t, true) }
   288  
   289  func testEqualFork(t *testing.T, full bool) {
   290  	length := 10
   291  
   292  	// Make first chain starting from genesis
   293  	_, processor, err := newCanonical(ethash.NewFaker(), length, full)
   294  	if err != nil {
   295  		t.Fatalf("failed to make new canonical chain: %v", err)
   296  	}
   297  	defer processor.Stop()
   298  
   299  	// Define the difficulty comparator
   300  	equal := func(td1, td2 *big.Int) {
   301  		if td2.Cmp(td1) != 0 {
   302  			t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1)
   303  		}
   304  	}
   305  	// Sum of numbers must be equal to `length` for this to be an equal fork
   306  	testFork(t, processor, 0, 10, full, equal)
   307  	testFork(t, processor, 1, 9, full, equal)
   308  	testFork(t, processor, 2, 8, full, equal)
   309  	testFork(t, processor, 5, 5, full, equal)
   310  	testFork(t, processor, 6, 4, full, equal)
   311  	testFork(t, processor, 9, 1, full, equal)
   312  }
   313  
   314  // Tests that chains missing links do not get accepted by the processor.
   315  func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) }
   316  func TestBrokenBlockChain(t *testing.T)  { testBrokenChain(t, true) }
   317  
   318  func testBrokenChain(t *testing.T, full bool) {
   319  	// Make chain starting from genesis
   320  	db, blockchain, err := newCanonical(ethash.NewFaker(), 10, full)
   321  	if err != nil {
   322  		t.Fatalf("failed to make new canonical chain: %v", err)
   323  	}
   324  	defer blockchain.Stop()
   325  
   326  	// Create a forked chain, and try to insert with a missing link
   327  	if full {
   328  		chain := makeBlockChain(blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed)[1:]
   329  		if err := testBlockChainImport(chain, blockchain); err == nil {
   330  			t.Errorf("broken block chain not reported")
   331  		}
   332  	} else {
   333  		chain := makeHeaderChain(blockchain.CurrentHeader(), 5, ethash.NewFaker(), db, forkSeed)[1:]
   334  		if err := testHeaderChainImport(chain, blockchain); err == nil {
   335  			t.Errorf("broken header chain not reported")
   336  		}
   337  	}
   338  }
   339  
   340  type bproc struct{}
   341  
   342  func (bproc) ValidateBody(*types.Block) error { return nil }
   343  func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error {
   344  	return nil
   345  }
   346  func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) {
   347  	return nil, nil, new(big.Int), nil
   348  }
   349  
   350  func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Header {
   351  	blocks := makeBlockChainWithDiff(genesis, d, seed)
   352  	headers := make([]*types.Header, len(blocks))
   353  	for i, block := range blocks {
   354  		headers[i] = block.Header()
   355  	}
   356  	return headers
   357  }
   358  
   359  func makeBlockChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block {
   360  	var chain []*types.Block
   361  	for i, difficulty := range d {
   362  		header := &types.Header{
   363  			Coinbase:    common.Address{seed},
   364  			Number:      big.NewInt(int64(i + 1)),
   365  			Difficulty:  big.NewInt(int64(difficulty)),
   366  			UncleHash:   types.EmptyUncleHash,
   367  			TxHash:      types.EmptyRootHash,
   368  			ReceiptHash: types.EmptyRootHash,
   369  			Time:        big.NewInt(int64(i) + 1),
   370  		}
   371  		if i == 0 {
   372  			header.ParentHash = genesis.Hash()
   373  		} else {
   374  			header.ParentHash = chain[i-1].Hash()
   375  		}
   376  		block := types.NewBlockWithHeader(header)
   377  		chain = append(chain, block)
   378  	}
   379  	return chain
   380  }
   381  
   382  // Tests that reorganising a long difficult chain after a short easy one
   383  // overwrites the canonical numbers and links in the database.
   384  func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) }
   385  func TestReorgLongBlocks(t *testing.T)  { testReorgLong(t, true) }
   386  
   387  func testReorgLong(t *testing.T, full bool) {
   388  	testReorg(t, []int{1, 2, 4}, []int{1, 2, 3, 4}, 10, full)
   389  }
   390  
   391  // Tests that reorganising a short difficult chain after a long easy one
   392  // overwrites the canonical numbers and links in the database.
   393  func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) }
   394  func TestReorgShortBlocks(t *testing.T)  { testReorgShort(t, true) }
   395  
   396  func testReorgShort(t *testing.T, full bool) {
   397  	testReorg(t, []int{1, 2, 3, 4}, []int{1, 10}, 11, full)
   398  }
   399  
   400  func testReorg(t *testing.T, first, second []int, td int64, full bool) {
   401  	bc := newTestBlockChain(true)
   402  	defer bc.Stop()
   403  
   404  	// Insert an easy and a difficult chain afterwards
   405  	if full {
   406  		bc.InsertChain(makeBlockChainWithDiff(bc.genesisBlock, first, 11))
   407  		bc.InsertChain(makeBlockChainWithDiff(bc.genesisBlock, second, 22))
   408  	} else {
   409  		bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, first, 11), 1)
   410  		bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, second, 22), 1)
   411  	}
   412  	// Check that the chain is valid number and link wise
   413  	if full {
   414  		prev := bc.CurrentBlock()
   415  		for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) {
   416  			if prev.ParentHash() != block.Hash() {
   417  				t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash())
   418  			}
   419  		}
   420  	} else {
   421  		prev := bc.CurrentHeader()
   422  		for header := bc.GetHeaderByNumber(bc.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, bc.GetHeaderByNumber(header.Number.Uint64()-1) {
   423  			if prev.ParentHash != header.Hash() {
   424  				t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash())
   425  			}
   426  		}
   427  	}
   428  	// Make sure the chain total difficulty is the correct one
   429  	want := new(big.Int).Add(bc.genesisBlock.Difficulty(), big.NewInt(td))
   430  	if full {
   431  		if have := bc.GetTdByHash(bc.CurrentBlock().Hash()); have.Cmp(want) != 0 {
   432  			t.Errorf("total difficulty mismatch: have %v, want %v", have, want)
   433  		}
   434  	} else {
   435  		if have := bc.GetTdByHash(bc.CurrentHeader().Hash()); have.Cmp(want) != 0 {
   436  			t.Errorf("total difficulty mismatch: have %v, want %v", have, want)
   437  		}
   438  	}
   439  }
   440  
   441  // Tests that the insertion functions detect banned hashes.
   442  func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) }
   443  func TestBadBlockHashes(t *testing.T)  { testBadHashes(t, true) }
   444  
   445  func testBadHashes(t *testing.T, full bool) {
   446  	bc := newTestBlockChain(true)
   447  	defer bc.Stop()
   448  
   449  	// Create a chain, ban a hash and try to import
   450  	var err error
   451  	if full {
   452  		blocks := makeBlockChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10)
   453  		BadHashes[blocks[2].Header().Hash()] = true
   454  		_, err = bc.InsertChain(blocks)
   455  	} else {
   456  		headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10)
   457  		BadHashes[headers[2].Hash()] = true
   458  		_, err = bc.InsertHeaderChain(headers, 1)
   459  	}
   460  	if err != ErrBlacklistedHash {
   461  		t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash)
   462  	}
   463  }
   464  
   465  // Tests that bad hashes are detected on boot, and the chain rolled back to a
   466  // good state prior to the bad hash.
   467  func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) }
   468  func TestReorgBadBlockHashes(t *testing.T)  { testReorgBadHashes(t, true) }
   469  
   470  func testReorgBadHashes(t *testing.T, full bool) {
   471  	bc := newTestBlockChain(true)
   472  	defer bc.Stop()
   473  
   474  	// Create a chain, import and ban afterwards
   475  	headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10)
   476  	blocks := makeBlockChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10)
   477  
   478  	if full {
   479  		if _, err := bc.InsertChain(blocks); err != nil {
   480  			t.Fatalf("failed to import blocks: %v", err)
   481  		}
   482  		if bc.CurrentBlock().Hash() != blocks[3].Hash() {
   483  			t.Errorf("last block hash mismatch: have: %x, want %x", bc.CurrentBlock().Hash(), blocks[3].Header().Hash())
   484  		}
   485  		BadHashes[blocks[3].Header().Hash()] = true
   486  		defer func() { delete(BadHashes, blocks[3].Header().Hash()) }()
   487  	} else {
   488  		if _, err := bc.InsertHeaderChain(headers, 1); err != nil {
   489  			t.Fatalf("failed to import headers: %v", err)
   490  		}
   491  		if bc.CurrentHeader().Hash() != headers[3].Hash() {
   492  			t.Errorf("last header hash mismatch: have: %x, want %x", bc.CurrentHeader().Hash(), headers[3].Hash())
   493  		}
   494  		BadHashes[headers[3].Hash()] = true
   495  		defer func() { delete(BadHashes, headers[3].Hash()) }()
   496  	}
   497  
   498  	// Create a new BlockChain and check that it rolled back the state.
   499  	ncm, err := NewBlockChain(bc.chainDb, bc.config, ethash.NewFaker(), vm.Config{})
   500  	if err != nil {
   501  		t.Fatalf("failed to create new chain manager: %v", err)
   502  	}
   503  	defer ncm.Stop()
   504  
   505  	if full {
   506  		if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() {
   507  			t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash())
   508  		}
   509  		if blocks[2].Header().GasLimit.Cmp(ncm.GasLimit()) != 0 {
   510  			t.Errorf("last  block gasLimit mismatch: have: %x, want %x", ncm.GasLimit(), blocks[2].Header().GasLimit)
   511  		}
   512  	} else {
   513  		if ncm.CurrentHeader().Hash() != headers[2].Hash() {
   514  			t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash())
   515  		}
   516  	}
   517  }
   518  
   519  // Tests chain insertions in the face of one entity containing an invalid nonce.
   520  func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) }
   521  func TestBlocksInsertNonceError(t *testing.T)  { testInsertNonceError(t, true) }
   522  
   523  func testInsertNonceError(t *testing.T, full bool) {
   524  	for i := 1; i < 25 && !t.Failed(); i++ {
   525  		// Create a pristine chain and database
   526  		db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full)
   527  		if err != nil {
   528  			t.Fatalf("failed to create pristine chain: %v", err)
   529  		}
   530  		defer blockchain.Stop()
   531  
   532  		// Create and insert a chain with a failing nonce
   533  		var (
   534  			failAt  int
   535  			failRes int
   536  			failNum uint64
   537  		)
   538  		if full {
   539  			blocks := makeBlockChain(blockchain.CurrentBlock(), i, ethash.NewFaker(), db, 0)
   540  
   541  			failAt = rand.Int() % len(blocks)
   542  			failNum = blocks[failAt].NumberU64()
   543  
   544  			blockchain.engine = ethash.NewFakeFailer(failNum)
   545  			failRes, err = blockchain.InsertChain(blocks)
   546  		} else {
   547  			headers := makeHeaderChain(blockchain.CurrentHeader(), i, ethash.NewFaker(), db, 0)
   548  
   549  			failAt = rand.Int() % len(headers)
   550  			failNum = headers[failAt].Number.Uint64()
   551  
   552  			blockchain.engine = ethash.NewFakeFailer(failNum)
   553  			blockchain.hc.engine = blockchain.engine
   554  			failRes, err = blockchain.InsertHeaderChain(headers, 1)
   555  		}
   556  		// Check that the returned error indicates the failure.
   557  		if failRes != failAt {
   558  			t.Errorf("test %d: failure index mismatch: have %d, want %d", i, failRes, failAt)
   559  		}
   560  		// Check that all no blocks after the failing block have been inserted.
   561  		for j := 0; j < i-failAt; j++ {
   562  			if full {
   563  				if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil {
   564  					t.Errorf("test %d: invalid block in chain: %v", i, block)
   565  				}
   566  			} else {
   567  				if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil {
   568  					t.Errorf("test %d: invalid header in chain: %v", i, header)
   569  				}
   570  			}
   571  		}
   572  	}
   573  }
   574  
   575  // Tests that fast importing a block chain produces the same chain data as the
   576  // classical full block processing.
   577  func TestFastVsFullChains(t *testing.T) {
   578  	// Configure and generate a sample block chain
   579  	var (
   580  		gendb, _ = ethdb.NewMemDatabase()
   581  		key, _   = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   582  		address  = crypto.PubkeyToAddress(key.PublicKey)
   583  		funds    = big.NewInt(1000000000)
   584  		gspec    = &Genesis{
   585  			Config: params.TestChainConfig,
   586  			Alloc:  GenesisAlloc{address: {Balance: funds}},
   587  		}
   588  		genesis = gspec.MustCommit(gendb)
   589  		signer  = types.NewEIP155Signer(gspec.Config.ChainId)
   590  	)
   591  	blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, 1024, func(i int, block *BlockGen) {
   592  		block.SetCoinbase(common.Address{0x00})
   593  
   594  		// If the block number is multiple of 3, send a few bonus transactions to the miner
   595  		if i%3 == 2 {
   596  			for j := 0; j < i%4+1; j++ {
   597  				tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), bigTxGas, nil, nil), signer, key)
   598  				if err != nil {
   599  					panic(err)
   600  				}
   601  				block.AddTx(tx)
   602  			}
   603  		}
   604  		// If the block number is a multiple of 5, add a few bonus uncles to the block
   605  		if i%5 == 5 {
   606  			block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))})
   607  		}
   608  	})
   609  	// Import the chain as an archive node for the comparison baseline
   610  	archiveDb, _ := ethdb.NewMemDatabase()
   611  	gspec.MustCommit(archiveDb)
   612  	archive, _ := NewBlockChain(archiveDb, gspec.Config, ethash.NewFaker(), vm.Config{})
   613  	defer archive.Stop()
   614  
   615  	if n, err := archive.InsertChain(blocks); err != nil {
   616  		t.Fatalf("failed to process block %d: %v", n, err)
   617  	}
   618  	// Fast import the chain as a non-archive node to test
   619  	fastDb, _ := ethdb.NewMemDatabase()
   620  	gspec.MustCommit(fastDb)
   621  	fast, _ := NewBlockChain(fastDb, gspec.Config, ethash.NewFaker(), vm.Config{})
   622  	defer fast.Stop()
   623  
   624  	headers := make([]*types.Header, len(blocks))
   625  	for i, block := range blocks {
   626  		headers[i] = block.Header()
   627  	}
   628  	if n, err := fast.InsertHeaderChain(headers, 1); err != nil {
   629  		t.Fatalf("failed to insert header %d: %v", n, err)
   630  	}
   631  	if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil {
   632  		t.Fatalf("failed to insert receipt %d: %v", n, err)
   633  	}
   634  	// Iterate over all chain data components, and cross reference
   635  	for i := 0; i < len(blocks); i++ {
   636  		num, hash := blocks[i].NumberU64(), blocks[i].Hash()
   637  
   638  		if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 {
   639  			t.Errorf("block #%d [%x]: td mismatch: have %v, want %v", num, hash, ftd, atd)
   640  		}
   641  		if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() {
   642  			t.Errorf("block #%d [%x]: header mismatch: have %v, want %v", num, hash, fheader, aheader)
   643  		}
   644  		if fblock, ablock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash); fblock.Hash() != ablock.Hash() {
   645  			t.Errorf("block #%d [%x]: block mismatch: have %v, want %v", num, hash, fblock, ablock)
   646  		} else if types.DeriveSha(fblock.Transactions()) != types.DeriveSha(ablock.Transactions()) {
   647  			t.Errorf("block #%d [%x]: transactions mismatch: have %v, want %v", num, hash, fblock.Transactions(), ablock.Transactions())
   648  		} else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(ablock.Uncles()) {
   649  			t.Errorf("block #%d [%x]: uncles mismatch: have %v, want %v", num, hash, fblock.Uncles(), ablock.Uncles())
   650  		}
   651  		if freceipts, areceipts := GetBlockReceipts(fastDb, hash, GetBlockNumber(fastDb, hash)), GetBlockReceipts(archiveDb, hash, GetBlockNumber(archiveDb, hash)); types.DeriveSha(freceipts) != types.DeriveSha(areceipts) {
   652  			t.Errorf("block #%d [%x]: receipts mismatch: have %v, want %v", num, hash, freceipts, areceipts)
   653  		}
   654  	}
   655  	// Check that the canonical chains are the same between the databases
   656  	for i := 0; i < len(blocks)+1; i++ {
   657  		if fhash, ahash := GetCanonicalHash(fastDb, uint64(i)), GetCanonicalHash(archiveDb, uint64(i)); fhash != ahash {
   658  			t.Errorf("block #%d: canonical hash mismatch: have %v, want %v", i, fhash, ahash)
   659  		}
   660  	}
   661  }
   662  
   663  // Tests that various import methods move the chain head pointers to the correct
   664  // positions.
   665  func TestLightVsFastVsFullChainHeads(t *testing.T) {
   666  	// Configure and generate a sample block chain
   667  	var (
   668  		gendb, _ = ethdb.NewMemDatabase()
   669  		key, _   = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   670  		address  = crypto.PubkeyToAddress(key.PublicKey)
   671  		funds    = big.NewInt(1000000000)
   672  		gspec    = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}}
   673  		genesis  = gspec.MustCommit(gendb)
   674  	)
   675  	height := uint64(1024)
   676  	blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil)
   677  
   678  	// Configure a subchain to roll back
   679  	remove := []common.Hash{}
   680  	for _, block := range blocks[height/2:] {
   681  		remove = append(remove, block.Hash())
   682  	}
   683  	// Create a small assertion method to check the three heads
   684  	assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) {
   685  		if num := chain.CurrentBlock().NumberU64(); num != block {
   686  			t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block)
   687  		}
   688  		if num := chain.CurrentFastBlock().NumberU64(); num != fast {
   689  			t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast)
   690  		}
   691  		if num := chain.CurrentHeader().Number.Uint64(); num != header {
   692  			t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header)
   693  		}
   694  	}
   695  	// Import the chain as an archive node and ensure all pointers are updated
   696  	archiveDb, _ := ethdb.NewMemDatabase()
   697  	gspec.MustCommit(archiveDb)
   698  
   699  	archive, _ := NewBlockChain(archiveDb, gspec.Config, ethash.NewFaker(), vm.Config{})
   700  	if n, err := archive.InsertChain(blocks); err != nil {
   701  		t.Fatalf("failed to process block %d: %v", n, err)
   702  	}
   703  	defer archive.Stop()
   704  
   705  	assert(t, "archive", archive, height, height, height)
   706  	archive.Rollback(remove)
   707  	assert(t, "archive", archive, height/2, height/2, height/2)
   708  
   709  	// Import the chain as a non-archive node and ensure all pointers are updated
   710  	fastDb, _ := ethdb.NewMemDatabase()
   711  	gspec.MustCommit(fastDb)
   712  	fast, _ := NewBlockChain(fastDb, gspec.Config, ethash.NewFaker(), vm.Config{})
   713  	defer fast.Stop()
   714  
   715  	headers := make([]*types.Header, len(blocks))
   716  	for i, block := range blocks {
   717  		headers[i] = block.Header()
   718  	}
   719  	if n, err := fast.InsertHeaderChain(headers, 1); err != nil {
   720  		t.Fatalf("failed to insert header %d: %v", n, err)
   721  	}
   722  	if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil {
   723  		t.Fatalf("failed to insert receipt %d: %v", n, err)
   724  	}
   725  	assert(t, "fast", fast, height, height, 0)
   726  	fast.Rollback(remove)
   727  	assert(t, "fast", fast, height/2, height/2, 0)
   728  
   729  	// Import the chain as a light node and ensure all pointers are updated
   730  	lightDb, _ := ethdb.NewMemDatabase()
   731  	gspec.MustCommit(lightDb)
   732  
   733  	light, _ := NewBlockChain(lightDb, gspec.Config, ethash.NewFaker(), vm.Config{})
   734  	if n, err := light.InsertHeaderChain(headers, 1); err != nil {
   735  		t.Fatalf("failed to insert header %d: %v", n, err)
   736  	}
   737  	defer light.Stop()
   738  
   739  	assert(t, "light", light, height, 0, 0)
   740  	light.Rollback(remove)
   741  	assert(t, "light", light, height/2, 0, 0)
   742  }
   743  
   744  // Tests that chain reorganisations handle transaction removals and reinsertions.
   745  func TestChainTxReorgs(t *testing.T) {
   746  	var (
   747  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   748  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   749  		key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
   750  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   751  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   752  		addr3   = crypto.PubkeyToAddress(key3.PublicKey)
   753  		db, _   = ethdb.NewMemDatabase()
   754  		gspec   = &Genesis{
   755  			Config:   params.TestChainConfig,
   756  			GasLimit: 3141592,
   757  			Alloc: GenesisAlloc{
   758  				addr1: {Balance: big.NewInt(1000000)},
   759  				addr2: {Balance: big.NewInt(1000000)},
   760  				addr3: {Balance: big.NewInt(1000000)},
   761  			},
   762  		}
   763  		genesis = gspec.MustCommit(db)
   764  		signer  = types.NewEIP155Signer(gspec.Config.ChainId)
   765  	)
   766  
   767  	// Create two transactions shared between the chains:
   768  	//  - postponed: transaction included at a later block in the forked chain
   769  	//  - swapped: transaction included at the same block number in the forked chain
   770  	postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), bigTxGas, nil, nil), signer, key1)
   771  	swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), bigTxGas, nil, nil), signer, key1)
   772  
   773  	// Create two transactions that will be dropped by the forked chain:
   774  	//  - pastDrop: transaction dropped retroactively from a past block
   775  	//  - freshDrop: transaction dropped exactly at the block where the reorg is detected
   776  	var pastDrop, freshDrop *types.Transaction
   777  
   778  	// Create three transactions that will be added in the forked chain:
   779  	//  - pastAdd:   transaction added before the reorganization is detected
   780  	//  - freshAdd:  transaction added at the exact block the reorg is detected
   781  	//  - futureAdd: transaction added after the reorg has already finished
   782  	var pastAdd, freshAdd, futureAdd *types.Transaction
   783  
   784  	chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {
   785  		switch i {
   786  		case 0:
   787  			pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key2)
   788  
   789  			gen.AddTx(pastDrop)  // This transaction will be dropped in the fork from below the split point
   790  			gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork
   791  
   792  		case 2:
   793  			freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key2)
   794  
   795  			gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point
   796  			gen.AddTx(swapped)   // This transaction will be swapped out at the exact height
   797  
   798  			gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain
   799  		}
   800  	})
   801  	// Import the chain. This runs all block validation rules.
   802  	blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
   803  	if i, err := blockchain.InsertChain(chain); err != nil {
   804  		t.Fatalf("failed to insert original chain[%d]: %v", i, err)
   805  	}
   806  	defer blockchain.Stop()
   807  
   808  	// overwrite the old chain
   809  	chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) {
   810  		switch i {
   811  		case 0:
   812  			pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3)
   813  			gen.AddTx(pastAdd) // This transaction needs to be injected during reorg
   814  
   815  		case 2:
   816  			gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain
   817  			gen.AddTx(swapped)   // This transaction was swapped from the exact current spot in the original chain
   818  
   819  			freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3)
   820  			gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time
   821  
   822  		case 3:
   823  			futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3)
   824  			gen.AddTx(futureAdd) // This transaction will be added after a full reorg
   825  		}
   826  	})
   827  	if _, err := blockchain.InsertChain(chain); err != nil {
   828  		t.Fatalf("failed to insert forked chain: %v", err)
   829  	}
   830  
   831  	// removed tx
   832  	for i, tx := range (types.Transactions{pastDrop, freshDrop}) {
   833  		if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn != nil {
   834  			t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn)
   835  		}
   836  		if rcpt, _, _, _ := GetReceipt(db, tx.Hash()); rcpt != nil {
   837  			t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt)
   838  		}
   839  	}
   840  	// added tx
   841  	for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) {
   842  		if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn == nil {
   843  			t.Errorf("add %d: expected tx to be found", i)
   844  		}
   845  		if rcpt, _, _, _ := GetReceipt(db, tx.Hash()); rcpt == nil {
   846  			t.Errorf("add %d: expected receipt to be found", i)
   847  		}
   848  	}
   849  	// shared tx
   850  	for i, tx := range (types.Transactions{postponed, swapped}) {
   851  		if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn == nil {
   852  			t.Errorf("share %d: expected tx to be found", i)
   853  		}
   854  		if rcpt, _, _, _ := GetReceipt(db, tx.Hash()); rcpt == nil {
   855  			t.Errorf("share %d: expected receipt to be found", i)
   856  		}
   857  	}
   858  }
   859  
   860  func TestLogReorgs(t *testing.T) {
   861  
   862  	var (
   863  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   864  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   865  		db, _   = ethdb.NewMemDatabase()
   866  		// this code generates a log
   867  		code    = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
   868  		gspec   = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}}
   869  		genesis = gspec.MustCommit(db)
   870  		signer  = types.NewEIP155Signer(gspec.Config.ChainId)
   871  	)
   872  
   873  	blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
   874  	defer blockchain.Stop()
   875  
   876  	rmLogsCh := make(chan RemovedLogsEvent)
   877  	blockchain.SubscribeRemovedLogsEvent(rmLogsCh)
   878  	chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) {
   879  		if i == 1 {
   880  			tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), code), signer, key1)
   881  			if err != nil {
   882  				t.Fatalf("failed to create tx: %v", err)
   883  			}
   884  			gen.AddTx(tx)
   885  		}
   886  	})
   887  	if _, err := blockchain.InsertChain(chain); err != nil {
   888  		t.Fatalf("failed to insert chain: %v", err)
   889  	}
   890  
   891  	chain, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {})
   892  	if _, err := blockchain.InsertChain(chain); err != nil {
   893  		t.Fatalf("failed to insert forked chain: %v", err)
   894  	}
   895  
   896  	timeout := time.NewTimer(1 * time.Second)
   897  	select {
   898  	case ev := <-rmLogsCh:
   899  		if len(ev.Logs) == 0 {
   900  			t.Error("expected logs")
   901  		}
   902  	case <-timeout.C:
   903  		t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.")
   904  	}
   905  }
   906  
   907  func TestReorgSideEvent(t *testing.T) {
   908  	var (
   909  		db, _   = ethdb.NewMemDatabase()
   910  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   911  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   912  		gspec   = &Genesis{
   913  			Config: params.TestChainConfig,
   914  			Alloc:  GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}},
   915  		}
   916  		genesis = gspec.MustCommit(db)
   917  		signer  = types.NewEIP155Signer(gspec.Config.ChainId)
   918  	)
   919  
   920  	blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
   921  	defer blockchain.Stop()
   922  
   923  	chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {})
   924  	if _, err := blockchain.InsertChain(chain); err != nil {
   925  		t.Fatalf("failed to insert chain: %v", err)
   926  	}
   927  
   928  	replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) {
   929  		tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil), signer, key1)
   930  		if i == 2 {
   931  			gen.OffsetTime(-9)
   932  		}
   933  		if err != nil {
   934  			t.Fatalf("failed to create tx: %v", err)
   935  		}
   936  		gen.AddTx(tx)
   937  	})
   938  	chainSideCh := make(chan ChainSideEvent, 64)
   939  	blockchain.SubscribeChainSideEvent(chainSideCh)
   940  	if _, err := blockchain.InsertChain(replacementBlocks); err != nil {
   941  		t.Fatalf("failed to insert chain: %v", err)
   942  	}
   943  
   944  	// first two block of the secondary chain are for a brief moment considered
   945  	// side chains because up to that point the first one is considered the
   946  	// heavier chain.
   947  	expectedSideHashes := map[common.Hash]bool{
   948  		replacementBlocks[0].Hash(): true,
   949  		replacementBlocks[1].Hash(): true,
   950  		chain[0].Hash():             true,
   951  		chain[1].Hash():             true,
   952  		chain[2].Hash():             true,
   953  	}
   954  
   955  	i := 0
   956  
   957  	const timeoutDura = 10 * time.Second
   958  	timeout := time.NewTimer(timeoutDura)
   959  done:
   960  	for {
   961  		select {
   962  		case ev := <-chainSideCh:
   963  			block := ev.Block
   964  			if _, ok := expectedSideHashes[block.Hash()]; !ok {
   965  				t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash())
   966  			}
   967  			i++
   968  
   969  			if i == len(expectedSideHashes) {
   970  				timeout.Stop()
   971  
   972  				break done
   973  			}
   974  			timeout.Reset(timeoutDura)
   975  
   976  		case <-timeout.C:
   977  			t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent")
   978  		}
   979  	}
   980  
   981  	// make sure no more events are fired
   982  	select {
   983  	case e := <-chainSideCh:
   984  		t.Errorf("unexpected event fired: %v", e)
   985  	case <-time.After(250 * time.Millisecond):
   986  	}
   987  
   988  }
   989  
   990  // Tests if the canonical block can be fetched from the database during chain insertion.
   991  func TestCanonicalBlockRetrieval(t *testing.T) {
   992  	bc := newTestBlockChain(true)
   993  	defer bc.Stop()
   994  
   995  	chain, _ := GenerateChain(bc.config, bc.genesisBlock, ethash.NewFaker(), bc.chainDb, 10, func(i int, gen *BlockGen) {})
   996  
   997  	var pend sync.WaitGroup
   998  	pend.Add(len(chain))
   999  
  1000  	for i := range chain {
  1001  		go func(block *types.Block) {
  1002  			defer pend.Done()
  1003  
  1004  			// try to retrieve a block by its canonical hash and see if the block data can be retrieved.
  1005  			for {
  1006  				ch := GetCanonicalHash(bc.chainDb, block.NumberU64())
  1007  				if ch == (common.Hash{}) {
  1008  					continue // busy wait for canonical hash to be written
  1009  				}
  1010  				if ch != block.Hash() {
  1011  					t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex())
  1012  				}
  1013  				fb := GetBlock(bc.chainDb, ch, block.NumberU64())
  1014  				if fb == nil {
  1015  					t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex())
  1016  				}
  1017  				if fb.Hash() != block.Hash() {
  1018  					t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex())
  1019  				}
  1020  				return
  1021  			}
  1022  		}(chain[i])
  1023  
  1024  		if _, err := bc.InsertChain(types.Blocks{chain[i]}); err != nil {
  1025  			t.Fatalf("failed to insert block %d: %v", i, err)
  1026  		}
  1027  	}
  1028  	pend.Wait()
  1029  }
  1030  
  1031  func TestEIP155Transition(t *testing.T) {
  1032  	// Configure and generate a sample block chain
  1033  	var (
  1034  		db, _      = ethdb.NewMemDatabase()
  1035  		key, _     = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1036  		address    = crypto.PubkeyToAddress(key.PublicKey)
  1037  		funds      = big.NewInt(1000000000)
  1038  		deleteAddr = common.Address{1}
  1039  		gspec      = &Genesis{
  1040  			Config: &params.ChainConfig{ChainId: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)},
  1041  			Alloc:  GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}},
  1042  		}
  1043  		genesis = gspec.MustCommit(db)
  1044  	)
  1045  
  1046  	blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
  1047  	defer blockchain.Stop()
  1048  
  1049  	blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) {
  1050  		var (
  1051  			tx      *types.Transaction
  1052  			err     error
  1053  			basicTx = func(signer types.Signer) (*types.Transaction, error) {
  1054  				return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
  1055  			}
  1056  		)
  1057  		switch i {
  1058  		case 0:
  1059  			tx, err = basicTx(types.HomesteadSigner{})
  1060  			if err != nil {
  1061  				t.Fatal(err)
  1062  			}
  1063  			block.AddTx(tx)
  1064  		case 2:
  1065  			tx, err = basicTx(types.HomesteadSigner{})
  1066  			if err != nil {
  1067  				t.Fatal(err)
  1068  			}
  1069  			block.AddTx(tx)
  1070  
  1071  			tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId))
  1072  			if err != nil {
  1073  				t.Fatal(err)
  1074  			}
  1075  			block.AddTx(tx)
  1076  		case 3:
  1077  			tx, err = basicTx(types.HomesteadSigner{})
  1078  			if err != nil {
  1079  				t.Fatal(err)
  1080  			}
  1081  			block.AddTx(tx)
  1082  
  1083  			tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId))
  1084  			if err != nil {
  1085  				t.Fatal(err)
  1086  			}
  1087  			block.AddTx(tx)
  1088  		}
  1089  	})
  1090  
  1091  	if _, err := blockchain.InsertChain(blocks); err != nil {
  1092  		t.Fatal(err)
  1093  	}
  1094  	block := blockchain.GetBlockByNumber(1)
  1095  	if block.Transactions()[0].Protected() {
  1096  		t.Error("Expected block[0].txs[0] to not be replay protected")
  1097  	}
  1098  
  1099  	block = blockchain.GetBlockByNumber(3)
  1100  	if block.Transactions()[0].Protected() {
  1101  		t.Error("Expected block[3].txs[0] to not be replay protected")
  1102  	}
  1103  	if !block.Transactions()[1].Protected() {
  1104  		t.Error("Expected block[3].txs[1] to be replay protected")
  1105  	}
  1106  	if _, err := blockchain.InsertChain(blocks[4:]); err != nil {
  1107  		t.Fatal(err)
  1108  	}
  1109  
  1110  	// generate an invalid chain id transaction
  1111  	config := &params.ChainConfig{ChainId: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}
  1112  	blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), db, 4, func(i int, block *BlockGen) {
  1113  		var (
  1114  			tx      *types.Transaction
  1115  			err     error
  1116  			basicTx = func(signer types.Signer) (*types.Transaction, error) {
  1117  				return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
  1118  			}
  1119  		)
  1120  		switch i {
  1121  		case 0:
  1122  			tx, err = basicTx(types.NewEIP155Signer(big.NewInt(2)))
  1123  			if err != nil {
  1124  				t.Fatal(err)
  1125  			}
  1126  			block.AddTx(tx)
  1127  		}
  1128  	})
  1129  	_, err := blockchain.InsertChain(blocks)
  1130  	if err != types.ErrInvalidChainId {
  1131  		t.Error("expected error:", types.ErrInvalidChainId)
  1132  	}
  1133  }
  1134  
  1135  func TestEIP161AccountRemoval(t *testing.T) {
  1136  	// Configure and generate a sample block chain
  1137  	var (
  1138  		db, _   = ethdb.NewMemDatabase()
  1139  		key, _  = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1140  		address = crypto.PubkeyToAddress(key.PublicKey)
  1141  		funds   = big.NewInt(1000000000)
  1142  		theAddr = common.Address{1}
  1143  		gspec   = &Genesis{
  1144  			Config: &params.ChainConfig{
  1145  				ChainId:        big.NewInt(1),
  1146  				HomesteadBlock: new(big.Int),
  1147  				EIP155Block:    new(big.Int),
  1148  				EIP158Block:    big.NewInt(2),
  1149  			},
  1150  			Alloc: GenesisAlloc{address: {Balance: funds}},
  1151  		}
  1152  		genesis = gspec.MustCommit(db)
  1153  	)
  1154  	blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
  1155  	defer blockchain.Stop()
  1156  
  1157  	blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) {
  1158  		var (
  1159  			tx     *types.Transaction
  1160  			err    error
  1161  			signer = types.NewEIP155Signer(gspec.Config.ChainId)
  1162  		)
  1163  		switch i {
  1164  		case 0:
  1165  			tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
  1166  		case 1:
  1167  			tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
  1168  		case 2:
  1169  			tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
  1170  		}
  1171  		if err != nil {
  1172  			t.Fatal(err)
  1173  		}
  1174  		block.AddTx(tx)
  1175  	})
  1176  	// account must exist pre eip 161
  1177  	if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil {
  1178  		t.Fatal(err)
  1179  	}
  1180  	if st, _ := blockchain.State(); !st.Exist(theAddr) {
  1181  		t.Error("expected account to exist")
  1182  	}
  1183  
  1184  	// account needs to be deleted post eip 161
  1185  	if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil {
  1186  		t.Fatal(err)
  1187  	}
  1188  	if st, _ := blockchain.State(); st.Exist(theAddr) {
  1189  		t.Error("account should not exist")
  1190  	}
  1191  
  1192  	// account musn't be created post eip 161
  1193  	if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil {
  1194  		t.Fatal(err)
  1195  	}
  1196  	if st, _ := blockchain.State(); st.Exist(theAddr) {
  1197  		t.Error("account should not exist")
  1198  	}
  1199  }