github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/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  	"sync"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/vntchain/go-vnt/common"
    28  	"github.com/vntchain/go-vnt/consensus/mock"
    29  	"github.com/vntchain/go-vnt/core/rawdb"
    30  	"github.com/vntchain/go-vnt/core/state"
    31  	"github.com/vntchain/go-vnt/core/types"
    32  	"github.com/vntchain/go-vnt/core/vm"
    33  	"github.com/vntchain/go-vnt/crypto"
    34  	"github.com/vntchain/go-vnt/params"
    35  	"github.com/vntchain/go-vnt/vntdb"
    36  )
    37  
    38  // Test fork of length N starting from block i
    39  func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) {
    40  	// Copy old chain up to #i into a new db
    41  	db, blockchain2, err := newCanonical(mock.NewMock(), i, full)
    42  	if err != nil {
    43  		t.Fatal("could not make new canonical in testFork", err)
    44  	}
    45  	defer blockchain2.Stop()
    46  
    47  	// Assert the chains have the same header/block at #i
    48  	var hash1, hash2 common.Hash
    49  	if full {
    50  		hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash()
    51  		hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash()
    52  	} else {
    53  		hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash()
    54  		hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash()
    55  	}
    56  	if hash1 != hash2 {
    57  		t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1)
    58  	}
    59  	// Extend the newly created chain
    60  	var (
    61  		blockChainB  []*types.Block
    62  		headerChainB []*types.Header
    63  	)
    64  	if full {
    65  		blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, mock.NewMock(), db, forkSeed)
    66  		if _, err := blockchain2.InsertChain(blockChainB); err != nil {
    67  			t.Fatalf("failed to insert forking chain: %v", err)
    68  		}
    69  	} else {
    70  		headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, mock.NewMock(), db, forkSeed)
    71  		if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil {
    72  			t.Fatalf("failed to insert forking chain: %v", err)
    73  		}
    74  	}
    75  	// Sanity check that the forked chain can be imported into the original
    76  	var tdPre, tdPost *big.Int
    77  
    78  	if full {
    79  		tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash())
    80  		if err := testBlockChainImport(blockChainB, blockchain); err != nil {
    81  			t.Fatalf("failed to import forked block chain: %v", err)
    82  		}
    83  		tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash())
    84  	} else {
    85  		tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash())
    86  		if err := testHeaderChainImport(headerChainB, blockchain); err != nil {
    87  			t.Fatalf("failed to import forked header chain: %v", err)
    88  		}
    89  		tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash())
    90  	}
    91  	// Compare the total difficulties of the chains
    92  	comparator(tdPre, tdPost)
    93  }
    94  
    95  func printChain(bc *BlockChain) {
    96  	for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- {
    97  		b := bc.GetBlockByNumber(uint64(i))
    98  		fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty())
    99  	}
   100  }
   101  
   102  // testBlockChainImport tries to process a chain of blocks, writing them into
   103  // the database if successful.
   104  func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
   105  	for _, block := range chain {
   106  		// Try and process the block
   107  		err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true)
   108  		if err == nil {
   109  			err = blockchain.validator.ValidateBody(block)
   110  		}
   111  		if err != nil {
   112  			if err == ErrKnownBlock {
   113  				continue
   114  			}
   115  			return err
   116  		}
   117  		statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache)
   118  		if err != nil {
   119  			return err
   120  		}
   121  		receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{})
   122  		if err != nil {
   123  			blockchain.reportBlock(block, receipts, err)
   124  			return err
   125  		}
   126  		err = blockchain.validator.ValidateState(block, blockchain.GetBlockByHash(block.ParentHash()), statedb, receipts, usedGas)
   127  		if err != nil {
   128  			blockchain.reportBlock(block, receipts, err)
   129  			return err
   130  		}
   131  		blockchain.mu.Lock()
   132  		rawdb.WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash())))
   133  		rawdb.WriteBlock(blockchain.db, block)
   134  		statedb.Commit(false)
   135  		blockchain.mu.Unlock()
   136  	}
   137  	return nil
   138  }
   139  
   140  // testHeaderChainImport tries to process a chain of header, writing them into
   141  // the database if successful.
   142  func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error {
   143  	for _, header := range chain {
   144  		// Try and validate the header
   145  		if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil {
   146  			return err
   147  		}
   148  		// Manually insert the header into the database, but don't reorganise (allows subsequent testing)
   149  		blockchain.mu.Lock()
   150  		rawdb.WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash)))
   151  		rawdb.WriteHeader(blockchain.db, header)
   152  		blockchain.mu.Unlock()
   153  	}
   154  	return nil
   155  }
   156  
   157  func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) {
   158  	_, err := blockchain.InsertChain(chain)
   159  	if err != nil {
   160  		fmt.Println(err)
   161  		t.FailNow()
   162  	}
   163  	done <- true
   164  }
   165  
   166  func TestLastBlock(t *testing.T) {
   167  	_, blockchain, err := newCanonical(mock.NewMock(), 0, true)
   168  	if err != nil {
   169  		t.Fatalf("failed to create pristine chain: %v", err)
   170  	}
   171  	defer blockchain.Stop()
   172  
   173  	blocks := makeBlockChain(blockchain.CurrentBlock(), 1, mock.NewMock(), blockchain.db, 0)
   174  	if _, err := blockchain.InsertChain(blocks); err != nil {
   175  		t.Fatalf("Failed to insert block: %v", err)
   176  	}
   177  	if blocks[len(blocks)-1].Hash() != rawdb.ReadHeadBlockHash(blockchain.db) {
   178  		t.Fatalf("Write/Get HeadBlockHash failed")
   179  	}
   180  }
   181  
   182  // Tests that given a starting canonical chain of a given size, it can be extended
   183  // with various length chains.
   184  func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) }
   185  func TestExtendCanonicalBlocks(t *testing.T)  { testExtendCanonical(t, true) }
   186  
   187  func testExtendCanonical(t *testing.T, full bool) {
   188  	length := 5
   189  
   190  	// Make first chain starting from genesis
   191  	_, processor, err := newCanonical(mock.NewMock(), length, full)
   192  	if err != nil {
   193  		t.Fatalf("failed to make new canonical chain: %v", err)
   194  	}
   195  	defer processor.Stop()
   196  
   197  	// Define the difficulty comparator
   198  	better := func(td1, td2 *big.Int) {
   199  		if td2.Cmp(td1) <= 0 {
   200  			t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1)
   201  		}
   202  	}
   203  	// Start fork from current height
   204  	testFork(t, processor, length, 1, full, better)
   205  	testFork(t, processor, length, 2, full, better)
   206  	testFork(t, processor, length, 5, full, better)
   207  	testFork(t, processor, length, 10, full, better)
   208  }
   209  
   210  // Tests that given a starting canonical chain of a given size, creating shorter
   211  // forks do not take canonical ownership.
   212  func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) }
   213  func TestShorterForkBlocks(t *testing.T)  { testShorterFork(t, true) }
   214  
   215  func testShorterFork(t *testing.T, full bool) {
   216  	length := 10
   217  
   218  	// Make first chain starting from genesis
   219  	_, processor, err := newCanonical(mock.NewMock(), length, full)
   220  	if err != nil {
   221  		t.Fatalf("failed to make new canonical chain: %v", err)
   222  	}
   223  	defer processor.Stop()
   224  
   225  	// Define the difficulty comparator
   226  	worse := func(td1, td2 *big.Int) {
   227  		if td2.Cmp(td1) >= 0 {
   228  			t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1)
   229  		}
   230  	}
   231  	// Sum of numbers must be less than `length` for this to be a shorter fork
   232  	testFork(t, processor, 0, 3, full, worse)
   233  	testFork(t, processor, 0, 7, full, worse)
   234  	testFork(t, processor, 1, 1, full, worse)
   235  	testFork(t, processor, 1, 7, full, worse)
   236  	testFork(t, processor, 5, 3, full, worse)
   237  	testFork(t, processor, 5, 4, full, worse)
   238  }
   239  
   240  // Tests that given a starting canonical chain of a given size, creating longer
   241  // forks do take canonical ownership.
   242  func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) }
   243  func TestLongerForkBlocks(t *testing.T)  { testLongerFork(t, true) }
   244  
   245  func testLongerFork(t *testing.T, full bool) {
   246  	length := 10
   247  
   248  	// Make first chain starting from genesis
   249  	_, processor, err := newCanonical(mock.NewMock(), length, full)
   250  	if err != nil {
   251  		t.Fatalf("failed to make new canonical chain: %v", err)
   252  	}
   253  	defer processor.Stop()
   254  
   255  	// Define the difficulty comparator
   256  	better := func(td1, td2 *big.Int) {
   257  		if td2.Cmp(td1) <= 0 {
   258  			t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1)
   259  		}
   260  	}
   261  	// Sum of numbers must be greater than `length` for this to be a longer fork
   262  	testFork(t, processor, 0, 11, full, better)
   263  	testFork(t, processor, 0, 15, full, better)
   264  	testFork(t, processor, 1, 10, full, better)
   265  	testFork(t, processor, 1, 12, full, better)
   266  	testFork(t, processor, 5, 6, full, better)
   267  	testFork(t, processor, 5, 8, full, better)
   268  }
   269  
   270  // Tests that given a starting canonical chain of a given size, creating equal
   271  // forks do take canonical ownership.
   272  func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) }
   273  func TestEqualForkBlocks(t *testing.T)  { testEqualFork(t, true) }
   274  
   275  func testEqualFork(t *testing.T, full bool) {
   276  	length := 10
   277  
   278  	// Make first chain starting from genesis
   279  	_, processor, err := newCanonical(mock.NewMock(), length, full)
   280  	if err != nil {
   281  		t.Fatalf("failed to make new canonical chain: %v", err)
   282  	}
   283  	defer processor.Stop()
   284  
   285  	// Define the difficulty comparator
   286  	equal := func(td1, td2 *big.Int) {
   287  		if td2.Cmp(td1) != 0 {
   288  			t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1)
   289  		}
   290  	}
   291  	// Sum of numbers must be equal to `length` for this to be an equal fork
   292  	testFork(t, processor, 0, 10, full, equal)
   293  	testFork(t, processor, 1, 9, full, equal)
   294  	testFork(t, processor, 2, 8, full, equal)
   295  	testFork(t, processor, 5, 5, full, equal)
   296  	testFork(t, processor, 6, 4, full, equal)
   297  	testFork(t, processor, 9, 1, full, equal)
   298  }
   299  
   300  // Tests that chains missing links do not get accepted by the processor.
   301  func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) }
   302  func TestBrokenBlockChain(t *testing.T)  { testBrokenChain(t, true) }
   303  
   304  func testBrokenChain(t *testing.T, full bool) {
   305  	// Make chain starting from genesis
   306  	db, blockchain, err := newCanonical(mock.NewMock(), 10, full)
   307  	if err != nil {
   308  		t.Fatalf("failed to make new canonical chain: %v", err)
   309  	}
   310  	defer blockchain.Stop()
   311  
   312  	// Create a forked chain, and try to insert with a missing link
   313  	if full {
   314  		chain := makeBlockChain(blockchain.CurrentBlock(), 5, mock.NewMock(), 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, mock.NewMock(), db, forkSeed)[1:]
   320  		if err := testHeaderChainImport(chain, blockchain); err == nil {
   321  			t.Errorf("broken header chain not reported")
   322  		}
   323  	}
   324  }
   325  
   326  // 正常产块情况,在当前主链后产生新区块,当前新区块应当成为头区块
   327  // Header chain测试
   328  func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) }
   329  
   330  // Block chain测试
   331  func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) }
   332  
   333  func testReorgLong(t *testing.T, full bool) {
   334  	testReorg(t, []int64{0, 0, 0}, []int64{0, 0, 0, 0}, 4, full, true, false)
   335  }
   336  
   337  // 测试攻击链的场景,填充过去某个时间点缺失的区块,创造更长的链
   338  // Test some block producers make up fake chain by filling skipped blocks.
   339  // first : A ->  -> B -> C
   340  // second: A -> B' -> C' -> D'
   341  func TestReorgFakeChainFillMissTimeAndLongHeaders(t *testing.T) {
   342  	testReorgFakeChainFillMissTimeAndLong(t, false)
   343  }
   344  func TestReorgFakeChainFillMissTimeAndLongBlocks(t *testing.T) {
   345  	testReorgFakeChainFillMissTimeAndLong(t, true)
   346  }
   347  func testReorgFakeChainFillMissTimeAndLong(t *testing.T, full bool) {
   348  	mainChain := []int64{0, 2, 0, 0}
   349  	fakeChain := []int64{0, 0, 0, 0, 0} // LIB之前的区块插入失败
   350  	testReorg(t, mainChain, fakeChain, 4, full, false, true)
   351  }
   352  
   353  // 临时分叉情况,网络突然中断,然后下一轮结束前恢复
   354  // Case 1.1 two blocks in the same height for bad network
   355  // first:  A -> B, 代表本地链
   356  // second: A -> -> C, 代表远端链
   357  // first is still main chain
   358  func TestReorgSameHeightFirstIsEarlyHeader(t *testing.T) {
   359  	testReorgSameHeightFirstIsEarly(t, false)
   360  }
   361  func TestReorgSameHeightFirstIsEarlyBlock(t *testing.T) {
   362  	testReorgSameHeightFirstIsEarly(t, true)
   363  }
   364  func testReorgSameHeightFirstIsEarly(t *testing.T, full bool) {
   365  	first := []int64{0, 0}
   366  	second := []int64{0, 2}
   367  	testReorg(t, first, second, 2, full, true, true)
   368  }
   369  
   370  // 临时分叉情况,网络突然中断,然后下一轮结束前恢复
   371  // Case 1.2 two blocks in the same height for bad network
   372  // 与Case 1.1相反的过程,但都应当选择`A -> B`
   373  // first:  A -> -> C
   374  // second: A -> B
   375  func TestReorgSameHeightSecondIsEarlyHeader(t *testing.T) {
   376  	testReorgSameHeightSecondIsEarly(t, false)
   377  }
   378  func TestReorgSameHeightSecondIsEarlyBlock(t *testing.T) {
   379  	testReorgSameHeightSecondIsEarly(t, true)
   380  }
   381  func testReorgSameHeightSecondIsEarly(t *testing.T, full bool) {
   382  	first := []int64{0, 2}
   383  	second := []int64{0, 0}
   384  	testReorg(t, first, second, 2, full, true, false)
   385  }
   386  
   387  // 临时分叉情况,网络在第N轮突然中断,然后在N+2轮结束恢复
   388  // Case 2.1
   389  // first:  A -> B
   390  // second: A ->  -> C -> D
   391  func TestReorgFirstIsEarlyButShortHeader(t *testing.T) {
   392  	testReorgFirstIsEarlyButShort(t, false)
   393  }
   394  func TestReorgFirstIsEarlyButShortBlock(t *testing.T) {
   395  	testReorgFirstIsEarlyButShort(t, true)
   396  }
   397  func testReorgFirstIsEarlyButShort(t *testing.T, full bool) {
   398  	first := []int64{0, 0}
   399  	second := []int64{0, 2, 0}
   400  	testReorg(t, first, second, 3, full, true, false)
   401  }
   402  
   403  // 临时分叉情况,网络在第N轮突然中断,然后在N+2轮结束恢复
   404  // Case 2.2
   405  // first:  A ->  -> C -> D
   406  // second: A -> B
   407  func TestReorgSecondIsEarlyButShortHeader(t *testing.T) {
   408  	testReorgSecondIsEarlyButShort(t, false)
   409  }
   410  func TestReorgSecondIsEarlyButShortBlock(t *testing.T) {
   411  	testReorgSecondIsEarlyButShort(t, true)
   412  }
   413  func testReorgSecondIsEarlyButShort(t *testing.T, full bool) {
   414  	first := []int64{0, 2, 0}
   415  	second := []int64{0, 0}
   416  	testReorg(t, first, second, 3, full, false, true)
   417  }
   418  
   419  // 临时分叉情况,络在第N轮突然中断,然后在N+1轮结束恢复,然后在N+2轮产生了新区块,
   420  // 在N+1轮产生区块的少数节点,如果没再case 1.1切回到first,在first生成新区块后切回first
   421  // Case 3.1
   422  // first:  A -> B ->  -> D
   423  // second: A ->  -> C
   424  func TestReorgFirstIsEarlyAndLongHeader(t *testing.T) {
   425  	testReorgFirstIsEarlyAndLong(t, false)
   426  }
   427  func TestReorgFirstIsEarlyAndLongBlock(t *testing.T) {
   428  	testReorgFirstIsEarlyAndLong(t, true)
   429  }
   430  func testReorgFirstIsEarlyAndLong(t *testing.T, full bool) {
   431  	first := []int64{0, 0, 2}
   432  	second := []int64{0, 2}
   433  	testReorg(t, first, second, 3, full, false, true)
   434  }
   435  
   436  // 临时分叉情况,络在第N轮突然中断,然后在N+1轮结束恢复,然后在N+2轮产生了新区块,
   437  // 在N+1轮产生区块的少数节点,如果没再case 1.1切回到first,在first生成新区块后切回first
   438  // Case 3.2
   439  // first:  A ->  -> C
   440  // second: A -> B ->  -> D
   441  func TestReorgSecondIsEarlyAndLongHeader(t *testing.T) {
   442  	testReorgSecondIsEarlyAndLong(t, false)
   443  }
   444  func TestReorgSecondIsEarlyAndLongBlock(t *testing.T) {
   445  	testReorgSecondIsEarlyAndLong(t, true)
   446  }
   447  func testReorgSecondIsEarlyAndLong(t *testing.T, full bool) {
   448  	first := []int64{0, 2}
   449  	second := []int64{0, 0, 2}
   450  	testReorg(t, first, second, 3, full, true, false)
   451  }
   452  
   453  // first: 第一条链,是当前主链的时间戳偏移,在当前生成的区块上进一步做时间戳偏移
   454  // second: 第二条链,分叉链、攻击链的时间戳偏移
   455  // td: reorg后成为主链的区块的总高度
   456  // full: 是否是header chain测试
   457  // firstIsMain: reorg后,第一条链是主链
   458  func testReorg(t *testing.T, first, second []int64, td int64, full, secondInsertSuccess, firstIsMain bool) {
   459  	// Create a pristine chain and database
   460  	db, blockchain, err := newCanonical(mock.NewMock(), 0, full)
   461  	if err != nil {
   462  		t.Fatalf("failed to create pristine chain: %v", err)
   463  	}
   464  	defer blockchain.Stop()
   465  
   466  	// 生成区块
   467  	firstBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), mock.NewMock(), db, len(first), func(i int, b *BlockGen) {
   468  		b.OffsetTime(first[i])
   469  	})
   470  	secondBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), mock.NewMock(), db, len(second), func(i int, b *BlockGen) {
   471  		b.OffsetTime(second[i])
   472  	})
   473  
   474  	printBlocks(t, "first  blocks:", firstBlocks)
   475  	printBlocks(t, "second blocks:", secondBlocks)
   476  
   477  	// 调用测试函数
   478  	testFun := testReorgBlock
   479  	if !full {
   480  		testFun = testReorgHeader
   481  	}
   482  	testFun(t, blockchain, firstBlocks, secondBlocks, td, secondInsertSuccess, firstIsMain)
   483  }
   484  
   485  // testReorgBlock block chain的reorg测试
   486  func testReorgBlock(t *testing.T, blockchain *BlockChain, firstBlocks, secondBlocks types.Blocks, td int64, secondInsertSuccess, firstIsMain bool) {
   487  	// 插入的区块链,first代表当前主链,必须成功
   488  	if _, err := blockchain.InsertChain(firstBlocks); err != nil {
   489  		t.Fatalf("failed to insert first chain: %v", err)
   490  	}
   491  	// second是攻击链或临时分叉,按要求执行,可能成功,可能失败
   492  	{
   493  		_, err := blockchain.InsertChain(secondBlocks)
   494  		if secondInsertSuccess {
   495  			if err != nil {
   496  				t.Logf("failed to insert second chain: %v", err)
   497  			}
   498  		} else {
   499  			if err == nil {
   500  				t.Logf("insert second chain successed, want failed")
   501  			}
   502  		}
   503  	}
   504  
   505  	// 检查链是否是连接正确的
   506  	block := blockchain.CurrentBlock()
   507  	for prev := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); prev.NumberU64() != 0; block, prev = prev, blockchain.GetBlockByNumber(prev.NumberU64()-1) {
   508  		// t.Logf("block hash: %s\n", block.Hash().String())
   509  		if block.ParentHash() != prev.Hash() {
   510  			t.Errorf("parent block hash mismatch: have %x, want %x", block.ParentHash(), prev.Hash())
   511  		}
   512  	}
   513  
   514  	// 链难度检查
   515  	wantTd := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td))
   516  	if have := blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()); have.Cmp(wantTd) != 0 {
   517  		t.Errorf("total difficulty mismatch: have %v, want %v", have, wantTd)
   518  	}
   519  
   520  	// 检查主链的区块是否匹配
   521  	targetChain := firstBlocks
   522  	if !firstIsMain {
   523  		targetChain = secondBlocks
   524  	}
   525  	blocks := make([]*types.Block, 0)
   526  	blk := blockchain.CurrentBlock()
   527  	for prev := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); blk.NumberU64() != 0; blk, prev = prev, blockchain.GetBlockByNumber(prev.NumberU64()-1) {
   528  		blocks = append(blocks, blk)
   529  	}
   530  	// 反序,高度从低到高
   531  	for i, j := 0, len(blocks)-1; i < j; i, j = i+1, j-1 {
   532  		blocks[i], blocks[j] = blocks[j], blocks[i]
   533  	}
   534  	printBlocks(t, "main chain:", blocks)
   535  
   536  	// 打印难度日志
   537  	genesis := blockchain.genesisBlock
   538  	td0 := blockchain.GetTdByHash(genesis.Hash())
   539  	t.Logf("genesis block %s, total diff: %v\n", genesis.Hash().String(), td0.String())
   540  	for i, b := range blocks {
   541  		td := blockchain.GetTdByHash(b.Hash())
   542  		t.Logf("block [%d] %s, total diff: %v\n", i, b.Hash().String(), td.String())
   543  	}
   544  
   545  	if len(blocks) != len(targetChain) {
   546  		t.Fatalf("total length mismatch: have %v, want %v", len(blocks), len(targetChain))
   547  	}
   548  	for i, b := range targetChain {
   549  		bc := blocks[i]
   550  		if b.Hash() != bc.Hash() {
   551  			t.Errorf("block [%d] mismatch: have %v, want: %v", i, bc.Hash().String(), b.Hash().String())
   552  		}
   553  	}
   554  }
   555  
   556  // testReorgBlock header chain的reorg测试
   557  func testReorgHeader(t *testing.T, blockchain *BlockChain, firstBlocks, secondBlocks types.Blocks, td int64, secondInsertSuccess, firstIsMain bool) {
   558  	firstHeaders := make([]*types.Header, len(firstBlocks))
   559  	for i, block := range firstBlocks {
   560  		firstHeaders[i] = block.Header()
   561  	}
   562  	secondHeaders := make([]*types.Header, len(secondBlocks))
   563  	for i, block := range secondBlocks {
   564  		secondHeaders[i] = block.Header()
   565  	}
   566  
   567  	// first是主链的header chain,必须成功
   568  	if _, err := blockchain.InsertHeaderChain(firstHeaders, 1); err != nil {
   569  		t.Fatalf("failed to insert first header chain: %v", err)
   570  	}
   571  	// second是攻击链或临时分叉的header chain,按要求觉得成功与否
   572  	{
   573  		_, err := blockchain.InsertHeaderChain(secondHeaders, 1)
   574  		if secondInsertSuccess {
   575  			if err != nil {
   576  				t.Fatalf("failed to insert second header chain: %v", err)
   577  			}
   578  		} else {
   579  			if err == nil {
   580  				t.Fatalf("insert second header chain successed, want failed")
   581  			}
   582  		}
   583  	}
   584  
   585  	// Check that the chain is valid number and link wise
   586  	header := blockchain.CurrentHeader()
   587  	for prev := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); prev.Number.Uint64() != 0; header, prev = prev, blockchain.GetHeaderByNumber(prev.Number.Uint64()-1) {
   588  		if header.ParentHash != prev.Hash() {
   589  			t.Errorf("parent header hash mismatch: have %x, want %x", header.ParentHash, prev.Hash())
   590  		}
   591  	}
   592  
   593  	// Make sure the chain total difficulty is the correct one
   594  	wantTd := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td))
   595  	if have := blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()); have.Cmp(wantTd) != 0 {
   596  		t.Errorf("total difficulty mismatch: have %v, want %v", have, wantTd)
   597  	}
   598  
   599  	// 检查主链是否匹配
   600  	targetHeader := firstHeaders
   601  	if !firstIsMain {
   602  		targetHeader = secondHeaders
   603  	}
   604  	chainHeader := make([]*types.Header, 0)
   605  	header = blockchain.CurrentHeader()
   606  	for prev := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; header, prev = prev, blockchain.GetHeaderByNumber(prev.Number.Uint64()-1) {
   607  		chainHeader = append(chainHeader, header)
   608  	}
   609  	for i, j := 0, len(chainHeader)-1; i < j; i, j = i+1, j-1 {
   610  		chainHeader[i], chainHeader[j] = chainHeader[j], chainHeader[i]
   611  	}
   612  	printHeaders(t, "header chain", chainHeader)
   613  
   614  	if len(targetHeader) != len(chainHeader) {
   615  		t.Fatalf("header chain lengeth mismatch, have: %d, want: %d", len(chainHeader), len(targetHeader))
   616  	}
   617  	for i := 0; i < len(targetHeader); i++ {
   618  		if targetHeader[i].Hash() != chainHeader[i].Hash() {
   619  			t.Errorf("header chain mismatch %d, have: %s, want: %s\n", i, chainHeader[i].Hash(), targetHeader[i].Hash())
   620  		}
   621  	}
   622  }
   623  
   624  func printBlocks(t *testing.T, tag string, blocks []*types.Block) {
   625  	t.Logf("%s\n", tag)
   626  	for i, b := range blocks {
   627  		t.Logf("b [%d], h: %s, time: %s, diff: %s, hash: %s\n", i, b.Number().String(), b.Time().String(), b.Difficulty().String(), b.Hash().String())
   628  	}
   629  }
   630  
   631  func printHeaders(t *testing.T, tag string, headers []*types.Header) {
   632  	t.Logf("%s\n", tag)
   633  	for i, h := range headers {
   634  		t.Logf("header [%d], h: %s, time: %s, diff: %s, hash: %s\n", i, h.Number.String(), h.Time.String(), h.Difficulty.String(), h.Hash().String())
   635  	}
   636  }
   637  
   638  // Tests that the insertion functions detect banned hashes.
   639  func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) }
   640  func TestBadBlockHashes(t *testing.T)  { testBadHashes(t, true) }
   641  
   642  func testBadHashes(t *testing.T, full bool) {
   643  	// Create a pristine chain and database
   644  	db, blockchain, err := newCanonical(mock.NewMock(), 0, full)
   645  	if err != nil {
   646  		t.Fatalf("failed to create pristine chain: %v", err)
   647  	}
   648  	defer blockchain.Stop()
   649  
   650  	// Create a chain, ban a hash and try to import
   651  	if full {
   652  		blocks := makeBlockChain(blockchain.CurrentBlock(), 3, mock.NewMock(), db, 10)
   653  
   654  		BadHashes[blocks[2].Header().Hash()] = true
   655  		defer func() { delete(BadHashes, blocks[2].Header().Hash()) }()
   656  
   657  		_, err = blockchain.InsertChain(blocks)
   658  	} else {
   659  		headers := makeHeaderChain(blockchain.CurrentHeader(), 3, mock.NewMock(), db, 10)
   660  
   661  		BadHashes[headers[2].Hash()] = true
   662  		defer func() { delete(BadHashes, headers[2].Hash()) }()
   663  
   664  		_, err = blockchain.InsertHeaderChain(headers, 1)
   665  	}
   666  	if err != ErrBlacklistedHash {
   667  		t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash)
   668  	}
   669  }
   670  
   671  // Tests that bad hashes are detected on boot, and the chain rolled back to a
   672  // good state prior to the bad hash.
   673  func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) }
   674  func TestReorgBadBlockHashes(t *testing.T)  { testReorgBadHashes(t, true) }
   675  
   676  func testReorgBadHashes(t *testing.T, full bool) {
   677  	// Create a pristine chain and database
   678  	db, blockchain, err := newCanonical(mock.NewMock(), 0, full)
   679  	if err != nil {
   680  		t.Fatalf("failed to create pristine chain: %v", err)
   681  	}
   682  	// Create a chain, import and ban afterwards
   683  	headers := makeHeaderChain(blockchain.CurrentHeader(), 4, mock.NewMock(), db, 10)
   684  	blocks := makeBlockChain(blockchain.CurrentBlock(), 4, mock.NewMock(), db, 10)
   685  
   686  	if full {
   687  		if _, err = blockchain.InsertChain(blocks); err != nil {
   688  			t.Errorf("failed to import blocks: %v", err)
   689  		}
   690  		if blockchain.CurrentBlock().Hash() != blocks[3].Hash() {
   691  			t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash())
   692  		}
   693  		BadHashes[blocks[3].Header().Hash()] = true
   694  		defer func() { delete(BadHashes, blocks[3].Header().Hash()) }()
   695  	} else {
   696  		if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil {
   697  			t.Errorf("failed to import headers: %v", err)
   698  		}
   699  		if blockchain.CurrentHeader().Hash() != headers[3].Hash() {
   700  			t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash())
   701  		}
   702  		BadHashes[headers[3].Hash()] = true
   703  		defer func() { delete(BadHashes, headers[3].Hash()) }()
   704  	}
   705  	blockchain.Stop()
   706  
   707  	// Create a new BlockChain and check that it rolled back the state.
   708  	ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, mock.NewMock(), vm.Config{})
   709  	if err != nil {
   710  		t.Fatalf("failed to create new chain manager: %v", err)
   711  	}
   712  	if full {
   713  		if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() {
   714  			t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash())
   715  		}
   716  		if blocks[2].Header().GasLimit != ncm.GasLimit() {
   717  			t.Errorf("last  block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit)
   718  		}
   719  	} else {
   720  		if ncm.CurrentHeader().Hash() != headers[2].Hash() {
   721  			t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash())
   722  		}
   723  	}
   724  	ncm.Stop()
   725  }
   726  
   727  // Tests chain insertions in the face of one entity containing an invalid nonce.
   728  func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) }
   729  func TestBlocksInsertNonceError(t *testing.T)  { testInsertNonceError(t, true) }
   730  
   731  func testInsertNonceError(t *testing.T, full bool) {
   732  	for i := 1; i < 25 && !t.Failed(); i++ {
   733  		// Create a pristine chain and database
   734  		db, blockchain, err := newCanonical(mock.NewMock(), 0, full)
   735  		if err != nil {
   736  			t.Fatalf("failed to create pristine chain: %v", err)
   737  		}
   738  		defer blockchain.Stop()
   739  
   740  		// Create and insert a chain with a failing nonce
   741  		var (
   742  			failAt  int
   743  			failRes int
   744  			failNum uint64
   745  		)
   746  		if full {
   747  			blocks := makeBlockChain(blockchain.CurrentBlock(), i, mock.NewMock(), db, 0)
   748  			fmt.Println(blocks)
   749  			failAt = rand.Int() % len(blocks)
   750  			failNum = blocks[failAt].NumberU64()
   751  
   752  			blockchain.engine = mock.NewMockFail(failNum)
   753  			failRes, err = blockchain.InsertChain(blocks)
   754  		} else {
   755  			headers := makeHeaderChain(blockchain.CurrentHeader(), i, mock.NewMock(), db, 0)
   756  
   757  			failAt = rand.Int() % len(headers)
   758  			failNum = headers[failAt].Number.Uint64()
   759  
   760  			blockchain.engine = mock.NewMockFail(failNum)
   761  			blockchain.hc.engine = blockchain.engine
   762  			failRes, err = blockchain.InsertHeaderChain(headers, 1)
   763  		}
   764  		// Check that the returned error indicates the failure.
   765  		if failRes != failAt {
   766  			t.Errorf("test %d: failure index mismatch: have %d, want %d", i, failRes, failAt)
   767  		}
   768  		// Check that all no blocks after the failing block have been inserted.
   769  		for j := 0; j < i-failAt; j++ {
   770  			if full {
   771  				if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil {
   772  					t.Errorf("test %d: invalid block in chain: %v", i, block)
   773  				}
   774  			} else {
   775  				if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil {
   776  					t.Errorf("test %d: invalid header in chain: %v", i, header)
   777  				}
   778  			}
   779  		}
   780  	}
   781  }
   782  
   783  // Tests that fast importing a block chain produces the same chain data as the
   784  // classical full block processing.
   785  func TestFastVsFullChains(t *testing.T) {
   786  	// Configure and generate a sample block chain
   787  	var (
   788  		gendb   = vntdb.NewMemDatabase()
   789  		key, _  = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   790  		address = crypto.PubkeyToAddress(key.PublicKey)
   791  		funds   = big.NewInt(1000000000)
   792  		gspec   = &Genesis{
   793  			Config: params.TestChainConfig,
   794  			Alloc:  GenesisAlloc{address: {Balance: funds}},
   795  		}
   796  		genesis = gspec.MustCommit(gendb)
   797  		signer  = types.NewHubbleSigner(gspec.Config.ChainID)
   798  	)
   799  	blocks, receipts := GenerateChain(gspec.Config, genesis, mock.NewMock(), gendb, 1024, func(i int, block *BlockGen) {
   800  		block.SetCoinbase(common.Address{0x00})
   801  
   802  		// If the block number is multiple of 3, send a few bonus transactions to the producer
   803  		if i%3 == 2 {
   804  			for j := 0; j < i%4+1; j++ {
   805  				tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key)
   806  				if err != nil {
   807  					panic(err)
   808  				}
   809  				block.AddTx(tx)
   810  			}
   811  		}
   812  	})
   813  	// Import the chain as an archive node for the comparison baseline
   814  	archiveDb := vntdb.NewMemDatabase()
   815  	gspec.MustCommit(archiveDb)
   816  	archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, mock.NewMock(), vm.Config{})
   817  	defer archive.Stop()
   818  
   819  	if n, err := archive.InsertChain(blocks); err != nil {
   820  		t.Fatalf("failed to process block %d: %v", n, err)
   821  	}
   822  	// Fast import the chain as a non-archive node to test
   823  	fastDb := vntdb.NewMemDatabase()
   824  	gspec.MustCommit(fastDb)
   825  	fast, _ := NewBlockChain(fastDb, nil, gspec.Config, mock.NewMock(), vm.Config{})
   826  	defer fast.Stop()
   827  
   828  	headers := make([]*types.Header, len(blocks))
   829  	for i, block := range blocks {
   830  		headers[i] = block.Header()
   831  	}
   832  	if n, err := fast.InsertHeaderChain(headers, 1); err != nil {
   833  		t.Fatalf("failed to insert header %d: %v", n, err)
   834  	}
   835  	if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil {
   836  		t.Fatalf("failed to insert receipt %d: %v", n, err)
   837  	}
   838  	// Iterate over all chain data components, and cross reference
   839  	for i := 0; i < len(blocks); i++ {
   840  		num, hash := blocks[i].NumberU64(), blocks[i].Hash()
   841  
   842  		if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 {
   843  			t.Errorf("block #%d [%x]: td mismatch: have %v, want %v", num, hash, ftd, atd)
   844  		}
   845  		if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() {
   846  			t.Errorf("block #%d [%x]: header mismatch: have %v, want %v", num, hash, fheader, aheader)
   847  		}
   848  		if fblock, ablock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash); fblock.Hash() != ablock.Hash() {
   849  			t.Errorf("block #%d [%x]: block mismatch: have %v, want %v", num, hash, fblock, ablock)
   850  		} else if types.DeriveSha(fblock.Transactions()) != types.DeriveSha(ablock.Transactions()) {
   851  			t.Errorf("block #%d [%x]: transactions mismatch: have %v, want %v", num, hash, fblock.Transactions(), ablock.Transactions())
   852  		}
   853  		if freceipts, areceipts := rawdb.ReadReceipts(fastDb, hash, *rawdb.ReadHeaderNumber(fastDb, hash)), rawdb.ReadReceipts(archiveDb, hash, *rawdb.ReadHeaderNumber(archiveDb, hash)); types.DeriveSha(freceipts) != types.DeriveSha(areceipts) {
   854  			t.Errorf("block #%d [%x]: receipts mismatch: have %v, want %v", num, hash, freceipts, areceipts)
   855  		}
   856  	}
   857  	// Check that the canonical chains are the same between the databases
   858  	for i := 0; i < len(blocks)+1; i++ {
   859  		if fhash, ahash := rawdb.ReadCanonicalHash(fastDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); fhash != ahash {
   860  			t.Errorf("block #%d: canonical hash mismatch: have %v, want %v", i, fhash, ahash)
   861  		}
   862  	}
   863  }
   864  
   865  // Tests that various import methods move the chain head pointers to the correct
   866  // positions.
   867  func TestLightVsFastVsFullChainHeads(t *testing.T) {
   868  	// Configure and generate a sample block chain
   869  	var (
   870  		gendb   = vntdb.NewMemDatabase()
   871  		key, _  = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   872  		address = crypto.PubkeyToAddress(key.PublicKey)
   873  		funds   = big.NewInt(1000000000)
   874  		gspec   = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}}
   875  		genesis = gspec.MustCommit(gendb)
   876  	)
   877  	height := uint64(1024)
   878  	blocks, receipts := GenerateChain(gspec.Config, genesis, mock.NewMock(), gendb, int(height), nil)
   879  
   880  	// Configure a subchain to roll back
   881  	remove := []common.Hash{}
   882  	for _, block := range blocks[height/2:] {
   883  		remove = append(remove, block.Hash())
   884  	}
   885  	// Create a small assertion method to check the three heads
   886  	assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) {
   887  		if num := chain.CurrentBlock().NumberU64(); num != block {
   888  			t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block)
   889  		}
   890  		if num := chain.CurrentFastBlock().NumberU64(); num != fast {
   891  			t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast)
   892  		}
   893  		if num := chain.CurrentHeader().Number.Uint64(); num != header {
   894  			t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header)
   895  		}
   896  	}
   897  	// Import the chain as an archive node and ensure all pointers are updated
   898  	archiveDb := vntdb.NewMemDatabase()
   899  	gspec.MustCommit(archiveDb)
   900  
   901  	archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, mock.NewMock(), vm.Config{})
   902  	if n, err := archive.InsertChain(blocks); err != nil {
   903  		t.Fatalf("failed to process block %d: %v", n, err)
   904  	}
   905  	defer archive.Stop()
   906  
   907  	assert(t, "archive", archive, height, height, height)
   908  	archive.Rollback(remove)
   909  	assert(t, "archive", archive, height/2, height/2, height/2)
   910  
   911  	// Import the chain as a non-archive node and ensure all pointers are updated
   912  	fastDb := vntdb.NewMemDatabase()
   913  	gspec.MustCommit(fastDb)
   914  	fast, _ := NewBlockChain(fastDb, nil, gspec.Config, mock.NewMock(), vm.Config{})
   915  	defer fast.Stop()
   916  
   917  	headers := make([]*types.Header, len(blocks))
   918  	for i, block := range blocks {
   919  		headers[i] = block.Header()
   920  	}
   921  	if n, err := fast.InsertHeaderChain(headers, 1); err != nil {
   922  		t.Fatalf("failed to insert header %d: %v", n, err)
   923  	}
   924  	if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil {
   925  		t.Fatalf("failed to insert receipt %d: %v", n, err)
   926  	}
   927  	assert(t, "fast", fast, height, height, 0)
   928  	fast.Rollback(remove)
   929  	assert(t, "fast", fast, height/2, height/2, 0)
   930  
   931  	// Import the chain as a light node and ensure all pointers are updated
   932  	lightDb := vntdb.NewMemDatabase()
   933  	gspec.MustCommit(lightDb)
   934  
   935  	light, _ := NewBlockChain(lightDb, nil, gspec.Config, mock.NewMock(), vm.Config{})
   936  	if n, err := light.InsertHeaderChain(headers, 1); err != nil {
   937  		t.Fatalf("failed to insert header %d: %v", n, err)
   938  	}
   939  	defer light.Stop()
   940  
   941  	assert(t, "light", light, height, 0, 0)
   942  	light.Rollback(remove)
   943  	assert(t, "light", light, height/2, 0, 0)
   944  }
   945  
   946  // Tests that chain reorganisations handle transaction removals and reinsertions.
   947  func TestChainTxReorgs(t *testing.T) {
   948  	var (
   949  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   950  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   951  		key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
   952  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   953  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   954  		addr3   = crypto.PubkeyToAddress(key3.PublicKey)
   955  		db      = vntdb.NewMemDatabase()
   956  		gspec   = &Genesis{
   957  			Config:   params.TestChainConfig,
   958  			GasLimit: 3141592,
   959  			Alloc: GenesisAlloc{
   960  				addr1: {Balance: big.NewInt(1000000)},
   961  				addr2: {Balance: big.NewInt(1000000)},
   962  				addr3: {Balance: big.NewInt(1000000)},
   963  			},
   964  		}
   965  		genesis = gspec.MustCommit(db)
   966  		signer  = types.NewHubbleSigner(gspec.Config.ChainID)
   967  	)
   968  
   969  	// Create three transactions shared between the chains:
   970  	//  - shared: transaction included at both chain
   971  	//  - removed: transaction included at the forked chain, will be removed
   972  	//  - added : transaction included at the main chain
   973  	shared, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
   974  	removed, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
   975  	added, _ := types.SignTx(types.NewTransaction(0, addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
   976  
   977  	chain, _ := GenerateChain(gspec.Config, genesis, mock.NewMock(), db, 3, func(i int, gen *BlockGen) {
   978  		switch i {
   979  		case 2:
   980  			gen.AddTx(shared)
   981  			gen.AddTx(removed)
   982  
   983  			gen.OffsetTime(2) // Later block timestamp to make it a forked chain
   984  		}
   985  	})
   986  	// Import the chain. This runs all block validation rules.
   987  	blockchain, _ := NewBlockChain(db, nil, gspec.Config, mock.NewMock(), vm.Config{})
   988  	if i, err := blockchain.InsertChain(chain); err != nil {
   989  		t.Fatalf("failed to insert original fork chain[%d]: %v", i, err)
   990  	}
   991  	defer blockchain.Stop()
   992  
   993  	// generate main chain, overwrite the old chain
   994  	chain, _ = GenerateChain(gspec.Config, genesis, mock.NewMock(), db, 3, func(i int, gen *BlockGen) {
   995  		switch i {
   996  		case 2:
   997  			gen.AddTx(shared)
   998  			gen.AddTx(added)
   999  		}
  1000  	})
  1001  	if _, err := blockchain.InsertChain(chain); err != nil {
  1002  		t.Fatalf("failed to insert main chain: %v", err)
  1003  	}
  1004  
  1005  	// removed tx
  1006  	for i, tx := range (types.Transactions{removed}) {
  1007  		if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil {
  1008  			t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn)
  1009  		}
  1010  		if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt != nil {
  1011  			t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt)
  1012  		}
  1013  	}
  1014  	// added tx
  1015  	for i, tx := range (types.Transactions{added}) {
  1016  		if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil {
  1017  			t.Errorf("add %d: expected tx to be found", i)
  1018  		}
  1019  		if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil {
  1020  			t.Errorf("add %d: expected receipt to be found", i)
  1021  		}
  1022  	}
  1023  	// shared tx
  1024  	for i, tx := range (types.Transactions{shared}) {
  1025  		if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil {
  1026  			t.Errorf("share %d: expected tx to be found", i)
  1027  		}
  1028  		if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil {
  1029  			t.Errorf("share %d: expected receipt to be found", i)
  1030  		}
  1031  	}
  1032  }
  1033  
  1034  func TestLogReorgs(t *testing.T) {
  1035  	var (
  1036  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1037  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
  1038  		db      = vntdb.NewMemDatabase()
  1039  		// this code generates a log
  1040  		code    = common.Hex2Bytes("0161736db9052f0100789c9c56db6f145518ff9d397ba6ed0eddeeb260b90418168818ebf6226db0722b21624d480c589110b29ddd39dd8eccced499d94221ddaec5101e7df4c542bcbc181f8cf1414a4cfc177cf1091e144d4c88461a0c2185c47c33b317290fc47998effb7ee7fbfdbe739b39e75157f966e71730fc0a03c0328949a556c324ab611298640b500cc1a5339b3eed59813c6d05d36fbb9613480f20b8e7a434cc35a83a669ac70d1f8c82ecb8630596615b97e4bb866719455bfa50a84578d2f5cae03cc11545490836c318139c415137f20536f6f1b584b68086b9daa9751c116a45565c6f4e8156284c4b63a650347cc959b250308dc02848c7e44ada9425dbf0a4f946d5290596eb401527c3521dc9fd5c81b61d477114e97abd5e8fbc0f232fbd4856db80f41572c6ead7ea75a43f0a41ad9b61acdea9a951a7f1806b795316abe582e54cb9bf3120017a12348f58875d881e37b60300146acb003801804fd06b32e40800db01fc486b70577c42e61c536f84d606a07e13ba3e65777c154a75d600dc2478a0eb0ac1df511e4b528de3007ea2a67bb719a06e634d776bd3d57690fb27b9eba83fc3007a88f357d429844a53007e2774a5a5b4d2525a6929fdd354ea059022ce83b631862def346a3c6caf4195ef13badaaab1daaa11badd27e279644f626a8aa847003c21148cb27a426eec6f6df9e9b0874ae86748691371388ba5c235530074314049247603d8006023856a38d177883004a453f1aa578c122d3c709575c790673865e9d3fa6601ec00f0325a4f1f803c80210087da70aabd1e00ed815d71fc666ccbb11d89ed586c3900eae4fe361d3c6e76c428163d39cb326c4f2a2b782addbb35956113bd80926719b65e1dcc025c804c220f42786a547b5d3bbc19107916052f6e3ebc59d700552002c6b340c76ef0d4214dd380ce17309e8d5a80ae1e507332d26f088c674951dbd726b06e1b1bcc52ce7bda190de8a670a2370a526d6cd160f7c4e505b1d3fbda824c934b53876f138d0fd2b61c9953e883fc8ce68bb1d554371916cd1eeb9ff0a5e7f75f90966f5897a60da7dc7fcc2d552bd209fcfea21b04b67c25907ed05f729dc0334a818fe7a614ab966db61131eb04b655cc4f53e5f0275498f164c9adcc58b6cc97c25d0711fe18f81d30d191dc29c4b4caaf2f2c0aa6f2bbd01506c620141a24bf4b3fc8e499eb57042b371a42ee3dc6444ff2a0d06e893dea8a183c20f62e890e95dfaf2d0a7188f4960557f9df4c57781b6d8531a1250f0a5dedd429fd5e4d1762204ad754fe90e94257df123d6a9fd06f88017551f42e096d8a52ffa84db52b3f7a4a793554de29b6a83f53f6af355d24f97596175c5de28b5446e5bf80c04f19092cfd673875a5399c2deab2d075b12b2f869649e9764d179c7fc9f22a7f3c7fa021c3f9e76c39ec40428945360a96dc19aa86107d2f9b044be684280b762b2af7b5928c378d1f7825db70cafaacf47ccb75f4fdf981fc80be37f0aace79fdd57d83af8d0cbcf4bff741ff3396fe79b570527e50b53c8992eb9856789e158ebaae8d8a5f4669daf0e0079ee594b1e6d89b181a1e39654cc913551b55cb098686479ad8316bb6e99faa169bfe9869e2bc9c9b9b7582f787e766a23d8b395cc425e072c2312a92059d58731f604f5f0594f816c09f7501484467bfc8140a170cbf522819b65d2805aee7ab6b4eef8ee8f0fefe87b39773543e379a0b815c5faee43a7e6038416e74cab07dd997b39c996ae0e746cf9eebcbb9d5a015047333440c095e952ae5e6fb9a7a5eac6738ae335771abfe5ac1666ec5a7cc582f9af91ce599f2a23463de7caba29c954e909b3f57ff170000ffff")
  1041  		gspec   = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18))}}}
  1042  		genesis = gspec.MustCommit(db)
  1043  		signer  = types.NewHubbleSigner(gspec.Config.ChainID)
  1044  	)
  1045  
  1046  	blockchain, _ := NewBlockChain(db, nil, gspec.Config, mock.NewMock(), vm.Config{})
  1047  	defer blockchain.Stop()
  1048  
  1049  	rmLogsCh := make(chan RemovedLogsEvent)
  1050  	blockchain.SubscribeRemovedLogsEvent(rmLogsCh)
  1051  	chain, _ := GenerateChain(params.TestChainConfig, genesis, mock.NewMock(), db, 3, func(i int, gen *BlockGen) {
  1052  		if i == 2 {
  1053  			gen.OffsetTime(2)
  1054  
  1055  			tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1)
  1056  			if err != nil {
  1057  				t.Fatalf("failed to create tx: %v", err)
  1058  			}
  1059  			gen.AddTx(tx)
  1060  		}
  1061  	})
  1062  	if _, err := blockchain.InsertChain(chain); err != nil {
  1063  		t.Fatalf("failed to insert chain: %v", err)
  1064  	}
  1065  
  1066  	// fork chain should to be canonical chain
  1067  	chain, _ = GenerateChain(params.TestChainConfig, genesis, mock.NewMock(), db, 3, func(i int, gen *BlockGen) {})
  1068  	if _, err := blockchain.InsertChain(chain); err != nil {
  1069  		t.Fatalf("failed to insert forked chain: %v", err)
  1070  	}
  1071  
  1072  	timeout := time.NewTimer(1 * time.Second)
  1073  	select {
  1074  	case ev := <-rmLogsCh:
  1075  		if len(ev.Logs) == 0 {
  1076  			t.Error("expected logs")
  1077  		}
  1078  	case <-timeout.C:
  1079  		t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.")
  1080  	}
  1081  }
  1082  
  1083  // Tests if the canonical block can be fetched from the database during chain insertion.
  1084  func TestCanonicalBlockRetrieval(t *testing.T) {
  1085  	_, blockchain, err := newCanonical(mock.NewMock(), 0, true)
  1086  	if err != nil {
  1087  		t.Fatalf("failed to create pristine chain: %v", err)
  1088  	}
  1089  	defer blockchain.Stop()
  1090  
  1091  	chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, mock.NewMock(), blockchain.db, 10, func(i int, gen *BlockGen) {})
  1092  
  1093  	var pend sync.WaitGroup
  1094  	pend.Add(len(chain))
  1095  
  1096  	for i := range chain {
  1097  		go func(block *types.Block) {
  1098  			defer pend.Done()
  1099  
  1100  			// try to retrieve a block by its canonical hash and see if the block data can be retrieved.
  1101  			for {
  1102  				ch := rawdb.ReadCanonicalHash(blockchain.db, block.NumberU64())
  1103  				if ch == (common.Hash{}) {
  1104  					continue // busy wait for canonical hash to be written
  1105  				}
  1106  				if ch != block.Hash() {
  1107  					t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex())
  1108  				}
  1109  				fb := rawdb.ReadBlock(blockchain.db, ch, block.NumberU64())
  1110  				if fb == nil {
  1111  					t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex())
  1112  				}
  1113  				if fb.Hash() != block.Hash() {
  1114  					t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex())
  1115  				}
  1116  				return
  1117  			}
  1118  		}(chain[i])
  1119  
  1120  		if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil {
  1121  			t.Fatalf("failed to insert block %d: %v", i, err)
  1122  		}
  1123  	}
  1124  	pend.Wait()
  1125  }
  1126  
  1127  func TestEIP155Transition(t *testing.T) {
  1128  	// Configure and generate a sample block chain
  1129  	var (
  1130  		db         = vntdb.NewMemDatabase()
  1131  		key, _     = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1132  		address    = crypto.PubkeyToAddress(key.PublicKey)
  1133  		funds      = big.NewInt(1000000000)
  1134  		deleteAddr = common.Address{1}
  1135  		gspec      = &Genesis{
  1136  			Config: &params.ChainConfig{ChainID: big.NewInt(1), HubbleBlock: new(big.Int)},
  1137  			Alloc:  GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}},
  1138  		}
  1139  		genesis = gspec.MustCommit(db)
  1140  	)
  1141  
  1142  	blockchain, _ := NewBlockChain(db, nil, gspec.Config, mock.NewMock(), vm.Config{})
  1143  	defer blockchain.Stop()
  1144  
  1145  	blocks, _ := GenerateChain(gspec.Config, genesis, mock.NewMock(), db, 4, func(i int, block *BlockGen) {
  1146  		var (
  1147  			tx      *types.Transaction
  1148  			err     error
  1149  			basicTx = func(signer types.Signer) (*types.Transaction, error) {
  1150  				return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key)
  1151  			}
  1152  		)
  1153  		switch i {
  1154  		case 0:
  1155  			tx, err = basicTx(types.NewHubbleSigner(gspec.Config.ChainID))
  1156  			if err != nil {
  1157  				t.Fatal(err)
  1158  			}
  1159  			block.AddTx(tx)
  1160  		case 2:
  1161  			tx, err = basicTx(types.NewHubbleSigner(gspec.Config.ChainID))
  1162  			if err != nil {
  1163  				t.Fatal(err)
  1164  			}
  1165  			block.AddTx(tx)
  1166  
  1167  			tx, err = basicTx(types.NewHubbleSigner(gspec.Config.ChainID))
  1168  			if err != nil {
  1169  				t.Fatal(err)
  1170  			}
  1171  			block.AddTx(tx)
  1172  		case 3:
  1173  			tx, err = basicTx(types.NewHubbleSigner(gspec.Config.ChainID))
  1174  			if err != nil {
  1175  				t.Fatal(err)
  1176  			}
  1177  			block.AddTx(tx)
  1178  
  1179  			tx, err = basicTx(types.NewHubbleSigner(gspec.Config.ChainID))
  1180  			if err != nil {
  1181  				t.Fatal(err)
  1182  			}
  1183  			block.AddTx(tx)
  1184  		}
  1185  	})
  1186  
  1187  	if _, err := blockchain.InsertChain(blocks); err != nil {
  1188  		t.Fatal(err)
  1189  	}
  1190  	block := blockchain.GetBlockByNumber(1)
  1191  	if !block.Transactions()[0].Protected() {
  1192  		t.Error("Expected block[0].txs[0] to be replay protected")
  1193  	}
  1194  
  1195  	block = blockchain.GetBlockByNumber(3)
  1196  	if !block.Transactions()[0].Protected() {
  1197  		t.Error("Expected block[3].txs[0] to be replay protected")
  1198  	}
  1199  	if !block.Transactions()[1].Protected() {
  1200  		t.Error("Expected block[3].txs[1] to be replay protected")
  1201  	}
  1202  	if _, err := blockchain.InsertChain(blocks[4:]); err != nil {
  1203  		t.Fatal(err)
  1204  	}
  1205  
  1206  	// generate an invalid chain id transaction
  1207  	config := &params.ChainConfig{ChainID: big.NewInt(2), HubbleBlock: new(big.Int)}
  1208  	blocks, _ = GenerateChain(config, blocks[len(blocks)-1], mock.NewMock(), db, 4, func(i int, block *BlockGen) {
  1209  		var (
  1210  			tx      *types.Transaction
  1211  			err     error
  1212  			basicTx = func(signer types.Signer) (*types.Transaction, error) {
  1213  				return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key)
  1214  			}
  1215  		)
  1216  		switch i {
  1217  		case 0:
  1218  			tx, err = basicTx(types.NewHubbleSigner(big.NewInt(2)))
  1219  			if err != nil {
  1220  				t.Fatal(err)
  1221  			}
  1222  			block.AddTx(tx)
  1223  		}
  1224  	})
  1225  	_, err := blockchain.InsertChain(blocks)
  1226  	if err != types.ErrInvalidChainId {
  1227  		t.Error("expected error:", types.ErrInvalidChainId)
  1228  	}
  1229  }
  1230  
  1231  func TestEIP161AccountRemoval(t *testing.T) {
  1232  	// Configure and generate a sample block chain
  1233  	var (
  1234  		db      = vntdb.NewMemDatabase()
  1235  		key, _  = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1236  		address = crypto.PubkeyToAddress(key.PublicKey)
  1237  		funds   = big.NewInt(1000000000)
  1238  		theAddr = common.Address{1}
  1239  		gspec   = &Genesis{
  1240  			Config: &params.ChainConfig{
  1241  				ChainID:     big.NewInt(1),
  1242  				HubbleBlock: new(big.Int),
  1243  			},
  1244  			Alloc: GenesisAlloc{address: {Balance: funds}},
  1245  		}
  1246  		genesis = gspec.MustCommit(db)
  1247  	)
  1248  	blockchain, _ := NewBlockChain(db, nil, gspec.Config, mock.NewMock(), vm.Config{})
  1249  	defer blockchain.Stop()
  1250  
  1251  	blocks, _ := GenerateChain(gspec.Config, genesis, mock.NewMock(), db, 3, func(i int, block *BlockGen) {
  1252  		var (
  1253  			tx     *types.Transaction
  1254  			err    error
  1255  			signer = types.NewHubbleSigner(gspec.Config.ChainID)
  1256  		)
  1257  		switch i {
  1258  		case 0:
  1259  			tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
  1260  		case 1:
  1261  			tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
  1262  		case 2:
  1263  			tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
  1264  		}
  1265  		if err != nil {
  1266  			t.Fatal(err)
  1267  		}
  1268  		block.AddTx(tx)
  1269  	})
  1270  
  1271  	// account must exist pre eip 161
  1272  	if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil {
  1273  		t.Fatal(err)
  1274  	}
  1275  	if st, _ := blockchain.State(); st.Exist(theAddr) {
  1276  		t.Error("account should not exist")
  1277  	}
  1278  
  1279  	// account needs to be deleted post eip 161
  1280  	if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil {
  1281  		t.Fatal(err)
  1282  	}
  1283  	if st, _ := blockchain.State(); st.Exist(theAddr) {
  1284  		t.Error("account should not exist")
  1285  	}
  1286  
  1287  	// account musn't be created post eip 161
  1288  	if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil {
  1289  		t.Fatal(err)
  1290  	}
  1291  	if st, _ := blockchain.State(); st.Exist(theAddr) {
  1292  		t.Error("account should not exist")
  1293  	}
  1294  }
  1295  
  1296  // Benchmarks large blocks with value transfers to non-existing accounts
  1297  func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) {
  1298  	var (
  1299  		signer          = types.HubbleSigner{}
  1300  		testBankKey, _  = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1301  		testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
  1302  		bankFunds       = big.NewInt(100000000000000000)
  1303  		gspec           = Genesis{
  1304  			Config: params.TestChainConfig,
  1305  			Alloc: GenesisAlloc{
  1306  				testBankAddress: {Balance: bankFunds},
  1307  				common.HexToAddress("0xc0de"): {
  1308  					Code:    []byte{0x60, 0x01, 0x50},
  1309  					Balance: big.NewInt(0),
  1310  				}, // push 1, pop
  1311  			},
  1312  			GasLimit: 100e6, // 100 M
  1313  		}
  1314  	)
  1315  	// Generate the original common chain segment and the two competing forks
  1316  	engine := mock.NewMock()
  1317  	db := vntdb.NewMemDatabase()
  1318  	genesis := gspec.MustCommit(db)
  1319  
  1320  	blockGenerator := func(i int, block *BlockGen) {
  1321  		block.SetCoinbase(common.Address{1})
  1322  		for txi := 0; txi < numTxs; txi++ {
  1323  			uniq := uint64(i*numTxs + txi)
  1324  			recipient := recipientFn(uniq)
  1325  			//recipient := common.BigToAddress(big.NewInt(0).SetUint64(1337 + uniq))
  1326  			tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey)
  1327  			if err != nil {
  1328  				b.Error(err)
  1329  			}
  1330  			block.AddTx(tx)
  1331  		}
  1332  	}
  1333  
  1334  	shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator)
  1335  	b.StopTimer()
  1336  	b.ResetTimer()
  1337  	for i := 0; i < b.N; i++ {
  1338  		// Import the shared chain and the original canonical one
  1339  		diskdb := vntdb.NewMemDatabase()
  1340  		gspec.MustCommit(diskdb)
  1341  
  1342  		chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
  1343  		if err != nil {
  1344  			b.Fatalf("failed to create tester chain: %v", err)
  1345  		}
  1346  		b.StartTimer()
  1347  		if _, err := chain.InsertChain(shared); err != nil {
  1348  			b.Fatalf("failed to insert shared chain: %v", err)
  1349  		}
  1350  		b.StopTimer()
  1351  		if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks {
  1352  			b.Fatalf("Transactions were not included, expected %d, got %d", (numTxs * numBlocks), got)
  1353  
  1354  		}
  1355  	}
  1356  }
  1357  func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) {
  1358  	var (
  1359  		numTxs    = 1000
  1360  		numBlocks = 1
  1361  	)
  1362  
  1363  	recipientFn := func(nonce uint64) common.Address {
  1364  		return common.BigToAddress(big.NewInt(0).SetUint64(1337 + nonce))
  1365  	}
  1366  	dataFn := func(nonce uint64) []byte {
  1367  		return nil
  1368  	}
  1369  
  1370  	benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn)
  1371  }
  1372  func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) {
  1373  	var (
  1374  		numTxs    = 1000
  1375  		numBlocks = 1
  1376  	)
  1377  	b.StopTimer()
  1378  	b.ResetTimer()
  1379  
  1380  	recipientFn := func(nonce uint64) common.Address {
  1381  		return common.BigToAddress(big.NewInt(0).SetUint64(1337))
  1382  	}
  1383  	dataFn := func(nonce uint64) []byte {
  1384  		return nil
  1385  	}
  1386  
  1387  	benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn)
  1388  }
  1389  func BenchmarkBlockChain_1x1000Executions(b *testing.B) {
  1390  	var (
  1391  		numTxs    = 1000
  1392  		numBlocks = 1
  1393  	)
  1394  	b.StopTimer()
  1395  	b.ResetTimer()
  1396  
  1397  	recipientFn := func(nonce uint64) common.Address {
  1398  		return common.BigToAddress(big.NewInt(0).SetUint64(0xc0de))
  1399  	}
  1400  	dataFn := func(nonce uint64) []byte {
  1401  		return nil
  1402  	}
  1403  
  1404  	benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn)
  1405  }