1
0
Fork 0
forked from forks/go-ethereum

core: reduce load on txindexer from API (#31752)

Fixes https://github.com/ethereum/go-ethereum/issues/31732.

This logic was removed in the recent refactoring in the txindexer to
handle history cutoff (#31393). It was first introduced in this PR:
https://github.com/ethereum/go-ethereum/pull/28908.

I have tested it and it works as an alternative to #31745.

This PR packs 3 changes to the flow of fetching txs from the API:

- It caches the indexer tail after each run is over to avoid hitting the
db all the time as was done originally in #28908.

- Changes `backend.GetTransaction`. It doesn't return an error anymore
when tx indexer is in progress. It shifts the responsibility to the
caller to check the progress. The reason is that in most cases we anyway
check the txpool for the tx. If it was indeed a pending tx we can avoid
the indexer progress check.

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
This commit is contained in:
Sina M 2025-05-05 04:07:55 +02:00 committed by GitHub
parent 516451dc3a
commit 615d29f7c2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 150 additions and 131 deletions

View file

@ -270,42 +270,20 @@ func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, max
// GetTransactionLookup retrieves the lookup along with the transaction
// itself associate with the given transaction hash.
//
// An error will be returned if the transaction is not found, and background
// indexing for transactions is still in progress. The transaction might be
// reachable shortly once it's indexed.
//
// A null will be returned in the transaction is not found and background
// transaction indexing is already finished. The transaction is not existent
// from the node's perspective.
func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction, error) {
// A null will be returned if the transaction is not found. This can be due to
// the transaction indexer not being finished. The caller must explicitly check
// the indexer progress.
func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction) {
bc.txLookupLock.RLock()
defer bc.txLookupLock.RUnlock()
// Short circuit if the txlookup already in the cache, retrieve otherwise
if item, exist := bc.txLookupCache.Get(hash); exist {
return item.lookup, item.transaction, nil
return item.lookup, item.transaction
}
tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash)
if tx == nil {
progress, err := bc.TxIndexProgress()
if err != nil {
// No error is returned if the transaction indexing progress is unreachable
// due to unexpected internal errors. In such cases, it is impossible to
// determine whether the transaction does not exist or has simply not been
// indexed yet without a progress marker.
//
// In such scenarios, the transaction is treated as unreachable, though
// this is clearly an unintended and unexpected situation.
return nil, nil, nil
}
// The transaction indexing is not finished yet, returning an
// error to explicitly indicate it.
if !progress.Done() {
return nil, nil, errors.New("transaction indexing still in progress")
}
// The transaction is already indexed, the transaction is either
// not existent or not in the range of index, returning null.
return nil, nil, nil
return nil, nil
}
lookup := &rawdb.LegacyTxLookupEntry{
BlockHash: blockHash,
@ -316,7 +294,23 @@ func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLoo
lookup: lookup,
transaction: tx,
})
return lookup, tx, nil
return lookup, tx
}
// TxIndexDone returns true if the transaction indexer has finished indexing.
func (bc *BlockChain) TxIndexDone() bool {
progress, err := bc.TxIndexProgress()
if err != nil {
// No error is returned if the transaction indexing progress is unreachable
// due to unexpected internal errors. In such cases, it is impossible to
// determine whether the transaction does not exist or has simply not been
// indexed yet without a progress marker.
//
// In such scenarios, the transaction is treated as unreachable, though
// this is clearly an unintended and unexpected situation.
return true
}
return progress.Done()
}
// HasState checks if state trie is fully present in the database or not.
@ -412,7 +406,7 @@ func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) {
if bc.txIndexer == nil {
return TxIndexProgress{}, errors.New("tx indexer is not enabled")
}
return bc.txIndexer.txIndexProgress()
return bc.txIndexer.txIndexProgress(), nil
}
// HistoryPruningCutoff returns the configured history pruning point.

View file

@ -17,8 +17,8 @@
package core
import (
"errors"
"fmt"
"sync/atomic"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
@ -47,26 +47,38 @@ type txIndexer struct {
// and all others shouldn't.
limit uint64
// The current head of blockchain for transaction indexing. This field
// is accessed by both the indexer and the indexing progress queries.
head atomic.Uint64
// The current tail of the indexed transactions, null indicates
// that no transactions have been indexed yet.
//
// This field is accessed by both the indexer and the indexing
// progress queries.
tail atomic.Pointer[uint64]
// cutoff denotes the block number before which the chain segment should
// be pruned and not available locally.
cutoff uint64
db ethdb.Database
progress chan chan TxIndexProgress
term chan chan struct{}
closed chan struct{}
cutoff uint64
db ethdb.Database
term chan chan struct{}
closed chan struct{}
}
// newTxIndexer initializes the transaction indexer.
func newTxIndexer(limit uint64, chain *BlockChain) *txIndexer {
cutoff, _ := chain.HistoryPruningCutoff()
indexer := &txIndexer{
limit: limit,
cutoff: cutoff,
db: chain.db,
progress: make(chan chan TxIndexProgress),
term: make(chan chan struct{}),
closed: make(chan struct{}),
limit: limit,
cutoff: cutoff,
db: chain.db,
term: make(chan chan struct{}),
closed: make(chan struct{}),
}
indexer.head.Store(indexer.resolveHead())
indexer.tail.Store(rawdb.ReadTxIndexTail(chain.db))
go indexer.loop(chain)
var msg string
@ -154,6 +166,7 @@ func (indexer *txIndexer) repair(head uint64) {
// A crash may occur between the two delete operations,
// potentially leaving dangling indexes in the database.
// However, this is considered acceptable.
indexer.tail.Store(nil)
rawdb.DeleteTxIndexTail(indexer.db)
rawdb.DeleteAllTxLookupEntries(indexer.db, nil)
log.Warn("Purge transaction indexes", "head", head, "tail", *tail)
@ -174,6 +187,7 @@ func (indexer *txIndexer) repair(head uint64) {
// Traversing the database directly within the transaction
// index namespace might be slow and expensive, but we
// have no choice.
indexer.tail.Store(nil)
rawdb.DeleteTxIndexTail(indexer.db)
rawdb.DeleteAllTxLookupEntries(indexer.db, nil)
log.Warn("Purge transaction indexes", "head", head, "cutoff", indexer.cutoff)
@ -187,6 +201,7 @@ func (indexer *txIndexer) repair(head uint64) {
// A crash may occur between the two delete operations,
// potentially leaving dangling indexes in the database.
// However, this is considered acceptable.
indexer.tail.Store(&indexer.cutoff)
rawdb.WriteTxIndexTail(indexer.db, indexer.cutoff)
rawdb.DeleteAllTxLookupEntries(indexer.db, func(txhash common.Hash, blob []byte) bool {
n := rawdb.DecodeTxLookupEntry(blob, indexer.db)
@ -216,16 +231,15 @@ func (indexer *txIndexer) loop(chain *BlockChain) {
// Listening to chain events and manipulate the transaction indexes.
var (
stop chan struct{} // Non-nil if background routine is active
done chan struct{} // Non-nil if background routine is active
head = indexer.resolveHead() // The latest announced chain head
stop chan struct{} // Non-nil if background routine is active
done chan struct{} // Non-nil if background routine is active
headCh = make(chan ChainHeadEvent)
sub = chain.SubscribeChainHeadEvent(headCh)
)
defer sub.Unsubscribe()
// Validate the transaction indexes and repair if necessary
head := indexer.head.Load()
indexer.repair(head)
// Launch the initial processing if chain is not empty (head != genesis).
@ -238,17 +252,18 @@ func (indexer *txIndexer) loop(chain *BlockChain) {
for {
select {
case h := <-headCh:
indexer.head.Store(h.Header.Number.Uint64())
if done == nil {
stop = make(chan struct{})
done = make(chan struct{})
go indexer.run(h.Header.Number.Uint64(), stop, done)
}
head = h.Header.Number.Uint64()
case <-done:
stop = nil
done = nil
case ch := <-indexer.progress:
ch <- indexer.report(head)
indexer.tail.Store(rawdb.ReadTxIndexTail(indexer.db))
case ch := <-indexer.term:
if stop != nil {
close(stop)
@ -264,7 +279,7 @@ func (indexer *txIndexer) loop(chain *BlockChain) {
}
// report returns the tx indexing progress.
func (indexer *txIndexer) report(head uint64) TxIndexProgress {
func (indexer *txIndexer) report(head uint64, tail *uint64) TxIndexProgress {
// Special case if the head is even below the cutoff,
// nothing to index.
if head < indexer.cutoff {
@ -284,7 +299,6 @@ func (indexer *txIndexer) report(head uint64) TxIndexProgress {
}
// Compute how many blocks have been indexed
var indexed uint64
tail := rawdb.ReadTxIndexTail(indexer.db)
if tail != nil {
indexed = head - *tail + 1
}
@ -300,16 +314,12 @@ func (indexer *txIndexer) report(head uint64) TxIndexProgress {
}
}
// txIndexProgress retrieves the tx indexing progress, or an error if the
// background tx indexer is already stopped.
func (indexer *txIndexer) txIndexProgress() (TxIndexProgress, error) {
ch := make(chan TxIndexProgress, 1)
select {
case indexer.progress <- ch:
return <-ch, nil
case <-indexer.closed:
return TxIndexProgress{}, errors.New("indexer is closed")
}
// txIndexProgress retrieves the transaction indexing progress. The reported
// progress may slightly lag behind the actual indexing state, as the tail is
// only updated at the end of each indexing operation. However, this delay is
// considered acceptable.
func (indexer *txIndexer) txIndexProgress() TxIndexProgress {
return indexer.report(indexer.head.Load(), indexer.tail.Load())
}
// close shutdown the indexer. Safe to be called for multiple times.

View file

@ -121,9 +121,8 @@ func TestTxIndexer(t *testing.T) {
// Index the initial blocks from ancient store
indexer := &txIndexer{
limit: 0,
db: db,
progress: make(chan chan TxIndexProgress),
limit: 0,
db: db,
}
for i, limit := range c.limits {
indexer.limit = limit
@ -241,9 +240,8 @@ func TestTxIndexerRepair(t *testing.T) {
// Index the initial blocks from ancient store
indexer := &txIndexer{
limit: c.limit,
db: db,
progress: make(chan chan TxIndexProgress),
limit: c.limit,
db: db,
}
indexer.run(chainHead, make(chan struct{}), make(chan struct{}))
@ -432,15 +430,11 @@ func TestTxIndexerReport(t *testing.T) {
// Index the initial blocks from ancient store
indexer := &txIndexer{
limit: c.limit,
cutoff: c.cutoff,
db: db,
progress: make(chan chan TxIndexProgress),
limit: c.limit,
cutoff: c.cutoff,
db: db,
}
if c.tail != nil {
rawdb.WriteTxIndexTail(db, *c.tail)
}
p := indexer.report(c.head)
p := indexer.report(c.head, c.tail)
if p.Indexed != c.expIndexed {
t.Fatalf("Unexpected indexed: %d, expected: %d", p.Indexed, c.expIndexed)
}

View file

@ -349,22 +349,20 @@ func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction
// GetTransaction retrieves the lookup along with the transaction itself associate
// with the given transaction hash.
//
// An error will be returned if the transaction is not found, and background
// indexing for transactions is still in progress. The error is used to indicate the
// scenario explicitly that the transaction might be reachable shortly.
//
// A null will be returned in the transaction is not found and background transaction
// indexing is already finished. The transaction is not existent from the perspective
// of node.
func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
lookup, tx, err := b.eth.blockchain.GetTransactionLookup(txHash)
if err != nil {
return false, nil, common.Hash{}, 0, 0, err
}
// A null will be returned if the transaction is not found. The transaction is not
// existent from the node's perspective. This can be due to the transaction indexer
// not being finished. The caller must explicitly check the indexer progress.
func (b *EthAPIBackend) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) {
lookup, tx := b.eth.blockchain.GetTransactionLookup(txHash)
if lookup == nil || tx == nil {
return false, nil, common.Hash{}, 0, 0, nil
return false, nil, common.Hash{}, 0, 0
}
return true, tx, lookup.BlockHash, lookup.BlockIndex, lookup.Index, nil
return true, tx, lookup.BlockHash, lookup.BlockIndex, lookup.Index
}
// TxIndexDone returns true if the transaction indexer has finished indexing.
func (b *EthAPIBackend) TxIndexDone() bool {
return b.eth.blockchain.TxIndexDone()
}
func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
@ -391,7 +389,7 @@ func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.S
return b.eth.txPool.SubscribeTransactions(ch, true)
}
func (b *EthAPIBackend) SyncProgress() ethereum.SyncProgress {
func (b *EthAPIBackend) SyncProgress(ctx context.Context) ethereum.SyncProgress {
prog := b.eth.Downloader().Progress()
if txProg, err := b.eth.blockchain.TxIndexProgress(); err == nil {
prog.TxIndexFinishedBlocks = txProg.Indexed

View file

@ -82,7 +82,8 @@ type Backend interface {
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64)
TxIndexDone() bool
RPCGasCap() uint64
ChainConfig() *params.ChainConfig
Engine() consensus.Engine
@ -858,12 +859,13 @@ func containsTx(block *types.Block, hash common.Hash) bool {
// TraceTransaction returns the structured logs created during the execution of EVM
// and returns them as a JSON object.
func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
found, _, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
if err != nil {
return nil, ethapi.NewTxIndexingError()
}
// Only mined txes are supported
found, _, blockHash, blockNumber, index := api.backend.GetTransaction(hash)
if !found {
// Warn in case tx indexer is not done.
if !api.backend.TxIndexDone() {
return nil, ethapi.NewTxIndexingError()
}
// Only mined txes are supported
return nil, errTxNotFound
}
// It shouldn't happen in practice.

View file

@ -116,9 +116,13 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber)
return b.chain.GetBlockByNumber(uint64(number)), nil
}
func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
func (b *testBackend) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) {
tx, hash, blockNumber, index := rawdb.ReadTransaction(b.chaindb, txHash)
return tx != nil, tx, hash, blockNumber, index, nil
return tx != nil, tx, hash, blockNumber, index
}
func (b *testBackend) TxIndexDone() bool {
return true
}
func (b *testBackend) RPCGasCap() uint64 {

View file

@ -66,7 +66,7 @@ type backend interface {
CurrentHeader() *types.Header
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
Stats() (pending int, queued int)
SyncProgress() ethereum.SyncProgress
SyncProgress(ctx context.Context) ethereum.SyncProgress
}
// fullNodeBackend encompasses the functionality necessary for a full node
@ -766,7 +766,7 @@ func (s *Service) reportStats(conn *connWrapper) error {
)
// check if backend is a full node
if fullBackend, ok := s.backend.(fullNodeBackend); ok {
sync := fullBackend.SyncProgress()
sync := fullBackend.SyncProgress(context.Background())
syncing = !sync.Done()
price, _ := fullBackend.SuggestGasTipCap(context.Background())
@ -775,7 +775,7 @@ func (s *Service) reportStats(conn *connWrapper) error {
gasprice += int(basefee.Uint64())
}
} else {
sync := s.backend.SyncProgress()
sync := s.backend.SyncProgress(context.Background())
syncing = !sync.Done()
}
// Assemble the node stats and send it to the server

View file

@ -229,7 +229,7 @@ func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, *Block)
return t.tx, t.block
}
// Try to return an already finalized transaction
found, tx, blockHash, _, index, _ := t.r.backend.GetTransaction(ctx, t.hash)
found, tx, blockHash, _, index := t.r.backend.GetTransaction(t.hash)
if found {
t.tx = tx
blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false)
@ -1530,8 +1530,8 @@ func (s *SyncState) TxIndexRemainingBlocks() hexutil.Uint64 {
// - healingBytecode: number of bytecodes pending
// - txIndexFinishedBlocks: number of blocks whose transactions are indexed
// - txIndexRemainingBlocks: number of blocks whose transactions are not indexed yet
func (r *Resolver) Syncing() (*SyncState, error) {
progress := r.backend.SyncProgress()
func (r *Resolver) Syncing(ctx context.Context) (*SyncState, error) {
progress := r.backend.SyncProgress(ctx)
// Return not syncing if the synchronisation already completed
if progress.Done() {

View file

@ -144,8 +144,8 @@ func (api *EthereumAPI) BlobBaseFee(ctx context.Context) *hexutil.Big {
// - highestBlock: block number of the highest block header this node has received from peers
// - pulledStates: number of state entries processed until now
// - knownStates: number of known state entries that still need to be pulled
func (api *EthereumAPI) Syncing() (interface{}, error) {
progress := api.b.SyncProgress()
func (api *EthereumAPI) Syncing(ctx context.Context) (interface{}, error) {
progress := api.b.SyncProgress(ctx)
// Return not syncing if the synchronisation already completed
if progress.Done() {
@ -1333,16 +1333,18 @@ func (api *TransactionAPI) GetTransactionCount(ctx context.Context, address comm
// GetTransactionByHash returns the transaction for the given hash
func (api *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
// Try to return an already finalized transaction
found, tx, blockHash, blockNumber, index, err := api.b.GetTransaction(ctx, hash)
found, tx, blockHash, blockNumber, index := api.b.GetTransaction(hash)
if !found {
// No finalized transaction, try to retrieve it from the pool
if tx := api.b.GetPoolTransaction(hash); tx != nil {
return NewRPCPendingTransaction(tx, api.b.CurrentHeader(), api.b.ChainConfig()), nil
}
if err == nil {
return nil, nil
// If also not in the pool there is a chance the tx indexer is still in progress.
if !api.b.TxIndexDone() {
return nil, NewTxIndexingError()
}
return nil, NewTxIndexingError()
// If the transaction is not found in the pool and the indexer is done, return nil
return nil, nil
}
header, err := api.b.HeaderByHash(ctx, blockHash)
if err != nil {
@ -1354,27 +1356,31 @@ func (api *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
func (api *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
// Retrieve a finalized transaction, or a pooled otherwise
found, tx, _, _, _, err := api.b.GetTransaction(ctx, hash)
found, tx, _, _, _ := api.b.GetTransaction(hash)
if !found {
if tx = api.b.GetPoolTransaction(hash); tx != nil {
return tx.MarshalBinary()
}
if err == nil {
return nil, nil
// If also not in the pool there is a chance the tx indexer is still in progress.
if !api.b.TxIndexDone() {
return nil, NewTxIndexingError()
}
return nil, NewTxIndexingError()
// If the transaction is not found in the pool and the indexer is done, return nil
return nil, nil
}
return tx.MarshalBinary()
}
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
func (api *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
found, tx, blockHash, blockNumber, index, err := api.b.GetTransaction(ctx, hash)
if err != nil {
return nil, NewTxIndexingError() // transaction is not fully indexed
}
found, tx, blockHash, blockNumber, index := api.b.GetTransaction(hash)
if !found {
return nil, nil // transaction is not existent or reachable
// Make sure indexer is done.
if !api.b.TxIndexDone() {
return nil, NewTxIndexingError()
}
// No such tx.
return nil, nil
}
header, err := api.b.HeaderByHash(ctx, blockHash)
if err != nil {
@ -1774,15 +1780,17 @@ func (api *DebugAPI) GetRawReceipts(ctx context.Context, blockNrOrHash rpc.Block
// GetRawTransaction returns the bytes of the transaction for the given hash.
func (api *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
// Retrieve a finalized transaction, or a pooled otherwise
found, tx, _, _, _, err := api.b.GetTransaction(ctx, hash)
found, tx, _, _, _ := api.b.GetTransaction(hash)
if !found {
if tx = api.b.GetPoolTransaction(hash); tx != nil {
return tx.MarshalBinary()
}
if err == nil {
return nil, nil
// If also not in the pool there is a chance the tx indexer is still in progress.
if !api.b.TxIndexDone() {
return nil, NewTxIndexingError()
}
return nil, NewTxIndexingError()
// Transaction is not found in the pool and the indexer is done.
return nil, nil
}
return tx.MarshalBinary()
}

View file

@ -472,7 +472,9 @@ func (b *testBackend) setPendingBlock(block *types.Block) {
b.pending = block
}
func (b testBackend) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} }
func (b testBackend) SyncProgress(ctx context.Context) ethereum.SyncProgress {
return ethereum.SyncProgress{}
}
func (b testBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
return big.NewInt(0), nil
}
@ -589,9 +591,12 @@ func (b testBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) even
func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
panic("implement me")
}
func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
func (b testBackend) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) {
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash)
return true, tx, blockHash, blockNumber, index, nil
return true, tx, blockHash, blockNumber, index
}
func (b testBackend) TxIndexDone() bool {
return true
}
func (b testBackend) GetPoolTransactions() (types.Transactions, error) { panic("implement me") }
func (b testBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { panic("implement me") }

View file

@ -41,7 +41,7 @@ import (
// both full and light clients) with access to necessary functions.
type Backend interface {
// General Ethereum API
SyncProgress() ethereum.SyncProgress
SyncProgress(ctx context.Context) ethereum.SyncProgress
SuggestGasTipCap(ctx context.Context) (*big.Int, error)
FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error)
@ -74,7 +74,8 @@ type Backend interface {
// Transaction pool API
SendTx(ctx context.Context, signedTx *types.Transaction) error
GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64)
TxIndexDone() bool
GetPoolTransactions() (types.Transactions, error)
GetPoolTransaction(txHash common.Hash) *types.Transaction
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)

View file

@ -323,7 +323,9 @@ func (b *backendMock) CurrentHeader() *types.Header { return b.current }
func (b *backendMock) ChainConfig() *params.ChainConfig { return b.config }
// Other methods needed to implement Backend interface.
func (b *backendMock) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} }
func (b *backendMock) SyncProgress(ctx context.Context) ethereum.SyncProgress {
return ethereum.SyncProgress{}
}
func (b *backendMock) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error) {
return nil, nil, nil, nil, nil, nil, nil
}
@ -378,9 +380,10 @@ func (b *backendMock) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) eve
return nil
}
func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
return false, nil, [32]byte{}, 0, 0, nil
func (b *backendMock) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) {
return false, nil, [32]byte{}, 0, 0
}
func (b *backendMock) TxIndexDone() bool { return true }
func (b *backendMock) GetPoolTransactions() (types.Transactions, error) { return nil, nil }
func (b *backendMock) GetPoolTransaction(txHash common.Hash) *types.Transaction { return nil }
func (b *backendMock) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {