@t2000/sdk 5.18.0 → 5.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +103 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -6
- package/dist/index.d.ts +20 -6
- package/dist/index.js +103 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.d.cts
CHANGED
|
@@ -76,6 +76,22 @@ interface VerifyAnchor {
|
|
|
76
76
|
anchoredBy?: string;
|
|
77
77
|
explorer: string;
|
|
78
78
|
}
|
|
79
|
+
/** A typed TCB claim from the attested upstream (dstack ACI §tcb-and-claims). */
|
|
80
|
+
interface UpstreamClaim {
|
|
81
|
+
name: string;
|
|
82
|
+
status: string;
|
|
83
|
+
source?: string;
|
|
84
|
+
}
|
|
85
|
+
interface VerifyUpstream {
|
|
86
|
+
provider?: string;
|
|
87
|
+
modelId?: string;
|
|
88
|
+
result?: string;
|
|
89
|
+
tcbStatus?: string;
|
|
90
|
+
/** The attested-session id (`as_…`) — resolve at GET /v1/aci/sessions/{id}. */
|
|
91
|
+
sessionId?: string;
|
|
92
|
+
/** Typed TCB claims (tee_attested, tcb_up_to_date, gpu_attested, …). */
|
|
93
|
+
claims?: UpstreamClaim[];
|
|
94
|
+
}
|
|
79
95
|
interface VerifyResult {
|
|
80
96
|
receiptId: string;
|
|
81
97
|
/** True iff the receipt resolved AND its on-chain Sui anchor matches. */
|
|
@@ -85,11 +101,7 @@ interface VerifyResult {
|
|
|
85
101
|
checks: VerifyCheck[];
|
|
86
102
|
wireHash?: string;
|
|
87
103
|
workloadId?: string;
|
|
88
|
-
upstream?:
|
|
89
|
-
provider?: string;
|
|
90
|
-
result?: string;
|
|
91
|
-
tcbStatus?: string;
|
|
92
|
-
};
|
|
104
|
+
upstream?: VerifyUpstream;
|
|
93
105
|
anchor?: VerifyAnchor;
|
|
94
106
|
}
|
|
95
107
|
interface VerifyOptions {
|
|
@@ -100,6 +112,8 @@ interface VerifyOptions {
|
|
|
100
112
|
/** Confidential model id for fetching the attested receipt-signing key
|
|
101
113
|
* (default `phala/glm-5.2`; the gateway key is workload-wide). */
|
|
102
114
|
model?: string;
|
|
115
|
+
/** Skip the local DCAP quote verification (the slower, network-bound check). */
|
|
116
|
+
skipQuote?: boolean;
|
|
103
117
|
}
|
|
104
118
|
/**
|
|
105
119
|
* Verify a confidential response by its receipt id. Reads the signed receipt
|
|
@@ -1070,4 +1084,4 @@ declare function fullHandle(label: string, parentName?: string): string;
|
|
|
1070
1084
|
*/
|
|
1071
1085
|
declare function displayHandle(label: string, parentName?: string): string;
|
|
1072
1086
|
|
|
1073
|
-
export { AGENT_ID_PARENT, AGENT_ID_PARENT_NAME, AGENT_ID_PARENT_NFT_ID, AUDRIC_PARENT, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type ApiModel, type AppenderContext, BalanceResponse, type BuildAddLeafParams, type BuildRevokeLeafParams, type ChatMessage, type ChatParams, type ChatResult, type ChatUsage, type CheckStatus, type ComposeTxOptions, type ComposeTxResult, DEFAULT_API_BASE, type DailySpend, DepositInfo, InvalidAddressError, type LabelValidationResult, type LimitAssertInput, LimitEnforcer, LimitExceededError, type LimitKind, type LimitOperation, type LimitsConfig, type LimitsFile, type NormalizedAddress, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SendResult, type SendTransferInput, SendableAsset, type StepPreview, SuinsNotRegisteredError, type SuinsParent, SuinsRpcError, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, type TrustMode, type VerifyAnchor, type VerifyCheck, type VerifyOptions, type VerifyResult, WRITE_APPENDER_REGISTRY, type WriteStep, type WriteToolName, ZkLoginProof, approxUsdValue, assertLimitConfig, buildAddLeafTx, buildRevokeLeafTx, chatCompletion, chatCompletionStream, clearLimits, composeTx, dailySpentToday, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fullHandle, generateKeypair, getAddress, getLimits, getSponsoredSwapProviders, getSwapQuote, hasLimits, keypairFromPrivateKey, listModels, loadKey, looksLikeSuiNs, normalizeAddressInput, queryBalance, readLimitsFile, recordDailySpend, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, saveBech32, saveKey, setLimits, validateLabel, verifyReceipt, walletExists, writeLimitsFile };
|
|
1087
|
+
export { AGENT_ID_PARENT, AGENT_ID_PARENT_NAME, AGENT_ID_PARENT_NFT_ID, AUDRIC_PARENT, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type ApiModel, type AppenderContext, BalanceResponse, type BuildAddLeafParams, type BuildRevokeLeafParams, type ChatMessage, type ChatParams, type ChatResult, type ChatUsage, type CheckStatus, type ComposeTxOptions, type ComposeTxResult, DEFAULT_API_BASE, type DailySpend, DepositInfo, InvalidAddressError, type LabelValidationResult, type LimitAssertInput, LimitEnforcer, LimitExceededError, type LimitKind, type LimitOperation, type LimitsConfig, type LimitsFile, type NormalizedAddress, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SendResult, type SendTransferInput, SendableAsset, type StepPreview, SuinsNotRegisteredError, type SuinsParent, SuinsRpcError, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, type TrustMode, type UpstreamClaim, type VerifyAnchor, type VerifyCheck, type VerifyOptions, type VerifyResult, type VerifyUpstream, WRITE_APPENDER_REGISTRY, type WriteStep, type WriteToolName, ZkLoginProof, approxUsdValue, assertLimitConfig, buildAddLeafTx, buildRevokeLeafTx, chatCompletion, chatCompletionStream, clearLimits, composeTx, dailySpentToday, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fullHandle, generateKeypair, getAddress, getLimits, getSponsoredSwapProviders, getSwapQuote, hasLimits, keypairFromPrivateKey, listModels, loadKey, looksLikeSuiNs, normalizeAddressInput, queryBalance, readLimitsFile, recordDailySpend, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, saveBech32, saveKey, setLimits, validateLabel, verifyReceipt, walletExists, writeLimitsFile };
|
package/dist/index.d.ts
CHANGED
|
@@ -76,6 +76,22 @@ interface VerifyAnchor {
|
|
|
76
76
|
anchoredBy?: string;
|
|
77
77
|
explorer: string;
|
|
78
78
|
}
|
|
79
|
+
/** A typed TCB claim from the attested upstream (dstack ACI §tcb-and-claims). */
|
|
80
|
+
interface UpstreamClaim {
|
|
81
|
+
name: string;
|
|
82
|
+
status: string;
|
|
83
|
+
source?: string;
|
|
84
|
+
}
|
|
85
|
+
interface VerifyUpstream {
|
|
86
|
+
provider?: string;
|
|
87
|
+
modelId?: string;
|
|
88
|
+
result?: string;
|
|
89
|
+
tcbStatus?: string;
|
|
90
|
+
/** The attested-session id (`as_…`) — resolve at GET /v1/aci/sessions/{id}. */
|
|
91
|
+
sessionId?: string;
|
|
92
|
+
/** Typed TCB claims (tee_attested, tcb_up_to_date, gpu_attested, …). */
|
|
93
|
+
claims?: UpstreamClaim[];
|
|
94
|
+
}
|
|
79
95
|
interface VerifyResult {
|
|
80
96
|
receiptId: string;
|
|
81
97
|
/** True iff the receipt resolved AND its on-chain Sui anchor matches. */
|
|
@@ -85,11 +101,7 @@ interface VerifyResult {
|
|
|
85
101
|
checks: VerifyCheck[];
|
|
86
102
|
wireHash?: string;
|
|
87
103
|
workloadId?: string;
|
|
88
|
-
upstream?:
|
|
89
|
-
provider?: string;
|
|
90
|
-
result?: string;
|
|
91
|
-
tcbStatus?: string;
|
|
92
|
-
};
|
|
104
|
+
upstream?: VerifyUpstream;
|
|
93
105
|
anchor?: VerifyAnchor;
|
|
94
106
|
}
|
|
95
107
|
interface VerifyOptions {
|
|
@@ -100,6 +112,8 @@ interface VerifyOptions {
|
|
|
100
112
|
/** Confidential model id for fetching the attested receipt-signing key
|
|
101
113
|
* (default `phala/glm-5.2`; the gateway key is workload-wide). */
|
|
102
114
|
model?: string;
|
|
115
|
+
/** Skip the local DCAP quote verification (the slower, network-bound check). */
|
|
116
|
+
skipQuote?: boolean;
|
|
103
117
|
}
|
|
104
118
|
/**
|
|
105
119
|
* Verify a confidential response by its receipt id. Reads the signed receipt
|
|
@@ -1070,4 +1084,4 @@ declare function fullHandle(label: string, parentName?: string): string;
|
|
|
1070
1084
|
*/
|
|
1071
1085
|
declare function displayHandle(label: string, parentName?: string): string;
|
|
1072
1086
|
|
|
1073
|
-
export { AGENT_ID_PARENT, AGENT_ID_PARENT_NAME, AGENT_ID_PARENT_NFT_ID, AUDRIC_PARENT, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type ApiModel, type AppenderContext, BalanceResponse, type BuildAddLeafParams, type BuildRevokeLeafParams, type ChatMessage, type ChatParams, type ChatResult, type ChatUsage, type CheckStatus, type ComposeTxOptions, type ComposeTxResult, DEFAULT_API_BASE, type DailySpend, DepositInfo, InvalidAddressError, type LabelValidationResult, type LimitAssertInput, LimitEnforcer, LimitExceededError, type LimitKind, type LimitOperation, type LimitsConfig, type LimitsFile, type NormalizedAddress, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SendResult, type SendTransferInput, SendableAsset, type StepPreview, SuinsNotRegisteredError, type SuinsParent, SuinsRpcError, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, type TrustMode, type VerifyAnchor, type VerifyCheck, type VerifyOptions, type VerifyResult, WRITE_APPENDER_REGISTRY, type WriteStep, type WriteToolName, ZkLoginProof, approxUsdValue, assertLimitConfig, buildAddLeafTx, buildRevokeLeafTx, chatCompletion, chatCompletionStream, clearLimits, composeTx, dailySpentToday, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fullHandle, generateKeypair, getAddress, getLimits, getSponsoredSwapProviders, getSwapQuote, hasLimits, keypairFromPrivateKey, listModels, loadKey, looksLikeSuiNs, normalizeAddressInput, queryBalance, readLimitsFile, recordDailySpend, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, saveBech32, saveKey, setLimits, validateLabel, verifyReceipt, walletExists, writeLimitsFile };
|
|
1087
|
+
export { AGENT_ID_PARENT, AGENT_ID_PARENT_NAME, AGENT_ID_PARENT_NFT_ID, AUDRIC_PARENT, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type ApiModel, type AppenderContext, BalanceResponse, type BuildAddLeafParams, type BuildRevokeLeafParams, type ChatMessage, type ChatParams, type ChatResult, type ChatUsage, type CheckStatus, type ComposeTxOptions, type ComposeTxResult, DEFAULT_API_BASE, type DailySpend, DepositInfo, InvalidAddressError, type LabelValidationResult, type LimitAssertInput, LimitEnforcer, LimitExceededError, type LimitKind, type LimitOperation, type LimitsConfig, type LimitsFile, type NormalizedAddress, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SendResult, type SendTransferInput, SendableAsset, type StepPreview, SuinsNotRegisteredError, type SuinsParent, SuinsRpcError, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, type TrustMode, type UpstreamClaim, type VerifyAnchor, type VerifyCheck, type VerifyOptions, type VerifyResult, type VerifyUpstream, WRITE_APPENDER_REGISTRY, type WriteStep, type WriteToolName, ZkLoginProof, approxUsdValue, assertLimitConfig, buildAddLeafTx, buildRevokeLeafTx, chatCompletion, chatCompletionStream, clearLimits, composeTx, dailySpentToday, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fullHandle, generateKeypair, getAddress, getLimits, getSponsoredSwapProviders, getSwapQuote, hasLimits, keypairFromPrivateKey, listModels, loadKey, looksLikeSuiNs, normalizeAddressInput, queryBalance, readLimitsFile, recordDailySpend, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, saveBech32, saveKey, setLimits, validateLabel, verifyReceipt, walletExists, writeLimitsFile };
|
package/dist/index.js
CHANGED
|
@@ -2028,6 +2028,23 @@ async function listModels(opts) {
|
|
|
2028
2028
|
}));
|
|
2029
2029
|
}
|
|
2030
2030
|
var RECEIPT_ANCHORED_SUFFIX = "::anchor::ReceiptAnchored";
|
|
2031
|
+
function normalizeClaims(claims) {
|
|
2032
|
+
if (!claims) {
|
|
2033
|
+
return [];
|
|
2034
|
+
}
|
|
2035
|
+
if (Array.isArray(claims)) {
|
|
2036
|
+
return claims.filter((c) => c.name).map((c) => ({
|
|
2037
|
+
name: c.name,
|
|
2038
|
+
status: c.status ?? "unknown",
|
|
2039
|
+
source: c.source
|
|
2040
|
+
}));
|
|
2041
|
+
}
|
|
2042
|
+
return Object.entries(claims).map(([name, v]) => ({
|
|
2043
|
+
name,
|
|
2044
|
+
status: v?.status ?? "unknown",
|
|
2045
|
+
source: v?.source
|
|
2046
|
+
}));
|
|
2047
|
+
}
|
|
2031
2048
|
function fullnodeUrl(network) {
|
|
2032
2049
|
return network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
|
|
2033
2050
|
}
|
|
@@ -2090,6 +2107,64 @@ function verifyReceiptSignature(receipt, signingKeyHex) {
|
|
|
2090
2107
|
return false;
|
|
2091
2108
|
}
|
|
2092
2109
|
}
|
|
2110
|
+
async function verifyTdxQuote(base, model, receiptWorkloadId) {
|
|
2111
|
+
let nonce;
|
|
2112
|
+
try {
|
|
2113
|
+
nonce = bytesToHex(globalThis.crypto.getRandomValues(new Uint8Array(32)));
|
|
2114
|
+
} catch {
|
|
2115
|
+
return { status: "skip", detail: "no secure RNG available", forged: false };
|
|
2116
|
+
}
|
|
2117
|
+
let report;
|
|
2118
|
+
try {
|
|
2119
|
+
const res = await fetch(
|
|
2120
|
+
`${base}/aci/attestation?model=${encodeURIComponent(model)}&nonce=${nonce}`
|
|
2121
|
+
);
|
|
2122
|
+
if (res.ok) {
|
|
2123
|
+
report = (await res.json()).report;
|
|
2124
|
+
}
|
|
2125
|
+
} catch {
|
|
2126
|
+
}
|
|
2127
|
+
const quoteHex = report?.attestation?.evidence?.quote;
|
|
2128
|
+
if (!quoteHex) {
|
|
2129
|
+
return {
|
|
2130
|
+
status: "skip",
|
|
2131
|
+
detail: "attestation report (with quote) unavailable \u2014 pass --model?",
|
|
2132
|
+
forged: false
|
|
2133
|
+
};
|
|
2134
|
+
}
|
|
2135
|
+
try {
|
|
2136
|
+
const { getCollateralAndVerify } = await import('@phala/dcap-qvl');
|
|
2137
|
+
const quoteBytes = hexToBytes(quoteHex.replace(/^0x/, ""));
|
|
2138
|
+
const vr = await getCollateralAndVerify(quoteBytes);
|
|
2139
|
+
const td = vr.report.asTd10() ?? vr.report.asTd15()?.base ?? null;
|
|
2140
|
+
const reportData = td?.reportData;
|
|
2141
|
+
const signingAddr = report?.signing_address?.replace(/^0x/, "").toLowerCase();
|
|
2142
|
+
const addrBound = Boolean(
|
|
2143
|
+
reportData && signingAddr && bytesToHex(reportData.slice(0, 20)) === signingAddr
|
|
2144
|
+
);
|
|
2145
|
+
const workloadMatch = report?.workload_id === receiptWorkloadId;
|
|
2146
|
+
const tcb = vr.status;
|
|
2147
|
+
const tcbBad = tcb === "Revoked" || tcb === "Unknown";
|
|
2148
|
+
const forged = !(addrBound && workloadMatch) || tcbBad;
|
|
2149
|
+
let detail;
|
|
2150
|
+
if (forged && tcbBad) {
|
|
2151
|
+
detail = `genuine TDX but TCB ${tcb}`;
|
|
2152
|
+
} else if (!addrBound) {
|
|
2153
|
+
detail = "report_data does NOT commit the report's signing address";
|
|
2154
|
+
} else if (!workloadMatch) {
|
|
2155
|
+
detail = "quote workload_id does not match the receipt's";
|
|
2156
|
+
} else {
|
|
2157
|
+
detail = `genuine Intel TDX (verified vs Intel collateral), TCB ${tcb}; report_data commits the attested signing address`;
|
|
2158
|
+
}
|
|
2159
|
+
return { status: forged ? "fail" : "pass", forged, tcbStatus: tcb, detail };
|
|
2160
|
+
} catch (e) {
|
|
2161
|
+
return {
|
|
2162
|
+
status: "fail",
|
|
2163
|
+
forged: false,
|
|
2164
|
+
detail: `could not verify the quote: ${e instanceof Error ? e.message : "error"}`
|
|
2165
|
+
};
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2093
2168
|
async function verifyReceipt(receiptId, opts = {}) {
|
|
2094
2169
|
const base = opts.apiBase ?? DEFAULT_API_BASE;
|
|
2095
2170
|
const network = opts.network ?? "mainnet";
|
|
@@ -2121,6 +2196,7 @@ async function verifyReceipt(receiptId, opts = {}) {
|
|
|
2121
2196
|
});
|
|
2122
2197
|
const upstreamEv = receipt.event_log.find((e) => e.type === "upstream.verified");
|
|
2123
2198
|
const upstreamOk = upstreamEv?.result === "verified";
|
|
2199
|
+
const claims = normalizeClaims(upstreamEv?.claims);
|
|
2124
2200
|
checks.push({
|
|
2125
2201
|
name: "Confidential upstream",
|
|
2126
2202
|
status: upstreamEv ? upstreamOk ? "pass" : "fail" : "skip",
|
|
@@ -2213,17 +2289,42 @@ async function verifyReceipt(receiptId, opts = {}) {
|
|
|
2213
2289
|
detail: sigDetail,
|
|
2214
2290
|
trust: sigStatus === "skip" ? "roadmap" : "trustless"
|
|
2215
2291
|
});
|
|
2292
|
+
let quoteForged = false;
|
|
2293
|
+
if (opts.skipQuote) {
|
|
2294
|
+
checks.push({
|
|
2295
|
+
name: "TDX quote (DCAP)",
|
|
2296
|
+
status: "skip",
|
|
2297
|
+
detail: "skipped (--quick)",
|
|
2298
|
+
trust: "trustless"
|
|
2299
|
+
});
|
|
2300
|
+
} else {
|
|
2301
|
+
const q = await verifyTdxQuote(
|
|
2302
|
+
base,
|
|
2303
|
+
opts.model ?? "phala/glm-5.2",
|
|
2304
|
+
workloadId ?? ""
|
|
2305
|
+
);
|
|
2306
|
+
quoteForged = q.forged;
|
|
2307
|
+
checks.push({
|
|
2308
|
+
name: "TDX quote (DCAP)",
|
|
2309
|
+
status: q.status,
|
|
2310
|
+
detail: q.detail,
|
|
2311
|
+
trust: "trustless"
|
|
2312
|
+
});
|
|
2313
|
+
}
|
|
2216
2314
|
return {
|
|
2217
2315
|
receiptId,
|
|
2218
|
-
verified: Boolean(wireHash && workloadId) && anchorVerified && !signatureForged,
|
|
2316
|
+
verified: Boolean(wireHash && workloadId) && anchorVerified && !signatureForged && !quoteForged,
|
|
2219
2317
|
anchorVerified,
|
|
2220
2318
|
checks,
|
|
2221
2319
|
wireHash,
|
|
2222
2320
|
workloadId,
|
|
2223
2321
|
upstream: upstreamEv ? {
|
|
2224
2322
|
provider: upstreamEv.provider ?? upstreamEv.upstream_name,
|
|
2323
|
+
modelId: upstreamEv.model_id,
|
|
2225
2324
|
result: upstreamEv.result,
|
|
2226
|
-
tcbStatus: upstreamEv.tcb_status
|
|
2325
|
+
tcbStatus: upstreamEv.tcb_status,
|
|
2326
|
+
sessionId: upstreamEv.session_id,
|
|
2327
|
+
claims: claims.length > 0 ? claims : void 0
|
|
2227
2328
|
} : void 0,
|
|
2228
2329
|
anchor
|
|
2229
2330
|
};
|