Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9c31cd7

Browse files
committedJan 3, 2025
feat: add remote attestation action and upload to proof[.]t16z[.]com explorer
1 parent 76d4f42 commit 9c31cd7

File tree

6 files changed

+118
-11
lines changed

6 files changed

+118
-11
lines changed
 

‎agent/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ export async function createAgent(
572572
]
573573
: []),
574574
...(teeMode !== TEEMode.OFF && walletSecretSalt
575-
? [teePlugin, solanaPlugin]
575+
? [teePlugin]
576576
: []),
577577
getSecret(character, "COINBASE_API_KEY") &&
578578
getSecret(character, "COINBASE_PRIVATE_KEY") &&

‎packages/plugin-tee/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"types": "dist/index.d.ts",
77
"dependencies": {
88
"@elizaos/core": "workspace:*",
9-
"@phala/dstack-sdk": "0.1.6",
9+
"@phala/dstack-sdk": "0.1.7",
1010
"@solana/spl-token": "0.4.9",
1111
"@solana/web3.js": "1.95.8",
1212
"bignumber": "1.1.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import type { IAgentRuntime, Memory, State, HandlerCallback } from "@elizaos/core";
2+
import { RemoteAttestationProvider } from "../providers/remoteAttestationProvider";
3+
4+
function hexToUint8Array(hex: string) {
5+
hex = hex.trim();
6+
if (!hex) {
7+
throw new Error("Invalid hex string");
8+
}
9+
if (hex.startsWith("0x")) {
10+
hex = hex.substring(2);
11+
}
12+
if (hex.length % 2 !== 0) {
13+
throw new Error("Invalid hex string");
14+
}
15+
16+
const array = new Uint8Array(hex.length / 2);
17+
for (let i = 0; i < hex.length; i += 2) {
18+
const byte = parseInt(hex.slice(i, i + 2), 16);
19+
if (isNaN(byte)) {
20+
throw new Error("Invalid hex string");
21+
}
22+
array[i / 2] = byte;
23+
}
24+
return array;
25+
}
26+
27+
async function uploadUint8Array(data: Uint8Array) {
28+
const blob = new Blob([data], { type: "application/octet-stream" });
29+
const file = new File([blob], "quote.bin", {
30+
type: "application/octet-stream",
31+
});
32+
const formData = new FormData();
33+
formData.append("file", file);
34+
35+
return await fetch("https://proof.t16z.com/api/upload", {
36+
method: "POST",
37+
body: formData,
38+
});
39+
}
40+
41+
export const remoteAttestationAction = {
42+
name: "REMOTE_ATTESTATION",
43+
similes: ["REMOTE_ATTESTATION", "TEE_REMOTE_ATTESTATION", "TEE_ATTESTATION"],
44+
description: "Generate a remote attestation to prove that the agent is running in a TEE",
45+
handler: async (
46+
runtime: IAgentRuntime,
47+
_message: Memory,
48+
_state: State,
49+
_options: { [key: string]: unknown },
50+
callback: HandlerCallback,
51+
) => {
52+
try {
53+
// Get the remote attestation of the agentId
54+
const agentId = runtime.agentId;
55+
const agentName = runtime.character.name;
56+
const teeMode = runtime.getSetting("TEE_MODE");
57+
const provider = new RemoteAttestationProvider(teeMode);
58+
const attestation = await provider.generateAttestation(agentId, 'raw');
59+
const attestationData = hexToUint8Array(attestation.quote);
60+
const response = await uploadUint8Array(attestationData);
61+
const data = await response.json();
62+
callback({
63+
text: `Uploading attestation to proof.t16z.com...`,
64+
action: "NONE",
65+
});
66+
callback({
67+
text: `Attestation report for ${agentName}: https://proof.t16z.com/reports/${data.checksum}`,
68+
action: "NONE",
69+
});
70+
return true;
71+
} catch (error) {
72+
console.error("Failed to fetch remote attestation: ", error);
73+
return false;
74+
}
75+
},
76+
validate: async (_runtime: IAgentRuntime) => {
77+
return true;
78+
},
79+
examples: [
80+
[
81+
{
82+
user: "{{user1}}",
83+
content: {
84+
text: "If you are running in a TEE, generate a remote attestation",
85+
},
86+
},
87+
{
88+
user: "{{user2}}",
89+
content: {
90+
text: "I'm running in a TEE, generate a remote attestation",
91+
action: "REMOTE_ATTESTATION",
92+
},
93+
},
94+
{
95+
user: "{{user2}}",
96+
content: {
97+
text: `Sure thing, here is my attestation report
98+
https://proof.t16z.com/reports/a0fd21c0602374388addb2f5272ab61008f5adf9c9b9a85978b799accb9c3442
99+
`,
100+
},
101+
},
102+
],
103+
],
104+
};

‎packages/plugin-tee/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Plugin } from "@elizaos/core";
22
import { remoteAttestationProvider } from "./providers/remoteAttestationProvider";
33
import { deriveKeyProvider } from "./providers/deriveKeyProvider";
4+
import { remoteAttestationAction } from "./actions/remoteAttestation";
45

56
export { DeriveKeyProvider } from "./providers/deriveKeyProvider";
67
export { RemoteAttestationProvider } from "./providers/remoteAttestationProvider";
@@ -12,6 +13,7 @@ export const teePlugin: Plugin = {
1213
"TEE plugin with actions to generate remote attestations and derive keys",
1314
actions: [
1415
/* custom actions */
16+
remoteAttestationAction,
1517
],
1618
evaluators: [
1719
/* custom evaluators */

‎packages/plugin-tee/src/providers/remoteAttestationProvider.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { IAgentRuntime, Memory, Provider, State } from "@elizaos/core";
2-
import { TdxQuoteResponse, TappdClient } from "@phala/dstack-sdk";
2+
import { TdxQuoteResponse, TappdClient, TdxQuoteHashAlgorithms } from "@phala/dstack-sdk";
33
import { RemoteAttestationQuote, TEEMode } from "../types/tee";
44

55
class RemoteAttestationProvider {
@@ -38,12 +38,13 @@ class RemoteAttestationProvider {
3838
}
3939

4040
async generateAttestation(
41-
reportData: string
41+
reportData: string,
42+
hashAlgorithm?: TdxQuoteHashAlgorithms
4243
): Promise<RemoteAttestationQuote> {
4344
try {
4445
console.log("Generating attestation for: ", reportData);
4546
const tdxQuote: TdxQuoteResponse =
46-
await this.client.tdxQuote(reportData);
47+
await this.client.tdxQuote(reportData, hashAlgorithm);
4748
const rtmrs = tdxQuote.replayRtmrs();
4849
console.log(
4950
`rtmr0: ${rtmrs[0]}\nrtmr1: ${rtmrs[1]}\nrtmr2: ${rtmrs[2]}\nrtmr3: ${rtmrs[3]}f`
@@ -74,7 +75,7 @@ const remoteAttestationProvider: Provider = {
7475

7576
try {
7677
console.log("Generating attestation for: ", agentId);
77-
const attestation = await provider.generateAttestation(agentId);
78+
const attestation = await provider.generateAttestation(agentId, 'raw');
7879
return `Your Agent's remote attestation is: ${JSON.stringify(attestation)}`;
7980
} catch (error) {
8081
console.error("Error in remote attestation provider:", error);

‎pnpm-lock.yaml

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.