github.com/dim4egster/coreth@v0.10.2/core/blockchain_reader.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 2021 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 "github.com/dim4egster/coreth/consensus" 31 "github.com/dim4egster/coreth/core/rawdb" 32 "github.com/dim4egster/coreth/core/state" 33 "github.com/dim4egster/coreth/core/state/snapshot" 34 "github.com/dim4egster/coreth/core/types" 35 "github.com/dim4egster/coreth/core/vm" 36 "github.com/dim4egster/coreth/params" 37 "github.com/ethereum/go-ethereum/common" 38 "github.com/ethereum/go-ethereum/event" 39 ) 40 41 // CurrentHeader retrieves the current head header of the canonical chain. The 42 // header is retrieved from the HeaderChain's internal cache. 43 func (bc *BlockChain) CurrentHeader() *types.Header { 44 return bc.hc.CurrentHeader() 45 } 46 47 // CurrentBlock retrieves the current head block of the canonical chain. The 48 // block is retrieved from the blockchain's internal cache. 49 func (bc *BlockChain) CurrentBlock() *types.Block { 50 return bc.currentBlock.Load().(*types.Block) 51 } 52 53 // HasHeader checks if a block header is present in the database or not, caching 54 // it if present. 55 func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool { 56 return bc.hc.HasHeader(hash, number) 57 } 58 59 // GetHeader retrieves a block header from the database by hash and number, 60 // caching it if found. 61 func (bc *BlockChain) GetHeader(hash common.Hash, number uint64) *types.Header { 62 return bc.hc.GetHeader(hash, number) 63 } 64 65 // GetHeaderByHash retrieves a block header from the database by hash, caching it if 66 // found. 67 func (bc *BlockChain) GetHeaderByHash(hash common.Hash) *types.Header { 68 return bc.hc.GetHeaderByHash(hash) 69 } 70 71 // GetHeaderByNumber retrieves a block header from the database by number, 72 // caching it (associated with its hash) if found. 73 func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header { 74 return bc.hc.GetHeaderByNumber(number) 75 } 76 77 // GetBody retrieves a block body (transactions and uncles) from the database by 78 // hash, caching it if found. 79 func (bc *BlockChain) GetBody(hash common.Hash) *types.Body { 80 // Short circuit if the body's already in the cache, retrieve otherwise 81 if cached, ok := bc.bodyCache.Get(hash); ok { 82 body := cached.(*types.Body) 83 return body 84 } 85 number := bc.hc.GetBlockNumber(hash) 86 if number == nil { 87 return nil 88 } 89 body := rawdb.ReadBody(bc.db, hash, *number) 90 if body == nil { 91 return nil 92 } 93 // Cache the found body for next time and return 94 bc.bodyCache.Add(hash, body) 95 return body 96 } 97 98 // HasBlock checks if a block is fully present in the database or not. 99 func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool { 100 if bc.blockCache.Contains(hash) { 101 return true 102 } 103 if !bc.HasHeader(hash, number) { 104 return false 105 } 106 return rawdb.HasBody(bc.db, hash, number) 107 } 108 109 // HasFastBlock checks if a fast block is fully present in the database or not. 110 func (bc *BlockChain) HasFastBlock(hash common.Hash, number uint64) bool { 111 if !bc.HasBlock(hash, number) { 112 return false 113 } 114 if bc.receiptsCache.Contains(hash) { 115 return true 116 } 117 return rawdb.HasReceipts(bc.db, hash, number) 118 } 119 120 // GetBlock retrieves a block from the database by hash and number, 121 // caching it if found. 122 func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { 123 // Short circuit if the block's already in the cache, retrieve otherwise 124 if block, ok := bc.blockCache.Get(hash); ok { 125 return block.(*types.Block) 126 } 127 block := rawdb.ReadBlock(bc.db, hash, number) 128 if block == nil { 129 return nil 130 } 131 // Cache the found block for next time and return 132 bc.blockCache.Add(block.Hash(), block) 133 return block 134 } 135 136 // GetBlockByHash retrieves a block from the database by hash, caching it if found. 137 func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block { 138 number := bc.hc.GetBlockNumber(hash) 139 if number == nil { 140 return nil 141 } 142 return bc.GetBlock(hash, *number) 143 } 144 145 // GetBlockByNumber retrieves a block from the database by number, caching it 146 // (associated with its hash) if found. 147 func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block { 148 hash := rawdb.ReadCanonicalHash(bc.db, number) 149 if hash == (common.Hash{}) { 150 return nil 151 } 152 return bc.GetBlock(hash, number) 153 } 154 155 // GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors. 156 // [deprecated by eth/62] 157 func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) { 158 number := bc.hc.GetBlockNumber(hash) 159 if number == nil { 160 return nil 161 } 162 for i := 0; i < n; i++ { 163 block := bc.GetBlock(hash, *number) 164 if block == nil { 165 break 166 } 167 blocks = append(blocks, block) 168 hash = block.ParentHash() 169 *number-- 170 } 171 return 172 } 173 174 // GetReceiptsByHash retrieves the receipts for all transactions in a given block. 175 func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { 176 if receipts, ok := bc.receiptsCache.Get(hash); ok { 177 return receipts.(types.Receipts) 178 } 179 number := rawdb.ReadHeaderNumber(bc.db, hash) 180 if number == nil { 181 return nil 182 } 183 receipts := rawdb.ReadReceipts(bc.db, hash, *number, bc.chainConfig) 184 if receipts == nil { 185 return nil 186 } 187 bc.receiptsCache.Add(hash, receipts) 188 return receipts 189 } 190 191 // GetCanonicalHash returns the canonical hash for a given block number 192 func (bc *BlockChain) GetCanonicalHash(number uint64) common.Hash { 193 return bc.hc.GetCanonicalHash(number) 194 } 195 196 // GetTransactionLookup retrieves the lookup associate with the given transaction 197 // hash from the cache or database. 198 func (bc *BlockChain) GetTransactionLookup(hash common.Hash) *rawdb.LegacyTxLookupEntry { 199 // Short circuit if the txlookup already in the cache, retrieve otherwise 200 if lookup, exist := bc.txLookupCache.Get(hash); exist { 201 return lookup.(*rawdb.LegacyTxLookupEntry) 202 } 203 tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash) 204 if tx == nil { 205 return nil 206 } 207 lookup := &rawdb.LegacyTxLookupEntry{BlockHash: blockHash, BlockIndex: blockNumber, Index: txIndex} 208 bc.txLookupCache.Add(hash, lookup) 209 return lookup 210 } 211 212 // HasState checks if state trie is fully present in the database or not. 213 func (bc *BlockChain) HasState(hash common.Hash) bool { 214 _, err := bc.stateCache.OpenTrie(hash) 215 return err == nil 216 } 217 218 // HasBlockAndState checks if a block and associated state trie is fully present 219 // in the database or not, caching it if present. 220 func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool { 221 // Check first that the block itself is known 222 block := bc.GetBlock(hash, number) 223 if block == nil { 224 return false 225 } 226 return bc.HasState(block.Root()) 227 } 228 229 // TrieNode retrieves a blob of data associated with a trie node 230 // either from ephemeral in-memory cache, or from persistent storage. 231 func (bc *BlockChain) TrieNode(hash common.Hash) ([]byte, error) { 232 return bc.stateCache.TrieDB().RawNode(hash) 233 } 234 235 // ContractCode retrieves a blob of data associated with a contract hash 236 // either from ephemeral in-memory cache, or from persistent storage. 237 func (bc *BlockChain) ContractCode(hash common.Hash) ([]byte, error) { 238 return bc.stateCache.ContractCode(common.Hash{}, hash) 239 } 240 241 // State returns a new mutable state based on the current HEAD block. 242 func (bc *BlockChain) State() (*state.StateDB, error) { 243 return bc.StateAt(bc.CurrentBlock().Root()) 244 } 245 246 // StateAt returns a new mutable state based on a particular point in time. 247 func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) { 248 return state.New(root, bc.stateCache, bc.snaps) 249 } 250 251 // Config retrieves the chain's fork configuration. 252 func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig } 253 254 // Engine retrieves the blockchain's consensus engine. 255 func (bc *BlockChain) Engine() consensus.Engine { return bc.engine } 256 257 // Snapshots returns the blockchain snapshot tree. 258 func (bc *BlockChain) Snapshots() *snapshot.Tree { 259 return bc.snaps 260 } 261 262 // Validator returns the current validator. 263 func (bc *BlockChain) Validator() Validator { 264 return bc.validator 265 } 266 267 // Processor returns the current processor. 268 func (bc *BlockChain) Processor() Processor { 269 return bc.processor 270 } 271 272 // StateCache returns the caching database underpinning the blockchain instance. 273 func (bc *BlockChain) StateCache() state.Database { 274 return bc.stateCache 275 } 276 277 // GasLimit returns the gas limit of the current HEAD block. 278 func (bc *BlockChain) GasLimit() uint64 { 279 return bc.CurrentBlock().GasLimit() 280 } 281 282 // Genesis retrieves the chain's genesis block. 283 func (bc *BlockChain) Genesis() *types.Block { 284 return bc.genesisBlock 285 } 286 287 // GetVMConfig returns the block chain VM config. 288 func (bc *BlockChain) GetVMConfig() *vm.Config { 289 return &bc.vmConfig 290 } 291 292 // SubscribeRemovedLogsEvent registers a subscription of RemovedLogsEvent. 293 func (bc *BlockChain) SubscribeRemovedLogsEvent(ch chan<- RemovedLogsEvent) event.Subscription { 294 return bc.scope.Track(bc.rmLogsFeed.Subscribe(ch)) 295 } 296 297 // SubscribeChainEvent registers a subscription of ChainEvent. 298 func (bc *BlockChain) SubscribeChainEvent(ch chan<- ChainEvent) event.Subscription { 299 return bc.scope.Track(bc.chainFeed.Subscribe(ch)) 300 } 301 302 // SubscribeChainHeadEvent registers a subscription of ChainHeadEvent. 303 func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription { 304 return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch)) 305 } 306 307 // SubscribeChainSideEvent registers a subscription of ChainSideEvent. 308 func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription { 309 return bc.scope.Track(bc.chainSideFeed.Subscribe(ch)) 310 } 311 312 // SubscribeLogsEvent registers a subscription of []*types.Log. 313 func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { 314 return bc.scope.Track(bc.logsFeed.Subscribe(ch)) 315 } 316 317 // SubscribeBlockProcessingEvent registers a subscription of bool where true means 318 // block processing has started while false means it has stopped. 319 func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscription { 320 return bc.scope.Track(bc.blockProcFeed.Subscribe(ch)) 321 } 322 323 // SubscribeChainAcceptedEvent registers a subscription of ChainEvent. 324 func (bc *BlockChain) SubscribeChainAcceptedEvent(ch chan<- ChainEvent) event.Subscription { 325 return bc.scope.Track(bc.chainAcceptedFeed.Subscribe(ch)) 326 } 327 328 // SubscribeAcceptedLogsEvent registers a subscription of accepted []*types.Log. 329 func (bc *BlockChain) SubscribeAcceptedLogsEvent(ch chan<- []*types.Log) event.Subscription { 330 return bc.scope.Track(bc.logsAcceptedFeed.Subscribe(ch)) 331 } 332 333 // SubscribeAcceptedTransactionEvent registers a subscription of accepted transactions 334 func (bc *BlockChain) SubscribeAcceptedTransactionEvent(ch chan<- NewTxsEvent) event.Subscription { 335 return bc.scope.Track(bc.txAcceptedFeed.Subscribe(ch)) 336 }