github.com/klaytn/klaytn@v1.10.2/blockchain/blockchain_test.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2014 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from core/blockchain_test.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package blockchain 22 23 import ( 24 "crypto/ecdsa" 25 "encoding/json" 26 "fmt" 27 "math/big" 28 "math/rand" 29 "strings" 30 "sync" 31 "testing" 32 "time" 33 34 "github.com/klaytn/klaytn/accounts/abi" 35 "github.com/klaytn/klaytn/blockchain/state" 36 "github.com/klaytn/klaytn/blockchain/types" 37 "github.com/klaytn/klaytn/blockchain/vm" 38 "github.com/klaytn/klaytn/common" 39 "github.com/klaytn/klaytn/common/compiler" 40 "github.com/klaytn/klaytn/common/hexutil" 41 "github.com/klaytn/klaytn/consensus" 42 "github.com/klaytn/klaytn/consensus/gxhash" 43 "github.com/klaytn/klaytn/crypto" 44 "github.com/klaytn/klaytn/params" 45 "github.com/klaytn/klaytn/rlp" 46 "github.com/klaytn/klaytn/storage" 47 "github.com/klaytn/klaytn/storage/database" 48 "github.com/klaytn/klaytn/storage/statedb" 49 50 "github.com/stretchr/testify/assert" 51 ) 52 53 // So we can deterministically seed different blockchains 54 var ( 55 canonicalSeed = 1 56 forkSeed = 2 57 ) 58 59 // newCanonical creates a chain database, and injects a deterministic canonical 60 // chain. Depending on the full flag, if creates either a full block chain or a 61 // header only chain. 62 func newCanonical(engine consensus.Engine, n int, full bool) (database.DBManager, *BlockChain, error) { 63 var ( 64 db = database.NewMemoryDBManager() 65 genesis = new(Genesis).MustCommit(db) 66 ) 67 68 // Initialize a fresh chain with only a genesis block 69 blockchain, _ := NewBlockChain(db, nil, params.AllGxhashProtocolChanges, engine, vm.Config{}) 70 // Create and inject the requested chain 71 if n == 0 { 72 return db, blockchain, nil 73 } 74 if full { 75 // Full block-chain requested 76 blocks := makeBlockChain(genesis, n, engine, db, canonicalSeed) 77 _, err := blockchain.InsertChain(blocks) 78 return db, blockchain, err 79 } 80 // Header-only chain requested 81 headers := makeHeaderChain(genesis.Header(), n, engine, db, canonicalSeed) 82 _, err := blockchain.InsertHeaderChain(headers, 1) 83 return db, blockchain, err 84 } 85 86 // Test fork of length N starting from block i 87 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { 88 // Copy old chain up to #i into a new db 89 db, blockchain2, err := newCanonical(gxhash.NewFaker(), i, full) 90 if err != nil { 91 t.Fatal("could not make new canonical in testFork", err) 92 } 93 defer blockchain2.Stop() 94 95 // Assert the chains have the same header/block at #i 96 var hash1, hash2 common.Hash 97 if full { 98 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 99 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 100 } else { 101 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 102 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 103 } 104 if hash1 != hash2 { 105 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 106 } 107 // Extend the newly created chain 108 var ( 109 blockChainB []*types.Block 110 headerChainB []*types.Header 111 ) 112 if full { 113 blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, gxhash.NewFaker(), db, forkSeed) 114 if _, err := blockchain2.InsertChain(blockChainB); err != nil { 115 t.Fatalf("failed to insert forking chain: %v", err) 116 } 117 } else { 118 headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, gxhash.NewFaker(), db, forkSeed) 119 if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { 120 t.Fatalf("failed to insert forking chain: %v", err) 121 } 122 } 123 // Sanity check that the forked chain can be imported into the original 124 var tdPre, tdPost *big.Int 125 126 if full { 127 tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) 128 if err := testBlockChainImport(blockChainB, blockchain); err != nil { 129 t.Fatalf("failed to import forked block chain: %v", err) 130 } 131 tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) 132 } else { 133 tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) 134 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 135 t.Fatalf("failed to import forked header chain: %v", err) 136 } 137 tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) 138 } 139 // Compare the total difficulties of the chains 140 comparator(tdPre, tdPost) 141 } 142 143 func printChain(bc *BlockChain) { 144 for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- { 145 b := bc.GetBlockByNumber(uint64(i)) 146 fmt.Printf("\t%x %v\n", b.Hash(), b.BlockScore()) 147 } 148 } 149 150 // testBlockChainImport tries to process a chain of blocks, writing them into 151 // the database if successful. 152 func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { 153 for _, block := range chain { 154 // Try and process the block 155 err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) 156 if err == nil { 157 err = blockchain.validator.ValidateBody(block) 158 } 159 if err != nil { 160 if err == ErrKnownBlock { 161 continue 162 } 163 return err 164 } 165 statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache, nil) 166 if err != nil { 167 return err 168 } 169 receipts, _, usedGas, _, _, err := blockchain.Processor().Process(block, statedb, vm.Config{}) 170 if err != nil { 171 blockchain.reportBlock(block, receipts, err) 172 return err 173 } 174 err = blockchain.validator.ValidateState(block, blockchain.GetBlockByHash(block.ParentHash()), statedb, receipts, usedGas) 175 if err != nil { 176 blockchain.reportBlock(block, receipts, err) 177 return err 178 } 179 blockchain.mu.Lock() 180 blockchain.db.WriteTd(block.Hash(), block.NumberU64(), new(big.Int).Add(block.BlockScore(), blockchain.GetTdByHash(block.ParentHash()))) 181 blockchain.db.WriteBlock(block) 182 statedb.Commit(false) 183 blockchain.mu.Unlock() 184 } 185 return nil 186 } 187 188 // testHeaderChainImport tries to process a chain of header, writing them into 189 // the database if successful. 190 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 191 for _, header := range chain { 192 // Try and validate the header 193 if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { 194 return err 195 } 196 // Manually insert the header into the database, but don't reorganise (allows subsequent testing) 197 blockchain.mu.Lock() 198 blockchain.db.WriteTd(header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.BlockScore, blockchain.GetTdByHash(header.ParentHash))) 199 blockchain.db.WriteHeader(header) 200 blockchain.mu.Unlock() 201 } 202 return nil 203 } 204 205 func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) { 206 _, err := blockchain.InsertChain(chain) 207 if err != nil { 208 fmt.Println(err) 209 t.FailNow() 210 } 211 done <- true 212 } 213 214 func TestLastBlock(t *testing.T) { 215 _, blockchain, err := newCanonical(gxhash.NewFaker(), 0, true) 216 if err != nil { 217 t.Fatalf("failed to create pristine chain: %v", err) 218 } 219 defer blockchain.Stop() 220 221 blocks := makeBlockChain(blockchain.CurrentBlock(), 1, gxhash.NewFullFaker(), blockchain.db, 0) 222 if _, err := blockchain.InsertChain(blocks); err != nil { 223 t.Fatalf("Failed to insert block: %v", err) 224 } 225 if blocks[len(blocks)-1].Hash() != blockchain.db.ReadHeadBlockHash() { 226 t.Fatalf("Write/Get HeadBlockHash failed") 227 } 228 } 229 230 // Tests that given a starting canonical chain of a given size, it can be extended 231 // with various length chains. 232 func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } 233 func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } 234 235 func testExtendCanonical(t *testing.T, full bool) { 236 length := 5 237 238 // Make first chain starting from genesis 239 _, processor, err := newCanonical(gxhash.NewFaker(), length, full) 240 if err != nil { 241 t.Fatalf("failed to make new canonical chain: %v", err) 242 } 243 defer processor.Stop() 244 245 // Define the blockscore comparator 246 better := func(td1, td2 *big.Int) { 247 if td2.Cmp(td1) <= 0 { 248 t.Errorf("total blockscore mismatch: have %v, expected more than %v", td2, td1) 249 } 250 } 251 // Start fork from current height 252 testFork(t, processor, length, 1, full, better) 253 testFork(t, processor, length, 2, full, better) 254 testFork(t, processor, length, 5, full, better) 255 testFork(t, processor, length, 10, full, better) 256 } 257 258 // Tests that given a starting canonical chain of a given size, creating shorter 259 // forks do not take canonical ownership. 260 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } 261 func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } 262 263 func testShorterFork(t *testing.T, full bool) { 264 length := 10 265 266 // Make first chain starting from genesis 267 _, processor, err := newCanonical(gxhash.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 blockscore comparator 274 worse := func(td1, td2 *big.Int) { 275 if td2.Cmp(td1) >= 0 { 276 t.Errorf("total blockscore mismatch: have %v, expected less than %v", td2, td1) 277 } 278 } 279 // Sum of numbers must be less than `length` for this to be a shorter fork 280 testFork(t, processor, 0, 3, full, worse) 281 testFork(t, processor, 0, 7, full, worse) 282 testFork(t, processor, 1, 1, full, worse) 283 testFork(t, processor, 1, 7, full, worse) 284 testFork(t, processor, 5, 3, full, worse) 285 testFork(t, processor, 5, 4, full, worse) 286 } 287 288 // Tests that given a starting canonical chain of a given size, creating longer 289 // forks do take canonical ownership. 290 func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } 291 func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } 292 293 func testLongerFork(t *testing.T, full bool) { 294 length := 10 295 296 // Make first chain starting from genesis 297 _, processor, err := newCanonical(gxhash.NewFaker(), length, full) 298 if err != nil { 299 t.Fatalf("failed to make new canonical chain: %v", err) 300 } 301 defer processor.Stop() 302 303 // Define the blockscore comparator 304 better := func(td1, td2 *big.Int) { 305 if td2.Cmp(td1) <= 0 { 306 t.Errorf("total blockscore mismatch: have %v, expected more than %v", td2, td1) 307 } 308 } 309 // Sum of numbers must be greater than `length` for this to be a longer fork 310 testFork(t, processor, 0, 11, full, better) 311 testFork(t, processor, 0, 15, full, better) 312 testFork(t, processor, 1, 10, full, better) 313 testFork(t, processor, 1, 12, full, better) 314 testFork(t, processor, 5, 6, full, better) 315 testFork(t, processor, 5, 8, full, better) 316 } 317 318 // Tests that given a starting canonical chain of a given size, creating equal 319 // forks do take canonical ownership. 320 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } 321 func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } 322 323 func testEqualFork(t *testing.T, full bool) { 324 length := 10 325 326 // Make first chain starting from genesis 327 _, processor, err := newCanonical(gxhash.NewFaker(), length, full) 328 if err != nil { 329 t.Fatalf("failed to make new canonical chain: %v", err) 330 } 331 defer processor.Stop() 332 333 // Define the blockscore comparator 334 equal := func(td1, td2 *big.Int) { 335 if td2.Cmp(td1) != 0 { 336 t.Errorf("total blockscore mismatch: have %v, want %v", td2, td1) 337 } 338 } 339 // Sum of numbers must be equal to `length` for this to be an equal fork 340 testFork(t, processor, 0, 10, full, equal) 341 testFork(t, processor, 1, 9, full, equal) 342 testFork(t, processor, 2, 8, full, equal) 343 testFork(t, processor, 5, 5, full, equal) 344 testFork(t, processor, 6, 4, full, equal) 345 testFork(t, processor, 9, 1, full, equal) 346 } 347 348 // Tests that chains missing links do not get accepted by the processor. 349 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } 350 func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } 351 352 func testBrokenChain(t *testing.T, full bool) { 353 // Make chain starting from genesis 354 db, blockchain, err := newCanonical(gxhash.NewFaker(), 10, full) 355 if err != nil { 356 t.Fatalf("failed to make new canonical chain: %v", err) 357 } 358 defer blockchain.Stop() 359 360 // Create a forked chain, and try to insert with a missing link 361 if full { 362 chain := makeBlockChain(blockchain.CurrentBlock(), 5, gxhash.NewFaker(), db, forkSeed)[1:] 363 if err := testBlockChainImport(chain, blockchain); err == nil { 364 t.Errorf("broken block chain not reported") 365 } 366 } else { 367 chain := makeHeaderChain(blockchain.CurrentHeader(), 5, gxhash.NewFaker(), db, forkSeed)[1:] 368 if err := testHeaderChainImport(chain, blockchain); err == nil { 369 t.Errorf("broken header chain not reported") 370 } 371 } 372 } 373 374 // Tests that reorganising a long difficult chain after a short easy one 375 // overwrites the canonical numbers and links in the database. 376 func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) } 377 func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) } 378 379 func testReorgLong(t *testing.T, full bool) { 380 testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280, full) 381 } 382 383 // Tests that reorganising a short difficult chain after a long easy one 384 // overwrites the canonical numbers and links in the database. 385 func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) } 386 func TestReorgShortBlocks(t *testing.T) { testReorgShort(t, true) } 387 388 func testReorgShort(t *testing.T, full bool) { 389 // Create a long easy chain vs. a short heavy one. Due to blockscore adjustment 390 // we need a fairly long chain of blocks with different difficulties for a short 391 // one to become heavyer than a long one. The 96 is an empirical value. 392 easy := make([]int64, 96) 393 for i := 0; i < len(easy); i++ { 394 easy[i] = 60 395 } 396 diff := make([]int64, len(easy)-1) 397 for i := 0; i < len(diff); i++ { 398 diff[i] = -9 399 } 400 testReorg(t, easy, diff, 12615120, full) 401 } 402 403 func testReorg(t *testing.T, first, second []int64, td int64, full bool) { 404 // Create a pristine chain and database 405 db, blockchain, err := newCanonical(gxhash.NewFaker(), 0, full) 406 if err != nil { 407 t.Fatalf("failed to create pristine chain: %v", err) 408 } 409 defer blockchain.Stop() 410 411 // Insert an easy and a difficult chain afterwards 412 easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), gxhash.NewFaker(), db, len(first), func(i int, b *BlockGen) { 413 b.OffsetTime(first[i]) 414 }) 415 diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), gxhash.NewFaker(), db, len(second), func(i int, b *BlockGen) { 416 b.OffsetTime(second[i]) 417 }) 418 if full { 419 if _, err := blockchain.InsertChain(easyBlocks); err != nil { 420 t.Fatalf("failed to insert easy chain: %v", err) 421 } 422 if _, err := blockchain.InsertChain(diffBlocks); err != nil { 423 t.Fatalf("failed to insert difficult chain: %v", err) 424 } 425 } else { 426 easyHeaders := make([]*types.Header, len(easyBlocks)) 427 for i, block := range easyBlocks { 428 easyHeaders[i] = block.Header() 429 } 430 diffHeaders := make([]*types.Header, len(diffBlocks)) 431 for i, block := range diffBlocks { 432 diffHeaders[i] = block.Header() 433 } 434 if _, err := blockchain.InsertHeaderChain(easyHeaders, 1); err != nil { 435 t.Fatalf("failed to insert easy chain: %v", err) 436 } 437 if _, err := blockchain.InsertHeaderChain(diffHeaders, 1); err != nil { 438 t.Fatalf("failed to insert difficult chain: %v", err) 439 } 440 } 441 // Check that the chain is valid number and link wise 442 if full { 443 prev := blockchain.CurrentBlock() 444 for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.GetBlockByNumber(block.NumberU64()-1) { 445 if prev.ParentHash() != block.Hash() { 446 t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) 447 } 448 } 449 } else { 450 prev := blockchain.CurrentHeader() 451 for header := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, blockchain.GetHeaderByNumber(header.Number.Uint64()-1) { 452 if prev.ParentHash != header.Hash() { 453 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 454 } 455 } 456 } 457 // Make sure the chain total blockscore is the correct one 458 want := new(big.Int).Add(blockchain.genesisBlock.BlockScore(), big.NewInt(td)) 459 if full { 460 if have := blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()); have.Cmp(want) != 0 { 461 t.Errorf("total blockscore mismatch: have %v, want %v", have, want) 462 } 463 } else { 464 if have := blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()); have.Cmp(want) != 0 { 465 t.Errorf("total blockscore mismatch: have %v, want %v", have, want) 466 } 467 } 468 } 469 470 // Tests that the insertion functions detect banned hashes. 471 func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) } 472 func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) } 473 474 func testBadHashes(t *testing.T, full bool) { 475 // Create a pristine chain and database 476 db, blockchain, err := newCanonical(gxhash.NewFaker(), 0, full) 477 if err != nil { 478 t.Fatalf("failed to create pristine chain: %v", err) 479 } 480 defer blockchain.Stop() 481 482 // Create a chain, ban a hash and try to import 483 if full { 484 blocks := makeBlockChain(blockchain.CurrentBlock(), 3, gxhash.NewFaker(), db, 10) 485 486 BadHashes[blocks[2].Header().Hash()] = true 487 defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() 488 489 _, err = blockchain.InsertChain(blocks) 490 } else { 491 headers := makeHeaderChain(blockchain.CurrentHeader(), 3, gxhash.NewFaker(), db, 10) 492 493 BadHashes[headers[2].Hash()] = true 494 defer func() { delete(BadHashes, headers[2].Hash()) }() 495 496 _, err = blockchain.InsertHeaderChain(headers, 1) 497 } 498 if err != ErrBlacklistedHash { 499 t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash) 500 } 501 } 502 503 // Tests that bad hashes are detected on boot, and the chain rolled back to a 504 // good state prior to the bad hash. 505 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } 506 func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } 507 508 func testReorgBadHashes(t *testing.T, full bool) { 509 // Create a pristine chain and database 510 db, blockchain, err := newCanonical(gxhash.NewFaker(), 0, full) 511 if err != nil { 512 t.Fatalf("failed to create pristine chain: %v", err) 513 } 514 // Create a chain, import and ban afterwards 515 headers := makeHeaderChain(blockchain.CurrentHeader(), 4, gxhash.NewFaker(), db, 10) 516 blocks := makeBlockChain(blockchain.CurrentBlock(), 4, gxhash.NewFaker(), db, 10) 517 518 if full { 519 if _, err = blockchain.InsertChain(blocks); err != nil { 520 t.Errorf("failed to import blocks: %v", err) 521 } 522 if blockchain.CurrentBlock().Hash() != blocks[3].Hash() { 523 t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash()) 524 } 525 BadHashes[blocks[3].Header().Hash()] = true 526 defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() 527 } else { 528 if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil { 529 t.Errorf("failed to import headers: %v", err) 530 } 531 if blockchain.CurrentHeader().Hash() != headers[3].Hash() { 532 t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash()) 533 } 534 BadHashes[headers[3].Hash()] = true 535 defer func() { delete(BadHashes, headers[3].Hash()) }() 536 } 537 blockchain.Stop() 538 539 // Create a new BlockChain and check that it rolled back the state. 540 ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, gxhash.NewFaker(), vm.Config{}) 541 if err != nil { 542 t.Fatalf("failed to create new chain manager: %v", err) 543 } 544 if full { 545 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 546 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 547 } 548 } else { 549 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 550 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 551 } 552 } 553 ncm.Stop() 554 } 555 556 // Tests chain insertions in the face of one entity containing an invalid nonce. 557 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } 558 func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } 559 560 func testInsertNonceError(t *testing.T, full bool) { 561 for i := 1; i < 25 && !t.Failed(); i++ { 562 // Create a pristine chain and database 563 db, blockchain, err := newCanonical(gxhash.NewFaker(), 0, full) 564 if err != nil { 565 t.Fatalf("failed to create pristine chain: %v", err) 566 } 567 defer blockchain.Stop() 568 569 // Create and insert a chain with a failing nonce 570 var ( 571 failAt int 572 failRes int 573 failNum uint64 574 ) 575 if full { 576 blocks := makeBlockChain(blockchain.CurrentBlock(), i, gxhash.NewFaker(), db, 0) 577 578 failAt = rand.Int() % len(blocks) 579 failNum = blocks[failAt].NumberU64() 580 581 blockchain.engine = gxhash.NewFakeFailer(failNum) 582 failRes, err = blockchain.InsertChain(blocks) 583 } else { 584 headers := makeHeaderChain(blockchain.CurrentHeader(), i, gxhash.NewFaker(), db, 0) 585 586 failAt = rand.Int() % len(headers) 587 failNum = headers[failAt].Number.Uint64() 588 589 blockchain.engine = gxhash.NewFakeFailer(failNum) 590 blockchain.hc.engine = blockchain.engine 591 failRes, err = blockchain.InsertHeaderChain(headers, 1) 592 } 593 // Check that the returned error indicates the failure. 594 if failRes != failAt { 595 t.Errorf("test %d: failure index mismatch: have %d, want %d", i, failRes, failAt) 596 } 597 // Check that all no blocks after the failing block have been inserted. 598 for j := 0; j < i-failAt; j++ { 599 if full { 600 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 601 t.Errorf("test %d: invalid block in chain: %v", i, block) 602 } 603 } else { 604 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 605 t.Errorf("test %d: invalid header in chain: %v", i, header) 606 } 607 } 608 } 609 } 610 } 611 612 // Tests that fast importing a block chain produces the same chain data as the 613 // classical full block processing. 614 func TestFastVsFullChains(t *testing.T) { 615 // Configure and generate a sample block chain 616 var ( 617 gendb = database.NewMemoryDBManager() 618 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 619 address = crypto.PubkeyToAddress(key.PublicKey) 620 funds = big.NewInt(1000000000) 621 gspec = &Genesis{ 622 Config: params.TestChainConfig, 623 Alloc: GenesisAlloc{address: {Balance: funds}}, 624 } 625 genesis = gspec.MustCommit(gendb) 626 signer = types.LatestSignerForChainID(gspec.Config.ChainID) 627 ) 628 blocks, receipts := GenerateChain(gspec.Config, genesis, gxhash.NewFaker(), gendb, 1024, func(i int, block *BlockGen) { 629 // If the block number is multiple of 3, send a few bonus transactions to the miner 630 if i%3 == 2 { 631 for j := 0; j < i%4+1; j++ { 632 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key) 633 if err != nil { 634 panic(err) 635 } 636 block.AddTx(tx) 637 } 638 } 639 }) 640 // Import the chain as an archive node for the comparison baseline 641 archiveDb := database.NewMemoryDBManager() 642 gspec.MustCommit(archiveDb) 643 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, gxhash.NewFaker(), vm.Config{}) 644 defer archive.Stop() 645 646 if n, err := archive.InsertChain(blocks); err != nil { 647 t.Fatalf("failed to process block %d: %v", n, err) 648 } 649 // Fast import the chain as a non-archive node to test 650 fastDb := database.NewMemoryDBManager() 651 gspec.MustCommit(fastDb) 652 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, gxhash.NewFaker(), vm.Config{}) 653 defer fast.Stop() 654 655 headers := make([]*types.Header, len(blocks)) 656 for i, block := range blocks { 657 headers[i] = block.Header() 658 } 659 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 660 t.Fatalf("failed to insert header %d: %v", n, err) 661 } 662 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 663 t.Fatalf("failed to insert receipt %d: %v", n, err) 664 } 665 // Iterate over all chain data components, and cross reference 666 for i := 0; i < len(blocks); i++ { 667 bnum, num, hash := blocks[i].Number(), blocks[i].NumberU64(), blocks[i].Hash() 668 669 if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 { 670 t.Errorf("block #%d [%x]: td mismatch: have %v, want %v", num, hash, ftd, atd) 671 } 672 if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { 673 t.Errorf("block #%d [%x]: header mismatch: have %v, want %v", num, hash, fheader, aheader) 674 } 675 if fblock, ablock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash); fblock.Hash() != ablock.Hash() { 676 t.Errorf("block #%d [%x]: block mismatch: have %v, want %v", num, hash, fblock, ablock) 677 } else if types.DeriveSha(fblock.Transactions(), bnum) != types.DeriveSha(ablock.Transactions(), bnum) { 678 t.Errorf("block #%d [%x]: transactions mismatch: have %v, want %v", num, hash, fblock.Transactions(), ablock.Transactions()) 679 } 680 freceipts := fastDb.ReadReceipts(hash, *fastDb.ReadHeaderNumber(hash)) 681 areceipts := archiveDb.ReadReceipts(hash, *archiveDb.ReadHeaderNumber(hash)) 682 if types.DeriveSha(freceipts, bnum) != types.DeriveSha(areceipts, bnum) { 683 t.Errorf("block #%d [%x]: receipts mismatch: have %v, want %v", num, hash, freceipts, areceipts) 684 } 685 } 686 // Check that the canonical chains are the same between the databases 687 for i := 0; i < len(blocks)+1; i++ { 688 if fhash, ahash := fastDb.ReadCanonicalHash(uint64(i)), archiveDb.ReadCanonicalHash(uint64(i)); fhash != ahash { 689 t.Errorf("block #%d: canonical hash mismatch: have %v, want %v", i, fhash, ahash) 690 } 691 } 692 } 693 694 // Tests that various import methods move the chain head pointers to the correct 695 // positions. 696 func TestLightVsFastVsFullChainHeads(t *testing.T) { 697 // Configure and generate a sample block chain 698 var ( 699 gendb = database.NewMemoryDBManager() 700 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 701 address = crypto.PubkeyToAddress(key.PublicKey) 702 funds = big.NewInt(1000000000) 703 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 704 genesis = gspec.MustCommit(gendb) 705 ) 706 height := uint64(1024) 707 blocks, receipts := GenerateChain(gspec.Config, genesis, gxhash.NewFaker(), gendb, int(height), nil) 708 709 // Configure a subchain to roll back 710 remove := []common.Hash{} 711 for _, block := range blocks[height/2:] { 712 remove = append(remove, block.Hash()) 713 } 714 // Create a small assertion method to check the three heads 715 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 716 if num := chain.CurrentBlock().NumberU64(); num != block { 717 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 718 } 719 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 720 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 721 } 722 if num := chain.CurrentHeader().Number.Uint64(); num != header { 723 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 724 } 725 } 726 // Import the chain as an archive node and ensure all pointers are updated 727 archiveDb := database.NewMemoryDBManager() 728 gspec.MustCommit(archiveDb) 729 730 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, gxhash.NewFaker(), vm.Config{}) 731 if n, err := archive.InsertChain(blocks); err != nil { 732 t.Fatalf("failed to process block %d: %v", n, err) 733 } 734 defer archive.Stop() 735 736 assert(t, "archive", archive, height, height, height) 737 archive.Rollback(remove) 738 assert(t, "archive", archive, height/2, height/2, height/2) 739 740 // Import the chain as a non-archive node and ensure all pointers are updated 741 fastDb := database.NewMemoryDBManager() 742 gspec.MustCommit(fastDb) 743 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, gxhash.NewFaker(), vm.Config{}) 744 defer fast.Stop() 745 746 headers := make([]*types.Header, len(blocks)) 747 for i, block := range blocks { 748 headers[i] = block.Header() 749 } 750 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 751 t.Fatalf("failed to insert header %d: %v", n, err) 752 } 753 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 754 t.Fatalf("failed to insert receipt %d: %v", n, err) 755 } 756 assert(t, "fast", fast, height, height, 0) 757 fast.Rollback(remove) 758 assert(t, "fast", fast, height/2, height/2, 0) 759 760 // Import the chain as a light node and ensure all pointers are updated 761 lightDb := database.NewMemoryDBManager() 762 gspec.MustCommit(lightDb) 763 764 light, _ := NewBlockChain(lightDb, nil, gspec.Config, gxhash.NewFaker(), vm.Config{}) 765 if n, err := light.InsertHeaderChain(headers, 1); err != nil { 766 t.Fatalf("failed to insert header %d: %v", n, err) 767 } 768 defer light.Stop() 769 770 assert(t, "light", light, height, 0, 0) 771 light.Rollback(remove) 772 assert(t, "light", light, height/2, 0, 0) 773 } 774 775 // Tests that chain reorganisations handle transaction removals and reinsertions. 776 func TestChainTxReorgs(t *testing.T) { 777 var ( 778 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 779 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 780 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 781 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 782 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 783 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 784 db = database.NewMemoryDBManager() 785 gspec = &Genesis{ 786 Config: params.TestChainConfig, 787 Alloc: GenesisAlloc{ 788 addr1: {Balance: big.NewInt(1000000)}, 789 addr2: {Balance: big.NewInt(1000000)}, 790 addr3: {Balance: big.NewInt(1000000)}, 791 }, 792 } 793 genesis = gspec.MustCommit(db) 794 signer = types.LatestSignerForChainID(gspec.Config.ChainID) 795 ) 796 797 // Create two transactions shared between the chains: 798 // - postponed: transaction included at a later block in the forked chain 799 // - swapped: transaction included at the same block number in the forked chain 800 postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 801 swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 802 803 // Create two transactions that will be dropped by the forked chain: 804 // - pastDrop: transaction dropped retroactively from a past block 805 // - freshDrop: transaction dropped exactly at the block where the reorg is detected 806 var pastDrop, freshDrop *types.Transaction 807 808 // Create three transactions that will be added in the forked chain: 809 // - pastAdd: transaction added before the reorganization is detected 810 // - freshAdd: transaction added at the exact block the reorg is detected 811 // - futureAdd: transaction added after the reorg has already finished 812 var pastAdd, freshAdd, futureAdd *types.Transaction 813 814 chain, _ := GenerateChain(gspec.Config, genesis, gxhash.NewFaker(), db, 3, func(i int, gen *BlockGen) { 815 switch i { 816 case 0: 817 pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 818 819 gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point 820 gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork 821 822 case 2: 823 freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 824 825 gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point 826 gen.AddTx(swapped) // This transaction will be swapped out at the exact height 827 828 gen.OffsetTime(9) // Lower the block blockscore to simulate a weaker chain 829 } 830 }) 831 // Import the chain. This runs all block validation rules. 832 blockchain, _ := NewBlockChain(db, nil, gspec.Config, gxhash.NewFaker(), vm.Config{}) 833 if i, err := blockchain.InsertChain(chain); err != nil { 834 t.Fatalf("failed to insert original chain[%d]: %v", i, err) 835 } 836 defer blockchain.Stop() 837 838 // overwrite the old chain 839 chain, _ = GenerateChain(gspec.Config, genesis, gxhash.NewFaker(), db, 5, func(i int, gen *BlockGen) { 840 switch i { 841 case 0: 842 pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 843 gen.AddTx(pastAdd) // This transaction needs to be injected during reorg 844 845 case 2: 846 gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain 847 gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain 848 849 freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 850 gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time 851 852 case 3: 853 futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 854 gen.AddTx(futureAdd) // This transaction will be added after a full reorg 855 } 856 }) 857 if _, err := blockchain.InsertChain(chain); err != nil { 858 t.Fatalf("failed to insert forked chain: %v", err) 859 } 860 861 // removed tx 862 for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 863 if txn, _, _, _ := db.ReadTxAndLookupInfo(tx.Hash()); txn != nil { 864 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 865 } 866 if rcpt, _, _, _ := db.ReadReceipt(tx.Hash()); rcpt != nil { 867 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 868 } 869 } 870 // added tx 871 for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 872 if txn, _, _, _ := db.ReadTxAndLookupInfo(tx.Hash()); txn == nil { 873 t.Errorf("add %d: expected tx to be found", i) 874 } 875 if rcpt, _, _, _ := db.ReadReceipt(tx.Hash()); rcpt == nil { 876 t.Errorf("add %d: expected receipt to be found", i) 877 } 878 } 879 // shared tx 880 for i, tx := range (types.Transactions{postponed, swapped}) { 881 if txn, _, _, _ := db.ReadTxAndLookupInfo(tx.Hash()); txn == nil { 882 t.Errorf("share %d: expected tx to be found", i) 883 } 884 if rcpt, _, _, _ := db.ReadReceipt(tx.Hash()); rcpt == nil { 885 t.Errorf("share %d: expected receipt to be found", i) 886 } 887 } 888 } 889 890 func TestLogReorgs(t *testing.T) { 891 var ( 892 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 893 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 894 db = database.NewMemoryDBManager() 895 // this code generates a log 896 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 897 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 898 genesis = gspec.MustCommit(db) 899 signer = types.LatestSignerForChainID(gspec.Config.ChainID) 900 ) 901 902 blockchain, _ := NewBlockChain(db, nil, gspec.Config, gxhash.NewFaker(), vm.Config{}) 903 defer blockchain.Stop() 904 905 rmLogsCh := make(chan RemovedLogsEvent) 906 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 907 chain, _ := GenerateChain(params.TestChainConfig, genesis, gxhash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 908 if i == 1 { 909 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 910 if err != nil { 911 t.Fatalf("failed to create tx: %v", err) 912 } 913 gen.AddTx(tx) 914 } 915 }) 916 if _, err := blockchain.InsertChain(chain); err != nil { 917 t.Fatalf("failed to insert chain: %v", err) 918 } 919 920 chain, _ = GenerateChain(params.TestChainConfig, genesis, gxhash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 921 if _, err := blockchain.InsertChain(chain); err != nil { 922 t.Fatalf("failed to insert forked chain: %v", err) 923 } 924 925 timeout := time.NewTimer(1 * time.Second) 926 select { 927 case ev := <-rmLogsCh: 928 if len(ev.Logs) == 0 { 929 t.Error("expected logs") 930 } 931 case <-timeout.C: 932 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 933 } 934 } 935 936 func TestReorgSideEvent(t *testing.T) { 937 var ( 938 db = database.NewMemoryDBManager() 939 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 940 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 941 gspec = &Genesis{ 942 Config: params.TestChainConfig, 943 Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}, 944 } 945 genesis = gspec.MustCommit(db) 946 signer = types.LatestSignerForChainID(gspec.Config.ChainID) 947 ) 948 949 blockchain, _ := NewBlockChain(db, nil, gspec.Config, gxhash.NewFaker(), vm.Config{}) 950 defer blockchain.Stop() 951 952 chain, _ := GenerateChain(gspec.Config, genesis, gxhash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 953 if _, err := blockchain.InsertChain(chain); err != nil { 954 t.Fatalf("failed to insert chain: %v", err) 955 } 956 957 replacementBlocks, _ := GenerateChain(gspec.Config, genesis, gxhash.NewFaker(), db, 4, func(i int, gen *BlockGen) { 958 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1) 959 if i == 2 { 960 gen.OffsetTime(-9) 961 } 962 if err != nil { 963 t.Fatalf("failed to create tx: %v", err) 964 } 965 gen.AddTx(tx) 966 }) 967 chainSideCh := make(chan ChainSideEvent, 64) 968 blockchain.SubscribeChainSideEvent(chainSideCh) 969 if _, err := blockchain.InsertChain(replacementBlocks); err != nil { 970 t.Fatalf("failed to insert chain: %v", err) 971 } 972 973 // first two block of the secondary chain are for a brief moment considered 974 // side chains because up to that point the first one is considered the 975 // heavier chain. 976 expectedSideHashes := map[common.Hash]bool{ 977 replacementBlocks[0].Hash(): true, 978 replacementBlocks[1].Hash(): true, 979 chain[0].Hash(): true, 980 chain[1].Hash(): true, 981 chain[2].Hash(): true, 982 } 983 984 i := 0 985 986 const timeoutDura = 10 * time.Second 987 timeout := time.NewTimer(timeoutDura) 988 done: 989 for { 990 select { 991 case ev := <-chainSideCh: 992 block := ev.Block 993 if _, ok := expectedSideHashes[block.Hash()]; !ok { 994 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 995 } 996 i++ 997 998 if i == len(expectedSideHashes) { 999 timeout.Stop() 1000 1001 break done 1002 } 1003 timeout.Reset(timeoutDura) 1004 1005 case <-timeout.C: 1006 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 1007 } 1008 } 1009 1010 // make sure no more events are fired 1011 select { 1012 case e := <-chainSideCh: 1013 t.Errorf("unexpected event fired: %v", e) 1014 case <-time.After(250 * time.Millisecond): 1015 } 1016 } 1017 1018 // Tests if the canonical block can be fetched from the database during chain insertion. 1019 func TestCanonicalBlockRetrieval(t *testing.T) { 1020 _, blockchain, err := newCanonical(gxhash.NewFaker(), 0, true) 1021 if err != nil { 1022 t.Fatalf("failed to create pristine chain: %v", err) 1023 } 1024 defer blockchain.Stop() 1025 1026 chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, gxhash.NewFaker(), blockchain.db, 10, func(i int, gen *BlockGen) {}) 1027 1028 var pend sync.WaitGroup 1029 pend.Add(len(chain)) 1030 1031 for i := range chain { 1032 go func(block *types.Block) { 1033 defer pend.Done() 1034 1035 // try to retrieve a block by its canonical hash and see if the block data can be retrieved. 1036 for { 1037 ch := blockchain.db.ReadCanonicalHash(block.NumberU64()) 1038 if ch == (common.Hash{}) { 1039 continue // busy wait for canonical hash to be written 1040 } 1041 if ch != block.Hash() { 1042 t.Errorf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1043 return 1044 } 1045 fb := blockchain.db.ReadBlock(ch, block.NumberU64()) 1046 if fb == nil { 1047 t.Errorf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1048 return 1049 } 1050 if fb.Hash() != block.Hash() { 1051 t.Errorf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1052 return 1053 } 1054 return 1055 } 1056 }(chain[i]) 1057 1058 if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { 1059 t.Fatalf("failed to insert block %d: %v", i, err) 1060 } 1061 } 1062 pend.Wait() 1063 } 1064 1065 func TestEIP155Transition(t *testing.T) { 1066 // Configure and generate a sample block chain 1067 var ( 1068 db = database.NewMemoryDBManager() 1069 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1070 address = crypto.PubkeyToAddress(key.PublicKey) 1071 funds = big.NewInt(1000000000) 1072 deleteAddr = common.Address{1} 1073 gspec = &Genesis{ 1074 Config: ¶ms.ChainConfig{ChainID: big.NewInt(1)}, 1075 Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 1076 } 1077 genesis = gspec.MustCommit(db) 1078 ) 1079 1080 blockchain, _ := NewBlockChain(db, nil, gspec.Config, gxhash.NewFaker(), vm.Config{}) 1081 defer blockchain.Stop() 1082 1083 // generate an invalid chain id transaction 1084 config := ¶ms.ChainConfig{ChainID: big.NewInt(2)} 1085 blocks, _ := GenerateChain(config, genesis, gxhash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1086 var ( 1087 tx *types.Transaction 1088 err error 1089 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1090 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1091 } 1092 ) 1093 if i == 0 { 1094 tx, err = basicTx(types.NewEIP155Signer(big.NewInt(2))) 1095 if err != nil { 1096 t.Fatal(err) 1097 } 1098 block.AddTx(tx) 1099 } 1100 }) 1101 _, err := blockchain.InsertChain(blocks) 1102 if err != types.ErrInvalidChainId { 1103 t.Error("expected error:", types.ErrInvalidChainId) 1104 } 1105 } 1106 1107 // TODO-Klaytn-FailedTest Failed test. Enable this later. 1108 /* 1109 func TestEIP161AccountRemoval(t *testing.T) { 1110 // Configure and generate a sample block chain 1111 var ( 1112 db = database.NewMemoryDBManager() 1113 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1114 address = crypto.PubkeyToAddress(key.PublicKey) 1115 funds = big.NewInt(1000000000) 1116 theAddr = common.Address{1} 1117 gspec = &Genesis{ 1118 Config: ¶ms.ChainConfig{ 1119 ChainID: big.NewInt(1), 1120 }, 1121 Alloc: GenesisAlloc{address: {Balance: funds}}, 1122 } 1123 genesis = gspec.MustCommit(db) 1124 ) 1125 blockchain, _ := NewBlockChain(db, nil, gspec.Config, gxhash.NewFaker(), vm.Config{}) 1126 defer blockchain.Stop() 1127 1128 blocks, _ := GenerateChain(gspec.Config, genesis, gxhash.NewFaker(), db, 3, func(i int, block *BlockGen) { 1129 var ( 1130 tx *types.Transaction 1131 err error 1132 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1133 ) 1134 switch i { 1135 case 0: 1136 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1137 case 1: 1138 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1139 case 2: 1140 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1141 } 1142 if err != nil { 1143 t.Fatal(err) 1144 } 1145 block.AddTx(tx) 1146 }) 1147 // account must exist pre eip 161 1148 if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1149 t.Fatal(err) 1150 } 1151 if st, _ := blockchain.State(); !st.Exist(theAddr) { 1152 t.Error("expected account to exist") 1153 } 1154 1155 // account needs to be deleted post eip 161 1156 if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1157 t.Fatal(err) 1158 } 1159 if st, _ := blockchain.State(); st.Exist(theAddr) { 1160 t.Error("account should not exist") 1161 } 1162 1163 // account musn't be created post eip 161 1164 if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1165 t.Fatal(err) 1166 } 1167 if st, _ := blockchain.State(); st.Exist(theAddr) { 1168 t.Error("account should not exist") 1169 } 1170 } 1171 */ 1172 1173 // This is a regression test (i.e. as weird as it is, don't delete it ever), which 1174 // tests that under weird reorg conditions the blockchain and its internal header- 1175 // chain return the same latest block/header. 1176 // 1177 // https://github.com/ethereum/go-ethereum/pull/15941 1178 func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { 1179 // Generate a canonical chain to act as the main dataset 1180 engine := gxhash.NewFaker() 1181 1182 db := database.NewMemoryDBManager() 1183 genesis := new(Genesis).MustCommit(db) 1184 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetRewardbase(common.Address{1}) }) 1185 1186 // Generate a bunch of fork blocks, each side forking from the canonical chain 1187 forks := make([]*types.Block, len(blocks)) 1188 for i := 0; i < len(forks); i++ { 1189 parent := genesis 1190 if i > 0 { 1191 parent = blocks[i-1] 1192 } 1193 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetRewardbase(common.Address{2}) }) 1194 forks[i] = fork[0] 1195 } 1196 // Import the canonical and fork chain side by side, verifying the current block 1197 // and current header consistency 1198 diskdb := database.NewMemoryDBManager() 1199 new(Genesis).MustCommit(diskdb) 1200 1201 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1202 if err != nil { 1203 t.Fatalf("failed to create tester chain: %v", err) 1204 } 1205 for i := 0; i < len(blocks); i++ { 1206 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1207 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1208 } 1209 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1210 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]) 1211 } 1212 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1213 t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) 1214 } 1215 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1216 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]) 1217 } 1218 } 1219 } 1220 1221 // Tests that importing small side forks doesn't leave junk in the trie database 1222 // cache (which would eventually cause memory issues). 1223 func TestTrieForkGC(t *testing.T) { 1224 // Generate a canonical chain to act as the main dataset 1225 engine := gxhash.NewFaker() 1226 1227 db := database.NewMemoryDBManager() 1228 genesis := new(Genesis).MustCommit(db) 1229 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*DefaultTriesInMemory, func(i int, b *BlockGen) { b.SetRewardbase(common.Address{1}) }) 1230 1231 // Generate a bunch of fork blocks, each side forking from the canonical chain 1232 forks := make([]*types.Block, len(blocks)) 1233 for i := 0; i < len(forks); i++ { 1234 parent := genesis 1235 if i > 0 { 1236 parent = blocks[i-1] 1237 } 1238 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetRewardbase(common.Address{2}) }) 1239 forks[i] = fork[0] 1240 } 1241 // Import the canonical and fork chain side by side, forcing the trie cache to cache both 1242 diskdb := database.NewMemoryDBManager() 1243 new(Genesis).MustCommit(diskdb) 1244 1245 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1246 if err != nil { 1247 t.Fatalf("failed to create tester chain: %v", err) 1248 } 1249 for i := 0; i < len(blocks); i++ { 1250 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1251 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1252 } 1253 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1254 t.Fatalf("fork %d: failed to insert into chain: %v", i, err) 1255 } 1256 } 1257 // Dereference all the recent tries and ensure no past trie is left in 1258 for i := 0; i < DefaultTriesInMemory; i++ { 1259 chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) 1260 chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) 1261 } 1262 if len(chain.stateCache.TrieDB().Nodes()) > 0 { 1263 t.Fatalf("stale tries still alive after garbase collection") 1264 } 1265 } 1266 1267 // TODO-Klaytn-FailedTest Failed test. Enable this later. 1268 /* 1269 // Tests that doing large reorgs works even if the state associated with the 1270 // forking point is not available any more. 1271 func TestLargeReorgTrieGC(t *testing.T) { 1272 // Generate the original common chain segment and the two competing forks 1273 engine := gxhash.NewFaker() 1274 1275 db := database.NewMemoryDBManager() 1276 genesis := new(Genesis).MustCommit(db) 1277 1278 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1279 original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*DefaultTriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1280 competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*DefaultTriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) 1281 1282 // Import the shared chain and the original canonical one 1283 diskdb := database.NewMemoryDBManager() 1284 new(Genesis).MustCommit(diskdb) 1285 1286 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1287 if err != nil { 1288 t.Fatalf("failed to create tester chain: %v", err) 1289 } 1290 if _, err := chain.InsertChain(shared); err != nil { 1291 t.Fatalf("failed to insert shared chain: %v", err) 1292 } 1293 if _, err := chain.InsertChain(original); err != nil { 1294 t.Fatalf("failed to insert shared chain: %v", err) 1295 } 1296 // Ensure that the state associated with the forking point is pruned away 1297 if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil { 1298 t.Fatalf("common-but-old ancestor still cache") 1299 } 1300 // Import the competitor chain without exceeding the canonical's TD and ensure 1301 // we have not processed any of the blocks (protection against malicious blocks) 1302 if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { 1303 t.Fatalf("failed to insert competitor chain: %v", err) 1304 } 1305 for i, block := range competitor[:len(competitor)-2] { 1306 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1307 t.Fatalf("competitor %d: low TD chain became processed", i) 1308 } 1309 } 1310 // Import the head of the competitor chain, triggering the reorg and ensure we 1311 // successfully reprocess all the stashed away blocks. 1312 if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { 1313 t.Fatalf("failed to finalize competitor chain: %v", err) 1314 } 1315 for i, block := range competitor[:len(competitor)-DefaultTriesInMemory] { 1316 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1317 t.Fatalf("competitor %d: competing chain state missing", i) 1318 } 1319 } 1320 } 1321 */ 1322 1323 // Benchmarks large blocks with value transfers to non-existing accounts 1324 func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) { 1325 var ( 1326 testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1327 testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) 1328 bankFunds = big.NewInt(100000000000000000) 1329 gspec = Genesis{ 1330 Config: params.TestChainConfig, 1331 Alloc: GenesisAlloc{ 1332 testBankAddress: {Balance: bankFunds}, 1333 common.HexToAddress("0xc0de"): { 1334 Code: []byte{0x60, 0x01, 0x50}, 1335 Balance: big.NewInt(0), 1336 }, // push 1, pop 1337 }, 1338 } 1339 signer = types.LatestSignerForChainID(gspec.Config.ChainID) 1340 ) 1341 // Generate the original common chain segment and the two competing forks 1342 engine := gxhash.NewFaker() 1343 db := database.NewMemoryDBManager() 1344 genesis := gspec.MustCommit(db) 1345 1346 blockGenerator := func(i int, block *BlockGen) { 1347 for txi := 0; txi < numTxs; txi++ { 1348 uniq := uint64(i*numTxs + txi) 1349 recipient := recipientFn(uniq) 1350 // recipient := common.BigToAddress(big.NewInt(0).SetUint64(1337 + uniq)) 1351 tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey) 1352 if err != nil { 1353 b.Error(err) 1354 } 1355 block.AddTx(tx) 1356 } 1357 } 1358 1359 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator) 1360 b.StopTimer() 1361 b.ResetTimer() 1362 for i := 0; i < b.N; i++ { 1363 // Import the shared chain and the original canonical one 1364 diskdb := database.NewMemoryDBManager() 1365 gspec.MustCommit(diskdb) 1366 1367 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1368 if err != nil { 1369 b.Fatalf("failed to create tester chain: %v", err) 1370 } 1371 b.StartTimer() 1372 if _, err := chain.InsertChain(shared); err != nil { 1373 b.Fatalf("failed to insert shared chain: %v", err) 1374 } 1375 b.StopTimer() 1376 if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { 1377 b.Fatalf("Transactions were not included, expected %d, got %d", (numTxs * numBlocks), got) 1378 } 1379 } 1380 } 1381 1382 func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) { 1383 var ( 1384 numTxs = 1000 1385 numBlocks = 1 1386 ) 1387 1388 recipientFn := func(nonce uint64) common.Address { 1389 return common.BigToAddress(big.NewInt(0).SetUint64(1337 + nonce)) 1390 } 1391 dataFn := func(nonce uint64) []byte { 1392 return nil 1393 } 1394 1395 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1396 } 1397 1398 func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) { 1399 var ( 1400 numTxs = 1000 1401 numBlocks = 1 1402 ) 1403 b.StopTimer() 1404 b.ResetTimer() 1405 1406 recipientFn := func(nonce uint64) common.Address { 1407 return common.BigToAddress(big.NewInt(0).SetUint64(1337)) 1408 } 1409 dataFn := func(nonce uint64) []byte { 1410 return nil 1411 } 1412 1413 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1414 } 1415 1416 func BenchmarkBlockChain_1x1000Executions(b *testing.B) { 1417 var ( 1418 numTxs = 1000 1419 numBlocks = 1 1420 ) 1421 b.StopTimer() 1422 b.ResetTimer() 1423 1424 recipientFn := func(nonce uint64) common.Address { 1425 return common.BigToAddress(big.NewInt(0).SetUint64(0xc0de)) 1426 } 1427 dataFn := func(nonce uint64) []byte { 1428 return nil 1429 } 1430 1431 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1432 } 1433 1434 // TestCheckBlockChainVersion tests the functionality of CheckBlockChainVersion function. 1435 func TestCheckBlockChainVersion(t *testing.T) { 1436 memDB := database.NewMemoryDBManager() 1437 1438 // 1. If DatabaseVersion is not stored yet, 1439 // calling CheckBlockChainVersion stores BlockChainVersion to DatabaseVersion. 1440 assert.Nil(t, memDB.ReadDatabaseVersion()) 1441 assert.NoError(t, CheckBlockChainVersion(memDB)) 1442 assert.Equal(t, uint64(BlockChainVersion), *memDB.ReadDatabaseVersion()) 1443 1444 // 2. If DatabaseVersion is stored but less than BlockChainVersion, 1445 // calling CheckBlockChainVersion stores BlockChainVersion to DatabaseVersion. 1446 memDB.WriteDatabaseVersion(BlockChainVersion - 1) 1447 assert.NoError(t, CheckBlockChainVersion(memDB)) 1448 assert.Equal(t, uint64(BlockChainVersion), *memDB.ReadDatabaseVersion()) 1449 1450 // 3. If DatabaseVersion is stored but greater than BlockChainVersion, 1451 // calling CheckBlockChainVersion returns an error and does not change the value. 1452 memDB.WriteDatabaseVersion(BlockChainVersion + 1) 1453 assert.Error(t, CheckBlockChainVersion(memDB)) 1454 assert.Equal(t, uint64(BlockChainVersion+1), *memDB.ReadDatabaseVersion()) 1455 } 1456 1457 var ( 1458 internalTxContractCode string 1459 internalTxContractAbi string 1460 ) 1461 1462 func genInternalTxTransaction(t *testing.T, block *BlockGen, address common.Address, signer types.Signer, key *ecdsa.PrivateKey) { 1463 // 1. Deploy internal transaction sample contract 1464 nonce := block.TxNonce(address) 1465 amount := new(big.Int).SetUint64(100000000) 1466 gasLimit := big.NewInt(500000).Uint64() 1467 gasPrice := big.NewInt(25000) 1468 1469 // It has to be cached because TestBlockChain_SetCanonicalBlock calls it many times 1470 if len(internalTxContractCode) == 0 { 1471 contracts, err := compiler.CompileSolidityOrLoad("", 1472 "../contracts/internal_tx_contract/internal_tx_contract.sol") 1473 assert.Nil(t, err) 1474 1475 var contract compiler.Contract 1476 for _, v := range contracts { // take the first one 1477 contract = *v 1478 break 1479 } 1480 1481 internalTxContractCode = strings.TrimPrefix(contract.Code, "0x") 1482 abi, err := json.Marshal(contract.Info.AbiDefinition) 1483 assert.Nil(t, err) 1484 internalTxContractAbi = string(abi) 1485 } 1486 1487 values := map[types.TxValueKeyType]interface{}{ 1488 types.TxValueKeyNonce: nonce, 1489 types.TxValueKeyAmount: amount, 1490 types.TxValueKeyGasLimit: gasLimit, 1491 types.TxValueKeyGasPrice: gasPrice, 1492 types.TxValueKeyHumanReadable: false, 1493 types.TxValueKeyTo: (*common.Address)(nil), 1494 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 1495 types.TxValueKeyFrom: address, 1496 types.TxValueKeyData: common.Hex2Bytes(internalTxContractCode), 1497 } 1498 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 1499 assert.Nil(t, err) 1500 1501 err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{key}) 1502 assert.Nil(t, err) 1503 1504 block.AddTx(tx) 1505 1506 contractAddr := crypto.CreateAddress(address, nonce) 1507 1508 // 2. Contract Execution 1509 abii, err := abi.JSON(strings.NewReader(internalTxContractAbi)) 1510 assert.Equal(t, nil, err) 1511 1512 // the contract method "sendKlay" send 1 peb to address 3 times 1513 data, err := abii.Pack("sendKlay", uint32(3), address) 1514 assert.Equal(t, nil, err) 1515 1516 values = map[types.TxValueKeyType]interface{}{ 1517 types.TxValueKeyNonce: block.TxNonce(address), 1518 types.TxValueKeyFrom: address, 1519 types.TxValueKeyTo: contractAddr, 1520 types.TxValueKeyAmount: big.NewInt(0), 1521 types.TxValueKeyGasLimit: gasLimit, 1522 types.TxValueKeyGasPrice: gasPrice, 1523 types.TxValueKeyData: data, 1524 } 1525 tx, err = types.NewTransactionWithMap(types.TxTypeSmartContractExecution, values) 1526 assert.Equal(t, nil, err) 1527 1528 err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{key}) 1529 assert.NoError(t, err) 1530 1531 block.AddTx(tx) 1532 } 1533 1534 // TestCallTraceChainEventSubscription tests if the method insertChain posts a chain event correctly. 1535 // Scenario: 1536 // 1. Deploy a contract 1537 // sendKlay(n uint32, receiver address): send 1 peb to `receiver` address `n` times. 1538 // 2. Send a smart contract execution transaction 1539 func TestCallTraceChainEventSubscription(t *testing.T) { 1540 // configure and generate a sample block chain 1541 var ( 1542 gendb = database.NewMemoryDBManager() 1543 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1544 address = crypto.PubkeyToAddress(key.PublicKey) 1545 funds = big.NewInt(100000000000000000) 1546 testGenesis = &Genesis{ 1547 Config: params.TestChainConfig, 1548 Alloc: GenesisAlloc{address: {Balance: funds}}, 1549 } 1550 genesis = testGenesis.MustCommit(gendb) 1551 signer = types.LatestSignerForChainID(testGenesis.Config.ChainID) 1552 ) 1553 db := database.NewMemoryDBManager() 1554 testGenesis.MustCommit(db) 1555 1556 // create new blockchain with enabled internal tx tracing option 1557 blockchain, _ := NewBlockChain(db, nil, testGenesis.Config, gxhash.NewFaker(), vm.Config{Debug: true, EnableInternalTxTracing: true}) 1558 defer blockchain.Stop() 1559 1560 // subscribe a new chain event channel 1561 chainEventCh := make(chan ChainEvent, 1) 1562 subscription := blockchain.SubscribeChainEvent(chainEventCh) 1563 defer subscription.Unsubscribe() 1564 1565 // generate blocks 1566 blocks, _ := GenerateChain(testGenesis.Config, genesis, gxhash.NewFaker(), gendb, 1, func(i int, block *BlockGen) { 1567 // Deploy a contract which can trigger internal transactions 1568 genInternalTxTransaction(t, block, address, signer, key) 1569 }) 1570 1571 // insert the generated blocks into the test chain 1572 if n, err := blockchain.InsertChain(blocks); err != nil { 1573 t.Fatalf("failed to process block %d: %v", n, err) 1574 } 1575 1576 timer := time.NewTimer(1 * time.Second) 1577 defer timer.Stop() 1578 // compare the published chain event with the expected test data 1579 select { 1580 case <-timer.C: 1581 t.Fatal("Timeout. There is no chain event posted for 1 second") 1582 case ev := <-chainEventCh: 1583 // a contract deploy tx and a contract execution tx 1584 assert.Equal(t, 2, len(ev.InternalTxTraces)) 1585 1586 // compare contract deploy result 1587 assert.Equal(t, address, *ev.InternalTxTraces[0].From) 1588 assert.Equal(t, 0, len(ev.InternalTxTraces[0].Calls)) 1589 assert.Equal(t, "0x"+internalTxContractCode, ev.InternalTxTraces[0].Input) 1590 assert.Equal(t, fmt.Sprintf("0x%x", 100000000), ev.InternalTxTraces[0].Value) 1591 1592 // compare contract execution result 1593 assert.Equal(t, address, *ev.InternalTxTraces[1].From) 1594 assert.Equal(t, 3, len(ev.InternalTxTraces[1].Calls)) 1595 assert.Equal(t, fmt.Sprintf("0x%x", 0), ev.InternalTxTraces[1].Value) 1596 } 1597 } 1598 1599 // TestBlockChain_SetCanonicalBlock tests SetCanonicalBlock. 1600 // It first generates the chain and then call SetCanonicalBlock to change CurrentBlock. 1601 func TestBlockChain_SetCanonicalBlock(t *testing.T) { 1602 // configure and generate a sample block chain 1603 var ( 1604 gendb = database.NewMemoryDBManager() 1605 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1606 address = crypto.PubkeyToAddress(key.PublicKey) 1607 funds = big.NewInt(100000000000000000) 1608 testGenesis = &Genesis{ 1609 Config: params.TestChainConfig, 1610 Alloc: GenesisAlloc{address: {Balance: funds}}, 1611 } 1612 genesis = testGenesis.MustCommit(gendb) 1613 signer = types.LatestSignerForChainID(testGenesis.Config.ChainID) 1614 ) 1615 db := database.NewMemoryDBManager() 1616 testGenesis.MustCommit(db) 1617 1618 // Archive mode is given to avoid mismatching between the given starting block number and 1619 // the actual block number where the blockchain has been rolled back to due to 128 blocks interval commit. 1620 cacheConfig := &CacheConfig{ 1621 ArchiveMode: true, 1622 CacheSize: 512, 1623 BlockInterval: DefaultBlockInterval, 1624 TriesInMemory: DefaultTriesInMemory, 1625 TrieNodeCacheConfig: statedb.GetEmptyTrieNodeCacheConfig(), 1626 SnapshotCacheSize: 512, 1627 } 1628 // create new blockchain with enabled internal tx tracing option 1629 blockchain, _ := NewBlockChain(db, cacheConfig, testGenesis.Config, gxhash.NewFaker(), vm.Config{Debug: true, EnableInternalTxTracing: true}) 1630 defer blockchain.Stop() 1631 1632 rand.Seed(time.Now().UnixNano()) 1633 chainLength := rand.Int63n(500) + 100 1634 1635 // generate blocks 1636 blocks, _ := GenerateChain(testGenesis.Config, genesis, gxhash.NewFaker(), gendb, int(chainLength), func(i int, block *BlockGen) { 1637 // Deploy a contract which can trigger internal transactions 1638 genInternalTxTransaction(t, block, address, signer, key) 1639 }) 1640 1641 // insert the generated blocks into the test chain 1642 if n, err := blockchain.InsertChain(blocks); err != nil { 1643 t.Fatalf("failed to process block %d: %v", n, err) 1644 } 1645 1646 // target block number is 1/2 of the original chain length 1647 targetBlockNum := uint64(chainLength / 2) 1648 targetBlock := blockchain.db.ReadBlockByNumber(targetBlockNum) 1649 1650 // set the canonical block with the target block number 1651 blockchain.SetCanonicalBlock(targetBlockNum) 1652 1653 // compare the current block to the target block 1654 newHeadBlock := blockchain.CurrentBlock() 1655 assert.Equal(t, targetBlock.Hash(), newHeadBlock.Hash()) 1656 assert.EqualValues(t, targetBlock, newHeadBlock) 1657 } 1658 1659 func TestBlockChain_writeBlockLogsToRemoteCache(t *testing.T) { 1660 storage.SkipLocalTest(t) 1661 1662 // prepare blockchain 1663 blockchain := &BlockChain{ 1664 stateCache: state.NewDatabaseWithNewCache(database.NewMemoryDBManager(), &statedb.TrieNodeCacheConfig{ 1665 CacheType: statedb.CacheTypeHybrid, 1666 LocalCacheSizeMiB: 100, 1667 RedisEndpoints: []string{"localhost:6379"}, 1668 RedisClusterEnable: false, 1669 }), 1670 } 1671 1672 // prepare test data to be written in the cache 1673 key := []byte{1, 2, 3, 4} 1674 log := &types.Log{ 1675 Address: common.Address{}, 1676 Topics: []common.Hash{common.BytesToHash(hexutil.MustDecode("0x123456789abcdef123456789abcdefffffffffff"))}, 1677 Data: []uint8{0x11, 0x22, 0x33, 0x44}, 1678 BlockNumber: uint64(1000), 1679 } 1680 receipt := &types.Receipt{ 1681 TxHash: common.Hash{}, 1682 GasUsed: uint64(999999), 1683 Status: types.ReceiptStatusSuccessful, 1684 Logs: []*types.Log{log}, 1685 } 1686 1687 // write log to cache 1688 blockchain.writeBlockLogsToRemoteCache(key, []*types.Receipt{receipt}) 1689 1690 // get log from cache 1691 ret := blockchain.stateCache.TrieDB().TrieNodeCache().Get(key) 1692 if ret == nil { 1693 t.Fatal("no cache") 1694 } 1695 1696 // decode return data to the original log format 1697 storageLog := []*types.LogForStorage{} 1698 if err := rlp.DecodeBytes(ret, &storageLog); err != nil { 1699 t.Fatal(err) 1700 } 1701 logs := make([]*types.Log, len(storageLog)) 1702 for i, log := range storageLog { 1703 logs[i] = (*types.Log)(log) 1704 } 1705 1706 assert.Equal(t, log, logs[0]) 1707 } 1708 1709 // TestDeleteCreateRevert tests a weird state transition corner case that we hit 1710 // while changing the internals of statedb. The workflow is that a contract is 1711 // self destructed, then in a followup transaction (but same block) it's created 1712 // again and the transaction reverted. 1713 func TestDeleteCreateRevert(t *testing.T) { 1714 var ( 1715 aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") 1716 bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") 1717 // Generate a canonical chain to act as the main dataset 1718 engine = gxhash.NewFaker() 1719 db = database.NewMemoryDBManager() 1720 1721 // A sender who makes transactions, has some funds 1722 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1723 address = crypto.PubkeyToAddress(key.PublicKey) 1724 funds = big.NewInt(1000000000) 1725 gspec = &Genesis{ 1726 Config: params.TestChainConfig, 1727 Alloc: GenesisAlloc{ 1728 address: {Balance: funds}, 1729 // The address 0xAAAAA selfdestructs if called 1730 aa: { 1731 // Code needs to just selfdestruct 1732 Code: []byte{byte(vm.PC), 0xFF}, 1733 Nonce: 1, 1734 Balance: big.NewInt(0), 1735 }, 1736 // The address 0xBBBB send 1 peb to 0xAAAA, then reverts 1737 bb: { 1738 Code: []byte{ 1739 byte(vm.PC), // [0] 1740 byte(vm.DUP1), // [0,0] 1741 byte(vm.DUP1), // [0,0,0] 1742 byte(vm.DUP1), // [0,0,0,0] 1743 byte(vm.PUSH1), 0x01, // [0,0,0,0,1] (value) 1744 byte(vm.PUSH2), 0xaa, 0xaa, // [0,0,0,0,1, 0xaaaa] 1745 byte(vm.GAS), 1746 byte(vm.CALL), 1747 byte(vm.REVERT), 1748 }, 1749 Balance: big.NewInt(1), 1750 }, 1751 }, 1752 } 1753 genesis = gspec.MustCommit(db) 1754 ) 1755 1756 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) { 1757 b.SetRewardbase(common.Address{1}) 1758 signer := types.LatestSignerForChainID(params.TestChainConfig.ChainID) 1759 // One transaction to AAAA 1760 tx, _ := types.SignTx(types.NewTransaction(0, aa, 1761 big.NewInt(0), 50000, big.NewInt(1), nil), signer, key) 1762 b.AddTx(tx) 1763 // One transaction to BBBB 1764 tx, _ = types.SignTx(types.NewTransaction(1, bb, 1765 big.NewInt(0), 100000, big.NewInt(1), nil), signer, key) 1766 b.AddTx(tx) 1767 }) 1768 // Import the canonical chain 1769 diskdb := database.NewMemoryDBManager() 1770 gspec.MustCommit(diskdb) 1771 1772 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1773 if err != nil { 1774 t.Fatalf("failed to create tester chain: %v", err) 1775 } 1776 if n, err := chain.InsertChain(blocks); err != nil { 1777 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1778 } 1779 } 1780 1781 // TestBlockChain_InsertChain_InsertFutureBlocks inserts future blocks that have a missing ancestor. 1782 // It should return an expected error, but not panic. 1783 func TestBlockChain_InsertChain_InsertFutureBlocks(t *testing.T) { 1784 // configure and generate a sample blockchain 1785 var ( 1786 db = database.NewMemoryDBManager() 1787 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1788 address = crypto.PubkeyToAddress(key.PublicKey) 1789 funds = big.NewInt(100000000000000000) 1790 testGenesis = &Genesis{ 1791 Config: params.TestChainConfig, 1792 Alloc: GenesisAlloc{address: {Balance: funds}}, 1793 } 1794 genesis = testGenesis.MustCommit(db) 1795 ) 1796 1797 // Archive mode is given to avoid mismatching between the given starting block number and 1798 // the actual block number where the blockchain has been rolled back to due to 128 blocks interval commit. 1799 cacheConfig := &CacheConfig{ 1800 ArchiveMode: true, 1801 CacheSize: 512, 1802 BlockInterval: DefaultBlockInterval, 1803 TriesInMemory: DefaultTriesInMemory, 1804 TrieNodeCacheConfig: statedb.GetEmptyTrieNodeCacheConfig(), 1805 SnapshotCacheSize: 512, 1806 } 1807 cacheConfig.TrieNodeCacheConfig.NumFetcherPrefetchWorker = 3 1808 1809 // create new blockchain with enabled internal tx tracing option 1810 blockchain, _ := NewBlockChain(db, cacheConfig, testGenesis.Config, gxhash.NewFaker(), vm.Config{}) 1811 defer blockchain.Stop() 1812 1813 // generate blocks 1814 blocks, _ := GenerateChain(testGenesis.Config, genesis, gxhash.NewFaker(), db, 10, func(i int, block *BlockGen) {}) 1815 1816 // insert the generated blocks into the test chain 1817 if n, err := blockchain.InsertChain(blocks[:2]); err != nil { 1818 t.Fatalf("failed to process block %d: %v", n, err) 1819 } 1820 1821 // insert future blocks 1822 _, err := blockchain.InsertChain(blocks[4:]) 1823 if err == nil { 1824 t.Fatal("should be failed") 1825 } 1826 1827 assert.Equal(t, consensus.ErrUnknownAncestor, err) 1828 }