Skip to content
LogoLogo

Light clients & filters

Mobile and browser wallets, asset holders and devices shouldn't have to run a full node. Arrekta uses BIP 157/158-style compact block filters, with one improvement over Bitcoin: every filter is committed in the block, so a light client checks it against proof of work instead of trusting the peer that served it (§9.5).

What a filter contains

  • every non-burn output lock in the block (coinbase included);
  • every spent output's lock;
  • every non-ARRK asset id among the outputs, as "A" ‖ asset_id, so "watch asset X" works.

Items are hashed into a Golomb-coded set (P = 19, M = 784,931) keyed by the parent block hash. Filters chain into filter headers: filter_header(b) = TH("filter/header", TH("filter", filter_b) ‖ filter_header(parent)).

The commitment

From height 1, the coinbase's last burn output with a 36-byte payload starting "ARKF" must carry the block's filter header (bad-cb-filter otherwise). The coinbase is covered by the block's merkle root and therefore by its proof of work.

How a light client syncs

  1. Sync headers (headers-first, each with its AuxPoW).
  2. Fetch filter headers from several peers and compare them.
  3. Download filters and check each against its header; check the header against the coinbase commitment using the coinbase and its merkle branch.
  4. Fetch only the full blocks whose filters match its locks or assets.

The server never learns which addresses the client watches (unlike BIP 37 bloom filters).

Where to get filters

TransportRoute
RESTGET /v1/blocks/{id}/filter (filter, header, coinbase, merkle branch) and GET /v1/filters/headers?start=&count= (Light clients API)
P2PGETCFILTERS / CFILTER / GETCFHEADERS / CFHEADERS, nodes with services bit NODE_FILTERS (4)

The SDKs provide verifyFilter, matchFilter, verifyMerkleBranch and verifyCheckpoint; see the Light client guide.