Skip to main content
Dstack enables running containerized applications in Trusted Execution Environments (TEE). For development purposes, you can use our TEE simulator to develop and test your applications locally without TEE hardware. This guide covers setting up the simulator and using our SDKs to interact with TEE functionalities. Refer to the Hardware Requirements for release.

Prerequisites

  • Rust toolchain (for building the simulator)
  • Git
  • One of the following development environments:
    • Node.js 16+ (for JavaScript SDK)
    • Python 3.7+ (for Python SDK)
    • Go 1.16+ (for Go SDK)
    • Rust 1.70+ (for Rust SDK)

Simulator

The latest TEE simulator is available in dstack code repository. Use the following commands to build it:

Build Simulator

# Install rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Clone the repository
git clone https://github.com/Dstack-TEE/dstack.git

# Build the simulator
cd dstack/sdk/simulator
./build.sh

# Run the simulator
./dstack-simulator

# The simulator will create the following socket files:
#   dstack.sock  // Current TEE service interface (v0.5+)
#   tappd.sock   // Legacy TEE service interface (v0.3)
#   external.sock
#   guest.sock
To use the simulator with any SDK, set the following environment variable with the absolute path:
export DSTACK_SIMULATOR_ENDPOINT=/path/to/dstack.sock

Verifying Simulator Setup

After starting the simulator, verify the setup by checking:
  1. The socket files exist in the simulator directory:
ls *.sock
  1. The environment variable is set correctly:
echo $DSTACK_SIMULATOR_ENDPOINT

Dstack API

The Dstack API provides the basic abstraction of the TEE functionalities. In general, it provides the following functions:
  • Get Key: Generate a cryptographic key from the specified key path and returns it along with its certificate chain.
  • Get TDX Quote: Generate a TDX quote with report data. This can be further verified in our TEE Attestation Explorer to prove your application and data are in TEE.
  • Get TDX Information: Retrieve worker information, one example response is like
    {
        "app_id": "<hex-encoded-app-id>",
        "instance_id": "<hex-encoded-instance-id>",
        "app_cert": "<certificate-string>",
        "tcb_info": "<tcb-info-string>",
        "app_name": "my-app",
        "public_logs": true,
        "public_sysinfo": true,
        "device_id": "<hex-encoded-device-id>",
        "mr_aggregated": "<hex-encoded-mr-aggregated>",
        "os_image_hash": "<hex-encoded-os-image-hash>",
        "key_provider_info": "<key-provider-info-string>",
        "compose_hash": "<hex-encoded-compose-hash>"
    }
    
The dstack.sock is the current TEE RPC API (v0.5+). For more detailed documents, check the SDK documentation.
Note: If you’re upgrading from dstack v0.3, see the Migration Guide for breaking changes.

Programming Language Support

JavaScript

Check the latest version in dstack code repository.

Installation

npm install @phala/dstack-sdk

Basic Usage

import { DstackClient } from '@phala/dstack-sdk';
import crypto from 'crypto';

const client = new DstackClient();

// Check if service is reachable (500ms timeout, never throws)
const isReachable = await client.isReachable();
if (!isReachable) {
  console.log('Dstack service is not available');
  return;
}

// Get the information of the Base Image.
await client.info();

// Get a deterministic key with path
const keyResult = await client.getKey('my-app/encryption/v1');
console.log(keyResult.key); // Uint8Array(32) - already a Uint8Array
console.log(keyResult.signature_chain); // Signature chain

// Generate TDX quote (manually hash data if > 64 bytes)
const data = 'some-data';
const hash = crypto.createHash('sha256').update(data).digest();
const quoteResult = await client.getQuote(hash.slice(0, 32));
console.log(quoteResult.quote); // TDX quote in hex format
console.log(quoteResult.event_log); // Event log
const rtmrs = quoteResult.replayRtmrs(); // Replay RTMRs

Python

Check the latest version in dstack code repository.

Installation

pip install dstack-sdk

Basic Usage

from dstack_sdk import DstackClient
import hashlib

# Synchronous client
client = DstackClient()

# Caution: You don't need to do this most of the time.
http_client = DstackClient('http://localhost:8000')

# Get the information of the Base Image.
info = client.info()
print(info.app_id)  # Application ID
print(info.tcb_info.mrtd)  # Access TCB info directly
print(info.tcb_info.event_log[0].event)  # Access event log entries

# Get a deterministic key with path
key_result = client.get_key('my-app/encryption/v1')
print(key_result.key)  # Hex string
print(key_result.signature_chain)  # Signature chain
key_bytes = key_result.decode_key()  # Decode to bytes (32 bytes)

# Generate TDX quote (manually hash data if > 64 bytes)
data = b'some-data'
hash_value = hashlib.sha256(data).digest()
quote_result = client.get_quote(hash_value[:32])
print(quote_result.quote)  # TDX quote in hex format
print(quote_result.event_log)  # Event log
rtmrs = quote_result.replay_rtmrs()  # Replay RTMRs

Golang

Check the latest version in dstack code repository.

Installation

go get github.com/Dstack-TEE/dstack/sdk/go

Basic Usage

package main

import (
	"context"
	"fmt"
	"log/slog"

	"github.com/Dstack-TEE/dstack/sdk/go/dstack"
)

func main() {
	client := dstack.NewDstackClient(
		// dstack.WithEndpoint("http://localhost"),
		// dstack.WithLogger(slog.Default()),
	)

	// Get information about the dstack client instance
	info, err := client.Info(context.Background())
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(info.AppID)  // Application ID
	fmt.Println(info.TcbInfo.Mrtd)  // Access TCB info directly
	fmt.Println(info.TcbInfo.EventLog[0].Event)  // Access event log entries

	path := "/test"
	purpose := "test" // or leave empty

	// Derive a key with optional path and purpose
	deriveKeyResp, err := client.GetKey(context.Background(), path, purpose)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(deriveKeyResp.Key)

	// Generate TDX quote
	tdxQuoteResp, err := client.GetQuote(context.Background(), []byte("test"))
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(tdxQuoteResp.Quote)  // 0x0000000000000000000 ...

	rtmrs, err := tdxQuoteResp.ReplayRTMRs()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(rtmrs)  // map[0:00000000000000000 ...
}

Rust

Check the latest version in dstack code repository.

Installation

[dependencies]
dstack-rust = { git = "https://github.com/Dstack-TEE/dstack.git", package = "dstack-rust" }

Basic Usage

use dstack_sdk::DstackClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = DstackClient::new(None); // Uses env var or default to Unix socket

    // Get system info
    let info = client.info().await?;
    println!("Instance ID: {}", info.instance_id);

    // Derive a key
    let key_resp = client.get_key(Some("my-app".to_string()), None).await?;
    println!("Key: {}", key_resp.key);
    println!("Signature Chain: {:?}", key_resp.signature_chain);

    // Generate TDX quote
    let quote_resp = client.get_quote(b"test-data".to_vec()).await?;
    println!("Quote: {}", quote_resp.quote);
    let rtmrs = quote_resp.replay_rtmrs()?;
    println!("Replayed RTMRs: {:?}", rtmrs);

    // Emit an event
    client.emit_event("BootComplete".to_string(), b"payload-data".to_vec()).await?;

    Ok(())
}