github.com/core-coin/go-core/v2@v2.1.9/core/blockchain_test.go (about) 1 // Copyright 2014 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-core library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 crand "crypto/rand" 21 "errors" 22 "fmt" 23 "io/ioutil" 24 "math/big" 25 "math/rand" 26 "os" 27 "sync" 28 "testing" 29 "time" 30 31 "github.com/core-coin/go-core/v2/xcbdb" 32 33 "github.com/core-coin/go-core/v2/consensus/cryptore" 34 35 "github.com/core-coin/go-core/v2/common" 36 "github.com/core-coin/go-core/v2/consensus" 37 "github.com/core-coin/go-core/v2/core/rawdb" 38 "github.com/core-coin/go-core/v2/core/state" 39 "github.com/core-coin/go-core/v2/core/types" 40 "github.com/core-coin/go-core/v2/core/vm" 41 "github.com/core-coin/go-core/v2/crypto" 42 "github.com/core-coin/go-core/v2/params" 43 "github.com/core-coin/go-core/v2/trie" 44 ) 45 46 // So we can deterministically seed different blockchains 47 var ( 48 canonicalSeed = 1 49 forkSeed = 2 50 ) 51 52 // newCanonical creates a chain database, and injects a deterministic canonical 53 // chain. Depending on the full flag, if creates either a full block chain or a 54 // header only chain. 55 func newCanonical(engine consensus.Engine, n int, full bool) (xcbdb.Database, *BlockChain, error) { 56 var ( 57 db = rawdb.NewMemoryDatabase() 58 genesis = new(Genesis).MustCommit(db) 59 ) 60 61 // Initialize a fresh chain with only a genesis block 62 blockchain, _ := NewBlockChain(db, nil, params.MainnetChainConfig, engine, vm.Config{}, nil, nil) 63 // Create and inject the requested chain 64 if n == 0 { 65 return db, blockchain, nil 66 } 67 if full { 68 // Full block-chain requested 69 blocks := makeBlockChain(genesis, n, engine, db, canonicalSeed) 70 _, err := blockchain.InsertChain(blocks) 71 return db, blockchain, err 72 } 73 // Header-only chain requested 74 headers := makeHeaderChain(genesis.Header(), n, engine, db, canonicalSeed) 75 _, err := blockchain.InsertHeaderChain(headers, 1) 76 return db, blockchain, err 77 } 78 79 // Test fork of length N starting from block i 80 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { 81 // Copy old chain up to #i into a new db 82 db, blockchain2, err := newCanonical(cryptore.NewFaker(), i, full) 83 if err != nil { 84 t.Fatal("could not make new canonical in testFork", err) 85 } 86 defer blockchain2.Stop() 87 88 // Assert the chains have the same header/block at #i 89 var hash1, hash2 common.Hash 90 if full { 91 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 92 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 93 } else { 94 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 95 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 96 } 97 if hash1 != hash2 { 98 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 99 } 100 // Extend the newly created chain 101 var ( 102 blockChainB []*types.Block 103 headerChainB []*types.Header 104 ) 105 if full { 106 blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, cryptore.NewFaker(), db, forkSeed) 107 if _, err := blockchain2.InsertChain(blockChainB); err != nil { 108 t.Fatalf("failed to insert forking chain: %v", err) 109 } 110 } else { 111 headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, cryptore.NewFaker(), db, forkSeed) 112 if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { 113 t.Fatalf("failed to insert forking chain: %v", err) 114 } 115 } 116 // Sanity check that the forked chain can be imported into the original 117 var tdPre, tdPost *big.Int 118 119 if full { 120 tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) 121 if err := testBlockChainImport(blockChainB, blockchain); err != nil { 122 t.Fatalf("failed to import forked block chain: %v", err) 123 } 124 tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) 125 } else { 126 tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) 127 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 128 t.Fatalf("failed to import forked header chain: %v", err) 129 } 130 tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) 131 } 132 // Compare the total difficulties of the chains 133 comparator(tdPre, tdPost) 134 } 135 136 // testBlockChainImport tries to process a chain of blocks, writing them into 137 // the database if successful. 138 func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { 139 for _, block := range chain { 140 // Try and process the block 141 err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) 142 if err == nil { 143 err = blockchain.validator.ValidateBody(block) 144 } 145 if err != nil { 146 if err == ErrKnownBlock { 147 continue 148 } 149 return err 150 } 151 statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache, nil) 152 if err != nil { 153 return err 154 } 155 receipts, _, usedEnergy, err := blockchain.processor.Process(block, statedb, vm.Config{}) 156 if err != nil { 157 blockchain.reportBlock(block, receipts, err) 158 return err 159 } 160 err = blockchain.validator.ValidateState(block, statedb, receipts, usedEnergy) 161 if err != nil { 162 blockchain.reportBlock(block, receipts, err) 163 return err 164 } 165 blockchain.chainmu.Lock() 166 rawdb.WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash()))) 167 rawdb.WriteBlock(blockchain.db, block) 168 statedb.Commit(false) 169 blockchain.chainmu.Unlock() 170 } 171 return nil 172 } 173 174 // testHeaderChainImport tries to process a chain of header, writing them into 175 // the database if successful. 176 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 177 for _, header := range chain { 178 // Try and validate the header 179 if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { 180 return err 181 } 182 // Manually insert the header into the database, but don't reorganise (allows subsequent testing) 183 blockchain.chainmu.Lock() 184 rawdb.WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash))) 185 rawdb.WriteHeader(blockchain.db, header) 186 blockchain.chainmu.Unlock() 187 } 188 return nil 189 } 190 191 func TestLastBlock(t *testing.T) { 192 _, blockchain, err := newCanonical(cryptore.NewFaker(), 0, true) 193 if err != nil { 194 t.Fatalf("failed to create pristine chain: %v", err) 195 } 196 defer blockchain.Stop() 197 198 blocks := makeBlockChain(blockchain.CurrentBlock(), 1, cryptore.NewFullFaker(), blockchain.db, 0) 199 if _, err := blockchain.InsertChain(blocks); err != nil { 200 t.Fatalf("Failed to insert block: %v", err) 201 } 202 if blocks[len(blocks)-1].Hash() != rawdb.ReadHeadBlockHash(blockchain.db) { 203 t.Fatalf("Write/Get HeadBlockHash failed") 204 } 205 } 206 207 // Tests that given a starting canonical chain of a given size, it can be extended 208 // with various length chains. 209 func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } 210 func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } 211 212 func testExtendCanonical(t *testing.T, full bool) { 213 length := 5 214 215 // Make first chain starting from genesis 216 _, processor, err := newCanonical(cryptore.NewFaker(), length, full) 217 if err != nil { 218 t.Fatalf("failed to make new canonical chain: %v", err) 219 } 220 defer processor.Stop() 221 222 // Define the difficulty comparator 223 better := func(td1, td2 *big.Int) { 224 if td2.Cmp(td1) <= 0 { 225 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 226 } 227 } 228 // Start fork from current height 229 testFork(t, processor, length, 1, full, better) 230 testFork(t, processor, length, 2, full, better) 231 testFork(t, processor, length, 5, full, better) 232 testFork(t, processor, length, 10, full, better) 233 } 234 235 // Tests that given a starting canonical chain of a given size, creating shorter 236 // forks do not take canonical ownership. 237 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } 238 func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } 239 240 func testShorterFork(t *testing.T, full bool) { 241 length := 10 242 243 // Make first chain starting from genesis 244 _, processor, err := newCanonical(cryptore.NewFaker(), length, full) 245 if err != nil { 246 t.Fatalf("failed to make new canonical chain: %v", err) 247 } 248 defer processor.Stop() 249 250 // Define the difficulty comparator 251 worse := func(td1, td2 *big.Int) { 252 if td2.Cmp(td1) >= 0 { 253 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 254 } 255 } 256 // Sum of numbers must be less than `length` for this to be a shorter fork 257 testFork(t, processor, 0, 3, full, worse) 258 testFork(t, processor, 0, 7, full, worse) 259 testFork(t, processor, 1, 1, full, worse) 260 testFork(t, processor, 1, 7, full, worse) 261 testFork(t, processor, 5, 3, full, worse) 262 testFork(t, processor, 5, 4, full, worse) 263 } 264 265 // Tests that given a starting canonical chain of a given size, creating longer 266 // forks do take canonical ownership. 267 func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } 268 func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } 269 270 func testLongerFork(t *testing.T, full bool) { 271 length := 10 272 273 // Make first chain starting from genesis 274 _, processor, err := newCanonical(cryptore.NewFaker(), length, full) 275 if err != nil { 276 t.Fatalf("failed to make new canonical chain: %v", err) 277 } 278 defer processor.Stop() 279 280 // Define the difficulty comparator 281 better := func(td1, td2 *big.Int) { 282 if td2.Cmp(td1) <= 0 { 283 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 284 } 285 } 286 // Sum of numbers must be greater than `length` for this to be a longer fork 287 testFork(t, processor, 0, 11, full, better) 288 testFork(t, processor, 0, 15, full, better) 289 testFork(t, processor, 1, 10, full, better) 290 testFork(t, processor, 1, 12, full, better) 291 testFork(t, processor, 5, 6, full, better) 292 testFork(t, processor, 5, 8, full, better) 293 } 294 295 // Tests that given a starting canonical chain of a given size, creating equal 296 // forks do take canonical ownership. 297 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } 298 func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } 299 300 func testEqualFork(t *testing.T, full bool) { 301 length := 10 302 303 // Make first chain starting from genesis 304 _, processor, err := newCanonical(cryptore.NewFaker(), length, full) 305 if err != nil { 306 t.Fatalf("failed to make new canonical chain: %v", err) 307 } 308 defer processor.Stop() 309 310 // Define the difficulty comparator 311 equal := func(td1, td2 *big.Int) { 312 if td2.Cmp(td1) != 0 { 313 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 314 } 315 } 316 // Sum of numbers must be equal to `length` for this to be an equal fork 317 testFork(t, processor, 0, 10, full, equal) 318 testFork(t, processor, 1, 9, full, equal) 319 testFork(t, processor, 2, 8, full, equal) 320 testFork(t, processor, 5, 5, full, equal) 321 testFork(t, processor, 6, 4, full, equal) 322 testFork(t, processor, 9, 1, full, equal) 323 } 324 325 // Tests that chains missing links do not get accepted by the processor. 326 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } 327 func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } 328 329 func testBrokenChain(t *testing.T, full bool) { 330 // Make chain starting from genesis 331 db, blockchain, err := newCanonical(cryptore.NewFaker(), 10, full) 332 if err != nil { 333 t.Fatalf("failed to make new canonical chain: %v", err) 334 } 335 defer blockchain.Stop() 336 337 // Create a forked chain, and try to insert with a missing link 338 if full { 339 chain := makeBlockChain(blockchain.CurrentBlock(), 5, cryptore.NewFaker(), db, forkSeed)[1:] 340 if err := testBlockChainImport(chain, blockchain); err == nil { 341 t.Errorf("broken block chain not reported") 342 } 343 } else { 344 chain := makeHeaderChain(blockchain.CurrentHeader(), 5, cryptore.NewFaker(), db, forkSeed)[1:] 345 if err := testHeaderChainImport(chain, blockchain); err == nil { 346 t.Errorf("broken header chain not reported") 347 } 348 } 349 } 350 351 // Tests that reorganising a long difficult chain after a short easy one 352 // overwrites the canonical numbers and links in the database. 353 func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) } 354 func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) } 355 356 func testReorgLong(t *testing.T, full bool) { 357 testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 24580, full) 358 } 359 360 // Tests that reorganising a short difficult chain after a long easy one 361 // overwrites the canonical numbers and links in the database. 362 func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) } 363 func TestReorgShortBlocks(t *testing.T) { testReorgShort(t, true) } 364 365 func testReorgShort(t *testing.T, full bool) { 366 // Create a long easy chain vs. a short heavy one. Due to difficulty adjustment 367 // we need a fairly long chain of blocks with different difficulties for a short 368 // one to become heavyer than a long one. The 96 is an empirical value. 369 easy := make([]int64, 96) 370 for i := 0; i < len(easy); i++ { 371 easy[i] = 60 372 } 373 diff := make([]int64, len(easy)-1) 374 for i := 0; i < len(diff); i++ { 375 diff[i] = -9 376 } 377 testReorg(t, easy, diff, 788288, full) 378 } 379 380 func testReorg(t *testing.T, first, second []int64, td int64, full bool) { 381 // Create a pristine chain and database 382 db, blockchain, err := newCanonical(cryptore.NewFaker(), 0, full) 383 if err != nil { 384 t.Fatalf("failed to create pristine chain: %v", err) 385 } 386 defer blockchain.Stop() 387 388 // Insert an easy and a difficult chain afterwards 389 easyBlocks, _ := GenerateChain(params.MainnetChainConfig, blockchain.CurrentBlock(), cryptore.NewFaker(), db, len(first), func(i int, b *BlockGen) { 390 b.OffsetTime(first[i]) 391 }) 392 diffBlocks, _ := GenerateChain(params.MainnetChainConfig, blockchain.CurrentBlock(), cryptore.NewFaker(), db, len(second), func(i int, b *BlockGen) { 393 b.OffsetTime(second[i]) 394 }) 395 if full { 396 if _, err := blockchain.InsertChain(easyBlocks); err != nil { 397 t.Fatalf("failed to insert easy chain: %v", err) 398 } 399 if _, err := blockchain.InsertChain(diffBlocks); err != nil { 400 t.Fatalf("failed to insert difficult chain: %v", err) 401 } 402 } else { 403 easyHeaders := make([]*types.Header, len(easyBlocks)) 404 for i, block := range easyBlocks { 405 easyHeaders[i] = block.Header() 406 } 407 diffHeaders := make([]*types.Header, len(diffBlocks)) 408 for i, block := range diffBlocks { 409 diffHeaders[i] = block.Header() 410 } 411 if _, err := blockchain.InsertHeaderChain(easyHeaders, 1); err != nil { 412 t.Fatalf("failed to insert easy chain: %v", err) 413 } 414 if _, err := blockchain.InsertHeaderChain(diffHeaders, 1); err != nil { 415 t.Fatalf("failed to insert difficult chain: %v", err) 416 } 417 } 418 // Check that the chain is valid number and link wise 419 if full { 420 prev := blockchain.CurrentBlock() 421 for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.GetBlockByNumber(block.NumberU64()-1) { 422 if prev.ParentHash() != block.Hash() { 423 t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) 424 } 425 } 426 } else { 427 prev := blockchain.CurrentHeader() 428 for header := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, blockchain.GetHeaderByNumber(header.Number.Uint64()-1) { 429 if prev.ParentHash != header.Hash() { 430 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 431 } 432 } 433 } 434 // Make sure the chain total difficulty is the correct one 435 want := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) 436 if full { 437 if have := blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()); have.Cmp(want) != 0 { 438 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 439 } 440 } else { 441 if have := blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()); have.Cmp(want) != 0 { 442 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 443 } 444 } 445 } 446 447 // Tests that the insertion functions detect banned hashes. 448 func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) } 449 func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) } 450 451 func testBadHashes(t *testing.T, full bool) { 452 // Create a pristine chain and database 453 db, blockchain, err := newCanonical(cryptore.NewFaker(), 0, full) 454 if err != nil { 455 t.Fatalf("failed to create pristine chain: %v", err) 456 } 457 defer blockchain.Stop() 458 459 // Create a chain, ban a hash and try to import 460 if full { 461 blocks := makeBlockChain(blockchain.CurrentBlock(), 3, cryptore.NewFaker(), db, 10) 462 463 BadHashes[blocks[2].Header().Hash()] = true 464 defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() 465 466 _, err = blockchain.InsertChain(blocks) 467 } else { 468 headers := makeHeaderChain(blockchain.CurrentHeader(), 3, cryptore.NewFaker(), db, 10) 469 470 BadHashes[headers[2].Hash()] = true 471 defer func() { delete(BadHashes, headers[2].Hash()) }() 472 473 _, err = blockchain.InsertHeaderChain(headers, 1) 474 } 475 if !errors.Is(err, ErrBlacklistedHash) { 476 t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash) 477 } 478 } 479 480 // Tests that bad hashes are detected on boot, and the chain rolled back to a 481 // good state prior to the bad hash. 482 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } 483 func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } 484 485 func testReorgBadHashes(t *testing.T, full bool) { 486 // Create a pristine chain and database 487 db, blockchain, err := newCanonical(cryptore.NewFaker(), 0, full) 488 if err != nil { 489 t.Fatalf("failed to create pristine chain: %v", err) 490 } 491 // Create a chain, import and ban afterwards 492 headers := makeHeaderChain(blockchain.CurrentHeader(), 4, cryptore.NewFaker(), db, 10) 493 blocks := makeBlockChain(blockchain.CurrentBlock(), 4, cryptore.NewFaker(), db, 10) 494 495 if full { 496 if _, err = blockchain.InsertChain(blocks); err != nil { 497 t.Errorf("failed to import blocks: %v", err) 498 } 499 if blockchain.CurrentBlock().Hash() != blocks[3].Hash() { 500 t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash()) 501 } 502 BadHashes[blocks[3].Header().Hash()] = true 503 defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() 504 } else { 505 if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil { 506 t.Errorf("failed to import headers: %v", err) 507 } 508 if blockchain.CurrentHeader().Hash() != headers[3].Hash() { 509 t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash()) 510 } 511 BadHashes[headers[3].Hash()] = true 512 defer func() { delete(BadHashes, headers[3].Hash()) }() 513 } 514 blockchain.Stop() 515 516 // Create a new BlockChain and check that it rolled back the state. 517 ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, cryptore.NewFaker(), vm.Config{}, nil, nil) 518 if err != nil { 519 t.Fatalf("failed to create new chain manager: %v", err) 520 } 521 if full { 522 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 523 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 524 } 525 if blocks[2].Header().EnergyLimit != ncm.EnergyLimit() { 526 t.Errorf("last block energyLimit mismatch: have: %d, want %d", ncm.EnergyLimit(), blocks[2].Header().EnergyLimit) 527 } 528 } else { 529 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 530 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 531 } 532 } 533 ncm.Stop() 534 } 535 536 // Tests chain insertions in the face of one entity containing an invalid nonce. 537 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } 538 func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } 539 540 func testInsertNonceError(t *testing.T, full bool) { 541 for i := 1; i < 25 && !t.Failed(); i++ { 542 // Create a pristine chain and database 543 db, blockchain, err := newCanonical(cryptore.NewFaker(), 0, full) 544 if err != nil { 545 t.Fatalf("failed to create pristine chain: %v", err) 546 } 547 defer blockchain.Stop() 548 549 // Create and insert a chain with a failing nonce 550 var ( 551 failAt int 552 failRes int 553 failNum uint64 554 ) 555 if full { 556 blocks := makeBlockChain(blockchain.CurrentBlock(), i, cryptore.NewFaker(), db, 0) 557 558 failAt = rand.Int() % len(blocks) 559 failNum = blocks[failAt].NumberU64() 560 561 blockchain.engine = cryptore.NewFakeFailer(failNum) 562 failRes, err = blockchain.InsertChain(blocks) 563 } else { 564 headers := makeHeaderChain(blockchain.CurrentHeader(), i, cryptore.NewFaker(), db, 0) 565 566 failAt = rand.Int() % len(headers) 567 failNum = headers[failAt].Number.Uint64() 568 569 blockchain.engine = cryptore.NewFakeFailer(failNum) 570 blockchain.hc.engine = blockchain.engine 571 failRes, err = blockchain.InsertHeaderChain(headers, 1) 572 } 573 // Check that the returned error indicates the failure 574 if failRes != failAt { 575 t.Errorf("test %d: failure (%v) index mismatch: have %d, want %d", i, err, failRes, failAt) 576 } 577 // Check that all blocks after the failing block have been inserted 578 for j := 0; j < i-failAt; j++ { 579 if full { 580 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 581 t.Errorf("test %d: invalid block in chain: %v", i, block) 582 } 583 } else { 584 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 585 t.Errorf("test %d: invalid header in chain: %v", i, header) 586 } 587 } 588 } 589 } 590 } 591 592 // Tests that fast importing a block chain produces the same chain data as the 593 // classical full block processing. 594 func TestFastVsFullChains(t *testing.T) { 595 // Configure and generate a sample block chain 596 var ( 597 gendb = rawdb.NewMemoryDatabase() 598 key, _ = crypto.UnmarshalPrivateKeyHex("ab856a9af6b0b651dd2f43b5e12193652ec1701c4da6f1c0d2a366ac4b9dabc9433ef09e41ca129552bd2c029086d9b03604de872a3b343204") 599 address = key.Address() 600 funds = big.NewInt(1000000000) 601 gspec = &Genesis{ 602 Config: params.MainnetChainConfig, 603 Alloc: GenesisAlloc{address: {Balance: funds}}, 604 } 605 genesis = gspec.MustCommit(gendb) 606 signer = types.NewNucleusSigner(gspec.Config.NetworkID) 607 ) 608 blocks, receipts := GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), gendb, 1024, func(i int, block *BlockGen) { 609 block.SetCoinbase(common.Address{0x00}) 610 611 // If the block number is multiple of 3, send a few bonus transactions to the miner 612 if i%3 == 2 { 613 for j := 0; j < i%4+1; j++ { 614 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxEnergy, nil, nil), signer, key) 615 if err != nil { 616 panic(err) 617 } 618 block.AddTx(tx) 619 } 620 } 621 // If the block number is a multiple of 5, add a few bonus uncles to the block 622 if i%5 == 5 { 623 block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))}) 624 } 625 }) 626 // Import the chain as an archive node for the comparison baseline 627 archiveDb := rawdb.NewMemoryDatabase() 628 gspec.MustCommit(archiveDb) 629 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 630 defer archive.Stop() 631 632 if n, err := archive.InsertChain(blocks); err != nil { 633 t.Fatalf("failed to process block %d: %v", n, err) 634 } 635 // Fast import the chain as a non-archive node to test 636 fastDb := rawdb.NewMemoryDatabase() 637 gspec.MustCommit(fastDb) 638 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 639 defer fast.Stop() 640 641 headers := make([]*types.Header, len(blocks)) 642 for i, block := range blocks { 643 headers[i] = block.Header() 644 } 645 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 646 t.Fatalf("failed to insert header %d: %v", n, err) 647 } 648 if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { 649 t.Fatalf("failed to insert receipt %d: %v", n, err) 650 } 651 // Freezer style fast import the chain. 652 frdir, err := ioutil.TempDir("", "") 653 if err != nil { 654 t.Fatalf("failed to create temp freezer dir: %v", err) 655 } 656 defer os.Remove(frdir) 657 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 658 if err != nil { 659 t.Fatalf("failed to create temp freezer db: %v", err) 660 } 661 gspec.MustCommit(ancientDb) 662 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 663 defer ancient.Stop() 664 665 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 666 t.Fatalf("failed to insert header %d: %v", n, err) 667 } 668 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(len(blocks)/2)); err != nil { 669 t.Fatalf("failed to insert receipt %d: %v", n, err) 670 } 671 // Iterate over all chain data components, and cross reference 672 for i := 0; i < len(blocks); i++ { 673 num, hash := blocks[i].NumberU64(), blocks[i].Hash() 674 675 if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 { 676 t.Errorf("block #%d [%x]: td mismatch: fastdb %v, archivedb %v", num, hash, ftd, atd) 677 } 678 if antd, artd := ancient.GetTdByHash(hash), archive.GetTdByHash(hash); antd.Cmp(artd) != 0 { 679 t.Errorf("block #%d [%x]: td mismatch: ancientdb %v, archivedb %v", num, hash, antd, artd) 680 } 681 if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { 682 t.Errorf("block #%d [%x]: header mismatch: fastdb %v, archivedb %v", num, hash, fheader, aheader) 683 } 684 if anheader, arheader := ancient.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); anheader.Hash() != arheader.Hash() { 685 t.Errorf("block #%d [%x]: header mismatch: ancientdb %v, archivedb %v", num, hash, anheader, arheader) 686 } 687 if fblock, arblock, anblock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash), ancient.GetBlockByHash(hash); fblock.Hash() != arblock.Hash() || anblock.Hash() != arblock.Hash() { 688 t.Errorf("block #%d [%x]: block mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock, anblock, arblock) 689 } else if types.DeriveSha(fblock.Transactions(), new(trie.Trie)) != types.DeriveSha(arblock.Transactions(), new(trie.Trie)) || types.DeriveSha(anblock.Transactions(), new(trie.Trie)) != types.DeriveSha(arblock.Transactions(), new(trie.Trie)) { 690 t.Errorf("block #%d [%x]: transactions mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock.Transactions(), anblock.Transactions(), arblock.Transactions()) 691 } else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(arblock.Uncles()) || types.CalcUncleHash(anblock.Uncles()) != types.CalcUncleHash(arblock.Uncles()) { 692 t.Errorf("block #%d [%x]: uncles mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock.Uncles(), anblock, arblock.Uncles()) 693 } 694 if freceipts, anreceipts, areceipts := rawdb.ReadReceipts(fastDb, hash, *rawdb.ReadHeaderNumber(fastDb, hash), fast.Config()), rawdb.ReadReceipts(ancientDb, hash, *rawdb.ReadHeaderNumber(ancientDb, hash), fast.Config()), rawdb.ReadReceipts(archiveDb, hash, *rawdb.ReadHeaderNumber(archiveDb, hash), fast.Config()); types.DeriveSha(freceipts, new(trie.Trie)) != types.DeriveSha(areceipts, new(trie.Trie)) { 695 t.Errorf("block #%d [%x]: receipts mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, freceipts, anreceipts, areceipts) 696 } 697 } 698 // Check that the canonical chains are the same between the databases 699 for i := 0; i < len(blocks)+1; i++ { 700 if fhash, ahash := rawdb.ReadCanonicalHash(fastDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); fhash != ahash { 701 t.Errorf("block #%d: canonical hash mismatch: fastdb %v, archivedb %v", i, fhash, ahash) 702 } 703 if anhash, arhash := rawdb.ReadCanonicalHash(ancientDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); anhash != arhash { 704 t.Errorf("block #%d: canonical hash mismatch: ancientdb %v, archivedb %v", i, anhash, arhash) 705 } 706 } 707 } 708 709 // Tests that various import methods move the chain head pointers to the correct 710 // positions. 711 func TestLightVsFastVsFullChainHeads(t *testing.T) { 712 // Configure and generate a sample block chain 713 var ( 714 gendb = rawdb.NewMemoryDatabase() 715 key, _ = crypto.UnmarshalPrivateKeyHex("ab856a9af6b0b651dd2f43b5e12193652ec1701c4da6f1c0d2a366ac4b9dabc9433ef09e41ca129552bd2c029086d9b03604de872a3b343204") 716 address = key.Address() 717 funds = big.NewInt(1000000000) 718 gspec = &Genesis{Config: params.MainnetChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 719 genesis = gspec.MustCommit(gendb) 720 ) 721 height := uint64(1024) 722 blocks, receipts := GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), gendb, int(height), nil) 723 724 // makeDb creates a db instance for testing. 725 makeDb := func() (xcbdb.Database, func()) { 726 dir, err := ioutil.TempDir("", "") 727 if err != nil { 728 t.Fatalf("failed to create temp freezer dir: %v", err) 729 } 730 defer os.Remove(dir) 731 db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "") 732 if err != nil { 733 t.Fatalf("failed to create temp freezer db: %v", err) 734 } 735 gspec.MustCommit(db) 736 return db, func() { os.RemoveAll(dir) } 737 } 738 // Configure a subchain to roll back 739 remove := blocks[height/2].NumberU64() 740 741 // Create a small assertion method to check the three heads 742 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 743 t.Helper() 744 745 if num := chain.CurrentBlock().NumberU64(); num != block { 746 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 747 } 748 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 749 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 750 } 751 if num := chain.CurrentHeader().Number.Uint64(); num != header { 752 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 753 } 754 } 755 // Import the chain as an archive node and ensure all pointers are updated 756 archiveDb, delfn := makeDb() 757 defer delfn() 758 759 archiveCaching := *defaultCacheConfig 760 archiveCaching.TrieDirtyDisabled = true 761 762 archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 763 if n, err := archive.InsertChain(blocks); err != nil { 764 t.Fatalf("failed to process block %d: %v", n, err) 765 } 766 defer archive.Stop() 767 768 assert(t, "archive", archive, height, height, height) 769 archive.SetHead(remove - 1) 770 assert(t, "archive", archive, height/2, height/2, height/2) 771 772 // Import the chain as a non-archive node and ensure all pointers are updated 773 fastDb, delfn := makeDb() 774 defer delfn() 775 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 776 defer fast.Stop() 777 778 headers := make([]*types.Header, len(blocks)) 779 for i, block := range blocks { 780 headers[i] = block.Header() 781 } 782 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 783 t.Fatalf("failed to insert header %d: %v", n, err) 784 } 785 if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { 786 t.Fatalf("failed to insert receipt %d: %v", n, err) 787 } 788 assert(t, "fast", fast, height, height, 0) 789 fast.SetHead(remove - 1) 790 assert(t, "fast", fast, height/2, height/2, 0) 791 792 // Import the chain as a ancient-first node and ensure all pointers are updated 793 ancientDb, delfn := makeDb() 794 defer delfn() 795 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 796 defer ancient.Stop() 797 798 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 799 t.Fatalf("failed to insert header %d: %v", n, err) 800 } 801 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 802 t.Fatalf("failed to insert receipt %d: %v", n, err) 803 } 804 assert(t, "ancient", ancient, height, height, 0) 805 ancient.SetHead(remove - 1) 806 assert(t, "ancient", ancient, 0, 0, 0) 807 808 if frozen, err := ancientDb.Ancients(); err != nil || frozen != 1 { 809 t.Fatalf("failed to truncate ancient store, want %v, have %v", 1, frozen) 810 } 811 // Import the chain as a light node and ensure all pointers are updated 812 lightDb, delfn := makeDb() 813 defer delfn() 814 light, _ := NewBlockChain(lightDb, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 815 if n, err := light.InsertHeaderChain(headers, 1); err != nil { 816 t.Fatalf("failed to insert header %d: %v", n, err) 817 } 818 defer light.Stop() 819 820 assert(t, "light", light, height, 0, 0) 821 light.SetHead(remove - 1) 822 assert(t, "light", light, height/2, 0, 0) 823 } 824 825 // Tests that chain reorganisations handle transaction removals and reinsertions. 826 func TestChainTxReorgs(t *testing.T) { 827 var ( 828 key1, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 829 key2, _ = crypto.UnmarshalPrivateKeyHex("ab856a9af6b0b651dd2f43b5e12193652ec1701c4da6f1c0d2a366ac4b9dabc9433ef09e41ca129552bd2c029086d9b03604de872a3b343204") 830 key3, _ = crypto.UnmarshalPrivateKeyHex("c0b711eea422df26d5ffdcaae35fe0527cf647c5ce62d3efb5e09a0e14fc8afe57fac1a5daa330bc10bfa1d3db11e172a822dcfffb86a0b26d") 831 db = rawdb.NewMemoryDatabase() 832 gspec = &Genesis{ 833 Config: params.MainnetChainConfig, 834 EnergyLimit: 3141592, 835 Alloc: GenesisAlloc{ 836 key1.Address(): {Balance: big.NewInt(1000000)}, 837 key2.Address(): {Balance: big.NewInt(1000000)}, 838 key3.Address(): {Balance: big.NewInt(1000000)}, 839 }, 840 } 841 genesis = gspec.MustCommit(db) 842 signer = types.NewNucleusSigner(gspec.Config.NetworkID) 843 ) 844 845 // Create two transactions shared between the chains: 846 // - postponed: transaction included at a later block in the forked chain 847 // - swapped: transaction included at the same block number in the forked chain 848 postponed, _ := types.SignTx(types.NewTransaction(0, key1.Address(), big.NewInt(1000), params.TxEnergy, nil, nil), signer, key1) 849 swapped, _ := types.SignTx(types.NewTransaction(1, key1.Address(), big.NewInt(1000), params.TxEnergy, nil, nil), signer, key1) 850 851 // Create two transactions that will be dropped by the forked chain: 852 // - pastDrop: transaction dropped retroactively from a past block 853 // - freshDrop: transaction dropped exactly at the block where the reorg is detected 854 var pastDrop, freshDrop *types.Transaction 855 856 // Create three transactions that will be added in the forked chain: 857 // - pastAdd: transaction added before the reorganization is detected 858 // - freshAdd: transaction added at the exact block the reorg is detected 859 // - futureAdd: transaction added after the reorg has already finished 860 var pastAdd, freshAdd, futureAdd *types.Transaction 861 862 chain, _ := GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), db, 3, func(i int, gen *BlockGen) { 863 switch i { 864 case 0: 865 pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(key2.Address()), key2.Address(), big.NewInt(1000), params.TxEnergy, nil, nil), signer, key2) 866 867 gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point 868 gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork 869 870 case 2: 871 freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(key2.Address()), key2.Address(), big.NewInt(1000), params.TxEnergy, nil, nil), signer, key2) 872 873 gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point 874 gen.AddTx(swapped) // This transaction will be swapped out at the exact height 875 876 gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain 877 } 878 }) 879 // Import the chain. This runs all block validation rules. 880 blockchain, _ := NewBlockChain(db, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 881 if i, err := blockchain.InsertChain(chain); err != nil { 882 t.Fatalf("failed to insert original chain[%d]: %v", i, err) 883 } 884 defer blockchain.Stop() 885 886 // overwrite the old chain 887 chain, _ = GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), db, 5, func(i int, gen *BlockGen) { 888 switch i { 889 case 0: 890 pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(key3.Address()), key3.Address(), big.NewInt(1000), params.TxEnergy, nil, nil), signer, key3) 891 gen.AddTx(pastAdd) // This transaction needs to be injected during reorg 892 893 case 2: 894 gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain 895 gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain 896 897 freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(key3.Address()), key3.Address(), big.NewInt(1000), params.TxEnergy, nil, nil), signer, key3) 898 gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time 899 900 case 3: 901 futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(key3.Address()), key3.Address(), big.NewInt(1000), params.TxEnergy, nil, nil), signer, key3) 902 gen.AddTx(futureAdd) // This transaction will be added after a full reorg 903 } 904 }) 905 if _, err := blockchain.InsertChain(chain); err != nil { 906 t.Fatalf("failed to insert forked chain: %v", err) 907 } 908 909 // removed tx 910 for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 911 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil { 912 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 913 } 914 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt != nil { 915 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 916 } 917 } 918 // added tx 919 for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 920 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 921 t.Errorf("add %d: expected tx to be found", i) 922 } 923 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { 924 t.Errorf("add %d: expected receipt to be found", i) 925 } 926 } 927 // shared tx 928 for i, tx := range (types.Transactions{postponed, swapped}) { 929 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 930 t.Errorf("share %d: expected tx to be found", i) 931 } 932 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { 933 t.Errorf("share %d: expected receipt to be found", i) 934 } 935 } 936 } 937 938 func TestLogReorgs(t *testing.T) { 939 var ( 940 key1, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 941 db = rawdb.NewMemoryDatabase() 942 // this code generates a log 943 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 944 gspec = &Genesis{Config: params.MainnetChainConfig, Alloc: GenesisAlloc{key1.Address(): {Balance: big.NewInt(10000000000000)}}} 945 genesis = gspec.MustCommit(db) 946 signer = types.NewNucleusSigner(gspec.Config.NetworkID) 947 ) 948 949 blockchain, _ := NewBlockChain(db, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 950 defer blockchain.Stop() 951 952 rmLogsCh := make(chan RemovedLogsEvent) 953 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 954 chain, _ := GenerateChain(params.MainnetChainConfig, genesis, cryptore.NewFaker(), db, 2, func(i int, gen *BlockGen) { 955 if i == 1 { 956 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(key1.Address()), new(big.Int), 1000000, new(big.Int), code), signer, key1) 957 if err != nil { 958 t.Fatalf("failed to create tx: %v", err) 959 } 960 gen.AddTx(tx) 961 } 962 }) 963 if _, err := blockchain.InsertChain(chain); err != nil { 964 t.Fatalf("failed to insert chain: %v", err) 965 } 966 967 chain, _ = GenerateChain(params.MainnetChainConfig, genesis, cryptore.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 968 done := make(chan struct{}) 969 go func() { 970 ev := <-rmLogsCh 971 if len(ev.Logs) == 0 { 972 t.Error("expected logs") 973 } 974 close(done) 975 }() 976 if _, err := blockchain.InsertChain(chain); err != nil { 977 t.Fatalf("failed to insert forked chain: %v", err) 978 } 979 timeout := time.NewTimer(1 * time.Second) 980 defer timeout.Stop() 981 select { 982 case <-done: 983 case <-timeout.C: 984 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 985 } 986 } 987 988 // This CVM code generates a log when the contract is created. 989 var logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 990 991 // This test checks that log events and RemovedLogsEvent are sent 992 // when the chain reorganizes. 993 func TestLogRebirth(t *testing.T) { 994 var ( 995 key1, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 996 db = rawdb.NewMemoryDatabase() 997 gspec = &Genesis{Config: params.MainnetChainConfig, Alloc: GenesisAlloc{key1.Address(): {Balance: big.NewInt(10000000000000)}}} 998 genesis = gspec.MustCommit(db) 999 signer = types.NewNucleusSigner(gspec.Config.NetworkID) 1000 engine = cryptore.NewFaker() 1001 blockchain, _ = NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil, nil) 1002 ) 1003 1004 defer blockchain.Stop() 1005 1006 // The event channels. 1007 newLogCh := make(chan []*types.Log, 10) 1008 rmLogsCh := make(chan RemovedLogsEvent, 10) 1009 blockchain.SubscribeLogsEvent(newLogCh) 1010 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 1011 1012 // This chain contains a single log. 1013 chain, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 2, func(i int, gen *BlockGen) { 1014 if i == 1 { 1015 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(key1.Address()), new(big.Int), 1000000, new(big.Int), logCode), signer, key1) 1016 if err != nil { 1017 t.Fatalf("failed to create tx: %v", err) 1018 } 1019 gen.AddTx(tx) 1020 } 1021 }) 1022 if _, err := blockchain.InsertChain(chain); err != nil { 1023 t.Fatalf("failed to insert chain: %v", err) 1024 } 1025 checkLogEvents(t, newLogCh, rmLogsCh, 1, 0) 1026 1027 // Generate long reorg chain containing another log. Inserting the 1028 // chain removes one log and adds one. 1029 forkChain, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 2, func(i int, gen *BlockGen) { 1030 if i == 1 { 1031 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(key1.Address()), new(big.Int), 1000000, new(big.Int), logCode), signer, key1) 1032 if err != nil { 1033 t.Fatalf("failed to create tx: %v", err) 1034 } 1035 gen.AddTx(tx) 1036 gen.OffsetTime(-9) // higher block difficulty 1037 } 1038 }) 1039 if _, err := blockchain.InsertChain(forkChain); err != nil { 1040 t.Fatalf("failed to insert forked chain: %v", err) 1041 } 1042 checkLogEvents(t, newLogCh, rmLogsCh, 1, 1) 1043 1044 // This chain segment is rooted in the original chain, but doesn't contain any logs. 1045 // When inserting it, the canonical chain switches away from forkChain and re-emits 1046 // the log event for the old chain, as well as a RemovedLogsEvent for forkChain. 1047 newBlocks, _ := GenerateChain(params.MainnetChainConfig, chain[len(chain)-1], engine, db, 1, func(i int, gen *BlockGen) {}) 1048 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1049 t.Fatalf("failed to insert forked chain: %v", err) 1050 } 1051 checkLogEvents(t, newLogCh, rmLogsCh, 1, 1) 1052 } 1053 1054 // This test is a variation of TestLogRebirth. It verifies that log events are emitted 1055 // when a side chain containing log events overtakes the canonical chain. 1056 func TestSideLogRebirth(t *testing.T) { 1057 var ( 1058 key1, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 1059 db = rawdb.NewMemoryDatabase() 1060 gspec = &Genesis{Config: params.MainnetChainConfig, Alloc: GenesisAlloc{key1.Address(): {Balance: big.NewInt(10000000000000)}}} 1061 genesis = gspec.MustCommit(db) 1062 signer = types.NewNucleusSigner(gspec.Config.NetworkID) 1063 blockchain, _ = NewBlockChain(db, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 1064 ) 1065 1066 defer blockchain.Stop() 1067 1068 newLogCh := make(chan []*types.Log, 10) 1069 rmLogsCh := make(chan RemovedLogsEvent, 10) 1070 blockchain.SubscribeLogsEvent(newLogCh) 1071 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 1072 1073 chain, _ := GenerateChain(params.MainnetChainConfig, genesis, cryptore.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1074 if i == 1 { 1075 gen.OffsetTime(-9) // higher block difficulty 1076 1077 } 1078 }) 1079 if _, err := blockchain.InsertChain(chain); err != nil { 1080 t.Fatalf("failed to insert forked chain: %v", err) 1081 } 1082 checkLogEvents(t, newLogCh, rmLogsCh, 0, 0) 1083 1084 // Generate side chain with lower difficulty 1085 sideChain, _ := GenerateChain(params.MainnetChainConfig, genesis, cryptore.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1086 if i == 1 { 1087 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(key1.Address()), new(big.Int), 1000000, new(big.Int), logCode), signer, key1) 1088 if err != nil { 1089 t.Fatalf("failed to create tx: %v", err) 1090 } 1091 gen.AddTx(tx) 1092 } 1093 }) 1094 if _, err := blockchain.InsertChain(sideChain); err != nil { 1095 t.Fatalf("failed to insert forked chain: %v", err) 1096 } 1097 checkLogEvents(t, newLogCh, rmLogsCh, 0, 0) 1098 1099 // Generate a new block based on side chain. 1100 newBlocks, _ := GenerateChain(params.MainnetChainConfig, sideChain[len(sideChain)-1], cryptore.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) 1101 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1102 t.Fatalf("failed to insert forked chain: %v", err) 1103 } 1104 checkLogEvents(t, newLogCh, rmLogsCh, 1, 0) 1105 } 1106 1107 func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan RemovedLogsEvent, wantNew, wantRemoved int) { 1108 t.Helper() 1109 1110 if len(logsCh) != wantNew { 1111 t.Fatalf("wrong number of log events: got %d, want %d", len(logsCh), wantNew) 1112 } 1113 if len(rmLogsCh) != wantRemoved { 1114 t.Fatalf("wrong number of removed log events: got %d, want %d", len(rmLogsCh), wantRemoved) 1115 } 1116 // Drain events. 1117 for i := 0; i < len(logsCh); i++ { 1118 <-logsCh 1119 } 1120 for i := 0; i < len(rmLogsCh); i++ { 1121 <-rmLogsCh 1122 } 1123 } 1124 1125 func TestReorgSideEvent(t *testing.T) { 1126 var ( 1127 db = rawdb.NewMemoryDatabase() 1128 key1, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 1129 gspec = &Genesis{ 1130 Config: params.MainnetChainConfig, 1131 Alloc: GenesisAlloc{key1.Address(): {Balance: big.NewInt(10000000000000)}}, 1132 } 1133 genesis = gspec.MustCommit(db) 1134 signer = types.NewNucleusSigner(gspec.Config.NetworkID) 1135 ) 1136 1137 blockchain, _ := NewBlockChain(db, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 1138 defer blockchain.Stop() 1139 1140 chain, _ := GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 1141 if _, err := blockchain.InsertChain(chain); err != nil { 1142 t.Fatalf("failed to insert chain: %v", err) 1143 } 1144 1145 replacementBlocks, _ := GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), db, 4, func(i int, gen *BlockGen) { 1146 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(key1.Address()), new(big.Int), 1000000, new(big.Int), nil), signer, key1) 1147 if i == 2 { 1148 gen.OffsetTime(-9) 1149 } 1150 if err != nil { 1151 t.Fatalf("failed to create tx: %v", err) 1152 } 1153 gen.AddTx(tx) 1154 }) 1155 chainSideCh := make(chan ChainSideEvent, 64) 1156 blockchain.SubscribeChainSideEvent(chainSideCh) 1157 if _, err := blockchain.InsertChain(replacementBlocks); err != nil { 1158 t.Fatalf("failed to insert chain: %v", err) 1159 } 1160 1161 // first two block of the secondary chain are for a brief moment considered 1162 // side chains because up to that point the first one is considered the 1163 // heavier chain. 1164 expectedSideHashes := map[common.Hash]bool{ 1165 replacementBlocks[0].Hash(): true, 1166 replacementBlocks[1].Hash(): true, 1167 chain[0].Hash(): true, 1168 chain[1].Hash(): true, 1169 chain[2].Hash(): true, 1170 } 1171 1172 i := 0 1173 1174 const timeoutDura = 10 * time.Second 1175 timeout := time.NewTimer(timeoutDura) 1176 done: 1177 for { 1178 select { 1179 case ev := <-chainSideCh: 1180 block := ev.Block 1181 if _, ok := expectedSideHashes[block.Hash()]; !ok { 1182 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 1183 } 1184 i++ 1185 1186 if i == len(expectedSideHashes) { 1187 timeout.Stop() 1188 1189 break done 1190 } 1191 timeout.Reset(timeoutDura) 1192 1193 case <-timeout.C: 1194 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 1195 } 1196 } 1197 1198 // make sure no more events are fired 1199 select { 1200 case e := <-chainSideCh: 1201 t.Errorf("unexpected event fired: %v", e) 1202 case <-time.After(250 * time.Millisecond): 1203 } 1204 1205 } 1206 1207 // Tests if the canonical block can be fetched from the database during chain insertion. 1208 func TestCanonicalBlockRetrieval(t *testing.T) { 1209 _, blockchain, err := newCanonical(cryptore.NewFaker(), 0, true) 1210 if err != nil { 1211 t.Fatalf("failed to create pristine chain: %v", err) 1212 } 1213 defer blockchain.Stop() 1214 1215 chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, cryptore.NewFaker(), blockchain.db, 10, func(i int, gen *BlockGen) {}) 1216 1217 var pend sync.WaitGroup 1218 pend.Add(len(chain)) 1219 1220 for i := range chain { 1221 go func(block *types.Block) { 1222 defer pend.Done() 1223 1224 // try to retrieve a block by its canonical hash and see if the block data can be retrieved. 1225 for { 1226 ch := rawdb.ReadCanonicalHash(blockchain.db, block.NumberU64()) 1227 if ch == (common.Hash{}) { 1228 continue // busy wait for canonical hash to be written 1229 } 1230 if ch != block.Hash() { 1231 t.Errorf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1232 return 1233 } 1234 fb := rawdb.ReadBlock(blockchain.db, ch, block.NumberU64()) 1235 if fb == nil { 1236 t.Errorf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1237 return 1238 } 1239 if fb.Hash() != block.Hash() { 1240 t.Errorf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1241 return 1242 } 1243 return 1244 } 1245 }(chain[i]) 1246 1247 if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { 1248 t.Fatalf("failed to insert block %d: %v", i, err) 1249 } 1250 } 1251 pend.Wait() 1252 } 1253 1254 func TestCIP155Transition(t *testing.T) { 1255 // Configure and generate a sample block chain 1256 var ( 1257 db = rawdb.NewMemoryDatabase() 1258 key, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 1259 address = key.Address() 1260 funds = big.NewInt(1000000000) 1261 deleteAddr = common.Address{1} 1262 gspec = &Genesis{ 1263 Config: ¶ms.ChainConfig{NetworkID: big.NewInt(1)}, 1264 Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 1265 } 1266 genesis = gspec.MustCommit(db) 1267 ) 1268 1269 blockchain, _ := NewBlockChain(db, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 1270 defer blockchain.Stop() 1271 1272 blocks, _ := GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), db, 4, func(i int, block *BlockGen) { 1273 var ( 1274 tx *types.Transaction 1275 err error 1276 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1277 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1278 } 1279 ) 1280 switch i { 1281 case 0: 1282 tx, err = basicTx(types.NewNucleusSigner(big.NewInt(1))) 1283 if err != nil { 1284 t.Fatal(err) 1285 } 1286 block.AddTx(tx) 1287 case 2: 1288 tx, err = basicTx(types.NewNucleusSigner(big.NewInt(1))) 1289 if err != nil { 1290 t.Fatal(err) 1291 } 1292 block.AddTx(tx) 1293 1294 tx, err = basicTx(types.NewNucleusSigner(gspec.Config.NetworkID)) 1295 if err != nil { 1296 t.Fatal(err) 1297 } 1298 block.AddTx(tx) 1299 case 3: 1300 tx, err = basicTx(types.NewNucleusSigner(big.NewInt(1))) 1301 if err != nil { 1302 t.Fatal(err) 1303 } 1304 block.AddTx(tx) 1305 1306 tx, err = basicTx(types.NewNucleusSigner(gspec.Config.NetworkID)) 1307 if err != nil { 1308 t.Fatal(err) 1309 } 1310 block.AddTx(tx) 1311 } 1312 }) 1313 1314 if _, err := blockchain.InsertChain(blocks); err != nil { 1315 t.Fatal(err) 1316 } 1317 if _, err := blockchain.InsertChain(blocks[4:]); err != nil { 1318 t.Fatal(err) 1319 } 1320 1321 // generate an invalid chain id transaction 1322 config := ¶ms.ChainConfig{NetworkID: big.NewInt(2)} 1323 blocks, _ = GenerateChain(config, blocks[len(blocks)-1], cryptore.NewFaker(), db, 4, func(i int, block *BlockGen) { 1324 var ( 1325 tx *types.Transaction 1326 err error 1327 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1328 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1329 } 1330 ) 1331 if i == 0 { 1332 tx, err = basicTx(types.NewNucleusSigner(big.NewInt(2))) 1333 if err != nil { 1334 t.Fatal(err) 1335 } 1336 block.AddTx(tx) 1337 } 1338 }) 1339 _, err := blockchain.InsertChain(blocks) 1340 if err != types.ErrInvalidNetworkId { 1341 t.Error("expected error:", types.ErrInvalidNetworkId) 1342 } 1343 } 1344 1345 func TestCIP161AccountRemoval(t *testing.T) { 1346 // Configure and generate a sample block chain 1347 var ( 1348 db = rawdb.NewMemoryDatabase() 1349 key, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 1350 addrKey, _ = crypto.GenerateKey(crand.Reader) 1351 address = key.Address() 1352 funds = big.NewInt(1000000000) 1353 theAddr = addrKey.Address() 1354 gspec = &Genesis{ 1355 Config: ¶ms.ChainConfig{ 1356 NetworkID: big.NewInt(1), 1357 }, 1358 Alloc: GenesisAlloc{address: {Balance: funds}}, 1359 } 1360 genesis = gspec.MustCommit(db) 1361 ) 1362 blockchain, _ := NewBlockChain(db, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 1363 defer blockchain.Stop() 1364 1365 blocks, _ := GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), db, 3, func(i int, block *BlockGen) { 1366 var ( 1367 tx *types.Transaction 1368 err error 1369 signer = types.NewNucleusSigner(gspec.Config.NetworkID) 1370 ) 1371 switch i { 1372 case 0: 1373 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1374 case 1: 1375 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1376 case 2: 1377 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1378 } 1379 if err != nil { 1380 t.Fatal(err) 1381 } 1382 block.AddTx(tx) 1383 }) 1384 if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1385 t.Fatal(err) 1386 } 1387 1388 // account needs to be deleted 1389 if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1390 t.Fatal(err) 1391 } 1392 if st, _ := blockchain.State(); st.Exist(theAddr) { 1393 t.Error("account should not exist") 1394 } 1395 1396 // account mustn't be created 1397 if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1398 t.Fatal(err) 1399 } 1400 if st, _ := blockchain.State(); st.Exist(theAddr) { 1401 t.Error("account should not exist") 1402 } 1403 } 1404 1405 // This is a regression test (i.e. as weird as it is, don't delete it ever), which 1406 // tests that under weird reorg conditions the blockchain and its internal header- 1407 // chain return the same latest block/header. 1408 // 1409 // https://github.com/core-coin/go-core/v2/pull/15941 1410 func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { 1411 // Generate a canonical chain to act as the main dataset 1412 engine := cryptore.NewFaker() 1413 1414 db := rawdb.NewMemoryDatabase() 1415 genesis := new(Genesis).MustCommit(db) 1416 blocks, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1417 1418 // Generate a bunch of fork blocks, each side forking from the canonical chain 1419 forks := make([]*types.Block, len(blocks)) 1420 for i := 0; i < len(forks); i++ { 1421 parent := genesis 1422 if i > 0 { 1423 parent = blocks[i-1] 1424 } 1425 fork, _ := GenerateChain(params.MainnetChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1426 forks[i] = fork[0] 1427 } 1428 // Import the canonical and fork chain side by side, verifying the current block 1429 // and current header consistency 1430 diskdb := rawdb.NewMemoryDatabase() 1431 new(Genesis).MustCommit(diskdb) 1432 1433 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{}, nil, nil) 1434 if err != nil { 1435 t.Fatalf("failed to create tester chain: %v", err) 1436 } 1437 for i := 0; i < len(blocks); i++ { 1438 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1439 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1440 } 1441 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1442 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]) 1443 } 1444 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1445 t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) 1446 } 1447 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1448 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]) 1449 } 1450 } 1451 } 1452 1453 // Tests that importing small side forks doesn't leave junk in the trie database 1454 // cache (which would eventually cause memory issues). 1455 func TestTrieForkGC(t *testing.T) { 1456 // Generate a canonical chain to act as the main dataset 1457 engine := cryptore.NewFaker() 1458 1459 db := rawdb.NewMemoryDatabase() 1460 genesis := new(Genesis).MustCommit(db) 1461 blocks, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1462 1463 // Generate a bunch of fork blocks, each side forking from the canonical chain 1464 forks := make([]*types.Block, len(blocks)) 1465 for i := 0; i < len(forks); i++ { 1466 parent := genesis 1467 if i > 0 { 1468 parent = blocks[i-1] 1469 } 1470 fork, _ := GenerateChain(params.MainnetChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1471 forks[i] = fork[0] 1472 } 1473 // Import the canonical and fork chain side by side, forcing the trie cache to cache both 1474 diskdb := rawdb.NewMemoryDatabase() 1475 new(Genesis).MustCommit(diskdb) 1476 1477 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{}, nil, nil) 1478 if err != nil { 1479 t.Fatalf("failed to create tester chain: %v", err) 1480 } 1481 for i := 0; i < len(blocks); i++ { 1482 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1483 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1484 } 1485 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1486 t.Fatalf("fork %d: failed to insert into chain: %v", i, err) 1487 } 1488 } 1489 // Dereference all the recent tries and ensure no past trie is left in 1490 for i := 0; i < TriesInMemory; i++ { 1491 chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) 1492 chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) 1493 } 1494 if len(chain.stateCache.TrieDB().Nodes()) > 0 { 1495 t.Fatalf("stale tries still alive after garbase collection") 1496 } 1497 } 1498 1499 // Tests that doing large reorgs works even if the state associated with the 1500 // forking point is not available any more. 1501 func TestLargeReorgTrieGC(t *testing.T) { 1502 // Generate the original common chain segment and the two competing forks 1503 engine := cryptore.NewFaker() 1504 1505 db := rawdb.NewMemoryDatabase() 1506 genesis := new(Genesis).MustCommit(db) 1507 1508 shared, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1509 original, _ := GenerateChain(params.MainnetChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1510 competitor, _ := GenerateChain(params.MainnetChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) 1511 1512 // Import the shared chain and the original canonical one 1513 diskdb := rawdb.NewMemoryDatabase() 1514 new(Genesis).MustCommit(diskdb) 1515 1516 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{}, nil, nil) 1517 if err != nil { 1518 t.Fatalf("failed to create tester chain: %v", err) 1519 } 1520 if _, err := chain.InsertChain(shared); err != nil { 1521 t.Fatalf("failed to insert shared chain: %v", err) 1522 } 1523 if _, err := chain.InsertChain(original); err != nil { 1524 t.Fatalf("failed to insert original chain: %v", err) 1525 } 1526 // Ensure that the state associated with the forking point is pruned away 1527 if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil { 1528 t.Fatalf("common-but-old ancestor still cache") 1529 } 1530 // Import the competitor chain without exceeding the canonical's TD and ensure 1531 // we have not processed any of the blocks (protection against malicious blocks) 1532 if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { 1533 t.Fatalf("failed to insert competitor chain: %v", err) 1534 } 1535 for i, block := range competitor[:len(competitor)-2] { 1536 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1537 t.Fatalf("competitor %d: low TD chain became processed", i) 1538 } 1539 } 1540 // Import the head of the competitor chain, triggering the reorg and ensure we 1541 // successfully reprocess all the stashed away blocks. 1542 if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { 1543 t.Fatalf("failed to finalize competitor chain: %v", err) 1544 } 1545 for i, block := range competitor[:len(competitor)-TriesInMemory] { 1546 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1547 t.Fatalf("competitor %d: competing chain state missing", i) 1548 } 1549 } 1550 } 1551 1552 func TestBlockchainRecovery(t *testing.T) { 1553 // Configure and generate a sample block chain 1554 var ( 1555 gendb = rawdb.NewMemoryDatabase() 1556 key, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 1557 address = key.Address() 1558 funds = big.NewInt(1000000000) 1559 gspec = &Genesis{Config: params.MainnetChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 1560 genesis = gspec.MustCommit(gendb) 1561 ) 1562 height := uint64(1024) 1563 blocks, receipts := GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), gendb, int(height), nil) 1564 1565 // Import the chain as a ancient-first node and ensure all pointers are updated 1566 frdir, err := ioutil.TempDir("", "") 1567 if err != nil { 1568 t.Fatalf("failed to create temp freezer dir: %v", err) 1569 } 1570 defer os.Remove(frdir) 1571 1572 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 1573 if err != nil { 1574 t.Fatalf("failed to create temp freezer db: %v", err) 1575 } 1576 gspec.MustCommit(ancientDb) 1577 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 1578 1579 headers := make([]*types.Header, len(blocks)) 1580 for i, block := range blocks { 1581 headers[i] = block.Header() 1582 } 1583 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 1584 t.Fatalf("failed to insert header %d: %v", n, err) 1585 } 1586 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 1587 t.Fatalf("failed to insert receipt %d: %v", n, err) 1588 } 1589 rawdb.WriteLastPivotNumber(ancientDb, blocks[len(blocks)-1].NumberU64()) // Force fast sync behavior 1590 ancient.Stop() 1591 1592 // Destroy head fast block manually 1593 midBlock := blocks[len(blocks)/2] 1594 rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash()) 1595 1596 // Reopen broken blockchain again 1597 ancient, _ = NewBlockChain(ancientDb, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 1598 defer ancient.Stop() 1599 if num := ancient.CurrentBlock().NumberU64(); num != 0 { 1600 t.Errorf("head block mismatch: have #%v, want #%v", num, 0) 1601 } 1602 if num := ancient.CurrentFastBlock().NumberU64(); num != midBlock.NumberU64() { 1603 t.Errorf("head fast-block mismatch: have #%v, want #%v", num, midBlock.NumberU64()) 1604 } 1605 if num := ancient.CurrentHeader().Number.Uint64(); num != midBlock.NumberU64() { 1606 t.Errorf("head header mismatch: have #%v, want #%v", num, midBlock.NumberU64()) 1607 } 1608 } 1609 1610 func TestIncompleteAncientReceiptChainInsertion(t *testing.T) { 1611 // Configure and generate a sample block chain 1612 var ( 1613 gendb = rawdb.NewMemoryDatabase() 1614 key, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 1615 address = key.Address() 1616 funds = big.NewInt(1000000000) 1617 gspec = &Genesis{Config: params.MainnetChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 1618 genesis = gspec.MustCommit(gendb) 1619 ) 1620 height := uint64(1024) 1621 blocks, receipts := GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), gendb, int(height), nil) 1622 1623 // Import the chain as a ancient-first node and ensure all pointers are updated 1624 frdir, err := ioutil.TempDir("", "") 1625 if err != nil { 1626 t.Fatalf("failed to create temp freezer dir: %v", err) 1627 } 1628 defer os.Remove(frdir) 1629 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 1630 if err != nil { 1631 t.Fatalf("failed to create temp freezer db: %v", err) 1632 } 1633 gspec.MustCommit(ancientDb) 1634 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, cryptore.NewFaker(), vm.Config{}, nil, nil) 1635 defer ancient.Stop() 1636 1637 headers := make([]*types.Header, len(blocks)) 1638 for i, block := range blocks { 1639 headers[i] = block.Header() 1640 } 1641 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 1642 t.Fatalf("failed to insert header %d: %v", n, err) 1643 } 1644 // Abort ancient receipt chain insertion deliberately 1645 ancient.terminateInsert = func(hash common.Hash, number uint64) bool { 1646 return number == blocks[len(blocks)/2].NumberU64() 1647 } 1648 previousFastBlock := ancient.CurrentFastBlock() 1649 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err == nil { 1650 t.Fatalf("failed to insert receipt %d: %v", n, err) 1651 } 1652 if ancient.CurrentFastBlock().NumberU64() != previousFastBlock.NumberU64() { 1653 t.Fatalf("failed to rollback ancient data, want %d, have %d", previousFastBlock.NumberU64(), ancient.CurrentFastBlock().NumberU64()) 1654 } 1655 if frozen, err := ancient.db.Ancients(); err != nil || frozen != 1 { 1656 t.Fatalf("failed to truncate ancient data") 1657 } 1658 ancient.terminateInsert = nil 1659 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 1660 t.Fatalf("failed to insert receipt %d: %v", n, err) 1661 } 1662 if ancient.CurrentFastBlock().NumberU64() != blocks[len(blocks)-1].NumberU64() { 1663 t.Fatalf("failed to insert ancient recept chain after rollback") 1664 } 1665 } 1666 1667 // Tests that importing a very large side fork, which is larger than the canon chain, 1668 // but where the difficulty per block is kept low: this means that it will not 1669 // overtake the 'canon' chain until after it's passed canon by about 200 blocks. 1670 // 1671 // Details at: 1672 // - https://github.com/core-coin/go-core/v2/issues/18977 1673 // - https://github.com/core-coin/go-core/v2/pull/18988 1674 func TestLowDiffLongChain(t *testing.T) { 1675 // Generate a canonical chain to act as the main dataset 1676 engine := cryptore.NewFaker() 1677 db := rawdb.NewMemoryDatabase() 1678 genesis := new(Genesis).MustCommit(db) 1679 1680 // We must use a pretty long chain to ensure that the fork doesn't overtake us 1681 // until after at least 128 blocks post tip 1682 blocks, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 6*TriesInMemory, func(i int, b *BlockGen) { 1683 b.SetCoinbase(common.Address{1}) 1684 b.OffsetTime(-9) 1685 }) 1686 1687 // Import the canonical chain 1688 diskdb := rawdb.NewMemoryDatabase() 1689 new(Genesis).MustCommit(diskdb) 1690 1691 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{}, nil, nil) 1692 if err != nil { 1693 t.Fatalf("failed to create tester chain: %v", err) 1694 } 1695 if n, err := chain.InsertChain(blocks); err != nil { 1696 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1697 } 1698 // Generate fork chain, starting from an early block 1699 parent := blocks[10] 1700 fork, _ := GenerateChain(params.MainnetChainConfig, parent, engine, db, 8*TriesInMemory, func(i int, b *BlockGen) { 1701 b.SetCoinbase(common.Address{2}) 1702 }) 1703 1704 // And now import the fork 1705 if i, err := chain.InsertChain(fork); err != nil { 1706 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1707 } 1708 head := chain.CurrentBlock() 1709 if got := fork[len(fork)-1].Hash(); got != head.Hash() { 1710 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 1711 } 1712 // Sanity check that all the canonical numbers are present 1713 header := chain.CurrentHeader() 1714 for number := head.NumberU64(); number > 0; number-- { 1715 if hash := chain.GetHeaderByNumber(number).Hash(); hash != header.Hash() { 1716 t.Fatalf("header %d: canonical hash mismatch: have %x, want %x", number, hash, header.Hash()) 1717 } 1718 header = chain.GetHeader(header.ParentHash, number-1) 1719 } 1720 } 1721 1722 // Tests that importing a sidechain (S), where 1723 // - S is sidechain, containing blocks [Sn...Sm] 1724 // - C is canon chain, containing blocks [G..Cn..Cm] 1725 // - A common ancestor is placed at prune-point + blocksBetweenCommonAncestorAndPruneblock 1726 // - The sidechain S is prepended with numCanonBlocksInSidechain blocks from the canon chain 1727 func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommonAncestorAndPruneblock int) { 1728 1729 // Generate a canonical chain to act as the main dataset 1730 engine := cryptore.NewFaker() 1731 db := rawdb.NewMemoryDatabase() 1732 genesis := new(Genesis).MustCommit(db) 1733 1734 // Generate and import the canonical chain 1735 blocks, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 2*TriesInMemory, nil) 1736 diskdb := rawdb.NewMemoryDatabase() 1737 new(Genesis).MustCommit(diskdb) 1738 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{}, nil, nil) 1739 if err != nil { 1740 t.Fatalf("failed to create tester chain: %v", err) 1741 } 1742 if n, err := chain.InsertChain(blocks); err != nil { 1743 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1744 } 1745 1746 lastPrunedIndex := len(blocks) - TriesInMemory - 1 1747 lastPrunedBlock := blocks[lastPrunedIndex] 1748 firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory] 1749 1750 // Verify pruning of lastPrunedBlock 1751 if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { 1752 t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) 1753 } 1754 // Verify firstNonPrunedBlock is not pruned 1755 if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { 1756 t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) 1757 } 1758 // Generate the sidechain 1759 // First block should be a known block, block after should be a pruned block. So 1760 // canon(pruned), side, side... 1761 1762 // Generate fork chain, make it longer than canon 1763 parentIndex := lastPrunedIndex + blocksBetweenCommonAncestorAndPruneblock 1764 parent := blocks[parentIndex] 1765 fork, _ := GenerateChain(params.MainnetChainConfig, parent, engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { 1766 b.SetCoinbase(common.Address{2}) 1767 }) 1768 // Prepend the parent(s) 1769 var sidechain []*types.Block 1770 for i := numCanonBlocksInSidechain; i > 0; i-- { 1771 sidechain = append(sidechain, blocks[parentIndex+1-i]) 1772 } 1773 sidechain = append(sidechain, fork...) 1774 _, err = chain.InsertChain(sidechain) 1775 if err != nil { 1776 t.Errorf("Got error, %v", err) 1777 } 1778 head := chain.CurrentBlock() 1779 if got := fork[len(fork)-1].Hash(); got != head.Hash() { 1780 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 1781 } 1782 } 1783 1784 // Tests that importing a sidechain (S), where 1785 // - S is sidechain, containing blocks [Sn...Sm] 1786 // - C is canon chain, containing blocks [G..Cn..Cm] 1787 // - The common ancestor Cc is pruned 1788 // - The first block in S: Sn, is == Cn 1789 // That is: the sidechain for import contains some blocks already present in canon chain. 1790 // So the blocks are 1791 // [ Cn, Cn+1, Cc, Sn+3 ... Sm] 1792 // 1793 // ^ ^ ^ pruned 1794 func TestPrunedImportSide(t *testing.T) { 1795 //glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false))) 1796 //glogger.Verbosity(3) 1797 //log.Root().SetHandler(log.Handler(glogger)) 1798 testSideImport(t, 3, 3) 1799 testSideImport(t, 3, -3) 1800 testSideImport(t, 10, 0) 1801 testSideImport(t, 1, 10) 1802 testSideImport(t, 1, -10) 1803 } 1804 1805 func TestInsertKnownHeaders(t *testing.T) { testInsertKnownChainData(t, "headers") } 1806 func TestInsertKnownReceiptChain(t *testing.T) { testInsertKnownChainData(t, "receipts") } 1807 func TestInsertKnownBlocks(t *testing.T) { testInsertKnownChainData(t, "blocks") } 1808 1809 func testInsertKnownChainData(t *testing.T, typ string) { 1810 engine := cryptore.NewFaker() 1811 1812 db := rawdb.NewMemoryDatabase() 1813 genesis := new(Genesis).MustCommit(db) 1814 1815 blocks, receipts := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 32, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1816 // A longer chain but total difficulty is lower. 1817 blocks2, receipts2 := GenerateChain(params.MainnetChainConfig, blocks[len(blocks)-1], engine, db, 65, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1818 // A shorter chain but total difficulty is higher. 1819 blocks3, receipts3 := GenerateChain(params.MainnetChainConfig, blocks[len(blocks)-1], engine, db, 64, func(i int, b *BlockGen) { 1820 b.SetCoinbase(common.Address{1}) 1821 b.OffsetTime(-9) // A higher difficulty 1822 }) 1823 // Import the shared chain and the original canonical one 1824 dir, err := ioutil.TempDir("", "") 1825 if err != nil { 1826 t.Fatalf("failed to create temp freezer dir: %v", err) 1827 } 1828 defer os.Remove(dir) 1829 chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "") 1830 if err != nil { 1831 t.Fatalf("failed to create temp freezer db: %v", err) 1832 } 1833 new(Genesis).MustCommit(chaindb) 1834 defer os.RemoveAll(dir) 1835 1836 chain, err := NewBlockChain(chaindb, nil, params.MainnetChainConfig, engine, vm.Config{}, nil, nil) 1837 if err != nil { 1838 t.Fatalf("failed to create tester chain: %v", err) 1839 } 1840 1841 var ( 1842 inserter func(blocks []*types.Block, receipts []types.Receipts) error 1843 asserter func(t *testing.T, block *types.Block) 1844 ) 1845 if typ == "headers" { 1846 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 1847 headers := make([]*types.Header, 0, len(blocks)) 1848 for _, block := range blocks { 1849 headers = append(headers, block.Header()) 1850 } 1851 _, err := chain.InsertHeaderChain(headers, 1) 1852 return err 1853 } 1854 asserter = func(t *testing.T, block *types.Block) { 1855 if chain.CurrentHeader().Hash() != block.Hash() { 1856 t.Fatalf("current head header mismatch, have %v, want %v", chain.CurrentHeader().Hash().Hex(), block.Hash().Hex()) 1857 } 1858 } 1859 } else if typ == "receipts" { 1860 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 1861 headers := make([]*types.Header, 0, len(blocks)) 1862 for _, block := range blocks { 1863 headers = append(headers, block.Header()) 1864 } 1865 _, err := chain.InsertHeaderChain(headers, 1) 1866 if err != nil { 1867 return err 1868 } 1869 _, err = chain.InsertReceiptChain(blocks, receipts, 0) 1870 return err 1871 } 1872 asserter = func(t *testing.T, block *types.Block) { 1873 if chain.CurrentFastBlock().Hash() != block.Hash() { 1874 t.Fatalf("current head fast block mismatch, have %v, want %v", chain.CurrentFastBlock().Hash().Hex(), block.Hash().Hex()) 1875 } 1876 } 1877 } else { 1878 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 1879 _, err := chain.InsertChain(blocks) 1880 return err 1881 } 1882 asserter = func(t *testing.T, block *types.Block) { 1883 if chain.CurrentBlock().Hash() != block.Hash() { 1884 t.Fatalf("current head block mismatch, have %v, want %v", chain.CurrentBlock().Hash().Hex(), block.Hash().Hex()) 1885 } 1886 } 1887 } 1888 1889 if err := inserter(blocks, receipts); err != nil { 1890 t.Fatalf("failed to insert chain data: %v", err) 1891 } 1892 1893 // Reimport the chain data again. All the imported 1894 // chain data are regarded "known" data. 1895 if err := inserter(blocks, receipts); err != nil { 1896 t.Fatalf("failed to insert chain data: %v", err) 1897 } 1898 asserter(t, blocks[len(blocks)-1]) 1899 1900 // Import a long canonical chain with some known data as prefix. 1901 rollback := blocks[len(blocks)/2].NumberU64() 1902 1903 chain.SetHead(rollback - 1) 1904 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 1905 t.Fatalf("failed to insert chain data: %v", err) 1906 } 1907 asserter(t, blocks2[len(blocks2)-1]) 1908 1909 // Import a heavier shorter but higher total difficulty chain with some known data as prefix. 1910 if err := inserter(append(blocks, blocks3...), append(receipts, receipts3...)); err != nil { 1911 t.Fatalf("failed to insert chain data: %v", err) 1912 } 1913 asserter(t, blocks3[len(blocks3)-1]) 1914 1915 // Import a longer but lower total difficulty chain with some known data as prefix. 1916 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 1917 t.Fatalf("failed to insert chain data: %v", err) 1918 } 1919 // The head shouldn't change. 1920 asserter(t, blocks3[len(blocks3)-1]) 1921 1922 // Rollback the heavier chain and re-insert the longer chain again 1923 chain.SetHead(rollback - 1) 1924 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 1925 t.Fatalf("failed to insert chain data: %v", err) 1926 } 1927 asserter(t, blocks2[len(blocks2)-1]) 1928 } 1929 1930 // getLongAndShortChains returns two chains, 1931 // A is longer, B is heavier 1932 func getLongAndShortChains() (*BlockChain, []*types.Block, []*types.Block, error) { 1933 // Generate a canonical chain to act as the main dataset 1934 engine := cryptore.NewFaker() 1935 db := rawdb.NewMemoryDatabase() 1936 genesis := new(Genesis).MustCommit(db) 1937 1938 // Generate and import the canonical chain, 1939 // Offset the time, to keep the difficulty low 1940 longChain, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 80, func(i int, b *BlockGen) { 1941 b.SetCoinbase(common.Address{1}) 1942 }) 1943 diskdb := rawdb.NewMemoryDatabase() 1944 new(Genesis).MustCommit(diskdb) 1945 1946 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{}, nil, nil) 1947 if err != nil { 1948 return nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err) 1949 } 1950 1951 // Generate fork chain, make it shorter than canon, with common ancestor pretty early 1952 parentIndex := 3 1953 parent := longChain[parentIndex] 1954 heavyChain, _ := GenerateChain(params.MainnetChainConfig, parent, engine, db, 75, func(i int, b *BlockGen) { 1955 b.SetCoinbase(common.Address{2}) 1956 b.OffsetTime(-9) 1957 }) 1958 // Verify that the test is sane 1959 var ( 1960 longerTd = new(big.Int) 1961 shorterTd = new(big.Int) 1962 ) 1963 for index, b := range longChain { 1964 longerTd.Add(longerTd, b.Difficulty()) 1965 if index <= parentIndex { 1966 shorterTd.Add(shorterTd, b.Difficulty()) 1967 } 1968 } 1969 for _, b := range heavyChain { 1970 shorterTd.Add(shorterTd, b.Difficulty()) 1971 } 1972 if shorterTd.Cmp(longerTd) <= 0 { 1973 return nil, nil, nil, fmt.Errorf("Test is moot, heavyChain td (%v) must be larger than canon td (%v)", shorterTd, longerTd) 1974 } 1975 longerNum := longChain[len(longChain)-1].NumberU64() 1976 shorterNum := heavyChain[len(heavyChain)-1].NumberU64() 1977 if shorterNum >= longerNum { 1978 return nil, nil, nil, fmt.Errorf("Test is moot, heavyChain num (%v) must be lower than canon num (%v)", shorterNum, longerNum) 1979 } 1980 return chain, longChain, heavyChain, nil 1981 } 1982 1983 // TestReorgToShorterRemovesCanonMapping tests that if we 1984 // 1. Have a chain [0 ... N .. X] 1985 // 2. Reorg to shorter but heavier chain [0 ... N ... Y] 1986 // 3. Then there should be no canon mapping for the block at height X 1987 func TestReorgToShorterRemovesCanonMapping(t *testing.T) { 1988 chain, canonblocks, sideblocks, err := getLongAndShortChains() 1989 if err != nil { 1990 t.Fatal(err) 1991 } 1992 if n, err := chain.InsertChain(canonblocks); err != nil { 1993 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1994 } 1995 canonNum := chain.CurrentBlock().NumberU64() 1996 _, err = chain.InsertChain(sideblocks) 1997 if err != nil { 1998 t.Errorf("Got error, %v", err) 1999 } 2000 head := chain.CurrentBlock() 2001 if got := sideblocks[len(sideblocks)-1].Hash(); got != head.Hash() { 2002 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 2003 } 2004 // We have now inserted a sidechain. 2005 if blockByNum := chain.GetBlockByNumber(canonNum); blockByNum != nil { 2006 t.Errorf("expected block to be gone: %v", blockByNum.NumberU64()) 2007 } 2008 if headerByNum := chain.GetHeaderByNumber(canonNum); headerByNum != nil { 2009 t.Errorf("expected header to be gone: %v", headerByNum.Number.Uint64()) 2010 } 2011 } 2012 2013 // TestReorgToShorterRemovesCanonMappingHeaderChain is the same scenario 2014 // as TestReorgToShorterRemovesCanonMapping, but applied on headerchain 2015 // imports -- that is, for fast sync 2016 func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) { 2017 chain, canonblocks, sideblocks, err := getLongAndShortChains() 2018 if err != nil { 2019 t.Fatal(err) 2020 } 2021 // Convert into headers 2022 canonHeaders := make([]*types.Header, len(canonblocks)) 2023 for i, block := range canonblocks { 2024 canonHeaders[i] = block.Header() 2025 } 2026 if n, err := chain.InsertHeaderChain(canonHeaders, 0); err != nil { 2027 t.Fatalf("header %d: failed to insert into chain: %v", n, err) 2028 } 2029 canonNum := chain.CurrentHeader().Number.Uint64() 2030 sideHeaders := make([]*types.Header, len(sideblocks)) 2031 for i, block := range sideblocks { 2032 sideHeaders[i] = block.Header() 2033 } 2034 if n, err := chain.InsertHeaderChain(sideHeaders, 0); err != nil { 2035 t.Fatalf("header %d: failed to insert into chain: %v", n, err) 2036 } 2037 head := chain.CurrentHeader() 2038 if got := sideblocks[len(sideblocks)-1].Hash(); got != head.Hash() { 2039 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 2040 } 2041 // We have now inserted a sidechain. 2042 if blockByNum := chain.GetBlockByNumber(canonNum); blockByNum != nil { 2043 t.Errorf("expected block to be gone: %v", blockByNum.NumberU64()) 2044 } 2045 if headerByNum := chain.GetHeaderByNumber(canonNum); headerByNum != nil { 2046 t.Errorf("expected header to be gone: %v", headerByNum.Number.Uint64()) 2047 } 2048 } 2049 2050 func TestTransactionIndices(t *testing.T) { 2051 // Configure and generate a sample block chain 2052 var ( 2053 gendb = rawdb.NewMemoryDatabase() 2054 key, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 2055 address = key.Address() 2056 funds = big.NewInt(1000000000) 2057 gspec = &Genesis{Config: params.MainnetChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 2058 genesis = gspec.MustCommit(gendb) 2059 signer = types.NewNucleusSigner(gspec.Config.NetworkID) 2060 ) 2061 height := uint64(128) 2062 blocks, receipts := GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), gendb, int(height), func(i int, block *BlockGen) { 2063 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxEnergy, nil, nil), signer, key) 2064 if err != nil { 2065 panic(err) 2066 } 2067 block.AddTx(tx) 2068 }) 2069 blocks2, _ := GenerateChain(gspec.Config, blocks[len(blocks)-1], cryptore.NewFaker(), gendb, 10, nil) 2070 2071 check := func(tail *uint64, chain *BlockChain) { 2072 stored := rawdb.ReadTxIndexTail(chain.db) 2073 if tail == nil && stored != nil { 2074 t.Fatalf("Oldest indexded block mismatch, want nil, have %d", *stored) 2075 } 2076 if tail != nil && *stored != *tail { 2077 t.Fatalf("Oldest indexded block mismatch, want %d, have %d", *tail, *stored) 2078 } 2079 if tail != nil { 2080 for i := *tail; i <= chain.CurrentBlock().NumberU64(); i++ { 2081 block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i) 2082 if block.Transactions().Len() == 0 { 2083 continue 2084 } 2085 for _, tx := range block.Transactions() { 2086 if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index == nil { 2087 t.Fatalf("Miss transaction indice, number %d hash %s", i, tx.Hash().Hex()) 2088 } 2089 } 2090 } 2091 for i := uint64(0); i < *tail; i++ { 2092 block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i) 2093 if block.Transactions().Len() == 0 { 2094 continue 2095 } 2096 for _, tx := range block.Transactions() { 2097 if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index != nil { 2098 t.Fatalf("Transaction indice should be deleted, number %d hash %s", i, tx.Hash().Hex()) 2099 } 2100 } 2101 } 2102 } 2103 } 2104 frdir, err := ioutil.TempDir("", "") 2105 if err != nil { 2106 t.Fatalf("failed to create temp freezer dir: %v", err) 2107 } 2108 defer os.Remove(frdir) 2109 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 2110 if err != nil { 2111 t.Fatalf("failed to create temp freezer db: %v", err) 2112 } 2113 gspec.MustCommit(ancientDb) 2114 2115 // Import all blocks into ancient db 2116 l := uint64(0) 2117 chain, err := NewBlockChain(ancientDb, nil, params.MainnetChainConfig, cryptore.NewFaker(), vm.Config{}, nil, &l) 2118 if err != nil { 2119 t.Fatalf("failed to create tester chain: %v", err) 2120 } 2121 headers := make([]*types.Header, len(blocks)) 2122 for i, block := range blocks { 2123 headers[i] = block.Header() 2124 } 2125 if n, err := chain.InsertHeaderChain(headers, 0); err != nil { 2126 t.Fatalf("failed to insert header %d: %v", n, err) 2127 } 2128 if n, err := chain.InsertReceiptChain(blocks, receipts, 128); err != nil { 2129 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2130 } 2131 chain.Stop() 2132 ancientDb.Close() 2133 2134 // Init block chain with external ancients, check all needed indices has been indexed. 2135 limit := []uint64{0, 32, 64, 128} 2136 for _, l := range limit { 2137 ancientDb, err = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 2138 if err != nil { 2139 t.Fatalf("failed to create temp freezer db: %v", err) 2140 } 2141 gspec.MustCommit(ancientDb) 2142 chain, err = NewBlockChain(ancientDb, nil, params.MainnetChainConfig, cryptore.NewFaker(), vm.Config{}, nil, &l) 2143 if err != nil { 2144 t.Fatalf("failed to create tester chain: %v", err) 2145 } 2146 time.Sleep(50 * time.Millisecond) // Wait for indices initialisation 2147 var tail uint64 2148 if l != 0 { 2149 tail = uint64(128) - l + 1 2150 } 2151 check(&tail, chain) 2152 chain.Stop() 2153 ancientDb.Close() 2154 } 2155 2156 // Reconstruct a block chain which only reserves HEAD-64 tx indices 2157 ancientDb, err = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 2158 if err != nil { 2159 t.Fatalf("failed to create temp freezer db: %v", err) 2160 } 2161 gspec.MustCommit(ancientDb) 2162 2163 limit = []uint64{0, 64 /* drop stale */, 32 /* shorten history */, 64 /* extend history */, 0 /* restore all */} 2164 tails := []uint64{0, 67 /* 130 - 64 + 1 */, 100 /* 131 - 32 + 1 */, 69 /* 132 - 64 + 1 */, 0} 2165 for i, l := range limit { 2166 chain, err = NewBlockChain(ancientDb, nil, params.MainnetChainConfig, cryptore.NewFaker(), vm.Config{}, nil, &l) 2167 if err != nil { 2168 t.Fatalf("failed to create tester chain: %v", err) 2169 } 2170 chain.InsertChain(blocks2[i : i+1]) // Feed chain a higher block to trigger indices updater. 2171 time.Sleep(50 * time.Millisecond) // Wait for indices initialisation 2172 check(&tails[i], chain) 2173 chain.Stop() 2174 } 2175 } 2176 2177 func TestSkipStaleTxIndicesInFastSync(t *testing.T) { 2178 // Configure and generate a sample block chain 2179 var ( 2180 gendb = rawdb.NewMemoryDatabase() 2181 key, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 2182 address = key.Address() 2183 funds = big.NewInt(1000000000) 2184 gspec = &Genesis{Config: params.MainnetChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 2185 genesis = gspec.MustCommit(gendb) 2186 signer = types.NewNucleusSigner(gspec.Config.NetworkID) 2187 ) 2188 height := uint64(128) 2189 blocks, receipts := GenerateChain(gspec.Config, genesis, cryptore.NewFaker(), gendb, int(height), func(i int, block *BlockGen) { 2190 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxEnergy, nil, nil), signer, key) 2191 if err != nil { 2192 panic(err) 2193 } 2194 block.AddTx(tx) 2195 }) 2196 2197 check := func(tail *uint64, chain *BlockChain) { 2198 stored := rawdb.ReadTxIndexTail(chain.db) 2199 if tail == nil && stored != nil { 2200 t.Fatalf("Oldest indexded block mismatch, want nil, have %d", *stored) 2201 } 2202 if tail != nil && *stored != *tail { 2203 t.Fatalf("Oldest indexded block mismatch, want %d, have %d", *tail, *stored) 2204 } 2205 if tail != nil { 2206 for i := *tail; i <= chain.CurrentBlock().NumberU64(); i++ { 2207 block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i) 2208 if block.Transactions().Len() == 0 { 2209 continue 2210 } 2211 for _, tx := range block.Transactions() { 2212 if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index == nil { 2213 t.Fatalf("Miss transaction indice, number %d hash %s", i, tx.Hash().Hex()) 2214 } 2215 } 2216 } 2217 for i := uint64(0); i < *tail; i++ { 2218 block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i) 2219 if block.Transactions().Len() == 0 { 2220 continue 2221 } 2222 for _, tx := range block.Transactions() { 2223 if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index != nil { 2224 t.Fatalf("Transaction indice should be deleted, number %d hash %s", i, tx.Hash().Hex()) 2225 } 2226 } 2227 } 2228 } 2229 } 2230 2231 frdir, err := ioutil.TempDir("", "") 2232 if err != nil { 2233 t.Fatalf("failed to create temp freezer dir: %v", err) 2234 } 2235 defer os.Remove(frdir) 2236 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 2237 if err != nil { 2238 t.Fatalf("failed to create temp freezer db: %v", err) 2239 } 2240 gspec.MustCommit(ancientDb) 2241 2242 // Import all blocks into ancient db, only HEAD-32 indices are kept. 2243 l := uint64(32) 2244 chain, err := NewBlockChain(ancientDb, nil, params.MainnetChainConfig, cryptore.NewFaker(), vm.Config{}, nil, &l) 2245 if err != nil { 2246 t.Fatalf("failed to create tester chain: %v", err) 2247 } 2248 headers := make([]*types.Header, len(blocks)) 2249 for i, block := range blocks { 2250 headers[i] = block.Header() 2251 } 2252 if n, err := chain.InsertHeaderChain(headers, 0); err != nil { 2253 t.Fatalf("failed to insert header %d: %v", n, err) 2254 } 2255 // The indices before ancient-N(32) should be ignored. After that all blocks should be indexed. 2256 if n, err := chain.InsertReceiptChain(blocks, receipts, 64); err != nil { 2257 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2258 } 2259 tail := uint64(32) 2260 check(&tail, chain) 2261 } 2262 2263 // Benchmarks large blocks with value transfers to non-existing accounts 2264 func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) { 2265 addr, err := common.HexToAddress("cb21000000000000000000000000000000000000aaaa") 2266 if err != nil { 2267 b.Error(err) 2268 } 2269 var ( 2270 signer = types.NewNucleusSigner(big.NewInt(1)) 2271 testBankKey, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 2272 bankFunds = big.NewInt(100000000000000000) 2273 gspec = Genesis{ 2274 Config: params.MainnetChainConfig, 2275 Alloc: GenesisAlloc{ 2276 testBankKey.Address(): {Balance: bankFunds}, 2277 addr: { 2278 Code: []byte{0x60, 0x01, 0x50}, 2279 Balance: big.NewInt(0), 2280 }, // push 1, pop 2281 }, 2282 EnergyLimit: 100e6, // 100 M 2283 } 2284 ) 2285 // Generate the original common chain segment and the two competing forks 2286 engine := cryptore.NewFaker() 2287 db := rawdb.NewMemoryDatabase() 2288 genesis := gspec.MustCommit(db) 2289 2290 blockGenerator := func(i int, block *BlockGen) { 2291 block.SetCoinbase(common.Address{1}) 2292 for txi := 0; txi < numTxs; txi++ { 2293 uniq := uint64(i*numTxs + txi) 2294 recipient := recipientFn(uniq) 2295 tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxEnergy, big.NewInt(1), nil), signer, testBankKey) 2296 if err != nil { 2297 b.Error(err) 2298 } 2299 block.AddTx(tx) 2300 } 2301 } 2302 2303 shared, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, numBlocks, blockGenerator) 2304 b.StopTimer() 2305 b.ResetTimer() 2306 for i := 0; i < b.N; i++ { 2307 // Import the shared chain and the original canonical one 2308 diskdb := rawdb.NewMemoryDatabase() 2309 gspec.MustCommit(diskdb) 2310 2311 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{}, nil, nil) 2312 if err != nil { 2313 b.Fatalf("failed to create tester chain: %v", err) 2314 } 2315 b.StartTimer() 2316 if _, err := chain.InsertChain(shared); err != nil { 2317 b.Fatalf("failed to insert shared chain: %v", err) 2318 } 2319 b.StopTimer() 2320 if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { 2321 b.Fatalf("Transactions were not included, expected %d, got %d", numTxs*numBlocks, got) 2322 2323 } 2324 } 2325 } 2326 2327 func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) { 2328 var ( 2329 numTxs = 1000 2330 numBlocks = 1 2331 ) 2332 recipientFn := func(nonce uint64) common.Address { 2333 return common.BigToAddress(big.NewInt(0).SetUint64(1337 + nonce)) 2334 } 2335 dataFn := func(nonce uint64) []byte { 2336 return nil 2337 } 2338 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2339 } 2340 2341 func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) { 2342 var ( 2343 numTxs = 1000 2344 numBlocks = 1 2345 ) 2346 b.StopTimer() 2347 b.ResetTimer() 2348 2349 recipientFn := func(nonce uint64) common.Address { 2350 return common.BigToAddress(big.NewInt(0).SetUint64(1337)) 2351 } 2352 dataFn := func(nonce uint64) []byte { 2353 return nil 2354 } 2355 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2356 } 2357 2358 func BenchmarkBlockChain_1x1000Executions(b *testing.B) { 2359 var ( 2360 numTxs = 1000 2361 numBlocks = 1 2362 ) 2363 b.StopTimer() 2364 b.ResetTimer() 2365 2366 recipientFn := func(nonce uint64) common.Address { 2367 return common.BigToAddress(big.NewInt(0).SetUint64(0xc0de)) 2368 } 2369 dataFn := func(nonce uint64) []byte { 2370 return nil 2371 } 2372 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2373 } 2374 2375 // Tests that importing a some old blocks, where all blocks are before the 2376 // pruning point. 2377 // This internally leads to a sidechain import, since the blocks trigger an 2378 // ErrPrunedAncestor error. 2379 // This may e.g. happen if 2380 // 1. Downloader rollbacks a batch of inserted blocks and exits 2381 // 2. Downloader starts to sync again 2382 // 3. The blocks fetched are all known and canonical blocks 2383 func TestSideImportPrunedBlocks(t *testing.T) { 2384 // Generate a canonical chain to act as the main dataset 2385 engine := cryptore.NewFaker() 2386 db := rawdb.NewMemoryDatabase() 2387 genesis := new(Genesis).MustCommit(db) 2388 2389 // Generate and import the canonical chain 2390 blocks, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 2*TriesInMemory, nil) 2391 diskdb := rawdb.NewMemoryDatabase() 2392 new(Genesis).MustCommit(diskdb) 2393 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{}, nil, nil) 2394 if err != nil { 2395 t.Fatalf("failed to create tester chain: %v", err) 2396 } 2397 if n, err := chain.InsertChain(blocks); err != nil { 2398 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2399 } 2400 2401 lastPrunedIndex := len(blocks) - TriesInMemory - 1 2402 lastPrunedBlock := blocks[lastPrunedIndex] 2403 2404 // Verify pruning of lastPrunedBlock 2405 if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { 2406 t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) 2407 } 2408 firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory] 2409 // Verify firstNonPrunedBlock is not pruned 2410 if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { 2411 t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) 2412 } 2413 // Now re-import some old blocks 2414 blockToReimport := blocks[5:8] 2415 _, err = chain.InsertChain(blockToReimport) 2416 if err != nil { 2417 t.Errorf("Got error, %v", err) 2418 } 2419 } 2420 2421 // TestDeleteCreateRevert tests a weird state transition corner case that we hit 2422 // while changing the internals of statedb. The workflow is that a contract is 2423 // self destructed, then in a followup transaction (but same block) it's created 2424 // again and the transaction reverted. 2425 // 2426 // The original statedb implementation flushed dirty objects to the tries after 2427 // each transaction, so this works ok. The rework accumulated writes in memory 2428 // first, but the journal wiped the entire state object on create-revert. 2429 func TestDeleteCreateRevert(t *testing.T) { 2430 var ( 2431 aa, err1 = common.HexToAddress("cb21000000000000000000000000000000000000aaaa") 2432 bb, err2 = common.HexToAddress("cb08000000000000000000000000000000000000bbbb") 2433 // Generate a canonical chain to act as the main dataset 2434 engine = cryptore.NewFaker() 2435 db = rawdb.NewMemoryDatabase() 2436 2437 // A sender who makes transactions, has some funds 2438 key, _ = crypto.UnmarshalPrivateKeyHex("856a9af6b0b651dd2f43b5e12193652ec1701c4da6f1c0d2a366ac4b9dabc9433ef09e41ca129552bd2c029086d9b03604de872a3b3432041f") 2439 address = key.Address() 2440 funds = big.NewInt(1000000000) 2441 gspec = &Genesis{ 2442 Config: params.MainnetChainConfig, 2443 Alloc: GenesisAlloc{ 2444 address: {Balance: funds}, 2445 // The address 0xAAAAA selfdestructs if called 2446 aa: { 2447 // Code needs to just selfdestruct 2448 Code: []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)}, 2449 Nonce: 1, 2450 Balance: big.NewInt(0), 2451 }, 2452 // The address 0xBBBB send 1 ore to 0xAAAA, then reverts 2453 bb: { 2454 Code: []byte{ 2455 byte(vm.PC), // [0] 2456 byte(vm.DUP1), // [0,0] 2457 byte(vm.DUP1), // [0,0,0] 2458 byte(vm.DUP1), // [0,0,0,0] 2459 byte(vm.PUSH1), 0x01, // [0,0,0,0,1] (value) 2460 byte(vm.PUSH2), 0xaa, 0xaa, // [0,0,0,0,1, 0xaaaa] 2461 byte(vm.ENERGY), 2462 byte(vm.CALL), 2463 byte(vm.REVERT), 2464 }, 2465 Balance: big.NewInt(1), 2466 }, 2467 }, 2468 } 2469 genesis = gspec.MustCommit(db) 2470 ) 2471 if err1 != nil { 2472 t.Error(err1) 2473 } 2474 if err2 != nil { 2475 t.Error(err2) 2476 } 2477 blocks, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) { 2478 b.SetCoinbase(common.Address{1}) 2479 // One transaction to AAAA 2480 tx, _ := types.SignTx(types.NewTransaction(0, aa, 2481 big.NewInt(0), 50000, big.NewInt(1), nil), types.NewNucleusSigner(params.MainnetChainConfig.NetworkID), key) 2482 b.AddTx(tx) 2483 // One transaction to BBBB 2484 tx, _ = types.SignTx(types.NewTransaction(1, bb, 2485 big.NewInt(0), 100000, big.NewInt(1), nil), types.NewNucleusSigner(params.MainnetChainConfig.NetworkID), key) 2486 b.AddTx(tx) 2487 }) 2488 // Import the canonical chain 2489 diskdb := rawdb.NewMemoryDatabase() 2490 gspec.MustCommit(diskdb) 2491 2492 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{}, nil, nil) 2493 if err != nil { 2494 t.Fatalf("failed to create tester chain: %v", err) 2495 } 2496 if n, err := chain.InsertChain(blocks); err != nil { 2497 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2498 } 2499 } 2500 2501 // TestDeleteRecreateSlots tests a state-transition that contains both deletion 2502 // and recreation of contract state. 2503 // Contract A exists, has slots 1 and 2 set 2504 // Tx 1: Selfdestruct A 2505 // Tx 2: Re-create A, set slots 3 and 4 2506 // Expected outcome is that _all_ slots are cleared from A, due to the selfdestruct, 2507 // and then the new slots exist 2508 func TestDeleteRecreateSlots(t *testing.T) { 2509 bb, err := common.HexToAddress("cb08000000000000000000000000000000000000bbbb") 2510 if err != nil { 2511 t.Error(err) 2512 } 2513 var ( 2514 // Generate a canonical chain to act as the main dataset 2515 engine = cryptore.NewFaker() 2516 db = rawdb.NewMemoryDatabase() 2517 // A sender who makes transactions, has some funds 2518 key, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 2519 address = key.Address() 2520 funds = big.NewInt(1000000000) 2521 aaStorage = make(map[common.Hash]common.Hash) // Initial storage in AA 2522 aaCode = []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)} // Code for AA (simple selfdestruct) 2523 ) 2524 // Populate two slots 2525 aaStorage[common.HexToHash("01")] = common.HexToHash("01") 2526 aaStorage[common.HexToHash("02")] = common.HexToHash("02") 2527 2528 // The bb-code needs to CREATE2 the aa contract. It consists of 2529 // both initcode and deployment code 2530 // initcode: 2531 // 1. Set slots 3=3, 4=4, 2532 // 2. Return aaCode 2533 2534 initCode := []byte{ 2535 byte(vm.PUSH1), 0x3, // value 2536 byte(vm.PUSH1), 0x3, // location 2537 byte(vm.SSTORE), // Set slot[3] = 1 2538 byte(vm.PUSH1), 0x4, // value 2539 byte(vm.PUSH1), 0x4, // location 2540 byte(vm.SSTORE), // Set slot[4] = 1 2541 // Slots are set, now return the code 2542 byte(vm.PUSH2), byte(vm.PC), byte(vm.SELFDESTRUCT), // Push code on stack 2543 byte(vm.PUSH1), 0x0, // memory start on stack 2544 byte(vm.MSTORE), 2545 // Code is now in memory. 2546 byte(vm.PUSH1), 0x2, // size 2547 byte(vm.PUSH1), byte(32 - 2), // offset 2548 byte(vm.RETURN), 2549 } 2550 if l := len(initCode); l > 32 { 2551 t.Fatalf("init code is too long for a pushx, need a more elaborate deployer") 2552 } 2553 bbCode := []byte{ 2554 // Push initcode onto stack 2555 byte(vm.PUSH1) + byte(len(initCode)-1)} 2556 bbCode = append(bbCode, initCode...) 2557 bbCode = append(bbCode, []byte{ 2558 byte(vm.PUSH1), 0x0, // memory start on stack 2559 byte(vm.MSTORE), 2560 byte(vm.PUSH1), 0x00, // salt 2561 byte(vm.PUSH1), byte(len(initCode)), // size 2562 byte(vm.PUSH1), byte(32 - len(initCode)), // offset 2563 byte(vm.PUSH1), 0x00, // endowment 2564 byte(vm.CREATE2), 2565 }...) 2566 2567 initHash := crypto.SHA3Hash(initCode) 2568 aa := crypto.CreateAddress2(bb, [32]byte{}, initHash[:]) 2569 t.Logf("Destination address: %x\n", aa) 2570 2571 gspec := &Genesis{ 2572 Config: params.MainnetChainConfig, 2573 Alloc: GenesisAlloc{ 2574 address: {Balance: funds}, 2575 // The address 0xAAAAA selfdestructs if called 2576 aa: { 2577 // Code needs to just selfdestruct 2578 Code: aaCode, 2579 Nonce: 1, 2580 Balance: big.NewInt(0), 2581 Storage: aaStorage, 2582 }, 2583 // The contract BB recreates AA 2584 bb: { 2585 Code: bbCode, 2586 Balance: big.NewInt(1), 2587 }, 2588 }, 2589 } 2590 genesis := gspec.MustCommit(db) 2591 2592 blocks, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) { 2593 b.SetCoinbase(common.Address{1}) 2594 // One transaction to AA, to kill it 2595 tx, _ := types.SignTx(types.NewTransaction(0, aa, 2596 big.NewInt(0), 50000, big.NewInt(1), nil), types.NewNucleusSigner(big.NewInt(1)), key) 2597 b.AddTx(tx) 2598 // One transaction to BB, to recreate AA 2599 tx, _ = types.SignTx(types.NewTransaction(1, bb, 2600 big.NewInt(0), 100000, big.NewInt(1), nil), types.NewNucleusSigner(big.NewInt(1)), key) 2601 b.AddTx(tx) 2602 }) 2603 // Import the canonical chain 2604 diskdb := rawdb.NewMemoryDatabase() 2605 gspec.MustCommit(diskdb) 2606 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{ 2607 Debug: true, 2608 Tracer: vm.NewJSONLogger(nil, os.Stdout), 2609 }, nil, nil) 2610 if err != nil { 2611 t.Fatalf("failed to create tester chain: %v", err) 2612 } 2613 if n, err := chain.InsertChain(blocks); err != nil { 2614 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2615 } 2616 statedb, _ := chain.State() 2617 2618 // If all is correct, then slot 1 and 2 are zero 2619 if got, exp := statedb.GetState(aa, common.HexToHash("01")), (common.Hash{}); got != exp { 2620 t.Errorf("got %x exp %x", got, exp) 2621 } 2622 if got, exp := statedb.GetState(aa, common.HexToHash("02")), (common.Hash{}); got != exp { 2623 t.Errorf("got %x exp %x", got, exp) 2624 } 2625 // Also, 3 and 4 should be set 2626 if got, exp := statedb.GetState(aa, common.HexToHash("03")), common.HexToHash("03"); got != exp { 2627 t.Fatalf("got %x exp %x", got, exp) 2628 } 2629 if got, exp := statedb.GetState(aa, common.HexToHash("04")), common.HexToHash("04"); got != exp { 2630 t.Fatalf("got %x exp %x", got, exp) 2631 } 2632 } 2633 2634 // TestDeleteRecreateAccount tests a state-transition that contains deletion of a 2635 // contract with storage, and a recreate of the same contract via a 2636 // regular value-transfer 2637 // Expected outcome is that _all_ slots are cleared from A 2638 func TestDeleteRecreateAccount(t *testing.T) { 2639 aa, err := common.HexToAddress("cb21000000000000000000000000000000000000aaaa") 2640 if err != nil { 2641 t.Error(err) 2642 } 2643 var ( 2644 // Generate a canonical chain to act as the main dataset 2645 engine = cryptore.NewFaker() 2646 db = rawdb.NewMemoryDatabase() 2647 // A sender who makes transactions, has some funds 2648 key, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 2649 address = key.Address() 2650 funds = big.NewInt(1000000000) 2651 2652 aaStorage = make(map[common.Hash]common.Hash) // Initial storage in AA 2653 aaCode = []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)} // Code for AA (simple selfdestruct) 2654 ) 2655 // Populate two slots 2656 aaStorage[common.HexToHash("01")] = common.HexToHash("01") 2657 aaStorage[common.HexToHash("02")] = common.HexToHash("02") 2658 2659 gspec := &Genesis{ 2660 Config: params.MainnetChainConfig, 2661 Alloc: GenesisAlloc{ 2662 address: {Balance: funds}, 2663 // The address 0xAAAAA selfdestructs if called 2664 aa: { 2665 // Code needs to just selfdestruct 2666 Code: aaCode, 2667 Nonce: 1, 2668 Balance: big.NewInt(0), 2669 Storage: aaStorage, 2670 }, 2671 }, 2672 } 2673 genesis := gspec.MustCommit(db) 2674 2675 blocks, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) { 2676 b.SetCoinbase(common.Address{1}) 2677 // One transaction to AA, to kill it 2678 tx, _ := types.SignTx(types.NewTransaction(0, aa, 2679 big.NewInt(0), 50000, big.NewInt(1), nil), types.NewNucleusSigner(big.NewInt(1)), key) 2680 b.AddTx(tx) 2681 // One transaction to AA, to recreate it (but without storage 2682 tx, _ = types.SignTx(types.NewTransaction(1, aa, 2683 big.NewInt(1), 100000, big.NewInt(1), nil), types.NewNucleusSigner(big.NewInt(1)), key) 2684 b.AddTx(tx) 2685 }) 2686 // Import the canonical chain 2687 diskdb := rawdb.NewMemoryDatabase() 2688 gspec.MustCommit(diskdb) 2689 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{ 2690 Debug: true, 2691 Tracer: vm.NewJSONLogger(nil, os.Stdout), 2692 }, nil, nil) 2693 if err != nil { 2694 t.Fatalf("failed to create tester chain: %v", err) 2695 } 2696 if n, err := chain.InsertChain(blocks); err != nil { 2697 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2698 } 2699 statedb, _ := chain.State() 2700 2701 // If all is correct, then both slots are zero 2702 if got, exp := statedb.GetState(aa, common.HexToHash("01")), (common.Hash{}); got != exp { 2703 t.Errorf("got %x exp %x", got, exp) 2704 } 2705 if got, exp := statedb.GetState(aa, common.HexToHash("02")), (common.Hash{}); got != exp { 2706 t.Errorf("got %x exp %x", got, exp) 2707 } 2708 } 2709 2710 // TestDeleteRecreateSlotsAcrossManyBlocks tests multiple state-transition that contains both deletion 2711 // and recreation of contract state. 2712 // Contract A exists, has slots 1 and 2 set 2713 // Tx 1: Selfdestruct A 2714 // Tx 2: Re-create A, set slots 3 and 4 2715 // Expected outcome is that _all_ slots are cleared from A, due to the selfdestruct, 2716 // and then the new slots exist 2717 func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) { 2718 bb, err := common.HexToAddress("cb08000000000000000000000000000000000000bbbb") 2719 if err != nil { 2720 t.Error(err) 2721 } 2722 var ( 2723 // Generate a canonical chain to act as the main dataset 2724 engine = cryptore.NewFaker() 2725 db = rawdb.NewMemoryDatabase() 2726 // A sender who makes transactions, has some funds 2727 key, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 2728 address = key.Address() 2729 funds = big.NewInt(1000000000) 2730 aaStorage = make(map[common.Hash]common.Hash) // Initial storage in AA 2731 aaCode = []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)} // Code for AA (simple selfdestruct) 2732 ) 2733 // Populate two slots 2734 aaStorage[common.HexToHash("01")] = common.HexToHash("01") 2735 aaStorage[common.HexToHash("02")] = common.HexToHash("02") 2736 2737 // The bb-code needs to CREATE2 the aa contract. It consists of 2738 // both initcode and deployment code 2739 // initcode: 2740 // 1. Set slots 3=blocknum+1, 4=4, 2741 // 2. Return aaCode 2742 2743 initCode := []byte{ 2744 byte(vm.PUSH1), 0x1, // 2745 byte(vm.NUMBER), // value = number + 1 2746 byte(vm.ADD), // 2747 byte(vm.PUSH1), 0x3, // location 2748 byte(vm.SSTORE), // Set slot[3] = number + 1 2749 byte(vm.PUSH1), 0x4, // value 2750 byte(vm.PUSH1), 0x4, // location 2751 byte(vm.SSTORE), // Set slot[4] = 4 2752 // Slots are set, now return the code 2753 byte(vm.PUSH2), byte(vm.PC), byte(vm.SELFDESTRUCT), // Push code on stack 2754 byte(vm.PUSH1), 0x0, // memory start on stack 2755 byte(vm.MSTORE), 2756 // Code is now in memory. 2757 byte(vm.PUSH1), 0x2, // size 2758 byte(vm.PUSH1), byte(32 - 2), // offset 2759 byte(vm.RETURN), 2760 } 2761 if l := len(initCode); l > 32 { 2762 t.Fatalf("init code is too long for a pushx, need a more elaborate deployer") 2763 } 2764 bbCode := []byte{ 2765 // Push initcode onto stack 2766 byte(vm.PUSH1) + byte(len(initCode)-1)} 2767 bbCode = append(bbCode, initCode...) 2768 bbCode = append(bbCode, []byte{ 2769 byte(vm.PUSH1), 0x0, // memory start on stack 2770 byte(vm.MSTORE), 2771 byte(vm.PUSH1), 0x00, // salt 2772 byte(vm.PUSH1), byte(len(initCode)), // size 2773 byte(vm.PUSH1), byte(32 - len(initCode)), // offset 2774 byte(vm.PUSH1), 0x00, // endowment 2775 byte(vm.CREATE2), 2776 }...) 2777 2778 initHash := crypto.SHA3Hash(initCode) 2779 aa := crypto.CreateAddress2(bb, [32]byte{}, initHash[:]) 2780 t.Logf("Destination address: %x\n", aa) 2781 gspec := &Genesis{ 2782 Config: params.MainnetChainConfig, 2783 Alloc: GenesisAlloc{ 2784 address: {Balance: funds}, 2785 // The address 0xAAAAA selfdestructs if called 2786 aa: { 2787 // Code needs to just selfdestruct 2788 Code: aaCode, 2789 Nonce: 1, 2790 Balance: big.NewInt(0), 2791 Storage: aaStorage, 2792 }, 2793 // The contract BB recreates AA 2794 bb: { 2795 Code: bbCode, 2796 Balance: big.NewInt(1), 2797 }, 2798 }, 2799 } 2800 genesis := gspec.MustCommit(db) 2801 var nonce uint64 2802 2803 type expectation struct { 2804 exist bool 2805 blocknum int 2806 values map[int]int 2807 } 2808 var current = &expectation{ 2809 exist: true, // exists in genesis 2810 blocknum: 0, 2811 values: map[int]int{1: 1, 2: 2}, 2812 } 2813 var expectations []*expectation 2814 var newDestruct = func(e *expectation) *types.Transaction { 2815 tx, _ := types.SignTx(types.NewTransaction(nonce, aa, 2816 big.NewInt(0), 50000, big.NewInt(1), nil), types.NewNucleusSigner(big.NewInt(1)), key) 2817 nonce++ 2818 if e.exist { 2819 e.exist = false 2820 e.values = nil 2821 } 2822 t.Logf("block %d; adding destruct\n", e.blocknum) 2823 return tx 2824 } 2825 var newResurrect = func(e *expectation) *types.Transaction { 2826 tx, _ := types.SignTx(types.NewTransaction(nonce, bb, 2827 big.NewInt(0), 100000, big.NewInt(1), nil), types.NewNucleusSigner(big.NewInt(1)), key) 2828 nonce++ 2829 if !e.exist { 2830 e.exist = true 2831 e.values = map[int]int{3: e.blocknum + 1, 4: 4} 2832 } 2833 t.Logf("block %d; adding resurrect\n", e.blocknum) 2834 return tx 2835 } 2836 2837 blocks, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 150, func(i int, b *BlockGen) { 2838 var exp = new(expectation) 2839 exp.blocknum = i + 1 2840 exp.values = make(map[int]int) 2841 for k, v := range current.values { 2842 exp.values[k] = v 2843 } 2844 exp.exist = current.exist 2845 2846 b.SetCoinbase(common.Address{1}) 2847 if i%2 == 0 { 2848 b.AddTx(newDestruct(exp)) 2849 } 2850 if i%3 == 0 { 2851 b.AddTx(newResurrect(exp)) 2852 } 2853 if i%5 == 0 { 2854 b.AddTx(newDestruct(exp)) 2855 } 2856 if i%7 == 0 { 2857 b.AddTx(newResurrect(exp)) 2858 } 2859 expectations = append(expectations, exp) 2860 current = exp 2861 }) 2862 // Import the canonical chain 2863 diskdb := rawdb.NewMemoryDatabase() 2864 gspec.MustCommit(diskdb) 2865 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{ 2866 //Debug: true, 2867 //Tracer: vm.NewJSONLogger(nil, os.Stdout), 2868 }, nil, nil) 2869 if err != nil { 2870 t.Fatalf("failed to create tester chain: %v", err) 2871 } 2872 var asHash = func(num int) common.Hash { 2873 return common.BytesToHash([]byte{byte(num)}) 2874 } 2875 for i, block := range blocks { 2876 blockNum := i + 1 2877 if n, err := chain.InsertChain([]*types.Block{block}); err != nil { 2878 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2879 } 2880 statedb, _ := chain.State() 2881 // If all is correct, then slot 1 and 2 are zero 2882 if got, exp := statedb.GetState(aa, common.HexToHash("01")), (common.Hash{}); got != exp { 2883 t.Errorf("block %d, got %x exp %x", blockNum, got, exp) 2884 } 2885 if got, exp := statedb.GetState(aa, common.HexToHash("02")), (common.Hash{}); got != exp { 2886 t.Errorf("block %d, got %x exp %x", blockNum, got, exp) 2887 } 2888 exp := expectations[i] 2889 if exp.exist { 2890 if !statedb.Exist(aa) { 2891 t.Fatalf("block %d, expected %v to exist, it did not", blockNum, aa) 2892 } 2893 for slot, val := range exp.values { 2894 if gotValue, expValue := statedb.GetState(aa, asHash(slot)), asHash(val); gotValue != expValue { 2895 t.Fatalf("block %d, slot %d, got %x exp %x", blockNum, slot, gotValue, expValue) 2896 } 2897 } 2898 } else { 2899 if statedb.Exist(aa) { 2900 t.Fatalf("block %d, expected %v to not exist, it did", blockNum, aa) 2901 } 2902 } 2903 } 2904 } 2905 2906 // TestInitThenFailCreateContract tests a pretty notorious case that happened 2907 // on mainnet over blocks 7338108, 7338110 and 7338115. 2908 // - Block 7338108: address e771789f5cccac282f23bb7add5690e1f6ca467c is initiated 2909 // with 0.001 core (thus created but no code) 2910 // - Block 7338110: a CREATE2 is attempted. The CREATE2 would deploy code on 2911 // the same address e771789f5cccac282f23bb7add5690e1f6ca467c. However, the 2912 // deployment fails due to OOG during initcode execution 2913 // - Block 7338115: another tx checks the balance of 2914 // e771789f5cccac282f23bb7add5690e1f6ca467c, and the snapshotter returned it as 2915 // zero. 2916 // 2917 // The problem being that the snapshotter maintains a destructset, and adds items 2918 // to the destructset in case something is created "onto" an existing item. 2919 // We need to either roll back the snapDestructs, or not place it into snapDestructs 2920 // in the first place. 2921 func TestInitThenFailCreateContract(t *testing.T) { 2922 bb, err := common.HexToAddress("cb08000000000000000000000000000000000000bbbb") 2923 if err != nil { 2924 t.Error(err) 2925 } 2926 var ( 2927 // Generate a canonical chain to act as the main dataset 2928 engine = cryptore.NewFaker() 2929 db = rawdb.NewMemoryDatabase() 2930 // A sender who makes transactions, has some funds 2931 key, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 2932 address = key.Address() 2933 funds = big.NewInt(1000000000) 2934 ) 2935 2936 // The bb-code needs to CREATE2 the aa contract. It consists of 2937 // both initcode and deployment code 2938 // initcode: 2939 // 1. If blocknum < 1, error out (e.g invalid opcode) 2940 // 2. else, return a snippet of code 2941 initCode := []byte{ 2942 byte(vm.PUSH1), 0x1, // y (2) 2943 byte(vm.NUMBER), // x (number) 2944 byte(vm.GT), // x > y? 2945 byte(vm.PUSH1), byte(0x8), 2946 byte(vm.JUMPI), // jump to label if number > 2 2947 byte(0xFE), // illegal opcode 2948 byte(vm.JUMPDEST), 2949 byte(vm.PUSH1), 0x2, // size 2950 byte(vm.PUSH1), 0x0, // offset 2951 byte(vm.RETURN), // return 2 bytes of zero-code 2952 } 2953 if l := len(initCode); l > 32 { 2954 t.Fatalf("init code is too long for a pushx, need a more elaborate deployer") 2955 } 2956 bbCode := []byte{ 2957 // Push initcode onto stack 2958 byte(vm.PUSH1) + byte(len(initCode)-1)} 2959 bbCode = append(bbCode, initCode...) 2960 bbCode = append(bbCode, []byte{ 2961 byte(vm.PUSH1), 0x0, // memory start on stack 2962 byte(vm.MSTORE), 2963 byte(vm.PUSH1), 0x00, // salt 2964 byte(vm.PUSH1), byte(len(initCode)), // size 2965 byte(vm.PUSH1), byte(32 - len(initCode)), // offset 2966 byte(vm.PUSH1), 0x00, // endowment 2967 byte(vm.CREATE2), 2968 }...) 2969 2970 initHash := crypto.SHA3Hash(initCode) 2971 aa := crypto.CreateAddress2(bb, [32]byte{}, initHash[:]) 2972 t.Logf("Destination address: %x\n", aa) 2973 2974 gspec := &Genesis{ 2975 Config: params.MainnetChainConfig, 2976 Alloc: GenesisAlloc{ 2977 address: {Balance: funds}, 2978 // The address aa has some funds 2979 aa: {Balance: big.NewInt(100000)}, 2980 // The contract BB tries to create code onto AA 2981 bb: { 2982 Code: bbCode, 2983 Balance: big.NewInt(1), 2984 }, 2985 }, 2986 } 2987 genesis := gspec.MustCommit(db) 2988 nonce := uint64(0) 2989 blocks, _ := GenerateChain(params.MainnetChainConfig, genesis, engine, db, 4, func(i int, b *BlockGen) { 2990 b.SetCoinbase(common.Address{1}) 2991 // One transaction to BB 2992 tx, _ := types.SignTx(types.NewTransaction(nonce, bb, 2993 big.NewInt(0), 100000, big.NewInt(1), nil), types.NewNucleusSigner(big.NewInt(1)), key) 2994 b.AddTx(tx) 2995 nonce++ 2996 }) 2997 2998 // Import the canonical chain 2999 diskdb := rawdb.NewMemoryDatabase() 3000 gspec.MustCommit(diskdb) 3001 chain, err := NewBlockChain(diskdb, nil, params.MainnetChainConfig, engine, vm.Config{ 3002 //Debug: true, 3003 //Tracer: vm.NewJSONLogger(nil, os.Stdout), 3004 }, nil, nil) 3005 if err != nil { 3006 t.Fatalf("failed to create tester chain: %v", err) 3007 } 3008 statedb, _ := chain.State() 3009 if got, exp := statedb.GetBalance(aa), big.NewInt(100000); got.Cmp(exp) != 0 { 3010 t.Fatalf("Genesis err, got %v exp %v", got, exp) 3011 } 3012 // First block tries to create, but fails 3013 { 3014 block := blocks[0] 3015 if _, err := chain.InsertChain([]*types.Block{blocks[0]}); err != nil { 3016 t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) 3017 } 3018 statedb, _ = chain.State() 3019 if got, exp := statedb.GetBalance(aa), big.NewInt(100000); got.Cmp(exp) != 0 { 3020 t.Fatalf("block %d: got %v exp %v", block.NumberU64(), got, exp) 3021 } 3022 } 3023 // Import the rest of the blocks 3024 for _, block := range blocks[1:] { 3025 if _, err := chain.InsertChain([]*types.Block{block}); err != nil { 3026 t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) 3027 } 3028 } 3029 }