api_backend.go 12.7 KB
Newer Older
1
// Copyright 2015 The go-ethereum Authors
2
// This file is part of the go-ethereum library.
3
//
4 5
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
6 7 8
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
9
// The go-ethereum library is distributed in the hope that it will be useful,
10 11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU Lesser General Public License for more details.
13
//
14 15
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16 17 18 19

package eth

import (
20
	"context"
21
	"errors"
22
	"math/big"
23
	"time"
24

25
	"github.com/ethereum/go-ethereum"
26 27
	"github.com/ethereum/go-ethereum/accounts"
	"github.com/ethereum/go-ethereum/common"
28
	"github.com/ethereum/go-ethereum/consensus"
29
	"github.com/ethereum/go-ethereum/core"
30
	"github.com/ethereum/go-ethereum/core/bloombits"
31
	"github.com/ethereum/go-ethereum/core/rawdb"
32 33 34 35
	"github.com/ethereum/go-ethereum/core/state"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/core/vm"
	"github.com/ethereum/go-ethereum/eth/gasprice"
36
	"github.com/ethereum/go-ethereum/eth/tracers"
37 38
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/event"
39
	"github.com/ethereum/go-ethereum/miner"
40
	"github.com/ethereum/go-ethereum/params"
41
	"github.com/ethereum/go-ethereum/rpc"
42 43
)

44 45
// EthAPIBackend implements ethapi.Backend for full nodes
type EthAPIBackend struct {
46 47 48 49
	extRPCEnabled       bool
	allowUnprotectedTxs bool
	eth                 *Ethereum
	gpo                 *gasprice.Oracle
50 51
}

52
// ChainConfig returns the active chain configuration.
53
func (b *EthAPIBackend) ChainConfig() *params.ChainConfig {
54
	return b.eth.blockchain.Config()
55 56
}

57
func (b *EthAPIBackend) CurrentBlock() *types.Block {
58 59 60
	return b.eth.blockchain.CurrentBlock()
}

61
func (b *EthAPIBackend) SetHead(number uint64) {
62
	b.eth.handler.downloader.Cancel()
63 64 65
	b.eth.blockchain.SetHead(number)
}

66
func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
67
	// Pending block is only known by the miner
68
	if number == rpc.PendingBlockNumber {
69
		block := b.eth.miner.PendingBlock()
70
		return block.Header(), nil
71 72
	}
	// Otherwise resolve and return the block
73
	if number == rpc.LatestBlockNumber {
74
		return b.eth.blockchain.CurrentBlock().Header(), nil
75
	}
76
	if number == rpc.FinalizedBlockNumber {
77 78 79 80 81 82 83 84 85 86 87 88
		block := b.eth.blockchain.CurrentFinalizedBlock()
		if block != nil {
			return block.Header(), nil
		}
		return nil, errors.New("finalized block not found")
	}
	if number == rpc.SafeBlockNumber {
		block := b.eth.blockchain.CurrentSafeBlock()
		if block != nil {
			return block.Header(), nil
		}
		return nil, errors.New("safe block not found")
89
	}
90
	return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil
91 92
}

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
func (b *EthAPIBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) {
	if blockNr, ok := blockNrOrHash.Number(); ok {
		return b.HeaderByNumber(ctx, blockNr)
	}
	if hash, ok := blockNrOrHash.Hash(); ok {
		header := b.eth.blockchain.GetHeaderByHash(hash)
		if header == nil {
			return nil, errors.New("header for hash not found")
		}
		if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
			return nil, errors.New("hash is not currently canonical")
		}
		return header, nil
	}
	return nil, errors.New("invalid arguments; neither block nor hash specified")
}

110 111 112 113
func (b *EthAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
	return b.eth.blockchain.GetHeaderByHash(hash), nil
}

114
func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
115
	// Pending block is only known by the miner
116
	if number == rpc.PendingBlockNumber {
117
		block := b.eth.miner.PendingBlock()
118 119 120
		return block, nil
	}
	// Otherwise resolve and return the block
121
	if number == rpc.LatestBlockNumber {
122 123
		return b.eth.blockchain.CurrentBlock(), nil
	}
124 125 126
	if number == rpc.FinalizedBlockNumber {
		return b.eth.blockchain.CurrentFinalizedBlock(), nil
	}
127 128 129
	if number == rpc.SafeBlockNumber {
		return b.eth.blockchain.CurrentSafeBlock(), nil
	}
130
	return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil
131 132
}

133 134 135 136
func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
	return b.eth.blockchain.GetBlockByHash(hash), nil
}

137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
	if blockNr, ok := blockNrOrHash.Number(); ok {
		return b.BlockByNumber(ctx, blockNr)
	}
	if hash, ok := blockNrOrHash.Hash(); ok {
		header := b.eth.blockchain.GetHeaderByHash(hash)
		if header == nil {
			return nil, errors.New("header for hash not found")
		}
		if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
			return nil, errors.New("hash is not currently canonical")
		}
		block := b.eth.blockchain.GetBlock(hash, header.Number.Uint64())
		if block == nil {
			return nil, errors.New("header found, but block body is missing")
		}
		return block, nil
	}
	return nil, errors.New("invalid arguments; neither block nor hash specified")
}

158 159 160 161
func (b *EthAPIBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
	return b.eth.miner.PendingBlockAndReceipts()
}

162
func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
163
	// Pending state is only known by the miner
164
	if number == rpc.PendingBlockNumber {
165
		block, state := b.eth.miner.Pending()
166
		return state, block.Header(), nil
167 168
	}
	// Otherwise resolve the block number and return its state
169
	header, err := b.HeaderByNumber(ctx, number)
170
	if err != nil {
171
		return nil, nil, err
172
	}
173 174 175
	if header == nil {
		return nil, nil, errors.New("header not found")
	}
176
	stateDb, err := b.eth.BlockChain().StateAt(header.Root)
177
	return stateDb, header, err
178 179
}

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
	if blockNr, ok := blockNrOrHash.Number(); ok {
		return b.StateAndHeaderByNumber(ctx, blockNr)
	}
	if hash, ok := blockNrOrHash.Hash(); ok {
		header, err := b.HeaderByHash(ctx, hash)
		if err != nil {
			return nil, nil, err
		}
		if header == nil {
			return nil, nil, errors.New("header for hash not found")
		}
		if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
			return nil, nil, errors.New("hash is not currently canonical")
		}
		stateDb, err := b.eth.BlockChain().StateAt(header.Root)
		return stateDb, header, err
	}
	return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
}

201
func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
202
	return b.eth.blockchain.GetReceiptsByHash(hash), nil
203 204
}

205 206
func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
	return rawdb.ReadLogs(b.eth.chainDb, hash, number, b.ChainConfig()), nil
207 208
}

209
func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
210 211 212 213
	if header := b.eth.blockchain.GetHeaderByHash(hash); header != nil {
		return b.eth.blockchain.GetTd(hash, header.Number.Uint64())
	}
	return nil
214 215
}

216
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) {
217
	vmError := func() error { return nil }
218 219 220
	if vmConfig == nil {
		vmConfig = b.eth.blockchain.GetVMConfig()
	}
221 222
	txContext := core.NewEVMTxContext(msg)
	context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
223
	return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), vmError, nil
224 225
}

226
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
227 228 229
	return b.eth.BlockChain().SubscribeRemovedLogsEvent(ch)
}

230 231 232 233
func (b *EthAPIBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription {
	return b.eth.miner.SubscribePendingLogs(ch)
}

234
func (b *EthAPIBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
235 236 237
	return b.eth.BlockChain().SubscribeChainEvent(ch)
}

238
func (b *EthAPIBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
239 240 241
	return b.eth.BlockChain().SubscribeChainHeadEvent(ch)
}

242
func (b *EthAPIBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
243 244 245
	return b.eth.BlockChain().SubscribeChainSideEvent(ch)
}

246
func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
247 248 249
	return b.eth.BlockChain().SubscribeLogsEvent(ch)
}

250
func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
251
	return b.eth.txPool.AddLocal(signedTx)
252 253
}

254
func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
255
	pending := b.eth.txPool.Pending(false)
256
	var txs types.Transactions
257
	for _, batch := range pending {
258 259
		txs = append(txs, batch...)
	}
260
	return txs, nil
261 262
}

263
func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction {
264
	return b.eth.txPool.Get(hash)
265 266
}

267 268 269 270 271
func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
	tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.eth.ChainDb(), txHash)
	return tx, blockHash, blockNumber, index, nil
}

272
func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
273
	return b.eth.txPool.Nonce(addr), nil
274 275
}

276
func (b *EthAPIBackend) Stats() (pending int, queued int) {
277 278 279
	return b.eth.txPool.Stats()
}

280
func (b *EthAPIBackend) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
281 282 283
	return b.eth.TxPool().Content()
}

284 285 286 287
func (b *EthAPIBackend) TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) {
	return b.eth.TxPool().ContentFrom(addr)
}

288 289 290 291
func (b *EthAPIBackend) TxPool() *core.TxPool {
	return b.eth.TxPool()
}

292 293
func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
	return b.eth.TxPool().SubscribeNewTxsEvent(ch)
294 295
}

296 297
func (b *EthAPIBackend) SyncProgress() ethereum.SyncProgress {
	return b.eth.Downloader().Progress()
298 299
}

300 301
func (b *EthAPIBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
	return b.gpo.SuggestTipCap(ctx)
302 303
}

304
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) {
305 306 307
	return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles)
}

308
func (b *EthAPIBackend) ChainDb() ethdb.Database {
309 310 311
	return b.eth.ChainDb()
}

312
func (b *EthAPIBackend) EventMux() *event.TypeMux {
313 314 315
	return b.eth.EventMux()
}

316
func (b *EthAPIBackend) AccountManager() *accounts.Manager {
317 318
	return b.eth.AccountManager()
}
319

320 321 322 323
func (b *EthAPIBackend) ExtRPCEnabled() bool {
	return b.extRPCEnabled
}

324 325 326 327
func (b *EthAPIBackend) UnprotectedAllowed() bool {
	return b.allowUnprotectedTxs
}

328
func (b *EthAPIBackend) RPCGasCap() uint64 {
329 330 331
	return b.eth.config.RPCGasCap
}

332 333 334 335
func (b *EthAPIBackend) RPCEVMTimeout() time.Duration {
	return b.eth.config.RPCEVMTimeout
}

336 337 338 339
func (b *EthAPIBackend) RPCTxFeeCap() float64 {
	return b.eth.config.RPCTxFeeCap
}

340
func (b *EthAPIBackend) BloomStatus() (uint64, uint64) {
341 342
	sections, _, _ := b.eth.bloomIndexer.Sections()
	return params.BloomBitsBlocks, sections
343 344
}

345
func (b *EthAPIBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {
346 347
	for i := 0; i < bloomFilterThreads; i++ {
		go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests)
348 349
	}
}
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365

func (b *EthAPIBackend) Engine() consensus.Engine {
	return b.eth.engine
}

func (b *EthAPIBackend) CurrentHeader() *types.Header {
	return b.eth.blockchain.CurrentHeader()
}

func (b *EthAPIBackend) Miner() *miner.Miner {
	return b.eth.Miner()
}

func (b *EthAPIBackend) StartMining(threads int) error {
	return b.eth.StartMining(threads)
}
366

367 368
func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) {
	return b.eth.StateAtBlock(block, reexec, base, readOnly, preferDisk)
369 370
}

371
func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
372 373
	return b.eth.stateAtTransaction(block, txIndex, reexec)
}