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