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