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