Skip to content

feat(kms): use Phala L2 light client in default compose - #1319

Open
kvinwang wants to merge 15 commits into
nextfrom
research/phala-l2-light-client
Open

kvinwang wants to merge 15 commits into
nextfrom
research/phala-l2-light-client

Conversation

@kvinwang

@kvinwang kvinwang commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Run the default KMS deployment against Phala L2 through proof-verified Helios reads.
  • Package KMS, auth-api, Helios and the relay in one image; Compose has no build directives and requires an explicit KMS_IMAGE digest.
  • Pin Dstack-TEE/helios master 645af74 (#1), which proves the Phala sequencer signer from Ethereum L1 before accepting any block.
  • Default deploy-to-vmm.sh to dstack-0.6.0: secure_time hangs on older guests (secure_time: true can never sync — guest chrony is built without NTS #745).
  • ETH_MAX_BLOCK_AGE_SECONDS bounds state age in both Helios and auth-api.

Trust model

Contract reads are verified against blocks signed by the sequencer key registered in Phala's L1 SystemConfig, proven through the Ethereum light client. L1 settlement is not checked, so the sequencer key remains trusted. Freshness depends on guest time: approve only KMS app-composes with secure_time: true.

Validation

Hardware TDX, QEMU 8.2.2, dstack-0.6.0 guest (OS hash 621080…471ca), Phala chain 2035, test KMS proxy 0xf4bcb0A454838a776D79D3e341D7f4aa2Cf366F0, block lag 2, max age 300s, relay idle timeout 30s, secure_time: true. Image built from fd2bbcf and served from a private test registry.

  • Helios rejects every block until the L1 signer proof succeeds; a tampered L1 storage proof is rejected.
  • Real key release: the app CVM reported key_provider=kms with the new KMS CA key. After removing its compose hash, a fresh CVM got Boot denied: Compose hash not allowed; the hash was restored.
  • Relay outage: authorization still succeeded 96s into the outage (previously Helios capped state age at 60s), was refused with authorization backend unavailable at 413s, and recovered after the network returned without restarting containers.
  • 340 eth_calls on 20 recent blocks matched the Phala RPC except 3 rate-limited RPC replies.
  • Two clean-cache builds of a6a38d9 from a fresh clone produced the same digest sha256:b1cc5ff158e20337c2c901e37bcf41b8d9b8b6d3eb0d47e26869fdef09349ec1.
  • 15 auth-api Jest tests pass.
  • Helios 645af74 (Rust 1.94.1): workspace fmt/clippy/wasm checks and tests pass, except network tests needing RPC secrets or Holesky. Local relay + Helios against Phala: signer proven from L1, head within one block of the Phala RPC, 12/12 eth_calls at head-2 matched. Calls in the first minute can fail closed until three blocks are cached.

@kvinwang
kvinwang marked this pull request as draft September 22, 2026 15:16
@kvinwang
kvinwang marked this pull request as ready for review September 22, 2026 15:49
@kvinwang
kvinwang force-pushed the research/phala-l2-light-client branch from 5c7f648 to 72fd3df Compare October 27, 2026 04:13
@kvinwang

Copy link
Copy Markdown
Collaborator Author

Rebased onto next and added two emSign CA distrust fixes:

Rebase conflicts were only in docker-compose.yaml / compose-dev.yaml, where #1466 had touched the old auth-api block; this PR's side was kept. The runtime stage now gets ca-certificates 20250419~deb12u2 from #1464. Helios uses native-tls with that trust store by default; with the old rust:1.92.0 bundle it accepted dv-g3b-emudhra.we-have-a-problem.com, and with the new bundle it rejects it. A full KMS image build has not been run.

#1492 deletes the legacy docker-compose.yaml. If it lands first, keep this PR's version of the file when rebasing.

Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Pin the Helios fork commit that proves the unsafe signer from Ethereum L1
before accepting blocks and enforces the configured head age. Require an
explicit KMS image, drop the preview release workflow and the dev Compose
alias, warn when auth-api runs without verified-read settings, and
document the secure_time requirement and failure handling.

Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Signed-off-by: Kevin Wang <wy721@qq.com>
Pin Dstack-TEE/helios master (645af74), which merges the Phala light
client with CI fixes and simplified static-peer reconnects. Default the
KMS deploy script to dstack-0.6.0, since secure_time hangs on older
guests (#745), and point the on-chain governance guide at the light
client settings.

Signed-off-by: Kevin Wang <wy721@qq.com>
The Phala RPC, Ethereum RPCs and relay peer are untrusted: every response
is checked against signatures or proofs. Read them from the unmeasured
user config so operators can replace an endpoint without a new compose
hash and on-chain approval. Only the user config file is mounted, and
only fixed keys are read, so the host cannot inject other variables. The
Ethereum checkpoint stays in Compose because it anchors verification.

Signed-off-by: Kevin Wang <wy721@qq.com>
The KMS image copies the auth-builder node binary into the runtime, so
auth-api ran on Node 20.20.2, which still trusts the compromised
eMudhra/emSign intermediates. Use the Node 22.23.4 image that #1466
already moved the compose auth-api to.

Signed-off-by: Kevin Wang <wy721@qq.com>
Dstack-TEE/helios#2 moves the lock to rustls-webpki 0.103.16 and
webpki-roots 1.0.10, so Helios rustls clients reject chains through
the compromised eMudhra/emSign intermediates.

Signed-off-by: Kevin Wang <wy721@qq.com>
@kvinwang
kvinwang force-pushed the research/phala-l2-light-client branch from 72fd3df to eb59916 Compare October 27, 2026 04:27

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant