github.com/energicryptocurrency/go-energi@v1.1.7/core/blockchain_test.go (about) 1 // Copyright 2018 The Energi Core Authors 2 // Copyright 2014 The go-ethereum Authors 3 // This file is part of the Energi Core library. 4 // 5 // The Energi Core library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The Energi Core library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>. 17 18 package core 19 20 import ( 21 "math/big" 22 "math/rand" 23 "sync" 24 "testing" 25 "time" 26 27 "github.com/energicryptocurrency/go-energi/common" 28 "github.com/energicryptocurrency/go-energi/consensus" 29 "github.com/energicryptocurrency/go-energi/consensus/ethash" 30 "github.com/energicryptocurrency/go-energi/core/rawdb" 31 "github.com/energicryptocurrency/go-energi/core/state" 32 "github.com/energicryptocurrency/go-energi/core/types" 33 "github.com/energicryptocurrency/go-energi/core/vm" 34 "github.com/energicryptocurrency/go-energi/crypto" 35 "github.com/energicryptocurrency/go-energi/ethdb" 36 "github.com/energicryptocurrency/go-energi/params" 37 ) 38 39 // So we can deterministically seed different blockchains 40 var ( 41 canonicalSeed = 1 42 forkSeed = 2 43 ) 44 45 // newCanonical creates a chain database, and injects a deterministic canonical 46 // chain. Depending on the full flag, if creates either a full block chain or a 47 // header only chain. 48 func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) { 49 var ( 50 db = ethdb.NewMemDatabase() 51 genesis = new(Genesis).MustCommit(db) 52 ) 53 54 // Initialize a fresh chain with only a genesis block 55 blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil) 56 // Create and inject the requested chain 57 if n == 0 { 58 return db, blockchain, nil 59 } 60 if full { 61 // Full block-chain requested 62 blocks := makeBlockChain(genesis, n, engine, db, canonicalSeed) 63 _, err := blockchain.InsertChain(blocks) 64 return db, blockchain, err 65 } 66 // Header-only chain requested 67 headers := makeHeaderChain(genesis.Header(), n, engine, db, canonicalSeed) 68 _, err := blockchain.InsertHeaderChain(headers, 1) 69 return db, blockchain, err 70 } 71 72 // Test fork of length N starting from block i 73 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { 74 // Copy old chain up to #i into a new db 75 db, blockchain2, err := newCanonical(ethash.NewFaker(), i, full) 76 if err != nil { 77 t.Fatal("could not make new canonical in testFork", err) 78 } 79 defer blockchain2.Stop() 80 81 // Assert the chains have the same header/block at #i 82 var hash1, hash2 common.Hash 83 if full { 84 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 85 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 86 } else { 87 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 88 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 89 } 90 if hash1 != hash2 { 91 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 92 } 93 // Extend the newly created chain 94 var ( 95 blockChainB []*types.Block 96 headerChainB []*types.Header 97 ) 98 if full { 99 blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed) 100 if _, err := blockchain2.InsertChain(blockChainB); err != nil { 101 t.Fatalf("failed to insert forking chain: %v", err) 102 } 103 } else { 104 headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, ethash.NewFaker(), db, forkSeed) 105 if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { 106 t.Fatalf("failed to insert forking chain: %v", err) 107 } 108 } 109 // Sanity check that the forked chain can be imported into the original 110 var tdPre, tdPost *big.Int 111 112 if full { 113 tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) 114 if err := testBlockChainImport(blockChainB, blockchain); err != nil { 115 t.Fatalf("failed to import forked block chain: %v", err) 116 } 117 tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) 118 } else { 119 tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) 120 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 121 t.Fatalf("failed to import forked header chain: %v", err) 122 } 123 tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) 124 } 125 // Compare the total difficulties of the chains 126 comparator(tdPre, tdPost) 127 } 128 129 // testBlockChainImport tries to process a chain of blocks, writing them into 130 // the database if successful. 131 func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { 132 for _, block := range chain { 133 // Try and process the block 134 err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) 135 if err == nil { 136 err = blockchain.validator.ValidateBody(block) 137 } 138 if err != nil { 139 if err == ErrKnownBlock { 140 continue 141 } 142 return err 143 } 144 statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache) 145 if err != nil { 146 return err 147 } 148 receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{}) 149 if err != nil { 150 blockchain.reportBlock(block, receipts, err) 151 return err 152 } 153 err = blockchain.validator.ValidateState(block, blockchain.GetBlockByHash(block.ParentHash()), statedb, receipts, usedGas) 154 if err != nil { 155 blockchain.reportBlock(block, receipts, err) 156 return err 157 } 158 blockchain.mu.Lock() 159 rawdb.WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash()))) 160 rawdb.WriteBlock(blockchain.db, block) 161 _, _ = statedb.Commit(false) 162 blockchain.mu.Unlock() 163 } 164 return nil 165 } 166 167 // testHeaderChainImport tries to process a chain of header, writing them into 168 // the database if successful. 169 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 170 for _, header := range chain { 171 // Try and validate the header 172 if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { 173 return err 174 } 175 // Manually insert the header into the database, but don't reorganise (allows subsequent testing) 176 blockchain.mu.Lock() 177 rawdb.WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash))) 178 rawdb.WriteHeader(blockchain.db, header) 179 blockchain.mu.Unlock() 180 } 181 return nil 182 } 183 184 func TestLastBlock(t *testing.T) { 185 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) 186 if err != nil { 187 t.Fatalf("failed to create pristine chain: %v", err) 188 } 189 defer blockchain.Stop() 190 191 blocks := makeBlockChain(blockchain.CurrentBlock(), 1, ethash.NewFullFaker(), blockchain.db, 0) 192 if _, err := blockchain.InsertChain(blocks); err != nil { 193 t.Fatalf("Failed to insert block: %v", err) 194 } 195 if blocks[len(blocks)-1].Hash() != rawdb.ReadHeadBlockHash(blockchain.db) { 196 t.Fatalf("Write/Get HeadBlockHash failed") 197 } 198 } 199 200 // Tests that given a starting canonical chain of a given size, it can be extended 201 // with various length chains. 202 func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } 203 func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } 204 205 func testExtendCanonical(t *testing.T, full bool) { 206 length := 5 207 208 // Make first chain starting from genesis 209 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 210 if err != nil { 211 t.Fatalf("failed to make new canonical chain: %v", err) 212 } 213 defer processor.Stop() 214 215 // Define the difficulty comparator 216 better := func(td1, td2 *big.Int) { 217 if td2.Cmp(td1) <= 0 { 218 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 219 } 220 } 221 // Start fork from current height 222 testFork(t, processor, length, 1, full, better) 223 testFork(t, processor, length, 2, full, better) 224 testFork(t, processor, length, 5, full, better) 225 testFork(t, processor, length, 10, full, better) 226 } 227 228 // Tests that given a starting canonical chain of a given size, creating shorter 229 // forks do not take canonical ownership. 230 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } 231 func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } 232 233 func testShorterFork(t *testing.T, full bool) { 234 length := 10 235 236 // Make first chain starting from genesis 237 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 238 if err != nil { 239 t.Fatalf("failed to make new canonical chain: %v", err) 240 } 241 defer processor.Stop() 242 243 // Define the difficulty comparator 244 worse := func(td1, td2 *big.Int) { 245 if td2.Cmp(td1) >= 0 { 246 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 247 } 248 } 249 // Sum of numbers must be less than `length` for this to be a shorter fork 250 testFork(t, processor, 0, 3, full, worse) 251 testFork(t, processor, 0, 7, full, worse) 252 testFork(t, processor, 1, 1, full, worse) 253 testFork(t, processor, 1, 7, full, worse) 254 testFork(t, processor, 5, 3, full, worse) 255 testFork(t, processor, 5, 4, full, worse) 256 } 257 258 // Tests that given a starting canonical chain of a given size, creating longer 259 // forks do take canonical ownership. 260 func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } 261 func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } 262 263 func testLongerFork(t *testing.T, full bool) { 264 length := 10 265 266 // Make first chain starting from genesis 267 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 268 if err != nil { 269 t.Fatalf("failed to make new canonical chain: %v", err) 270 } 271 defer processor.Stop() 272 273 // Define the difficulty comparator 274 better := func(td1, td2 *big.Int) { 275 if td2.Cmp(td1) <= 0 { 276 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 277 } 278 } 279 // Sum of numbers must be greater than `length` for this to be a longer fork 280 testFork(t, processor, 0, 11, full, better) 281 testFork(t, processor, 0, 15, full, better) 282 testFork(t, processor, 1, 10, full, better) 283 testFork(t, processor, 1, 12, full, better) 284 testFork(t, processor, 5, 6, full, better) 285 testFork(t, processor, 5, 8, full, better) 286 } 287 288 // Tests that given a starting canonical chain of a given size, creating equal 289 // forks do take canonical ownership. 290 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } 291 func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } 292 293 func testEqualFork(t *testing.T, full bool) { 294 length := 10 295 296 // Make first chain starting from genesis 297 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 298 if err != nil { 299 t.Fatalf("failed to make new canonical chain: %v", err) 300 } 301 defer processor.Stop() 302 303 // Define the difficulty comparator 304 equal := func(td1, td2 *big.Int) { 305 if td2.Cmp(td1) != 0 { 306 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 307 } 308 } 309 // Sum of numbers must be equal to `length` for this to be an equal fork 310 testFork(t, processor, 0, 10, full, equal) 311 testFork(t, processor, 1, 9, full, equal) 312 testFork(t, processor, 2, 8, full, equal) 313 testFork(t, processor, 5, 5, full, equal) 314 testFork(t, processor, 6, 4, full, equal) 315 testFork(t, processor, 9, 1, full, equal) 316 } 317 318 // Tests that chains missing links do not get accepted by the processor. 319 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } 320 func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } 321 322 func testBrokenChain(t *testing.T, full bool) { 323 // Make chain starting from genesis 324 db, blockchain, err := newCanonical(ethash.NewFaker(), 10, full) 325 if err != nil { 326 t.Fatalf("failed to make new canonical chain: %v", err) 327 } 328 defer blockchain.Stop() 329 330 // Create a forked chain, and try to insert with a missing link 331 if full { 332 chain := makeBlockChain(blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed)[1:] 333 if err := testBlockChainImport(chain, blockchain); err == nil { 334 t.Errorf("broken block chain not reported") 335 } 336 } else { 337 chain := makeHeaderChain(blockchain.CurrentHeader(), 5, ethash.NewFaker(), db, forkSeed)[1:] 338 if err := testHeaderChainImport(chain, blockchain); err == nil { 339 t.Errorf("broken header chain not reported") 340 } 341 } 342 } 343 344 // Tests that reorganising a long difficult chain after a short easy one 345 // overwrites the canonical numbers and links in the database. 346 func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) } 347 func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) } 348 349 func testReorgLong(t *testing.T, full bool) { 350 testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280, full) 351 } 352 353 // Tests that reorganising a short difficult chain after a long easy one 354 // overwrites the canonical numbers and links in the database. 355 func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) } 356 func TestReorgShortBlocks(t *testing.T) { testReorgShort(t, true) } 357 358 func testReorgShort(t *testing.T, full bool) { 359 // Create a long easy chain vs. a short heavy one. Due to difficulty adjustment 360 // we need a fairly long chain of blocks with different difficulties for a short 361 // one to become heavyer than a long one. The 96 is an empirical value. 362 easy := make([]int64, 96) 363 for i := 0; i < len(easy); i++ { 364 easy[i] = 60 365 } 366 diff := make([]int64, len(easy)-1) 367 for i := 0; i < len(diff); i++ { 368 diff[i] = -9 369 } 370 testReorg(t, easy, diff, 12615120, full) 371 } 372 373 func testReorg(t *testing.T, first, second []int64, td int64, full bool) { 374 // Create a pristine chain and database 375 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 376 if err != nil { 377 t.Fatalf("failed to create pristine chain: %v", err) 378 } 379 defer blockchain.Stop() 380 381 // Insert an easy and a difficult chain afterwards 382 easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(first), func(i int, b *BlockGen) { 383 b.OffsetTime(first[i]) 384 }) 385 diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(second), func(i int, b *BlockGen) { 386 b.OffsetTime(second[i]) 387 }) 388 if full { 389 if _, err := blockchain.InsertChain(easyBlocks); err != nil { 390 t.Fatalf("failed to insert easy chain: %v", err) 391 } 392 if _, err := blockchain.InsertChain(diffBlocks); err != nil { 393 t.Fatalf("failed to insert difficult chain: %v", err) 394 } 395 } else { 396 easyHeaders := make([]*types.Header, len(easyBlocks)) 397 for i, block := range easyBlocks { 398 easyHeaders[i] = block.Header() 399 } 400 diffHeaders := make([]*types.Header, len(diffBlocks)) 401 for i, block := range diffBlocks { 402 diffHeaders[i] = block.Header() 403 } 404 if _, err := blockchain.InsertHeaderChain(easyHeaders, 1); err != nil { 405 t.Fatalf("failed to insert easy chain: %v", err) 406 } 407 if _, err := blockchain.InsertHeaderChain(diffHeaders, 1); err != nil { 408 t.Fatalf("failed to insert difficult chain: %v", err) 409 } 410 } 411 // Check that the chain is valid number and link wise 412 if full { 413 prev := blockchain.CurrentBlock() 414 for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.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 := blockchain.CurrentHeader() 421 for header := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, blockchain.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(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) 429 if full { 430 if have := blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()); have.Cmp(want) != 0 { 431 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 432 } 433 } else { 434 if have := blockchain.GetTdByHash(blockchain.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 // Create a pristine chain and database 446 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 447 if err != nil { 448 t.Fatalf("failed to create pristine chain: %v", err) 449 } 450 defer blockchain.Stop() 451 452 // Create a chain, ban a hash and try to import 453 if full { 454 blocks := makeBlockChain(blockchain.CurrentBlock(), 3, ethash.NewFaker(), db, 10) 455 456 BadHashes[blocks[2].Header().Hash()] = true 457 defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() 458 459 _, err = blockchain.InsertChain(blocks) 460 } else { 461 headers := makeHeaderChain(blockchain.CurrentHeader(), 3, ethash.NewFaker(), db, 10) 462 463 BadHashes[headers[2].Hash()] = true 464 defer func() { delete(BadHashes, headers[2].Hash()) }() 465 466 _, err = blockchain.InsertHeaderChain(headers, 1) 467 } 468 if err != ErrBlacklistedHash { 469 t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash) 470 } 471 } 472 473 // Tests that bad hashes are detected on boot, and the chain rolled back to a 474 // good state prior to the bad hash. 475 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } 476 func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } 477 478 func testReorgBadHashes(t *testing.T, full bool) { 479 // Create a pristine chain and database 480 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 481 if err != nil { 482 t.Fatalf("failed to create pristine chain: %v", err) 483 } 484 // Create a chain, import and ban afterwards 485 headers := makeHeaderChain(blockchain.CurrentHeader(), 4, ethash.NewFaker(), db, 10) 486 blocks := makeBlockChain(blockchain.CurrentBlock(), 4, ethash.NewFaker(), db, 10) 487 488 if full { 489 if _, err = blockchain.InsertChain(blocks); err != nil { 490 t.Errorf("failed to import blocks: %v", err) 491 } 492 if blockchain.CurrentBlock().Hash() != blocks[3].Hash() { 493 t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash()) 494 } 495 BadHashes[blocks[3].Header().Hash()] = true 496 defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() 497 } else { 498 if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil { 499 t.Errorf("failed to import headers: %v", err) 500 } 501 if blockchain.CurrentHeader().Hash() != headers[3].Hash() { 502 t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash()) 503 } 504 BadHashes[headers[3].Hash()] = true 505 defer func() { delete(BadHashes, headers[3].Hash()) }() 506 } 507 blockchain.Stop() 508 509 // Create a new BlockChain and check that it rolled back the state. 510 ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}, nil) 511 if err != nil { 512 t.Fatalf("failed to create new chain manager: %v", err) 513 } 514 if full { 515 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 516 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 517 } 518 if blocks[2].Header().GasLimit != ncm.GasLimit() { 519 t.Errorf("last block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit) 520 } 521 } else { 522 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 523 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 524 } 525 } 526 ncm.Stop() 527 } 528 529 // Tests chain insertions in the face of one entity containing an invalid nonce. 530 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } 531 func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } 532 533 func testInsertNonceError(t *testing.T, full bool) { 534 for i := 1; i < 25 && !t.Failed(); i++ { 535 // Create a pristine chain and database 536 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 537 if err != nil { 538 t.Fatalf("failed to create pristine chain: %v", err) 539 } 540 defer blockchain.Stop() 541 542 // Create and insert a chain with a failing nonce 543 var ( 544 failAt int 545 failRes int 546 failNum uint64 547 ) 548 if full { 549 blocks := makeBlockChain(blockchain.CurrentBlock(), i, ethash.NewFaker(), db, 0) 550 551 failAt = rand.Int() % len(blocks) 552 failNum = blocks[failAt].NumberU64() 553 554 blockchain.engine = ethash.NewFakeFailer(failNum) 555 failRes, err = blockchain.InsertChain(blocks) 556 } else { 557 headers := makeHeaderChain(blockchain.CurrentHeader(), i, ethash.NewFaker(), db, 0) 558 559 failAt = rand.Int() % len(headers) 560 failNum = headers[failAt].Number.Uint64() 561 562 blockchain.engine = ethash.NewFakeFailer(failNum) 563 blockchain.hc.engine = blockchain.engine 564 failRes, err = blockchain.InsertHeaderChain(headers, 1) 565 } 566 // Check that the returned error indicates the failure 567 if failRes != failAt { 568 t.Errorf("test %d: failure (%v) index mismatch: have %d, want %d", i, err, failRes, failAt) 569 } 570 // Check that all blocks after the failing block have been inserted 571 for j := 0; j < i-failAt; j++ { 572 if full { 573 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 574 t.Errorf("test %d: invalid block in chain: %v", i, block) 575 } 576 } else { 577 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 578 t.Errorf("test %d: invalid header in chain: %v", i, header) 579 } 580 } 581 } 582 } 583 } 584 585 // Tests that fast importing a block chain produces the same chain data as the 586 // classical full block processing. 587 func TestFastVsFullChains(t *testing.T) { 588 // Configure and generate a sample block chain 589 var ( 590 gendb = ethdb.NewMemDatabase() 591 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 592 address = crypto.PubkeyToAddress(key.PublicKey) 593 funds = big.NewInt(1000000000) 594 gspec = &Genesis{ 595 Config: params.TestChainConfig, 596 Alloc: GenesisAlloc{address: {Balance: funds}}, 597 } 598 genesis = gspec.MustCommit(gendb) 599 signer = types.NewEIP155Signer(gspec.Config.ChainID) 600 ) 601 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, 1024, func(i int, block *BlockGen) { 602 block.SetCoinbase(common.Address{0x00}) 603 604 // If the block number is multiple of 3, send a few bonus transactions to the miner 605 if i%3 == 2 { 606 for j := 0; j < i%4+1; j++ { 607 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key) 608 if err != nil { 609 panic(err) 610 } 611 block.AddTx(tx) 612 } 613 } 614 // If the block number is a multiple of 5, add a few bonus uncles to the block 615 if i%5 == 5 { 616 block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))}) 617 } 618 }) 619 // Import the chain as an archive node for the comparison baseline 620 archiveDb := ethdb.NewMemDatabase() 621 gspec.MustCommit(archiveDb) 622 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 623 defer archive.Stop() 624 625 if n, err := archive.InsertChain(blocks); err != nil { 626 t.Fatalf("failed to process block %d: %v", n, err) 627 } 628 // Fast import the chain as a non-archive node to test 629 fastDb := ethdb.NewMemDatabase() 630 gspec.MustCommit(fastDb) 631 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 632 defer fast.Stop() 633 634 headers := make([]*types.Header, len(blocks)) 635 for i, block := range blocks { 636 headers[i] = block.Header() 637 } 638 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 639 t.Fatalf("failed to insert header %d: %v", n, err) 640 } 641 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 642 t.Fatalf("failed to insert receipt %d: %v", n, err) 643 } 644 // Iterate over all chain data components, and cross reference 645 for i := 0; i < len(blocks); i++ { 646 num, hash := blocks[i].NumberU64(), blocks[i].Hash() 647 648 if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 { 649 t.Errorf("block #%d [%x]: td mismatch: have %v, want %v", num, hash, ftd, atd) 650 } 651 if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { 652 t.Errorf("block #%d [%x]: header mismatch: have %v, want %v", num, hash, fheader, aheader) 653 } 654 if fblock, ablock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash); fblock.Hash() != ablock.Hash() { 655 t.Errorf("block #%d [%x]: block mismatch: have %v, want %v", num, hash, fblock, ablock) 656 } else if types.DeriveSha(fblock.Transactions()) != types.DeriveSha(ablock.Transactions()) { 657 t.Errorf("block #%d [%x]: transactions mismatch: have %v, want %v", num, hash, fblock.Transactions(), ablock.Transactions()) 658 } else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(ablock.Uncles()) { 659 t.Errorf("block #%d [%x]: uncles mismatch: have %v, want %v", num, hash, fblock.Uncles(), ablock.Uncles()) 660 } 661 if freceipts, areceipts := rawdb.ReadReceipts(fastDb, hash, *rawdb.ReadHeaderNumber(fastDb, hash)), rawdb.ReadReceipts(archiveDb, hash, *rawdb.ReadHeaderNumber(archiveDb, hash)); types.DeriveSha(freceipts) != types.DeriveSha(areceipts) { 662 t.Errorf("block #%d [%x]: receipts mismatch: have %v, want %v", num, hash, freceipts, areceipts) 663 } 664 } 665 // Check that the canonical chains are the same between the databases 666 for i := 0; i < len(blocks)+1; i++ { 667 if fhash, ahash := rawdb.ReadCanonicalHash(fastDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); fhash != ahash { 668 t.Errorf("block #%d: canonical hash mismatch: have %v, want %v", i, fhash, ahash) 669 } 670 } 671 } 672 673 // Tests that various import methods move the chain head pointers to the correct 674 // positions. 675 func TestLightVsFastVsFullChainHeads(t *testing.T) { 676 // Configure and generate a sample block chain 677 var ( 678 gendb = ethdb.NewMemDatabase() 679 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 680 address = crypto.PubkeyToAddress(key.PublicKey) 681 funds = big.NewInt(1000000000) 682 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 683 genesis = gspec.MustCommit(gendb) 684 ) 685 height := uint64(1024) 686 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 687 688 // Configure a subchain to roll back 689 remove := []common.Hash{} 690 for _, block := range blocks[height/2:] { 691 remove = append(remove, block.Hash()) 692 } 693 // Create a small assertion method to check the three heads 694 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 695 if num := chain.CurrentBlock().NumberU64(); num != block { 696 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 697 } 698 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 699 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 700 } 701 if num := chain.CurrentHeader().Number.Uint64(); num != header { 702 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 703 } 704 } 705 // Import the chain as an archive node and ensure all pointers are updated 706 archiveDb := ethdb.NewMemDatabase() 707 gspec.MustCommit(archiveDb) 708 709 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 710 if n, err := archive.InsertChain(blocks); err != nil { 711 t.Fatalf("failed to process block %d: %v", n, err) 712 } 713 defer archive.Stop() 714 715 assert(t, "archive", archive, height, height, height) 716 archive.Rollback(remove) 717 assert(t, "archive", archive, height/2, height/2, height/2) 718 719 // Import the chain as a non-archive node and ensure all pointers are updated 720 fastDb := ethdb.NewMemDatabase() 721 gspec.MustCommit(fastDb) 722 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 723 defer fast.Stop() 724 725 headers := make([]*types.Header, len(blocks)) 726 for i, block := range blocks { 727 headers[i] = block.Header() 728 } 729 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 730 t.Fatalf("failed to insert header %d: %v", n, err) 731 } 732 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 733 t.Fatalf("failed to insert receipt %d: %v", n, err) 734 } 735 assert(t, "fast", fast, height, height, 0) 736 fast.Rollback(remove) 737 assert(t, "fast", fast, height/2, height/2, 0) 738 739 // Import the chain as a light node and ensure all pointers are updated 740 lightDb := ethdb.NewMemDatabase() 741 gspec.MustCommit(lightDb) 742 743 light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 744 if n, err := light.InsertHeaderChain(headers, 1); err != nil { 745 t.Fatalf("failed to insert header %d: %v", n, err) 746 } 747 defer light.Stop() 748 749 assert(t, "light", light, height, 0, 0) 750 light.Rollback(remove) 751 assert(t, "light", light, height/2, 0, 0) 752 } 753 754 // Tests that chain reorganisations handle transaction removals and reinsertions. 755 func TestChainTxReorgs(t *testing.T) { 756 var ( 757 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 758 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 759 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 760 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 761 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 762 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 763 db = ethdb.NewMemDatabase() 764 gspec = &Genesis{ 765 Config: params.TestChainConfig, 766 GasLimit: 40000000, 767 Alloc: GenesisAlloc{ 768 addr1: {Balance: big.NewInt(10000000)}, 769 addr2: {Balance: big.NewInt(10000000)}, 770 addr3: {Balance: big.NewInt(10000000)}, 771 }, 772 } 773 genesis = gspec.MustCommit(db) 774 signer = types.NewEIP155Signer(gspec.Config.ChainID) 775 ) 776 777 // Create two transactions shared between the chains: 778 // - postponed: transaction included at a later block in the forked chain 779 // - swapped: transaction included at the same block number in the forked chain 780 postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 781 swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 782 783 // Create two transactions that will be dropped by the forked chain: 784 // - pastDrop: transaction dropped retroactively from a past block 785 // - freshDrop: transaction dropped exactly at the block where the reorg is detected 786 var pastDrop, freshDrop *types.Transaction 787 788 // Create three transactions that will be added in the forked chain: 789 // - pastAdd: transaction added before the reorganization is detected 790 // - freshAdd: transaction added at the exact block the reorg is detected 791 // - futureAdd: transaction added after the reorg has already finished 792 var pastAdd, freshAdd, futureAdd *types.Transaction 793 794 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) { 795 switch i { 796 case 0: 797 pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 798 799 gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point 800 gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork 801 802 case 2: 803 freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 804 805 gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point 806 gen.AddTx(swapped) // This transaction will be swapped out at the exact height 807 808 gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain 809 } 810 }) 811 // Import the chain. This runs all block validation rules. 812 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 813 if i, err := blockchain.InsertChain(chain); err != nil { 814 t.Fatalf("failed to insert original chain[%d]: %v", i, err) 815 } 816 defer blockchain.Stop() 817 818 // overwrite the old chain 819 chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) { 820 switch i { 821 case 0: 822 pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 823 gen.AddTx(pastAdd) // This transaction needs to be injected during reorg 824 825 case 2: 826 gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain 827 gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain 828 829 freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 830 gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time 831 832 case 3: 833 futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 834 gen.AddTx(futureAdd) // This transaction will be added after a full reorg 835 } 836 }) 837 if _, err := blockchain.InsertChain(chain); err != nil { 838 t.Fatalf("failed to insert forked chain: %v", err) 839 } 840 841 // removed tx 842 for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 843 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil { 844 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 845 } 846 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt != nil { 847 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 848 } 849 } 850 // added tx 851 for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 852 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 853 t.Errorf("add %d: expected tx to be found", i) 854 } 855 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil { 856 t.Errorf("add %d: expected receipt to be found", i) 857 } 858 } 859 // shared tx 860 for i, tx := range (types.Transactions{postponed, swapped}) { 861 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 862 t.Errorf("share %d: expected tx to be found", i) 863 } 864 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil { 865 t.Errorf("share %d: expected receipt to be found", i) 866 } 867 } 868 } 869 870 func TestLogReorgs(t *testing.T) { 871 var ( 872 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 873 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 874 db = ethdb.NewMemDatabase() 875 // this code generates a log 876 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 877 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 878 genesis = gspec.MustCommit(db) 879 signer = types.NewEIP155Signer(gspec.Config.ChainID) 880 ) 881 882 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 883 defer blockchain.Stop() 884 885 rmLogsCh := make(chan RemovedLogsEvent) 886 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 887 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 888 if i == 1 { 889 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 890 if err != nil { 891 t.Fatalf("failed to create tx: %v", err) 892 } 893 gen.AddTx(tx) 894 } 895 }) 896 if _, err := blockchain.InsertChain(chain); err != nil { 897 t.Fatalf("failed to insert chain: %v", err) 898 } 899 900 chain, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 901 if _, err := blockchain.InsertChain(chain); err != nil { 902 t.Fatalf("failed to insert forked chain: %v", err) 903 } 904 905 timeout := time.NewTimer(1 * time.Second) 906 select { 907 case ev := <-rmLogsCh: 908 if len(ev.Logs) == 0 { 909 t.Error("expected logs") 910 } 911 case <-timeout.C: 912 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 913 } 914 } 915 916 func TestLogRebirth(t *testing.T) { 917 var ( 918 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 919 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 920 db = ethdb.NewMemDatabase() 921 922 // this code generates a log 923 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 924 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 925 genesis = gspec.MustCommit(db) 926 signer = types.NewEIP155Signer(gspec.Config.ChainID) 927 newLogCh = make(chan bool) 928 ) 929 930 // listenNewLog checks whether the received logs number is equal with expected. 931 listenNewLog := func(sink chan []*types.Log, expect int) { 932 cnt := 0 933 for { 934 select { 935 case logs := <-sink: 936 cnt += len(logs) 937 case <-time.NewTimer(5 * time.Second).C: 938 // new logs timeout 939 newLogCh <- false 940 return 941 } 942 if cnt == expect { 943 break 944 } else if cnt > expect { 945 // redundant logs received 946 newLogCh <- false 947 return 948 } 949 } 950 select { 951 case <-sink: 952 // redundant logs received 953 newLogCh <- false 954 case <-time.NewTimer(100 * time.Millisecond).C: 955 newLogCh <- true 956 } 957 } 958 959 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 960 defer blockchain.Stop() 961 962 logsCh := make(chan []*types.Log) 963 blockchain.SubscribeLogsEvent(logsCh) 964 965 rmLogsCh := make(chan RemovedLogsEvent) 966 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 967 968 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 969 if i == 1 { 970 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 971 if err != nil { 972 t.Fatalf("failed to create tx: %v", err) 973 } 974 gen.AddTx(tx) 975 } 976 }) 977 978 // Spawn a goroutine to receive log events 979 go listenNewLog(logsCh, 1) 980 if _, err := blockchain.InsertChain(chain); err != nil { 981 t.Fatalf("failed to insert chain: %v", err) 982 } 983 if !<-newLogCh { 984 t.Fatalf("failed to receive new log event") 985 } 986 987 // Generate long reorg chain 988 forkChain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 989 if i == 1 { 990 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 991 if err != nil { 992 t.Fatalf("failed to create tx: %v", err) 993 } 994 gen.AddTx(tx) 995 // Higher block difficulty 996 gen.OffsetTime(-9) 997 } 998 }) 999 1000 // Spawn a goroutine to receive log events 1001 go listenNewLog(logsCh, 1) 1002 if _, err := blockchain.InsertChain(forkChain); err != nil { 1003 t.Fatalf("failed to insert forked chain: %v", err) 1004 } 1005 if !<-newLogCh { 1006 t.Fatalf("failed to receive new log event") 1007 } 1008 // Ensure removedLog events received 1009 select { 1010 case ev := <-rmLogsCh: 1011 if len(ev.Logs) == 0 { 1012 t.Error("expected logs") 1013 } 1014 case <-time.NewTimer(1 * time.Second).C: 1015 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 1016 } 1017 1018 newBlocks, _ := GenerateChain(params.TestChainConfig, chain[len(chain)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) 1019 go listenNewLog(logsCh, 1) 1020 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1021 t.Fatalf("failed to insert forked chain: %v", err) 1022 } 1023 // Ensure removedLog events received 1024 select { 1025 case ev := <-rmLogsCh: 1026 if len(ev.Logs) == 0 { 1027 t.Error("expected logs") 1028 } 1029 case <-time.NewTimer(1 * time.Second).C: 1030 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 1031 } 1032 // Rebirth logs should omit a newLogEvent 1033 if !<-newLogCh { 1034 t.Fatalf("failed to receive new log event") 1035 } 1036 } 1037 1038 func TestSideLogRebirth(t *testing.T) { 1039 var ( 1040 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1041 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1042 db = ethdb.NewMemDatabase() 1043 1044 // this code generates a log 1045 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 1046 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 1047 genesis = gspec.MustCommit(db) 1048 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1049 newLogCh = make(chan bool) 1050 ) 1051 1052 // listenNewLog checks whether the received logs number is equal with expected. 1053 listenNewLog := func(sink chan []*types.Log, expect int) { 1054 cnt := 0 1055 for { 1056 select { 1057 case logs := <-sink: 1058 cnt += len(logs) 1059 case <-time.NewTimer(5 * time.Second).C: 1060 // new logs timeout 1061 newLogCh <- false 1062 return 1063 } 1064 if cnt == expect { 1065 break 1066 } else if cnt > expect { 1067 // redundant logs received 1068 newLogCh <- false 1069 return 1070 } 1071 } 1072 select { 1073 case <-sink: 1074 // redundant logs received 1075 newLogCh <- false 1076 case <-time.NewTimer(100 * time.Millisecond).C: 1077 newLogCh <- true 1078 } 1079 } 1080 1081 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1082 defer blockchain.Stop() 1083 1084 logsCh := make(chan []*types.Log) 1085 blockchain.SubscribeLogsEvent(logsCh) 1086 1087 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1088 if i == 1 { 1089 // Higher block difficulty 1090 gen.OffsetTime(-9) 1091 } 1092 }) 1093 if _, err := blockchain.InsertChain(chain); err != nil { 1094 t.Fatalf("failed to insert forked chain: %v", err) 1095 } 1096 1097 // Generate side chain with lower difficulty 1098 sideChain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1099 if i == 1 { 1100 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 1101 if err != nil { 1102 t.Fatalf("failed to create tx: %v", err) 1103 } 1104 gen.AddTx(tx) 1105 } 1106 }) 1107 if _, err := blockchain.InsertChain(sideChain); err != nil { 1108 t.Fatalf("failed to insert forked chain: %v", err) 1109 } 1110 1111 // Generate a new block based on side chain 1112 newBlocks, _ := GenerateChain(params.TestChainConfig, sideChain[len(sideChain)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) 1113 go listenNewLog(logsCh, 1) 1114 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1115 t.Fatalf("failed to insert forked chain: %v", err) 1116 } 1117 // Rebirth logs should omit a newLogEvent 1118 if !<-newLogCh { 1119 t.Fatalf("failed to receive new log event") 1120 } 1121 } 1122 1123 func TestReorgSideEvent(t *testing.T) { 1124 var ( 1125 db = ethdb.NewMemDatabase() 1126 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1127 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1128 gspec = &Genesis{ 1129 Config: params.TestChainConfig, 1130 Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}, 1131 } 1132 genesis = gspec.MustCommit(db) 1133 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1134 ) 1135 1136 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1137 defer blockchain.Stop() 1138 1139 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 1140 if _, err := blockchain.InsertChain(chain); err != nil { 1141 t.Fatalf("failed to insert chain: %v", err) 1142 } 1143 1144 replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) { 1145 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1) 1146 if i == 2 { 1147 gen.OffsetTime(-9) 1148 } 1149 if err != nil { 1150 t.Fatalf("failed to create tx: %v", err) 1151 } 1152 gen.AddTx(tx) 1153 }) 1154 chainSideCh := make(chan ChainSideEvent, 64) 1155 blockchain.SubscribeChainSideEvent(chainSideCh) 1156 if _, err := blockchain.InsertChain(replacementBlocks); err != nil { 1157 t.Fatalf("failed to insert chain: %v", err) 1158 } 1159 1160 // first two block of the secondary chain are for a brief moment considered 1161 // side chains because up to that point the first one is considered the 1162 // heavier chain. 1163 expectedSideHashes := map[common.Hash]bool{ 1164 replacementBlocks[0].Hash(): true, 1165 replacementBlocks[1].Hash(): true, 1166 chain[0].Hash(): true, 1167 chain[1].Hash(): true, 1168 chain[2].Hash(): true, 1169 } 1170 1171 i := 0 1172 1173 const timeoutDura = 10 * time.Second 1174 timeout := time.NewTimer(timeoutDura) 1175 done: 1176 for { 1177 select { 1178 case ev := <-chainSideCh: 1179 block := ev.Block 1180 if _, ok := expectedSideHashes[block.Hash()]; !ok { 1181 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 1182 } 1183 i++ 1184 1185 if i == len(expectedSideHashes) { 1186 timeout.Stop() 1187 1188 break done 1189 } 1190 timeout.Reset(timeoutDura) 1191 1192 case <-timeout.C: 1193 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 1194 } 1195 } 1196 1197 // make sure no more events are fired 1198 select { 1199 case e := <-chainSideCh: 1200 t.Errorf("unexpected event fired: %v", e) 1201 case <-time.After(250 * time.Millisecond): 1202 } 1203 1204 } 1205 1206 // Tests if the canonical block can be fetched from the database during chain insertion. 1207 func TestCanonicalBlockRetrieval(t *testing.T) { 1208 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) 1209 if err != nil { 1210 t.Fatalf("failed to create pristine chain: %v", err) 1211 } 1212 defer blockchain.Stop() 1213 1214 chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, ethash.NewFaker(), blockchain.db, 10, func(i int, gen *BlockGen) {}) 1215 1216 var pend sync.WaitGroup 1217 pend.Add(len(chain)) 1218 1219 for i := range chain { 1220 go func(block *types.Block) { 1221 defer pend.Done() 1222 1223 // try to retrieve a block by its canonical hash and see if the block data can be retrieved. 1224 for { 1225 ch := rawdb.ReadCanonicalHash(blockchain.db, block.NumberU64()) 1226 if ch == (common.Hash{}) { 1227 continue // busy wait for canonical hash to be written 1228 } 1229 if ch != block.Hash() { 1230 t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1231 } 1232 fb := rawdb.ReadBlock(blockchain.db, ch, block.NumberU64()) 1233 if fb == nil { 1234 t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1235 } 1236 if fb.Hash() != block.Hash() { 1237 t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1238 } 1239 return 1240 } 1241 }(chain[i]) 1242 1243 if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { 1244 t.Fatalf("failed to insert block %d: %v", i, err) 1245 } 1246 } 1247 pend.Wait() 1248 } 1249 1250 func TestEIP155Transition(t *testing.T) { 1251 // Configure and generate a sample block chain 1252 var ( 1253 db = ethdb.NewMemDatabase() 1254 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1255 address = crypto.PubkeyToAddress(key.PublicKey) 1256 funds = big.NewInt(1000000000) 1257 deleteAddr = common.Address{1} 1258 gspec = &Genesis{ 1259 Config: ¶ms.ChainConfig{ChainID: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}, 1260 Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 1261 } 1262 genesis = gspec.MustCommit(db) 1263 ) 1264 1265 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1266 defer blockchain.Stop() 1267 1268 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1269 var ( 1270 tx *types.Transaction 1271 err error 1272 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1273 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1274 } 1275 ) 1276 switch i { 1277 case 0: 1278 tx, err = basicTx(types.HomesteadSigner{}) 1279 if err != nil { 1280 t.Fatal(err) 1281 } 1282 block.AddTx(tx) 1283 case 2: 1284 tx, err = basicTx(types.HomesteadSigner{}) 1285 if err != nil { 1286 t.Fatal(err) 1287 } 1288 block.AddTx(tx) 1289 1290 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainID)) 1291 if err != nil { 1292 t.Fatal(err) 1293 } 1294 block.AddTx(tx) 1295 case 3: 1296 tx, err = basicTx(types.HomesteadSigner{}) 1297 if err != nil { 1298 t.Fatal(err) 1299 } 1300 block.AddTx(tx) 1301 1302 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainID)) 1303 if err != nil { 1304 t.Fatal(err) 1305 } 1306 block.AddTx(tx) 1307 } 1308 }) 1309 1310 if _, err := blockchain.InsertChain(blocks); err != nil { 1311 t.Fatal(err) 1312 } 1313 block := blockchain.GetBlockByNumber(1) 1314 if block.Transactions()[0].Protected() { 1315 t.Error("Expected block[0].txs[0] to not be replay protected") 1316 } 1317 1318 block = blockchain.GetBlockByNumber(3) 1319 if block.Transactions()[0].Protected() { 1320 t.Error("Expected block[3].txs[0] to not be replay protected") 1321 } 1322 if !block.Transactions()[1].Protected() { 1323 t.Error("Expected block[3].txs[1] to be replay protected") 1324 } 1325 if _, err := blockchain.InsertChain(blocks[4:]); err != nil { 1326 t.Fatal(err) 1327 } 1328 1329 // generate an invalid chain id transaction 1330 config := ¶ms.ChainConfig{ChainID: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)} 1331 blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1332 var ( 1333 tx *types.Transaction 1334 err error 1335 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1336 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1337 } 1338 ) 1339 if i == 0 { 1340 tx, err = basicTx(types.NewEIP155Signer(big.NewInt(2))) 1341 if err != nil { 1342 t.Fatal(err) 1343 } 1344 block.AddTx(tx) 1345 } 1346 }) 1347 _, err := blockchain.InsertChain(blocks) 1348 if err != types.ErrInvalidChainId { 1349 t.Error("expected error:", types.ErrInvalidChainId) 1350 } 1351 } 1352 1353 func TestEIP161AccountRemoval(t *testing.T) { 1354 // Configure and generate a sample block chain 1355 var ( 1356 db = ethdb.NewMemDatabase() 1357 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1358 address = crypto.PubkeyToAddress(key.PublicKey) 1359 funds = big.NewInt(1000000000) 1360 theAddr = common.Address{1} 1361 gspec = &Genesis{ 1362 Config: ¶ms.ChainConfig{ 1363 ChainID: big.NewInt(1), 1364 HomesteadBlock: new(big.Int), 1365 EIP155Block: new(big.Int), 1366 EIP158Block: big.NewInt(2), 1367 }, 1368 Alloc: GenesisAlloc{address: {Balance: funds}}, 1369 } 1370 genesis = gspec.MustCommit(db) 1371 ) 1372 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1373 defer blockchain.Stop() 1374 1375 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) { 1376 var ( 1377 tx *types.Transaction 1378 err error 1379 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1380 ) 1381 switch i { 1382 case 0: 1383 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1384 case 1: 1385 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1386 case 2: 1387 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1388 } 1389 if err != nil { 1390 t.Fatal(err) 1391 } 1392 block.AddTx(tx) 1393 }) 1394 // account must exist pre eip 161 1395 if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1396 t.Fatal(err) 1397 } 1398 if st, _ := blockchain.State(); !st.Exist(theAddr) { 1399 t.Error("expected account to exist") 1400 } 1401 1402 // account needs to be deleted post eip 161 1403 if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1404 t.Fatal(err) 1405 } 1406 if st, _ := blockchain.State(); st.Exist(theAddr) { 1407 t.Error("account should not exist") 1408 } 1409 1410 // account musn't be created post eip 161 1411 if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1412 t.Fatal(err) 1413 } 1414 if st, _ := blockchain.State(); st.Exist(theAddr) { 1415 t.Error("account should not exist") 1416 } 1417 } 1418 1419 // This is a regression test (i.e. as weird as it is, don't delete it ever), which 1420 // tests that under weird reorg conditions the blockchain and its internal header- 1421 // chain return the same latest block/header. 1422 // 1423 // https://github.com/energicryptocurrency/go-energi/pull/15941 1424 func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { 1425 // Generate a canonical chain to act as the main dataset 1426 engine := ethash.NewFaker() 1427 1428 db := ethdb.NewMemDatabase() 1429 genesis := new(Genesis).MustCommit(db) 1430 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1431 1432 // Generate a bunch of fork blocks, each side forking from the canonical chain 1433 forks := make([]*types.Block, len(blocks)) 1434 for i := 0; i < len(forks); i++ { 1435 parent := genesis 1436 if i > 0 { 1437 parent = blocks[i-1] 1438 } 1439 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1440 forks[i] = fork[0] 1441 } 1442 // Import the canonical and fork chain side by side, verifying the current block 1443 // and current header consistency 1444 diskdb := ethdb.NewMemDatabase() 1445 new(Genesis).MustCommit(diskdb) 1446 1447 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1448 if err != nil { 1449 t.Fatalf("failed to create tester chain: %v", err) 1450 } 1451 for i := 0; i < len(blocks); i++ { 1452 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1453 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1454 } 1455 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1456 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]) 1457 } 1458 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1459 t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) 1460 } 1461 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1462 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]) 1463 } 1464 } 1465 } 1466 1467 // Tests that importing small side forks doesn't leave junk in the trie database 1468 // cache (which would eventually cause memory issues). 1469 func TestTrieForkGC(t *testing.T) { 1470 // Generate a canonical chain to act as the main dataset 1471 engine := ethash.NewFaker() 1472 1473 db := ethdb.NewMemDatabase() 1474 genesis := new(Genesis).MustCommit(db) 1475 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1476 1477 // Generate a bunch of fork blocks, each side forking from the canonical chain 1478 forks := make([]*types.Block, len(blocks)) 1479 for i := 0; i < len(forks); i++ { 1480 parent := genesis 1481 if i > 0 { 1482 parent = blocks[i-1] 1483 } 1484 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1485 forks[i] = fork[0] 1486 } 1487 // Import the canonical and fork chain side by side, forcing the trie cache to cache both 1488 diskdb := ethdb.NewMemDatabase() 1489 new(Genesis).MustCommit(diskdb) 1490 1491 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1492 if err != nil { 1493 t.Fatalf("failed to create tester chain: %v", err) 1494 } 1495 for i := 0; i < len(blocks); i++ { 1496 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1497 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1498 } 1499 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1500 t.Fatalf("fork %d: failed to insert into chain: %v", i, err) 1501 } 1502 } 1503 // Dereference all the recent tries and ensure no past trie is left in 1504 for i := 0; i < triesInMemory; i++ { 1505 chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) 1506 chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) 1507 } 1508 if len(chain.stateCache.TrieDB().Nodes()) > 0 { 1509 t.Fatalf("stale tries still alive after garbase collection") 1510 } 1511 } 1512 1513 // Tests that doing large reorgs works even if the state associated with the 1514 // forking point is not available any more. 1515 func TestLargeReorgTrieGC(t *testing.T) { 1516 // Generate the original common chain segment and the two competing forks 1517 engine := ethash.NewFaker() 1518 1519 db := ethdb.NewMemDatabase() 1520 genesis := new(Genesis).MustCommit(db) 1521 1522 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1523 original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1524 competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) 1525 1526 // Import the shared chain and the original canonical one 1527 diskdb := ethdb.NewMemDatabase() 1528 new(Genesis).MustCommit(diskdb) 1529 1530 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1531 if err != nil { 1532 t.Fatalf("failed to create tester chain: %v", err) 1533 } 1534 if _, err := chain.InsertChain(shared); err != nil { 1535 t.Fatalf("failed to insert shared chain: %v", err) 1536 } 1537 if _, err := chain.InsertChain(original); err != nil { 1538 t.Fatalf("failed to insert original chain: %v", err) 1539 } 1540 // Ensure that the state associated with the forking point is pruned away 1541 if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil { 1542 t.Fatalf("common-but-old ancestor still cache") 1543 } 1544 // Import the competitor chain without exceeding the canonical's TD and ensure 1545 // we have not processed any of the blocks (protection against malicious blocks) 1546 if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { 1547 t.Fatalf("failed to insert competitor chain: %v", err) 1548 } 1549 for i, block := range competitor[:len(competitor)-2] { 1550 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1551 t.Fatalf("competitor %d: low TD chain became processed", i) 1552 } 1553 } 1554 // Import the head of the competitor chain, triggering the reorg and ensure we 1555 // successfully reprocess all the stashed away blocks. 1556 if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { 1557 t.Fatalf("failed to finalize competitor chain: %v", err) 1558 } 1559 for i, block := range competitor[:len(competitor)-triesInMemory] { 1560 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1561 t.Fatalf("competitor %d: competing chain state missing", i) 1562 } 1563 } 1564 } 1565 1566 // Benchmarks large blocks with value transfers to non-existing accounts 1567 func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) { 1568 var ( 1569 signer = types.HomesteadSigner{} 1570 testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1571 testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) 1572 bankFunds = big.NewInt(100000000000000000) 1573 gspec = Genesis{ 1574 Config: params.TestChainConfig, 1575 Alloc: GenesisAlloc{ 1576 testBankAddress: {Balance: bankFunds}, 1577 common.HexToAddress("0xc0de"): { 1578 Code: []byte{0x60, 0x01, 0x50}, 1579 Balance: big.NewInt(0), 1580 }, // push 1, pop 1581 }, 1582 GasLimit: 100e6, // 100 M 1583 } 1584 ) 1585 // Generate the original common chain segment and the two competing forks 1586 engine := ethash.NewFaker() 1587 db := ethdb.NewMemDatabase() 1588 genesis := gspec.MustCommit(db) 1589 1590 blockGenerator := func(i int, block *BlockGen) { 1591 block.SetCoinbase(common.Address{1}) 1592 for txi := 0; txi < numTxs; txi++ { 1593 uniq := uint64(i*numTxs + txi) 1594 recipient := recipientFn(uniq) 1595 //recipient := common.BigToAddress(big.NewInt(0).SetUint64(1337 + uniq)) 1596 tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey) 1597 if err != nil { 1598 b.Error(err) 1599 } 1600 block.AddTx(tx) 1601 } 1602 } 1603 1604 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator) 1605 b.StopTimer() 1606 b.ResetTimer() 1607 for i := 0; i < b.N; i++ { 1608 // Import the shared chain and the original canonical one 1609 diskdb := ethdb.NewMemDatabase() 1610 gspec.MustCommit(diskdb) 1611 1612 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1613 if err != nil { 1614 b.Fatalf("failed to create tester chain: %v", err) 1615 } 1616 b.StartTimer() 1617 if _, err := chain.InsertChain(shared); err != nil { 1618 b.Fatalf("failed to insert shared chain: %v", err) 1619 } 1620 b.StopTimer() 1621 if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { 1622 b.Fatalf("Transactions were not included, expected %d, got %d", (numTxs * numBlocks), got) 1623 1624 } 1625 } 1626 } 1627 func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) { 1628 var ( 1629 numTxs = 1000 1630 numBlocks = 1 1631 ) 1632 1633 recipientFn := func(nonce uint64) common.Address { 1634 return common.BigToAddress(big.NewInt(0).SetUint64(1337 + nonce)) 1635 } 1636 dataFn := func(nonce uint64) []byte { 1637 return nil 1638 } 1639 1640 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1641 } 1642 func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) { 1643 var ( 1644 numTxs = 1000 1645 numBlocks = 1 1646 ) 1647 b.StopTimer() 1648 b.ResetTimer() 1649 1650 recipientFn := func(nonce uint64) common.Address { 1651 return common.BigToAddress(big.NewInt(0).SetUint64(1337)) 1652 } 1653 dataFn := func(nonce uint64) []byte { 1654 return nil 1655 } 1656 1657 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1658 } 1659 func BenchmarkBlockChain_1x1000Executions(b *testing.B) { 1660 var ( 1661 numTxs = 1000 1662 numBlocks = 1 1663 ) 1664 b.StopTimer() 1665 b.ResetTimer() 1666 1667 recipientFn := func(nonce uint64) common.Address { 1668 return common.BigToAddress(big.NewInt(0).SetUint64(0xc0de)) 1669 } 1670 dataFn := func(nonce uint64) []byte { 1671 return nil 1672 } 1673 1674 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1675 } 1676 1677 // Tests that importing a very large side fork, which is larger than the canon chain, 1678 // but where the difficulty per block is kept low: this means that it will not 1679 // overtake the 'canon' chain until after it's passed canon by about 200 blocks. 1680 // 1681 // Details at: 1682 // - https://github.com/energicryptocurrency/go-energi/issues/18977 1683 // - https://github.com/energicryptocurrency/go-energi/pull/18988 1684 func TestLowDiffLongChain(t *testing.T) { 1685 // Generate a canonical chain to act as the main dataset 1686 engine := ethash.NewFaker() 1687 db := ethdb.NewMemDatabase() 1688 genesis := new(Genesis).MustCommit(db) 1689 1690 // We must use a pretty long chain to ensure that the fork doesn't overtake us 1691 // until after at least 128 blocks post tip 1692 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 6*triesInMemory, func(i int, b *BlockGen) { 1693 b.SetCoinbase(common.Address{1}) 1694 b.OffsetTime(-9) 1695 }) 1696 1697 // Import the canonical chain 1698 diskdb := ethdb.NewMemDatabase() 1699 new(Genesis).MustCommit(diskdb) 1700 1701 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1702 if err != nil { 1703 t.Fatalf("failed to create tester chain: %v", err) 1704 } 1705 if n, err := chain.InsertChain(blocks); err != nil { 1706 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1707 } 1708 // Generate fork chain, starting from an early block 1709 parent := blocks[10] 1710 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 8*triesInMemory, func(i int, b *BlockGen) { 1711 b.SetCoinbase(common.Address{2}) 1712 }) 1713 1714 // And now import the fork 1715 if i, err := chain.InsertChain(fork); err != nil { 1716 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1717 } 1718 head := chain.CurrentBlock() 1719 if got := fork[len(fork)-1].Hash(); got != head.Hash() { 1720 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 1721 } 1722 // Sanity check that all the canonical numbers are present 1723 header := chain.CurrentHeader() 1724 for number := head.NumberU64(); number > 0; number-- { 1725 if hash := chain.GetHeaderByNumber(number).Hash(); hash != header.Hash() { 1726 t.Fatalf("header %d: canonical hash mismatch: have %x, want %x", number, hash, header.Hash()) 1727 } 1728 header = chain.GetHeader(header.ParentHash, number-1) 1729 } 1730 }