This commit is contained in:
Ömer Faruk IRMAK 2025-06-20 15:27:28 +03:00
parent ca523a7da4
commit e90fa79b7e
4 changed files with 89 additions and 13 deletions

View file

@ -242,6 +242,11 @@ func (bc *BlockChain) GetReceiptByIndex(tx *types.Transaction, blockHash common.
return receipt, nil
}
// GetRawReceipt
func (bc *BlockChain) GetRawReceipt(blockHash common.Hash, blockNumber, txIndex uint64) (*types.Receipt, error) {
return rawdb.ReadRawReceipt(bc.db, blockHash, blockNumber, txIndex)
}
// GetReceiptsByHash retrieves the receipts for all transactions in a given block.
func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
if receipts, ok := bc.receiptsCache.Get(hash); ok {
@ -336,6 +341,36 @@ func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLoo
return lookup, tx
}
// GetTxIndex
func (bc *BlockChain) GetTxIndex(txHash common.Hash) *rawdb.TxIndex {
return rawdb.ReadTxIndex(bc.db, txHash)
}
// MakeDeriveReceiptContextFromIndex
func MakeDeriveReceiptContextFromIndex(txHash common.Hash, txIndex *rawdb.TxIndex) types.DeriveReceiptContext {
return types.DeriveReceiptContext{
BlockHash: txIndex.BlockHash,
BlockNumber: txIndex.BlockNumber,
BlockTime: txIndex.BlockTime,
BaseFee: txIndex.BaseFee,
BlobGasPrice: txIndex.BlobGasPrice, // todo
// Receipt fields
GasUsed: txIndex.GasUsed,
LogIndex: uint(txIndex.LogIndex), // Number of logs in the block until this receipt
// Tx fields
Hash: txHash,
Nonce: txIndex.Nonce,
Index: uint(txIndex.TxIndex),
Type: txIndex.Type,
From: txIndex.Sender,
To: txIndex.To,
EffectiveGasPrice: txIndex.EffectiveGasPrice,
BlobGas: txIndex.BlobGas,
}
}
// TxIndexDone returns true if the transaction indexer has finished indexing.
func (bc *BlockChain) TxIndexDone() bool {
progress, err := bc.TxIndexProgress()

View file

@ -331,6 +331,33 @@ func ReadRawReceiptWithContext(db ethdb.Reader, blockHash common.Hash, blockNumb
return nil, RawReceiptContext{}, fmt.Errorf("receipt not found, %d, %x, %d", blockNumber, blockHash, txIndex)
}
// ReadRawReceipt
func ReadRawReceipt(db ethdb.Reader, blockHash common.Hash, blockNumber, txIndex uint64) (*types.Receipt, error) {
receiptIt, err := rlp.NewListIterator(ReadReceiptsRLP(db, blockHash, blockNumber))
if err != nil {
return nil, err
}
for i := uint64(0); i <= txIndex; i++ {
// Unexpected iteration error
if receiptIt.Err() != nil {
return nil, receiptIt.Err()
}
// Unexpected end of iteration
if !receiptIt.Next() {
return nil, fmt.Errorf("receipt not found, %d, %x, %d", blockNumber, blockHash, txIndex)
}
if i == txIndex {
var stored types.ReceiptForStorage
if err := rlp.DecodeBytes(receiptIt.Value(), &stored); err != nil {
return nil, err
}
return (*types.Receipt)(&stored), nil
}
}
return nil, fmt.Errorf("receipt not found, %d, %x, %d", blockNumber, blockHash, txIndex)
}
// ReadFilterMapExtRow retrieves a filter map row at the given mapRowIndex
// (see filtermaps.mapRowIndex for the storage index encoding).
// Note that zero length rows are not stored in the database and therefore all

View file

@ -614,7 +614,8 @@ func (api *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rp
result := make([]map[string]interface{}, len(receipts))
for i, receipt := range receipts {
result[i] = marshalReceipt(receipt, block.Hash(), block.NumberU64(), signer, txs[i], i)
sender, _ := signer.Sender(txs[i])
result[i] = marshalReceipt(receipt, &sender, txs[i].To())
}
return result, nil
@ -1373,6 +1374,18 @@ func (api *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash com
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
func (api *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
// Check the new tx index first
txIndex := api.b.GetTxIndex(hash)
if txIndex != nil {
receipt, err := api.b.GetRawReceipt(txIndex.BlockHash, txIndex.BlockNumber, uint64(txIndex.TxIndex))
if err != nil {
return nil, err
}
receipt.DeriveFields(core.MakeDeriveReceiptContextFromIndex(hash, txIndex))
return marshalReceipt(receipt, &txIndex.Sender, txIndex.To), nil
}
// Slow path where the new tx index doesn't exist
found, tx, blockHash, blockNumber, index := api.b.GetTransaction(hash)
if !found {
// Make sure indexer is done.
@ -1390,28 +1403,26 @@ func (api *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash commo
if err != nil {
return nil, err
}
// Derive the sender.
signer := types.MakeSigner(api.b.ChainConfig(), header.Number, header.Time)
return marshalReceipt(receipt, blockHash, blockNumber, signer, tx, int(index)), nil
from, _ := signer.Sender(tx)
return marshalReceipt(receipt, &from, tx.To()), nil
}
// marshalReceipt marshals a transaction receipt into a JSON object.
func marshalReceipt(receipt *types.Receipt, blockHash common.Hash, blockNumber uint64, signer types.Signer, tx *types.Transaction, txIndex int) map[string]interface{} {
from, _ := types.Sender(signer, tx)
func marshalReceipt(receipt *types.Receipt, from, to *common.Address) map[string]interface{} {
fields := map[string]interface{}{
"blockHash": blockHash,
"blockNumber": hexutil.Uint64(blockNumber),
"transactionHash": tx.Hash(),
"transactionIndex": hexutil.Uint64(txIndex),
"blockHash": receipt.BlockHash,
"blockNumber": hexutil.Uint64(receipt.BlockNumber.Uint64()),
"transactionHash": receipt.TxHash,
"transactionIndex": hexutil.Uint64(receipt.TransactionIndex),
"from": from,
"to": tx.To(),
"to": to,
"gasUsed": hexutil.Uint64(receipt.GasUsed),
"cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed),
"contractAddress": nil,
"logs": receipt.Logs,
"logsBloom": receipt.Bloom,
"type": hexutil.Uint(tx.Type()),
"type": hexutil.Uint(receipt.Type),
"effectiveGasPrice": (*hexutil.Big)(receipt.EffectiveGasPrice),
}
@ -1425,7 +1436,7 @@ func marshalReceipt(receipt *types.Receipt, blockHash common.Hash, blockNumber u
fields["logs"] = []*types.Log{}
}
if tx.Type() == types.BlobTxType {
if receipt.Type == types.BlobTxType {
fields["blobGasUsed"] = hexutil.Uint64(receipt.BlobGasUsed)
fields["blobGasPrice"] = (*hexutil.Big)(receipt.BlobGasPrice)
}

View file

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/filtermaps"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@ -68,10 +69,12 @@ type Backend interface {
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error)
Pending() (*types.Block, types.Receipts, *state.StateDB)
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
GetRawReceipt(blockHash common.Hash, blockNumber, blockIndex uint64) (*types.Receipt, error)
GetReceiptByIndex(tx *types.Transaction, blockHash common.Hash, blockNumber, blockIndex uint64) (*types.Receipt, error)
GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
GetTxIndex(txHash common.Hash) *rawdb.TxIndex
// Transaction pool API
SendTx(ctx context.Context, signedTx *types.Transaction) error