github.com/theQRL/go-zond@v0.2.1/core/blockchain_reader.go (about) 1 // Copyright 2021 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 "github.com/theQRL/go-zond/common" 21 "github.com/theQRL/go-zond/consensus" 22 "github.com/theQRL/go-zond/core/rawdb" 23 "github.com/theQRL/go-zond/core/state" 24 "github.com/theQRL/go-zond/core/state/snapshot" 25 "github.com/theQRL/go-zond/core/types" 26 "github.com/theQRL/go-zond/core/vm" 27 "github.com/theQRL/go-zond/event" 28 "github.com/theQRL/go-zond/params" 29 "github.com/theQRL/go-zond/rlp" 30 "github.com/theQRL/go-zond/trie" 31 ) 32 33 // CurrentHeader retrieves the current head header of the canonical chain. The 34 // header is retrieved from the HeaderChain's internal cache. 35 func (bc *BlockChain) CurrentHeader() *types.Header { 36 return bc.hc.CurrentHeader() 37 } 38 39 // CurrentBlock retrieves the current head block of the canonical chain. The 40 // block is retrieved from the blockchain's internal cache. 41 func (bc *BlockChain) CurrentBlock() *types.Header { 42 return bc.currentBlock.Load() 43 } 44 45 // CurrentSnapBlock retrieves the current snap-sync head block of the canonical 46 // chain. The block is retrieved from the blockchain's internal cache. 47 func (bc *BlockChain) CurrentSnapBlock() *types.Header { 48 return bc.currentSnapBlock.Load() 49 } 50 51 // CurrentFinalBlock retrieves the current finalized block of the canonical 52 // chain. The block is retrieved from the blockchain's internal cache. 53 func (bc *BlockChain) CurrentFinalBlock() *types.Header { 54 return bc.currentFinalBlock.Load() 55 } 56 57 // CurrentSafeBlock retrieves the current safe block of the canonical 58 // chain. The block is retrieved from the blockchain's internal cache. 59 func (bc *BlockChain) CurrentSafeBlock() *types.Header { 60 return bc.currentSafeBlock.Load() 61 } 62 63 // HasHeader checks if a block header is present in the database or not, caching 64 // it if present. 65 func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool { 66 return bc.hc.HasHeader(hash, number) 67 } 68 69 // GetHeader retrieves a block header from the database by hash and number, 70 // caching it if found. 71 func (bc *BlockChain) GetHeader(hash common.Hash, number uint64) *types.Header { 72 return bc.hc.GetHeader(hash, number) 73 } 74 75 // GetHeaderByHash retrieves a block header from the database by hash, caching it if 76 // found. 77 func (bc *BlockChain) GetHeaderByHash(hash common.Hash) *types.Header { 78 return bc.hc.GetHeaderByHash(hash) 79 } 80 81 // GetHeaderByNumber retrieves a block header from the database by number, 82 // caching it (associated with its hash) if found. 83 func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header { 84 return bc.hc.GetHeaderByNumber(number) 85 } 86 87 // GetHeadersFrom returns a contiguous segment of headers, in rlp-form, going 88 // backwards from the given number. 89 func (bc *BlockChain) GetHeadersFrom(number, count uint64) []rlp.RawValue { 90 return bc.hc.GetHeadersFrom(number, count) 91 } 92 93 // GetBody retrieves a block body (transactions) from the database by 94 // hash, caching it if found. 95 func (bc *BlockChain) GetBody(hash common.Hash) *types.Body { 96 // Short circuit if the body's already in the cache, retrieve otherwise 97 if cached, ok := bc.bodyCache.Get(hash); ok { 98 return cached 99 } 100 number := bc.hc.GetBlockNumber(hash) 101 if number == nil { 102 return nil 103 } 104 body := rawdb.ReadBody(bc.db, hash, *number) 105 if body == nil { 106 return nil 107 } 108 // Cache the found body for next time and return 109 bc.bodyCache.Add(hash, body) 110 return body 111 } 112 113 // GetBodyRLP retrieves a block body in RLP encoding from the database by hash, 114 // caching it if found. 115 func (bc *BlockChain) GetBodyRLP(hash common.Hash) rlp.RawValue { 116 // Short circuit if the body's already in the cache, retrieve otherwise 117 if cached, ok := bc.bodyRLPCache.Get(hash); ok { 118 return cached 119 } 120 number := bc.hc.GetBlockNumber(hash) 121 if number == nil { 122 return nil 123 } 124 body := rawdb.ReadBodyRLP(bc.db, hash, *number) 125 if len(body) == 0 { 126 return nil 127 } 128 // Cache the found body for next time and return 129 bc.bodyRLPCache.Add(hash, body) 130 return body 131 } 132 133 // HasBlock checks if a block is fully present in the database or not. 134 func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool { 135 if bc.blockCache.Contains(hash) { 136 return true 137 } 138 if !bc.HasHeader(hash, number) { 139 return false 140 } 141 return rawdb.HasBody(bc.db, hash, number) 142 } 143 144 // HasFastBlock checks if a fast block is fully present in the database or not. 145 func (bc *BlockChain) HasFastBlock(hash common.Hash, number uint64) bool { 146 if !bc.HasBlock(hash, number) { 147 return false 148 } 149 if bc.receiptsCache.Contains(hash) { 150 return true 151 } 152 return rawdb.HasReceipts(bc.db, hash, number) 153 } 154 155 // GetBlock retrieves a block from the database by hash and number, 156 // caching it if found. 157 func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { 158 // Short circuit if the block's already in the cache, retrieve otherwise 159 if block, ok := bc.blockCache.Get(hash); ok { 160 return block 161 } 162 block := rawdb.ReadBlock(bc.db, hash, number) 163 if block == nil { 164 return nil 165 } 166 // Cache the found block for next time and return 167 bc.blockCache.Add(block.Hash(), block) 168 return block 169 } 170 171 // GetBlockByHash retrieves a block from the database by hash, caching it if found. 172 func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block { 173 number := bc.hc.GetBlockNumber(hash) 174 if number == nil { 175 return nil 176 } 177 return bc.GetBlock(hash, *number) 178 } 179 180 // GetBlockByNumber retrieves a block from the database by number, caching it 181 // (associated with its hash) if found. 182 func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block { 183 hash := rawdb.ReadCanonicalHash(bc.db, number) 184 if hash == (common.Hash{}) { 185 return nil 186 } 187 return bc.GetBlock(hash, number) 188 } 189 190 // GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors. 191 // [deprecated by zond/62] 192 func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) { 193 number := bc.hc.GetBlockNumber(hash) 194 if number == nil { 195 return nil 196 } 197 for i := 0; i < n; i++ { 198 block := bc.GetBlock(hash, *number) 199 if block == nil { 200 break 201 } 202 blocks = append(blocks, block) 203 hash = block.ParentHash() 204 *number-- 205 } 206 return 207 } 208 209 // GetReceiptsByHash retrieves the receipts for all transactions in a given block. 210 func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { 211 if receipts, ok := bc.receiptsCache.Get(hash); ok { 212 return receipts 213 } 214 number := rawdb.ReadHeaderNumber(bc.db, hash) 215 if number == nil { 216 return nil 217 } 218 header := bc.GetHeader(hash, *number) 219 if header == nil { 220 return nil 221 } 222 receipts := rawdb.ReadReceipts(bc.db, hash, *number, header.Time, bc.chainConfig) 223 if receipts == nil { 224 return nil 225 } 226 bc.receiptsCache.Add(hash, receipts) 227 return receipts 228 } 229 230 // GetCanonicalHash returns the canonical hash for a given block number 231 func (bc *BlockChain) GetCanonicalHash(number uint64) common.Hash { 232 return bc.hc.GetCanonicalHash(number) 233 } 234 235 // GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or 236 // a close ancestor of it is canonical. maxNonCanonical points to a downwards counter limiting the 237 // number of blocks to be individually checked before we reach the canonical chain. 238 // 239 // Note: ancestor == 0 returns the same block, 1 returns its parent and so on. 240 func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) { 241 return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical) 242 } 243 244 // HasState checks if state trie is fully present in the database or not. 245 func (bc *BlockChain) HasState(hash common.Hash) bool { 246 _, err := bc.stateCache.OpenTrie(hash) 247 return err == nil 248 } 249 250 // HasBlockAndState checks if a block and associated state trie is fully present 251 // in the database or not, caching it if present. 252 func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool { 253 // Check first that the block itself is known 254 block := bc.GetBlock(hash, number) 255 if block == nil { 256 return false 257 } 258 return bc.HasState(block.Root()) 259 } 260 261 // stateRecoverable checks if the specified state is recoverable. 262 // Note, this function assumes the state is not present, because 263 // state is not treated as recoverable if it's available, thus 264 // false will be returned in this case. 265 func (bc *BlockChain) stateRecoverable(root common.Hash) bool { 266 if bc.triedb.Scheme() == rawdb.HashScheme { 267 return false 268 } 269 result, _ := bc.triedb.Recoverable(root) 270 return result 271 } 272 273 // ContractCodeWithPrefix retrieves a blob of data associated with a contract 274 // hash either from ephemeral in-memory cache, or from persistent storage. 275 // 276 // If the code doesn't exist in the in-memory cache, check the storage with 277 // new code scheme. 278 func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) { 279 type codeReader interface { 280 ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error) 281 } 282 // TODO(rjl493456442) The associated account address is also required 283 // in Verkle scheme. Fix it once snap-sync is supported for Verkle. 284 return bc.stateCache.(codeReader).ContractCodeWithPrefix(common.Address{}, hash) 285 } 286 287 // State returns a new mutable state based on the current HEAD block. 288 func (bc *BlockChain) State() (*state.StateDB, error) { 289 return bc.StateAt(bc.CurrentBlock().Root) 290 } 291 292 // StateAt returns a new mutable state based on a particular point in time. 293 func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) { 294 return state.New(root, bc.stateCache, bc.snaps) 295 } 296 297 // Config retrieves the chain's fork configuration. 298 func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig } 299 300 // Engine retrieves the blockchain's consensus engine. 301 func (bc *BlockChain) Engine() consensus.Engine { return bc.engine } 302 303 // Snapshots returns the blockchain snapshot tree. 304 func (bc *BlockChain) Snapshots() *snapshot.Tree { 305 return bc.snaps 306 } 307 308 // Validator returns the current validator. 309 func (bc *BlockChain) Validator() Validator { 310 return bc.validator 311 } 312 313 // Processor returns the current processor. 314 func (bc *BlockChain) Processor() Processor { 315 return bc.processor 316 } 317 318 // StateCache returns the caching database underpinning the blockchain instance. 319 func (bc *BlockChain) StateCache() state.Database { 320 return bc.stateCache 321 } 322 323 // GasLimit returns the gas limit of the current HEAD block. 324 func (bc *BlockChain) GasLimit() uint64 { 325 return bc.CurrentBlock().GasLimit 326 } 327 328 // Genesis retrieves the chain's genesis block. 329 func (bc *BlockChain) Genesis() *types.Block { 330 return bc.genesisBlock 331 } 332 333 // GetVMConfig returns the block chain VM config. 334 func (bc *BlockChain) GetVMConfig() *vm.Config { 335 return &bc.vmConfig 336 } 337 338 // SetTxLookupLimit is responsible for updating the txlookup limit to the 339 // original one stored in db if the new mismatches with the old one. 340 func (bc *BlockChain) SetTxLookupLimit(limit uint64) { 341 bc.txLookupLimit = limit 342 } 343 344 // TxLookupLimit retrieves the txlookup limit used by blockchain to prune 345 // stale transaction indices. 346 func (bc *BlockChain) TxLookupLimit() uint64 { 347 return bc.txLookupLimit 348 } 349 350 // TrieDB retrieves the low level trie database used for data storage. 351 func (bc *BlockChain) TrieDB() *trie.Database { 352 return bc.triedb 353 } 354 355 // SubscribeRemovedLogsEvent registers a subscription of RemovedLogsEvent. 356 func (bc *BlockChain) SubscribeRemovedLogsEvent(ch chan<- RemovedLogsEvent) event.Subscription { 357 return bc.scope.Track(bc.rmLogsFeed.Subscribe(ch)) 358 } 359 360 // SubscribeChainEvent registers a subscription of ChainEvent. 361 func (bc *BlockChain) SubscribeChainEvent(ch chan<- ChainEvent) event.Subscription { 362 return bc.scope.Track(bc.chainFeed.Subscribe(ch)) 363 } 364 365 // SubscribeChainHeadEvent registers a subscription of ChainHeadEvent. 366 func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription { 367 return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch)) 368 } 369 370 // SubscribeChainSideEvent registers a subscription of ChainSideEvent. 371 func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription { 372 return bc.scope.Track(bc.chainSideFeed.Subscribe(ch)) 373 } 374 375 // SubscribeLogsEvent registers a subscription of []*types.Log. 376 func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { 377 return bc.scope.Track(bc.logsFeed.Subscribe(ch)) 378 } 379 380 // SubscribeBlockProcessingEvent registers a subscription of bool where true means 381 // block processing has started while false means it has stopped. 382 func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscription { 383 return bc.scope.Track(bc.blockProcFeed.Subscribe(ch)) 384 }