github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/blockchain_test.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2014 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package core 26 27 import ( 28 "fmt" 29 "math/big" 30 "math/rand" 31 "sync" 32 "testing" 33 "time" 34 35 "github.com/ethereum/go-ethereum/common" 36 "github.com/ethereum/go-ethereum/consensus" 37 "github.com/ethereum/go-ethereum/consensus/ethash" 38 "github.com/ethereum/go-ethereum/core/rawdb" 39 "github.com/ethereum/go-ethereum/core/state" 40 "github.com/ethereum/go-ethereum/core/types" 41 "github.com/ethereum/go-ethereum/core/vm" 42 "github.com/ethereum/go-ethereum/crypto" 43 "github.com/ethereum/go-ethereum/ethdb" 44 "github.com/ethereum/go-ethereum/params" 45 ) 46 47 //所以我们可以确定地植入不同的区块链 48 var ( 49 canonicalSeed = 1 50 forkSeed = 2 51 ) 52 53 //newcanonical创建一个链数据库,并注入一个确定性canonical 54 //链。根据完整标志,如果创建完整的区块链或 55 //仅限收割台链条。 56 func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) { 57 var ( 58 db = ethdb.NewMemDatabase() 59 genesis = new(Genesis).MustCommit(db) 60 ) 61 62 //仅使用Genesis块初始化新链 63 blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}) 64 //创建并注入请求的链 65 if n == 0 { 66 return db, blockchain, nil 67 } 68 if full { 69 //请求完整的区块链 70 blocks := makeBlockChain(genesis, n, engine, db, canonicalSeed) 71 _, err := blockchain.InsertChain(blocks) 72 return db, blockchain, err 73 } 74 //仅请求头链 75 headers := makeHeaderChain(genesis.Header(), n, engine, db, canonicalSeed) 76 _, err := blockchain.InsertHeaderChain(headers, 1) 77 return db, blockchain, err 78 } 79 80 //从I区开始的长度为n的测试叉 81 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { 82 //将旧链复制到新数据库中 83 db, blockchain2, err := newCanonical(ethash.NewFaker(), i, full) 84 if err != nil { 85 t.Fatal("could not make new canonical in testFork", err) 86 } 87 defer blockchain2.Stop() 88 89 //断言链在i处具有相同的头/块 90 var hash1, hash2 common.Hash 91 if full { 92 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 93 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 94 } else { 95 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 96 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 97 } 98 if hash1 != hash2 { 99 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 100 } 101 //扩展新创建的链 102 var ( 103 blockChainB []*types.Block 104 headerChainB []*types.Header 105 ) 106 if full { 107 blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed) 108 if _, err := blockchain2.InsertChain(blockChainB); err != nil { 109 t.Fatalf("failed to insert forking chain: %v", err) 110 } 111 } else { 112 headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, ethash.NewFaker(), db, forkSeed) 113 if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { 114 t.Fatalf("failed to insert forking chain: %v", err) 115 } 116 } 117 //健全性检查叉链是否可以导入原始 118 var tdPre, tdPost *big.Int 119 120 if full { 121 tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) 122 if err := testBlockChainImport(blockChainB, blockchain); err != nil { 123 t.Fatalf("failed to import forked block chain: %v", err) 124 } 125 tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) 126 } else { 127 tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) 128 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 129 t.Fatalf("failed to import forked header chain: %v", err) 130 } 131 tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) 132 } 133 //比较链条的总难度 134 comparator(tdPre, tdPost) 135 } 136 137 func printChain(bc *BlockChain) { 138 for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- { 139 b := bc.GetBlockByNumber(uint64(i)) 140 fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty()) 141 } 142 } 143 144 //TestBlockChainImport尝试处理一系列块,将它们写入 145 //如果成功,则返回数据库。 146 func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { 147 for _, block := range chain { 148 //尝试并处理块 149 err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) 150 if err == nil { 151 err = blockchain.validator.ValidateBody(block) 152 } 153 if err != nil { 154 if err == ErrKnownBlock { 155 continue 156 } 157 return err 158 } 159 statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache) 160 if err != nil { 161 return err 162 } 163 receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{}) 164 if err != nil { 165 blockchain.reportBlock(block, receipts, err) 166 return err 167 } 168 err = blockchain.validator.ValidateState(block, blockchain.GetBlockByHash(block.ParentHash()), statedb, receipts, usedGas) 169 if err != nil { 170 blockchain.reportBlock(block, receipts, err) 171 return err 172 } 173 blockchain.mu.Lock() 174 rawdb.WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash()))) 175 rawdb.WriteBlock(blockchain.db, block) 176 statedb.Commit(false) 177 blockchain.mu.Unlock() 178 } 179 return nil 180 } 181 182 //testHeaderChainimport尝试处理一个头链,将其写入 183 //如果成功,则返回数据库。 184 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 185 for _, header := range chain { 186 //尝试验证标题 187 if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { 188 return err 189 } 190 //手动将头插入数据库,但不重新组织(允许后续测试) 191 blockchain.mu.Lock() 192 rawdb.WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash))) 193 rawdb.WriteHeader(blockchain.db, header) 194 blockchain.mu.Unlock() 195 } 196 return nil 197 } 198 199 func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) { 200 _, err := blockchain.InsertChain(chain) 201 if err != nil { 202 fmt.Println(err) 203 t.FailNow() 204 } 205 done <- true 206 } 207 208 func TestLastBlock(t *testing.T) { 209 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) 210 if err != nil { 211 t.Fatalf("failed to create pristine chain: %v", err) 212 } 213 defer blockchain.Stop() 214 215 blocks := makeBlockChain(blockchain.CurrentBlock(), 1, ethash.NewFullFaker(), blockchain.db, 0) 216 if _, err := blockchain.InsertChain(blocks); err != nil { 217 t.Fatalf("Failed to insert block: %v", err) 218 } 219 if blocks[len(blocks)-1].Hash() != rawdb.ReadHeadBlockHash(blockchain.db) { 220 t.Fatalf("Write/Get HeadBlockHash failed") 221 } 222 } 223 224 //测试给定一个给定大小的起始规范链,它可以被扩展 225 //有各种长度的链条。 226 func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } 227 func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } 228 229 func testExtendCanonical(t *testing.T, full bool) { 230 length := 5 231 232 //从创世纪开始制造第一条链条 233 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 234 if err != nil { 235 t.Fatalf("failed to make new canonical chain: %v", err) 236 } 237 defer processor.Stop() 238 239 //定义难度比较器 240 better := func(td1, td2 *big.Int) { 241 if td2.Cmp(td1) <= 0 { 242 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 243 } 244 } 245 //从当前高度开始拨叉 246 testFork(t, processor, length, 1, full, better) 247 testFork(t, processor, length, 2, full, better) 248 testFork(t, processor, length, 5, full, better) 249 testFork(t, processor, length, 10, full, better) 250 } 251 252 //测试给定给定大小的起始规范链,创建较短的 253 //forks不具有规范的所有权。 254 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } 255 func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } 256 257 func testShorterFork(t *testing.T, full bool) { 258 length := 10 259 260 //从创世纪开始制造第一条链条 261 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 262 if err != nil { 263 t.Fatalf("failed to make new canonical chain: %v", err) 264 } 265 defer processor.Stop() 266 267 //定义难度比较器 268 worse := func(td1, td2 *big.Int) { 269 if td2.Cmp(td1) >= 0 { 270 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 271 } 272 } 273 //数字之和必须小于“length”,才能成为较短的分叉 274 testFork(t, processor, 0, 3, full, worse) 275 testFork(t, processor, 0, 7, full, worse) 276 testFork(t, processor, 1, 1, full, worse) 277 testFork(t, processor, 1, 7, full, worse) 278 testFork(t, processor, 5, 3, full, worse) 279 testFork(t, processor, 5, 4, full, worse) 280 } 281 282 //测试给定给定大小的起始规范链,创建更长的 283 //forks确实拥有规范的所有权。 284 func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } 285 func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } 286 287 func testLongerFork(t *testing.T, full bool) { 288 length := 10 289 290 //从创世纪开始制造第一条链条 291 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 292 if err != nil { 293 t.Fatalf("failed to make new canonical chain: %v", err) 294 } 295 defer processor.Stop() 296 297 //定义难度比较器 298 better := func(td1, td2 *big.Int) { 299 if td2.Cmp(td1) <= 0 { 300 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 301 } 302 } 303 //数字之和必须大于“length”,才能成为较长的分叉 304 testFork(t, processor, 0, 11, full, better) 305 testFork(t, processor, 0, 15, full, better) 306 testFork(t, processor, 1, 10, full, better) 307 testFork(t, processor, 1, 12, full, better) 308 testFork(t, processor, 5, 6, full, better) 309 testFork(t, processor, 5, 8, full, better) 310 } 311 312 //测试给定给定大小的起始规范链,创建相等的 313 //forks确实拥有规范的所有权。 314 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } 315 func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } 316 317 func testEqualFork(t *testing.T, full bool) { 318 length := 10 319 320 //从创世纪开始制造第一条链条 321 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 322 if err != nil { 323 t.Fatalf("failed to make new canonical chain: %v", err) 324 } 325 defer processor.Stop() 326 327 //定义难度比较器 328 equal := func(td1, td2 *big.Int) { 329 if td2.Cmp(td1) != 0 { 330 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 331 } 332 } 333 //数字之和必须等于“length”,才能成为相等的叉 334 testFork(t, processor, 0, 10, full, equal) 335 testFork(t, processor, 1, 9, full, equal) 336 testFork(t, processor, 2, 8, full, equal) 337 testFork(t, processor, 5, 5, full, equal) 338 testFork(t, processor, 6, 4, full, equal) 339 testFork(t, processor, 9, 1, full, equal) 340 } 341 342 //处理器不接受链接缺失的测试。 343 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } 344 func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } 345 346 func testBrokenChain(t *testing.T, full bool) { 347 //从Genesis开始制作链条 348 db, blockchain, err := newCanonical(ethash.NewFaker(), 10, full) 349 if err != nil { 350 t.Fatalf("failed to make new canonical chain: %v", err) 351 } 352 defer blockchain.Stop() 353 354 //创建分叉链,并尝试插入缺少的链接 355 if full { 356 chain := makeBlockChain(blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed)[1:] 357 if err := testBlockChainImport(chain, blockchain); err == nil { 358 t.Errorf("broken block chain not reported") 359 } 360 } else { 361 chain := makeHeaderChain(blockchain.CurrentHeader(), 5, ethash.NewFaker(), db, forkSeed)[1:] 362 if err := testHeaderChainImport(chain, blockchain); err == nil { 363 t.Errorf("broken header chain not reported") 364 } 365 } 366 } 367 368 //在短而容易的链条之后对长而难的链条进行重组的测试 369 //覆盖数据库中的规范数字和链接。 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, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280, full) 375 } 376 377 //在一个长而容易的链之后重新组织一个短而难的链的测试 378 //覆盖数据库中的规范数字和链接。 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 //创建一个长而容易的链条与短而重的链条。由于调整困难 384 //我们需要一个相当长的、有不同困难的区块链。 385 //比长的更重。96是一个经验值。 386 easy := make([]int64, 96) 387 for i := 0; i < len(easy); i++ { 388 easy[i] = 60 389 } 390 diff := make([]int64, len(easy)-1) 391 for i := 0; i < len(diff); i++ { 392 diff[i] = -9 393 } 394 testReorg(t, easy, diff, 12615120, full) 395 } 396 397 func testReorg(t *testing.T, first, second []int64, td int64, full bool) { 398 //创建原始链和数据库 399 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 400 if err != nil { 401 t.Fatalf("failed to create pristine chain: %v", err) 402 } 403 defer blockchain.Stop() 404 405 //然后插入一个容易和困难的链条 406 easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(first), func(i int, b *BlockGen) { 407 b.OffsetTime(first[i]) 408 }) 409 diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(second), func(i int, b *BlockGen) { 410 b.OffsetTime(second[i]) 411 }) 412 if full { 413 if _, err := blockchain.InsertChain(easyBlocks); err != nil { 414 t.Fatalf("failed to insert easy chain: %v", err) 415 } 416 if _, err := blockchain.InsertChain(diffBlocks); err != nil { 417 t.Fatalf("failed to insert difficult chain: %v", err) 418 } 419 } else { 420 easyHeaders := make([]*types.Header, len(easyBlocks)) 421 for i, block := range easyBlocks { 422 easyHeaders[i] = block.Header() 423 } 424 diffHeaders := make([]*types.Header, len(diffBlocks)) 425 for i, block := range diffBlocks { 426 diffHeaders[i] = block.Header() 427 } 428 if _, err := blockchain.InsertHeaderChain(easyHeaders, 1); err != nil { 429 t.Fatalf("failed to insert easy chain: %v", err) 430 } 431 if _, err := blockchain.InsertHeaderChain(diffHeaders, 1); err != nil { 432 t.Fatalf("failed to insert difficult chain: %v", err) 433 } 434 } 435 //检查链条是否为有效的数字和链接方式 436 if full { 437 prev := blockchain.CurrentBlock() 438 for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.GetBlockByNumber(block.NumberU64()-1) { 439 if prev.ParentHash() != block.Hash() { 440 t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) 441 } 442 } 443 } else { 444 prev := blockchain.CurrentHeader() 445 for header := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, blockchain.GetHeaderByNumber(header.Number.Uint64()-1) { 446 if prev.ParentHash != header.Hash() { 447 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 448 } 449 } 450 } 451 //确保链条的总难度是正确的。 452 want := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) 453 if full { 454 if have := blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()); have.Cmp(want) != 0 { 455 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 456 } 457 } else { 458 if have := blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()); have.Cmp(want) != 0 { 459 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 460 } 461 } 462 } 463 464 //测试插入函数是否检测禁止的哈希。 465 func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) } 466 func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) } 467 468 func testBadHashes(t *testing.T, full bool) { 469 //创建原始链和数据库 470 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 471 if err != nil { 472 t.Fatalf("failed to create pristine chain: %v", err) 473 } 474 defer blockchain.Stop() 475 476 //创建链,禁止散列并尝试导入 477 if full { 478 blocks := makeBlockChain(blockchain.CurrentBlock(), 3, ethash.NewFaker(), db, 10) 479 480 BadHashes[blocks[2].Header().Hash()] = true 481 defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() 482 483 _, err = blockchain.InsertChain(blocks) 484 } else { 485 headers := makeHeaderChain(blockchain.CurrentHeader(), 3, ethash.NewFaker(), db, 10) 486 487 BadHashes[headers[2].Hash()] = true 488 defer func() { delete(BadHashes, headers[2].Hash()) }() 489 490 _, err = blockchain.InsertHeaderChain(headers, 1) 491 } 492 if err != ErrBlacklistedHash { 493 t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash) 494 } 495 } 496 497 //测试在引导时检测到错误的哈希,并将链回滚到 498 //坏哈希前的良好状态。 499 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } 500 func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } 501 502 func testReorgBadHashes(t *testing.T, full bool) { 503 //创建原始链和数据库 504 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 505 if err != nil { 506 t.Fatalf("failed to create pristine chain: %v", err) 507 } 508 //创建一个链,然后导入和禁止 509 headers := makeHeaderChain(blockchain.CurrentHeader(), 4, ethash.NewFaker(), db, 10) 510 blocks := makeBlockChain(blockchain.CurrentBlock(), 4, ethash.NewFaker(), db, 10) 511 512 if full { 513 if _, err = blockchain.InsertChain(blocks); err != nil { 514 t.Errorf("failed to import blocks: %v", err) 515 } 516 if blockchain.CurrentBlock().Hash() != blocks[3].Hash() { 517 t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash()) 518 } 519 BadHashes[blocks[3].Header().Hash()] = true 520 defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() 521 } else { 522 if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil { 523 t.Errorf("failed to import headers: %v", err) 524 } 525 if blockchain.CurrentHeader().Hash() != headers[3].Hash() { 526 t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash()) 527 } 528 BadHashes[headers[3].Hash()] = true 529 defer func() { delete(BadHashes, headers[3].Hash()) }() 530 } 531 blockchain.Stop() 532 533 //创建一个新的区块链并检查它是否回滚状态。 534 ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}) 535 if err != nil { 536 t.Fatalf("failed to create new chain manager: %v", err) 537 } 538 if full { 539 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 540 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 541 } 542 if blocks[2].Header().GasLimit != ncm.GasLimit() { 543 t.Errorf("last block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit) 544 } 545 } else { 546 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 547 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 548 } 549 } 550 ncm.Stop() 551 } 552 553 //在包含无效nonce的实体的面上测试链插入。 554 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } 555 func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } 556 557 func testInsertNonceError(t *testing.T, full bool) { 558 for i := 1; i < 25 && !t.Failed(); i++ { 559 //创建原始链和数据库 560 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 561 if err != nil { 562 t.Fatalf("failed to create pristine chain: %v", err) 563 } 564 defer blockchain.Stop() 565 566 //创建并插入带有失败的nonce的链 567 var ( 568 failAt int 569 failRes int 570 failNum uint64 571 ) 572 if full { 573 blocks := makeBlockChain(blockchain.CurrentBlock(), i, ethash.NewFaker(), db, 0) 574 575 failAt = rand.Int() % len(blocks) 576 failNum = blocks[failAt].NumberU64() 577 578 blockchain.engine = ethash.NewFakeFailer(failNum) 579 failRes, err = blockchain.InsertChain(blocks) 580 } else { 581 headers := makeHeaderChain(blockchain.CurrentHeader(), i, ethash.NewFaker(), db, 0) 582 583 failAt = rand.Int() % len(headers) 584 failNum = headers[failAt].Number.Uint64() 585 586 blockchain.engine = ethash.NewFakeFailer(failNum) 587 blockchain.hc.engine = blockchain.engine 588 failRes, err = blockchain.InsertHeaderChain(headers, 1) 589 } 590 //检查返回的错误是否指示故障。 591 if failRes != failAt { 592 t.Errorf("test %d: failure index mismatch: have %d, want %d", i, failRes, failAt) 593 } 594 //检查故障块插入后是否所有块都没有。 595 for j := 0; j < i-failAt; j++ { 596 if full { 597 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 598 t.Errorf("test %d: invalid block in chain: %v", i, block) 599 } 600 } else { 601 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 602 t.Errorf("test %d: invalid header in chain: %v", i, header) 603 } 604 } 605 } 606 } 607 } 608 609 //测试快速导入块链是否产生与 610 //经典的全块处理。 611 func TestFastVsFullChains(t *testing.T) { 612 //配置并生成示例区块链 613 var ( 614 gendb = ethdb.NewMemDatabase() 615 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 616 address = crypto.PubkeyToAddress(key.PublicKey) 617 funds = big.NewInt(1000000000) 618 gspec = &Genesis{ 619 Config: params.TestChainConfig, 620 Alloc: GenesisAlloc{address: {Balance: funds}}, 621 } 622 genesis = gspec.MustCommit(gendb) 623 signer = types.NewEIP155Signer(gspec.Config.ChainID) 624 ) 625 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, 1024, func(i int, block *BlockGen) { 626 block.SetCoinbase(common.Address{0x00}) 627 628 //如果区块号是3的倍数,则向矿工发送一些奖金交易。 629 if i%3 == 2 { 630 for j := 0; j < i%4+1; j++ { 631 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key) 632 if err != nil { 633 panic(err) 634 } 635 block.AddTx(tx) 636 } 637 } 638 //如果区块编号是5的倍数,则在区块中添加一些奖金叔叔。 639 if i%5 == 5 { 640 block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))}) 641 } 642 }) 643 //将链作为比较基准的存档节点导入 644 archiveDb := ethdb.NewMemDatabase() 645 gspec.MustCommit(archiveDb) 646 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 647 defer archive.Stop() 648 649 if n, err := archive.InsertChain(blocks); err != nil { 650 t.Fatalf("failed to process block %d: %v", n, err) 651 } 652 //将链快速导入为要测试的非存档节点 653 fastDb := ethdb.NewMemDatabase() 654 gspec.MustCommit(fastDb) 655 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 656 defer fast.Stop() 657 658 headers := make([]*types.Header, len(blocks)) 659 for i, block := range blocks { 660 headers[i] = block.Header() 661 } 662 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 663 t.Fatalf("failed to insert header %d: %v", n, err) 664 } 665 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 666 t.Fatalf("failed to insert receipt %d: %v", n, err) 667 } 668 //遍历所有链数据组件,并交叉引用 669 for i := 0; i < len(blocks); i++ { 670 num, hash := blocks[i].NumberU64(), blocks[i].Hash() 671 672 if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 { 673 t.Errorf("block #%d [%x]: td mismatch: have %v, want %v", num, hash, ftd, atd) 674 } 675 if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { 676 t.Errorf("block #%d [%x]: header mismatch: have %v, want %v", num, hash, fheader, aheader) 677 } 678 if fblock, ablock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash); fblock.Hash() != ablock.Hash() { 679 t.Errorf("block #%d [%x]: block mismatch: have %v, want %v", num, hash, fblock, ablock) 680 } else if types.DeriveSha(fblock.Transactions()) != types.DeriveSha(ablock.Transactions()) { 681 t.Errorf("block #%d [%x]: transactions mismatch: have %v, want %v", num, hash, fblock.Transactions(), ablock.Transactions()) 682 } else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(ablock.Uncles()) { 683 t.Errorf("block #%d [%x]: uncles mismatch: have %v, want %v", num, hash, fblock.Uncles(), ablock.Uncles()) 684 } 685 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) { 686 t.Errorf("block #%d [%x]: receipts mismatch: have %v, want %v", num, hash, freceipts, areceipts) 687 } 688 } 689 //检查数据库之间的规范链是否相同 690 for i := 0; i < len(blocks)+1; i++ { 691 if fhash, ahash := rawdb.ReadCanonicalHash(fastDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); fhash != ahash { 692 t.Errorf("block #%d: canonical hash mismatch: have %v, want %v", i, fhash, ahash) 693 } 694 } 695 } 696 697 //测试各种导入方法是否将链头指针移动到正确的 698 //位置。 699 func TestLightVsFastVsFullChainHeads(t *testing.T) { 700 //配置并生成示例区块链 701 var ( 702 gendb = ethdb.NewMemDatabase() 703 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 704 address = crypto.PubkeyToAddress(key.PublicKey) 705 funds = big.NewInt(1000000000) 706 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 707 genesis = gspec.MustCommit(gendb) 708 ) 709 height := uint64(1024) 710 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 711 712 //配置子链以回滚 713 remove := []common.Hash{} 714 for _, block := range blocks[height/2:] { 715 remove = append(remove, block.Hash()) 716 } 717 //创建一个小断言方法来检查三个头 718 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 719 if num := chain.CurrentBlock().NumberU64(); num != block { 720 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 721 } 722 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 723 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 724 } 725 if num := chain.CurrentHeader().Number.Uint64(); num != header { 726 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 727 } 728 } 729 //将链作为存档节点导入,并确保更新所有指针 730 archiveDb := ethdb.NewMemDatabase() 731 gspec.MustCommit(archiveDb) 732 733 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 734 if n, err := archive.InsertChain(blocks); err != nil { 735 t.Fatalf("failed to process block %d: %v", n, err) 736 } 737 defer archive.Stop() 738 739 assert(t, "archive", archive, height, height, height) 740 archive.Rollback(remove) 741 assert(t, "archive", archive, height/2, height/2, height/2) 742 743 //将链作为非存档节点导入,并确保更新所有指针 744 fastDb := ethdb.NewMemDatabase() 745 gspec.MustCommit(fastDb) 746 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 747 defer fast.Stop() 748 749 headers := make([]*types.Header, len(blocks)) 750 for i, block := range blocks { 751 headers[i] = block.Header() 752 } 753 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 754 t.Fatalf("failed to insert header %d: %v", n, err) 755 } 756 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 757 t.Fatalf("failed to insert receipt %d: %v", n, err) 758 } 759 assert(t, "fast", fast, height, height, 0) 760 fast.Rollback(remove) 761 assert(t, "fast", fast, height/2, height/2, 0) 762 763 //将链作为轻型节点导入,并确保更新所有指针 764 lightDb := ethdb.NewMemDatabase() 765 gspec.MustCommit(lightDb) 766 767 light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 768 if n, err := light.InsertHeaderChain(headers, 1); err != nil { 769 t.Fatalf("failed to insert header %d: %v", n, err) 770 } 771 defer light.Stop() 772 773 assert(t, "light", light, height, 0, 0) 774 light.Rollback(remove) 775 assert(t, "light", light, height/2, 0, 0) 776 } 777 778 //链重组处理事务移除和重新插入的测试。 779 func TestChainTxReorgs(t *testing.T) { 780 var ( 781 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 782 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 783 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 784 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 785 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 786 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 787 db = ethdb.NewMemDatabase() 788 gspec = &Genesis{ 789 Config: params.TestChainConfig, 790 GasLimit: 3141592, 791 Alloc: GenesisAlloc{ 792 addr1: {Balance: big.NewInt(1000000)}, 793 addr2: {Balance: big.NewInt(1000000)}, 794 addr3: {Balance: big.NewInt(1000000)}, 795 }, 796 } 797 genesis = gspec.MustCommit(db) 798 signer = types.NewEIP155Signer(gspec.Config.ChainID) 799 ) 800 801 //创建链之间共享的两个事务: 802 //-延期:在分叉链的后一个块中包含事务 803 //-交换:在分叉链中同一个块编号处包含的事务 804 postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 805 swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 806 807 //创建将由分叉链删除的两个事务: 808 //-pastdrop:从上一个块追溯删除的事务 809 //-freshdrop:事务正好在检测到REORG的块上删除 810 var pastDrop, freshDrop *types.Transaction 811 812 //创建将添加到分叉链中的三个事务: 813 //-pastadd:在检测到重组之前添加的事务 814 //-freshadd:在检测到REORG的确切块处添加的事务 815 //-futureread:在REORG完成后添加的事务 816 var pastAdd, freshAdd, futureAdd *types.Transaction 817 818 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) { 819 switch i { 820 case 0: 821 pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 822 823 gen.AddTx(pastDrop) //此事务将从拆分点下方放到分叉中。 824 gen.AddTx(postponed) //此交易将推迟到fork的block 3 825 826 case 2: 827 freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 828 829 gen.AddTx(freshDrop) //此事务将从拆分点完全删除到分叉中。 830 gen.AddTx(swapped) //此事务将在准确的高度交换出去 831 832 gen.OffsetTime(9) //降低块难度以模拟较弱的链 833 } 834 }) 835 //导入链。这将运行所有块验证规则。 836 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 837 if i, err := blockchain.InsertChain(chain); err != nil { 838 t.Fatalf("failed to insert original chain[%d]: %v", i, err) 839 } 840 defer blockchain.Stop() 841 842 //覆盖旧链 843 chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) { 844 switch i { 845 case 0: 846 pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 847 gen.AddTx(pastAdd) //此事务需要在REORG期间注入 848 849 case 2: 850 gen.AddTx(postponed) //此交易从原始链中的块1推迟。 851 gen.AddTx(swapped) //此交易是从原始链中的确切当前点交换的 852 853 freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 854 gen.AddTx(freshAdd) //此事务将在REORG时完全添加 855 856 case 3: 857 futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 858 gen.AddTx(futureAdd) //此事务将在完全重新排序后添加 859 } 860 }) 861 if _, err := blockchain.InsertChain(chain); err != nil { 862 t.Fatalf("failed to insert forked chain: %v", err) 863 } 864 865 //移除TX 866 for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 867 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil { 868 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 869 } 870 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt != nil { 871 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 872 } 873 } 874 //添加TX 875 for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 876 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 877 t.Errorf("add %d: expected tx to be found", i) 878 } 879 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil { 880 t.Errorf("add %d: expected receipt to be found", i) 881 } 882 } 883 //共享TX 884 for i, tx := range (types.Transactions{postponed, swapped}) { 885 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 886 t.Errorf("share %d: expected tx to be found", i) 887 } 888 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil { 889 t.Errorf("share %d: expected receipt to be found", i) 890 } 891 } 892 } 893 894 func TestLogReorgs(t *testing.T) { 895 896 var ( 897 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 898 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 899 db = ethdb.NewMemDatabase() 900 //此代码生成日志 901 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 902 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 903 genesis = gspec.MustCommit(db) 904 signer = types.NewEIP155Signer(gspec.Config.ChainID) 905 ) 906 907 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 908 defer blockchain.Stop() 909 910 rmLogsCh := make(chan RemovedLogsEvent) 911 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 912 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 913 if i == 1 { 914 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 915 if err != nil { 916 t.Fatalf("failed to create tx: %v", err) 917 } 918 gen.AddTx(tx) 919 } 920 }) 921 if _, err := blockchain.InsertChain(chain); err != nil { 922 t.Fatalf("failed to insert chain: %v", err) 923 } 924 925 chain, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 926 if _, err := blockchain.InsertChain(chain); err != nil { 927 t.Fatalf("failed to insert forked chain: %v", err) 928 } 929 930 timeout := time.NewTimer(1 * time.Second) 931 select { 932 case ev := <-rmLogsCh: 933 if len(ev.Logs) == 0 { 934 t.Error("expected logs") 935 } 936 case <-timeout.C: 937 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 938 } 939 } 940 941 func TestReorgSideEvent(t *testing.T) { 942 var ( 943 db = ethdb.NewMemDatabase() 944 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 945 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 946 gspec = &Genesis{ 947 Config: params.TestChainConfig, 948 Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}, 949 } 950 genesis = gspec.MustCommit(db) 951 signer = types.NewEIP155Signer(gspec.Config.ChainID) 952 ) 953 954 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 955 defer blockchain.Stop() 956 957 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 958 if _, err := blockchain.InsertChain(chain); err != nil { 959 t.Fatalf("failed to insert chain: %v", err) 960 } 961 962 replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) { 963 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1) 964 if i == 2 { 965 gen.OffsetTime(-9) 966 } 967 if err != nil { 968 t.Fatalf("failed to create tx: %v", err) 969 } 970 gen.AddTx(tx) 971 }) 972 chainSideCh := make(chan ChainSideEvent, 64) 973 blockchain.SubscribeChainSideEvent(chainSideCh) 974 if _, err := blockchain.InsertChain(replacementBlocks); err != nil { 975 t.Fatalf("failed to insert chain: %v", err) 976 } 977 978 //第二链的前两个区块被考虑了一小段时间。 979 //侧链,因为在这一点上,第一个被认为是 980 //较重的链。 981 expectedSideHashes := map[common.Hash]bool{ 982 replacementBlocks[0].Hash(): true, 983 replacementBlocks[1].Hash(): true, 984 chain[0].Hash(): true, 985 chain[1].Hash(): true, 986 chain[2].Hash(): true, 987 } 988 989 i := 0 990 991 const timeoutDura = 10 * time.Second 992 timeout := time.NewTimer(timeoutDura) 993 done: 994 for { 995 select { 996 case ev := <-chainSideCh: 997 block := ev.Block 998 if _, ok := expectedSideHashes[block.Hash()]; !ok { 999 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 1000 } 1001 i++ 1002 1003 if i == len(expectedSideHashes) { 1004 timeout.Stop() 1005 1006 break done 1007 } 1008 timeout.Reset(timeoutDura) 1009 1010 case <-timeout.C: 1011 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 1012 } 1013 } 1014 1015 //确保不再触发事件 1016 select { 1017 case e := <-chainSideCh: 1018 t.Errorf("unexpected event fired: %v", e) 1019 case <-time.After(250 * time.Millisecond): 1020 } 1021 1022 } 1023 1024 //测试在链插入期间是否可以从数据库中提取规范块。 1025 func TestCanonicalBlockRetrieval(t *testing.T) { 1026 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) 1027 if err != nil { 1028 t.Fatalf("failed to create pristine chain: %v", err) 1029 } 1030 defer blockchain.Stop() 1031 1032 chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, ethash.NewFaker(), blockchain.db, 10, func(i int, gen *BlockGen) {}) 1033 1034 var pend sync.WaitGroup 1035 pend.Add(len(chain)) 1036 1037 for i := range chain { 1038 go func(block *types.Block) { 1039 defer pend.Done() 1040 1041 //尝试通过其规范哈希检索块,并查看是否可以检索块数据。 1042 for { 1043 ch := rawdb.ReadCanonicalHash(blockchain.db, block.NumberU64()) 1044 if ch == (common.Hash{}) { 1045 continue //正忙等待规范哈希被写入 1046 } 1047 if ch != block.Hash() { 1048 t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1049 } 1050 fb := rawdb.ReadBlock(blockchain.db, ch, block.NumberU64()) 1051 if fb == nil { 1052 t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1053 } 1054 if fb.Hash() != block.Hash() { 1055 t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1056 } 1057 return 1058 } 1059 }(chain[i]) 1060 1061 if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { 1062 t.Fatalf("failed to insert block %d: %v", i, err) 1063 } 1064 } 1065 pend.Wait() 1066 } 1067 1068 func TestEIP155Transition(t *testing.T) { 1069 //配置并生成示例区块链 1070 var ( 1071 db = ethdb.NewMemDatabase() 1072 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1073 address = crypto.PubkeyToAddress(key.PublicKey) 1074 funds = big.NewInt(1000000000) 1075 deleteAddr = common.Address{1} 1076 gspec = &Genesis{ 1077 Config: ¶ms.ChainConfig{ChainID: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}, 1078 Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 1079 } 1080 genesis = gspec.MustCommit(db) 1081 ) 1082 1083 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 1084 defer blockchain.Stop() 1085 1086 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1087 var ( 1088 tx *types.Transaction 1089 err error 1090 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1091 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1092 } 1093 ) 1094 switch i { 1095 case 0: 1096 tx, err = basicTx(types.HomesteadSigner{}) 1097 if err != nil { 1098 t.Fatal(err) 1099 } 1100 block.AddTx(tx) 1101 case 2: 1102 tx, err = basicTx(types.HomesteadSigner{}) 1103 if err != nil { 1104 t.Fatal(err) 1105 } 1106 block.AddTx(tx) 1107 1108 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainID)) 1109 if err != nil { 1110 t.Fatal(err) 1111 } 1112 block.AddTx(tx) 1113 case 3: 1114 tx, err = basicTx(types.HomesteadSigner{}) 1115 if err != nil { 1116 t.Fatal(err) 1117 } 1118 block.AddTx(tx) 1119 1120 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainID)) 1121 if err != nil { 1122 t.Fatal(err) 1123 } 1124 block.AddTx(tx) 1125 } 1126 }) 1127 1128 if _, err := blockchain.InsertChain(blocks); err != nil { 1129 t.Fatal(err) 1130 } 1131 block := blockchain.GetBlockByNumber(1) 1132 if block.Transactions()[0].Protected() { 1133 t.Error("Expected block[0].txs[0] to not be replay protected") 1134 } 1135 1136 block = blockchain.GetBlockByNumber(3) 1137 if block.Transactions()[0].Protected() { 1138 t.Error("Expected block[3].txs[0] to not be replay protected") 1139 } 1140 if !block.Transactions()[1].Protected() { 1141 t.Error("Expected block[3].txs[1] to be replay protected") 1142 } 1143 if _, err := blockchain.InsertChain(blocks[4:]); err != nil { 1144 t.Fatal(err) 1145 } 1146 1147 //生成无效的链ID事务 1148 config := ¶ms.ChainConfig{ChainID: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)} 1149 blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1150 var ( 1151 tx *types.Transaction 1152 err error 1153 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1154 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1155 } 1156 ) 1157 if i == 0 { 1158 tx, err = basicTx(types.NewEIP155Signer(big.NewInt(2))) 1159 if err != nil { 1160 t.Fatal(err) 1161 } 1162 block.AddTx(tx) 1163 } 1164 }) 1165 _, err := blockchain.InsertChain(blocks) 1166 if err != types.ErrInvalidChainId { 1167 t.Error("expected error:", types.ErrInvalidChainId) 1168 } 1169 } 1170 1171 func TestEIP161AccountRemoval(t *testing.T) { 1172 //配置并生成示例区块链 1173 var ( 1174 db = ethdb.NewMemDatabase() 1175 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1176 address = crypto.PubkeyToAddress(key.PublicKey) 1177 funds = big.NewInt(1000000000) 1178 theAddr = common.Address{1} 1179 gspec = &Genesis{ 1180 Config: ¶ms.ChainConfig{ 1181 ChainID: big.NewInt(1), 1182 HomesteadBlock: new(big.Int), 1183 EIP155Block: new(big.Int), 1184 EIP158Block: big.NewInt(2), 1185 }, 1186 Alloc: GenesisAlloc{address: {Balance: funds}}, 1187 } 1188 genesis = gspec.MustCommit(db) 1189 ) 1190 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 1191 defer blockchain.Stop() 1192 1193 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) { 1194 var ( 1195 tx *types.Transaction 1196 err error 1197 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1198 ) 1199 switch i { 1200 case 0: 1201 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1202 case 1: 1203 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1204 case 2: 1205 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1206 } 1207 if err != nil { 1208 t.Fatal(err) 1209 } 1210 block.AddTx(tx) 1211 }) 1212 //账户必须存在于EIP 161之前 1213 if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1214 t.Fatal(err) 1215 } 1216 if st, _ := blockchain.State(); !st.Exist(theAddr) { 1217 t.Error("expected account to exist") 1218 } 1219 1220 //在EIP 161之后需要删除帐户 1221 if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1222 t.Fatal(err) 1223 } 1224 if st, _ := blockchain.State(); st.Exist(theAddr) { 1225 t.Error("account should not exist") 1226 } 1227 1228 //不能在EIP 161后创建帐户库 1229 if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1230 t.Fatal(err) 1231 } 1232 if st, _ := blockchain.State(); st.Exist(theAddr) { 1233 t.Error("account should not exist") 1234 } 1235 } 1236 1237 //这是一个回归测试(也就是说,尽管很奇怪,但永远不要删除它),它 1238 //测试在奇怪的重组条件下,区块链及其内部头段- 1239 //链返回相同的最新块/头。 1240 // 1241 //https://github.com/ethereum/go-ethereum/pull/15941 1242 func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { 1243 //生成规范链作为主数据集 1244 engine := ethash.NewFaker() 1245 1246 db := ethdb.NewMemDatabase() 1247 genesis := new(Genesis).MustCommit(db) 1248 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1249 1250 //生成一组分叉块,每侧都从规范链分叉 1251 forks := make([]*types.Block, len(blocks)) 1252 for i := 0; i < len(forks); i++ { 1253 parent := genesis 1254 if i > 0 { 1255 parent = blocks[i-1] 1256 } 1257 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1258 forks[i] = fork[0] 1259 } 1260 //并排导入规范链和叉链,验证当前块 1261 //和当前标题一致性 1262 diskdb := ethdb.NewMemDatabase() 1263 new(Genesis).MustCommit(diskdb) 1264 1265 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1266 if err != nil { 1267 t.Fatalf("failed to create tester chain: %v", err) 1268 } 1269 for i := 0; i < len(blocks); i++ { 1270 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1271 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1272 } 1273 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1274 t.Errorf("block %d: current block/header mismatch: block #%d [%x…], header #%d [%x…]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) 1275 } 1276 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1277 t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) 1278 } 1279 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1280 t.Errorf(" fork %d: current block/header mismatch: block #%d [%x…], header #%d [%x…]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) 1281 } 1282 } 1283 } 1284 1285 //测试导入小型侧叉不会在trie数据库中留下垃圾 1286 //缓存(最终会导致内存问题)。 1287 func TestTrieForkGC(t *testing.T) { 1288 //生成规范链作为主数据集 1289 engine := ethash.NewFaker() 1290 1291 db := ethdb.NewMemDatabase() 1292 genesis := new(Genesis).MustCommit(db) 1293 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1294 1295 //生成一组分叉块,每侧都从规范链分叉 1296 forks := make([]*types.Block, len(blocks)) 1297 for i := 0; i < len(forks); i++ { 1298 parent := genesis 1299 if i > 0 { 1300 parent = blocks[i-1] 1301 } 1302 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1303 forks[i] = fork[0] 1304 } 1305 //并排导入规范链和分叉链,强制trie缓存同时缓存 1306 diskdb := ethdb.NewMemDatabase() 1307 new(Genesis).MustCommit(diskdb) 1308 1309 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1310 if err != nil { 1311 t.Fatalf("failed to create tester chain: %v", err) 1312 } 1313 for i := 0; i < len(blocks); i++ { 1314 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1315 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1316 } 1317 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1318 t.Fatalf("fork %d: failed to insert into chain: %v", i, err) 1319 } 1320 } 1321 //取消引用所有最近的尝试,并确保没有留下过去的trie 1322 for i := 0; i < triesInMemory; i++ { 1323 chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) 1324 chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) 1325 } 1326 if len(chain.stateCache.TrieDB().Nodes()) > 0 { 1327 t.Fatalf("stale tries still alive after garbase collection") 1328 } 1329 } 1330 1331 //即使状态与 1332 //分叉点不再可用。 1333 func TestLargeReorgTrieGC(t *testing.T) { 1334 //生成原始的公共链段和两个竞争分支 1335 engine := ethash.NewFaker() 1336 1337 db := ethdb.NewMemDatabase() 1338 genesis := new(Genesis).MustCommit(db) 1339 1340 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1341 original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1342 competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) 1343 1344 //导入共享链和原始规范链 1345 diskdb := ethdb.NewMemDatabase() 1346 new(Genesis).MustCommit(diskdb) 1347 1348 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1349 if err != nil { 1350 t.Fatalf("failed to create tester chain: %v", err) 1351 } 1352 if _, err := chain.InsertChain(shared); err != nil { 1353 t.Fatalf("failed to insert shared chain: %v", err) 1354 } 1355 if _, err := chain.InsertChain(original); err != nil { 1356 t.Fatalf("failed to insert shared chain: %v", err) 1357 } 1358 //确保修剪掉与分叉点关联的状态 1359 if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil { 1360 t.Fatalf("common-but-old ancestor still cache") 1361 } 1362 //在不超过canonical的td的情况下导入竞争对手链并确保 1363 //我们没有处理任何块(防止恶意块) 1364 if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { 1365 t.Fatalf("failed to insert competitor chain: %v", err) 1366 } 1367 for i, block := range competitor[:len(competitor)-2] { 1368 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1369 t.Fatalf("competitor %d: low TD chain became processed", i) 1370 } 1371 } 1372 //导入竞争对手链的负责人,触发REORG并确保 1373 //成功地重新处理所有隐藏的块。 1374 if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { 1375 t.Fatalf("failed to finalize competitor chain: %v", err) 1376 } 1377 for i, block := range competitor[:len(competitor)-triesInMemory] { 1378 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1379 t.Fatalf("competitor %d: competing chain state missing", i) 1380 } 1381 } 1382 } 1383 1384 //将价值转移到非现有账户的大型区块作为基准 1385 func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) { 1386 var ( 1387 signer = types.HomesteadSigner{} 1388 testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1389 testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) 1390 bankFunds = big.NewInt(100000000000000000) 1391 gspec = Genesis{ 1392 Config: params.TestChainConfig, 1393 Alloc: GenesisAlloc{ 1394 testBankAddress: {Balance: bankFunds}, 1395 common.HexToAddress("0xc0de"): { 1396 Code: []byte{0x60, 0x01, 0x50}, 1397 Balance: big.NewInt(0), 1398 }, //推1,流行 1399 }, 1400 GasLimit: 100e6, //100米 1401 } 1402 ) 1403 //生成原始的公共链段和两个竞争分支 1404 engine := ethash.NewFaker() 1405 db := ethdb.NewMemDatabase() 1406 genesis := gspec.MustCommit(db) 1407 1408 blockGenerator := func(i int, block *BlockGen) { 1409 block.SetCoinbase(common.Address{1}) 1410 for txi := 0; txi < numTxs; txi++ { 1411 uniq := uint64(i*numTxs + txi) 1412 recipient := recipientFn(uniq) 1413 //收件人:=common.bigtoAddress(big.newint(0).setuint64(1337+uniq)) 1414 tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey) 1415 if err != nil { 1416 b.Error(err) 1417 } 1418 block.AddTx(tx) 1419 } 1420 } 1421 1422 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator) 1423 b.StopTimer() 1424 b.ResetTimer() 1425 for i := 0; i < b.N; i++ { 1426 //导入共享链和原始规范链 1427 diskdb := ethdb.NewMemDatabase() 1428 gspec.MustCommit(diskdb) 1429 1430 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1431 if err != nil { 1432 b.Fatalf("failed to create tester chain: %v", err) 1433 } 1434 b.StartTimer() 1435 if _, err := chain.InsertChain(shared); err != nil { 1436 b.Fatalf("failed to insert shared chain: %v", err) 1437 } 1438 b.StopTimer() 1439 if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { 1440 b.Fatalf("Transactions were not included, expected %d, got %d", (numTxs * numBlocks), got) 1441 1442 } 1443 } 1444 } 1445 func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) { 1446 var ( 1447 numTxs = 1000 1448 numBlocks = 1 1449 ) 1450 1451 recipientFn := func(nonce uint64) common.Address { 1452 return common.BigToAddress(big.NewInt(0).SetUint64(1337 + nonce)) 1453 } 1454 dataFn := func(nonce uint64) []byte { 1455 return nil 1456 } 1457 1458 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1459 } 1460 func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) { 1461 var ( 1462 numTxs = 1000 1463 numBlocks = 1 1464 ) 1465 b.StopTimer() 1466 b.ResetTimer() 1467 1468 recipientFn := func(nonce uint64) common.Address { 1469 return common.BigToAddress(big.NewInt(0).SetUint64(1337)) 1470 } 1471 dataFn := func(nonce uint64) []byte { 1472 return nil 1473 } 1474 1475 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1476 } 1477 func BenchmarkBlockChain_1x1000Executions(b *testing.B) { 1478 var ( 1479 numTxs = 1000 1480 numBlocks = 1 1481 ) 1482 b.StopTimer() 1483 b.ResetTimer() 1484 1485 recipientFn := func(nonce uint64) common.Address { 1486 return common.BigToAddress(big.NewInt(0).SetUint64(0xc0de)) 1487 } 1488 dataFn := func(nonce uint64) []byte { 1489 return nil 1490 } 1491 1492 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1493 }