upstream

Reference

Attester network

Run an attester, or collect attestations from several: the API, the checks, and what each failure looks like.

An attester is a small web service: it reads one public page, looks for one code and signs what it saw. The code is in src/attester/; attester/ has the Node server, a Cloudflare Worker entry and a README with deployment notes.

API

GET  /v1/info
     -> { name, publicKey, apiVersion, platforms }

POST /v1/attest   { mint, target, wallet, epoch }
     -> 200 { status: "verified", code, profile, attestation }     the code is on the page
     -> 200 { status: "code_missing", code, profile }               it was read, the code is not there
     -> 400 bad_json | bad_request | bad_mint | bad_wallet | bad_epoch | bad_target
     -> 404 not_found   413 too_large   429 rate_limited   502 network | upstream | cors   504 timeout

target is anything the platform parser accepts. Responses carry access-control-allow-origin: * so a web page can call an attester directly.

What an attester will and will not do

  • It never holds funds and never decides ownership on its own judgement: it signs only a code it found.
  • It validates every field before doing anything. Bad input causes no outgoing request (tested).
  • It can only fetch the public endpoints of the four platforms, built from a validated handle. It cannot be pointed at another host.
  • It rate-limits per client address and caps request size at 2 KB.
  • It times out slow platforms (8 seconds by default).

The client side

collect() in src/attester/client.mjs asks all attesters in parallel and believes none of them blindly. For each answer it checks the pinned public key, that mint, wallet and epoch are the ones asked for, the account id if known, that the timestamp is fresh, that the code equals the one computed locally, and that the signature verifies. It even checks that an attester that says "code missing" asks the owner to paste the right code, so a lying attester cannot send the owner on a wild goose chase. Each attester ends up as verified, code_missing, invalid, error or timeout, with the reason.

Tested over real HTTP

  • Three attesters, a bundle collected over the network, and the vault paying out.
  • One attester down and one that never answers: two of three still work, and a hung attester cannot hold a claim up.
  • An attester that lies in seven different ways, all caught by the client.
  • Input validation, rate limiting (one noisy client does not lock out others), CORS, and the Fetch API adapter used by Workers.

Running one

node cli/upstream.mjs keygen --out attester.json
node attester/server.mjs 8787 alpha --key attester.json     # or: cd attester && npx wrangler deploy

Then publish the operator's name and the public key. A coin's vault stores up to five public keys; whoever creates the coin chooses them, and holders should read the list before buying.

Independence is the whole point

Two attesters run by the same person on the same machine are one attester. The network is only as honest as the number of genuinely separate operators in each coin’s list. No operator is running one yet.