github.com/ethereum/go-ethereum@v1.16.1/eth/api_backend.go (about) 1 // Copyright 2015 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 eth 18 19 import ( 20 "context" 21 "errors" 22 "math/big" 23 "time" 24 25 "github.com/ethereum/go-ethereum" 26 "github.com/ethereum/go-ethereum/accounts" 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/consensus" 29 "github.com/ethereum/go-ethereum/consensus/misc/eip4844" 30 "github.com/ethereum/go-ethereum/core" 31 "github.com/ethereum/go-ethereum/core/filtermaps" 32 "github.com/ethereum/go-ethereum/core/history" 33 "github.com/ethereum/go-ethereum/core/rawdb" 34 "github.com/ethereum/go-ethereum/core/state" 35 "github.com/ethereum/go-ethereum/core/txpool" 36 "github.com/ethereum/go-ethereum/core/txpool/locals" 37 "github.com/ethereum/go-ethereum/core/types" 38 "github.com/ethereum/go-ethereum/core/vm" 39 "github.com/ethereum/go-ethereum/eth/gasprice" 40 "github.com/ethereum/go-ethereum/eth/tracers" 41 "github.com/ethereum/go-ethereum/ethdb" 42 "github.com/ethereum/go-ethereum/event" 43 "github.com/ethereum/go-ethereum/params" 44 "github.com/ethereum/go-ethereum/rpc" 45 ) 46 47 // EthAPIBackend implements ethapi.Backend and tracers.Backend for full nodes 48 type EthAPIBackend struct { 49 extRPCEnabled bool 50 allowUnprotectedTxs bool 51 eth *Ethereum 52 gpo *gasprice.Oracle 53 } 54 55 // ChainConfig returns the active chain configuration. 56 func (b *EthAPIBackend) ChainConfig() *params.ChainConfig { 57 return b.eth.blockchain.Config() 58 } 59 60 func (b *EthAPIBackend) CurrentBlock() *types.Header { 61 return b.eth.blockchain.CurrentBlock() 62 } 63 64 func (b *EthAPIBackend) SetHead(number uint64) { 65 b.eth.handler.downloader.Cancel() 66 b.eth.blockchain.SetHead(number) 67 } 68 69 func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { 70 // Pending block is only known by the miner 71 if number == rpc.PendingBlockNumber { 72 block, _, _ := b.eth.miner.Pending() 73 if block == nil { 74 return nil, errors.New("pending block is not available") 75 } 76 return block.Header(), nil 77 } 78 // Otherwise resolve and return the block 79 if number == rpc.LatestBlockNumber { 80 return b.eth.blockchain.CurrentBlock(), nil 81 } 82 if number == rpc.FinalizedBlockNumber { 83 block := b.eth.blockchain.CurrentFinalBlock() 84 if block == nil { 85 return nil, errors.New("finalized block not found") 86 } 87 return block, nil 88 } 89 if number == rpc.SafeBlockNumber { 90 block := b.eth.blockchain.CurrentSafeBlock() 91 if block == nil { 92 return nil, errors.New("safe block not found") 93 } 94 return block, nil 95 } 96 var bn uint64 97 if number == rpc.EarliestBlockNumber { 98 bn = b.HistoryPruningCutoff() 99 } else { 100 bn = uint64(number) 101 } 102 return b.eth.blockchain.GetHeaderByNumber(bn), nil 103 } 104 105 func (b *EthAPIBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { 106 if blockNr, ok := blockNrOrHash.Number(); ok { 107 return b.HeaderByNumber(ctx, blockNr) 108 } 109 if hash, ok := blockNrOrHash.Hash(); ok { 110 header := b.eth.blockchain.GetHeaderByHash(hash) 111 if header == nil { 112 return nil, errors.New("header for hash not found") 113 } 114 if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { 115 return nil, errors.New("hash is not currently canonical") 116 } 117 return header, nil 118 } 119 return nil, errors.New("invalid arguments; neither block nor hash specified") 120 } 121 122 func (b *EthAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 123 return b.eth.blockchain.GetHeaderByHash(hash), nil 124 } 125 126 func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { 127 // Pending block is only known by the miner 128 if number == rpc.PendingBlockNumber { 129 block, _, _ := b.eth.miner.Pending() 130 if block == nil { 131 return nil, errors.New("pending block is not available") 132 } 133 return block, nil 134 } 135 // Otherwise resolve and return the block 136 if number == rpc.LatestBlockNumber { 137 header := b.eth.blockchain.CurrentBlock() 138 return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil 139 } 140 if number == rpc.FinalizedBlockNumber { 141 header := b.eth.blockchain.CurrentFinalBlock() 142 if header == nil { 143 return nil, errors.New("finalized block not found") 144 } 145 return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil 146 } 147 if number == rpc.SafeBlockNumber { 148 header := b.eth.blockchain.CurrentSafeBlock() 149 if header == nil { 150 return nil, errors.New("safe block not found") 151 } 152 return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil 153 } 154 bn := uint64(number) // the resolved number 155 if number == rpc.EarliestBlockNumber { 156 bn = b.HistoryPruningCutoff() 157 } 158 block := b.eth.blockchain.GetBlockByNumber(bn) 159 if block == nil && bn < b.HistoryPruningCutoff() { 160 return nil, &history.PrunedHistoryError{} 161 } 162 return block, nil 163 } 164 165 func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 166 number := b.eth.blockchain.GetBlockNumber(hash) 167 if number == nil { 168 return nil, nil 169 } 170 block := b.eth.blockchain.GetBlock(hash, *number) 171 if block == nil && *number < b.HistoryPruningCutoff() { 172 return nil, &history.PrunedHistoryError{} 173 } 174 return block, nil 175 } 176 177 // GetBody returns body of a block. It does not resolve special block numbers. 178 func (b *EthAPIBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { 179 if number < 0 || hash == (common.Hash{}) { 180 return nil, errors.New("invalid arguments; expect hash and no special block numbers") 181 } 182 body := b.eth.blockchain.GetBody(hash) 183 if body == nil { 184 if uint64(number) < b.HistoryPruningCutoff() { 185 return nil, &history.PrunedHistoryError{} 186 } 187 return nil, errors.New("block body not found") 188 } 189 return body, nil 190 } 191 192 func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { 193 if blockNr, ok := blockNrOrHash.Number(); ok { 194 return b.BlockByNumber(ctx, blockNr) 195 } 196 if hash, ok := blockNrOrHash.Hash(); ok { 197 header := b.eth.blockchain.GetHeaderByHash(hash) 198 if header == nil { 199 // Return 'null' and no error if block is not found. 200 // This behavior is required by RPC spec. 201 return nil, nil 202 } 203 if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { 204 return nil, errors.New("hash is not currently canonical") 205 } 206 block := b.eth.blockchain.GetBlock(hash, header.Number.Uint64()) 207 if block == nil { 208 if header.Number.Uint64() < b.HistoryPruningCutoff() { 209 return nil, &history.PrunedHistoryError{} 210 } 211 return nil, errors.New("header found, but block body is missing") 212 } 213 return block, nil 214 } 215 return nil, errors.New("invalid arguments; neither block nor hash specified") 216 } 217 218 func (b *EthAPIBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) { 219 return b.eth.miner.Pending() 220 } 221 222 func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { 223 // Pending state is only known by the miner 224 if number == rpc.PendingBlockNumber { 225 block, _, state := b.eth.miner.Pending() 226 if block == nil || state == nil { 227 return nil, nil, errors.New("pending state is not available") 228 } 229 return state, block.Header(), nil 230 } 231 // Otherwise resolve the block number and return its state 232 header, err := b.HeaderByNumber(ctx, number) 233 if err != nil { 234 return nil, nil, err 235 } 236 if header == nil { 237 return nil, nil, errors.New("header not found") 238 } 239 stateDb, err := b.eth.BlockChain().StateAt(header.Root) 240 if err != nil { 241 stateDb, err = b.eth.BlockChain().HistoricState(header.Root) 242 if err != nil { 243 return nil, nil, err 244 } 245 } 246 return stateDb, header, nil 247 } 248 249 func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { 250 if blockNr, ok := blockNrOrHash.Number(); ok { 251 return b.StateAndHeaderByNumber(ctx, blockNr) 252 } 253 if hash, ok := blockNrOrHash.Hash(); ok { 254 header, err := b.HeaderByHash(ctx, hash) 255 if err != nil { 256 return nil, nil, err 257 } 258 if header == nil { 259 return nil, nil, errors.New("header for hash not found") 260 } 261 if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { 262 return nil, nil, errors.New("hash is not currently canonical") 263 } 264 stateDb, err := b.eth.BlockChain().StateAt(header.Root) 265 if err != nil { 266 stateDb, err = b.eth.BlockChain().HistoricState(header.Root) 267 if err != nil { 268 return nil, nil, err 269 } 270 } 271 return stateDb, header, nil 272 } 273 return nil, nil, errors.New("invalid arguments; neither block nor hash specified") 274 } 275 276 func (b *EthAPIBackend) HistoryPruningCutoff() uint64 { 277 bn, _ := b.eth.blockchain.HistoryPruningCutoff() 278 return bn 279 } 280 281 func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { 282 return b.eth.blockchain.GetReceiptsByHash(hash), nil 283 } 284 285 func (b *EthAPIBackend) GetCanonicalReceipt(tx *types.Transaction, blockHash common.Hash, blockNumber, blockIndex uint64) (*types.Receipt, error) { 286 return b.eth.blockchain.GetCanonicalReceipt(tx, blockHash, blockNumber, blockIndex) 287 } 288 289 func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { 290 return rawdb.ReadLogs(b.eth.chainDb, hash, number), nil 291 } 292 293 func (b *EthAPIBackend) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM { 294 if vmConfig == nil { 295 vmConfig = b.eth.blockchain.GetVMConfig() 296 } 297 var context vm.BlockContext 298 if blockCtx != nil { 299 context = *blockCtx 300 } else { 301 context = core.NewEVMBlockContext(header, b.eth.BlockChain(), nil) 302 } 303 return vm.NewEVM(context, state, b.ChainConfig(), *vmConfig) 304 } 305 306 func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { 307 return b.eth.BlockChain().SubscribeRemovedLogsEvent(ch) 308 } 309 310 func (b *EthAPIBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { 311 return b.eth.BlockChain().SubscribeChainEvent(ch) 312 } 313 314 func (b *EthAPIBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { 315 return b.eth.BlockChain().SubscribeChainHeadEvent(ch) 316 } 317 318 func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { 319 return b.eth.BlockChain().SubscribeLogsEvent(ch) 320 } 321 322 func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { 323 err := b.eth.txPool.Add([]*types.Transaction{signedTx}, false)[0] 324 325 // If the local transaction tracker is not configured, returns whatever 326 // returned from the txpool. 327 if b.eth.localTxTracker == nil { 328 return err 329 } 330 // If the transaction fails with an error indicating it is invalid, or if there is 331 // very little chance it will be accepted later (e.g., the gas price is below the 332 // configured minimum, or the sender has insufficient funds to cover the cost), 333 // propagate the error to the user. 334 if err != nil && !locals.IsTemporaryReject(err) { 335 return err 336 } 337 // No error will be returned to user if the transaction fails with a temporary 338 // error and might be accepted later (e.g., the transaction pool is full). 339 // Locally submitted transactions will be resubmitted later via the local tracker. 340 b.eth.localTxTracker.Track(signedTx) 341 return nil 342 } 343 344 func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) { 345 pending := b.eth.txPool.Pending(txpool.PendingFilter{}) 346 var txs types.Transactions 347 for _, batch := range pending { 348 for _, lazy := range batch { 349 if tx := lazy.Resolve(); tx != nil { 350 txs = append(txs, tx) 351 } 352 } 353 } 354 return txs, nil 355 } 356 357 func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction { 358 return b.eth.txPool.Get(hash) 359 } 360 361 // GetCanonicalTransaction retrieves the lookup along with the transaction itself 362 // associate with the given transaction hash. 363 // 364 // A null will be returned if the transaction is not found. The transaction is not 365 // existent from the node's perspective. This can be due to the transaction indexer 366 // not being finished. The caller must explicitly check the indexer progress. 367 // 368 // Notably, only the transaction in the canonical chain is visible. 369 func (b *EthAPIBackend) GetCanonicalTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) { 370 lookup, tx := b.eth.blockchain.GetCanonicalTransaction(txHash) 371 if lookup == nil || tx == nil { 372 return false, nil, common.Hash{}, 0, 0 373 } 374 return true, tx, lookup.BlockHash, lookup.BlockIndex, lookup.Index 375 } 376 377 // TxIndexDone returns true if the transaction indexer has finished indexing. 378 func (b *EthAPIBackend) TxIndexDone() bool { 379 return b.eth.blockchain.TxIndexDone() 380 } 381 382 func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { 383 return b.eth.txPool.PoolNonce(addr), nil 384 } 385 386 func (b *EthAPIBackend) Stats() (runnable int, blocked int) { 387 return b.eth.txPool.Stats() 388 } 389 390 func (b *EthAPIBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) { 391 return b.eth.txPool.Content() 392 } 393 394 func (b *EthAPIBackend) TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) { 395 return b.eth.txPool.ContentFrom(addr) 396 } 397 398 func (b *EthAPIBackend) TxPool() *txpool.TxPool { 399 return b.eth.txPool 400 } 401 402 func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { 403 return b.eth.txPool.SubscribeTransactions(ch, true) 404 } 405 406 func (b *EthAPIBackend) SyncProgress(ctx context.Context) ethereum.SyncProgress { 407 prog := b.eth.Downloader().Progress() 408 if txProg, err := b.eth.blockchain.TxIndexProgress(); err == nil { 409 prog.TxIndexFinishedBlocks = txProg.Indexed 410 prog.TxIndexRemainingBlocks = txProg.Remaining 411 } 412 remain, err := b.eth.blockchain.StateIndexProgress() 413 if err == nil { 414 prog.StateIndexRemaining = remain 415 } 416 return prog 417 } 418 419 func (b *EthAPIBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 420 return b.gpo.SuggestTipCap(ctx) 421 } 422 423 func (b *EthAPIBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, baseFeePerBlobGas []*big.Int, blobGasUsedRatio []float64, err error) { 424 return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles) 425 } 426 427 func (b *EthAPIBackend) BlobBaseFee(ctx context.Context) *big.Int { 428 if excess := b.CurrentHeader().ExcessBlobGas; excess != nil { 429 return eip4844.CalcBlobFee(b.ChainConfig(), b.CurrentHeader()) 430 } 431 return nil 432 } 433 434 func (b *EthAPIBackend) ChainDb() ethdb.Database { 435 return b.eth.ChainDb() 436 } 437 438 func (b *EthAPIBackend) AccountManager() *accounts.Manager { 439 return b.eth.AccountManager() 440 } 441 442 func (b *EthAPIBackend) ExtRPCEnabled() bool { 443 return b.extRPCEnabled 444 } 445 446 func (b *EthAPIBackend) UnprotectedAllowed() bool { 447 return b.allowUnprotectedTxs 448 } 449 450 func (b *EthAPIBackend) RPCGasCap() uint64 { 451 return b.eth.config.RPCGasCap 452 } 453 454 func (b *EthAPIBackend) RPCEVMTimeout() time.Duration { 455 return b.eth.config.RPCEVMTimeout 456 } 457 458 func (b *EthAPIBackend) RPCTxFeeCap() float64 { 459 return b.eth.config.RPCTxFeeCap 460 } 461 462 func (b *EthAPIBackend) CurrentView() *filtermaps.ChainView { 463 head := b.eth.blockchain.CurrentBlock() 464 if head == nil { 465 return nil 466 } 467 return filtermaps.NewChainView(b.eth.blockchain, head.Number.Uint64(), head.Hash()) 468 } 469 470 func (b *EthAPIBackend) NewMatcherBackend() filtermaps.MatcherBackend { 471 return b.eth.filterMaps.NewMatcherBackend() 472 } 473 474 func (b *EthAPIBackend) Engine() consensus.Engine { 475 return b.eth.engine 476 } 477 478 func (b *EthAPIBackend) CurrentHeader() *types.Header { 479 return b.eth.blockchain.CurrentHeader() 480 } 481 482 func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) { 483 return b.eth.stateAtBlock(ctx, block, reexec, base, readOnly, preferDisk) 484 } 485 486 func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { 487 return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) 488 }