Attest a verified sender
See Verified-sender attestation for what an attestation is and why a sending organization buys one. This page is the technical reference: the attest, lookup, and revoke commands, the postmaster fee setting, and the on-chain mechanics they ride.
sithbit domain attest-sender <MAIL_DOMAIN> [WALLET] \
( --witness-file <path> | --witness-hex <hex> ) \
[--payer-keypair <path>] \
[--skip-preflight]
This is the third member of the proof-carrying family, alongside
domain authorize and
domain reclaim. It submits the same DNSSEC
witness — the RRSIG chain proving the domain’s _solana.authority
delegation, which the on-chain program verifies for itself — but
instead of authorizing the domain, a verified proof records that the
domain vouches for a wallet as a legitimate sender. Like its siblings
it is permissionless: anyone may submit a proof and pay for it,
because the proof, not the signer, is the authority.
What a verified proof mints is the SenderAttestation account for the
(domain, wallet) pair, stamped with the chain clock. Three shape
differences from domain authorize are worth knowing:
- No domain account is involved. Attesting neither reads nor creates a
MailDomain: a domain that has never been registered as a mail domain can attest senders just the same. The attestation is a freestanding record, and it confers no serving rights over the domain. - The attested wallet rides the instruction payload. It defaults to the payer’s own address, but the proving claimant may attest any wallet — control of the domain’s DNS is the sole authorization, and the authority key the leaf TXT publishes is not required to match the attested wallet (the domain vouches for whoever it names).
- One record per (domain, wallet) pair, any number of pairs. A domain may attest as many wallets as it likes; each attestation is minted — and later revoked — independently.
The witness, its two input sources (--witness-file / --witness-hex),
the client-side size bound, gathering the witness from live
DNS, the
automatic buffer staging + ComputeBudget bump + precompile emission for
non-RSA chain links, and the automatic buffer close on success are
exactly as domain authorize
describes — an attest reuses that whole pipeline, including the
prerequisite root KSK.
The staged buffer is even the same (payer, domain) PDA, so
either command can reclaim it.
# attest your own wallet (the payer's address is the default)
sithbit domain attest-sender acme.com --witness-file ./proof.bin
# attest a different sending wallet
sithbit domain attest-sender acme.com mAiLiLdgjgGdWoCZkpW3cj7JLAC56qb4NErFyQFWNJg \
--witness-file ./proof.bin
The attestation fee
A verified proof pays a one-time flat fee to the postoffice —
DEFAULT_SENDER_ATTESTATION_FEE_LAMPORTS, 0.01 SOL by default —
debited from the payer once, at the attest step, after the chain walk
succeeds. A failed proof charges nothing beyond transaction fees, and
the staged buffer’s rent stays reclaimable. The CLI quotes the currently
tuned fee in its success output, and anyone can read it ahead of time —
no signature, ships in every build:
sithbit postoffice fee attestation
The delegate tunes the fee with:
sithbit postmaster fee attestation <LAMPORTS> \
[--keypair <delegate keypair>] \
[--skip-preflight]
The value is hard-capped on-chain at
MAX_SENDER_ATTESTATION_FEE_LAMPORTS (0.1 SOL, 10× the default) — an
over-cap value refuses with custom error 101
(SenderAttestationFeeAboveCap) — so even a compromised delegate key
cannot price attestation out of reach. Zero resets to the protocol
default: like the settlement rates, a zero stores the “unset” sentinel,
so the fee cannot be tuned to literal zero. A postoffice account that
predates the fee field reads back the default, and the setter grows the
legacy account in place (to the 184-byte layout) on its first run. See the
tunable-constants table.
Looking up an attestation
sithbit domain attestation <MAIL_DOMAIN> <WALLET>
Read-only, and — like domain get — it ships in every
build. It prints the attested wallet, the attestation account, and the
attested-at timestamp, or a not-found notice when the domain has not
attested that wallet (a missing record is the common negative answer, not
an error):
sithbit domain attestation acme.com mAiLiLdgjgGdWoCZkpW3cj7JLAC56qb4NErFyQFWNJg
Servers ask the same question over the
mail-grpc gateway: the
GetSenderAttestation call takes {domain, wallet} and answers
{attested, attested_at}. A clean on-chain absence answers
attested = false; a failed chain read is an UNAVAILABLE status, never
a false — absent and unknown stay distinguishable. The read is
finalized-commitment and uncached, so a fresh attestation (or revocation)
is visible on the next call.
Revoking an attestation
sithbit domain revoke-attestation <MAIL_DOMAIN> \
[--keypair <path>] \
[--skip-preflight]
Closes the (domain, wallet) attestation for the signing wallet and
refunds the record’s rent to it. Only the attested wallet itself can
revoke: the attestation’s address is re-derived from the signer, so any
other key — the domain’s included — derives a different address and never
reaches the record (the same derivation binding
CloseProofWitness uses for its
payer). The command refuses client-side when no attestation exists for the
signer under that domain.
sithbit domain revoke-attestation acme.com -k wallet.json
Reclaiming an abandoned witness buffer
sithbit domain attest-sender <MAIL_DOMAIN> --close-witness \
[--payer-keypair <path>] \
[--skip-preflight]
A successful attest reclaims the staged witness buffer’s rent
automatically; a failed or abandoned attempt leaves the buffer behind for
a retry or inspection, exactly as domain authorize does. When you are
done with it, --close-witness closes the buffer and refunds its full
rent to the same payer keypair that staged it — the buffer PDA is
seeded on the payer, so it is the only key that can. Because the buffer is
the shared (payer, domain) staging PDA,
domain authorize --close-witness
reclaims the identical buffer.
Measured compute cost
Measured through the deployed .so on a real cluster, like every row in
the compute-unit table: the attest
transaction consumed 322,474 CU (fenced at 345,000) — the DNSSEC chain
walk dominates, which is why the CLI prepends the same ComputeBudget
limit domain authorize sizes to the proof’s zone depth.
RevokeSenderAttestation measured 11,224 CU (fenced 34,000) and
SetSenderAttestationFee 6,546 CU (fenced 30,000), both comfortably on
the 200k default budget.
Related
- Verified-sender attestation — what the record means, who buys it, and what it does not confer.
- Reputation-scaled first-contact pricing — the economic effect an attestation buys: a stranger’s first contact priced at the discount floor immediately, no spend history required.
- Authorize a domain by proof — the shared
witness pipeline, root-KSK prerequisite, and
gather-witness. - Reclaim a domain by proof — the other proof-carrying sibling, for seizing an existing domain’s authority.
- Program & PDA reference — the
instruction discriminants and the
sender_attestationPDA seed.