Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request for eth logs or events within a range doesn't return an error if they are not indexed #12709

Open
rvagg opened this issue Nov 20, 2024 · 0 comments
Assignees

Comments

@rvagg
Copy link
Member

rvagg commented Nov 20, 2024

This was flagged in the initial ChainIndexer review but I think we need to do something about it. To describe the problem, consider the following from my node which has default ChainIndexer prune settings:

$ sqlite3 ./chainindex/chainindex.db 'select min(height) from tipset_message'
4438537
$ node -pe '"0x" + (4438530-10).toString(16)'
0x43b9f8
$ curl -X POST 'http://127.0.0.1:1236/rpc/v1' -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","id":1,"method":"Filecoin.EthGetLogs","params":[{"fromBlock":"0x43b9f8","toBlock": "0x43b9f8"}]}'
{"error":{"code":1,"message":"failed to get events for filter: failed to get events for filter from chain indexer: not found in index"},"id":1,"jsonrpc":"2.0"}
$ #
$ curl -X POST 'http://127.0.0.1:1236/rpc/v1' -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","id":1,"method":"Filecoin.GetActorEventsRaw","params":[{"fromHeight":4438527,"toHeight":4438527}]}'
{"error":{"code":1,"message":"get events for filter: not found in index"},"id":1,"jsonrpc":"2.0"}
$ #
$ curl -X POST 'http://127.0.0.1:1236/rpc/v1' -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","id":1,"method":"Filecoin.EthGetLogs","params":[{"fromBlock":"0x43b9f8","toBlock": "0x43b9f9"}]}'
{"id":1,"jsonrpc":"2.0","result":[]}
$ #
$ curl -X POST 'http://127.0.0.1:1236/rpc/v1' -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","id":1,"method":"Filecoin.GetActorEventsRaw","params":[{"fromHeight":4438527,"toHeight":4438528}]}'
{"id":1,"jsonrpc":"2.0","result":null}
$ #
  1. When you request events for a specific epoch that isn't indexed, you'll get an error, this is good (also see Issue while calling Filecoin.EthGetLogs method #12555)
  2. When you request a range of epochs, it doesn't check whether it has them, you won't get an error and it'll act like there's just no events there

It's hitting the fall-through here:

lotus/chain/index/events.go

Lines 258 to 264 in 2cd6f40

// This function distinguishes between two scenarios:
// 1. Missing events: The requested tipset is not present in the Index (an error condition).
// 2. Valid case: The tipset exists but contains no events (a normal situation).
// Currently, this distinction is only made for the common use case where a user requests events for a single tipset.
// TODO: Implement this functionality for a range of tipsets. This is expensive and not a common use case so it's deferred for now.
return nil
}

The original problem was that we didn't want to check an arbitrary number of tipsets for existence.

We do this for a single tipset check (single height range or a specific tipset): SELECT EXISTS(SELECT 1 FROM tipset_message WHERE tipset_key_cid = ?), first converting the height to a tipset if that's the case. In that process we check whether it's a null round or not and if it is we return an error telling the user. However, if it's a range, then we bypass all of this.

We could do something like this for a range of heights:

SELECT (
    SELECT COUNT(DISTINCT height)
    FROM tipset_message
    WHERE height BETWEEN :from_height AND :to_height
) = (:to_height - :from_height + 1)

But that doesn't account for null epochs and we currently don't have a way of marking those in the db (I think). So I'm not sure we can make that work nicely without scanning our list of tipsets.

We can alternatively make an approximation, we have a range, so the important questions are something like:

  1. Is the end of the range not in the future
  2. Is the start of the range in the past and is it indexed

I don't have the details in my head, but there should be a quick way of determining whether we expect the end of the range to have been indexed (accounting for possible null rounds). For the start of the index, we can do similar to what we do now with the single height look-up but with one exception: if we get the NullRound error when finding the tipset key for that height, then look for the next height until we don't get a NullRound, and check for that. It's ok to have a null round within a range, we just have to pretend that there isn't one and the user just doesn't get events for that height.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 📌 Triage
Development

No branches or pull requests

2 participants