@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.cjs
CHANGED
|
@@ -2034,6 +2034,23 @@ async function listModels(opts) {
|
|
|
2034
2034
|
}));
|
|
2035
2035
|
}
|
|
2036
2036
|
var RECEIPT_ANCHORED_SUFFIX = "::anchor::ReceiptAnchored";
|
|
2037
|
+
function normalizeClaims(claims) {
|
|
2038
|
+
if (!claims) {
|
|
2039
|
+
return [];
|
|
2040
|
+
}
|
|
2041
|
+
if (Array.isArray(claims)) {
|
|
2042
|
+
return claims.filter((c) => c.name).map((c) => ({
|
|
2043
|
+
name: c.name,
|
|
2044
|
+
status: c.status ?? "unknown",
|
|
2045
|
+
source: c.source
|
|
2046
|
+
}));
|
|
2047
|
+
}
|
|
2048
|
+
return Object.entries(claims).map(([name, v]) => ({
|
|
2049
|
+
name,
|
|
2050
|
+
status: v?.status ?? "unknown",
|
|
2051
|
+
source: v?.source
|
|
2052
|
+
}));
|
|
2053
|
+
}
|
|
2037
2054
|
function fullnodeUrl(network) {
|
|
2038
2055
|
return network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
|
|
2039
2056
|
}
|
|
@@ -2096,6 +2113,64 @@ function verifyReceiptSignature(receipt, signingKeyHex) {
|
|
|
2096
2113
|
return false;
|
|
2097
2114
|
}
|
|
2098
2115
|
}
|
|
2116
|
+
async function verifyTdxQuote(base, model, receiptWorkloadId) {
|
|
2117
|
+
let nonce;
|
|
2118
|
+
try {
|
|
2119
|
+
nonce = utils$1.bytesToHex(globalThis.crypto.getRandomValues(new Uint8Array(32)));
|
|
2120
|
+
} catch {
|
|
2121
|
+
return { status: "skip", detail: "no secure RNG available", forged: false };
|
|
2122
|
+
}
|
|
2123
|
+
let report;
|
|
2124
|
+
try {
|
|
2125
|
+
const res = await fetch(
|
|
2126
|
+
`${base}/aci/attestation?model=${encodeURIComponent(model)}&nonce=${nonce}`
|
|
2127
|
+
);
|
|
2128
|
+
if (res.ok) {
|
|
2129
|
+
report = (await res.json()).report;
|
|
2130
|
+
}
|
|
2131
|
+
} catch {
|
|
2132
|
+
}
|
|
2133
|
+
const quoteHex = report?.attestation?.evidence?.quote;
|
|
2134
|
+
if (!quoteHex) {
|
|
2135
|
+
return {
|
|
2136
|
+
status: "skip",
|
|
2137
|
+
detail: "attestation report (with quote) unavailable \u2014 pass --model?",
|
|
2138
|
+
forged: false
|
|
2139
|
+
};
|
|
2140
|
+
}
|
|
2141
|
+
try {
|
|
2142
|
+
const { getCollateralAndVerify } = await import('@phala/dcap-qvl');
|
|
2143
|
+
const quoteBytes = utils$1.hexToBytes(quoteHex.replace(/^0x/, ""));
|
|
2144
|
+
const vr = await getCollateralAndVerify(quoteBytes);
|
|
2145
|
+
const td = vr.report.asTd10() ?? vr.report.asTd15()?.base ?? null;
|
|
2146
|
+
const reportData = td?.reportData;
|
|
2147
|
+
const signingAddr = report?.signing_address?.replace(/^0x/, "").toLowerCase();
|
|
2148
|
+
const addrBound = Boolean(
|
|
2149
|
+
reportData && signingAddr && utils$1.bytesToHex(reportData.slice(0, 20)) === signingAddr
|
|
2150
|
+
);
|
|
2151
|
+
const workloadMatch = report?.workload_id === receiptWorkloadId;
|
|
2152
|
+
const tcb = vr.status;
|
|
2153
|
+
const tcbBad = tcb === "Revoked" || tcb === "Unknown";
|
|
2154
|
+
const forged = !(addrBound && workloadMatch) || tcbBad;
|
|
2155
|
+
let detail;
|
|
2156
|
+
if (forged && tcbBad) {
|
|
2157
|
+
detail = `genuine TDX but TCB ${tcb}`;
|
|
2158
|
+
} else if (!addrBound) {
|
|
2159
|
+
detail = "report_data does NOT commit the report's signing address";
|
|
2160
|
+
} else if (!workloadMatch) {
|
|
2161
|
+
detail = "quote workload_id does not match the receipt's";
|
|
2162
|
+
} else {
|
|
2163
|
+
detail = `genuine Intel TDX (verified vs Intel collateral), TCB ${tcb}; report_data commits the attested signing address`;
|
|
2164
|
+
}
|
|
2165
|
+
return { status: forged ? "fail" : "pass", forged, tcbStatus: tcb, detail };
|
|
2166
|
+
} catch (e) {
|
|
2167
|
+
return {
|
|
2168
|
+
status: "fail",
|
|
2169
|
+
forged: false,
|
|
2170
|
+
detail: `could not verify the quote: ${e instanceof Error ? e.message : "error"}`
|
|
2171
|
+
};
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2099
2174
|
async function verifyReceipt(receiptId, opts = {}) {
|
|
2100
2175
|
const base = opts.apiBase ?? DEFAULT_API_BASE;
|
|
2101
2176
|
const network = opts.network ?? "mainnet";
|
|
@@ -2127,6 +2202,7 @@ async function verifyReceipt(receiptId, opts = {}) {
|
|
|
2127
2202
|
});
|
|
2128
2203
|
const upstreamEv = receipt.event_log.find((e) => e.type === "upstream.verified");
|
|
2129
2204
|
const upstreamOk = upstreamEv?.result === "verified";
|
|
2205
|
+
const claims = normalizeClaims(upstreamEv?.claims);
|
|
2130
2206
|
checks.push({
|
|
2131
2207
|
name: "Confidential upstream",
|
|
2132
2208
|
status: upstreamEv ? upstreamOk ? "pass" : "fail" : "skip",
|
|
@@ -2219,17 +2295,42 @@ async function verifyReceipt(receiptId, opts = {}) {
|
|
|
2219
2295
|
detail: sigDetail,
|
|
2220
2296
|
trust: sigStatus === "skip" ? "roadmap" : "trustless"
|
|
2221
2297
|
});
|
|
2298
|
+
let quoteForged = false;
|
|
2299
|
+
if (opts.skipQuote) {
|
|
2300
|
+
checks.push({
|
|
2301
|
+
name: "TDX quote (DCAP)",
|
|
2302
|
+
status: "skip",
|
|
2303
|
+
detail: "skipped (--quick)",
|
|
2304
|
+
trust: "trustless"
|
|
2305
|
+
});
|
|
2306
|
+
} else {
|
|
2307
|
+
const q = await verifyTdxQuote(
|
|
2308
|
+
base,
|
|
2309
|
+
opts.model ?? "phala/glm-5.2",
|
|
2310
|
+
workloadId ?? ""
|
|
2311
|
+
);
|
|
2312
|
+
quoteForged = q.forged;
|
|
2313
|
+
checks.push({
|
|
2314
|
+
name: "TDX quote (DCAP)",
|
|
2315
|
+
status: q.status,
|
|
2316
|
+
detail: q.detail,
|
|
2317
|
+
trust: "trustless"
|
|
2318
|
+
});
|
|
2319
|
+
}
|
|
2222
2320
|
return {
|
|
2223
2321
|
receiptId,
|
|
2224
|
-
verified: Boolean(wireHash && workloadId) && anchorVerified && !signatureForged,
|
|
2322
|
+
verified: Boolean(wireHash && workloadId) && anchorVerified && !signatureForged && !quoteForged,
|
|
2225
2323
|
anchorVerified,
|
|
2226
2324
|
checks,
|
|
2227
2325
|
wireHash,
|
|
2228
2326
|
workloadId,
|
|
2229
2327
|
upstream: upstreamEv ? {
|
|
2230
2328
|
provider: upstreamEv.provider ?? upstreamEv.upstream_name,
|
|
2329
|
+
modelId: upstreamEv.model_id,
|
|
2231
2330
|
result: upstreamEv.result,
|
|
2232
|
-
tcbStatus: upstreamEv.tcb_status
|
|
2331
|
+
tcbStatus: upstreamEv.tcb_status,
|
|
2332
|
+
sessionId: upstreamEv.session_id,
|
|
2333
|
+
claims: claims.length > 0 ? claims : void 0
|
|
2233
2334
|
} : void 0,
|
|
2234
2335
|
anchor
|
|
2235
2336
|
};
|