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