internal/ethapi: return null for missing debug_getRawTransaction

Change DebugAPI.GetRawTransaction return type from hexutil.Bytes to
*hexutil.Bytes so that a not-found transaction serialises as JSON null
instead of "0x". Add TestRPCDebugGetRawTransaction with golden files.
This commit is contained in:
ManuelArto 2026-06-26 15:38:32 +02:00
parent 6d96f127a7
commit 33e1d84d16
5 changed files with 55 additions and 3 deletions

View file

@ -2100,12 +2100,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) {
func (api *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (*hexutil.Bytes, error) {
// Retrieve a finalized transaction, or a pooled otherwise
found, tx, _, _, _ := api.b.GetCanonicalTransaction(hash)
if !found {
if tx = api.b.GetPoolTransaction(hash); tx != nil {
return tx.MarshalBinary()
blob, err := tx.MarshalBinary()
if err != nil {
return nil, err
}
b := hexutil.Bytes(blob)
return &b, nil
}
// If also not in the pool there is a chance the tx indexer is still in progress.
if !api.b.TxIndexDone() {
@ -2114,7 +2119,12 @@ func (api *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (h
// Transaction is not found in the pool and the indexer is done.
return nil, nil
}
return tx.MarshalBinary()
blob, err := tx.MarshalBinary()
if err != nil {
return nil, err
}
b := hexutil.Bytes(blob)
return &b, nil
}
// PrintBlock retrieves a block and returns its pretty printed form.

View file

@ -4468,3 +4468,42 @@ func TestRPCGetRawTransactionByBlockNumberAndIndex(t *testing.T) {
testRPCResponseWithFile(t, i, result, "eth_getRawTransactionByBlockNumberAndIndex", tt.file)
}
}
func TestRPCDebugGetRawTransaction(t *testing.T) {
t.Parallel()
var (
backend, txHashes = setupReceiptBackend(t, 2)
api = NewDebugAPI(backend)
)
var testSuite = []struct {
txHash common.Hash
file string
}{
// 0. legacy transfer tx (block 0 default case)
{
txHash: txHashes[0],
file: "found-legacy",
},
// 1. zero hash, not in chain
{
txHash: common.Hash{},
file: "txhash-empty",
},
// 2. unknown hash, not in chain
{
txHash: common.HexToHash("deadbeef"),
file: "txhash-notfound",
},
}
for i, tt := range testSuite {
result, err := api.GetRawTransaction(context.Background(), tt.txHash)
if err != nil {
t.Errorf("test %d: want no error, have %v", i, err)
continue
}
testRPCResponseWithFile(t, i, result, "debug_getRawTransaction", tt.file)
}
}

View file

@ -0,0 +1 @@
"0xf8658084342770c0825208940d3ab14bbad3d99f4203bd7a11acb94882050e7e8203e8801ba0cd190747077598c3b9c5f21ea06f8487d6ab1e23358fbe0e0e0c4e64651b68f3a0467ebcb2186b332969991e2e25244959dcdb3feb7652ff6b81ce96e646d86abd"

View file

@ -0,0 +1 @@
null

View file

@ -0,0 +1 @@
null