From 1c39f8f1953fede442f42e47481c934d392468eb Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Tue, 23 Aug 2022 09:22:38 -0400 Subject: [PATCH] introduce mapping for block not found errors Instead of returning empty block info for an unknown/unvalidated block, some evm blockchains will return an error. Now, the ethereum connector can keep track of these different errors and treat them as if `blockInfo` is nil Signed-off-by: Alex Shorsher --- internal/ethereum/error_mapping.go | 6 ++++++ internal/ethereum/get_block_info.go | 9 ++++++++- internal/ethereum/get_block_info_test.go | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/internal/ethereum/error_mapping.go b/internal/ethereum/error_mapping.go index 7452c68..dc97bd1 100644 --- a/internal/ethereum/error_mapping.go +++ b/internal/ethereum/error_mapping.go @@ -28,6 +28,7 @@ const ( filterRPCMethods ethRPCMethodCategory = iota sendRPCMethods callRPCMethods + blockRPCMethods ) // mapErrorToReason provides a common place for mapping Ethereum client @@ -58,6 +59,11 @@ func mapError(methodType ethRPCMethodCategory, err error) ffcapi.ErrorReason { case strings.Contains(errString, "known transaction"): return ffcapi.ErrorKnownTransaction } + case blockRPCMethods: + // https://docs.avax.network/quickstart/integrate-exchange-with-avalanche#determining-finality + if strings.Contains(errString, "cannot query unfinalized data") { + return ffcapi.ErrorReasonNotFound + } } // Best default in FFCAPI is to provide no mapping diff --git a/internal/ethereum/get_block_info.go b/internal/ethereum/get_block_info.go index ae47773..abc146f 100644 --- a/internal/ethereum/get_block_info.go +++ b/internal/ethereum/get_block_info.go @@ -68,7 +68,14 @@ func (c *ethConnector) getBlockInfoByNumber(ctx context.Context, blockNumber int if blockInfo == nil { err := c.backend.Invoke(ctx, &blockInfo, "eth_getBlockByNumber", ethtypes.NewHexInteger64(blockNumber), false /* only the txn hashes */) - if err != nil || blockInfo == nil { + if err != nil { + if mapError(blockRPCMethods, err) == ffcapi.ErrorReasonNotFound { + log.L(ctx).Debugf("Received error signifying 'block not found': '%s'", err) + return nil, nil + } + return nil, err + } + if blockInfo == nil { return nil, err } c.addToBlockCache(blockInfo) diff --git a/internal/ethereum/get_block_info_test.go b/internal/ethereum/get_block_info_test.go index 03cf1ed..31b9a45 100644 --- a/internal/ethereum/get_block_info_test.go +++ b/internal/ethereum/get_block_info_test.go @@ -110,6 +110,22 @@ func TestGetBlockInfoByNumberOK(t *testing.T) { } +func TestGetBlockInfoByNumberBlockNotFoundError(t *testing.T) { + ctx, c, mRPC, done := newTestConnector(t) + defer done() + + mRPC.On("Invoke", mock.Anything, mock.Anything, "eth_getBlockByNumber", mock.Anything, false). + Return(fmt.Errorf("cannot query unfinalized data")) + + var req ffcapi.BlockInfoByNumberRequest + err := json.Unmarshal([]byte(sampleGetBlockInfoByNumber), &req) + assert.NoError(t, err) + res, reason, err := c.BlockInfoByNumber(ctx, &req) + assert.Regexp(t, "FF23011", err) + assert.Equal(t, ffcapi.ErrorReasonNotFound, reason) + assert.Nil(t, res) +} + func TestGetBlockInfoByNumberNotFound(t *testing.T) { ctx, c, mRPC, done := newTestConnector(t)