github.com/MetalBlockchain/subnet-evm@v0.4.9/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 "fmt" 31 "math/big" 32 33 "github.com/MetalBlockchain/subnet-evm/commontype" 34 "github.com/MetalBlockchain/subnet-evm/consensus" 35 "github.com/MetalBlockchain/subnet-evm/constants" 36 "github.com/MetalBlockchain/subnet-evm/core/rawdb" 37 "github.com/MetalBlockchain/subnet-evm/core/state" 38 "github.com/MetalBlockchain/subnet-evm/core/state/snapshot" 39 "github.com/MetalBlockchain/subnet-evm/core/types" 40 "github.com/MetalBlockchain/subnet-evm/core/vm" 41 "github.com/MetalBlockchain/subnet-evm/params" 42 "github.com/MetalBlockchain/subnet-evm/precompile" 43 "github.com/ethereum/go-ethereum/common" 44 "github.com/ethereum/go-ethereum/event" 45 ) 46 47 // CurrentHeader retrieves the current head header of the canonical chain. The 48 // header is retrieved from the HeaderChain's internal cache. 49 func (bc *BlockChain) CurrentHeader() *types.Header { 50 return bc.hc.CurrentHeader() 51 } 52 53 // CurrentBlock retrieves the current head block of the canonical chain. The 54 // block is retrieved from the blockchain's internal cache. 55 func (bc *BlockChain) CurrentBlock() *types.Block { 56 return bc.currentBlock.Load().(*types.Block) 57 } 58 59 // HasHeader checks if a block header is present in the database or not, caching 60 // it if present. 61 func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool { 62 return bc.hc.HasHeader(hash, number) 63 } 64 65 // GetHeader retrieves a block header from the database by hash and number, 66 // caching it if found. 67 func (bc *BlockChain) GetHeader(hash common.Hash, number uint64) *types.Header { 68 return bc.hc.GetHeader(hash, number) 69 } 70 71 // GetHeaderByHash retrieves a block header from the database by hash, caching it if 72 // found. 73 func (bc *BlockChain) GetHeaderByHash(hash common.Hash) *types.Header { 74 return bc.hc.GetHeaderByHash(hash) 75 } 76 77 // GetHeaderByNumber retrieves a block header from the database by number, 78 // caching it (associated with its hash) if found. 79 func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header { 80 return bc.hc.GetHeaderByNumber(number) 81 } 82 83 // GetBody retrieves a block body (transactions and uncles) from the database by 84 // hash, caching it if found. 85 func (bc *BlockChain) GetBody(hash common.Hash) *types.Body { 86 // Short circuit if the body's already in the cache, retrieve otherwise 87 if cached, ok := bc.bodyCache.Get(hash); ok { 88 body := cached.(*types.Body) 89 return body 90 } 91 number := bc.hc.GetBlockNumber(hash) 92 if number == nil { 93 return nil 94 } 95 body := rawdb.ReadBody(bc.db, hash, *number) 96 if body == nil { 97 return nil 98 } 99 // Cache the found body for next time and return 100 bc.bodyCache.Add(hash, body) 101 return body 102 } 103 104 // HasBlock checks if a block is fully present in the database or not. 105 func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool { 106 if bc.blockCache.Contains(hash) { 107 return true 108 } 109 if !bc.HasHeader(hash, number) { 110 return false 111 } 112 return rawdb.HasBody(bc.db, hash, number) 113 } 114 115 // HasFastBlock checks if a fast block is fully present in the database or not. 116 func (bc *BlockChain) HasFastBlock(hash common.Hash, number uint64) bool { 117 if !bc.HasBlock(hash, number) { 118 return false 119 } 120 if bc.receiptsCache.Contains(hash) { 121 return true 122 } 123 return rawdb.HasReceipts(bc.db, hash, number) 124 } 125 126 // GetBlock retrieves a block from the database by hash and number, 127 // caching it if found. 128 func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { 129 // Short circuit if the block's already in the cache, retrieve otherwise 130 if block, ok := bc.blockCache.Get(hash); ok { 131 return block.(*types.Block) 132 } 133 block := rawdb.ReadBlock(bc.db, hash, number) 134 if block == nil { 135 return nil 136 } 137 // Cache the found block for next time and return 138 bc.blockCache.Add(block.Hash(), block) 139 return block 140 } 141 142 // GetBlockByHash retrieves a block from the database by hash, caching it if found. 143 func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block { 144 number := bc.hc.GetBlockNumber(hash) 145 if number == nil { 146 return nil 147 } 148 return bc.GetBlock(hash, *number) 149 } 150 151 // GetBlockByNumber retrieves a block from the database by number, caching it 152 // (associated with its hash) if found. 153 func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block { 154 hash := rawdb.ReadCanonicalHash(bc.db, number) 155 if hash == (common.Hash{}) { 156 return nil 157 } 158 return bc.GetBlock(hash, number) 159 } 160 161 // GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors. 162 // [deprecated by eth/62] 163 func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) { 164 number := bc.hc.GetBlockNumber(hash) 165 if number == nil { 166 return nil 167 } 168 for i := 0; i < n; i++ { 169 block := bc.GetBlock(hash, *number) 170 if block == nil { 171 break 172 } 173 blocks = append(blocks, block) 174 hash = block.ParentHash() 175 *number-- 176 } 177 return 178 } 179 180 // GetReceiptsByHash retrieves the receipts for all transactions in a given block. 181 func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { 182 if receipts, ok := bc.receiptsCache.Get(hash); ok { 183 return receipts.(types.Receipts) 184 } 185 number := rawdb.ReadHeaderNumber(bc.db, hash) 186 if number == nil { 187 return nil 188 } 189 receipts := rawdb.ReadReceipts(bc.db, hash, *number, bc.chainConfig) 190 if receipts == nil { 191 return nil 192 } 193 bc.receiptsCache.Add(hash, receipts) 194 return receipts 195 } 196 197 // GetCanonicalHash returns the canonical hash for a given block number 198 func (bc *BlockChain) GetCanonicalHash(number uint64) common.Hash { 199 return bc.hc.GetCanonicalHash(number) 200 } 201 202 // GetTransactionLookup retrieves the lookup associate with the given transaction 203 // hash from the cache or database. 204 func (bc *BlockChain) GetTransactionLookup(hash common.Hash) *rawdb.LegacyTxLookupEntry { 205 // Short circuit if the txlookup already in the cache, retrieve otherwise 206 if lookup, exist := bc.txLookupCache.Get(hash); exist { 207 return lookup.(*rawdb.LegacyTxLookupEntry) 208 } 209 tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash) 210 if tx == nil { 211 return nil 212 } 213 lookup := &rawdb.LegacyTxLookupEntry{BlockHash: blockHash, BlockIndex: blockNumber, Index: txIndex} 214 bc.txLookupCache.Add(hash, lookup) 215 return lookup 216 } 217 218 // HasState checks if state trie is fully present in the database or not. 219 func (bc *BlockChain) HasState(hash common.Hash) bool { 220 _, err := bc.stateCache.OpenTrie(hash) 221 return err == nil 222 } 223 224 // HasBlockAndState checks if a block and associated state trie is fully present 225 // in the database or not, caching it if present. 226 func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool { 227 // Check first that the block itself is known 228 block := bc.GetBlock(hash, number) 229 if block == nil { 230 return false 231 } 232 return bc.HasState(block.Root()) 233 } 234 235 // TrieNode retrieves a blob of data associated with a trie node 236 // either from ephemeral in-memory cache, or from persistent storage. 237 func (bc *BlockChain) TrieNode(hash common.Hash) ([]byte, error) { 238 return bc.stateCache.TrieDB().RawNode(hash) 239 } 240 241 // ContractCode retrieves a blob of data associated with a contract hash 242 // either from ephemeral in-memory cache, or from persistent storage. 243 func (bc *BlockChain) ContractCode(hash common.Hash) ([]byte, error) { 244 return bc.stateCache.ContractCode(common.Hash{}, hash) 245 } 246 247 // State returns a new mutable state based on the current HEAD block. 248 func (bc *BlockChain) State() (*state.StateDB, error) { 249 return bc.StateAt(bc.CurrentBlock().Root()) 250 } 251 252 // StateAt returns a new mutable state based on a particular point in time. 253 func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) { 254 return state.New(root, bc.stateCache, bc.snaps) 255 } 256 257 // Config retrieves the chain's fork configuration. 258 func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig } 259 260 // Engine retrieves the blockchain's consensus engine. 261 func (bc *BlockChain) Engine() consensus.Engine { return bc.engine } 262 263 // Snapshots returns the blockchain snapshot tree. 264 func (bc *BlockChain) Snapshots() *snapshot.Tree { 265 return bc.snaps 266 } 267 268 // Validator returns the current validator. 269 func (bc *BlockChain) Validator() Validator { 270 return bc.validator 271 } 272 273 // Processor returns the current processor. 274 func (bc *BlockChain) Processor() Processor { 275 return bc.processor 276 } 277 278 // StateCache returns the caching database underpinning the blockchain instance. 279 func (bc *BlockChain) StateCache() state.Database { 280 return bc.stateCache 281 } 282 283 // GasLimit returns the gas limit of the current HEAD block. 284 func (bc *BlockChain) GasLimit() uint64 { 285 return bc.CurrentBlock().GasLimit() 286 } 287 288 // Genesis retrieves the chain's genesis block. 289 func (bc *BlockChain) Genesis() *types.Block { 290 return bc.genesisBlock 291 } 292 293 // GetVMConfig returns the block chain VM config. 294 func (bc *BlockChain) GetVMConfig() *vm.Config { 295 return &bc.vmConfig 296 } 297 298 // SubscribeRemovedLogsEvent registers a subscription of RemovedLogsEvent. 299 func (bc *BlockChain) SubscribeRemovedLogsEvent(ch chan<- RemovedLogsEvent) event.Subscription { 300 return bc.scope.Track(bc.rmLogsFeed.Subscribe(ch)) 301 } 302 303 // SubscribeChainEvent registers a subscription of ChainEvent. 304 func (bc *BlockChain) SubscribeChainEvent(ch chan<- ChainEvent) event.Subscription { 305 return bc.scope.Track(bc.chainFeed.Subscribe(ch)) 306 } 307 308 // SubscribeChainHeadEvent registers a subscription of ChainHeadEvent. 309 func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription { 310 return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch)) 311 } 312 313 // SubscribeChainSideEvent registers a subscription of ChainSideEvent. 314 func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription { 315 return bc.scope.Track(bc.chainSideFeed.Subscribe(ch)) 316 } 317 318 // SubscribeLogsEvent registers a subscription of []*types.Log. 319 func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { 320 return bc.scope.Track(bc.logsFeed.Subscribe(ch)) 321 } 322 323 // SubscribeBlockProcessingEvent registers a subscription of bool where true means 324 // block processing has started while false means it has stopped. 325 func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscription { 326 return bc.scope.Track(bc.blockProcFeed.Subscribe(ch)) 327 } 328 329 // SubscribeChainAcceptedEvent registers a subscription of ChainEvent. 330 func (bc *BlockChain) SubscribeChainAcceptedEvent(ch chan<- ChainEvent) event.Subscription { 331 return bc.scope.Track(bc.chainAcceptedFeed.Subscribe(ch)) 332 } 333 334 // SubscribeAcceptedLogsEvent registers a subscription of accepted []*types.Log. 335 func (bc *BlockChain) SubscribeAcceptedLogsEvent(ch chan<- []*types.Log) event.Subscription { 336 return bc.scope.Track(bc.logsAcceptedFeed.Subscribe(ch)) 337 } 338 339 // SubscribeAcceptedTransactionEvent registers a subscription of accepted transactions 340 func (bc *BlockChain) SubscribeAcceptedTransactionEvent(ch chan<- NewTxsEvent) event.Subscription { 341 return bc.scope.Track(bc.txAcceptedFeed.Subscribe(ch)) 342 } 343 344 // GetFeeConfigAt returns the fee configuration and the last changed block number at [parent]. 345 // If FeeConfigManager is activated at [parent], returns the fee config in the precompile contract state. 346 // Otherwise returns the fee config in the chain config. 347 // Assumes that a valid configuration is stored when the precompile is activated. 348 func (bc *BlockChain) GetFeeConfigAt(parent *types.Header) (commontype.FeeConfig, *big.Int, error) { 349 config := bc.Config() 350 bigTime := new(big.Int).SetUint64(parent.Time) 351 if !config.IsFeeConfigManager(bigTime) { 352 return config.FeeConfig, common.Big0, nil 353 } 354 355 // try to return it from the cache 356 if cached, hit := bc.feeConfigCache.Get(parent.Root); hit { 357 cachedFeeConfig, ok := cached.(*cacheableFeeConfig) 358 if !ok { 359 return commontype.EmptyFeeConfig, nil, fmt.Errorf("expected type cacheableFeeConfig, got %T", cached) 360 } 361 return cachedFeeConfig.feeConfig, cachedFeeConfig.lastChangedAt, nil 362 } 363 364 stateDB, err := bc.StateAt(parent.Root) 365 if err != nil { 366 return commontype.EmptyFeeConfig, nil, err 367 } 368 369 storedFeeConfig := precompile.GetStoredFeeConfig(stateDB) 370 // this should not return an invalid fee config since it's assumed that 371 // StoreFeeConfig returns an error when an invalid fee config is attempted to be stored. 372 // However an external stateDB call can modify the contract state. 373 // This check is added to add a defense in-depth. 374 if err := storedFeeConfig.Verify(); err != nil { 375 return commontype.EmptyFeeConfig, nil, err 376 } 377 lastChangedAt := precompile.GetFeeConfigLastChangedAt(stateDB) 378 cacheable := &cacheableFeeConfig{feeConfig: storedFeeConfig, lastChangedAt: lastChangedAt} 379 // add it to the cache 380 bc.feeConfigCache.Add(parent.Root, cacheable) 381 return storedFeeConfig, lastChangedAt, nil 382 } 383 384 // GetCoinbaseAt returns the configured coinbase address at [parent]. 385 // If RewardManager is activated at [parent], returns the reward manager config in the precompile contract state. 386 // If fee recipients are allowed, returns true in the second return value. 387 func (bc *BlockChain) GetCoinbaseAt(parent *types.Header) (common.Address, bool, error) { 388 config := bc.Config() 389 bigTime := new(big.Int).SetUint64(parent.Time) 390 391 if !config.IsSubnetEVM(bigTime) { 392 return constants.BlackholeAddr, false, nil 393 } 394 395 if !config.IsRewardManager(bigTime) { 396 if bc.chainConfig.AllowFeeRecipients { 397 return common.Address{}, true, nil 398 } else { 399 return constants.BlackholeAddr, false, nil 400 } 401 } 402 403 // try to return it from the cache 404 if cached, hit := bc.coinbaseConfigCache.Get(parent.Root); hit { 405 cachedCoinbaseConfig, ok := cached.(*cacheableCoinbaseConfig) 406 if !ok { 407 return common.Address{}, false, fmt.Errorf("expected type cachedCoinbaseConfig, got %T", cached) 408 } 409 return cachedCoinbaseConfig.coinbaseAddress, cachedCoinbaseConfig.allowFeeRecipients, nil 410 } 411 412 stateDB, err := bc.StateAt(parent.Root) 413 if err != nil { 414 return common.Address{}, false, err 415 } 416 rewardAddress, feeRecipients := precompile.GetStoredRewardAddress(stateDB) 417 418 cacheable := &cacheableCoinbaseConfig{coinbaseAddress: rewardAddress, allowFeeRecipients: feeRecipients} 419 bc.coinbaseConfigCache.Add(parent.Root, cacheable) 420 return rewardAddress, feeRecipients, nil 421 } 422 423 // GetLogs fetches all logs from a given block. 424 func (bc *BlockChain) GetLogs(hash common.Hash, number uint64) [][]*types.Log { 425 logs, ok := bc.acceptedLogsCache.Get(hash) // this cache is thread-safe 426 if ok { 427 return logs 428 } 429 return rawdb.ReadLogs(bc.db, hash, number) 430 }