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