Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Initial TEE Plugin #632

Merged
merged 7 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,8 @@ ZEROG_FLOW_ADDRESS=
# Coinbase Commerce
COINBASE_COMMERCE_KEY=


# TEE Configuration
DSTACK_SIMULATOR_ENDPOINT=
WALLET_SECRET_SALT=secret_salt

83 changes: 68 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
FROM node:23.3.0
# Install pnpm globally
RUN npm install -g [email protected]
# Stage 1: Build dependencies in a temporary stage
FROM node:23.3.0 AS builder

# Install required global dependencies
RUN apt-get update && apt-get install -y \
python3 \
build-essential \
git \
curl \
sqlite3 && \
apt-get clean \
&& npm install -g [email protected]

# Set the working directory
# Set working directory
WORKDIR /app

# Add configuration files and install dependencies
Expand All @@ -11,20 +20,64 @@ ADD package.json /app/package.json
ADD .npmrc /app/.npmrc
ADD tsconfig.json /app/tsconfig.json
ADD pnpm-lock.yaml /app/pnpm-lock.yaml
RUN pnpm i

# Add the documentation
ADD docs /app/docs
RUN pnpm i
# Install dependencies
RUN pnpm install

# Add the rest of the application code
# Copy source code
ADD docs /app/docs
ADD packages /app/packages
RUN pnpm i

# Add the environment variables
ADD scripts /app/scripts
ADD characters /app/characters
ADD .env /app/.env
ADD agent /app/agent

# Add dependencies to workspace root
RUN pnpm add -w -D ts-node typescript @types/node

WORKDIR /app/packages/agent

# Add dependencies to the agent package specifically
RUN pnpm add -D ts-node typescript @types/node --filter "@ai16z/agent"

WORKDIR /app/packages/core
RUN pnpm add -D ts-node typescript @types/node --filter "@ai16z/eliza"

WORKDIR /app

# Optional: build step if using TypeScript or other build process
RUN pnpm build

# Stage 2: Production image
FROM node:23.3.0

# Install dependencies required for the final runtime
RUN apt-get update && apt-get install -y \
python3 \
build-essential \
git \
curl \
sqlite3 && \
apt-get clean \
&& npm install -g [email protected]

# Set working directory
WORKDIR /app

# Copy built files from the builder stage
COPY --from=builder /app /app

# install playwright
RUN pnpm exec playwright install
RUN pnpm exec playwright install-deps

# Expose application port if running a web server
EXPOSE 3000

# Add health check to ensure the app is running
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s CMD curl -f http://localhost:3000 || exit 1

# Set environment variables to configure runtime model settings
ENV NODE_ENV=production

# Command to run the container
CMD ["tail", "-f", "/dev/null"]
# Default command to run the application
CMD ["pnpm", "start"]
1 change: 1 addition & 0 deletions agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@ai16z/plugin-solana": "workspace:*",
"@ai16z/plugin-0g": "workspace:*",
"@ai16z/plugin-starknet": "workspace:*",
"@ai16z/plugin-tee": "workspace:*",
"@ai16z/plugin-coinbase": "workspace:*",
"readline": "1.3.0",
"ws": "8.18.0",
Expand Down
4 changes: 4 additions & 0 deletions agent/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ import {
import { confluxPlugin } from "@ai16z/plugin-conflux";
import { createNodePlugin } from "@ai16z/plugin-node";
import { solanaPlugin } from "@ai16z/plugin-solana";
import { nodePlugin } from "@ai16z/plugin-node";
import { teePlugin } from "@ai16z/plugin-tee";

import Database from "better-sqlite3";
import fs from "fs";
import path from "path";
Expand Down Expand Up @@ -281,6 +284,7 @@ export function createAgent(
? coinbaseMassPaymentsPlugin
: null,
getSecret(character, "BUTTPLUG_API_KEY") ? buttplugPlugin : null,
getSecret(character, "WALLET_SECRET_SALT") ? teePlugin : null,
].filter(Boolean),
providers: [],
actions: [],
Expand Down
40 changes: 40 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
services:
tee:
command: ["pnpm", "start"]
image: hashwarlock/tee-agent:latest
stdin_open: true
tty: true
volumes:
- /var/run/tappd.sock:/var/run/tappd.sock
- tee:/app/packages/client-twitter/src/tweetcache
- tee:/app/db.sqlite
environment:
- OPENAI_API_KEY=
- REDPILL_API_KEY=
- ELEVENLABS_XI_API_KEY=
- ELEVENLABS_MODEL_ID=eleven_multilingual_v2
- ELEVENLABS_VOICE_ID=21m00Tcm4TlvDq8ikWAM
- ELEVENLABS_VOICE_STABILITY=0.5
- ELEVENLABS_VOICE_SIMILARITY_BOOST=0.9
- ELEVENLABS_VOICE_STYLE=0.66
- ELEVENLABS_VOICE_USE_SPEAKER_BOOST=false
- ELEVENLABS_OPTIMIZE_STREAMING_LATENCY=4
- ELEVENLABS_OUTPUT_FORMAT=pcm_16000
- TWITTER_DRY_RUN=false
- TWITTER_USERNAME=
- TWITTER_PASSWORD=
- TWITTER_EMAIL=
- X_SERVER_URL=https://api.red-pill.ai/v1
- BIRDEYE_API_KEY=
- SOL_ADDRESS=So11111111111111111111111111111111111111112
- SLIPPAGE=1
- RPC_URL=https://api.mainnet-beta.solana.com
- HELIUS_API_KEY=
- SERVER_PORT=3000
- WALLET_SECRET_SALT=secret_salt
ports:
- "3000:80"
restart: always

volumes:
tee:
6 changes: 6 additions & 0 deletions packages/plugin-tee/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*

!dist/**
!package.json
!readme.md
!tsup.config.ts
52 changes: 52 additions & 0 deletions packages/plugin-tee/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Plugin TEE

A plugin for handling Trusted Execution Environment (TEE) operations.

## Providers

This plugin includes several providers for handling different TEE-related operations.

### DeriveKeyProvider

The `DeriveKeyProvider` allows for secure key derivation within a TEE environment.

#### Usage

```typescript
import { DeriveKeyProvider } from "@ai16z/plugin-tee";
// Initialize the provider
const provider = new DeriveKeyProvider();
// Derive a key
try {
const keypair = await provider.deriveKey("/path/to/derive", "subject-identifier");
// keypair can now be used for cryptographic operations
} catch (error) {
console.error("Key derivation failed:", error);
}
```

### RemoteAttestationProvider

The `RemoteAttestationProvider` allows for generating a remote attestation within a TEE environment.

#### Usage

```typescript
const provider = new RemoteAttestationProvider();

try {
const attestation = await provider.generateAttestation("your-report-data");
console.log("Attestation:", attestation);
} catch (error) {
console.error("Failed to generate attestation:", error);
}
```

### Configuration

When using the provider through the runtime environment, ensure the following settings are configured:

```env
DSTACK_SIMULATOR_ENDPOINT="your-endpoint-url" # Optional, for simulator purposes if testing on mac or windows
WALLET_SECRET_SALT=your-secret-salt // Required to single agent deployments
```
26 changes: 26 additions & 0 deletions packages/plugin-tee/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@ai16z/plugin-tee",
"version": "0.1.3",
"main": "dist/index.js",
"type": "module",
"types": "dist/index.d.ts",
"dependencies": {
"@ai16z/eliza": "workspace:*",
"@phala/dstack-sdk": "^0.1.4",
"@solana/web3.js": "1.95.4",
"@solana/spl-token": "0.4.9",
"bignumber": "1.1.0",
"bignumber.js": "9.1.2",
"bs58": "^6.0.0",
"node-cache": "5.1.2",
"pumpdotfun-sdk": "1.3.2",
"tsup": "^8.3.5"
},
"scripts": {
"build": "tsup --format esm --dts",
"dev": "tsup --watch"
},
"peerDependencies": {
"whatwg-url": "7.1.0"
}
}
25 changes: 25 additions & 0 deletions packages/plugin-tee/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Plugin } from "@ai16z/eliza";
import { remoteAttestationProvider } from "./providers/remoteAttestationProvider";
import { deriveKeyProvider } from "./providers/deriveKeyProvider";
import { walletProvider } from "./providers/walletProvider";

export const teePlugin: Plugin = {
name: "tee",
description:
"TEE plugin with actions to generate remote attestations and derive keys",
actions: [
/* custom actions */
],
evaluators: [
/* custom evaluators */
],
providers: [
/* custom providers */
remoteAttestationProvider,
deriveKeyProvider,
walletProvider,
],
services: [
/* custom services */
],
};
69 changes: 69 additions & 0 deletions packages/plugin-tee/src/providers/deriveKeyProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { IAgentRuntime, Memory, Provider, State } from "@ai16z/eliza";
import { Keypair } from "@solana/web3.js";
import crypto from "crypto";
import { TappdClient } from "@phala/dstack-sdk";

class DeriveKeyProvider {
private client: TappdClient;

constructor(endpoint?: string) {
this.client = endpoint ? new TappdClient(endpoint) : new TappdClient();
}

async deriveKey(path: string, subject: string): Promise<Keypair> {
try {
if (!path || !subject) {
console.error("Path and Subject are required for key derivation");
}

console.log("Deriving Key in TEE...");
const derivedKey = await this.client.deriveKey(path, subject);
const uint8ArrayDerivedKey = derivedKey.asUint8Array();

const hash = crypto.createHash("sha256");
hash.update(uint8ArrayDerivedKey);
const seed = hash.digest();
const seedArray = new Uint8Array(seed);
const keypair = Keypair.fromSeed(seedArray.slice(0, 32));

console.log("Key Derived Successfully!");
return keypair;
} catch (error) {
console.error("Error deriving key:", error);
throw error;
}
}
}

const deriveKeyProvider: Provider = {
get: async (runtime: IAgentRuntime, _message?: Memory, _state?: State) => {
const endpoint = runtime.getSetting("DSTACK_SIMULATOR_ENDPOINT");
const provider = new DeriveKeyProvider(endpoint);
try {
// Validate wallet configuration
if (!runtime.getSetting("WALLET_SECRET_SALT")) {
console.error(
"Wallet secret salt is not configured in settings"
);
return "";
}

let keypair: Keypair;
try {
const secretSalt =
runtime.getSetting("WALLET_SECRET_SALT") || "secret_salt";
return await provider.deriveKey("/", secretSalt);
} catch (error) {
console.error("Error creating PublicKey:", error);
return "";
}

return keypair;
} catch (error) {
console.error("Error in derive key provider:", error.message);
return `Failed to fetch derive key information: ${error instanceof Error ? error.message : "Unknown error"}`;
}
},
};

export { deriveKeyProvider, DeriveKeyProvider };
Loading
Loading