github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/eth/downloader/testchain_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:37</date>
    10  //</624450088449609728>
    11  
    12  
    13  package downloader
    14  
    15  import (
    16  	"fmt"
    17  	"math/big"
    18  	"sync"
    19  
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/consensus/ethash"
    22  	"github.com/ethereum/go-ethereum/core"
    23  	"github.com/ethereum/go-ethereum/core/types"
    24  	"github.com/ethereum/go-ethereum/crypto"
    25  	"github.com/ethereum/go-ethereum/ethdb"
    26  	"github.com/ethereum/go-ethereum/params"
    27  )
    28  
    29  //测试链参数。
    30  var (
    31  	testKey, _  = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    32  	testAddress = crypto.PubkeyToAddress(testKey.PublicKey)
    33  	testDB      = ethdb.NewMemDatabase()
    34  	testGenesis = core.GenesisBlockForTesting(testDB, testAddress, big.NewInt(1000000000))
    35  )
    36  
    37  //所有测试链的通用前缀:
    38  var testChainBase = newTestChain(blockCacheItems+200, testGenesis)
    39  
    40  //基链顶部的不同叉:
    41  var testChainForkLightA, testChainForkLightB, testChainForkHeavy *testChain
    42  
    43  func init() {
    44  	var forkLen = int(MaxForkAncestry + 50)
    45  	var wg sync.WaitGroup
    46  	wg.Add(3)
    47  	go func() { testChainForkLightA = testChainBase.makeFork(forkLen, false, 1); wg.Done() }()
    48  	go func() { testChainForkLightB = testChainBase.makeFork(forkLen, false, 2); wg.Done() }()
    49  	go func() { testChainForkHeavy = testChainBase.makeFork(forkLen, true, 3); wg.Done() }()
    50  	wg.Wait()
    51  }
    52  
    53  type testChain struct {
    54  	genesis  *types.Block
    55  	chain    []common.Hash
    56  	headerm  map[common.Hash]*types.Header
    57  	blockm   map[common.Hash]*types.Block
    58  	receiptm map[common.Hash][]*types.Receipt
    59  	tdm      map[common.Hash]*big.Int
    60  }
    61  
    62  //NexTestCu链创建给定长度的块链。
    63  func newTestChain(length int, genesis *types.Block) *testChain {
    64  	tc := new(testChain).copy(length)
    65  	tc.genesis = genesis
    66  	tc.chain = append(tc.chain, genesis.Hash())
    67  	tc.headerm[tc.genesis.Hash()] = tc.genesis.Header()
    68  	tc.tdm[tc.genesis.Hash()] = tc.genesis.Difficulty()
    69  	tc.blockm[tc.genesis.Hash()] = tc.genesis
    70  	tc.generate(length-1, 0, genesis, false)
    71  	return tc
    72  }
    73  
    74  //makefork在测试链的顶部创建一个fork。
    75  func (tc *testChain) makeFork(length int, heavy bool, seed byte) *testChain {
    76  	fork := tc.copy(tc.len() + length)
    77  	fork.generate(length, seed, tc.headBlock(), heavy)
    78  	return fork
    79  }
    80  
    81  //缩短创建一个给定长度的链副本。如果它是恐慌的
    82  //长度大于可用块的数量。
    83  func (tc *testChain) shorten(length int) *testChain {
    84  	if length > tc.len() {
    85  		panic(fmt.Errorf("can't shorten test chain to %d blocks, it's only %d blocks long", length, tc.len()))
    86  	}
    87  	return tc.copy(length)
    88  }
    89  
    90  func (tc *testChain) copy(newlen int) *testChain {
    91  	cpy := &testChain{
    92  		genesis:  tc.genesis,
    93  		headerm:  make(map[common.Hash]*types.Header, newlen),
    94  		blockm:   make(map[common.Hash]*types.Block, newlen),
    95  		receiptm: make(map[common.Hash][]*types.Receipt, newlen),
    96  		tdm:      make(map[common.Hash]*big.Int, newlen),
    97  	}
    98  	for i := 0; i < len(tc.chain) && i < newlen; i++ {
    99  		hash := tc.chain[i]
   100  		cpy.chain = append(cpy.chain, tc.chain[i])
   101  		cpy.tdm[hash] = tc.tdm[hash]
   102  		cpy.blockm[hash] = tc.blockm[hash]
   103  		cpy.headerm[hash] = tc.headerm[hash]
   104  		cpy.receiptm[hash] = tc.receiptm[hash]
   105  	}
   106  	return cpy
   107  }
   108  
   109  //生成创建一个由n个块组成的链,从父块开始并包含父块。
   110  //返回的哈希链是有序的head->parent。此外,每22个街区
   111  //包含一个事务,每隔5分钟一个叔叔以允许测试正确的块
   112  //重新组装。
   113  func (tc *testChain) generate(n int, seed byte, parent *types.Block, heavy bool) {
   114  //开始:=时间。现在())
   115  //defer func()fmt.printf(“测试链在%v中生成”,time.since(start))()
   116  
   117  	blocks, receipts := core.GenerateChain(params.TestChainConfig, parent, ethash.NewFaker(), testDB, n, func(i int, block *core.BlockGen) {
   118  		block.SetCoinbase(common.Address{seed})
   119  //If a heavy chain is requested, delay blocks to raise difficulty
   120  		if heavy {
   121  			block.OffsetTime(-1)
   122  		}
   123  //将事务包括到矿工中,以使块更有趣。
   124  		if parent == tc.genesis && i%22 == 0 {
   125  			signer := types.MakeSigner(params.TestChainConfig, block.Number())
   126  			tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil), signer, testKey)
   127  			if err != nil {
   128  				panic(err)
   129  			}
   130  			block.AddTx(tx)
   131  		}
   132  //如果区块编号是5的倍数,请在区块中添加一个奖金叔叔。
   133  		if i > 0 && i%5 == 0 {
   134  			block.AddUncle(&types.Header{
   135  				ParentHash: block.PrevBlock(i - 1).Hash(),
   136  				Number:     big.NewInt(block.Number().Int64() - 1),
   137  			})
   138  		}
   139  	})
   140  
   141  //将块链转换为哈希链和头/块映射
   142  	td := new(big.Int).Set(tc.td(parent.Hash()))
   143  	for i, b := range blocks {
   144  		td := td.Add(td, b.Difficulty())
   145  		hash := b.Hash()
   146  		tc.chain = append(tc.chain, hash)
   147  		tc.blockm[hash] = b
   148  		tc.headerm[hash] = b.Header()
   149  		tc.receiptm[hash] = receipts[i]
   150  		tc.tdm[hash] = new(big.Int).Set(td)
   151  	}
   152  }
   153  
   154  //len返回链中的块总数。
   155  func (tc *testChain) len() int {
   156  	return len(tc.chain)
   157  }
   158  
   159  //上架返回链条头部。
   160  func (tc *testChain) headBlock() *types.Block {
   161  	return tc.blockm[tc.chain[len(tc.chain)-1]]
   162  }
   163  
   164  //td返回给定块的总难度。
   165  func (tc *testChain) td(hash common.Hash) *big.Int {
   166  	return tc.tdm[hash]
   167  }
   168  
   169  //HeadersByHash从给定哈希按升序返回头。
   170  func (tc *testChain) headersByHash(origin common.Hash, amount int, skip int) []*types.Header {
   171  	num, _ := tc.hashToNumber(origin)
   172  	return tc.headersByNumber(num, amount, skip)
   173  }
   174  
   175  //HeadersByNumber从给定的数字以升序返回标题。
   176  func (tc *testChain) headersByNumber(origin uint64, amount int, skip int) []*types.Header {
   177  	result := make([]*types.Header, 0, amount)
   178  	for num := origin; num < uint64(len(tc.chain)) && len(result) < amount; num += uint64(skip) + 1 {
   179  		if header, ok := tc.headerm[tc.chain[int(num)]]; ok {
   180  			result = append(result, header)
   181  		}
   182  	}
   183  	return result
   184  }
   185  
   186  //收据返回给定块散列的收据。
   187  func (tc *testChain) receipts(hashes []common.Hash) [][]*types.Receipt {
   188  	results := make([][]*types.Receipt, 0, len(hashes))
   189  	for _, hash := range hashes {
   190  		if receipt, ok := tc.receiptm[hash]; ok {
   191  			results = append(results, receipt)
   192  		}
   193  	}
   194  	return results
   195  }
   196  
   197  //bodies返回给定块散列的块体。
   198  func (tc *testChain) bodies(hashes []common.Hash) ([][]*types.Transaction, [][]*types.Header) {
   199  	transactions := make([][]*types.Transaction, 0, len(hashes))
   200  	uncles := make([][]*types.Header, 0, len(hashes))
   201  	for _, hash := range hashes {
   202  		if block, ok := tc.blockm[hash]; ok {
   203  			transactions = append(transactions, block.Transactions())
   204  			uncles = append(uncles, block.Uncles())
   205  		}
   206  	}
   207  	return transactions, uncles
   208  }
   209  
   210  func (tc *testChain) hashToNumber(target common.Hash) (uint64, bool) {
   211  	for num, hash := range tc.chain {
   212  		if hash == target {
   213  			return uint64(num), true
   214  		}
   215  	}
   216  	return 0, false
   217  }
   218