The obvious way to find your records, “give me everything owned by S1, S2, S3…”, would tell the RPC
provider your full set of addresses and undo everything. Arkognito never asks about specific
records or addresses.
Three steps
- List the app. Download every record of the app as of one block: keys, owners, creators,
creation blocks and attributes, no payloads. Every user of the app downloads the same list.
- Open tags locally. Try to decrypt each record’s
vtag. Only tags made by your root key
open; each names one of your keys, whose address must equal the record’s owner.
- Fetch by batch. Download full records only for the batches that hold one of yours, plus two
other batches at random, then verify each signature.
The RPC provider learns that you use the app, and that one of a few batches interests you. It
never learns which record, or which addresses, are yours.
After writing
The client confirms a new record the same way: it fetches the whole batch the relayer named, never
the single key. If a relayer fails to answer, the client looks for its own tag in a fresh listing
before trying another relayer, so a relayer that wrote the record and then crashed causes no
duplicate.
Cost
The listing grows with the number of records in the app: about 1–3 seconds for a few hundred
records in our tests. Large apps will want an index service in a later version.
Implementation notes
- Listings are pinned to one block with
atBlock, because Arkiv cursors are tied to the block they
were read at.
- Batches are fetched with a
$createdAt = u64(block) AND $creator = addr(relayer) query. The node
supports this filter even though the Arkiv SDK’s query builder refuses it, so the SDK sends it as
a raw query.
Last modified on October 12, 2026