gitlab.com/flarenetwork/coreth@v0.1.1/eth/api_backend.go (about) 1 // (c) 2019-2020, 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 2015 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 eth 28 29 import ( 30 "context" 31 "errors" 32 "math/big" 33 "time" 34 35 "github.com/ethereum/go-ethereum/common" 36 "github.com/ethereum/go-ethereum/eth/downloader" 37 "github.com/ethereum/go-ethereum/ethdb" 38 "github.com/ethereum/go-ethereum/event" 39 "gitlab.com/flarenetwork/coreth/accounts" 40 "gitlab.com/flarenetwork/coreth/consensus" 41 "gitlab.com/flarenetwork/coreth/core" 42 "gitlab.com/flarenetwork/coreth/core/bloombits" 43 "gitlab.com/flarenetwork/coreth/core/rawdb" 44 "gitlab.com/flarenetwork/coreth/core/state" 45 "gitlab.com/flarenetwork/coreth/core/types" 46 "gitlab.com/flarenetwork/coreth/core/vm" 47 "gitlab.com/flarenetwork/coreth/eth/gasprice" 48 "gitlab.com/flarenetwork/coreth/params" 49 "gitlab.com/flarenetwork/coreth/rpc" 50 ) 51 52 var ( 53 ErrUnfinalizedData = errors.New("cannot query unfinalized data") 54 errExpired = errors.New("request expired") 55 ) 56 57 // EthAPIBackend implements ethapi.Backend for full nodes 58 type EthAPIBackend struct { 59 extRPCEnabled bool 60 allowUnprotectedTxs bool 61 eth *Ethereum 62 gpo *gasprice.Oracle 63 } 64 65 // ChainConfig returns the active chain configuration. 66 func (b *EthAPIBackend) ChainConfig() *params.ChainConfig { 67 return b.eth.blockchain.Config() 68 } 69 70 func (b *EthAPIBackend) GetVMConfig() *vm.Config { 71 return b.eth.blockchain.GetVMConfig() 72 } 73 74 func (b *EthAPIBackend) CurrentBlock() *types.Block { 75 return b.eth.blockchain.CurrentBlock() 76 } 77 78 func (b *EthAPIBackend) LastAcceptedBlock() *types.Block { 79 return b.eth.LastAcceptedBlock() 80 } 81 82 func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { 83 if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 { 84 return nil, errExpired 85 } 86 // Treat requests for the pending, latest, or accepted block 87 // identically. 88 acceptedBlock := b.eth.LastAcceptedBlock() 89 if number.IsAccepted() { 90 return acceptedBlock.Header(), nil 91 } 92 93 if !b.GetVMConfig().AllowUnfinalizedQueries && acceptedBlock != nil { 94 if number.Int64() > acceptedBlock.Number().Int64() { 95 return nil, ErrUnfinalizedData 96 } 97 } 98 99 return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil 100 } 101 102 func (b *EthAPIBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { 103 if blockNr, ok := blockNrOrHash.Number(); ok { 104 return b.HeaderByNumber(ctx, blockNr) 105 } 106 if hash, ok := blockNrOrHash.Hash(); ok { 107 header := b.eth.blockchain.GetHeaderByHash(hash) 108 if header == nil { 109 return nil, errors.New("header for hash not found") 110 } 111 if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { 112 return nil, errors.New("hash is not currently canonical") 113 } 114 return header, nil 115 } 116 return nil, errors.New("invalid arguments; neither block nor hash specified") 117 } 118 119 func (b *EthAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 120 if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 { 121 return nil, errExpired 122 } 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 if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 { 128 return nil, errExpired 129 } 130 // Treat requests for the pending, latest, or accepted block 131 // identically. 132 acceptedBlock := b.eth.LastAcceptedBlock() 133 if number.IsAccepted() { 134 return acceptedBlock, nil 135 } 136 137 if !b.GetVMConfig().AllowUnfinalizedQueries && acceptedBlock != nil { 138 if number.Int64() > acceptedBlock.Number().Int64() { 139 return nil, ErrUnfinalizedData 140 } 141 } 142 143 return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil 144 } 145 146 func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 147 if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 { 148 return nil, errExpired 149 } 150 return b.eth.blockchain.GetBlockByHash(hash), nil 151 } 152 153 func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { 154 if blockNr, ok := blockNrOrHash.Number(); ok { 155 return b.BlockByNumber(ctx, blockNr) 156 } 157 if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 { 158 return nil, errExpired 159 } 160 if hash, ok := blockNrOrHash.Hash(); ok { 161 header := b.eth.blockchain.GetHeaderByHash(hash) 162 if header == nil { 163 return nil, errors.New("header for hash not found") 164 } 165 if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { 166 return nil, errors.New("hash is not currently canonical") 167 } 168 block := b.eth.blockchain.GetBlock(hash, header.Number.Uint64()) 169 if block == nil { 170 return nil, errors.New("header found, but block body is missing") 171 } 172 return block, nil 173 } 174 return nil, errors.New("invalid arguments; neither block nor hash specified") 175 } 176 177 func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { 178 // Request the block by its number and retrieve its state 179 header, err := b.HeaderByNumber(ctx, number) 180 if err != nil { 181 return nil, nil, err 182 } 183 if header == nil { 184 return nil, nil, errors.New("header not found") 185 } 186 stateDb, err := b.eth.BlockChain().StateAt(header.Root) 187 return stateDb, header, err 188 } 189 190 func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { 191 if blockNr, ok := blockNrOrHash.Number(); ok { 192 return b.StateAndHeaderByNumber(ctx, blockNr) 193 } 194 if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 { 195 return nil, nil, errExpired 196 } 197 if hash, ok := blockNrOrHash.Hash(); ok { 198 header, err := b.HeaderByHash(ctx, hash) 199 if err != nil { 200 return nil, nil, err 201 } 202 if header == nil { 203 return nil, nil, errors.New("header for hash not found") 204 } 205 if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { 206 return nil, nil, errors.New("hash is not currently canonical") 207 } 208 stateDb, err := b.eth.BlockChain().StateAt(header.Root) 209 return stateDb, header, err 210 } 211 return nil, nil, errors.New("invalid arguments; neither block nor hash specified") 212 } 213 214 func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { 215 if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 { 216 return nil, errExpired 217 } 218 return b.eth.blockchain.GetReceiptsByHash(hash), nil 219 } 220 221 func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) { 222 if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 { 223 return nil, errExpired 224 } 225 receipts := b.eth.blockchain.GetReceiptsByHash(hash) 226 if receipts == nil { 227 return nil, nil 228 } 229 logs := make([][]*types.Log, len(receipts)) 230 for i, receipt := range receipts { 231 logs[i] = receipt.Logs 232 } 233 return logs, nil 234 } 235 236 func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { 237 return b.eth.blockchain.GetTdByHash(hash) 238 } 239 240 func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { 241 vmError := func() error { return nil } 242 if vmConfig == nil { 243 vmConfig = b.eth.blockchain.GetVMConfig() 244 } 245 txContext := core.NewEVMTxContext(msg) 246 context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil) 247 return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), vmError, nil 248 } 249 250 func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { 251 return b.eth.BlockChain().SubscribeRemovedLogsEvent(ch) 252 } 253 254 func (b *EthAPIBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { 255 return b.eth.miner.SubscribePendingLogs(ch) 256 } 257 258 func (b *EthAPIBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { 259 return b.eth.BlockChain().SubscribeChainEvent(ch) 260 } 261 262 func (b *EthAPIBackend) SubscribeChainAcceptedEvent(ch chan<- core.ChainEvent) event.Subscription { 263 return b.eth.BlockChain().SubscribeChainAcceptedEvent(ch) 264 } 265 266 func (b *EthAPIBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { 267 return b.eth.BlockChain().SubscribeChainHeadEvent(ch) 268 } 269 270 func (b *EthAPIBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { 271 return b.eth.BlockChain().SubscribeChainSideEvent(ch) 272 } 273 274 func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { 275 return b.eth.BlockChain().SubscribeLogsEvent(ch) 276 } 277 278 func (b *EthAPIBackend) SubscribeAcceptedLogsEvent(ch chan<- []*types.Log) event.Subscription { 279 return b.eth.BlockChain().SubscribeAcceptedLogsEvent(ch) 280 } 281 282 func (b *EthAPIBackend) SubscribeAcceptedTransactionEvent(ch chan<- core.NewTxsEvent) event.Subscription { 283 return b.eth.BlockChain().SubscribeAcceptedTransactionEvent(ch) 284 } 285 286 func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { 287 if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 { 288 return errExpired 289 } 290 err := b.eth.txPool.AddLocal(signedTx) 291 return err 292 } 293 294 func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) { 295 pending, err := b.eth.txPool.Pending(false) 296 if err != nil { 297 return nil, err 298 } 299 var txs types.Transactions 300 for _, batch := range pending { 301 txs = append(txs, batch...) 302 } 303 return txs, nil 304 } 305 306 func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction { 307 return b.eth.txPool.Get(hash) 308 } 309 310 func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { 311 tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.eth.ChainDb(), txHash) 312 313 // Respond as if the transaction does not exist if it is not yet in an 314 // accepted block. We explicitly choose not to error here to avoid breaking 315 // expectations with clients (expect an empty response when a transaction 316 // does not exist). 317 acceptedBlock := b.eth.LastAcceptedBlock() 318 if !b.GetVMConfig().AllowUnfinalizedQueries && acceptedBlock != nil && tx != nil { 319 if blockNumber > acceptedBlock.NumberU64() { 320 return nil, common.Hash{}, 0, 0, nil 321 } 322 } 323 324 return tx, blockHash, blockNumber, index, nil 325 } 326 327 func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { 328 return b.eth.txPool.Nonce(addr), nil 329 } 330 331 func (b *EthAPIBackend) Stats() (pending int, queued int) { 332 return b.eth.txPool.Stats() 333 } 334 335 func (b *EthAPIBackend) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) { 336 return b.eth.TxPool().Content() 337 } 338 339 func (b *EthAPIBackend) TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) { 340 return b.eth.TxPool().ContentFrom(addr) 341 } 342 343 func (b *EthAPIBackend) TxPool() *core.TxPool { 344 return b.eth.TxPool() 345 } 346 347 func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { 348 return b.eth.TxPool().SubscribeNewTxsEvent(ch) 349 } 350 351 func (b *EthAPIBackend) Downloader() *downloader.Downloader { 352 return b.eth.Downloader() 353 } 354 355 func (b *EthAPIBackend) EstimateBaseFee(ctx context.Context) (*big.Int, error) { 356 return b.gpo.EstimateBaseFee(ctx) 357 } 358 359 func (b *EthAPIBackend) SuggestPrice(ctx context.Context) (*big.Int, error) { 360 return b.gpo.SuggestPrice(ctx) 361 } 362 363 func (b *EthAPIBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 364 return b.gpo.SuggestTipCap(ctx) 365 } 366 367 // TODO(aaronbuchwald) uncomment after migrating gasprice changes from v1.10.6 368 // func (b *EthAPIBackend) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) { 369 // return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles) 370 // } 371 372 func (b *EthAPIBackend) ChainDb() ethdb.Database { 373 return b.eth.ChainDb() 374 } 375 376 func (b *EthAPIBackend) EventMux() *event.TypeMux { 377 return b.eth.EventMux() 378 } 379 380 func (b *EthAPIBackend) AccountManager() *accounts.Manager { 381 return b.eth.AccountManager() 382 } 383 384 func (b *EthAPIBackend) ExtRPCEnabled() bool { 385 return b.extRPCEnabled 386 } 387 388 func (b *EthAPIBackend) UnprotectedAllowed() bool { 389 return b.allowUnprotectedTxs 390 } 391 392 func (b *EthAPIBackend) RPCGasCap() uint64 { 393 return b.eth.config.RPCGasCap 394 } 395 396 func (b *EthAPIBackend) RPCTxFeeCap() float64 { 397 return b.eth.config.RPCTxFeeCap 398 } 399 400 func (b *EthAPIBackend) BloomStatus() (uint64, uint64) { 401 sections, _, _ := b.eth.bloomIndexer.Sections() 402 return params.BloomBitsBlocks, sections 403 } 404 405 func (b *EthAPIBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { 406 for i := 0; i < bloomFilterThreads; i++ { 407 go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests) 408 } 409 } 410 411 func (b *EthAPIBackend) Engine() consensus.Engine { 412 return b.eth.engine 413 } 414 415 func (b *EthAPIBackend) CurrentHeader() *types.Header { 416 return b.eth.blockchain.CurrentHeader() 417 } 418 419 func (b *EthAPIBackend) GetMaxBlocksPerRequest() int64 { 420 return b.eth.settings.MaxBlocksPerRequest 421 } 422 423 func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool) (*state.StateDB, error) { 424 return b.eth.stateAtBlock(block, reexec, base, checkLive) 425 } 426 427 func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) { 428 return b.eth.stateAtTransaction(block, txIndex, reexec) 429 }