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