Skip to content

getLogs improvements #876

Open
Open

Description

@sakulstra

Using eth_getLogs for indexing is very painful.

  1. there is no built in reorg handling
  2. there is no consistent error on exceeded range https://github.com/ponder-sh/ponder/blob/ba9a1b5e1262efe0dc7341de7f600ed32d52b391/packages/utils/src/getLogsRetryHelper.ts#L36 and no consistent limits accross providers
  3. there is no pagination
  4. json rpc is not very efficient
  5. when fetching up to latest, you do not know what latest was - just which was the last block that contained an event

While 3),4) and 5) probably cannot be solved within the existing spec, i guess the other two perhaps could be?

For 1) fromBlock could potentially accept a blockHash or a new fromBlockHash could be introduced.
Not entirely sure what should happen when fromBlockHash is orphaned though - opening this issue to start the discussion.

For 2) i guess it's a pure matter of standardizing the error.


I've worked a lot with rpcs and other data providers over the years and for what it's worth envio has managed to come up with a api that reliably solves these issues. Wondering if we could have a more sophisticated (envio like)api on the clients.

Activity

  1. LukaszRozmej commented on Sep 7, 2026

    @LukaszRozmej
    1. Not sure how would this work on stateless endpoint. You do have reorg support through eth_subscribe and removed flag.
    2. I think there is work around it, but that still may be somewhat true that it is under-speced.
    3. This would need new endpoint with this feature (may be worth specing)
    4. Depends what do you mean by that. If you are doing long range scans (like millions of blocks), or are you querying very dense logs (only hundreds of blocks, but very large amount of logs returned). For former both Nethermind and Geth have optional index structures. Second is just somewhat limited of just how much data you can push through JSON-RPC.
    5. This is somewhat true - not only for this endpoint. Could be speced with 3 on new endpont. But can be mitigated by the client, first query current head, then query logs based on hash (or number).
  2. sakulstra commented on Sep 7, 2026

    @sakulstra
    Author

    I mostly wanted to get the discussion started as the recent crypto projects I've been involved in eventually all pivoted away from pure rpc indexing, but to my surprise I basically did not find any issues addressing any of their problems except #617.

    I personally think it would be much better to have a new eth_getLogsV2 vs a bloated eth_getLogs. Also I doubt that pagination can be introduced within the existing eth_getLogs.

    1* A stateless endpoint could just return a NOT_CANONICAL_CHAIN error i assume? Re eth_subscribe imho is no answer to that problem: It only works for indexers that constantly consume live data. It only works with some rpcs. Often has different limitations regarding filter topics. Also it does not support fromHash or similar either, so with a broken stream you have kinda the same issue on continuity.

    4* sorry, that was unclear — i didn't mean node side scan performance. i meant json-rpc request/response is just the wrong shape for a backfill. you want to say "give me everything from here" once and have it streamed, rather than n round trips where you also have to guess n and handle provider specific errors(2).

    How i imagine an ideal api to look like(largely stolen from envio):

    Request

    {
      "fromBlockHash": "0x..", // <- for reorg safe start
      "toBlock": "latest",
      "address": ["0x.."],
      "topics": [],
      "fields": ["blockNumber", "address", "data"] // <- as in a lot of cases the client does not care about huge chunks of the data
    }

    response / stream chunk

    {
      "logs": [],
      "toBlock": "0x..", "toBlockHash": "0x..",
      "headBlock": "0x..", "headBlockHash": "0x.."
    }

    the server truncates wherever it likes, the client feeds toBlockHash back in as the next fromBlockHash until it catches up with head:

    • no range guessing and no provider specific error handling
    • an orphaned anchor is just an error
    • if implemented as a stream it's the same thing. Just that it doesn't stop, and a dropped connection resumes from the last toBlockHash.

    Probably is not as easy as that.
    I assume the cursor might need to be more complex so it can point "mid-block".
    Envio does some deduplication via block/txn fields which i personally like, just not so sure how complex the rpc native endpoint should be 🤷

    "field_selection": {
        "block": ["number", "timestamp", "hash"],
        "transaction": ["block_number", "transaction_index", "hash", "from", "to"]
     }
    
  3. bomanaps commented on Sep 9, 2026

    @bomanaps
    Contributor

    The mid-block cursor you flagged connects directly to an open question in #855 where the cursor needs a block-global log index to work correctly and right now geth, erigon, and reth all return different values for that index so that needs to be settled before the cursor design can move forward.

  4. sakulstra commented on Sep 22, 2026

    @sakulstra
    Author

    Seems like monad is doing sth on that front monad-crypto/MIPs#88

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions