← docs

Plan: our own index of every Doginal

Written by Claude on 2026-10-20 from a talk with Martin. Not started yet: waiting for Martin's go.

Goal

Every arcade knows every Doginal on the Dogecoin chain, about 8 million of them: - its id, number and content type; - where its content sits in the chain; - where it is now (which output holds it).

All of this is read from the chain by the arcades themselves.

Rules Martin set (2026-10-20)

The ring: each arcade holds part of the index, every part on exactly two (Martin 2026-10-20)

Martin: "One arcade should hold a portion of the index ... so that every portion of the index has two nodes so that we have a redundant copy of the complete index ... based on the number of blocks or inscriptions indexed divided by the number of arcades"; then "split the token index by token numbers ... each token is indexed on exactly 2 arcades in the same way that the ORDs are". Tokens placed by a hash of the tick (his choice).

Why: a full index is several GB (Dogecoin: 14M inscriptions at ~8% of its blocks; the GX10's files 6-8 GB each), and fetching one onto .25 stopped the live site on 2026-10-20.

Redesign (Martin, 2026-10-20 evening): cover first, stitch in order, audit after

This replaces "How the work is cut", "Following" and "Trust" below where they differ. Martin's words: - "each assigned a batch of blocks to scan so that no 2 nodes are scanning the same blocks"; - "get the entire index first and then check it second"; - "two nodes in agreement ... legitimate; three or four or more ... the confidence score can go up"; - "we start from the genesis block and just walk through the block chain a section at a time; if one of the computers is faster than others it can be assigned back to back chunks ... the next one who finishes its chunk would just be assigned the next chunk in line"; - "Anyone who wants to hold the full index can request it, and it will be served torrent style from the rest of its peers that hold it; there should be a UI element in the ORD panel".

1. Cover: every chunk scanned once, handed out in line

2. What a chunk scan records

3. Stitch: owners and balances, in order, from the notes

4. Audit: only after the whole index exists

5. Holding the full index: on request, served torrent-style

Built 2026-10-20 (branch claude/ord-cover-stitch)

Open (to measure or decide while building)

What is stored (per arcade, SQLite ~/.dogecoinarcade/doginals-index.sqlite)

table row about
insc id (genesis txid + index), number, genesis height, content type, content pointer (txids of the envelope pieces, or block file + offset + length on a Core arcade), size 60-80 B
at the output that holds it now (txid:vout), its offset in that output, the height it moved there 45 B
chunk chunk number, block range, status, result hash, who scanned it, signed notes small
blockhash height, block hash, hash of that block's scan result, hash after following small

The content itself is never copied. It is read from the chain when someone asks for it, and popular pieces can be cached.

How the work is cut

Finding: the chunk loop

  1. An arcade claims the next free chunk in the mesh room doginals-scan, the same "first taker wins" pattern as the shared order book. It gets a 10-minute lease.
  2. Loop: fetch one block, check it against the header chain, scan it, write that block's result, then the next block. At most 1-2 blocks are held in memory.
  3. Every 10 blocks it sends "chunk N, done to height H" to the room. This renews the lease.
  4. If the lease runs out, the chunk is free again. The next taker starts from the last height reported done, so no finished block is redone.
  5. At the end it publishes the chunk result:
  6. the new inscriptions per block;
  7. the "envelope continues in tx T" notes for Doginals that span several transactions;
  8. a hash per block plus the chunk hash, signed with the arcade's node key.
  9. An arcade that keeps dropping chunks is offered fewer of them.

Where blocks come from: - An arcade with Dogecoin Core reads its own node. That means one block at a time, raw (getblock <hash> 0), with a cap on reads per second. Two reasons for the cap: .25's disk is an HDD, and many requests at once flood dogecoind's RPC queue, as happened before with Doginal reads. - An arcade with no Core fetches raw blocks from Core arcades over the mesh. It checks each block's hash against its header chain and the transactions against the merkle root, so it trusts no one.

Doginals that span several transactions

A Doginal's content can be split over a chain of transactions, each spending the previous one's P2SH output. A chunk can end in the middle of one. The finder records "piece k of n started in tx T, continues in the spend of T:vout". The follower walk joins the pieces, since it already follows spends. The parsing code in arcade/doginals.py (trace) is the starting point. It and the new scanner must agree on the same envelopes; a test runs both on the same transactions.

Following: who holds what

Trust: how a lie or a bug gets caught

On a Core arcade that means its own scan and its own walk, or agreed plus its own walk. Until then, today's per-coin chain walk (doginals.trace) stays the answer.

Statuses an entry can have

The Wallet and the NFTs pages can show Doginals from found on, labelled. Money paths need agreed + followed.

New blocks

Once the history is done, each Core arcade: - scans every new block itself, which is cheap; - moves its own walk forward; - publishes the block's two hashes.

The mesh is then only for comparing hashes and for new arcades catching up. On a reorg, it rolls back the blocks that were replaced: the scan rows, the moves and the hashes. The 2026-09-29 reorg wipe is the warning.

A new arcade joining

  1. Download the finished index from peers, in chunks.
  2. Check the chunk hashes against what the mesh agreed on.
  3. Spot-check some blocks itself.
  4. If it has Core, run its own follow walk to confirm the current locations.
  5. Then take part in new chunks like any other arcade.

Build order

  1. Scanner, single arcade: the block loop on .25 alone, rate-limited, writing insc and blockhash. Tests on regtest blocks with known Doginals, single- and multi-transaction, checked against doginals.trace.
  2. Follower walk: the in-memory output set, ord-dogecoin moves, per-block hashes, reorg rollback. Tests: transfers, an inscription moved with its coin split, a reorg.
  3. Chunks over the mesh: the doginals-scan room, claim/lease/progress/result, signed notes, double scans, mismatch handling. Test with 3 local arcades, one killed mid-chunk.
  4. No-Core arcades: blocks over the mesh, header-chain and merkle checks.
  5. Use it:
  6. the Wallet's Doginals and the NFTs pages read the index;
  7. the money paths switch over once agreed + followed are in place;
  8. the old per-coin walk stays as the fallback until then.
  9. Joining and catching up: download the index from peers and check it.

Steps 1-2 alone already give .25 a full index; the mesh steps spread the work and add cross-checks.

Open questions for Martin

Rings A / B / C replace the slice pairs (Martin 2026-10-20, late)

Martin: "it's two complete indexes stacked on top of each other in a ring ... you only have to be assigned to the inner ring or the outer ring ... ring A or ring B ... a C level ring and added redundancy as the network goes to tens of thousands of arcades." And: a new arcade "will have a 0% sliver, and as it's allocated ... its percentage should grow on the circle"; the GX10 "holds 50% of the chain on Pepe, it should show that".

Ring upkeep rules (Martin 2026-10-20, later still)

Building the split (rings A/B) on the slim layout -- design (Claude 2026-10-21, for Martin's go-ahead)

What a holder keeps today (PEP Main, layout 2, 2.1 GB): inscriptions (rows + lookup tables ~1.1 GB), where each one is (at + its lookup ~0.64 GB), blocks/notes (~0.3 GB), names/tokens (small).

What every holder must still keep whole (cannot be split without wrong answers): - Where every inscription's FIRST koinu sits -- a new inscription is born only when no inscription already sits on the first koinu of input 0 (ord's reinscription rule); numbering every later inscription right needs that answer for every coin, so every holder keeps the set of occupied outpoints. Kept as bare 36-byte outpoints (no row ids, no heights): ~0.25 GB for PEP Main's 6.7M, instead of 0.64 GB. - The count of births (inscription numbers are global): from the shared notes, cheap. - The chain walk itself (every block's notes) -- unchanged, shared by all.

What is split around the ring (each holder keeps only its stretch, on its ring): - Inscriptions by number -- the rows (id, type, protocol, size, height) and where each one is with its offset, for numbers in the stretch. Lookups by id go to the stretch's holder on either ring (the id -> number map is the one global piece: kept whole as 32+4 bytes each, ~0.24 GB, or answered by asking around). - Tokens by a hash of the tick -- deploys, mints, balances and the transfer inscriptions of those ticks (their moves followed by the token's holder). - Names by a hash of the name -- every claim of a name, so its first valid claim is decided in one place.

Per holder, PEP Main with 5 arcades on each of two rings: ~0.5 GB kept whole + ~1.4 GB / 5 = ~0.8 GB, against 2.1 GB for the whole index. Dogecoin (14M inscriptions) roughly double.

Steps: 1. The compact whole set (occupied outpoints, id -> number) as its own tables; the walk follows only its stretch's rows. Converting an existing full index = deleting what lies outside its stretch (nothing walked again). 2. Ring membership over the mesh: each holder says its ring, stretch and how far it reaches; the ring rules from the mock-up (gap filling from both sides, a newcomer at the centre of the biggest gap, even shares once whole, seams never aligned) decide stretches; a stretch grows only by COPYING rows from the other ring's holders (pieces, checked against the chunk hashes two arcades agreed on), and lets go only once the new holder has it. 3. Lookups routed to a stretch's holders (either ring), the Look up box and every wallet/exchange read included; the chain walk (doginals.trace) stays the fallback. 4. The Ords panel's rings show stretches instead of whole copies.