Skip to content

Commit 0c2be45

Browse files
authored
Merge pull request #276 from smartcontractkit/rtinianov_teeRuntime
Add the TEERuntime
2 parents c26b561 + a7c7cff commit 0c2be45

16 files changed

Lines changed: 663 additions & 56 deletions

File tree

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[submodule "submodules/chainlink-protos"]
22
path = submodules/chainlink-protos
33
url = https://github.com/smartcontractkit/chainlink-protos.git
4-
branch = capabilities-development
4+
branch = capabilities-development

packages/cre-sdk/src/generated-sdk/capabilities/networking/http/v1alpha/client_sdk_gen.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
type Response,
77
ResponseSchema,
88
} from '@cre/generated/capabilities/networking/http/v1alpha/client_pb'
9-
import type { NodeRuntime, Runtime } from '@cre/sdk'
9+
import type { NodeRuntime, Runtime, TeeRuntime } from '@cre/sdk'
1010
import { Report } from '@cre/sdk/report'
1111
import type { ConsensusAggregation, PrimitiveTypes, UnwrapOptions } from '@cre/sdk/utils'
1212
import type { CapabilityInput } from '@cre/sdk/utils/types/no-excess'
@@ -37,10 +37,18 @@ export class ClientCapability {
3737
static readonly CAPABILITY_NAME = 'http-actions'
3838
static readonly CAPABILITY_VERSION = '1.0.0-alpha'
3939

40+
sendRequest<TInput>(
41+
runtime: TeeRuntime<unknown>,
42+
input: CapabilityInput<TInput, Request, RequestJson>,
43+
): { result: () => Response }
4044
sendRequest<TInput>(
4145
runtime: NodeRuntime<unknown>,
4246
input: CapabilityInput<TInput, Request, RequestJson>,
4347
): { result: () => Response }
48+
sendRequest<TInput>(
49+
runtime: NodeRuntime<unknown> | TeeRuntime<unknown>,
50+
input: CapabilityInput<TInput, Request, RequestJson>,
51+
): { result: () => Response }
4452
sendRequest<TArgs extends unknown[], TOutput>(
4553
runtime: Runtime<unknown>,
4654
fn: (sendRequester: SendRequester, ...args: TArgs) => TOutput,
@@ -59,11 +67,14 @@ export class ClientCapability {
5967
return this.sendRequestSugarHelper(runtime, fn, consensusAggregation, unwrapOptions)
6068
}
6169
// Otherwise, this is the basic call overload
62-
const [runtime, input] = args as [NodeRuntime<unknown>, Request | RequestJson]
70+
const [runtime, input] = args as [
71+
NodeRuntime<unknown> | TeeRuntime<unknown>,
72+
Request | RequestJson,
73+
]
6374
return this.sendRequestCallHelper(runtime, input)
6475
}
6576
private sendRequestCallHelper(
66-
runtime: NodeRuntime<unknown>,
77+
runtime: NodeRuntime<unknown> | TeeRuntime<unknown>,
6778
input: Request | RequestJson,
6879
): { result: () => Response } {
6980
// Handle input conversion - unwrap if it's a wrapped type, convert from JSON if needed

packages/cre-sdk/src/generator/generate-action.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export function generateActionMethod(
1717
capabilityClassName: string,
1818
labels: ProcessedLabel[],
1919
modePrefix: string,
20+
teeEnabled: boolean,
2021
): string {
2122
const capabilityIdLogic = generateCapabilityIdLogic(labels, capabilityClassName)
2223

@@ -47,9 +48,25 @@ export function generateActionMethod(
4748
// - JSON shape -> wrapped in NoExcess so unknown keys (e.g. plain
4849
// `body` instead of `bodyString`) fail at the call boundary even
4950
// when the user lifts the request object into a variable.
50-
const callSig = `<TInput>(runtime: ${modePrefix}Runtime<unknown>, input: CapabilityInput<TInput, ${nativeInputType}, ${jsonInputType}>): {result: () => ${outputType}}`
51-
// Internal impl signature - widest, accepts either form.
52-
const implSig = `(runtime: ${modePrefix}Runtime<unknown>, input: ${nativeInputType} | ${jsonInputType}): {result: () => ${outputType}}`
51+
const basicSig = `<TInput>(runtime: ${modePrefix}Runtime<unknown>, input: CapabilityInput<TInput, ${nativeInputType}, ${jsonInputType}>): {result: () => ${outputType}}`
52+
53+
const callSig = teeEnabled
54+
? basicSig.replace(
55+
`${modePrefix}Runtime<unknown>`,
56+
`${modePrefix}Runtime<unknown> | TeeRuntime<unknown>`,
57+
)
58+
: basicSig
59+
60+
const teeSig = basicSig.replace(`${modePrefix}Runtime<unknown>`, `TeeRuntime<unknown>`)
61+
62+
var nameAndPublicSigs = teeEnabled
63+
? `${methodName}${teeSig}\n${methodName}${basicSig};\n${methodName}${callSig};`
64+
: `${methodName}${callSig};`
65+
66+
// Internal impl signature - widest, accepts either form (and either runtime when TEE is enabled).
67+
const implSig = `(runtime: ${modePrefix}Runtime<unknown>${
68+
teeEnabled ? ' | TeeRuntime<unknown>' : ''
69+
}, input: ${nativeInputType} | ${jsonInputType}): {result: () => ${outputType}}`
5370
const callSigAndBody = `${implSig} {
5471
// Handle input conversion - unwrap if it's a wrapped type, convert from JSON if needed
5572
let payload: ${method.input.name}
@@ -113,7 +130,7 @@ export function generateActionMethod(
113130
: UnwrapOptions<TOutput>,
114131
): (...args: TArgs) => { result: () => TOutput }`
115132
return `
116-
${methodName}${callSig}
133+
${nameAndPublicSigs}
117134
${methodName}${sugarSig}
118135
${methodName}(...args: unknown[]): unknown {
119136
// Check if this is the sugar syntax overload (has function parameter)
@@ -122,7 +139,7 @@ export function generateActionMethod(
122139
return this.${methodName}SugarHelper(runtime, fn, consensusAggregation, unwrapOptions)
123140
}
124141
// Otherwise, this is the basic call overload
125-
const [runtime, input] = args as [${modePrefix}Runtime<unknown>, ${inputTypes.join(' | ')}]
142+
const [runtime, input] = args as [${teeEnabled ? `${modePrefix}Runtime<unknown> | TeeRuntime<unknown>` : `${modePrefix}Runtime<unknown>`}, ${inputTypes.join(' | ')}]
126143
return this.${methodName}CallHelper(runtime, input)
127144
}
128145
private ${methodName}CallHelper${callSigAndBody}
@@ -134,7 +151,13 @@ export function generateActionMethod(
134151
return runtime.runInNodeMode(wrappedFn, consensusAggregation, unwrapOptions)
135152
}`
136153
}
154+
155+
// For DON mode: emit tee + basic overload declarations, then the implementation with its name.
156+
// nameAndPublicSigs is designed for Node mode's dispatcher pattern and must not be reused here.
157+
const donOverloads = teeEnabled
158+
? `${methodName}${teeSig}\n ${methodName}${basicSig}\n `
159+
: `${methodName}${callSig}\n `
160+
137161
return `
138-
${methodName}${callSig}
139-
${methodName}${callSigAndBody}`
162+
${donOverloads}${methodName}${callSigAndBody}`
140163
}

packages/cre-sdk/src/generator/generate-sdk.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,15 @@ import type { GenFile } from '@bufbuild/protobuf/codegenv2'
55
import { Mode } from '@cre/generated/sdk/v1alpha/sdk_pb'
66
import type { CapabilityMetadata } from '@cre/generated/tools/generator/v1alpha/cre_metadata_pb'
77
import {
8+
AdditionalEnvironments,
89
capability,
910
method as methodOption,
1011
} from '@cre/generated/tools/generator/v1alpha/cre_metadata_pb'
1112
import { generateActionMethod } from './generate-action'
1213
import { generateReportWrapper } from './generate-report-wrapper'
1314
import { generateActionSugarClass } from './generate-sugar'
1415
import { generateTriggerClass, generateTriggerMethod } from './generate-trigger'
15-
import {
16-
generateCapabilityIdLogic,
17-
generateConstructorParams,
18-
generateLabelSupport,
19-
processLabels,
20-
} from './label-utils'
16+
import { generateConstructorParams, generateLabelSupport, processLabels } from './label-utils'
2117
import { getImportPathForFile, lowerCaseFirstLetter } from './utils'
2218

2319
const getCapabilityServiceOptions = (service: DescService): CapabilityMetadata | false => {
@@ -96,6 +92,7 @@ export function generateSdk(file: GenFile, outputDir: string) {
9692
})
9793

9894
const modePrefix = capOption.mode === Mode.NODE ? 'Node' : ''
95+
const teeEnabled = capOption.additionalEnvironments.includes(AdditionalEnvironments.TEE)
9996

10097
// Build import statements
10198
// Note: protobuf imports are deferred until after report wrappers are processed,
@@ -122,10 +119,12 @@ export function generateSdk(file: GenFile, outputDir: string) {
122119

123120
if (hasActions) {
124121
if (modePrefix !== '') {
125-
imports.add(`import type { Runtime, ${modePrefix}Runtime } from "@cre/sdk"`)
122+
imports.add(
123+
`import type { Runtime, ${modePrefix}Runtime${teeEnabled ? ', TeeRuntime' : ''} } from "@cre/sdk"`,
124+
)
126125
imports.add(`import { Report } from "@cre/sdk/report"`)
127126
} else {
128-
imports.add(`import type { Runtime } from "@cre/sdk"`)
127+
imports.add(`import type { Runtime ${teeEnabled ? ', TeeRuntime' : ''} } from "@cre/sdk"`)
129128
imports.add(`import { Report } from "@cre/sdk/report"`)
130129
imports.add(`import { hexToBytes } from "@cre/sdk/utils/hex-utils";`)
131130
}
@@ -234,7 +233,14 @@ export function generateSdk(file: GenFile, outputDir: string) {
234233
}
235234

236235
// Generate action method
237-
return generateActionMethod(method, methodName, capabilityClassName, labels, modePrefix)
236+
return generateActionMethod(
237+
method,
238+
methodName,
239+
capabilityClassName,
240+
labels,
241+
modePrefix,
242+
teeEnabled,
243+
)
238244
})
239245
.join('\n')
240246

packages/cre-sdk/src/sdk/cre/index.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { ClientCapability as HTTPClient } from '@cre/generated-sdk/capabilities/
1010
import { HTTPCapability } from '@cre/generated-sdk/capabilities/networking/http/v1alpha/http_sdk_gen'
1111
import { CronCapability } from '@cre/generated-sdk/capabilities/scheduler/cron/v1/cron_sdk_gen'
1212
import { prepareRuntime } from '@cre/sdk/utils/prepare-runtime'
13-
import { handler } from '@cre/sdk/workflow'
13+
import { handler, handlerInTee } from '@cre/sdk/workflow'
1414

1515
/**
1616
* Public exports for the CRE SDK.
@@ -26,6 +26,7 @@ export {
2626
} from '@cre/generated/capabilities/blockchain/solana/v1alpha/client_pb'
2727
export type { Payload as HTTPPayload } from '@cre/generated/capabilities/networking/http/v1alpha/trigger_pb'
2828
export type { Payload as CronPayload } from '@cre/generated/capabilities/scheduler/cron/v1/trigger_pb'
29+
export { TeeType } from '@cre/generated/sdk/v1alpha/sdk_pb'
2930
// Aptos Capability
3031
export {
3132
ClientCapability as AptosClient,
@@ -53,13 +54,20 @@ export {
5354
type SendRequester as HTTPSendRequester,
5455
} from '@cre/generated-sdk/capabilities/networking/http/v1alpha/client_sdk_gen'
5556
export { HTTPCapability } from '@cre/generated-sdk/capabilities/networking/http/v1alpha/http_sdk_gen'
56-
5757
// CRON Capability
5858
export { CronCapability } from '@cre/generated-sdk/capabilities/scheduler/cron/v1/cron_sdk_gen'
59-
6059
// Runtime
61-
export type { NodeRuntime, Runtime } from '@cre/sdk/runtime'
62-
export { handler } from '@cre/sdk/workflow'
60+
export type { NodeRuntime, Runtime, TeeRuntime } from '@cre/sdk/runtime'
61+
export type {
62+
AnyTeeConstraint,
63+
NitroBinding,
64+
NitroRegion,
65+
OneOfTees,
66+
Region,
67+
TeeBinding,
68+
TeeConstraint,
69+
} from '@cre/sdk/workflow'
70+
export { handler, handlerInTee, NITRO_REGIONS, REGIONS } from '@cre/sdk/workflow'
6371

6472
prepareRuntime()
6573

@@ -74,4 +82,5 @@ export const cre = {
7482
SolanaClient,
7583
},
7684
handler,
85+
handlerInTee,
7786
}

packages/cre-sdk/src/sdk/impl/runtime-impl.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import type {
3434
ReportRequest,
3535
ReportRequestJson,
3636
Runtime,
37+
TeeRuntime,
3738
} from '@cre/sdk'
3839
import type { Report } from '@cre/sdk/report'
3940
import {
@@ -462,6 +463,63 @@ export class RuntimeImpl<C> extends BaseRuntimeImpl<C> implements Runtime<C> {
462463
}
463464
}
464465

466+
export class TeeRuntimeImpl<C> implements TeeRuntime<C> {
467+
private readonly runtime: RuntimeImpl<C>
468+
constructor(
469+
public config: C,
470+
public nextCallId: number,
471+
helpers: RuntimeHelpers,
472+
maxResponseSize: bigint,
473+
) {
474+
this.runtime = new RuntimeImpl(config, nextCallId, helpers, maxResponseSize)
475+
}
476+
getSecret(request: SecretRequest | SecretRequestJson): { result: () => Secret } {
477+
return this.runtime.getSecret(request)
478+
}
479+
now(): Date {
480+
return this.runtime.now()
481+
}
482+
483+
log(message: string): void {
484+
this.runtime.log(message)
485+
}
486+
487+
emitMetric(
488+
name: string,
489+
value: number,
490+
type: MetricType,
491+
labels?: Record<string, string>,
492+
): boolean {
493+
return this.runtime.emitMetric(name, value, type, labels)
494+
}
495+
496+
callCapability<I extends Message, O extends Message>({
497+
capabilityId,
498+
method,
499+
payload,
500+
inputSchema,
501+
outputSchema,
502+
}: CallCapabilityParams<I, O>): { result: () => O } {
503+
return this.runtime.callCapability({
504+
capabilityId,
505+
method,
506+
payload,
507+
inputSchema,
508+
outputSchema,
509+
})
510+
}
511+
512+
reportFromDon(input: ReportRequest | ReportRequestJson): {
513+
result: () => Report
514+
} {
515+
return this.runtime.report(input)
516+
}
517+
518+
usingTheDons(): Runtime<C> {
519+
return this.runtime
520+
}
521+
}
522+
465523
/**
466524
* Interface to the WASM host environment.
467525
* Provides low-level access to capabilities, secrets, and utilities.

packages/cre-sdk/src/sdk/runtime.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,28 @@ export interface NodeRuntime<C> extends BaseRuntime<C> {
4747
readonly _isNodeRuntime: true
4848
}
4949

50+
/**
51+
* Runtime for Tee mode execution.
52+
*/
53+
export interface TeeRuntime<C> extends BaseRuntime<C>, SecretsProvider {
54+
/**
55+
* Generates a report from the DON.
56+
* Data requestsed throught this method will be routed outside of the TEE.
57+
*
58+
* @param input - Report request to generate a report from the DON
59+
* @returns Report generated from the DON
60+
*/
61+
reportFromDon(input: ReportRequest | ReportRequestJson): {
62+
result: () => Report
63+
}
64+
65+
/**
66+
* Returns the runtime that makes requests to the CRE DONs.
67+
* Requests made through this runtime will therefore be routed outside of the TEE
68+
*/
69+
usingTheDons(): Runtime<C>
70+
}
71+
5072
/**
5173
* Runtime for DON mode execution.
5274
*/

0 commit comments

Comments
 (0)