github.com/ethereumproject/go-ethereum@v5.5.2+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 "fmt" 21 "math/big" 22 "math/rand" 23 "os" 24 "path/filepath" 25 "strconv" 26 "testing" 27 "time" 28 29 "github.com/ethereumproject/ethash" 30 "github.com/ethereumproject/go-ethereum/common" 31 "github.com/ethereumproject/go-ethereum/core/state" 32 "github.com/ethereumproject/go-ethereum/core/types" 33 "github.com/ethereumproject/go-ethereum/core/vm" 34 "github.com/ethereumproject/go-ethereum/crypto" 35 "github.com/ethereumproject/go-ethereum/ethdb" 36 "github.com/ethereumproject/go-ethereum/event" 37 "github.com/ethereumproject/go-ethereum/logger/glog" 38 "github.com/ethereumproject/go-ethereum/rlp" 39 "github.com/hashicorp/golang-lru" 40 "io/ioutil" 41 "strings" 42 ) 43 44 func init() { 45 // Disable any display logs for tests. 46 glog.SetD(0) 47 } 48 49 // GenesisBlockForTesting creates a block in which addr has the given wei balance. 50 // The state trie of the block is written to db. the passed db needs to contain a state root 51 func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block { 52 statedb, err := state.New(common.Hash{}, state.NewDatabase(db)) 53 if err != nil { 54 panic(err) 55 } 56 57 obj := statedb.GetOrNewStateObject(addr) 58 obj.SetBalance(balance) 59 root, err := statedb.CommitTo(db, false) 60 if err != nil { 61 panic(fmt.Sprintf("cannot write state: %v", err)) 62 } 63 64 return types.NewBlock(&types.Header{ 65 Difficulty: big.NewInt(131072), 66 GasLimit: big.NewInt(4712388), 67 Root: root, 68 }, nil, nil, nil) 69 } 70 71 func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain { 72 pow, err := ethash.NewForTesting() 73 if err != nil { 74 t.Fatal(err) 75 } 76 77 var eventMux event.TypeMux 78 if _, err := WriteGenesisBlock(db, DefaultConfigMorden.Genesis); err != nil { 79 t.Fatal(err) 80 } 81 blockchain, err := NewBlockChain(db, testChainConfig(), pow, &eventMux) 82 if err != nil { 83 t.Error("failed creating blockchain:", err) 84 t.FailNow() 85 return nil 86 } 87 88 return blockchain 89 } 90 91 // Test fork of length N starting from block i 92 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { 93 // Copy old chain up to #i into a new db 94 db, blockchain2, err := newCanonical(testChainConfig(), i, full) 95 if err != nil { 96 t.Fatal("could not make new canonical in testFork", err) 97 } 98 // Assert the chains have the same header/block at #i 99 var hash1, hash2 common.Hash 100 if full { 101 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 102 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 103 } else { 104 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 105 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 106 } 107 if hash1 != hash2 { 108 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 109 } 110 // Extend the newly created chain 111 var ( 112 blockChainB []*types.Block 113 headerChainB []*types.Header 114 ) 115 if full { 116 blockChainB = makeBlockChain(blockchain2.config, blockchain2.CurrentBlock(), n, db, forkSeed) 117 if res := blockchain2.InsertChain(blockChainB); res.Error != nil { 118 t.Fatalf("failed to insert forking chain: %v", res.Error) 119 } 120 } else { 121 headerChainB = makeHeaderChain(blockchain2.config, blockchain2.CurrentHeader(), n, db, forkSeed) 122 if res := blockchain2.InsertHeaderChain(headerChainB, 1); res.Error != nil { 123 t.Fatalf("failed to insert forking chain: %v", res.Error) 124 } 125 } 126 // Sanity check that the forked chain can be imported into the original 127 var tdPre, tdPost *big.Int 128 129 if full { 130 tdPre = blockchain.GetTd(blockchain.CurrentBlock().Hash()) 131 if err := testBlockChainImport(blockChainB, blockchain); err != nil { 132 t.Fatalf("failed to import forked block chain: %v", err) 133 } 134 tdPost = blockchain.GetTd(blockChainB[len(blockChainB)-1].Hash()) 135 } else { 136 tdPre = blockchain.GetTd(blockchain.CurrentHeader().Hash()) 137 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 138 t.Fatalf("failed to import forked header chain: %v", err) 139 } 140 tdPost = blockchain.GetTd(headerChainB[len(headerChainB)-1].Hash()) 141 } 142 // Compare the total difficulties of the chains 143 comparator(tdPre, tdPost) 144 } 145 146 // testBlockChainImport tries to process a chain of blocks, writing them into 147 // the database if successful. 148 func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { 149 for _, block := range chain { 150 // Try and process the block 151 err := blockchain.Validator().ValidateBlock(block) 152 if err != nil { 153 if IsKnownBlockErr(err) { 154 continue 155 } 156 return err 157 } 158 statedb, err := state.New(blockchain.GetBlock(block.ParentHash()).Root(), state.NewDatabase(blockchain.chainDb)) 159 if err != nil { 160 return err 161 } 162 receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb) 163 if err != nil { 164 return err 165 } 166 err = blockchain.Validator().ValidateState(block, blockchain.GetBlock(block.ParentHash()), statedb, receipts, usedGas) 167 if err != nil { 168 return err 169 } 170 blockchain.mu.Lock() 171 WriteTd(blockchain.chainDb, block.Hash(), new(big.Int).Add(block.Difficulty(), blockchain.GetTd(block.ParentHash()))) 172 WriteBlock(blockchain.chainDb, block) 173 statedb.CommitTo(blockchain.chainDb, false) 174 blockchain.mu.Unlock() 175 } 176 return nil 177 } 178 179 // testHeaderChainImport tries to process a chain of header, writing them into 180 // the database if successful. 181 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 182 for _, header := range chain { 183 // Try and validate the header 184 if err := blockchain.Validator().ValidateHeader(header, blockchain.GetHeader(header.ParentHash), false); err != nil { 185 return err 186 } 187 // Manually insert the header into the database, but don't reorganise (allows subsequent testing) 188 blockchain.mu.Lock() 189 WriteTd(blockchain.chainDb, header.Hash(), new(big.Int).Add(header.Difficulty, blockchain.GetTd(header.ParentHash))) 190 WriteHeader(blockchain.chainDb, header) 191 blockchain.mu.Unlock() 192 } 193 return nil 194 } 195 196 func loadChain(fn string, t *testing.T) (types.Blocks, error) { 197 fh, err := os.OpenFile(filepath.Join("testdata", fn), os.O_RDONLY, os.ModePerm) 198 if err != nil { 199 return nil, err 200 } 201 defer fh.Close() 202 203 var chain types.Blocks 204 if err := rlp.Decode(fh, &chain); err != nil { 205 return nil, err 206 } 207 208 return chain, nil 209 } 210 211 func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) { 212 res := blockchain.InsertChain(chain) 213 if res.Error != nil { 214 t.Fatal(res.Error) 215 } 216 done <- true 217 } 218 219 func TestLastBlock(t *testing.T) { 220 db, err := ethdb.NewMemDatabase() 221 if err != nil { 222 t.Fatal(err) 223 } 224 225 bchain := theBlockChain(db, t) 226 block := makeBlockChain(bchain.config, bchain.CurrentBlock(), 1, db, 0)[0] 227 bchain.insert(block) 228 if block.Hash() != GetHeadBlockHash(db) { 229 t.Errorf("Write/Get HeadBlockHash failed") 230 } 231 } 232 233 // Tests that given a starting canonical chain of a given size, it can be extended 234 // with various length chains. 235 func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } 236 func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } 237 238 func testExtendCanonical(t *testing.T, full bool) { 239 length := 5 240 241 // Make first chain starting from genesis 242 _, processor, err := newCanonical(testChainConfig(), length, full) 243 if err != nil { 244 t.Fatalf("failed to make new canonical chain: %v", err) 245 } 246 // Define the difficulty comparator 247 better := func(td1, td2 *big.Int) { 248 if td2.Cmp(td1) <= 0 { 249 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 250 } 251 } 252 // Start fork from current height 253 testFork(t, processor, length, 1, full, better) 254 testFork(t, processor, length, 2, full, better) 255 testFork(t, processor, length, 5, full, better) 256 testFork(t, processor, length, 10, full, better) 257 } 258 259 // Tests that given a starting canonical chain of a given size, creating shorter 260 // forks do not take canonical ownership. 261 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } 262 func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } 263 264 func testShorterFork(t *testing.T, full bool) { 265 length := 10 266 267 // Make first chain starting from genesis 268 _, processor, err := newCanonical(testChainConfig(), length, full) 269 if err != nil { 270 t.Fatalf("failed to make new canonical chain: %v", err) 271 } 272 // Define the difficulty comparator 273 worse := func(td1, td2 *big.Int) { 274 if td2.Cmp(td1) >= 0 { 275 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 276 } 277 } 278 // Sum of numbers must be less than `length` for this to be a shorter fork 279 testFork(t, processor, 0, 3, full, worse) 280 testFork(t, processor, 0, 7, full, worse) 281 testFork(t, processor, 1, 1, full, worse) 282 testFork(t, processor, 1, 7, full, worse) 283 testFork(t, processor, 5, 3, full, worse) 284 testFork(t, processor, 5, 4, full, worse) 285 } 286 287 // Tests that given a starting canonical chain of a given size, creating longer 288 // forks do take canonical ownership. 289 func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } 290 func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } 291 292 func testLongerFork(t *testing.T, full bool) { 293 length := 10 294 295 // Make first chain starting from genesis 296 _, processor, err := newCanonical(testChainConfig(), length, full) 297 if err != nil { 298 t.Fatalf("failed to make new canonical chain: %v", err) 299 } 300 // Define the difficulty comparator 301 better := func(td1, td2 *big.Int) { 302 if td2.Cmp(td1) <= 0 { 303 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 304 } 305 } 306 // Sum of numbers must be greater than `length` for this to be a longer fork 307 testFork(t, processor, 0, 11, full, better) 308 testFork(t, processor, 0, 15, full, better) 309 testFork(t, processor, 1, 10, full, better) 310 testFork(t, processor, 1, 12, full, better) 311 testFork(t, processor, 5, 6, full, better) 312 testFork(t, processor, 5, 8, full, better) 313 } 314 315 // Tests that given a starting canonical chain of a given size, creating equal 316 // forks do take canonical ownership. 317 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } 318 func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } 319 320 func testEqualFork(t *testing.T, full bool) { 321 length := 10 322 323 // Make first chain starting from genesis 324 _, processor, err := newCanonical(testChainConfig(), length, full) 325 if err != nil { 326 t.Fatalf("failed to make new canonical chain: %v", err) 327 } 328 // Define the difficulty comparator 329 equal := func(td1, td2 *big.Int) { 330 if td2.Cmp(td1) != 0 { 331 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 332 } 333 } 334 // Sum of numbers must be equal to `length` for this to be an equal fork 335 testFork(t, processor, 0, 10, full, equal) 336 testFork(t, processor, 1, 9, full, equal) 337 testFork(t, processor, 2, 8, full, equal) 338 testFork(t, processor, 5, 5, full, equal) 339 testFork(t, processor, 6, 4, full, equal) 340 testFork(t, processor, 9, 1, full, equal) 341 } 342 343 // Tests that chains missing links do not get accepted by the processor. 344 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } 345 func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } 346 347 func testBrokenChain(t *testing.T, full bool) { 348 // Make chain starting from genesis 349 db, blockchain, err := newCanonical(testChainConfig(), 10, full) 350 if err != nil { 351 t.Fatalf("failed to make new canonical chain: %v", err) 352 } 353 // Create a forked chain, and try to insert with a missing link 354 if full { 355 chain := makeBlockChain(blockchain.config, blockchain.CurrentBlock(), 5, db, forkSeed)[1:] 356 if err := testBlockChainImport(chain, blockchain); err == nil { 357 t.Errorf("broken block chain not reported") 358 } 359 } else { 360 chain := makeHeaderChain(blockchain.config, blockchain.CurrentHeader(), 5, db, forkSeed)[1:] 361 if err := testHeaderChainImport(chain, blockchain); err == nil { 362 t.Errorf("broken header chain not reported") 363 } 364 } 365 } 366 367 func TestChainInsertions(t *testing.T) { 368 t.Skip("Skipped: outdated test files") 369 370 db, err := ethdb.NewMemDatabase() 371 if err != nil { 372 t.Fatal(err) 373 } 374 375 chain1, err := loadChain("valid1", t) 376 if err != nil { 377 t.Fatal(err) 378 } 379 380 chain2, err := loadChain("valid2", t) 381 if err != nil { 382 t.Fatal(err) 383 } 384 385 blockchain := theBlockChain(db, t) 386 387 const max = 2 388 done := make(chan bool, max) 389 390 go insertChain(done, blockchain, chain1, t) 391 go insertChain(done, blockchain, chain2, t) 392 393 for i := 0; i < max; i++ { 394 <-done 395 } 396 397 if chain2[len(chain2)-1].Hash() != blockchain.CurrentBlock().Hash() { 398 t.Error("chain2 is canonical and shouldn't be") 399 } 400 401 if chain1[len(chain1)-1].Hash() != blockchain.CurrentBlock().Hash() { 402 t.Error("chain1 isn't canonical and should be") 403 } 404 } 405 406 func TestChainMultipleInsertions(t *testing.T) { 407 t.Skip("Skipped: outdated test files") 408 409 db, err := ethdb.NewMemDatabase() 410 if err != nil { 411 t.Fatal(err) 412 } 413 414 const max = 4 415 chains := make([]types.Blocks, max) 416 var longest int 417 for i := 0; i < max; i++ { 418 var err error 419 name := "valid" + strconv.Itoa(i+1) 420 chains[i], err = loadChain(name, t) 421 if len(chains[i]) >= len(chains[longest]) { 422 longest = i 423 } 424 t.Log("loaded ", name, " with a length of ", len(chains[i])) 425 if err != nil { 426 t.Fatal(err) 427 } 428 } 429 430 blockchain := theBlockChain(db, t) 431 432 done := make(chan bool, max) 433 for i, chain := range chains { 434 // XXX the go routine would otherwise reference the same (chain[3]) variable and fail 435 i := i 436 chain := chain 437 go func() { 438 insertChain(done, blockchain, chain, t) 439 t.Log(i, "done") 440 }() 441 } 442 443 for i := 0; i < max; i++ { 444 <-done 445 } 446 447 if chains[longest][len(chains[longest])-1].Hash() != blockchain.CurrentBlock().Hash() { 448 t.Error("Invalid canonical chain") 449 } 450 } 451 452 type bproc struct{} 453 454 func (bproc) ValidateBlock(*types.Block) error { return nil } 455 func (bproc) ValidateHeader(*types.Header, *types.Header, bool) error { return nil } 456 func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error { 457 return nil 458 } 459 func (bproc) VerifyUncles(block, parent *types.Block) error { return nil } 460 func (bproc) Process(block *types.Block, statedb *state.StateDB) (types.Receipts, vm.Logs, *big.Int, error) { 461 return nil, nil, nil, nil 462 } 463 464 func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Header { 465 blocks := makeBlockChainWithDiff(genesis, d, seed) 466 headers := make([]*types.Header, len(blocks)) 467 for i, block := range blocks { 468 headers[i] = block.Header() 469 } 470 return headers 471 } 472 473 func makeBlockChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block { 474 var chain []*types.Block 475 for i, difficulty := range d { 476 header := &types.Header{ 477 Coinbase: common.Address{seed}, 478 Number: big.NewInt(int64(i + 1)), 479 Difficulty: big.NewInt(int64(difficulty)), 480 UncleHash: types.EmptyUncleHash, 481 TxHash: types.EmptyRootHash, 482 ReceiptHash: types.EmptyRootHash, 483 } 484 if i == 0 { 485 header.ParentHash = genesis.Hash() 486 } else { 487 header.ParentHash = chain[i-1].Hash() 488 } 489 block := types.NewBlockWithHeader(header) 490 chain = append(chain, block) 491 } 492 return chain 493 } 494 495 func chm(t testing.TB, genesis *types.Block, db ethdb.Database) *BlockChain { 496 var eventMux event.TypeMux 497 config := testChainConfig() 498 bc := &BlockChain{ 499 chainDb: db, 500 genesisBlock: genesis, 501 eventMux: &eventMux, 502 pow: FakePow{}, 503 config: config, 504 } 505 valFn := func() HeaderValidator { return bc.Validator() } 506 var err error 507 bc.hc, err = NewHeaderChain(db, config, bc.eventMux, valFn, bc.getProcInterrupt) 508 if err != nil { 509 t.Fatal(err) 510 } 511 bc.bodyCache, err = lru.New(100) 512 if err != nil { 513 t.Fatal(err) 514 } 515 bc.bodyRLPCache, err = lru.New(100) 516 if err != nil { 517 t.Fatal(err) 518 } 519 bc.blockCache, err = lru.New(100) 520 if err != nil { 521 t.Fatal(err) 522 } 523 bc.futureBlocks, err = lru.New(100) 524 if err != nil { 525 t.Fatal(err) 526 } 527 bc.SetValidator(bproc{}) 528 bc.SetProcessor(bproc{}) 529 bc.ResetWithGenesisBlock(genesis) 530 531 return bc 532 } 533 534 // Tests that reorganising a long difficult chain after a short easy one 535 // overwrites the canonical numbers and links in the database. 536 func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) } 537 func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) } 538 539 func testReorgLong(t *testing.T, full bool) { 540 testReorg(t, []int{1, 2, 4}, []int{1, 2, 3, 4}, 10, full) 541 } 542 543 // Tests that reorganising a short difficult chain after a long easy one 544 // overwrites the canonical numbers and links in the database. 545 func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) } 546 func TestReorgShortBlocks(t *testing.T) { testReorgShort(t, true) } 547 548 func testReorgShort(t *testing.T, full bool) { 549 testReorg(t, []int{1, 2, 3, 4}, []int{1, 10}, 11, full) 550 } 551 552 func testReorg(t *testing.T, first, second []int, td int64, full bool) { 553 // Create a pristine block chain 554 db, err := ethdb.NewMemDatabase() 555 if err != nil { 556 t.Fatal(err) 557 } 558 genesis, err := WriteGenesisBlock(db, DefaultConfigMorden.Genesis) 559 if err != nil { 560 t.Fatal(err) 561 } 562 bc := chm(t, genesis, db) 563 564 // Insert an easy and a difficult chain afterwards 565 if full { 566 bc.InsertChain(makeBlockChainWithDiff(genesis, first, 11)) 567 bc.InsertChain(makeBlockChainWithDiff(genesis, second, 22)) 568 } else { 569 bc.InsertHeaderChain(makeHeaderChainWithDiff(genesis, first, 11), 1) 570 bc.InsertHeaderChain(makeHeaderChainWithDiff(genesis, second, 22), 1) 571 } 572 // Check that the chain is valid number and link wise 573 if full { 574 prev := bc.CurrentBlock() 575 for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) { 576 if prev.ParentHash() != block.Hash() { 577 t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) 578 } 579 } 580 } else { 581 prev := bc.CurrentHeader() 582 for header := bc.GetHeaderByNumber(bc.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, bc.GetHeaderByNumber(header.Number.Uint64()-1) { 583 if prev.ParentHash != header.Hash() { 584 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 585 } 586 } 587 } 588 // Make sure the chain total difficulty is the correct one 589 want := new(big.Int).Add(genesis.Difficulty(), big.NewInt(td)) 590 if full { 591 if have := bc.GetTd(bc.CurrentBlock().Hash()); have.Cmp(want) != 0 { 592 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 593 } 594 } else { 595 if have := bc.GetTd(bc.CurrentHeader().Hash()); have.Cmp(want) != 0 { 596 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 597 } 598 } 599 } 600 601 func TestInsertHeaderChainBadHash(t *testing.T) { 602 db, err := ethdb.NewMemDatabase() 603 if err != nil { 604 t.Fatal(err) 605 } 606 genesis, err := WriteGenesisBlock(db, DefaultConfigMorden.Genesis) 607 if err != nil { 608 t.Fatal(err) 609 } 610 headers := makeHeaderChainWithDiff(genesis, []int{1, 2, 4}, 10) 611 bc := chm(t, genesis, db) 612 bc.config.BadHashes = []*BadHash{ 613 { 614 Block: headers[2].Number, 615 Hash: headers[2].Hash(), 616 }, 617 } 618 619 res := bc.InsertHeaderChain(headers, 1) 620 if res.Error != ErrHashKnownBad { 621 t.Errorf("got error %#v, want %#v", res.Error, ErrHashKnownBad) 622 } 623 } 624 625 func TestInsertChainBadHash(t *testing.T) { 626 db, err := ethdb.NewMemDatabase() 627 if err != nil { 628 t.Fatal(err) 629 } 630 genesis, err := WriteGenesisBlock(db, DefaultConfigMorden.Genesis) 631 if err != nil { 632 t.Fatal(err) 633 } 634 blocks := makeBlockChainWithDiff(genesis, []int{1, 2, 4}, 10) 635 bc := chm(t, genesis, db) 636 bc.config.BadHashes = []*BadHash{ 637 { 638 Block: blocks[2].Number(), 639 Hash: blocks[2].Header().Hash(), 640 }, 641 } 642 643 res := bc.InsertChain(blocks) 644 if res.Error != ErrHashKnownBad { 645 t.Errorf("got error %#v, want %#v", res.Error, ErrHashKnownBad) 646 } 647 } 648 649 // Tests that bad hashes are detected on boot, and the chain rolled back to a 650 // good state prior to the bad hash. 651 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } 652 func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } 653 654 func testReorgBadHashes(t *testing.T, full bool) { 655 // Create a pristine block chain 656 db, err := ethdb.NewMemDatabase() 657 if err != nil { 658 t.Fatal(err) 659 } 660 genesis, err := WriteGenesisBlock(db, DefaultConfigMorden.Genesis) 661 if err != nil { 662 t.Fatal(err) 663 } 664 bc := chm(t, genesis, db) 665 666 // Create a chain, import and ban afterwards 667 headers := makeHeaderChainWithDiff(genesis, []int{1, 2, 3, 4}, 10) 668 blocks := makeBlockChainWithDiff(genesis, []int{1, 2, 3, 4}, 10) 669 670 if full { 671 if res := bc.InsertChain(blocks); res.Error != nil { 672 t.Fatalf("failed to import blocks: %v", res.Error) 673 } 674 if bc.CurrentBlock().Hash() != blocks[3].Hash() { 675 t.Errorf("last block hash mismatch: have: %x, want %x", bc.CurrentBlock().Hash(), blocks[3].Header().Hash()) 676 } 677 bc.config.BadHashes = []*BadHash{ 678 { 679 Block: blocks[3].Number(), 680 Hash: blocks[3].Header().Hash(), 681 }, 682 } 683 defer func() { bc.config.BadHashes = []*BadHash{} }() 684 } else { 685 if res := bc.InsertHeaderChain(headers, 1); res.Error != nil { 686 t.Fatalf("failed to import headers: %v", res.Error) 687 } 688 if bc.CurrentHeader().Hash() != headers[3].Hash() { 689 t.Errorf("last header hash mismatch: have: %x, want %x", bc.CurrentHeader().Hash(), headers[3].Hash()) 690 } 691 bc.config.BadHashes = []*BadHash{ 692 { 693 Block: headers[3].Number, 694 Hash: headers[3].Hash(), 695 }, 696 } 697 defer func() { bc.config.BadHashes = []*BadHash{} }() 698 } 699 // Create a new chain manager and check it rolled back the state 700 ncm, err := NewBlockChain(db, bc.config, FakePow{}, new(event.TypeMux)) 701 if err != nil { 702 t.Fatalf("failed to create new chain manager: %v", err) 703 } 704 if full { 705 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 706 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 707 } 708 if blocks[2].Header().GasLimit.Cmp(ncm.GasLimit()) != 0 { 709 t.Errorf("last block gasLimit mismatch: have: %x, want %x", ncm.GasLimit(), blocks[2].Header().GasLimit) 710 } 711 } else { 712 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 713 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 714 } 715 } 716 } 717 718 // Tests chain insertions in the face of one entity containing an invalid nonce. 719 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } 720 func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } 721 722 func testInsertNonceError(t *testing.T, full bool) { 723 for i := 1; i < 25 && !t.Failed(); i++ { 724 // Create a pristine chain and database 725 db, blockchain, err := newCanonical(testChainConfig(), 0, full) 726 if err != nil { 727 t.Fatalf("failed to create pristine chain: %v", err) 728 } 729 // Create and insert a chain with a failing nonce 730 var ( 731 failAt int 732 failRes int 733 failNum uint64 734 failHash common.Hash 735 ) 736 if full { 737 blocks := makeBlockChain(blockchain.config, blockchain.CurrentBlock(), i, db, 0) 738 739 failAt = rand.Int() % len(blocks) 740 failNum = blocks[failAt].NumberU64() 741 failHash = blocks[failAt].Hash() 742 743 blockchain.pow = failPow{failNum} 744 745 res := blockchain.InsertChain(blocks) 746 failRes, err = res.Index, res.Error 747 } else { 748 headers := makeHeaderChain(blockchain.config, blockchain.CurrentHeader(), i, db, 0) 749 750 failAt = rand.Int() % len(headers) 751 failNum = headers[failAt].Number.Uint64() 752 failHash = headers[failAt].Hash() 753 754 blockchain.pow = failPow{failNum} 755 blockchain.validator = NewBlockValidator(testChainConfig(), blockchain, failPow{failNum}) 756 757 res := blockchain.InsertHeaderChain(headers, 1) 758 failRes, err = res.Index, res.Error 759 } 760 // Check that the returned error indicates the nonce failure. 761 if failRes != failAt { 762 t.Errorf("test %d: failure index mismatch: have %d, want %d", i, failRes, failAt) 763 } 764 if !IsBlockNonceErr(err) { 765 t.Fatalf("test %d: error mismatch: have %v, want nonce error %T", i, err, err) 766 } 767 nerr := err.(*BlockNonceErr) 768 if nerr.Number.Uint64() != failNum { 769 t.Errorf("test %d: number mismatch: have %v, want %v", i, nerr.Number, failNum) 770 } 771 if nerr.Hash != failHash { 772 t.Errorf("test %d: hash mismatch: have %x, want %x", i, nerr.Hash[:4], failHash[:4]) 773 } 774 // Check that all no blocks after the failing block have been inserted. 775 for j := 0; j < i-failAt; j++ { 776 if full { 777 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 778 t.Errorf("test %d: invalid block in chain: %v", i, block) 779 } 780 } else { 781 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 782 t.Errorf("test %d: invalid header in chain: %v", i, header) 783 } 784 } 785 } 786 } 787 } 788 789 // Tests that fast importing a block chain produces the same chain data as the 790 // classical full block processing. 791 func TestFastVsFullChains(t *testing.T) { 792 // Configure and generate a sample block chain 793 gendb, err := ethdb.NewMemDatabase() 794 if err != nil { 795 t.Fatal(err) 796 } 797 key, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 798 if err != nil { 799 t.Fatal(err) 800 } 801 var ( 802 address = crypto.PubkeyToAddress(key.PublicKey) 803 funds = big.NewInt(1000000000) 804 genesis = GenesisBlockForTesting(gendb, address, funds) 805 signer = types.NewChainIdSigner(big.NewInt(63)) 806 config = MakeDiehardChainConfig() 807 ) 808 blocks, receipts := GenerateChain(config, genesis, gendb, 1024, func(i int, block *BlockGen) { 809 block.SetCoinbase(common.Address{0x00}) 810 811 // If the block number is multiple of 3, send a few bonus transactions to the miner 812 if i%3 == 2 { 813 for j := 0; j < i%4+1; j++ { 814 tx, err := types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), TxGas, nil, nil).WithSigner(signer).SignECDSA(key) 815 if err != nil { 816 panic(err) 817 } 818 block.AddTx(tx) 819 } 820 } 821 // If the block number is a multiple of 5, add a few bonus uncles to the block 822 if i%5 == 5 { 823 block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))}) 824 } 825 }) 826 // Import the chain as an archive node for the comparison baseline 827 archiveDb, err := ethdb.NewMemDatabase() 828 if err != nil { 829 t.Fatal(err) 830 } 831 WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds}) 832 833 archive, err := NewBlockChain(archiveDb, config, FakePow{}, new(event.TypeMux)) 834 if err != nil { 835 t.Fatal(err) 836 } 837 838 if res := archive.InsertChain(blocks); res.Error != nil { 839 t.Fatalf("failed to process block %d: %v", res.Index, res.Error) 840 } 841 // Fast import the chain as a non-archive node to test 842 fastDb, err := ethdb.NewMemDatabase() 843 if err != nil { 844 t.Fatal(err) 845 } 846 WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds}) 847 fast, err := NewBlockChain(fastDb, config, FakePow{}, new(event.TypeMux)) 848 if err != nil { 849 t.Fatal(err) 850 } 851 852 headers := make([]*types.Header, len(blocks)) 853 for i, block := range blocks { 854 headers[i] = block.Header() 855 } 856 if res := fast.InsertHeaderChain(headers, 1); res.Error != nil { 857 t.Fatalf("failed to insert header %d: %v", res.Index, res.Error) 858 } 859 if res := fast.InsertReceiptChain(blocks, receipts); res.Error != nil { 860 t.Fatalf("failed to insert receipt %d: %v", res.Index, res.Error) 861 } 862 // Iterate over all chain data components, and cross reference 863 for i := 0; i < len(blocks); i++ { 864 num, hash := blocks[i].NumberU64(), blocks[i].Hash() 865 866 if ftd, atd := fast.GetTd(hash), archive.GetTd(hash); ftd.Cmp(atd) != 0 { 867 t.Errorf("block #%d [%x]: td mismatch: have %v, want %v", num, hash, ftd, atd) 868 } 869 if fheader, aheader := fast.GetHeader(hash), archive.GetHeader(hash); fheader.Hash() != aheader.Hash() { 870 t.Errorf("block #%d [%x]: header mismatch: have %v, want %v", num, hash, fheader, aheader) 871 } 872 if fblock, ablock := fast.GetBlock(hash), archive.GetBlock(hash); fblock.Hash() != ablock.Hash() { 873 t.Errorf("block #%d [%x]: block mismatch: have %v, want %v", num, hash, fblock, ablock) 874 } else if types.DeriveSha(fblock.Transactions()) != types.DeriveSha(ablock.Transactions()) { 875 t.Errorf("block #%d [%x]: transactions mismatch: have %v, want %v", num, hash, fblock.Transactions(), ablock.Transactions()) 876 } else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(ablock.Uncles()) { 877 t.Errorf("block #%d [%x]: uncles mismatch: have %v, want %v", num, hash, fblock.Uncles(), ablock.Uncles()) 878 } 879 if freceipts, areceipts := GetBlockReceipts(fastDb, hash), GetBlockReceipts(archiveDb, hash); types.DeriveSha(freceipts) != types.DeriveSha(areceipts) { 880 t.Errorf("block #%d [%x]: receipts mismatch: have %v, want %v", num, hash, freceipts, areceipts) 881 } 882 } 883 // Check that the canonical chains are the same between the databases 884 for i := 0; i < len(blocks)+1; i++ { 885 if fhash, ahash := GetCanonicalHash(fastDb, uint64(i)), GetCanonicalHash(archiveDb, uint64(i)); fhash != ahash { 886 t.Errorf("block #%d: canonical hash mismatch: have %v, want %v", i, fhash, ahash) 887 } 888 } 889 } 890 891 func TestFastVsFullChainsATXI(t *testing.T) { 892 archiveDir, e := ioutil.TempDir("", "archive-") 893 if e != nil { 894 t.Fatal(e) 895 } 896 fastDir, e := ioutil.TempDir("", "fast-") 897 if e != nil { 898 t.Fatal(e) 899 } 900 defer os.RemoveAll(archiveDir) 901 defer os.RemoveAll(fastDir) 902 903 // Create the dbs 904 // 905 archiveDb, err := ethdb.NewLDBDatabase(archiveDir, 10, 100) 906 if err != nil { 907 t.Fatal(err) 908 } 909 fastDb, err := ethdb.NewLDBDatabase(fastDir, 10, 100) 910 if err != nil { 911 t.Fatal(err) 912 } 913 914 MinGasLimit = big.NewInt(125000) 915 916 key1, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 917 if err != nil { 918 t.Fatal(err) 919 } 920 key2, err := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 921 if err != nil { 922 t.Fatal(err) 923 } 924 925 var ( 926 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 927 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 928 signer = types.NewChainIdSigner(big.NewInt(63)) 929 dbs = []ethdb.Database{archiveDb, fastDb} 930 config = MakeDiehardChainConfig() 931 ) 932 933 for i, db := range dbs { 934 t1, err := types.NewTransaction(0, addr2, big.NewInt(1000), TxGas, nil, nil).WithSigner(signer).SignECDSA(key1) 935 if err != nil { 936 t.Fatal(err) 937 } 938 t2, err := types.NewTransaction(1, addr2, big.NewInt(1000), TxGas, nil, nil).WithSigner(signer).SignECDSA(key1) 939 if err != nil { 940 t.Fatal(err) 941 } 942 t3, err := types.NewTransaction(0, addr1, big.NewInt(1000), TxGas, nil, nil).WithSigner(signer).SignECDSA(key2) 943 if err != nil { 944 t.Fatal(err) 945 } 946 genesis := WriteGenesisBlockForTesting(db, 947 GenesisAccount{addr1, big.NewInt(1000000)}, 948 GenesisAccount{addr2, big.NewInt(1000000)}, 949 ) 950 blocks, receipts := GenerateChain(config, genesis, db, 3, func(i int, gen *BlockGen) { 951 if i == 0 { 952 gen.AddTx(t1) 953 } 954 if i == 1 { 955 gen.AddTx(t2) 956 } 957 if i == 2 { 958 gen.AddTx(t3) 959 } 960 }) 961 962 blockchain, err := NewBlockChain(db, config, FakePow{}, new(event.TypeMux)) 963 if err != nil { 964 t.Fatal(err) 965 } 966 // turn on atxi 967 blockchain.SetAtxi(&AtxiT{Db: db}) 968 if i == 0 { 969 if res := blockchain.InsertChain(blocks); res.Error != nil { 970 t.Fatalf("failed to process block %d: %v", res.Index, res.Error) 971 } 972 } else { 973 headers := make([]*types.Header, len(blocks)) 974 for i, block := range blocks { 975 headers[i] = block.Header() 976 } 977 if res := blockchain.InsertHeaderChain(headers, 1); res.Error != nil { 978 t.Fatalf("failed to insert header %d: %v", res.Index, res.Error) 979 } 980 if res := blockchain.InsertReceiptChain(blocks, receipts); res.Error != nil { 981 t.Fatalf("failed to insert receipt %d: %v", res.Index, res.Error) 982 } 983 } 984 985 out, _ := GetAddrTxs(db, addr1, 0, 0, "", "", -1, -1, false) 986 if len(out) != 3 { 987 t.Errorf("[%d] got: %v, want: %v", i, len(out), 3) 988 } 989 990 // method should return an error if pagination params are invalid 991 _, err = GetAddrTxs(db, addr1, 0, 0, "", "", 2, 1, false) 992 if err == nil { 993 t.Errorf("[%d] got: %v, want: %v", i, err, errAtxiInvalidUse) 994 } 995 996 out, _ = GetAddrTxs(db, addr1, 0, 0, "from", "", -1, -1, false) 997 if len(out) != 2 { 998 t.Errorf("[%d] got: %v, want: %v", i, len(out), 2) 999 } 1000 out, _ = GetAddrTxs(db, addr1, 0, 0, "to", "", -1, -1, false) 1001 if len(out) != 1 { 1002 t.Errorf("[%d] got: %v, want: %v", i, len(out), 1) 1003 } 1004 out, _ = GetAddrTxs(db, addr2, 0, 0, "", "", -1, -1, false) 1005 if len(out) != 3 { 1006 t.Errorf("[%d] got: %v, want: %v", i, len(out), 3) 1007 } 1008 out, _ = GetAddrTxs(db, addr2, 3, 3, "", "", -1, -1, false) 1009 if len(out) != 1 { 1010 t.Errorf("[%d] got: %v, want: %v", i, len(out), 1) 1011 } 1012 } 1013 } 1014 1015 func TestRmAddrTx(t *testing.T) { 1016 archiveDir, e := ioutil.TempDir("", "archive-") 1017 if e != nil { 1018 t.Fatal(e) 1019 } 1020 defer os.RemoveAll(archiveDir) 1021 1022 // Create the dbs 1023 // 1024 db, err := ethdb.NewLDBDatabase(archiveDir, 10, 100) 1025 if err != nil { 1026 t.Fatal(err) 1027 } 1028 1029 MinGasLimit = big.NewInt(125000) 1030 1031 key1, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1032 if err != nil { 1033 t.Fatal(err) 1034 } 1035 key2, err := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1036 if err != nil { 1037 t.Fatal(err) 1038 } 1039 1040 var ( 1041 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1042 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 1043 signer = types.NewChainIdSigner(big.NewInt(63)) 1044 config = MakeDiehardChainConfig() 1045 ) 1046 1047 t1, err := types.NewTransaction(0, addr2, big.NewInt(1000), TxGas, nil, nil).WithSigner(signer).SignECDSA(key1) 1048 if err != nil { 1049 t.Fatal(err) 1050 } 1051 t2, err := types.NewTransaction(1, addr2, big.NewInt(1000), TxGas, nil, nil).WithSigner(signer).SignECDSA(key1) 1052 if err != nil { 1053 t.Fatal(err) 1054 } 1055 t3, err := types.NewTransaction(0, addr1, big.NewInt(1000), TxGas, nil, nil).WithSigner(signer).SignECDSA(key2) 1056 if err != nil { 1057 t.Fatal(err) 1058 } 1059 genesis := WriteGenesisBlockForTesting(db, 1060 GenesisAccount{addr1, big.NewInt(1000000)}, 1061 GenesisAccount{addr2, big.NewInt(1000000)}, 1062 ) 1063 blocks, _ := GenerateChain(config, genesis, db, 3, func(i int, gen *BlockGen) { 1064 if i == 0 { 1065 gen.AddTx(t1) 1066 } 1067 if i == 1 { 1068 gen.AddTx(t2) 1069 } 1070 if i == 2 { 1071 gen.AddTx(t3) 1072 } 1073 }) 1074 1075 blockchain, err := NewBlockChain(db, config, FakePow{}, new(event.TypeMux)) 1076 if err != nil { 1077 t.Fatal(err) 1078 } 1079 // turn on atxi 1080 blockchain.SetAtxi(&AtxiT{Db: db}) 1081 1082 if res := blockchain.InsertChain(blocks); res.Error != nil { 1083 t.Fatalf("failed to process block %d: %v", res.Index, res.Error) 1084 } 1085 1086 out, _ := GetAddrTxs(db, addr1, 0, 0, "", "", -1, -1, false) 1087 if len(out) != 3 { 1088 t.Errorf("got: %v, want: %v", len(out), 3) 1089 } 1090 if err := RmAddrTx(db, t1); err != nil { 1091 t.Fatal(err) 1092 } 1093 out, _ = GetAddrTxs(db, addr1, 0, 0, "", "", -1, -1, false) 1094 if len(out) != 2 { 1095 t.Errorf("got: %v, want: %v", len(out), 2) 1096 } 1097 } 1098 1099 // Tests that various import methods move the chain head pointers to the correct 1100 // positions. 1101 func TestLightVsFastVsFullChainHeads(t *testing.T) { 1102 // Configure and generate a sample block chain 1103 gendb, err := ethdb.NewMemDatabase() 1104 if err != nil { 1105 t.Fatal(err) 1106 } 1107 key, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1108 if err != nil { 1109 t.Fatal(err) 1110 } 1111 var ( 1112 address = crypto.PubkeyToAddress(key.PublicKey) 1113 funds = big.NewInt(1000000000) 1114 genesis = GenesisBlockForTesting(gendb, address, funds) 1115 ) 1116 height := uint64(1024) 1117 blocks, receipts := GenerateChain(MakeChainConfig(), genesis, gendb, int(height), nil) 1118 1119 // Configure a subchain to roll back 1120 remove := []common.Hash{} 1121 for _, block := range blocks[height/2:] { 1122 remove = append(remove, block.Hash()) 1123 } 1124 // Create a small assertion method to check the three heads 1125 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 1126 if num := chain.CurrentBlock().NumberU64(); num != block { 1127 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 1128 } 1129 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 1130 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 1131 } 1132 if num := chain.CurrentHeader().Number.Uint64(); num != header { 1133 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 1134 } 1135 } 1136 // Import the chain as an archive node and ensure all pointers are updated 1137 archiveDb, err := ethdb.NewMemDatabase() 1138 if err != nil { 1139 t.Fatal(err) 1140 } 1141 WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds}) 1142 1143 archive, err := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux)) 1144 if err != nil { 1145 t.Fatal(err) 1146 } 1147 1148 if res := archive.InsertChain(blocks); res.Error != nil { 1149 t.Fatalf("failed to process block %d: %v", res.Index, res.Error) 1150 } 1151 assert(t, "archive", archive, height, height, height) 1152 archive.Rollback(remove) 1153 assert(t, "archive", archive, height/2, height/2, height/2) 1154 1155 // Import the chain as a non-archive node and ensure all pointers are updated 1156 fastDb, err := ethdb.NewMemDatabase() 1157 if err != nil { 1158 t.Fatal(err) 1159 } 1160 WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds}) 1161 fast, err := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux)) 1162 if err != nil { 1163 t.Fatal(err) 1164 } 1165 1166 headers := make([]*types.Header, len(blocks)) 1167 for i, block := range blocks { 1168 headers[i] = block.Header() 1169 } 1170 if res := fast.InsertHeaderChain(headers, 1); res.Error != nil { 1171 t.Fatalf("failed to insert header %d: %v", res.Index, res.Error) 1172 } 1173 if res := fast.InsertReceiptChain(blocks, receipts); res.Error != nil { 1174 t.Fatalf("failed to insert receipt %d: %v", res.Index, res.Error) 1175 } 1176 assert(t, "fast", fast, height, height, 0) 1177 fast.Rollback(remove) 1178 assert(t, "fast", fast, height/2, height/2, 0) 1179 1180 // Import the chain as a light node and ensure all pointers are updated 1181 lightDb, err := ethdb.NewMemDatabase() 1182 if err != nil { 1183 t.Fatal(err) 1184 } 1185 WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds}) 1186 light, err := NewBlockChain(lightDb, testChainConfig(), FakePow{}, new(event.TypeMux)) 1187 if err != nil { 1188 t.Fatal(err) 1189 } 1190 1191 if res := light.InsertHeaderChain(headers, 1); res.Error != nil { 1192 t.Fatalf("failed to insert header %d: %v", res.Index, res.Error) 1193 } 1194 assert(t, "light", light, height, 0, 0) 1195 light.Rollback(remove) 1196 assert(t, "light", light, height/2, 0, 0) 1197 } 1198 1199 // Tests that chain reorganisations handle transaction removals and reinsertions. 1200 func TestChainTxReorgs(t *testing.T) { 1201 db, err := ethdb.NewMemDatabase() 1202 if err != nil { 1203 t.Fatal(err) 1204 } 1205 testChainTxReorgs(t, db, false) 1206 } 1207 1208 func TestChainTxReorgsAtxi(t *testing.T) { 1209 p, err := ioutil.TempDir("", "test-reorg-atxi-") 1210 if err != nil { 1211 t.Fatal(err) 1212 } 1213 defer os.RemoveAll(p) 1214 1215 db, err := ethdb.NewLDBDatabase(p, 10, 100) 1216 if err != nil { 1217 t.Fatal(err) 1218 } 1219 testChainTxReorgs(t, db, true) 1220 } 1221 1222 func testChainTxReorgs(t *testing.T, db ethdb.Database, withATXI bool) { 1223 MinGasLimit = big.NewInt(125000) 1224 1225 key1, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1226 if err != nil { 1227 t.Fatal(err) 1228 } 1229 key2, err := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1230 if err != nil { 1231 t.Fatal(err) 1232 } 1233 key3, err := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 1234 if err != nil { 1235 t.Fatal(err) 1236 } 1237 1238 var ( 1239 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1240 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 1241 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 1242 signer = types.NewChainIdSigner(big.NewInt(63)) 1243 ) 1244 genesis := WriteGenesisBlockForTesting(db, 1245 GenesisAccount{addr1, big.NewInt(1000000)}, 1246 GenesisAccount{addr2, big.NewInt(1000000)}, 1247 GenesisAccount{addr3, big.NewInt(1000000)}, 1248 ) 1249 // Create two transactions shared between the chains: 1250 // addr1 -> addr2 1251 // - postponed: transaction included at a later block in the forked chain 1252 // - swapped: transaction included at the same block number in the forked chain 1253 postponed, err := types.NewTransaction(0, addr2, big.NewInt(1000), TxGas, nil, nil).WithSigner(signer).SignECDSA(key1) 1254 if err != nil { 1255 t.Fatal(err) 1256 } 1257 swapped, err := types.NewTransaction(1, addr2, big.NewInt(1001), TxGas, nil, nil).WithSigner(signer).SignECDSA(key1) 1258 if err != nil { 1259 t.Fatal(err) 1260 } 1261 1262 // Create two transactions that will be dropped by the forked chain: 1263 // addr2 -> addr3 1264 // - pastDrop: transaction dropped retroactively from a past block 1265 // - freshDrop: transaction dropped exactly at the block where the reorg is detected 1266 var pastDrop, freshDrop *types.Transaction 1267 1268 // Create three transactions that will be added in the forked chain: 1269 // addr3 -> addr1 1270 // - pastAdd: transaction added before the reorganization is detected 1271 // - freshAdd: transaction added at the exact block the reorg is detected 1272 // - futureAdd: transaction added after the reorg has already finished 1273 var pastAdd, freshAdd, futureAdd *types.Transaction 1274 1275 // ATXI tallies, (means) will be removed 1276 // addr1: 2f+3t 1277 // addr2: 2t+(2f) 1278 // addr3: (2t)+3f 1279 1280 chainConfig := MakeDiehardChainConfig() 1281 chain, _ := GenerateChain(chainConfig, genesis, db, 3, func(i int, gen *BlockGen) { 1282 switch i { 1283 case 0: 1284 pastDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1002), TxGas, nil, nil).WithSigner(signer).SignECDSA(key2) 1285 1286 gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point 1287 gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork 1288 1289 case 2: 1290 freshDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1003), TxGas, nil, nil).WithSigner(signer).SignECDSA(key2) 1291 1292 gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point 1293 gen.AddTx(swapped) // This transaction will be swapped out at the exact height 1294 1295 gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain 1296 } 1297 }) 1298 1299 // Import the chain. This runs all block validation rules. 1300 evmux := &event.TypeMux{} 1301 blockchain, err := NewBlockChain(db, chainConfig, FakePow{}, evmux) 1302 if err != nil { 1303 t.Fatal(err) 1304 } 1305 if withATXI { 1306 blockchain.SetAtxi(&AtxiT{Db: db}) 1307 } 1308 if res := blockchain.InsertChain(chain); res.Error != nil { 1309 t.Fatalf("failed to insert original chain[%d]: %v", res.Index, res.Error) 1310 } 1311 1312 // overwrite the old chain 1313 chain, _ = GenerateChain(chainConfig, genesis, db, 5, func(i int, gen *BlockGen) { 1314 switch i { 1315 case 0: 1316 pastAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr1, big.NewInt(1004), TxGas, nil, nil).WithSigner(signer).SignECDSA(key3) 1317 gen.AddTx(pastAdd) // This transaction needs to be injected during reorg 1318 1319 case 2: 1320 gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain 1321 gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain 1322 1323 freshAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr1, big.NewInt(1005), TxGas, nil, nil).WithSigner(signer).SignECDSA(key3) 1324 gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time 1325 1326 case 3: 1327 futureAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr1, big.NewInt(1006), TxGas, nil, nil).WithSigner(signer).SignECDSA(key3) 1328 gen.AddTx(futureAdd) // This transaction will be added after a full reorg 1329 } 1330 }) 1331 if res := blockchain.InsertChain(chain); res.Error != nil { 1332 t.Fatalf("failed to insert forked chain: %v", res.Error) 1333 } 1334 1335 // Conveniently grouped 1336 txsRemoved := types.Transactions{pastDrop, freshDrop} 1337 txsAdded := types.Transactions{pastAdd, freshAdd, futureAdd} 1338 txsShared := types.Transactions{postponed, swapped} 1339 txsAll := types.Transactions{pastDrop, freshDrop, pastAdd, freshAdd, futureAdd, postponed, swapped} 1340 1341 // removed tx 1342 for i, tx := range txsRemoved { 1343 if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn != nil { 1344 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 1345 } 1346 if GetReceipt(db, tx.Hash()) != nil { 1347 t.Errorf("drop %d: receipt found while shouldn't have been", i) 1348 } 1349 } 1350 // added tx 1351 for i, tx := range txsAdded { 1352 if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn == nil { 1353 t.Errorf("add %d: expected tx to be found", i) 1354 } 1355 if GetReceipt(db, tx.Hash()) == nil { 1356 t.Errorf("add %d: expected receipt to be found", i) 1357 } 1358 } 1359 // shared tx 1360 for i, tx := range txsShared { 1361 if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn == nil { 1362 t.Errorf("share %d: expected tx to be found", i) 1363 } 1364 if GetReceipt(db, tx.Hash()) == nil { 1365 t.Errorf("share %d: expected receipt to be found", i) 1366 } 1367 } 1368 1369 // ATXI checks 1370 if !withATXI { 1371 return 1372 } 1373 txsh1, _ := GetAddrTxs(db, addr1, 0, 0, "", "", -1, -1, false) 1374 txsh2, _ := GetAddrTxs(db, addr2, 0, 0, "", "", -1, -1, false) 1375 txsh3, _ := GetAddrTxs(db, addr3, 0, 0, "", "", -1, -1, false) 1376 1377 allAtxis := txsh1 1378 allAtxis = append(allAtxis, txsh2...) 1379 allAtxis = append(allAtxis, txsh3...) 1380 1381 // Ensure a transaction exists for each atxi hash 1382 for _, x := range allAtxis { 1383 if tx, _, _, _ := GetTransaction(db, common.HexToHash(x)); tx == nil { 1384 t.Error("atxi not removed") 1385 } 1386 } 1387 1388 // Ensure no duplicate tx hashes returned 1389 DUPECHECK: 1390 for i, l := range [][]string{txsh1, txsh2, txsh3} { 1391 j := strings.Join(l, "") 1392 for _, h := range l { 1393 if strings.Count(j, h[:8]) > 1 { 1394 // show offending tx 1395 offendingTxN := new(big.Int) 1396 for _, x := range txsAll { 1397 if x.Hash().Hex() == h { 1398 offendingTxN.Set(x.Value()) // use unique value as a way to identify offender 1399 break 1400 } 1401 } 1402 t.Log(strings.Join(l, "\n")) 1403 t.Errorf("[%d] duplicate tx hash (%v)", i, offendingTxN) 1404 break DUPECHECK 1405 } 1406 } 1407 1408 } 1409 1410 // Check magnitude; 2 atxis per canonical tx (to & from) 1411 wantMag := (len(txsAdded) + len(txsShared)) * 2 1412 if len(allAtxis) != wantMag { 1413 t.Errorf("got: %v, want: %v", len(allAtxis), wantMag) 1414 } 1415 } 1416 1417 func TestLogReorgs(t *testing.T) { 1418 // This test itself is a little bit incorrect. Below, 1419 // MakeDiehardChainConfig would make a chain configuration that 1420 // only contains EIP160, and bypass EIP150 and Homestead. We never 1421 // have any chain like this exist in real world, so SputnikVM does 1422 // not contain a patch for this. As a result, it cannot figure out 1423 // a correct patch to run. So we bypass this test when running 1424 // with `UseSputnikVM`. 1425 if UseSputnikVM == "true" { 1426 return 1427 } 1428 1429 MinGasLimit = big.NewInt(125000) 1430 1431 key1, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1432 if err != nil { 1433 t.Fatal(err) 1434 } 1435 addr1 := crypto.PubkeyToAddress(key1.PublicKey) 1436 // this code generates a log 1437 code := common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 1438 signer := types.NewChainIdSigner(big.NewInt(63)) 1439 db, err := ethdb.NewMemDatabase() 1440 if err != nil { 1441 t.Fatal(err) 1442 } 1443 genesis := WriteGenesisBlockForTesting(db, 1444 GenesisAccount{addr1, big.NewInt(10000000000000)}, 1445 ) 1446 chainConfig := MakeDiehardChainConfig() 1447 1448 evmux := &event.TypeMux{} 1449 blockchain, err := NewBlockChain(db, chainConfig, FakePow{}, evmux) 1450 if err != nil { 1451 t.Fatal(err) 1452 } 1453 1454 subs := evmux.Subscribe(RemovedLogsEvent{}) 1455 chain, _ := GenerateChain(chainConfig, genesis, db, 2, func(i int, gen *BlockGen) { 1456 if i == 1 { 1457 tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), code).WithSigner(signer).SignECDSA(key1) 1458 if err != nil { 1459 t.Fatalf("failed to create tx: %v", err) 1460 } 1461 gen.AddTx(tx) 1462 } 1463 }) 1464 if res := blockchain.InsertChain(chain); res.Error != nil { 1465 t.Fatalf("failed to insert chain: %v", res.Error) 1466 } 1467 1468 chain, _ = GenerateChain(chainConfig, genesis, db, 3, func(i int, gen *BlockGen) {}) 1469 if res := blockchain.InsertChain(chain); res.Error != nil { 1470 t.Fatalf("failed to insert forked chain: %v", res.Error) 1471 } 1472 1473 ev := <-subs.Chan() 1474 if len(ev.Data.(RemovedLogsEvent).Logs) == 0 { 1475 t.Error("expected logs") 1476 } 1477 } 1478 1479 func TestReorgSideEvent(t *testing.T) { 1480 // This test itself is a little bit incorrect. Below, 1481 // MakeDiehardChainConfig would make a chain configuration that 1482 // only contains EIP160, and bypass EIP150 and Homestead. We never 1483 // have any chain like this exist in real world, so SputnikVM does 1484 // not contain a patch for this. As a result, it cannot figure out 1485 // a correct patch to run. So we bypass this test when running 1486 // with `UseSputnikVM`. 1487 if UseSputnikVM == "true" { 1488 return 1489 } 1490 1491 key1, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1492 if err != nil { 1493 t.Fatal(err) 1494 } 1495 addr1 := crypto.PubkeyToAddress(key1.PublicKey) 1496 db, err := ethdb.NewMemDatabase() 1497 if err != nil { 1498 t.Fatal(err) 1499 } 1500 genesis := WriteGenesisBlockForTesting(db, GenesisAccount{addr1, big.NewInt(10000000000000)}) 1501 signer := types.NewChainIdSigner(big.NewInt(63)) 1502 chainConfig := MakeDiehardChainConfig() 1503 1504 evmux := &event.TypeMux{} 1505 blockchain, err := NewBlockChain(db, chainConfig, FakePow{}, evmux) 1506 if err != nil { 1507 t.Fatal(err) 1508 } 1509 1510 chain, _ := GenerateChain(blockchain.config, genesis, db, 3, func(i int, gen *BlockGen) {}) 1511 if res := blockchain.InsertChain(chain); res.Error != nil { 1512 t.Fatalf("failed to insert chain: %v", res.Error) 1513 } 1514 1515 replacementBlocks, _ := GenerateChain(blockchain.config, genesis, db, 4, func(i int, gen *BlockGen) { 1516 tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil).WithSigner(signer).SignECDSA(key1) 1517 if i == 2 { 1518 gen.OffsetTime(-1) 1519 } 1520 if err != nil { 1521 t.Fatalf("failed to create tx: %v", err) 1522 } 1523 gen.AddTx(tx) 1524 }) 1525 1526 subs := evmux.Subscribe(ChainSideEvent{}) 1527 if res := blockchain.InsertChain(replacementBlocks); res.Error != nil { 1528 t.Fatalf("failed to insert chain: %v", res.Error) 1529 } 1530 1531 // first two block of the secondary chain are for a brief moment considered 1532 // side chains because up to that point the first one is considered the 1533 // heavier chain. 1534 expectedSideHashes := map[common.Hash]bool{ 1535 replacementBlocks[0].Hash(): true, 1536 replacementBlocks[1].Hash(): true, 1537 chain[0].Hash(): true, 1538 chain[1].Hash(): true, 1539 chain[2].Hash(): true, 1540 } 1541 1542 i := 0 1543 1544 const timeoutDura = 10 * time.Second 1545 timeout := time.NewTimer(timeoutDura) 1546 done: 1547 for { 1548 select { 1549 case ev := <-subs.Chan(): 1550 block := ev.Data.(ChainSideEvent).Block 1551 if _, ok := expectedSideHashes[block.Hash()]; !ok { 1552 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 1553 } 1554 i++ 1555 1556 if i == len(expectedSideHashes) { 1557 timeout.Stop() 1558 1559 break done 1560 } 1561 timeout.Reset(timeoutDura) 1562 1563 case <-timeout.C: 1564 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 1565 } 1566 } 1567 1568 // make sure no more events are fired 1569 select { 1570 case e := <-subs.Chan(): 1571 t.Errorf("unexpected event fired: %v", e) 1572 case <-time.After(250 * time.Millisecond): 1573 } 1574 1575 } 1576 1577 // Tests if the canonical block can be fetched from the database during chain insertion. 1578 func TestCanonicalBlockRetrieval(t *testing.T) { 1579 t.Skip("Skipped: needs updating") 1580 db, err := ethdb.NewMemDatabase() 1581 if err != nil { 1582 t.Fatal(err) 1583 } 1584 genesis := WriteGenesisBlockForTesting(db) 1585 1586 evmux := &event.TypeMux{} 1587 blockchain, err := NewBlockChain(db, testChainConfig(), FakePow{}, evmux) 1588 if err != nil { 1589 t.Fatal(err) 1590 } 1591 1592 chain, _ := GenerateChain(MakeChainConfig(), genesis, db, 10, func(i int, gen *BlockGen) {}) 1593 1594 for i := range chain { 1595 go func(block *types.Block) { 1596 // try to retrieve a block by its canonical hash and see if the block data can be retrieved. 1597 for { 1598 ch := GetCanonicalHash(db, block.NumberU64()) 1599 if ch == (common.Hash{}) { 1600 continue // busy wait for canonical hash to be written 1601 } 1602 if ch != block.Hash() { 1603 t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1604 } 1605 fb := GetBlock(db, ch) 1606 if fb == nil { 1607 t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1608 } 1609 if fb.Hash() != block.Hash() { 1610 t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1611 } 1612 return 1613 } 1614 }(chain[i]) 1615 1616 blockchain.InsertChain(types.Blocks{chain[i]}) 1617 } 1618 } 1619 1620 func TestEIP155Transition(t *testing.T) { 1621 // Configure and generate a sample block chain 1622 db, err := ethdb.NewMemDatabase() 1623 if err != nil { 1624 t.Fatal(err) 1625 } 1626 key, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1627 if err != nil { 1628 t.Fatal(err) 1629 } 1630 var ( 1631 address = crypto.PubkeyToAddress(key.PublicKey) 1632 funds = big.NewInt(1000000000) 1633 genesis = WriteGenesisBlockForTesting(db, GenesisAccount{address, funds}) 1634 config = &ChainConfig{ 1635 Forks: []*Fork{ 1636 { 1637 Name: "Homestead", 1638 Block: big.NewInt(0), 1639 Features: []*ForkFeature{ 1640 { 1641 ID: "difficulty", 1642 Options: ChainFeatureConfigOptions{ 1643 "type": "homestead", 1644 }, 1645 }, 1646 { 1647 ID: "gastable", 1648 Options: ChainFeatureConfigOptions{ 1649 "type": "homestead", 1650 }, 1651 }, 1652 }, 1653 }, 1654 { 1655 Name: "Diehard", 1656 Block: big.NewInt(2), 1657 Features: []*ForkFeature{ 1658 { 1659 ID: "eip155", 1660 Options: ChainFeatureConfigOptions{ 1661 "chainID": 1, 1662 }, 1663 }, 1664 { // ecip1010 bomb delay 1665 ID: "gastable", 1666 Options: ChainFeatureConfigOptions{ 1667 "type": "eip160", 1668 }, 1669 }, 1670 { // ecip1010 bomb delay 1671 ID: "difficulty", 1672 Options: ChainFeatureConfigOptions{ 1673 "type": "ecip1010", 1674 "length": 2000000, 1675 }, 1676 }, 1677 }, 1678 }, 1679 }, 1680 } 1681 mux event.TypeMux 1682 ) 1683 1684 blockchain, err := NewBlockChain(db, config, FakePow{}, &mux) 1685 if err != nil { 1686 t.Fatal(err) 1687 } 1688 blocks, _ := GenerateChain(config, genesis, db, 4, func(i int, block *BlockGen) { 1689 var ( 1690 tx *types.Transaction 1691 err error 1692 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1693 tx := types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil) 1694 tx.SetSigner(signer) 1695 return tx.SignECDSA(key) 1696 } 1697 ) 1698 switch i { 1699 case 0: 1700 tx, err = basicTx(types.BasicSigner{}) 1701 if err != nil { 1702 t.Fatal(err) 1703 } 1704 block.AddTx(tx) 1705 case 2: 1706 tx, err = basicTx(types.BasicSigner{}) 1707 if err != nil { 1708 t.Fatal(err) 1709 } 1710 block.AddTx(tx) 1711 1712 tx, err = basicTx(types.NewChainIdSigner(config.GetChainID())) 1713 if err != nil { 1714 t.Fatal(err) 1715 } 1716 block.AddTx(tx) 1717 case 3: 1718 tx, err = basicTx(types.BasicSigner{}) 1719 if err != nil { 1720 t.Fatal(err) 1721 } 1722 block.AddTx(tx) 1723 1724 tx, err = basicTx(types.NewChainIdSigner(config.GetChainID())) 1725 if err != nil { 1726 t.Fatal(err) 1727 } 1728 block.AddTx(tx) 1729 } 1730 }) 1731 1732 if res := blockchain.InsertChain(blocks); res.Error != nil { 1733 t.Fatal(res.Error) 1734 } 1735 block := blockchain.GetBlockByNumber(1) 1736 if block.Transactions()[0].Protected() { 1737 t.Error("Expected block[0].txs[0] to not be replay protected") 1738 } 1739 1740 block = blockchain.GetBlockByNumber(3) 1741 if block.Transactions()[0].Protected() { 1742 t.Error("Expected block[3].txs[0] to not be replay protected") 1743 } 1744 if !block.Transactions()[1].Protected() { 1745 t.Error("Expected block[3].txs[1] to be replay protected") 1746 } 1747 if res := blockchain.InsertChain(blocks[4:]); res.Error != nil { 1748 t.Fatal(res.Error) 1749 } 1750 1751 // generate an invalid chain id transaction 1752 config = &ChainConfig{ 1753 Forks: []*Fork{ 1754 { 1755 Name: "Homestead", 1756 Block: big.NewInt(0), 1757 Features: []*ForkFeature{ 1758 { 1759 ID: "difficulty", 1760 Options: ChainFeatureConfigOptions{ 1761 "type": "homestead", 1762 }, 1763 }, 1764 { 1765 ID: "gastable", 1766 Options: ChainFeatureConfigOptions{ 1767 "type": "homestead", 1768 }, 1769 }, 1770 }, 1771 }, 1772 { 1773 Name: "Diehard", 1774 Block: big.NewInt(2), 1775 Features: []*ForkFeature{ 1776 { 1777 ID: "eip155", 1778 Options: ChainFeatureConfigOptions{ 1779 "chainID": 2, 1780 }, 1781 }, 1782 { // ecip1010 bomb delay 1783 ID: "gastable", 1784 Options: ChainFeatureConfigOptions{ 1785 "type": "eip160", 1786 }, 1787 }, 1788 { // ecip1010 bomb delay 1789 ID: "difficulty", 1790 Options: ChainFeatureConfigOptions{ 1791 "type": "ecip1010", 1792 "length": 2000000, 1793 }, 1794 }, 1795 }, 1796 }, 1797 }, 1798 } 1799 blocks, _ = GenerateChain(config, blocks[len(blocks)-1], db, 4, func(i int, block *BlockGen) { 1800 var ( 1801 tx *types.Transaction 1802 err error 1803 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1804 tx := types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil) 1805 tx.SetSigner(signer) 1806 return tx.SignECDSA(key) 1807 } 1808 ) 1809 switch i { 1810 case 0: 1811 tx, err = basicTx(types.NewChainIdSigner(config.GetChainID())) 1812 if err != nil { 1813 t.Fatal(err) 1814 } 1815 block.AddTx(tx) 1816 } 1817 }) 1818 errExp := "Invalid transaction chain id. Current chain id: 1 tx chain id: 2" 1819 res := blockchain.InsertChain(blocks) 1820 if res.Error == nil { 1821 t.Error("expected transaction chain id error") 1822 } else if res.Error.Error() != errExp { 1823 t.Error("expected:", errExp, "got:", res.Error) 1824 } 1825 } 1826 1827 func TestBlockChain_BlockIsGenesis(t *testing.T) { 1828 // Make chain starting from genesis 1829 _, blockchain, err := newCanonical(testChainConfig(), 10, false) 1830 if err != nil { 1831 t.Fatalf("failed to make new canonical chain: %v", err) 1832 } 1833 1834 if !blockchain.blockIsGenesis(blockchain.GetBlockByNumber(0)) { 1835 t.Errorf("expected: is genesis block") 1836 } 1837 if blockchain.blockIsGenesis(blockchain.GetBlockByNumber(1)) { 1838 t.Errorf("expected: is not genesis block") 1839 } 1840 }