From 7586710395e3cfe2104e4c8197475cd43aef9ba4 Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Thu, 26 Jan 2023 12:10:42 +0000 Subject: [PATCH] Fix panic in EthGetCode --- itests/eth_conformance_test.go | 209 +++++++++++++++++---------------- node/impl/full/eth.go | 6 +- 2 files changed, 113 insertions(+), 102 deletions(-) diff --git a/itests/eth_conformance_test.go b/itests/eth_conformance_test.go index 10ab1956b..344c8ef65 100644 --- a/itests/eth_conformance_test.go +++ b/itests/eth_conformance_test.go @@ -143,7 +143,7 @@ func TestEthOpenRPCConformance(t *testing.T) { variant string // suffix applied to the test name to distinguish different variants of a method call call func(*ethAPIRaw) (json.RawMessage, error) }{ - // Simple no-argument calls first + // Alphabetical order { method: "eth_accounts", @@ -159,6 +159,17 @@ func TestEthOpenRPCConformance(t *testing.T) { }, }, + { + method: "eth_call", + variant: "latest", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthCall(context.Background(), ethtypes.EthCall{ + From: &senderEthAddr, + Data: contractBin, + }, "latest") + }, + }, + { method: "eth_chainId", call: func(a *ethAPIRaw) (json.RawMessage, error) { @@ -166,6 +177,23 @@ func TestEthOpenRPCConformance(t *testing.T) { }, }, + { + method: "eth_estimateGas", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthEstimateGas(context.Background(), ethtypes.EthCall{ + From: &senderEthAddr, + Data: contractBin, + }) + }, + }, + + { + method: "eth_feeHistory", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthFeeHistory(context.Background(), ethtypes.EthUint64(2), "", nil) + }, + }, + { method: "eth_gasPrice", call: func(a *ethAPIRaw) (json.RawMessage, error) { @@ -174,30 +202,10 @@ func TestEthOpenRPCConformance(t *testing.T) { }, { - method: "eth_maxPriorityFeePerGas", + method: "eth_getBalance", + variant: "blocknumber", call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthMaxPriorityFeePerGas(context.Background()) - }, - }, - - { - method: "eth_newBlockFilter", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthNewBlockFilter(context.Background()) - }, - }, - - { - method: "eth_newPendingTransactionFilter", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthNewPendingTransactionFilter(context.Background()) - }, - }, - - { - method: "eth_getTransactionReceipt", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthGetTransactionReceipt(context.Background(), messageWithEvents) + return ethapi.EthGetBalance(context.Background(), contractEthAddr, "0x0") }, }, @@ -255,37 +263,10 @@ func TestEthOpenRPCConformance(t *testing.T) { }, { - method: "eth_getTransactionByBlockHashAndIndex", + method: "eth_getCode", + variant: "blocknumber", call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthGetTransactionByBlockHashAndIndex(context.Background(), blockHashWithMessage, ethtypes.EthUint64(0)) - }, - }, - - { - method: "eth_getTransactionByBlockNumberAndIndex", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthGetTransactionByBlockNumberAndIndex(context.Background(), blockNumberWithMessage, ethtypes.EthUint64(0)) - }, - }, - - { - method: "eth_getTransactionByHash", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthGetTransactionByHash(context.Background(), &messageWithEvents) - }, - }, - - { - method: "eth_sendRawTransaction", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthSendRawTransaction(context.Background(), rawSignedEthTx) - }, - }, - - { - method: "eth_getLogs", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthGetLogs(context.Background(), filterAllLogs) + return ethapi.EthGetCode(context.Background(), contractEthAddr, blockNumberWithMessage.Hex()) }, }, @@ -321,52 +302,9 @@ func TestEthOpenRPCConformance(t *testing.T) { }, { - method: "eth_uninstallFilter", + method: "eth_getLogs", call: func(a *ethAPIRaw) (json.RawMessage, error) { - return a.EthUninstallFilter(ctx, uninstallableFilterID) - }, - }, - - { - method: "eth_call", - variant: "latest", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthCall(context.Background(), ethtypes.EthCall{ - From: &senderEthAddr, - Data: contractBin, - }, "latest") - }, - }, - - { - method: "eth_estimateGas", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthEstimateGas(context.Background(), ethtypes.EthCall{ - From: &senderEthAddr, - Data: contractBin, - }) - }, - }, - - { - method: "eth_feeHistory", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthFeeHistory(context.Background(), ethtypes.EthUint64(2), "", nil) - }, - }, - { - method: "eth_getTransactionCount", - variant: "blocknumber", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthGetTransactionCount(context.Background(), senderEthAddr, "0x0") - }, - }, - - { - method: "eth_getCode", - variant: "blocknumber", - call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthGetCode(context.Background(), contractEthAddr, "0x0") + return ethapi.EthGetLogs(context.Background(), filterAllLogs) }, }, @@ -379,10 +317,79 @@ func TestEthOpenRPCConformance(t *testing.T) { }, { - method: "eth_getBalance", + method: "eth_getTransactionByBlockHashAndIndex", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionByBlockHashAndIndex(context.Background(), blockHashWithMessage, ethtypes.EthUint64(0)) + }, + }, + + { + method: "eth_getTransactionByBlockNumberAndIndex", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionByBlockNumberAndIndex(context.Background(), blockNumberWithMessage, ethtypes.EthUint64(0)) + }, + }, + + { + method: "eth_getTransactionByHash", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionByHash(context.Background(), &messageWithEvents) + }, + }, + + { + method: "eth_getTransactionCount", variant: "blocknumber", call: func(a *ethAPIRaw) (json.RawMessage, error) { - return ethapi.EthGetBalance(context.Background(), contractEthAddr, "0x0") + return ethapi.EthGetTransactionCount(context.Background(), senderEthAddr, blockNumberWithMessage.Hex()) + }, + }, + + { + method: "eth_getTransactionReceipt", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionReceipt(context.Background(), messageWithEvents) + }, + }, + + { + method: "eth_maxPriorityFeePerGas", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthMaxPriorityFeePerGas(context.Background()) + }, + }, + + { + method: "eth_newBlockFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthNewBlockFilter(context.Background()) + }, + }, + + { + method: "eth_newFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthNewFilter(context.Background(), filterAllLogs) + }, + }, + + { + method: "eth_newPendingTransactionFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthNewPendingTransactionFilter(context.Background()) + }, + }, + + { + method: "eth_sendRawTransaction", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthSendRawTransaction(context.Background(), rawSignedEthTx) + }, + }, + { + method: "eth_uninstallFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return a.EthUninstallFilter(ctx, uninstallableFilterID) }, }, } diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index f6ebf613c..c65a930f0 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -441,6 +441,11 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress, return nil, xerrors.Errorf("cannot parse block param: %s", blkParam) } + // StateManager.Call will panic if there is no parent + if ts.Height() == 0 { + return nil, xerrors.Errorf("block param must not specify genesis block") + } + // Try calling until we find a height with no migration. var res *api.InvocResult for { @@ -838,7 +843,6 @@ func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam s if msg.To == builtintypes.EthereumAddressManagerActorAddr { // As far as I can tell, the Eth API always returns empty on contract deployment return ethtypes.EthBytes{}, nil - } else if len(invokeResult.MsgRct.Return) > 0 { return cbg.ReadByteArray(bytes.NewReader(invokeResult.MsgRct.Return), uint64(len(invokeResult.MsgRct.Return))) }