Indexing infrastructure
Every generic indexer trusts a block
the moment it sees one.
On GIWA, that's already wrong.
Flashblocks give GIWA ~200ms preconfirmations inside every ~1s block — and the transaction set behind a block hash can still change before it's final. Roardex is the indexing layer built to expect that, instead of being surprised by it.
- Balance mismatches, naive indexer
- 100/100
- Balance mismatches, Roardex
- 0/100
- Panics over the extended live run
- 0
The problem
A wrong answer that looks completely normal
The Graph, Ponder, Envio — every general-purpose indexer we looked at assumes a block is final the instant it's observed. GIWA's own docs say plainly that this doesn't hold: "even for the same block, the hash may change if the set of preconfirmed transactions changes." No generic indexing stack accounts for that.
The failure mode isn't a crash. It's a balance, a log, a fill status that's confidently wrong for exactly as long as it takes a preconfirmation to revise — with nothing in the response telling you so.
What we measured
Same feed, two indexers
| Naive indexer | Roardex | |
|---|---|---|
| Balance mismatches | 100 / 100 | 0 / 100 |
| Log query mismatches | 500 / 500 | 0 / 500 |
Naive here means the default behavior of every generic indexing tool against a feed shaped like the real Flashblocks cadence — wrong on every answer, with no indication anything is off.
The fix
One idea, applied uniformly
A Flashblocks revision is structurally a depth-1 reorg. Track exactly what each revision contributed, undo it cleanly when superseded, replay the canonical version — the same mechanism handles a 200ms preconfirmation flip and a multi-block chain reorg with an identical code path.
Revision-tagged writes
Every write is tagged with its revision and rolled back cleanly when superseded — nothing is ever overwritten blind.
Compressed bitset log index
Roaring-style address/topic indexing for
eth_getLogs-shaped queries — measured 17× less memory than a naive bitset at scale.LSM-backed durable storage
Pebble, not a B-tree — sustained high-write ingestion is exactly the workload LSM engines were built for.
Merkle Mountain Range, anchored on-chain
Sealing is gated behind
finalized, neverlatest— the MMR is append-only and can't un-see a leaf a later reorg reaches back into. Every sealed root is also posted to a small contract on GIWA Sepolia, so it's checkable independent of us.Reorg vs. catch-up classification
A genuine chain reorganization is counted separately from a pending-tier view simply not being final yet — two different events, two different signals.
Validated against the real chain
Run continuously on the live testnet
Two indexing strategies, side by side, on real testnet traffic.
- Log lines observed
- 72,800+
- Blocks sealed into the MMR
- 126
- Panics / fatal errors
- 0
- Memory vs. naive bitset
- 17× less
Found and fixed a real O(n²) growth bug mid-validation — a 500k-log indexing pass went from ~9s to ~150ms. The 17× memory gap kept widening the longer the run went, not a one-time benchmark number.
Live right now
The indexer, running
The status below comes from the actual indexer, polling GIWA Sepolia as you read this. You can hit the endpoint yourself.
- Last pending block
- —
- Last sealed block
- —
- Sealed blocks total
- —
- Current MMR root
- —
Every root above is also posted on-chain as it's sealed — MMRAnchor on Blockscout.
Limitations
Where things stand
- Reorg repair is scoped to unfinalized blocks by design — MMR-sealed data is intentionally out of scope for automatic repair. The alternative is silent corruption, which is worse.
- Public testnet RPC is genuinely rate-limited — a meaningful share of pending polls failed over our extended live run. Production needs dedicated or self-hosted node access.
- The MMR root is anchored on GIWA Sepolia itself after every seal, via a small owner-gated contract — a consumer verifying a proof doesn't have to trust our HTTP response for the root, only the chain. See the contract for the exact call.
What we're looking for
- Dedicated or self-hosted GIWA RPC access — our own measurements show the public endpoint isn't viable for sustained production use.
- Introductions to early GIWA Wallet / dApp teams who'd be real first consumers of a Flashblocks-aware log API.