From e90fa79b7e25ca098d2d247bae281d606c012cf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20IRMAK?= Date: Fri, 20 Jun 2025 15:27:28 +0300 Subject: [PATCH] wip --- core/blockchain_reader.go | 35 +++++++++++++++++++++++++++++++ core/rawdb/accessors_indexes.go | 27 ++++++++++++++++++++++++ internal/ethapi/api.go | 37 +++++++++++++++++++++------------ internal/ethapi/backend.go | 3 +++ 4 files changed, 89 insertions(+), 13 deletions(-) diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index 3ec0c85d1e..b3dbff5760 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -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() diff --git a/core/rawdb/accessors_indexes.go b/core/rawdb/accessors_indexes.go index 06ece36350..b68931e140 100644 --- a/core/rawdb/accessors_indexes.go +++ b/core/rawdb/accessors_indexes.go @@ -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 diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index ae198c8f42..bb1d87f457 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -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) } diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 1b29796118..ba4c6b6458 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -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