From 15f24ff1896835e6ab908b0d17c1cc36b300c408 Mon Sep 17 00:00:00 2001 From: Dmitry Shulyak Date: Mon, 3 Jun 2019 18:52:02 +0300 Subject: [PATCH] ethclient: ensure tx json is not nil before accessing it (#19653) TransactionInBlock crashed if json was nil and there was an error because it tried to access fields `From` and `BlockHash` of the nil object. --- ethclient/ethclient.go | 13 +++++++------ ethclient/ethclient_test.go | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index f3163e19b..aedf2814a 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -241,12 +241,13 @@ func (ec *Client) TransactionCount(ctx context.Context, blockHash common.Hash) ( func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { var json *rpcTransaction err := ec.c.CallContext(ctx, &json, "eth_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index)) - if err == nil { - if json == nil { - return nil, ethereum.NotFound - } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { - return nil, fmt.Errorf("server returned transaction without signature") - } + if err != nil { + return nil, err + } + if json == nil { + return nil, ethereum.NotFound + } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { + return nil, fmt.Errorf("server returned transaction without signature") } if json.From != nil && json.BlockHash != nil { setSenderFromServer(json.tx, *json.From, *json.BlockHash) diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 74711bd39..2e464cd42 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -301,3 +301,21 @@ func TestBalanceAt(t *testing.T) { }) } } + +func TestTransactionInBlockInterrupted(t *testing.T) { + backend, _ := newTestBackend(t) + client, _ := backend.Attach() + defer backend.Stop() + defer client.Close() + + ec := NewClient(client) + ctx, cancel := context.WithCancel(context.Background()) + cancel() + tx, err := ec.TransactionInBlock(ctx, common.Hash{1}, 1) + if tx != nil { + t.Fatal("transaction should be nil") + } + if err == nil { + t.Fatal("error should not be nil") + } +}