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