Gas sponsorship
AttestMesh nodes never hold ETH. Funding ephemeral, attested machines with gas money would be an operational and security headache — so every state-changing call a node makes is an EIP-4337 UserOperation, paid by a paymaster under the operator’s policy.
The flow
Section titled “The flow”sidecar ──► bundler (eth_sendUserOperation) │ ├─► paymaster policy ──► sponsorship webhook « operator's gate » │ approve / deny └─► EntryPoint ──► ClusterMember.validateUserOp ──► execute- The sidecar wraps the real call (registration,
send,setCskCommitment) asClusterMember.execute(cluster, 0, calldata)and requests sponsorship. - The paymaster consults the operator’s sponsorship webhook before signing.
- The bundler submits; the node’s account validates the signature on chain.
The bootstrap trick
Section titled “The bootstrap trick”The very first UserOperation a node sends is its own registration — at which point
its account has no owner key on chain yet. validateUserOp handles this with
a bootstrap path: for a dstack_register call, it recovers the signer from the
attestation proof inside the operation itself, and the registration installs
that key as the permanent owner. One sponsored operation takes a node from
“nothing on chain” to “registered member with a working smart account.”
Every later operation verifies against the installed owner — the same TEE-derived
key, re-derived on each boot. (The account’s nonce comes from
EntryPoint.getNonce; see field notes for the bug that
taught us to fetch it correctly.)
The webhook: provenance, not balance
Section titled “The webhook: provenance, not balance”The sponsorship webhook is a small Cloudflare Worker that answers one question: is this UserOperation AttestMesh traffic the operator wants to pay for? It checks:
- the outer shape — must be
ClusterMember.executeinto a known cluster (deployed by the recognized factories, or an owner-allowlisted app id on the Path A flow); - the inner selector — must be on the allowlist of cluster operations:
registration, wireguard key publication, encrypted
send, the CSK commitment, and the cluster-admin operations (allowlist management, ownership transfers); - the chain id and the policy’s shared token.
Deny means the operator doesn’t pay — it is a spending control. Actual access control lives on chain (membership gates, owner gates) and stands on its own even if the webhook approved garbage.
Operating notes
Section titled “Operating notes”- The webhook deploys with
deploy/webhook.sh, which also asserts the custom-domain route — a stale route surfaces as bundler401s and is the single most-debugged failure in this system’s history. - Costs are small: a node’s entire lifecycle (registration, a handful of envelopes, CSK commitment) is a few sponsored operations; steady state adds envelopes only when membership changes.