Skip to content

Messaging & the CSK

Members message each other through the cluster contract — which sounds wrong until you see what it buys:

  • Sender authentication for free. MessageFacet.send is gated by membership, and the emitted MessageSent event carries the sender’s member id as resolved on chain. A message cannot be spoofed.
  • No plaintext, ever. The payload is a sealed-box ciphertext (libsodium construction: ephemeral x25519 + XSalsa20-Poly1305) encrypted to the recipient’s registered x25519 key. The project rule is absolute — nothing readable goes on chain.
  • Durable, ordered delivery. Events are the transport. A node that was down for an hour replays exactly what it missed from logs; the Indexer makes the live path fast.
  • Replay protection. The facet deduplicates (recipient, envelopeId) pairs on chain.

The sidecar uses this channel itself (for the endpoint envelopes that carry heartbeat keys) and exposes it to your application as SendMessage / SubscribeMessages — encryption, submission, decryption, and sender attribution all handled.

This is a coordination channel, not a data plane: each message is a sponsored on-chain transaction. Use it for control messages and key material; bulk traffic belongs on the wireguard mesh.

Many clustered applications want one symmetric secret every member holds — encrypting a replicated store, deriving session keys, sealing snapshots. AttestMesh provides this as the CSK: 32 bytes, identical on every member, never seen by the chain or the operator.

first member (originator) every later member (onboardee)
────────────────────────── ────────────────────────────────
derive CSK inside the TEE wait for the mesh to come up
commit keccak256(CSK) on chain ──► read the commitment from chain
serve peer pulls over the mesh ──► pull sealed CSK from a live peer
verify hash == commitment, keep it
  • Origination. The first registered member derives the CSK deterministically from its TEE seed and publishes only keccak256(CSK) — a one-time, on-chain commitment (the contract enforces both “originator only” and “only once”).
  • Distribution. Peers request the CSK over the authenticated mesh (a gRPC service bound to the mesh interface — unreachable from outside). The holder seals it to the requester’s on-chain x25519 key: even a hypothetical tunnel compromise doesn’t expose it, and only a current member can decrypt it.
  • Verification. The receiver checks the hash against the commitment. A malicious or buggy peer cannot hand over a wrong key.

The CSK is designed to be re-acquirable from nothing:

  • The originator re-derives it on any restart (same TEE identity → same key) and re-verifies against the commitment — so its custody survives even total loss of local state.
  • Onboardees re-pull from any live peer.
  • The cluster as a whole keeps the CSK alive as long as at least one originator-derivable or CSK-holding member exists.

Applications read it from the sidecar (GetClusterSharedKey), which refuses until the node is fully healthy — so by the time your code holds the CSK, the membership it implies is real, attested, and converged.