Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement debug_getRawTransaction #13626

Merged
merged 4 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion turbo/jsonrpc/debug_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package jsonrpc

import (
"bytes"
"context"
"errors"
"fmt"
Expand All @@ -34,6 +35,7 @@ import (
"github.com/erigontech/erigon-lib/types/accounts"
"github.com/erigontech/erigon/core/rawdb"
"github.com/erigontech/erigon/core/state"
types2 "github.com/erigontech/erigon/core/types"
"github.com/erigontech/erigon/eth/stagedsync/stages"
tracersConfig "github.com/erigontech/erigon/eth/tracers/config"
"github.com/erigontech/erigon/rpc"
Expand Down Expand Up @@ -65,6 +67,7 @@ type PrivateDebugAPI interface {
GetRawBlock(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (hexutility.Bytes, error)
GetRawReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]hexutility.Bytes, error)
GetBadBlocks(ctx context.Context) ([]map[string]interface{}, error)
GetRawTransaction(ctx context.Context, hash common.Hash) (hexutility.Bytes, error)
}

// PrivateDebugAPIImpl is implementation of the PrivateDebugAPI interface based on remote Db access
Expand Down Expand Up @@ -358,6 +361,7 @@ type AccountResult struct {
CodeHash common.Hash `json:"codeHash"`
}

// GetRawHeader implements debug_getRawHeader - returns a an RLP-encoded header, given a block number or hash
func (api *PrivateDebugAPIImpl) GetRawHeader(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (hexutility.Bytes, error) {
tx, err := api.db.BeginTemporalRo(ctx)
if err != nil {
Expand All @@ -378,6 +382,7 @@ func (api *PrivateDebugAPIImpl) GetRawHeader(ctx context.Context, blockNrOrHash
return rlp.EncodeToBytes(header)
}

// Implements debug_getRawBlock - Returns an RLP-encoded block
func (api *PrivateDebugAPIImpl) GetRawBlock(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (hexutility.Bytes, error) {
tx, err := api.db.BeginTemporalRo(ctx)
if err != nil {
Expand All @@ -398,7 +403,7 @@ func (api *PrivateDebugAPIImpl) GetRawBlock(ctx context.Context, blockNrOrHash r
return rlp.EncodeToBytes(block)
}

// GetRawReceipts retrieves the binary-encoded receipts of a single block.
// GetRawReceipts implements debug_getRawReceipts - retrieves and returns an array of EIP-2718 binary-encoded receipts of a single block
func (api *PrivateDebugAPIImpl) GetRawReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]hexutility.Bytes, error) {
tx, err := api.db.BeginTemporalRo(ctx)
if err != nil {
Expand Down Expand Up @@ -450,6 +455,7 @@ func (api *PrivateDebugAPIImpl) GetRawReceipts(ctx context.Context, blockNrOrHas
return result, nil
}

// GetBadBlocks implements debug_getBadBlocks - Returns an array of recent bad blocks that the client has seen on the network
func (api *PrivateDebugAPIImpl) GetBadBlocks(ctx context.Context) ([]map[string]interface{}, error) {
tx, err := api.db.BeginTemporalRo(ctx)
if err != nil {
Expand Down Expand Up @@ -485,3 +491,42 @@ func (api *PrivateDebugAPIImpl) GetBadBlocks(ctx context.Context) ([]map[string]

return results, nil
}

// GetRawTransaction implements debug_getRawTransaction - Returns an array of EIP-2718 binary-encoded transactions
func (api *PrivateDebugAPIImpl) GetRawTransaction(ctx context.Context, hash common.Hash) (hexutility.Bytes, error) {
tx, err := api.db.BeginTemporalRo(ctx)
if err != nil {
return nil, err
}
defer tx.Rollback()

blockNum, _, ok, err := api.txnLookup(ctx, tx, hash)
if err != nil {
return nil, err
}
if !ok {
return nil, nil
}
block, err := api.blockByNumberWithSenders(ctx, tx, blockNum)
somnathb1 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}
if block == nil {
return nil, nil
}
var txn types2.Transaction
for _, transaction := range block.Transactions() {
if transaction.Hash() == hash {
txn = transaction
break
}
}

if txn != nil {
var buf bytes.Buffer
err = txn.MarshalBinary(&buf)
return buf.Bytes(), err
}

return nil, nil
}
40 changes: 40 additions & 0 deletions turbo/jsonrpc/debug_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -595,3 +595,43 @@ func TestGetBadBlocks(t *testing.T) {
require.Equal(data[2]["hash"], hash2)
require.Equal(data[3]["hash"], hash1)
}

func TestGetRawTransaction(t *testing.T) {
m, _, _ := rpcdaemontest.CreateTestSentry(t)
api := NewPrivateDebugAPI(newBaseApiForTest(m), m.DB, 5000000)
ctx := context.Background()

require := require.New(t)
tx, err := m.DB.BeginRw(ctx)
if err != nil {
t.Errorf("could not begin read transaction: %s", err)
}
number := *rawdb.ReadCurrentBlockNumber(tx)
tx.Commit()

if number < 1 {
t.Error("TestSentry doesn't have enough blocks for this test")
}
var testedOnce = false
for i := uint64(0); i < number; i++ {
tx, err := m.DB.BeginRo(ctx)
require.NoError(err)
block, err := api._blockReader.BlockByNumber(ctx, tx, i)
require.NoError(err)
tx.Rollback()
txns := block.Transactions()

for _, txn := range txns {
// Get the first txn
txnBinary := bytes.Buffer{}
err = txn.MarshalBinary(&txnBinary)
require.NoError(err)
data, err := api.GetRawTransaction(ctx, txn.Hash())
require.NoError(err)
require.NotEmpty(data)
require.Equal([]byte(data), txnBinary.Bytes())
testedOnce = true
}
}
require.True(testedOnce, "Test flow didn't touch the target flow")
}
Loading