Getting started
This guide brings up a complete AttestMesh cluster on Base mainnet using the dstack (Phala) attestation method: the on-chain contracts, the gas-sponsorship webhook, the shared indexer, and two attested nodes that finish meshed, converged, and holding the Cluster Shared Key.
Prerequisites
Section titled “Prerequisites”- The AttestMesh monorepo checked out.
- Foundry (
forge,cast) and Rust (stable) installed. - A funded deployer key (cluster owner). Gas costs are small — the full on-chain deployment is well under 0.001 ETH on Base.
- An Alchemy app for Base (RPC + EIP-4337 bundler + Gas Manager policy).
- A Phala Cloud account with the
phalaCLI logged in (npx phala login) — nodes and the indexer run as dstack CVMs. - A Cloudflare account (the sponsorship webhook is a Worker).
- A ghcr.io pull token if your sidecar/indexer images are private.
Credentials are loaded from the environment by deploy/env.sh; nothing secret is
ever committed.
One command (Smithers)
Section titled “One command (Smithers)”The entire bring-up is codified as a durable, resumable Smithers workflow:
source deploy/env.shbunx smithers-orchestrator up deploy/workflows/deploy.tsxThe attestmesh-deploy-full workflow runs 17 ordered tasks:
preflight → infra → cluster → pathaUpgrade → webhook → indexerEnsure → node-1 { env-file → deploy → prime → upgrade → verify } → node-2 { env-file → deploy → prime → upgrade → verify } → meshVerifyEvery step is crash-recoverable: if a step fails (or a slow registration times
out), fix the cause and resume with --run-id <id> --resume true — completed
steps, deployed CVMs, and on-chain state are all reused, never redone.
Notable steps:
- indexerEnsure is a no-op when the chain already has a registered indexer — the indexer is shared infrastructure, one instance for every cluster.
- meshVerify polls both nodes’ health endpoints until they report
phase: "healthy"— wireguard up, heartbeats converged, CSK held.
Step by step (bash routines)
Section titled “Step by step (bash routines)”Each workflow task shells out to an idempotent, logged bash routine you can also
run directly. Every step tees its output to deploy/logs/.
1. Contracts
Section titled “1. Contracts”source deploy/env.shdeploy/onchain.sh preflight # checks keys, chain id, balancesdeploy/onchain.sh infra # facets, factories, IndexerRegistry (no-op if deployed)deploy/onchain.sh cluster attestmesh-1deploy/onchain.sh patha-upgrade <cluster-address>2. Gas-sponsorship webhook
Section titled “2. Gas-sponsorship webhook”deploy/webhook.sh deploy # wrangler deploy + asserts the custom-domain routeThen point your Alchemy Gas Manager policy’s webhook at the deployed URL.
3. The shared indexer
Section titled “3. The shared indexer”deploy/indexer.sh attestmesh-indexer-1 ensureensure checks IndexerRegistry.current() first: if an indexer is already
registered on this chain, it does nothing. Otherwise it deploys the indexer CVM,
waits for boot, scrapes the TEE-derived signing pubkey from the logs, and registers
(endpoint, codeId, pubKey) on chain.
4. Nodes
Section titled “4. Nodes”CLUSTER=<cluster> MEMBER_IMPL=<impl> COMPOSE=deploy/compose/node-1.yaml \ deploy/node-pathA.sh attestmesh-node-1 allThe “Path A” routine (dstack base KMS) deploys a stock dstack app, allowlists its
compose hash and app id on the cluster, upgrades the proxy to ClusterMember, and
then polls the chain while the sidecar inside the CVM self-registers via a
sponsored UserOperation. Repeat for attestmesh-node-2.
5. Verify the mesh
Section titled “5. Verify the mesh”deploy/node-pathA.sh attestmesh-node-1 mesh-verifydeploy/node-pathA.sh attestmesh-node-2 mesh-verifySuccess looks like:
{"csk_acquired":true,"first_converged":true,"live_peers":1,"phase":"healthy"}From a cold start, both nodes typically reach healthy within a few minutes of
their CVMs booting.
What just happened
Section titled “What just happened”Each node, entirely on its own: derived its keys inside the TEE, proved its code identity to the cluster contract, found its peers from chain state, brought up an encrypted wireguard mesh through the dstack gateway, exchanged signed heartbeat keys via encrypted on-chain envelopes, and acquired the Cluster Shared Key — the first node by deriving it, every later node by pulling it over the mesh and verifying it against the on-chain commitment.
Next: Running a node for the node lifecycle in detail, and Day-2 operations for updates and rollouts.