Verifiable on-chain history on Portaldot

on-chain
history,
no servers.

Load any dApp’s history in seconds, straight from Portaldot. Every chunk is checked against the source chain in your browser: no indexer, no API, no trust.

// open polkadot-ah.balance-history
// in the browser, no server

▸ registry
  latest manifest from PotluckRegistry
  on Portaldot V3 (pallet-revive)▸ fetch
  chunk 0 via bitswap_v1_get
  blocks #22,021,128 – #22,071,133▸ L1 integrity
  rawHash 0xb826c80c… matches the manifest
  canonical rows, bloom checked▸ L3 reconcile
  every balance delta against System.Account
  on Polkadot Asset Hub itself

Sourcing history from

  • Polkadot Asset Hub
  • Kusama Asset Hub
  • Portaldot V3

See history verify itself

Pantry loads Polkadot Asset Hub from Portaldot in seconds, not the ~11 minutes a direct sync takes, and reconciles every account against the chain. Forge one row and it names the exact amount.

How it works

Four steps from a spec to a history every user can check for themselves.

  1. 01

    Describe

    A JSON spec names the events to index, the row each one becomes, and how rows reconcile with chain state.

    specs/*.json
  2. 02

    Build

    The publisher reads finalized blocks, decodes each with the runtime that executed it, and writes canonical NDJSON chunks.

    potluck build · potluck verify
  3. 03

    Publish

    Chunks go into Portaldot’s TransactionStorage and the manifest into the PotluckRegistry contract, in one batch.

    potluck publish
  4. 04

    Load & verify

    Any browser reads the registry, fetches chunks over bitswap, checks L1 · L2 · L3 against the source chain, then tails new blocks.

    @potluck/client · Pantry

Everything an indexer does; nothing you have to trust.

  • pantry · verify
    // an honest accountL1  digest · rawHash · bloomokL2  rows re-derived from blocks183 / 183L3  Σ rows = Δ System.Accountexact · 1.8 s // a forged chunk, re-hashed by the forgerL1  digest · rawHash · bloompassesL2  rows re-derived from blockspassesL3  accounts reconcile903 / 904 ✗    off by exactly the hidden amount

    Verifiable history

    Know it’s true

    L1 checks every chunk’s hashes, L2 re-derives an account’s rows from their blocks, and L3 reconciles every balance against the chain itself. A forged chunk is caught to the exact amount.

  • publish · portaldot-v3
    // publisher, oncetransactionStorage.store(chunk 0)2.5 MBtransactionStorage.store(chunk 1)0.65 MButility.batchAll([  transactionStorage.store(manifest),  revive.call(PotluckRegistry.publish)manifest #3]) // every browser, afterregistry 0xef93…82eb → manifest #3eth_callbitswap_v1_get(chunk 0 CID)2.5 MB · ≈ 4 s

    Portaldot data layer

    Know where it lives

    Chunks live in Portaldot’s TransactionStorage, manifests in a PotluckRegistry contract on pallet-revive, and browsers fetch them with bitswap_v1_get. No server, no bucket, no API key.

  • client · coverage plan
    portaldot-v3 · unified-historysnapshot  #1 – #129,069manifest #2direct    #129,070 – headlive tailmixed sync, L3 938 / 9383.0 s polkadot-asset-hub · balance-historysnapshot  #22,021,128 – #22,101,127manifest #3direct    #22,101,128 – headlive tail80,000 blocks from the snapshotnot ≈ 11 min

    Adaptive sync

    Know what’s fastest

    Direct sync when a chain is cheap (Portaldot V3: genesis to head in a browser), snapshots when it’s heavy, and a live tail of new finalized blocks either way.

  • specs/polkadot-ah.balance-history.json
    {  "source": { "chain": "polkadot-asset-hub",              "fromBlock": 11405259 },  "columns": ["kind", "from", "to", "amount"],  "match": [    { "pallet": "Balances", "event": "Transfer" },row    { "pallet": "System", "event": "KilledAccount",reset      "effect": "reset" }, …  ],  "reconcile": { "storage": "System.Account" }}

    Declarative specs

    Know what’s indexed

    One JSON file says which events become which rows and how they reconcile. No handler code: the same spec over the same blocks gives the same rawHash on any machine.

History that ships as a spec and a few blobs, not as an indexer you run forever.

Proof, not promises

accounts reconciled per chunk · polkadot-ah · #20,572,285–#22,072,28430 / 30 chunks · 617,190 checks · 0 off0k6k12k18k24kchunk 0chunk 9chunk 19chunk 29

On-chain. Check it yourself.

Every address and block below is on the Portaldot V3 testnet.

  • PotluckRegistry (EVM)

    0xef93…82eb on Portaldot V3, deployed at block #129,014.

  • Deploy transaction

    0x3abb…0352, storage deposit 433.2 tPOT. Open in explorer.

  • Manifest #2

    Portaldot V3 history, blocks #1–#129,069, registered at block #129,095.

  • Manifest #3

    Polkadot AH, 80,000 blocks and 114,460 rows for 372.64 tPOT, registered at block #129,233.

  • Tested contracts

    21 Foundry tests, 100% coverage; EVM and PVM bytecode pass ReviveApi dry runs. Source.

  • Public on GitHub

    Spec, core, client, CLI and both apps in one repo. wngstnr-code/potluck.