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