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