check progress at the end

This commit is contained in:
Sina Mahmoodi 2025-05-02 11:38:13 +02:00
parent 0fab68d072
commit c134d6b40e
6 changed files with 57 additions and 47 deletions

View file

@ -275,17 +275,17 @@ func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, max
// // 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 (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction, error) {
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 {
return nil, nil, nil
return nil, nil
}
lookup := &rawdb.LegacyTxLookupEntry{
BlockHash: blockHash,
@ -296,11 +296,11 @@ 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(ctx context.Context) (bool, error) {
func (bc *BlockChain) TxIndexDone(ctx context.Context) bool {
progress, err := bc.TxIndexProgress(ctx)
if err != nil {
// No error is returned if the transaction indexing progress is unreachable
@ -310,12 +310,12 @@ func (bc *BlockChain) TxIndexDone(ctx context.Context) (bool, error) {
//
// In such scenarios, the transaction is treated as unreachable, though
// this is clearly an unintended and unexpected situation.
return true, nil
return true
}
if !progress.Done() {
return false, nil
return false
}
return true, nil
return true
}
// HasState checks if state trie is fully present in the database or not.

View file

@ -349,22 +349,21 @@ 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(ctx, txHash)
if err != nil {
return false, nil, common.Hash{}, 0, 0, err
}
// A null will be returned in 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(ctx context.Context) bool {
return b.eth.blockchain.TxIndexDone(ctx)
}
func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {

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(ctx context.Context) 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(ctx) {
return nil, ethapi.NewTxIndexingError()
}
// Only mined txes are supported
return nil, errTxNotFound
}
// It shouldn't happen in practice.

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)

View file

@ -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(ctx) {
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(ctx) {
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(ctx) {
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(ctx) {
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

@ -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(ctx context.Context) bool
GetPoolTransactions() (types.Transactions, error)
GetPoolTransaction(txHash common.Hash) *types.Transaction
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)