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