- support both stateful and stateless (per-block) indexing
- allow dividing large indexing tasks into multiple partial proofs
- use one index as the input of another; use multiple inputs (all derived from the same source chain)
- handle forks and verifier function updates
- support N-of-M multiple verifier function setups
- Block processing CPU cost overhead:
- 1.5-2% (without parallelization)
- Search & prove time for full chain history:
- cca 10ms if no results
- 1.5-3ms extra per result
- Proof size for full chain history:
- cca 70k if no results (25-30k in case of on-chain verification)
- 3-5k extra per result
eip: 8304 title: Trustless log and transaction index description: Store the root hashes of index tables in a system contract to allow efficient trustless proofs of log and transaction lookups author: Zsolt Felföldi (@zsfelfoldi) discussions-to: https://ethereum-magicians.org/t/eip-8304-trustless-log-and-transaction-index/28824 status: Draft type: Standards Track category: Core created: 2026-06-17
Author: Zsolt Felföldi (zsfelfoldi@ethereum.org)
This document is a preview of an alternative for the original EIP-7745 design, which tried to achieve three key goals:
- efficient proofs for long history search
- search structure always available up to the current head
Author: Zsolt Felföldi (zsfelfoldi@ethereum.org)
This document is a preview of a simplified and improved alternative version of EIP-7745, intended to collect feedback.
After getting lots of feedback about EIP-7745 being very complex and also experiencing this complexity myself while working on a production ready implementation, I shortly revisited an alternative approach I had earlier that I dismissed back then because I could not work out some issues in a satisfactory way (and also the filter maps design appeared a lot simpler originally). This time though, after having worked through all the difficulties of the old design, I realized how the alternative proposed here can be made not only feasible but actually a lot simpler and more performant.
This document specifies the extensions to the Ethereum Wire Protocol required to initialize the log index.
[request-id: P, referenceBlockHash: B_32, proofType: P, proofSubset: P]
A log index proof is a Merkle multiproof that fully or partially proves the contents of certain filter map rows and index entries. The proof format specified here can be used to prove the results of log queries, transaction and block hash lookups, and also to initialize the log index state. The root hash of any proof can be calculated and validated against the expected log index root regardless of its contents but the required contents (the proven subset of filter rows and index entries) depend on the use case. These use cases and their conditions for proof validity are detailed in separate documents.
The general format of a log index proof is defined as follows:
class LogIndexProof(Container):
filter_rows: FilterRows
index_entries: IndexEntries
This document gives a high level overview of the tasks related to EIP-7745 (Trustless log and transaction index). It does not go into specification details, it builds on the EIP, the Python EELS implementation and also some Geth code pieces (both production and WIP). It is intended to organize available resources, track the progress of unfinished tasks and address practical issues related to actual client implementation.
Minimal consensus implementation can be based on the EELS implementation which maintains the minimum subset of the log index tree required to add new entries and calculate the log index tree root. If the client also wants to use the log index either for local acceleration or proof ge
This document gives a general overview of the new log indexer implementation.
This structure is responsible for database access. Unlike the old implementation, this database structure only stores fully rendered maps (the last partially rendered map is simply re-rendered in memory at startup, takes a fraction of a second). It can also mark certain maps dirty, allowing the layer above it to clean up asynchronously. Similarly to the old implementation, it handles four types of database entries:
- map range: a single entry that contains information about existing map entries. If it is missing then the database is considered not initialized and everything in the filtermaps key range will be deleted before initializing.
- version: database is uninitialized if it does not match the version known by the client.