github.com/halybang/go-ethereum@v1.0.5-0.20180325041310-3b262bc1367c/core/blockchain_test.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "fmt" 21 "math/big" 22 "math/rand" 23 "sync" 24 "testing" 25 "time" 26 27 "github.com/wanchain/go-wanchain/common" 28 "github.com/wanchain/go-wanchain/consensus/ethash" 29 "github.com/wanchain/go-wanchain/core/state" 30 "github.com/wanchain/go-wanchain/core/types" 31 "github.com/wanchain/go-wanchain/core/vm" 32 "github.com/wanchain/go-wanchain/crypto" 33 "github.com/wanchain/go-wanchain/ethdb" 34 "github.com/wanchain/go-wanchain/params" 35 ) 36 37 // newTestBlockChain creates a blockchain without validation. 38 func newTestBlockChain(fake bool) (*BlockChain, *ChainEnv) { 39 db, _ := ethdb.NewMemDatabase() 40 gspec := DefaultPPOWTestingGenesisBlock() 41 gspec.Difficulty = big.NewInt(1) 42 gspec.MustCommit(db) 43 engine := ethash.NewFullFaker(db) 44 if !fake { 45 engine = ethash.NewTester(db) 46 } 47 blockchain, err := NewBlockChain(db, gspec.Config, engine, vm.Config{}) 48 if err != nil { 49 panic(err) 50 } 51 chainEnv := NewChainEnv(params.TestChainConfig, gspec, engine, blockchain, db) 52 blockchain.SetValidator(bproc{}) 53 return blockchain, chainEnv 54 } 55 56 // Test fork of length N starting from block i 57 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { 58 // Copy old chain up to #i into a new db 59 _, blockchain2, err, chainEnv := newCanonical(i, full) 60 if err != nil { 61 t.Fatal("could not make new canonical in testFork", err) 62 } 63 defer blockchain2.Stop() 64 65 // Assert the chains have the same header/block at #i 66 var hash1, hash2 common.Hash 67 if full { 68 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 69 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 70 } else { 71 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 72 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 73 } 74 if hash1 != hash2 { 75 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 76 } 77 // Extend the newly created chain 78 var ( 79 blockChainB []*types.Block 80 headerChainB []*types.Header 81 ) 82 if full { 83 blockChainB = chainEnv.makeBlockChain(blockchain2.CurrentBlock(), n, forkSeed) 84 if _, err := blockchain2.InsertChain(blockChainB); err != nil { 85 t.Fatalf("failed to insert forking chain: %v", err) 86 } 87 } else { 88 headerChainB = chainEnv.makeHeaderChain(blockchain2.CurrentHeader(), n, forkSeed) 89 if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { 90 t.Fatalf("failed to insert forking chain: %v", err) 91 } 92 } 93 // Sanity check that the forked chain can be imported into the original 94 var tdPre, tdPost *big.Int 95 96 if full { 97 tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) 98 if err := testBlockChainImport(blockChainB, blockchain); err != nil { 99 t.Fatalf("failed to import forked block chain: %v", err) 100 } 101 tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) 102 } else { 103 tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) 104 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 105 t.Fatalf("failed to import forked header chain: %v", err) 106 } 107 tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) 108 } 109 // Compare the total difficulties of the chains 110 comparator(tdPre, tdPost) 111 } 112 113 func printChain(bc *BlockChain) { 114 for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- { 115 b := bc.GetBlockByNumber(uint64(i)) 116 fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty()) 117 } 118 } 119 120 // testBlockChainImport tries to process a chain of blocks, writing them into 121 // the database if successful. 122 func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { 123 for _, block := range chain { 124 // Try and process the block 125 err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) 126 if err == nil { 127 err = blockchain.validator.ValidateBody(block) 128 } 129 if err != nil { 130 if err == ErrKnownBlock { 131 continue 132 } 133 return err 134 } 135 statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache) 136 if err != nil { 137 return err 138 } 139 receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{}) 140 if err != nil { 141 blockchain.reportBlock(block, receipts, err) 142 return err 143 } 144 err = blockchain.validator.ValidateState(block, blockchain.GetBlockByHash(block.ParentHash()), statedb, receipts, usedGas) 145 if err != nil { 146 blockchain.reportBlock(block, receipts, err) 147 return err 148 } 149 blockchain.mu.Lock() 150 WriteTd(blockchain.chainDb, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash()))) 151 WriteBlock(blockchain.chainDb, block) 152 statedb.CommitTo(blockchain.chainDb, false) 153 blockchain.mu.Unlock() 154 } 155 return nil 156 } 157 158 // testHeaderChainImport tries to process a chain of header, writing them into 159 // the database if successful. 160 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 161 for _, header := range chain { 162 // Try and validate the header 163 if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { 164 return err 165 } 166 // Manually insert the header into the database, but don't reorganise (allows subsequent testing) 167 blockchain.mu.Lock() 168 WriteTd(blockchain.chainDb, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash))) 169 WriteHeader(blockchain.chainDb, header) 170 blockchain.mu.Unlock() 171 } 172 return nil 173 } 174 175 func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) { 176 _, err := blockchain.InsertChain(chain) 177 if err != nil { 178 fmt.Println(err) 179 t.FailNow() 180 } 181 done <- true 182 } 183 184 func TestLastBlock(t *testing.T) { 185 bchain, chainEnv := newTestBlockChain(false) 186 defer bchain.Stop() 187 188 block := chainEnv.makeBlockChain(bchain.CurrentBlock(), 1, 0)[0] 189 bchain.insert(block) 190 if block.Hash() != GetHeadBlockHash(bchain.chainDb) { 191 t.Errorf("Write/Get HeadBlockHash failed") 192 } 193 } 194 195 // Tests that given a starting canonical chain of a given size, it can be extended 196 // with various length chains. 197 func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } 198 func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } 199 200 func testExtendCanonical(t *testing.T, full bool) { 201 length := 5 202 203 // Make first chain starting from genesis 204 _, processor, err, _ := newCanonical(length, full) 205 if err != nil { 206 t.Fatalf("failed to make new canonical chain: %v", err) 207 } 208 defer processor.Stop() 209 210 // Define the difficulty comparator 211 better := func(td1, td2 *big.Int) { 212 if td2.Cmp(td1) <= 0 { 213 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 214 } 215 } 216 // Start fork from current height 217 testFork(t, processor, length, 1, full, better) 218 testFork(t, processor, length, 2, full, better) 219 testFork(t, processor, length, 5, full, better) 220 testFork(t, processor, length, 10, full, better) 221 } 222 223 // Tests that given a starting canonical chain of a given size, creating shorter 224 // forks do not take canonical ownership. 225 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } 226 func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } 227 228 func testShorterFork(t *testing.T, full bool) { 229 length := 10 230 231 // Make first chain starting from genesis 232 _, processor, err, _ := newCanonical(length, full) 233 if err != nil { 234 t.Fatalf("failed to make new canonical chain: %v", err) 235 } 236 defer processor.Stop() 237 238 // Define the difficulty comparator 239 worse := func(td1, td2 *big.Int) { 240 if td2.Cmp(td1) >= 0 { 241 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 242 } 243 } 244 // Sum of numbers must be less than `length` for this to be a shorter fork 245 testFork(t, processor, 0, 3, full, worse) 246 testFork(t, processor, 0, 7, full, worse) 247 testFork(t, processor, 1, 1, full, worse) 248 testFork(t, processor, 1, 7, full, worse) 249 testFork(t, processor, 5, 3, full, worse) 250 testFork(t, processor, 5, 4, full, worse) 251 } 252 253 // Tests that given a starting canonical chain of a given size, creating longer 254 // forks do take canonical ownership. 255 func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } 256 func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } 257 258 func testLongerFork(t *testing.T, full bool) { 259 length := 10 260 261 // Make first chain starting from genesis 262 _, processor, err, _ := newCanonical(length, full) 263 if err != nil { 264 t.Fatalf("failed to make new canonical chain: %v", err) 265 } 266 defer processor.Stop() 267 268 // Define the difficulty comparator 269 better := func(td1, td2 *big.Int) { 270 if td2.Cmp(td1) <= 0 { 271 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 272 } 273 } 274 // Sum of numbers must be greater than `length` for this to be a longer fork 275 testFork(t, processor, 0, 11, full, better) 276 testFork(t, processor, 0, 15, full, better) 277 testFork(t, processor, 1, 10, full, better) 278 testFork(t, processor, 1, 12, full, better) 279 testFork(t, processor, 5, 6, full, better) 280 testFork(t, processor, 5, 8, full, better) 281 } 282 283 // Tests that given a starting canonical chain of a given size, creating equal 284 // forks do take canonical ownership. 285 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } 286 func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } 287 288 func testEqualFork(t *testing.T, full bool) { 289 length := 10 290 291 // Make first chain starting from genesis 292 _, processor, err, _ := newCanonical(length, full) 293 if err != nil { 294 t.Fatalf("failed to make new canonical chain: %v", err) 295 } 296 defer processor.Stop() 297 298 // Define the difficulty comparator 299 equal := func(td1, td2 *big.Int) { 300 if td2.Cmp(td1) != 0 { 301 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 302 } 303 } 304 // Sum of numbers must be equal to `length` for this to be an equal fork 305 testFork(t, processor, 0, 10, full, equal) 306 testFork(t, processor, 1, 9, full, equal) 307 testFork(t, processor, 2, 8, full, equal) 308 testFork(t, processor, 5, 5, full, equal) 309 testFork(t, processor, 6, 4, full, equal) 310 testFork(t, processor, 9, 1, full, equal) 311 } 312 313 // Tests that chains missing links do not get accepted by the processor. 314 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } 315 func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } 316 317 func testBrokenChain(t *testing.T, full bool) { 318 // Make chain starting from genesis 319 _, blockchain, err, chainEnv := newCanonical(10, full) 320 if err != nil { 321 t.Fatalf("failed to make new canonical chain: %v", err) 322 } 323 defer blockchain.Stop() 324 325 // Create a forked chain, and try to insert with a missing link 326 if full { 327 chain := chainEnv.makeBlockChain(blockchain.CurrentBlock(), 5, forkSeed)[1:] 328 if err := testBlockChainImport(chain, blockchain); err == nil { 329 t.Errorf("broken block chain not reported") 330 } 331 } else { 332 chain := chainEnv.makeHeaderChain(blockchain.CurrentHeader(), 5, forkSeed)[1:] 333 if err := testHeaderChainImport(chain, blockchain); err == nil { 334 t.Errorf("broken header chain not reported") 335 } 336 } 337 } 338 339 type bproc struct{} 340 341 func (bproc) ValidateBody(*types.Block) error { return nil } 342 func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error { 343 return nil 344 } 345 func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) { 346 return nil, nil, new(big.Int), nil 347 } 348 349 func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Header { 350 blocks := makeBlockChainWithDiff(genesis, d, seed) 351 headers := make([]*types.Header, len(blocks)) 352 for i, block := range blocks { 353 headers[i] = block.Header() 354 } 355 return headers 356 } 357 358 func makeBlockChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block { 359 var chain []*types.Block 360 for i, difficulty := range d { 361 header := &types.Header{ 362 Coinbase: common.Address{seed}, 363 Number: big.NewInt(int64(i + 1)), 364 Difficulty: big.NewInt(int64(difficulty)), 365 UncleHash: types.EmptyUncleHash, 366 TxHash: types.EmptyRootHash, 367 ReceiptHash: types.EmptyRootHash, 368 Time: big.NewInt(int64(i) + 1), 369 } 370 if i == 0 { 371 header.ParentHash = genesis.Hash() 372 } else { 373 header.ParentHash = chain[i-1].Hash() 374 } 375 block := types.NewBlockWithHeader(header) 376 chain = append(chain, block) 377 } 378 return chain 379 } 380 381 // Tests that reorganising a long difficult chain after a short easy one 382 // overwrites the canonical numbers and links in the database. 383 func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) } 384 func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) } 385 386 func testReorgLong(t *testing.T, full bool) { 387 testReorg(t, []int{1, 2, 4}, []int{1, 2, 3, 4}, 10, full) 388 } 389 390 // Tests that reorganising a short difficult chain after a long easy one 391 // overwrites the canonical numbers and links in the database. 392 func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) } 393 func TestReorgShortBlocks(t *testing.T) { testReorgShort(t, true) } 394 395 func testReorgShort(t *testing.T, full bool) { 396 testReorg(t, []int{1, 2, 3, 4}, []int{1, 10}, 11, full) 397 } 398 399 func testReorg(t *testing.T, first, second []int, td int64, full bool) { 400 bc, _ := newTestBlockChain(true) 401 defer bc.Stop() 402 403 // Insert an easy and a difficult chain afterwards 404 if full { 405 bc.InsertChain(makeBlockChainWithDiff(bc.genesisBlock, first, 11)) 406 bc.InsertChain(makeBlockChainWithDiff(bc.genesisBlock, second, 22)) 407 } else { 408 bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, first, 11), 1) 409 bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, second, 22), 1) 410 } 411 // Check that the chain is valid number and link wise 412 if full { 413 prev := bc.CurrentBlock() 414 for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) { 415 if prev.ParentHash() != block.Hash() { 416 t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) 417 } 418 } 419 } else { 420 prev := bc.CurrentHeader() 421 for header := bc.GetHeaderByNumber(bc.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, bc.GetHeaderByNumber(header.Number.Uint64()-1) { 422 if prev.ParentHash != header.Hash() { 423 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 424 } 425 } 426 } 427 // Make sure the chain total difficulty is the correct one 428 want := new(big.Int).Add(bc.genesisBlock.Difficulty(), big.NewInt(td)) 429 if full { 430 if have := bc.GetTdByHash(bc.CurrentBlock().Hash()); have.Cmp(want) != 0 { 431 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 432 } 433 } else { 434 if have := bc.GetTdByHash(bc.CurrentHeader().Hash()); have.Cmp(want) != 0 { 435 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 436 } 437 } 438 } 439 440 // Tests that the insertion functions detect banned hashes. 441 func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) } 442 func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) } 443 444 func testBadHashes(t *testing.T, full bool) { 445 bc, _ := newTestBlockChain(true) 446 defer bc.Stop() 447 448 // Create a chain, ban a hash and try to import 449 var err error 450 if full { 451 blocks := makeBlockChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10) 452 BadHashes[blocks[2].Header().Hash()] = true 453 _, err = bc.InsertChain(blocks) 454 } else { 455 headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10) 456 BadHashes[headers[2].Hash()] = true 457 _, err = bc.InsertHeaderChain(headers, 1) 458 } 459 if err != ErrBlacklistedHash { 460 t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash) 461 } 462 } 463 464 // Tests that bad hashes are detected on boot, and the chain rolled back to a 465 // good state prior to the bad hash. 466 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } 467 func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } 468 469 func testReorgBadHashes(t *testing.T, full bool) { 470 bc, chainEnv := newTestBlockChain(true) 471 defer bc.Stop() 472 473 // Create a chain, import and ban afterwards 474 headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10) 475 blocks := makeBlockChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10) 476 477 if full { 478 if _, err := bc.InsertChain(blocks); err != nil { 479 t.Fatalf("failed to import blocks: %v", err) 480 } 481 if bc.CurrentBlock().Hash() != blocks[3].Hash() { 482 t.Errorf("last block hash mismatch: have: %x, want %x", bc.CurrentBlock().Hash(), blocks[3].Header().Hash()) 483 } 484 BadHashes[blocks[3].Header().Hash()] = true 485 defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() 486 } else { 487 if _, err := bc.InsertHeaderChain(headers, 1); err != nil { 488 t.Fatalf("failed to import headers: %v", err) 489 } 490 if bc.CurrentHeader().Hash() != headers[3].Hash() { 491 t.Errorf("last header hash mismatch: have: %x, want %x", bc.CurrentHeader().Hash(), headers[3].Hash()) 492 } 493 BadHashes[headers[3].Hash()] = true 494 defer func() { delete(BadHashes, headers[3].Hash()) }() 495 } 496 497 // Create a new BlockChain and check that it rolled back the state. 498 ncm, err := NewBlockChain(bc.chainDb, bc.config, ethash.NewFaker(chainEnv.db), vm.Config{}) 499 if err != nil { 500 t.Fatalf("failed to create new chain manager: %v", err) 501 } 502 defer ncm.Stop() 503 504 if full { 505 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 506 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 507 } 508 if blocks[2].Header().GasLimit.Cmp(ncm.GasLimit()) != 0 { 509 t.Errorf("last block gasLimit mismatch: have: %x, want %x", ncm.GasLimit(), blocks[2].Header().GasLimit) 510 } 511 } else { 512 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 513 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 514 } 515 } 516 } 517 518 // Tests chain insertions in the face of one entity containing an invalid nonce. 519 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } 520 func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } 521 522 func testInsertNonceError(t *testing.T, full bool) { 523 for i := 1; i < 25 && !t.Failed(); i++ { 524 // Create a pristine chain and database 525 _, blockchain, err, chainEnv := newCanonical(0, full) 526 if err != nil { 527 t.Fatalf("failed to create pristine chain: %v", err) 528 } 529 defer blockchain.Stop() 530 531 // Create and insert a chain with a failing nonce 532 var ( 533 failAt int 534 failRes int 535 failNum uint64 536 ) 537 if full { 538 blocks := chainEnv.makeBlockChain(blockchain.CurrentBlock(), i, 0) 539 540 failAt = rand.Int() % len(blocks) 541 failNum = blocks[failAt].NumberU64() 542 543 blockchain.engine = ethash.NewFakeFailer(failNum, chainEnv.db) 544 failRes, err = blockchain.InsertChain(blocks) 545 } else { 546 headers := chainEnv.makeHeaderChain(blockchain.CurrentHeader(), i, 0) 547 548 failAt = rand.Int() % len(headers) 549 failNum = headers[failAt].Number.Uint64() 550 551 blockchain.engine = ethash.NewFakeFailer(failNum, chainEnv.db) 552 blockchain.hc.engine = blockchain.engine 553 failRes, err = blockchain.InsertHeaderChain(headers, 1) 554 } 555 // Check that the returned error indicates the failure. 556 if failRes != failAt { 557 t.Errorf("test %d: failure index mismatch: have %d, want %d", i, failRes, failAt) 558 } 559 // Check that all no blocks after the failing block have been inserted. 560 for j := 0; j < i-failAt; j++ { 561 if full { 562 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 563 t.Errorf("test %d: invalid block in chain: %v", i, block) 564 } 565 } else { 566 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 567 t.Errorf("test %d: invalid header in chain: %v", i, header) 568 } 569 } 570 } 571 } 572 } 573 574 // Tests that fast importing a block chain produces the same chain data as the 575 // classical full block processing. 576 func TestFastVsFullChains(t *testing.T) { 577 // Configure and generate a sample block chain 578 var ( 579 gendb, _ = ethdb.NewMemDatabase() 580 key, _ = crypto.HexToECDSA("f1572f76b75b40a7da72d6f2ee7fda3d1189c2d28f0a2f096347055abe344d7f") 581 address = crypto.PubkeyToAddress(key.PublicKey) 582 funds = big.NewInt(1000000000) 583 //gspec = &Genesis{ 584 // Config: params.TestChainConfig, 585 // Alloc: GenesisAlloc{address: {Balance: funds}}, 586 //} 587 // 588 //signer = types.NewEIP155Signer(gspec.Config.ChainId) 589 ) 590 591 gspec := DefaultPPOWTestingGenesisBlock() 592 gspec.Alloc = GenesisAlloc{address: {Balance: funds}} 593 genesis := gspec.MustCommit(gendb) 594 signer := types.NewEIP155Signer(gspec.Config.ChainId) 595 engine := ethash.NewFaker(gendb) 596 stdChain, _ := NewBlockChain(gendb, gspec.Config, engine, vm.Config{}) 597 defer stdChain.Stop() 598 stdChainEnv := NewChainEnv(params.TestChainConfig, gspec, engine, stdChain, gendb) 599 600 blocks, receipts := stdChainEnv.GenerateChain(genesis, 1024, func(i int, block *BlockGen) { 601 block.SetCoinbase(common.Address{0x00}) 602 603 // If the block number is multiple of 3, send a few bonus transactions to the miner 604 if i%3 == 2 { 605 for j := 0; j < i%4+1; j++ { 606 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), bigTxGas, nil, nil), signer, key) 607 if err != nil { 608 panic(err) 609 } 610 block.AddTx(tx) 611 } 612 } 613 // If the block number is a multiple of 5, add a few bonus uncles to the block 614 if i%5 == 5 { 615 //block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))}) 616 } 617 }) 618 // Import the chain as an archive node for the comparison baseline 619 archiveDb, _ := ethdb.NewMemDatabase() 620 gspec.MustCommit(archiveDb) 621 archive, _ := NewBlockChain(archiveDb, gspec.Config, ethash.NewFaker(archiveDb), vm.Config{}) 622 defer archive.Stop() 623 624 if n, err := archive.InsertChain(blocks); err != nil { 625 t.Fatalf("failed to process block %d: %v", n, err) 626 } 627 // Fast import the chain as a non-archive node to test 628 fastDb, _ := ethdb.NewMemDatabase() 629 gspec.MustCommit(fastDb) 630 fast, _ := NewBlockChain(fastDb, gspec.Config, ethash.NewFaker(fastDb), vm.Config{}) 631 defer fast.Stop() 632 633 headers := make([]*types.Header, len(blocks)) 634 for i, block := range blocks { 635 headers[i] = block.Header() 636 } 637 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 638 t.Fatalf("failed to insert header %d: %v", n, err) 639 } 640 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 641 t.Fatalf("failed to insert receipt %d: %v", n, err) 642 } 643 // Iterate over all chain data components, and cross reference 644 for i := 0; i < len(blocks); i++ { 645 num, hash := blocks[i].NumberU64(), blocks[i].Hash() 646 647 if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 { 648 t.Errorf("block #%d [%x]: td mismatch: have %v, want %v", num, hash, ftd, atd) 649 } 650 if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { 651 t.Errorf("block #%d [%x]: header mismatch: have %v, want %v", num, hash, fheader, aheader) 652 } 653 if fblock, ablock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash); fblock.Hash() != ablock.Hash() { 654 t.Errorf("block #%d [%x]: block mismatch: have %v, want %v", num, hash, fblock, ablock) 655 } else if types.DeriveSha(fblock.Transactions()) != types.DeriveSha(ablock.Transactions()) { 656 t.Errorf("block #%d [%x]: transactions mismatch: have %v, want %v", num, hash, fblock.Transactions(), ablock.Transactions()) 657 } else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(ablock.Uncles()) { 658 t.Errorf("block #%d [%x]: uncles mismatch: have %v, want %v", num, hash, fblock.Uncles(), ablock.Uncles()) 659 } 660 if freceipts, areceipts := GetBlockReceipts(fastDb, hash, GetBlockNumber(fastDb, hash)), GetBlockReceipts(archiveDb, hash, GetBlockNumber(archiveDb, hash)); types.DeriveSha(freceipts) != types.DeriveSha(areceipts) { 661 t.Errorf("block #%d [%x]: receipts mismatch: have %v, want %v", num, hash, freceipts, areceipts) 662 } 663 } 664 // Check that the canonical chains are the same between the databases 665 for i := 0; i < len(blocks)+1; i++ { 666 if fhash, ahash := GetCanonicalHash(fastDb, uint64(i)), GetCanonicalHash(archiveDb, uint64(i)); fhash != ahash { 667 t.Errorf("block #%d: canonical hash mismatch: have %v, want %v", i, fhash, ahash) 668 } 669 } 670 } 671 672 // Tests that various import methods move the chain head pointers to the correct 673 // positions. 674 func TestLightVsFastVsFullChainHeads(t *testing.T) { 675 // Configure and generate a sample block chain 676 var ( 677 gendb, _ = ethdb.NewMemDatabase() 678 key, _ = crypto.HexToECDSA("f1572f76b75b40a7da72d6f2ee7fda3d1189c2d28f0a2f096347055abe344d7f") 679 address = crypto.PubkeyToAddress(key.PublicKey) 680 funds = big.NewInt(1000000000) 681 //gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 682 //genesis = gspec.MustCommit(gendb) 683 ) 684 685 gspec := DefaultPPOWTestingGenesisBlock() 686 gspec.Alloc = GenesisAlloc{address: {Balance: funds}} 687 genesis := gspec.MustCommit(gendb) 688 engine := ethash.NewFaker(gendb) 689 stdChain, _ := NewBlockChain(gendb, gspec.Config, engine, vm.Config{}) 690 defer stdChain.Stop() 691 stdChainEnv := NewChainEnv(params.TestChainConfig, gspec, engine, stdChain, gendb) 692 693 height := uint64(1024) 694 blocks, receipts := stdChainEnv.GenerateChain(genesis, int(height), nil) 695 696 // Configure a subchain to roll back 697 remove := []common.Hash{} 698 for _, block := range blocks[height/2:] { 699 remove = append(remove, block.Hash()) 700 } 701 // Create a small assertion method to check the three heads 702 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 703 if num := chain.CurrentBlock().NumberU64(); num != block { 704 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 705 } 706 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 707 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 708 } 709 if num := chain.CurrentHeader().Number.Uint64(); num != header { 710 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 711 } 712 } 713 // Import the chain as an archive node and ensure all pointers are updated 714 archiveDb, _ := ethdb.NewMemDatabase() 715 gspec.MustCommit(archiveDb) 716 717 archive, _ := NewBlockChain(archiveDb, gspec.Config, ethash.NewFaker(archiveDb), vm.Config{}) 718 if n, err := archive.InsertChain(blocks); err != nil { 719 t.Fatalf("failed to process block %d: %v", n, err) 720 } 721 defer archive.Stop() 722 723 assert(t, "archive", archive, height, height, height) 724 archive.Rollback(remove) 725 assert(t, "archive", archive, height/2, height/2, height/2) 726 727 // Import the chain as a non-archive node and ensure all pointers are updated 728 fastDb, _ := ethdb.NewMemDatabase() 729 gspec.MustCommit(fastDb) 730 fast, _ := NewBlockChain(fastDb, gspec.Config, ethash.NewFaker(fastDb), vm.Config{}) 731 defer fast.Stop() 732 733 headers := make([]*types.Header, len(blocks)) 734 for i, block := range blocks { 735 headers[i] = block.Header() 736 } 737 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 738 t.Fatalf("failed to insert header %d: %v", n, err) 739 } 740 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 741 t.Fatalf("failed to insert receipt %d: %v", n, err) 742 } 743 assert(t, "fast", fast, height, height, 0) 744 fast.Rollback(remove) 745 assert(t, "fast", fast, height/2, height/2, 0) 746 747 // Import the chain as a light node and ensure all pointers are updated 748 lightDb, _ := ethdb.NewMemDatabase() 749 gspec.MustCommit(lightDb) 750 751 light, _ := NewBlockChain(lightDb, gspec.Config, ethash.NewFaker(lightDb), vm.Config{}) 752 if n, err := light.InsertHeaderChain(headers, 1); err != nil { 753 t.Fatalf("failed to insert header %d: %v", n, err) 754 } 755 defer light.Stop() 756 757 assert(t, "light", light, height, 0, 0) 758 light.Rollback(remove) 759 assert(t, "light", light, height/2, 0, 0) 760 } 761 762 // Tests that chain reorganisations handle transaction removals and reinsertions. 763 func TestChainTxReorgs(t *testing.T) { 764 var ( 765 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 766 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 767 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 768 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 769 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 770 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 771 db, _ = ethdb.NewMemDatabase() 772 //gspec = &Genesis{ 773 // Config: params.TestChainConfig, 774 // GasLimit: 3141592, 775 // Alloc: GenesisAlloc{ 776 // addr1: {Balance: big.NewInt(1000000)}, 777 // addr2: {Balance: big.NewInt(1000000)}, 778 // addr3: {Balance: big.NewInt(1000000)}, 779 // }, 780 //} 781 //genesis = gspec.MustCommit(db) 782 783 ) 784 785 gspec := DefaultPPOWTestingGenesisBlock() 786 gspec.Alloc = GenesisAlloc{ 787 addr1: {Balance: big.NewInt(1000000)}, 788 addr2: {Balance: big.NewInt(1000000)}, 789 addr3: {Balance: big.NewInt(1000000)}, 790 } 791 signer := types.NewEIP155Signer(gspec.Config.ChainId) 792 genesis := gspec.MustCommit(db) 793 engine := ethash.NewFaker(db) 794 stdChain, _ := NewBlockChain(db, gspec.Config, engine, vm.Config{}) 795 defer stdChain.Stop() 796 stdChainEnv := NewChainEnv(params.TestChainConfig, gspec, engine, stdChain, db) 797 798 // Create two transactions shared between the chains: 799 // - postponed: transaction included at a later block in the forked chain 800 // - swapped: transaction included at the same block number in the forked chain 801 postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), bigTxGas, nil, nil), signer, key1) 802 swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), bigTxGas, nil, nil), signer, key1) 803 804 // Create two transactions that will be dropped by the forked chain: 805 // - pastDrop: transaction dropped retroactively from a past block 806 // - freshDrop: transaction dropped exactly at the block where the reorg is detected 807 var pastDrop, freshDrop *types.Transaction 808 809 // Create three transactions that will be added in the forked chain: 810 // - pastAdd: transaction added before the reorganization is detected 811 // - freshAdd: transaction added at the exact block the reorg is detected 812 // - futureAdd: transaction added after the reorg has already finished 813 var pastAdd, freshAdd, futureAdd *types.Transaction 814 815 chain, _ := stdChainEnv.GenerateChain(genesis, 3, func(i int, gen *BlockGen) { 816 switch i { 817 case 0: 818 pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key2) 819 820 gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point 821 gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork 822 823 case 2: 824 freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key2) 825 826 gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point 827 gen.AddTx(swapped) // This transaction will be swapped out at the exact height 828 829 gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain 830 } 831 }) 832 // Import the chain. This runs all block validation rules. 833 //blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(db), vm.Config{}) 834 if i, err := stdChain.InsertChain(chain); err != nil { 835 t.Fatalf("failed to insert original chain[%d]: %v", i, err) 836 } 837 838 // overwrite the old chain 839 chain, _ = stdChainEnv.GenerateChain(genesis, 5, func(i int, gen *BlockGen) { 840 switch i { 841 case 0: 842 pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3) 843 gen.AddTx(pastAdd) // This transaction needs to be injected during reorg 844 845 case 2: 846 gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain 847 gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain 848 849 freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3) 850 gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time 851 852 case 3: 853 futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3) 854 gen.AddTx(futureAdd) // This transaction will be added after a full reorg 855 } 856 }) 857 if _, err := stdChain.InsertChain(chain); err != nil { 858 t.Fatalf("failed to insert forked chain: %v", err) 859 } 860 861 // removed tx 862 for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 863 if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn != nil { 864 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 865 } 866 if rcpt, _, _, _ := GetReceipt(db, tx.Hash()); rcpt != nil { 867 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 868 } 869 } 870 // added tx 871 for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 872 if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn == nil { 873 t.Errorf("add %d: expected tx to be found", i) 874 } 875 if rcpt, _, _, _ := GetReceipt(db, tx.Hash()); rcpt == nil { 876 t.Errorf("add %d: expected receipt to be found", i) 877 } 878 } 879 // shared tx 880 for i, tx := range (types.Transactions{postponed, swapped}) { 881 if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn == nil { 882 t.Errorf("share %d: expected tx to be found", i) 883 } 884 if rcpt, _, _, _ := GetReceipt(db, tx.Hash()); rcpt == nil { 885 t.Errorf("share %d: expected receipt to be found", i) 886 } 887 } 888 } 889 890 func TestLogReorgs(t *testing.T) { 891 var ( 892 key1, _ = crypto.HexToECDSA("f1572f76b75b40a7da72d6f2ee7fda3d1189c2d28f0a2f096347055abe344d7f") 893 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 894 db, _ = ethdb.NewMemDatabase() 895 // this code generates a log 896 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 897 //gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 898 //genesis = gspec.MustCommit(db) 899 //signer = types.NewEIP155Signer(gspec.Config.ChainId) 900 ) 901 902 gspec := DefaultPPOWTestingGenesisBlock() 903 gspec.Alloc = GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}} 904 signer := types.NewEIP155Signer(gspec.Config.ChainId) 905 genesis := gspec.MustCommit(db) 906 engine := ethash.NewFaker(db) 907 blockchain, _ := NewBlockChain(db, gspec.Config, engine, vm.Config{}) 908 defer blockchain.Stop() 909 chainEnv := NewChainEnv(params.TestChainConfig, gspec, engine, blockchain, db) 910 911 rmLogsCh := make(chan RemovedLogsEvent) 912 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 913 chain, _ := chainEnv.GenerateChain(genesis, 2, func(i int, gen *BlockGen) { 914 if i == 1 { 915 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), code), signer, key1) 916 if err != nil { 917 t.Fatalf("failed to create tx: %v", err) 918 } 919 gen.AddTx(tx) 920 } 921 }) 922 if _, err := blockchain.InsertChain(chain); err != nil { 923 t.Fatalf("failed to insert chain: %v", err) 924 } 925 926 chain, _ = chainEnv.GenerateChain(genesis, 3, func(i int, gen *BlockGen) {}) 927 if _, err := blockchain.InsertChain(chain); err != nil { 928 t.Fatalf("failed to insert forked chain: %v", err) 929 } 930 931 timeout := time.NewTimer(1 * time.Second) 932 select { 933 case ev := <-rmLogsCh: 934 if len(ev.Logs) == 0 { 935 t.Error("expected logs") 936 } 937 case <-timeout.C: 938 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 939 } 940 } 941 942 func TestReorgSideEvent(t *testing.T) { 943 var ( 944 db, _ = ethdb.NewMemDatabase() 945 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 946 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 947 //gspec = &Genesis{ 948 // Config: params.TestChainConfig, 949 // Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}, 950 //} 951 //genesis = gspec.MustCommit(db) 952 //signer = types.NewEIP155Signer(gspec.Config.ChainId) 953 ) 954 955 gspec := DefaultPPOWTestingGenesisBlock() 956 gspec.Alloc = GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}} 957 signer := types.NewEIP155Signer(gspec.Config.ChainId) 958 genesis := gspec.MustCommit(db) 959 engine := ethash.NewFaker(db) 960 blockchain, _ := NewBlockChain(db, gspec.Config, engine, vm.Config{}) 961 defer blockchain.Stop() 962 chainEnv := NewChainEnv(params.TestChainConfig, gspec, engine, blockchain, db) 963 964 chain, _ := chainEnv.GenerateChain(genesis, 3, func(i int, gen *BlockGen) {}) 965 if _, err := blockchain.InsertChain(chain); err != nil { 966 t.Fatalf("failed to insert chain: %v", err) 967 } 968 969 replacementBlocks, _ := chainEnv.GenerateChain(genesis, 4, func(i int, gen *BlockGen) { 970 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil), signer, key1) 971 if i == 2 { 972 gen.OffsetTime(-9) 973 } 974 if err != nil { 975 t.Fatalf("failed to create tx: %v", err) 976 } 977 gen.AddTx(tx) 978 }) 979 chainSideCh := make(chan ChainSideEvent, 64) 980 blockchain.SubscribeChainSideEvent(chainSideCh) 981 if _, err := blockchain.InsertChain(replacementBlocks); err != nil { 982 t.Fatalf("failed to insert chain: %v", err) 983 } 984 985 // first two block of the secondary chain are for a brief moment considered 986 // side chains because up to that point the first one is considered the 987 // heavier chain. 988 expectedSideHashes := map[common.Hash]bool{ 989 replacementBlocks[0].Hash(): true, 990 replacementBlocks[1].Hash(): true, 991 chain[0].Hash(): true, 992 chain[1].Hash(): true, 993 chain[2].Hash(): true, 994 } 995 996 i := 0 997 998 const timeoutDura = 10 * time.Second 999 timeout := time.NewTimer(timeoutDura) 1000 done: 1001 for { 1002 select { 1003 case ev := <-chainSideCh: 1004 block := ev.Block 1005 if _, ok := expectedSideHashes[block.Hash()]; !ok { 1006 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 1007 } 1008 i++ 1009 1010 if i == len(expectedSideHashes) { 1011 timeout.Stop() 1012 1013 break done 1014 } 1015 timeout.Reset(timeoutDura) 1016 1017 case <-timeout.C: 1018 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 1019 } 1020 } 1021 1022 // make sure no more events are fired 1023 select { 1024 case e := <-chainSideCh: 1025 t.Errorf("unexpected event fired: %v", e) 1026 case <-time.After(250 * time.Millisecond): 1027 } 1028 1029 } 1030 1031 // Tests if the canonical block can be fetched from the database during chain insertion. 1032 func TestCanonicalBlockRetrieval(t *testing.T) { 1033 bc, chainEnv := newTestBlockChain(true) 1034 defer bc.Stop() 1035 1036 chain, _ := chainEnv.GenerateChain(bc.genesisBlock, 10, func(i int, gen *BlockGen) {}) 1037 1038 var pend sync.WaitGroup 1039 pend.Add(len(chain)) 1040 1041 for i := range chain { 1042 go func(block *types.Block) { 1043 defer pend.Done() 1044 1045 // try to retrieve a block by its canonical hash and see if the block data can be retrieved. 1046 for { 1047 ch := GetCanonicalHash(bc.chainDb, block.NumberU64()) 1048 if ch == (common.Hash{}) { 1049 continue // busy wait for canonical hash to be written 1050 } 1051 if ch != block.Hash() { 1052 t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1053 } 1054 fb := GetBlock(bc.chainDb, ch, block.NumberU64()) 1055 if fb == nil { 1056 t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1057 } 1058 if fb.Hash() != block.Hash() { 1059 t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1060 } 1061 return 1062 } 1063 }(chain[i]) 1064 1065 if _, err := bc.InsertChain(types.Blocks{chain[i]}); err != nil { 1066 t.Fatalf("failed to insert block %d: %v", i, err) 1067 } 1068 } 1069 pend.Wait() 1070 } 1071 1072 //func TestEIP155Transition(t *testing.T) { 1073 // // Configure and generate a sample block chain 1074 // var ( 1075 // db, _ = ethdb.NewMemDatabase() 1076 // key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1077 // address = crypto.PubkeyToAddress(key.PublicKey) 1078 // funds = big.NewInt(1000000000) 1079 // deleteAddr = common.Address{1} 1080 // gspec = &Genesis{ 1081 // Config: ¶ms.ChainConfig{ChainId: big.NewInt(2), ByzantiumBlock: new(big.Int)}, 1082 // Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 1083 // } 1084 // genesis = gspec.MustCommit(db) 1085 // ) 1086 // 1087 // blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{}) 1088 // defer blockchain.Stop() 1089 // 1090 // blocks, _ := GenerateChain(nil, gspec.Config, genesis, db, nil, 4, func(i int, block *BlockGen) { 1091 // var ( 1092 // tx *types.Transaction 1093 // err error 1094 // basicTx = func(signer types.Signer) (*types.Transaction, error) { 1095 // return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key) 1096 // } 1097 // ) 1098 // switch i { 1099 // case 0: 1100 // tx, err = basicTx(types.HomesteadSigner{}) 1101 // if err != nil { 1102 // t.Fatal(err) 1103 // } 1104 // block.AddTx(tx) 1105 // case 2: 1106 // tx, err = basicTx(types.HomesteadSigner{}) 1107 // if err != nil { 1108 // t.Fatal(err) 1109 // } 1110 // block.AddTx(tx) 1111 // 1112 // tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId)) 1113 // if err != nil { 1114 // t.Fatal(err) 1115 // } 1116 // block.AddTx(tx) 1117 // case 3: 1118 // tx, err = basicTx(types.HomesteadSigner{}) 1119 // if err != nil { 1120 // t.Fatal(err) 1121 // } 1122 // block.AddTx(tx) 1123 // 1124 // tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId)) 1125 // if err != nil { 1126 // t.Fatal(err) 1127 // } 1128 // block.AddTx(tx) 1129 // } 1130 // }) 1131 // 1132 // if _, err := blockchain.InsertChain(blocks); err != nil { 1133 // t.Fatal(err) 1134 // } 1135 // block := blockchain.GetBlockByNumber(1) 1136 // if block.Transactions()[0].Protected() { 1137 // t.Error("Expected block[0].txs[0] to not be replay protected") 1138 // } 1139 // 1140 // block = blockchain.GetBlockByNumber(3) 1141 // if block.Transactions()[0].Protected() { 1142 // t.Error("Expected block[3].txs[0] to not be replay protected") 1143 // } 1144 // if !block.Transactions()[1].Protected() { 1145 // t.Error("Expected block[3].txs[1] to be replay protected") 1146 // } 1147 // if _, err := blockchain.InsertChain(blocks[4:]); err != nil { 1148 // t.Fatal(err) 1149 // } 1150 // 1151 // // generate an invalid chain id transaction 1152 // config := ¶ms.ChainConfig{ChainId: big.NewInt(1), ByzantiumBlock: new(big.Int)} 1153 // blocks, _ = GenerateChain(nil, config, blocks[len(blocks)-1], db, nil, 4, func(i int, block *BlockGen) { 1154 // var ( 1155 // tx *types.Transaction 1156 // err error 1157 // basicTx = func(signer types.Signer) (*types.Transaction, error) { 1158 // return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key) 1159 // } 1160 // ) 1161 // switch i { 1162 // case 0: 1163 // tx, err = basicTx(types.NewEIP155Signer(big.NewInt(1))) 1164 // if err != nil { 1165 // t.Fatal(err) 1166 // } 1167 // block.AddTx(tx) 1168 // } 1169 // }) 1170 // _, err := blockchain.InsertChain(blocks) 1171 // if err != types.ErrInvalidChainId { 1172 // t.Error("expected error:", types.ErrInvalidChainId) 1173 // } 1174 //} 1175 // 1176 //func TestEIP161AccountRemoval(t *testing.T) { 1177 // // Configure and generate a sample block chain 1178 // var ( 1179 // db, _ = ethdb.NewMemDatabase() 1180 // key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1181 // address = crypto.PubkeyToAddress(key.PublicKey) 1182 // funds = big.NewInt(1000000000) 1183 // theAddr = common.Address{1} 1184 // gspec = &Genesis{ 1185 // Config: ¶ms.ChainConfig{ 1186 // ChainId: big.NewInt(1), 1187 // //HomesteadBlock: new(big.Int), 1188 // //EIP155Block: new(big.Int), 1189 // //EIP158Block: big.NewInt(2), 1190 // }, 1191 // Alloc: GenesisAlloc{address: {Balance: funds}}, 1192 // } 1193 // genesis = gspec.MustCommit(db) 1194 // ) 1195 // blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{}) 1196 // defer blockchain.Stop() 1197 // 1198 // //blocks, _ := GenerateChain(gspec.Config, genesis, db, 3, func(i int, block *BlockGen) { 1199 // blocks, _ := GenerateChain(nil, gspec.Config, genesis, db, nil, 1, func(i int, block *BlockGen) { 1200 // var ( 1201 // tx *types.Transaction 1202 // err error 1203 // signer = types.NewEIP155Signer(gspec.Config.ChainId) 1204 // ) 1205 // switch i { 1206 // case 0: 1207 // tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key) 1208 // //case 1: 1209 // // tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key) 1210 // //case 2: 1211 // // tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key) 1212 // } 1213 // if err != nil { 1214 // t.Fatal(err) 1215 // } 1216 // block.AddTx(tx) 1217 // }) 1218 // 1219 // // account musn't be created post eip 161 1220 // if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1221 // t.Fatal(err) 1222 // } 1223 // if st, _ := blockchain.State(); st.Exist(theAddr) { 1224 // t.Error("account should not exist") 1225 // } 1226 // 1227 // /* 1228 // // account must exist pre eip 161 1229 // if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1230 // t.Fatal(err) 1231 // } 1232 // if st, _ := blockchain.State(); !st.Exist(theAddr) { 1233 // t.Error("expected account to exist") 1234 // } 1235 // 1236 // // account needs to be deleted post eip 161 1237 // if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1238 // t.Fatal(err) 1239 // } 1240 // if st, _ := blockchain.State(); st.Exist(theAddr) { 1241 // t.Error("account should not exist") 1242 // } 1243 // 1244 // // account musn't be created post eip 161 1245 // if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1246 // t.Fatal(err) 1247 // } 1248 // if st, _ := blockchain.State(); st.Exist(theAddr) { 1249 // t.Error("account should not exist") 1250 // } 1251 // */ 1252 //}