github.com/MetalBlockchain/subnet-evm@v0.4.9/core/headerchain_test.go (about) 1 // (c) 2019-2021, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2020 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package core 28 29 import ( 30 "errors" 31 "fmt" 32 "math/big" 33 "testing" 34 35 "github.com/MetalBlockchain/subnet-evm/consensus" 36 "github.com/MetalBlockchain/subnet-evm/consensus/dummy" 37 "github.com/MetalBlockchain/subnet-evm/core/rawdb" 38 "github.com/MetalBlockchain/subnet-evm/core/types" 39 "github.com/MetalBlockchain/subnet-evm/core/vm" 40 "github.com/MetalBlockchain/subnet-evm/params" 41 "github.com/ethereum/go-ethereum/common" 42 "github.com/ethereum/go-ethereum/log" 43 ) 44 45 func verifyUnbrokenCanonchain(bc *BlockChain) error { 46 h := bc.hc.CurrentHeader() 47 for { 48 canonHash := rawdb.ReadCanonicalHash(bc.hc.chainDb, h.Number.Uint64()) 49 if exp := h.Hash(); canonHash != exp { 50 return fmt.Errorf("Canon hash chain broken, block %d got %x, expected %x", 51 h.Number, canonHash[:8], exp[:8]) 52 } 53 if h.Number.Uint64() == 0 { 54 break 55 } 56 h = bc.hc.GetHeader(h.ParentHash, h.Number.Uint64()-1) 57 } 58 return nil 59 } 60 61 func testInsert(t *testing.T, bc *BlockChain, chain []*types.Block, wantErr error) { 62 t.Helper() 63 64 _, err := bc.InsertChain(chain) 65 // Always verify that the header chain is unbroken 66 if err := verifyUnbrokenCanonchain(bc); err != nil { 67 t.Fatal(err) 68 } 69 if !errors.Is(err, wantErr) { 70 t.Fatalf("unexpected error from InsertHeaderChain: %v", err) 71 } 72 } 73 74 // This test checks status reporting of InsertHeaderChain. 75 func TestHeaderInsertion(t *testing.T) { 76 var ( 77 db = rawdb.NewMemoryDatabase() 78 genesis = (&Genesis{ 79 BaseFee: big.NewInt(params.TestInitialBaseFee), 80 Config: params.TestChainConfig, 81 }).MustCommit(db) 82 ) 83 chain, err := NewBlockChain(db, DefaultCacheConfig, params.TestChainConfig, dummy.NewCoinbaseFaker(), vm.Config{}, common.Hash{}) 84 if err != nil { 85 t.Fatal(err) 86 } 87 // chain A: G->A1->A2...A128 88 chainA, _, _ := GenerateChain(params.TestChainConfig, types.NewBlockWithHeader(genesis.Header()), dummy.NewCoinbaseFaker(), db, 128, 10, func(i int, b *BlockGen) { 89 b.SetCoinbase(common.Address{0: byte(10), 19: byte(i)}) 90 }) 91 // chain B: G->A1->B2...B128 92 chainB, _, _ := GenerateChain(params.TestChainConfig, types.NewBlockWithHeader(chainA[0].Header()), dummy.NewCoinbaseFaker(), db, 128, 10, func(i int, b *BlockGen) { 93 b.SetCoinbase(common.Address{0: byte(10), 19: byte(i)}) 94 }) 95 log.Root().SetHandler(log.StdoutHandler) 96 97 // Inserting 64 headers on an empty chain 98 testInsert(t, chain, chainA[:64], nil) 99 100 // Inserting 64 identical headers 101 testInsert(t, chain, chainA[:64], nil) 102 103 // Inserting the same some old, some new headers 104 testInsert(t, chain, chainA[32:96], nil) 105 106 // Inserting side blocks, but not overtaking the canon chain 107 testInsert(t, chain, chainB[0:32], nil) 108 109 // Inserting more side blocks, but we don't have the parent 110 testInsert(t, chain, chainB[34:36], consensus.ErrUnknownAncestor) 111 112 // Inserting more sideblocks, overtaking the canon chain 113 testInsert(t, chain, chainB[32:97], nil) 114 115 // Inserting more A-headers, taking back the canonicality 116 testInsert(t, chain, chainA[90:100], nil) 117 118 // And B becomes canon again 119 testInsert(t, chain, chainB[97:107], nil) 120 121 // And B becomes even longer 122 testInsert(t, chain, chainB[107:128], nil) 123 }