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