From a8dc5b32687f92130751a2404163ff7fb7164484 Mon Sep 17 00:00:00 2001 From: Viraj Bhartiya Date: Thu, 7 Nov 2024 09:53:32 +0700 Subject: [PATCH 1/5] Refactor GetMsgInfo to handle message retrieval with head index wait --- chain/index/read.go | 7 +++- chain/index/read_test.go | 79 +++++++++++++++++++++++++++++++++------- 2 files changed, 71 insertions(+), 15 deletions(-) diff --git a/chain/index/read.go b/chain/index/read.go index d7c00bd35cf..540c86b9089 100644 --- a/chain/index/read.go +++ b/chain/index/read.go @@ -48,7 +48,12 @@ func (si *SqliteIndexer) GetMsgInfo(ctx context.Context, messageCid cid.Cid) (*M var tipsetKeyCidBytes []byte var height int64 - if err := si.queryMsgInfo(ctx, messageCid, &tipsetKeyCidBytes, &height); err != nil { + if err := si.readWithHeadIndexWait(ctx, func() error { + return si.queryMsgInfo(ctx, messageCid, &tipsetKeyCidBytes, &height) + }); err != nil { + if err == sql.ErrNoRows { + return nil, ErrNotFound + } return nil, err } diff --git a/chain/index/read_test.go b/chain/index/read_test.go index ebb6d1acf41..d952d2b0ceb 100644 --- a/chain/index/read_test.go +++ b/chain/index/read_test.go @@ -57,23 +57,74 @@ func TestGetMsgInfo(t *testing.T) { t.Logf("seed: %d", seed) rng := pseudo.New(pseudo.NewSource(seed)) s, _, _ := setupWithHeadIndexed(t, 10, rng) - msgCid := randomCid(t, rng) - msgCidBytes := msgCid.Bytes() - tsKeyCid := randomCid(t, rng) - insertTipsetMessage(t, s, tipsetMessage{ - tipsetKeyCid: tsKeyCid.Bytes(), - height: uint64(1), - reverted: false, - messageCid: msgCidBytes, - messageIndex: 1, + t.Run("message exists", func(t *testing.T) { + msgCid := randomCid(t, rng) + msgCidBytes := msgCid.Bytes() + tsKeyCid := randomCid(t, rng) + + insertTipsetMessage(t, s, tipsetMessage{ + tipsetKeyCid: tsKeyCid.Bytes(), + height: uint64(1), + reverted: false, + messageCid: msgCidBytes, + messageIndex: 1, + }) + + mi, err := s.GetMsgInfo(ctx, msgCid) + require.NoError(t, err) + require.Equal(t, msgCid, mi.Message) + require.Equal(t, tsKeyCid, mi.TipSet) + require.Equal(t, abi.ChainEpoch(1), mi.Epoch) }) - mi, err := s.GetMsgInfo(ctx, msgCid) - require.NoError(t, err) - require.Equal(t, msgCid, mi.Message) - require.Equal(t, tsKeyCid, mi.TipSet) - require.Equal(t, abi.ChainEpoch(1), mi.Epoch) + t.Run("message appears after head indexed", func(t *testing.T) { + msgCid := randomCid(t, rng) + tsKeyCid := randomCid(t, rng) + + // Create a context with timeout + ctx, cancel := context.WithTimeout(ctx, 2*time.Second) + defer cancel() + + // Start a goroutine that will insert the message after a short delay + go func() { + time.Sleep(100 * time.Millisecond) + insertTipsetMessage(t, s, tipsetMessage{ + tipsetKeyCid: tsKeyCid.Bytes(), + height: uint64(2), + reverted: false, + messageCid: msgCid.Bytes(), + messageIndex: 1, + }) + }() + + // Retry with backoff until message is found or context times out + var mi *MsgInfo + var err error + for { + mi, err = s.GetMsgInfo(ctx, msgCid) + if err == nil { + break + } + if ctx.Err() != nil { + t.Fatalf("timed out waiting for message to appear: %v", err) + } + time.Sleep(50 * time.Millisecond) + } + + require.NoError(t, err) + require.Equal(t, msgCid, mi.Message) + require.Equal(t, tsKeyCid, mi.TipSet) + require.Equal(t, abi.ChainEpoch(2), mi.Epoch) + }) + + t.Run("message not found", func(t *testing.T) { + nonExistentMsgCid := randomCid(t, rng) + mi, err := s.GetMsgInfo(ctx, nonExistentMsgCid) + require.Error(t, err) + require.True(t, errors.Is(err, ErrNotFound)) + require.Nil(t, mi) + }) } func setupWithHeadIndexed(t *testing.T, headHeight abi.ChainEpoch, rng *pseudo.Rand) (*SqliteIndexer, *types.TipSet, *dummyChainStore) { From 74f6718293519ec20a88feab5f5a32f083995ca0 Mon Sep 17 00:00:00 2001 From: Viraj Bhartiya Date: Wed, 20 Nov 2024 14:04:47 +0530 Subject: [PATCH 2/5] Refactor getMsgInfo --- chain/index/read.go | 7 +++---- chain/index/read_test.go | 40 ---------------------------------------- 2 files changed, 3 insertions(+), 44 deletions(-) diff --git a/chain/index/read.go b/chain/index/read.go index 540c86b9089..6ca820c6e4f 100644 --- a/chain/index/read.go +++ b/chain/index/read.go @@ -3,6 +3,7 @@ package index import ( "context" "database/sql" + "strings" "time" "github.com/ipfs/go-cid" @@ -48,10 +49,8 @@ func (si *SqliteIndexer) GetMsgInfo(ctx context.Context, messageCid cid.Cid) (*M var tipsetKeyCidBytes []byte var height int64 - if err := si.readWithHeadIndexWait(ctx, func() error { - return si.queryMsgInfo(ctx, messageCid, &tipsetKeyCidBytes, &height) - }); err != nil { - if err == sql.ErrNoRows { + if err := si.queryMsgInfo(ctx, messageCid, &tipsetKeyCidBytes, &height); err != nil { + if strings.Contains(err.Error(), "no rows in result set") { return nil, ErrNotFound } return nil, err diff --git a/chain/index/read_test.go b/chain/index/read_test.go index d952d2b0ceb..bb9852a1593 100644 --- a/chain/index/read_test.go +++ b/chain/index/read_test.go @@ -78,46 +78,6 @@ func TestGetMsgInfo(t *testing.T) { require.Equal(t, abi.ChainEpoch(1), mi.Epoch) }) - t.Run("message appears after head indexed", func(t *testing.T) { - msgCid := randomCid(t, rng) - tsKeyCid := randomCid(t, rng) - - // Create a context with timeout - ctx, cancel := context.WithTimeout(ctx, 2*time.Second) - defer cancel() - - // Start a goroutine that will insert the message after a short delay - go func() { - time.Sleep(100 * time.Millisecond) - insertTipsetMessage(t, s, tipsetMessage{ - tipsetKeyCid: tsKeyCid.Bytes(), - height: uint64(2), - reverted: false, - messageCid: msgCid.Bytes(), - messageIndex: 1, - }) - }() - - // Retry with backoff until message is found or context times out - var mi *MsgInfo - var err error - for { - mi, err = s.GetMsgInfo(ctx, msgCid) - if err == nil { - break - } - if ctx.Err() != nil { - t.Fatalf("timed out waiting for message to appear: %v", err) - } - time.Sleep(50 * time.Millisecond) - } - - require.NoError(t, err) - require.Equal(t, msgCid, mi.Message) - require.Equal(t, tsKeyCid, mi.TipSet) - require.Equal(t, abi.ChainEpoch(2), mi.Epoch) - }) - t.Run("message not found", func(t *testing.T) { nonExistentMsgCid := randomCid(t, rng) mi, err := s.GetMsgInfo(ctx, nonExistentMsgCid) From 8c77444df484d359b1c6c4d2dcd391f39e3b6594 Mon Sep 17 00:00:00 2001 From: Viraj Bhartiya Date: Thu, 21 Nov 2024 00:07:40 +0530 Subject: [PATCH 3/5] Refactor getMsgInfo and testcase --- chain/index/read.go | 3 +-- chain/index/read_test.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/chain/index/read.go b/chain/index/read.go index 6ca820c6e4f..b075429fde7 100644 --- a/chain/index/read.go +++ b/chain/index/read.go @@ -3,7 +3,6 @@ package index import ( "context" "database/sql" - "strings" "time" "github.com/ipfs/go-cid" @@ -50,7 +49,7 @@ func (si *SqliteIndexer) GetMsgInfo(ctx context.Context, messageCid cid.Cid) (*M var height int64 if err := si.queryMsgInfo(ctx, messageCid, &tipsetKeyCidBytes, &height); err != nil { - if strings.Contains(err.Error(), "no rows in result set") { + if err == sql.ErrNoRows { return nil, ErrNotFound } return nil, err diff --git a/chain/index/read_test.go b/chain/index/read_test.go index bb9852a1593..4f8b4699c07 100644 --- a/chain/index/read_test.go +++ b/chain/index/read_test.go @@ -82,7 +82,7 @@ func TestGetMsgInfo(t *testing.T) { nonExistentMsgCid := randomCid(t, rng) mi, err := s.GetMsgInfo(ctx, nonExistentMsgCid) require.Error(t, err) - require.True(t, errors.Is(err, ErrNotFound)) + require.ErrorIs(t, err, ErrNotFound) require.Nil(t, mi) }) } From b546c2f66b911451f310c9f6c12a42709f21abfd Mon Sep 17 00:00:00 2001 From: Viraj Bhartiya Date: Thu, 21 Nov 2024 00:24:54 +0530 Subject: [PATCH 4/5] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56421ef500c..ac7cf11a716 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Implement `EthGetTransactionByBlockNumberAndIndex` (`eth_getTransactionByBlockNumberAndIndex`) and `EthGetTransactionByBlockHashAndIndex` (`eth_getTransactionByBlockHashAndIndex`) methods. ([filecoin-project/lotus#12618](https://github.com/filecoin-project/lotus/pull/12618)) ## Bug Fixes +- GetMsgInfo returns an ErrNotFound when there are no rows ([filecoin-project/lotus#12680](https://github.com/filecoin-project/lotus/pull/12680)) - Fix a bug in the `lotus-shed indexes backfill-events` command that may result in either duplicate events being backfilled where there are existing events (such an operation *should* be idempotent) or events erroneously having duplicate `logIndex` values when queried via ETH APIs. ([filecoin-project/lotus#12567](https://github.com/filecoin-project/lotus/pull/12567)) - Event APIs (Eth events and actor events) should only return reverted events if client queries by specific block hash / tipset. Eth and actor event subscription APIs should always return reverted events to enable accurate observation of real-time changes. ([filecoin-project/lotus#12585](https://github.com/filecoin-project/lotus/pull/12585)) - Add logic to check if the miner's owner address is delegated (f4 address). If it is delegated, the `lotus-shed sectors termination-estimate` command now sends the termination state call using the worker ID. This fix resolves the issue where termination-estimate did not function correctly for miners with delegated owner addresses. ([filecoin-project/lotus#12569](https://github.com/filecoin-project/lotus/pull/12569)) From 6d96074f9f0fd9303fe2d55ad4f922439c317744 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Thu, 21 Nov 2024 14:54:05 +1100 Subject: [PATCH 5/5] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 645608c6034..6ec67431064 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - Make `EthTraceFilter` / `trace_filter` skip null rounds instead of erroring. ([filecoin-project/lotus#12702](https://github.com/filecoin-project/lotus/pull/12702)) - Event APIs (`GetActorEventsRaw`, `SubscribeActorEventsRaw`, `eth_getLogs`, `eth_newFilter`, etc.) will now return an error when a request matches more than `MaxFilterResults` (default: 10,000) rather than silently truncating the results. Also apply an internal event matcher for `eth_getLogs` (etc.) to avoid builtin actor events on database query so as not to include them in `MaxFilterResults` calculation. ([filecoin-project/lotus#12671](https://github.com/filecoin-project/lotus/pull/12671)) -- GetMsgInfo returns an ErrNotFound when there are no rows ([filecoin-project/lotus#12680](https://github.com/filecoin-project/lotus/pull/12680)) +- `ChainIndexer#GetMsgInfo` returns an `ErrNotFound` when there are no rows. ([filecoin-project/lotus#12680](https://github.com/filecoin-project/lotus/pull/12680)) ## New Features