github.com/MetalBlockchain/subnet-evm@v0.4.9/core/blockchain_sethead_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 // Tests that setting the chain head backwards doesn't leave the database in some 28 // strange state with gaps in the chain, nor with block data dangling in the future. 29 30 package core 31 32 import ( 33 "testing" 34 35 "github.com/MetalBlockchain/subnet-evm/core/types" 36 ) 37 38 // verifyNoGaps checks that there are no gaps after the initial set of blocks in 39 // the database and errors if found. 40 func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks) { 41 t.Helper() 42 43 var end uint64 44 for i := uint64(0); i <= uint64(len(inserted)); i++ { 45 header := chain.GetHeaderByNumber(i) 46 if header == nil && end == 0 { 47 end = i 48 } 49 if header != nil && end > 0 { 50 if canonical { 51 t.Errorf("Canonical header gap between #%d-#%d", end, i-1) 52 } else { 53 t.Errorf("Sidechain header gap between #%d-#%d", end, i-1) 54 } 55 end = 0 // Reset for further gap detection 56 } 57 } 58 end = 0 59 for i := uint64(0); i <= uint64(len(inserted)); i++ { 60 block := chain.GetBlockByNumber(i) 61 if block == nil && end == 0 { 62 end = i 63 } 64 if block != nil && end > 0 { 65 if canonical { 66 t.Errorf("Canonical block gap between #%d-#%d", end, i-1) 67 } else { 68 t.Errorf("Sidechain block gap between #%d-#%d", end, i-1) 69 } 70 end = 0 // Reset for further gap detection 71 } 72 } 73 end = 0 74 for i := uint64(1); i <= uint64(len(inserted)); i++ { 75 receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()) 76 if receipts == nil && end == 0 { 77 end = i 78 } 79 if receipts != nil && end > 0 { 80 if canonical { 81 t.Errorf("Canonical receipt gap between #%d-#%d", end, i-1) 82 } else { 83 t.Errorf("Sidechain receipt gap between #%d-#%d", end, i-1) 84 } 85 end = 0 // Reset for further gap detection 86 } 87 } 88 } 89 90 // verifyCutoff checks that there are no chain data available in the chain after 91 // the specified limit, but that it is available before. 92 func verifyCutoff(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks, head int) { 93 t.Helper() 94 95 for i := 1; i <= len(inserted); i++ { 96 if i <= head { 97 if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header == nil { 98 if canonical { 99 t.Errorf("Canonical header #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 100 } else { 101 t.Errorf("Sidechain header #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 102 } 103 } 104 if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block == nil { 105 if canonical { 106 t.Errorf("Canonical block #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 107 } else { 108 t.Errorf("Sidechain block #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 109 } 110 } 111 if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts == nil { 112 if canonical { 113 t.Errorf("Canonical receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 114 } else { 115 t.Errorf("Sidechain receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 116 } 117 } 118 } else { 119 if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header != nil { 120 if canonical { 121 t.Errorf("Canonical header #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 122 } else { 123 t.Errorf("Sidechain header #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 124 } 125 } 126 if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block != nil { 127 if canonical { 128 t.Errorf("Canonical block #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 129 } else { 130 t.Errorf("Sidechain block #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 131 } 132 } 133 if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts != nil { 134 if canonical { 135 t.Errorf("Canonical receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 136 } else { 137 t.Errorf("Sidechain receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 138 } 139 } 140 } 141 } 142 }