github.com/alanchchen/go-ethereum@v1.6.6-0.20170601190819-6171d01b1195/core/blockchain_test.go (about)

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