Skip to content

Latest commit

 

History

History
201 lines (141 loc) · 6.18 KB

File metadata and controls

201 lines (141 loc) · 6.18 KB

On-Chain Governance

This guide is for self-hosted deployments on your own TDX hardware. For cloud deployments, see Quickstart.

This guide covers setting up on-chain governance for dstack using smart contracts on Ethereum.

Overview

On-chain governance adds:

  • Smart contract-based authorization: App registration and whitelisting managed by smart contracts
  • Decentralized trust: No single operator controls keys
  • Transparent policies: Anyone can verify authorization rules on-chain

Prerequisites

  • Production dstack deployment with KMS and Gateway as CVMs (see Deployment Guide)
  • Ethereum wallet with funds on Sepolia testnet (or your target network)
  • Foundry installed
  • Node.js and npm installed (for the bootAuth server)

Deploy DstackKms Contract

cd dstack/kms/auth-eth
npm install        # Install Node.js dependencies
forge install      # Install Foundry dependencies

# Deploy contracts (deploys both DstackApp implementation and DstackKms proxy)
PRIVATE_KEY=<your-key> forge script script/Deploy.s.sol:DeployScript \
  --broadcast --rpc-url https://eth-sepolia.g.alchemy.com/v2/<your-alchemy-key>

Sample output:

Deploying with account: 0x...
DstackApp implementation deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3
DstackKms implementation deployed to: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
DstackKms proxy deployed to: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0

Note the proxy address (e.g., 0x9fE4...).

Set environment variables for subsequent commands:

export KMS_CONTRACT_ADDR="<DstackKms-proxy-address>"
export PRIVATE_KEY="<your-private-key>"
export RPC_URL="https://eth-sepolia.g.alchemy.com/v2/<your-alchemy-key>"

Configure KMS for On-Chain Auth

The KMS CVM includes an auth-api service that connects to your DstackKms contract. Configure it via environment variables in the KMS CVM:

KMS_CONTRACT_ADDR=<your-dstack-kms-contract-address>
ETH_RPC_URL=<ethereum-rpc-endpoint>

The auth-api validates boot requests against the smart contract. See Deployment Guide for complete setup instructions.

Whitelist OS Image

OS_IMAGE_HASH=0x<os-image-hash> \
  forge script script/Manage.s.sol:AddOsImage --broadcast --rpc-url $RPC_URL

Output: Added OS image hash: 0x...

The os_image_hash is in the digest.txt file from the guest OS image build (see Building Guest Images).

Register Gateway App

# Create a new app with allowAnyDevice=true
ALLOW_ANY_DEVICE=true \
  forge script script/Manage.s.sol:DeployApp --broadcast --rpc-url $RPC_URL

Sample output:

Deployed new app at: 0x75537828f2ce51be7289709686A69CbFDbB714F1
  Owner: 0x...
  Allow any device: true

Note the App ID (deployed app address) from the output.

Set it as the gateway app:

GATEWAY_APP_ID=<app-id> \
  forge script script/Manage.s.sol:SetGatewayAppId --broadcast --rpc-url $RPC_URL

Output: Set gateway app ID: <app-id>

Add the gateway's compose hash to the whitelist. To compute the compose hash:

sha256sum /path/to/gateway-compose.json | awk '{print "0x"$1}'

Then add it:

APP_CONTRACT_ADDR=<app-id> COMPOSE_HASH=<compose-hash> \
  forge script script/Manage.s.sol:AddComposeHash --broadcast --rpc-url $RPC_URL

Output: Added compose hash: 0x...

Register Apps On-Chain

For each app you want to deploy:

Create App

ALLOW_ANY_DEVICE=true \
  forge script script/Manage.s.sol:DeployApp --broadcast --rpc-url $RPC_URL

Note the App ID from the output.

Add Compose Hash

Compute your app's compose hash:

sha256sum /path/to/your-app-compose.json | awk '{print "0x"$1}'

Then add it:

APP_CONTRACT_ADDR=<app-id> COMPOSE_HASH=<compose-hash> \
  forge script script/Manage.s.sol:AddComposeHash --broadcast --rpc-url $RPC_URL

Deploy via VMM

Use the App ID when deploying through the VMM dashboard or VMM CLI.

Smart Contract Reference

DstackKms (Main Contract)

The central governance contract that manages OS image whitelisting, app registration, and KMS authorization.

Function Description
addOsImageHash(bytes32) Whitelist an OS image hash
removeOsImageHash(bytes32) Remove an OS image from whitelist
setGatewayAppId(string) Set the trusted Gateway app ID
registerApp(address) Register an app contract
deployAndRegisterApp(...) Deploy and register app in one transaction
isAppAllowed(AppBootInfo) Check if an app is allowed to boot
isKmsAllowed(AppBootInfo) Check if KMS is allowed to boot

DstackApp (Per-App Contract)

Each app has its own contract controlling which compose hashes and devices are allowed.

Function Description
addComposeHash(bytes32) Whitelist a compose hash
removeComposeHash(bytes32) Remove a compose hash from whitelist
addDevice(bytes32) Whitelist a device ID
removeDevice(bytes32) Remove a device from whitelist
setAllowAnyDevice(bool) Allow any device to run this app
isAppAllowed(AppBootInfo) Check if app can boot with given config
disableUpgrades() Permanently disable contract upgrades

AppBootInfo Structure

Both isAppAllowed and isKmsAllowed take an AppBootInfo struct:

struct AppBootInfo {
    address appId;        // Unique app identifier (contract address)
    bytes32 composeHash;  // Hash of docker-compose configuration
    address instanceId;   // Unique instance identifier
    bytes32 deviceId;     // Hardware device identifier
    bytes32 mrAggregated; // Aggregated measurement register
    bytes32 mrSystem;     // System measurement register
    bytes32 osImageHash;  // OS image hash
    string tcbStatus;     // TCB status (e.g., "UpToDate")
    string[] advisoryIds; // Security advisory IDs
}

Source: dstack/kms/auth-eth/contracts/

See Also