diff --git a/api/api_full.go b/api/api_full.go index 7bdbbcfc9a1..165026acf97 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -72,10 +72,12 @@ type FullNode interface { // TipSetKey TipSetKey // // Height is the epoch height at which the validation is performed. // Height uint64 - // // IndexedMessagesCount indicates the number of indexed messages for the canonical tipset at this epoch. + // // IndexedMessagesCount is the number of indexed messages for the canonical tipset at this epoch. // IndexedMessagesCount uint64 - // // IndexedEventsCount signifies the number of indexed events for the canonical tipset at this epoch. + // // IndexedEventsCount is the number of indexed events for the canonical tipset at this epoch. // IndexedEventsCount uint64 + // // IndexedEventEntriesCount is the number of indexed event entries for the canonical tipset at this epoch. + // IndexedEventEntriesCount uint64 // // Backfilled denotes whether missing data was successfully backfilled into the index during validation. // Backfilled bool // // IsNullRound indicates if the epoch corresponds to a null round and therefore does not have any indexed messages or events. diff --git a/build/openrpc/full.json b/build/openrpc/full.json index 54470f8230e..25a1fde8a02 100644 --- a/build/openrpc/full.json +++ b/build/openrpc/full.json @@ -2012,7 +2012,7 @@ { "name": "Filecoin.ChainValidateIndex", "description": "```go\nfunc (s *FullNodeStruct) ChainValidateIndex(p0 context.Context, p1 abi.ChainEpoch, p2 bool) (*types.IndexValidation, error) {\n\tif s.Internal.ChainValidateIndex == nil {\n\t\treturn nil, ErrNotSupported\n\t}\n\treturn s.Internal.ChainValidateIndex(p0, p1, p2)\n}\n```", - "summary": "IndexValidation contains detailed information about the validation status of a specific chain epoch.\ntype IndexValidation struct {\n\t// TipSetKey is the key of the canonical tipset for this epoch.\n\tTipSetKey TipSetKey\n\t// Height is the epoch height at which the validation is performed.\n\tHeight uint64\n\t// IndexedMessagesCount indicates the number of indexed messages for the canonical tipset at this epoch.\n\tIndexedMessagesCount uint64\n\t// IndexedEventsCount signifies the number of indexed events for the canonical tipset at this epoch.\n\tIndexedEventsCount uint64\n\t// Backfilled denotes whether missing data was successfully backfilled into the index during validation.\n\tBackfilled bool\n\t// IsNullRound indicates if the epoch corresponds to a null round and therefore does not have any indexed messages or events.\n\tIsNullRound bool\n}\n\nChainValidateIndex validates the integrity of the chain index at a specified epoch and also optionally backfills missing data.\n\nParameters:\n - epoch: The specific chain epoch for which to validate/backfill the index.\n - backfill: A boolean flag indicating whether to attempt backfilling of missing data if the index does not have data for the\n specified epoch.\n\nReturns:\n - *types.IndexValidation: A pointer to an IndexValidation struct containing the results of the validation/backfill.\n - error: An error object if the validation/backfill fails. The error message will contain details about the index\n corruption if the call fails because of an incosistency between indexed data and the actual chain state.\n\nNote: The API returns an error if the index does not have data for the specified epoch and backfill is set to false.\n\nThe `ChainValidateIndex` API serves multiple purposes:\n\n1. Validates the chain index at a specific epoch:\n - Ensures consistency between indexed data and actual chain state\n - Reports any errors found during validation (i.e. the indexed data does not match the actual chain state, missing data, etc.)\n\n2. Optionally backfills missing data:\n - Backfills data if the index is missing information for the specified epoch\n - Backfilling only occurs when the `backfill` parameter is set to `true`\n\n3. Detects \"holes\" in the index:\n - If `backfill` is `false` and the index lacks data for the specified epoch, the API returns an error indicating missing data\n", + "summary": "IndexValidation contains detailed information about the validation status of a specific chain epoch.\ntype IndexValidation struct {\n\t// TipSetKey is the key of the canonical tipset for this epoch.\n\tTipSetKey TipSetKey\n\t// Height is the epoch height at which the validation is performed.\n\tHeight uint64\n\t// IndexedMessagesCount is the number of indexed messages for the canonical tipset at this epoch.\n\tIndexedMessagesCount uint64\n\t// IndexedEventsCount is the number of indexed events for the canonical tipset at this epoch.\n\tIndexedEventsCount uint64\n\t// IndexedEventEntriesCount is the number of indexed event entries for the canonical tipset at this epoch.\n\tIndexedEventEntriesCount uint64\n\t// Backfilled denotes whether missing data was successfully backfilled into the index during validation.\n\tBackfilled bool\n\t// IsNullRound indicates if the epoch corresponds to a null round and therefore does not have any indexed messages or events.\n\tIsNullRound bool\n}\n\nChainValidateIndex validates the integrity of the chain index at a specified epoch and also optionally backfills missing data.\n\nParameters:\n - epoch: The specific chain epoch for which to validate/backfill the index.\n - backfill: A boolean flag indicating whether to attempt backfilling of missing data if the index does not have data for the\n specified epoch.\n\nReturns:\n - *types.IndexValidation: A pointer to an IndexValidation struct containing the results of the validation/backfill.\n - error: An error object if the validation/backfill fails. The error message will contain details about the index\n corruption if the call fails because of an incosistency between indexed data and the actual chain state.\n\nNote: The API returns an error if the index does not have data for the specified epoch and backfill is set to false.\n\nThe `ChainValidateIndex` API serves multiple purposes:\n\n1. Validates the chain index at a specific epoch:\n - Ensures consistency between indexed data and actual chain state\n - Reports any errors found during validation (i.e. the indexed data does not match the actual chain state, missing data, etc.)\n\n2. Optionally backfills missing data:\n - Backfills data if the index is missing information for the specified epoch\n - Backfilling only occurs when the `backfill` parameter is set to `true`\n\n3. Detects \"holes\" in the index:\n - If `backfill` is `false` and the index lacks data for the specified epoch, the API returns an error indicating missing data\n", "paramStructure": "by-position", "params": [ { @@ -2066,6 +2066,7 @@ "Height": 42, "IndexedMessagesCount": 42, "IndexedEventsCount": 42, + "IndexedEventEntriesCount": 42, "Backfilled": true, "IsNullRound": true } @@ -2079,6 +2080,10 @@ "title": "number", "type": "number" }, + "IndexedEventEntriesCount": { + "title": "number", + "type": "number" + }, "IndexedEventsCount": { "title": "number", "type": "number" diff --git a/chain/index/ddls.go b/chain/index/ddls.go index 90df97bdab5..2ae7ff2f4e5 100644 --- a/chain/index/ddls.go +++ b/chain/index/ddls.go @@ -52,8 +52,6 @@ var ddls = []string{ `CREATE INDEX IF NOT EXISTS idx_height ON tipset_message (height)`, `CREATE INDEX IF NOT EXISTS event_entry_event_id ON event_entry(event_id)`, - - `CREATE INDEX IF NOT EXISTS idx_tipset_key_reverted_message_id ON tipset_message (tipset_key_cid, reverted, message_id)`, } // preparedStatementMapping returns a map of fields of the preparedStatements struct to the SQL @@ -85,7 +83,7 @@ func preparedStatementMapping(ps *preparedStatements) map[**sql.Stmt]string { &ps.countTipsetsAtHeightStmt: "SELECT COUNT(CASE WHEN reverted = 1 THEN 1 END) AS reverted_count, COUNT(CASE WHEN reverted = 0 THEN 1 END) AS non_reverted_count FROM (SELECT tipset_key_cid, MAX(reverted) AS reverted FROM tipset_message WHERE height = ? GROUP BY tipset_key_cid) AS unique_tipsets", &ps.getNonRevertedTipsetMessageCountStmt: "SELECT COUNT(*) FROM tipset_message WHERE tipset_key_cid = ? AND reverted = 0 AND message_cid IS NOT NULL", &ps.getNonRevertedTipsetEventCountStmt: "SELECT COUNT(*) FROM event WHERE reverted = 0 AND message_id IN (SELECT message_id FROM tipset_message WHERE tipset_key_cid = ? AND reverted = 0)", - &ps.getNonRevertedTipsetEventEntriesCountStmt: "SELECT COUNT(ee.event_id) AS event_entry_count FROM tipset_message AS t INNER JOIN event AS ev ON t.message_id = ev.message_id INNER JOIN event_entry AS ee ON ev.event_id = ee.event_id WHERE t.tipset_key_cid = ? AND t.reverted = 0", + &ps.getNonRevertedTipsetEventEntriesCountStmt: "SELECT COUNT(ee.event_id) AS entry_count FROM event_entry ee JOIN event e ON ee.event_id = e.event_id JOIN tipset_message tm ON e.message_id = tm.message_id WHERE tm.tipset_key_cid = ? AND tm.reverted = 0", &ps.hasRevertedEventsInTipsetStmt: "SELECT EXISTS(SELECT 1 FROM event WHERE reverted = 1 AND message_id IN (SELECT message_id FROM tipset_message WHERE tipset_key_cid = ?))", } } diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 87fd167a956..4b210f1ac6a 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -1241,10 +1241,12 @@ type IndexValidation struct { TipSetKey TipSetKey // Height is the epoch height at which the validation is performed. Height uint64 - // IndexedMessagesCount indicates the number of indexed messages for the canonical tipset at this epoch. + // IndexedMessagesCount is the number of indexed messages for the canonical tipset at this epoch. IndexedMessagesCount uint64 - // IndexedEventsCount signifies the number of indexed events for the canonical tipset at this epoch. + // IndexedEventsCount is the number of indexed events for the canonical tipset at this epoch. IndexedEventsCount uint64 + // IndexedEventEntriesCount is the number of indexed event entries for the canonical tipset at this epoch. + IndexedEventEntriesCount uint64 // Backfilled denotes whether missing data was successfully backfilled into the index during validation. Backfilled bool // IsNullRound indicates if the epoch corresponds to a null round and therefore does not have any indexed messages or events. @@ -1303,6 +1305,7 @@ Response: "Height": 42, "IndexedMessagesCount": 42, "IndexedEventsCount": 42, + "IndexedEventEntriesCount": 42, "Backfilled": true, "IsNullRound": true } diff --git a/itests/eth_filter_test.go b/itests/eth_filter_test.go index 430e5ff90fd..5e18e8c0773 100644 --- a/itests/eth_filter_test.go +++ b/itests/eth_filter_test.go @@ -543,6 +543,7 @@ func TestEthGetLogsBasic(t *testing.T) { totalMessageCount := 0 totalEventCount := 0 + totalEventEntriesCount := 0 messages, err := client.ChainGetMessagesInTipset(ctx, ts.Key()) require.NoError(err) totalMessageCount = len(messages) @@ -555,6 +556,9 @@ func TestEthGetLogsBasic(t *testing.T) { events, err := client.ChainGetEvents(ctx, *receipt.Receipt.EventsRoot) require.NoError(err) totalEventCount += len(events) + for _, event := range events { + totalEventEntriesCount += len(event.Entries) + } } } t.Logf("tipset %d: %d messages, %d events", height, totalMessageCount, totalEventCount) @@ -566,6 +570,7 @@ func TestEthGetLogsBasic(t *testing.T) { require.EqualValues(height, iv.Height) require.EqualValues(totalMessageCount, iv.IndexedMessagesCount) require.EqualValues(totalEventCount, iv.IndexedEventsCount) + require.EqualValues(totalEventEntriesCount, iv.IndexedEventEntriesCount) require.False(iv.Backfilled) } }