@reclaimprotocol/attestor-core 5.0.1-beta.2 → 5.0.1-beta.21
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/browser/resources/attestor-browser.min.mjs +4512 -0
- package/lib/external-rpc/index.js +10399 -3
- package/lib/index.js +8323 -10
- package/package.json +9 -4
- package/lib/avs/abis/avsDirectoryABI.js +0 -343
- package/lib/avs/abis/delegationABI.js +0 -4
- package/lib/avs/abis/registryABI.js +0 -728
- package/lib/avs/client/create-claim-on-avs.js +0 -168
- package/lib/avs/config.js +0 -26
- package/lib/avs/contracts/ReclaimServiceManager.js +0 -0
- package/lib/avs/contracts/common.js +0 -0
- package/lib/avs/contracts/factories/ReclaimServiceManager__factory.js +0 -1183
- package/lib/avs/contracts/factories/index.js +0 -4
- package/lib/avs/contracts/index.js +0 -6
- package/lib/avs/types/index.js +0 -0
- package/lib/avs/utils/contracts.js +0 -53
- package/lib/avs/utils/register.js +0 -74
- package/lib/avs/utils/tasks.js +0 -48
- package/lib/client/create-claim.js +0 -461
- package/lib/client/index.js +0 -3
- package/lib/client/tunnels/make-rpc-tcp-tunnel.js +0 -53
- package/lib/client/tunnels/make-rpc-tls-tunnel.js +0 -127
- package/lib/client/utils/attestor-pool.js +0 -24
- package/lib/client/utils/client-socket.js +0 -120
- package/lib/client/utils/message-handler.js +0 -97
- package/lib/config/index.js +0 -62
- package/lib/external-rpc/benchmark.js +0 -82
- package/lib/external-rpc/event-bus.js +0 -17
- package/lib/external-rpc/global.d.js +0 -0
- package/lib/external-rpc/handle-incoming-msg.js +0 -241
- package/lib/external-rpc/jsc-polyfills/1.js +0 -80
- package/lib/external-rpc/jsc-polyfills/2.js +0 -15
- package/lib/external-rpc/jsc-polyfills/event.js +0 -19
- package/lib/external-rpc/jsc-polyfills/index.js +0 -2
- package/lib/external-rpc/jsc-polyfills/ws.js +0 -83
- package/lib/external-rpc/setup-browser.js +0 -33
- package/lib/external-rpc/setup-jsc.js +0 -22
- package/lib/external-rpc/types.js +0 -0
- package/lib/external-rpc/utils.js +0 -100
- package/lib/external-rpc/zk.js +0 -58
- package/lib/mechain/abis/governanceABI.js +0 -461
- package/lib/mechain/abis/taskABI.js +0 -512
- package/lib/mechain/client/create-claim-on-mechain.js +0 -33
- package/lib/mechain/client/index.js +0 -1
- package/lib/mechain/constants/index.js +0 -8
- package/lib/mechain/index.js +0 -2
- package/lib/mechain/types/index.js +0 -0
- package/lib/proto/api.js +0 -4250
- package/lib/proto/tee-bundle.js +0 -1296
- package/lib/providers/http/index.js +0 -640
- package/lib/providers/http/patch-parse5-tree.js +0 -34
- package/lib/providers/http/utils.js +0 -283
- package/lib/providers/index.js +0 -7
- package/lib/scripts/check-avs-registration.js +0 -28
- package/lib/scripts/fallbacks/crypto.js +0 -4
- package/lib/scripts/fallbacks/empty.js +0 -4
- package/lib/scripts/fallbacks/re2.js +0 -7
- package/lib/scripts/fallbacks/snarkjs.js +0 -10
- package/lib/scripts/fallbacks/stwo.js +0 -159
- package/lib/scripts/generate-provider-types.js +0 -101
- package/lib/scripts/generate-receipt.js +0 -101
- package/lib/scripts/generate-toprf-keys.js +0 -24
- package/lib/scripts/jsc-cli-rpc.js +0 -35
- package/lib/scripts/register-avs-operator.js +0 -3
- package/lib/scripts/start-server.js +0 -11
- package/lib/scripts/update-avs-metadata.js +0 -20
- package/lib/scripts/utils.js +0 -10
- package/lib/scripts/whitelist-operator.js +0 -16
- package/lib/server/create-server.js +0 -105
- package/lib/server/handlers/claimTeeBundle.js +0 -232
- package/lib/server/handlers/claimTunnel.js +0 -80
- package/lib/server/handlers/completeClaimOnChain.js +0 -29
- package/lib/server/handlers/createClaimOnChain.js +0 -32
- package/lib/server/handlers/createTaskOnMechain.js +0 -57
- package/lib/server/handlers/createTunnel.js +0 -98
- package/lib/server/handlers/disconnectTunnel.js +0 -8
- package/lib/server/handlers/fetchCertificateBytes.js +0 -57
- package/lib/server/handlers/index.js +0 -25
- package/lib/server/handlers/init.js +0 -33
- package/lib/server/handlers/toprf.js +0 -19
- package/lib/server/index.js +0 -4
- package/lib/server/socket.js +0 -112
- package/lib/server/tunnels/make-tcp-tunnel.js +0 -202
- package/lib/server/utils/apm.js +0 -29
- package/lib/server/utils/assert-valid-claim-request.js +0 -354
- package/lib/server/utils/config-env.js +0 -4
- package/lib/server/utils/dns.js +0 -24
- package/lib/server/utils/gcp-attestation.js +0 -237
- package/lib/server/utils/generics.js +0 -45
- package/lib/server/utils/iso.js +0 -259
- package/lib/server/utils/keep-alive.js +0 -38
- package/lib/server/utils/nitro-attestation.js +0 -249
- package/lib/server/utils/oprf-raw.js +0 -61
- package/lib/server/utils/process-handshake.js +0 -233
- package/lib/server/utils/proxy-session.js +0 -6
- package/lib/server/utils/tee-oprf-mpc-verification.js +0 -86
- package/lib/server/utils/tee-oprf-verification.js +0 -151
- package/lib/server/utils/tee-transcript-reconstruction.js +0 -140
- package/lib/server/utils/tee-verification.js +0 -358
- package/lib/server/utils/validation.js +0 -45
- package/lib/types/bgp.js +0 -0
- package/lib/types/claims.js +0 -0
- package/lib/types/client.js +0 -0
- package/lib/types/general.js +0 -0
- package/lib/types/handlers.js +0 -0
- package/lib/types/index.js +0 -10
- package/lib/types/providers.gen.js +0 -16
- package/lib/types/providers.js +0 -0
- package/lib/types/rpc.js +0 -0
- package/lib/types/signatures.js +0 -0
- package/lib/types/tunnel.js +0 -0
- package/lib/types/zk.js +0 -0
- package/lib/utils/auth.js +0 -71
- package/lib/utils/b64-json.js +0 -17
- package/lib/utils/bgp-listener.js +0 -123
- package/lib/utils/claims.js +0 -89
- package/lib/utils/env.js +0 -19
- package/lib/utils/error.js +0 -54
- package/lib/utils/generics.js +0 -268
- package/lib/utils/http-parser.js +0 -201
- package/lib/utils/index.js +0 -13
- package/lib/utils/logger.js +0 -82
- package/lib/utils/prepare-packets.js +0 -69
- package/lib/utils/redactions.js +0 -135
- package/lib/utils/retries.js +0 -26
- package/lib/utils/signatures/eth.js +0 -31
- package/lib/utils/signatures/index.js +0 -12
- package/lib/utils/socket-base.js +0 -96
- package/lib/utils/tls.js +0 -58
- package/lib/utils/ws.js +0 -22
- package/lib/utils/zk.js +0 -625
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import "../server/utils/config-env.js";
|
|
2
|
-
import { setCryptoImplementation } from "@reclaimprotocol/tls";
|
|
3
|
-
import { webcryptoCrypto } from "@reclaimprotocol/tls/webcrypto";
|
|
4
|
-
import { readFile } from "fs/promises";
|
|
5
|
-
import {
|
|
6
|
-
API_SERVER_PORT,
|
|
7
|
-
createClaimOnAttestor,
|
|
8
|
-
getAttestorClientFromPool,
|
|
9
|
-
getTranscriptString,
|
|
10
|
-
logger,
|
|
11
|
-
providers,
|
|
12
|
-
WS_PATHNAME
|
|
13
|
-
} from "../index.js";
|
|
14
|
-
import { getCliArgument } from "../scripts/utils.js";
|
|
15
|
-
import { createServer, decryptTranscript } from "../server/index.js";
|
|
16
|
-
import { assertValidateProviderParams } from "../server/utils/validation.js";
|
|
17
|
-
import { getEnvVariable } from "../utils/env.js";
|
|
18
|
-
setCryptoImplementation(webcryptoCrypto);
|
|
19
|
-
const DEFAULT_ATTESTOR_HOST_PORT = "wss://eu.attestor.reclaimprotocol.org/ws";
|
|
20
|
-
const PRIVATE_KEY_HEX = getEnvVariable("PRIVATE_KEY_HEX") || "0x0123788edad59d7c013cdc85e4372f350f828e2cec62d9a2de4560e69aec7f89";
|
|
21
|
-
let server;
|
|
22
|
-
async function main(receiptParams) {
|
|
23
|
-
const paramsJson = receiptParams ?? await getInputParameters();
|
|
24
|
-
if (!(paramsJson.name in providers)) {
|
|
25
|
-
throw new Error(`Unknown provider "${paramsJson.name}"`);
|
|
26
|
-
}
|
|
27
|
-
assertValidateProviderParams(paramsJson.name, paramsJson.params);
|
|
28
|
-
let attestorHostPort = getCliArgument("attestor") || DEFAULT_ATTESTOR_HOST_PORT;
|
|
29
|
-
if (attestorHostPort === "local") {
|
|
30
|
-
console.log("starting local attestor server...");
|
|
31
|
-
server = await createServer();
|
|
32
|
-
attestorHostPort = `ws://localhost:${API_SERVER_PORT}${WS_PATHNAME}`;
|
|
33
|
-
}
|
|
34
|
-
globalThis.ATTESTOR_BASE_URL = attestorHostPort.replace("ws://", "http://").replace("wss://", "https://");
|
|
35
|
-
const zkEngine = getCliArgument("zk") === "gnark" ? "gnark" : "stwo";
|
|
36
|
-
const { request, error, claim } = await createClaimOnAttestor({
|
|
37
|
-
name: paramsJson.name,
|
|
38
|
-
secretParams: paramsJson.secretParams,
|
|
39
|
-
params: paramsJson.params,
|
|
40
|
-
ownerPrivateKey: PRIVATE_KEY_HEX,
|
|
41
|
-
client: { url: attestorHostPort },
|
|
42
|
-
logger,
|
|
43
|
-
zkEngine
|
|
44
|
-
});
|
|
45
|
-
if (error) {
|
|
46
|
-
console.error("claim creation failed:", error);
|
|
47
|
-
} else {
|
|
48
|
-
const ctx = claim?.context ? JSON.parse(claim.context) : {};
|
|
49
|
-
console.log(`receipt is valid for ${paramsJson.name} provider`);
|
|
50
|
-
if (ctx.extractedParameters) {
|
|
51
|
-
console.log("extracted params:", ctx.extractedParameters);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (!request) {
|
|
55
|
-
throw new Error("Missing request in claim");
|
|
56
|
-
}
|
|
57
|
-
const decTranscript = await decryptTranscript(
|
|
58
|
-
request?.transcript,
|
|
59
|
-
logger,
|
|
60
|
-
zkEngine,
|
|
61
|
-
request?.fixedServerIV,
|
|
62
|
-
request?.fixedClientIV
|
|
63
|
-
);
|
|
64
|
-
const transcriptStr = getTranscriptString(decTranscript);
|
|
65
|
-
console.log("receipt:\n", transcriptStr);
|
|
66
|
-
console.log("claim:\n", claim);
|
|
67
|
-
const client = getAttestorClientFromPool(attestorHostPort);
|
|
68
|
-
await client.terminateConnection();
|
|
69
|
-
}
|
|
70
|
-
async function getInputParameters() {
|
|
71
|
-
const paramsJsonFile = getCliArgument("json");
|
|
72
|
-
if (!paramsJsonFile) {
|
|
73
|
-
const name = getCliArgument("name");
|
|
74
|
-
const paramsStr = getCliArgument("params");
|
|
75
|
-
const secretParamsStr = getCliArgument("secretParams");
|
|
76
|
-
if (!name || !paramsStr || !secretParamsStr) {
|
|
77
|
-
throw new Error("Either provide --json argument for parameters JSON or provide separately with --name, --params & --secretParams");
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
name,
|
|
81
|
-
params: JSON.parse(paramsStr),
|
|
82
|
-
secretParams: JSON.parse(secretParamsStr)
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
let fileContents = await readFile(paramsJsonFile, "utf8");
|
|
86
|
-
for (const variable in process.env) {
|
|
87
|
-
fileContents = fileContents.replace(
|
|
88
|
-
`{{${variable}}}`,
|
|
89
|
-
process.env[variable]
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
return JSON.parse(fileContents);
|
|
93
|
-
}
|
|
94
|
-
main().catch((err) => {
|
|
95
|
-
console.error("error in receipt gen", err);
|
|
96
|
-
}).finally(() => {
|
|
97
|
-
server?.close();
|
|
98
|
-
});
|
|
99
|
-
export {
|
|
100
|
-
main
|
|
101
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { hexlify } from "ethers";
|
|
2
|
-
import { logger, makeDefaultOPRFOperator } from "../utils/index.js";
|
|
3
|
-
const ENGINE = "gnark";
|
|
4
|
-
const TOTAL_KEYS = 10;
|
|
5
|
-
const THRESHOLD = 1;
|
|
6
|
-
async function main() {
|
|
7
|
-
const op = makeDefaultOPRFOperator("chacha20", ENGINE, logger);
|
|
8
|
-
const {
|
|
9
|
-
publicKey,
|
|
10
|
-
privateKey,
|
|
11
|
-
shares
|
|
12
|
-
} = await op.generateThresholdKeys(TOTAL_KEYS, THRESHOLD);
|
|
13
|
-
logEnvValue("TOPRF_PUBLIC_KEY", publicKey);
|
|
14
|
-
logEnvValue("TOPRF_PRIVATE_KEY", privateKey);
|
|
15
|
-
for (const [i, share] of shares.entries()) {
|
|
16
|
-
console.log(`# Share ${i}`);
|
|
17
|
-
logEnvValue("TOPRF_SHARE_PUBLIC_KEY", share.publicKey);
|
|
18
|
-
logEnvValue("TOPRF_SHARE_PRIVATE_KEY", share.privateKey);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
function logEnvValue(name, value) {
|
|
22
|
-
console.log(`${name}=${hexlify(value)}`);
|
|
23
|
-
}
|
|
24
|
-
void main();
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import "../external-rpc/jsc-polyfills/index.js";
|
|
2
|
-
import { setCryptoImplementation } from "@reclaimprotocol/tls";
|
|
3
|
-
import { pureJsCrypto } from "@reclaimprotocol/tls/purejs-crypto";
|
|
4
|
-
import { handleIncomingMessage } from "../external-rpc/index.js";
|
|
5
|
-
import { B64_JSON_REVIVER } from "../utils/b64-json.js";
|
|
6
|
-
function readIncomingMsg() {
|
|
7
|
-
const cmd2 = readline();
|
|
8
|
-
return JSON.parse(cmd2, B64_JSON_REVIVER);
|
|
9
|
-
}
|
|
10
|
-
setCryptoImplementation(pureJsCrypto);
|
|
11
|
-
print("Input base URL for attestor");
|
|
12
|
-
const initCmd = readIncomingMsg();
|
|
13
|
-
if (initCmd.type !== "init") {
|
|
14
|
-
throw new Error("Expected init command");
|
|
15
|
-
}
|
|
16
|
-
globalThis.RPC_CHANNEL_NAME = "cli";
|
|
17
|
-
globalThis.ATTESTOR_BASE_URL = initCmd.attestorBaseUrl;
|
|
18
|
-
const channel = {
|
|
19
|
-
postMessage(message) {
|
|
20
|
-
print(message);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
globalThis[RPC_CHANNEL_NAME] = channel;
|
|
24
|
-
print("reading RPC messages...");
|
|
25
|
-
let cmd;
|
|
26
|
-
while (cmd = readIncomingMsg(), cmd.type !== "quit") {
|
|
27
|
-
if (cmd.type === "init") {
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
handleIncomingMessage(cmd);
|
|
31
|
-
await new Promise((resolve) => {
|
|
32
|
-
setTimeout(resolve, 500);
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
print("done");
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import "../server/utils/config-env.js";
|
|
2
|
-
import { setCryptoImplementation } from "@reclaimprotocol/tls";
|
|
3
|
-
import { webcryptoCrypto } from "@reclaimprotocol/tls/webcrypto";
|
|
4
|
-
import { getApm } from "../server/utils/apm.js";
|
|
5
|
-
getApm();
|
|
6
|
-
setCryptoImplementation(webcryptoCrypto);
|
|
7
|
-
async function main() {
|
|
8
|
-
const { createServer } = await import("../server/index.js");
|
|
9
|
-
return createServer();
|
|
10
|
-
}
|
|
11
|
-
main();
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import "src/server/utils/config-env";
|
|
2
|
-
import { getContracts } from "../avs/utils/contracts.js";
|
|
3
|
-
import { getCliArgument } from "../scripts/utils.js";
|
|
4
|
-
async function main() {
|
|
5
|
-
const { contract } = getContracts();
|
|
6
|
-
const minSignaturesPerTask = getCliArgument("minSignaturesPerTask");
|
|
7
|
-
if (!minSignaturesPerTask) {
|
|
8
|
-
throw new Error(
|
|
9
|
-
"Provide operator address via --minSignaturesPerTask <num>"
|
|
10
|
-
);
|
|
11
|
-
}
|
|
12
|
-
const tx = await contract.updateTaskCreationMetadata({
|
|
13
|
-
minSignaturesPerTask: +(minSignaturesPerTask || 0),
|
|
14
|
-
maxTaskCreationDelayS: 0,
|
|
15
|
-
maxTaskLifetimeS: 0
|
|
16
|
-
});
|
|
17
|
-
await tx.wait();
|
|
18
|
-
console.log("Updated task creation metadata");
|
|
19
|
-
}
|
|
20
|
-
void main();
|
package/lib/scripts/utils.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import "src/server/utils/config-env";
|
|
2
|
-
import { getContracts } from "../avs/utils/contracts.js";
|
|
3
|
-
import { getCliArgument } from "../scripts/utils.js";
|
|
4
|
-
async function main() {
|
|
5
|
-
const { contract } = getContracts();
|
|
6
|
-
const address = getCliArgument("address");
|
|
7
|
-
if (!address) {
|
|
8
|
-
throw new Error(
|
|
9
|
-
"Provide operator address via --address <addr>"
|
|
10
|
-
);
|
|
11
|
-
}
|
|
12
|
-
const tx = await contract.whitelistAddressAsOperator(address, true);
|
|
13
|
-
await tx.wait();
|
|
14
|
-
console.log("Whitelisted address:", address);
|
|
15
|
-
}
|
|
16
|
-
void main();
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { createServer as createHttpServer } from "http";
|
|
2
|
-
import serveStatic from "serve-static";
|
|
3
|
-
import { WebSocketServer } from "ws";
|
|
4
|
-
import { API_SERVER_PORT, ATTESTOR_ADDRESS_PATHNAME, BROWSER_RPC_PATHNAME, WS_PATHNAME } from "../config/index.js";
|
|
5
|
-
import { AttestorServerSocket } from "../server/socket.js";
|
|
6
|
-
import { getAttestorAddress } from "../server/utils/generics.js";
|
|
7
|
-
import { addKeepAlive } from "../server/utils/keep-alive.js";
|
|
8
|
-
import { createBgpListener } from "../utils/bgp-listener.js";
|
|
9
|
-
import { getEnvVariable } from "../utils/env.js";
|
|
10
|
-
import { logger as LOGGER } from "../utils/index.js";
|
|
11
|
-
import { SelectedServiceSignatureType } from "../utils/signatures/index.js";
|
|
12
|
-
import { promisifySend } from "../utils/ws.js";
|
|
13
|
-
const PORT = +(getEnvVariable("PORT") || API_SERVER_PORT);
|
|
14
|
-
const DISABLE_BGP_CHECKS = getEnvVariable("DISABLE_BGP_CHECKS") === "1";
|
|
15
|
-
const ATTESTOR_ADDRESS_JSON_RES = JSON.stringify({
|
|
16
|
-
address: getAttestorAddress(SelectedServiceSignatureType),
|
|
17
|
-
signatureType: SelectedServiceSignatureType
|
|
18
|
-
});
|
|
19
|
-
async function createServer(port = PORT) {
|
|
20
|
-
const http = createHttpServer();
|
|
21
|
-
const serveBrowserRpc = serveStatic(
|
|
22
|
-
"browser",
|
|
23
|
-
{
|
|
24
|
-
index: ["index.html"],
|
|
25
|
-
setHeaders(res) {
|
|
26
|
-
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
);
|
|
30
|
-
const bgpListener = !DISABLE_BGP_CHECKS ? createBgpListener(LOGGER.child({ service: "bgp-listener" })) : void 0;
|
|
31
|
-
const wss = new WebSocketServer({ noServer: true });
|
|
32
|
-
http.on("upgrade", handleUpgrade.bind(wss));
|
|
33
|
-
http.on("request", (req, res) => {
|
|
34
|
-
const url = URL.parse(req.url || "", "http://localhost");
|
|
35
|
-
if (!url) {
|
|
36
|
-
res.statusCode = 422;
|
|
37
|
-
res.end("Invalid URL");
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
if (url.pathname === ATTESTOR_ADDRESS_PATHNAME) {
|
|
41
|
-
res.writeHead(200, { "Content-Type": "application/json" });
|
|
42
|
-
res.end(ATTESTOR_ADDRESS_JSON_RES);
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
if (!url.pathname?.startsWith(BROWSER_RPC_PATHNAME)) {
|
|
46
|
-
res.statusCode = 404;
|
|
47
|
-
res.end("Not found");
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
req.url = req.url.slice(BROWSER_RPC_PATHNAME.length) || "/";
|
|
51
|
-
serveBrowserRpc(req, res, (err) => {
|
|
52
|
-
if (err) {
|
|
53
|
-
LOGGER.error({ err, url: req.url }, "Failed to serve file");
|
|
54
|
-
}
|
|
55
|
-
res.statusCode = err?.statusCode ?? 404;
|
|
56
|
-
res.end(err?.message ?? "Not found");
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
http.listen(port);
|
|
60
|
-
await new Promise((resolve, reject) => {
|
|
61
|
-
http.once("listening", () => resolve());
|
|
62
|
-
http.once("error", reject);
|
|
63
|
-
});
|
|
64
|
-
wss.on("connection", (ws, req) => handleNewClient(ws, req, bgpListener));
|
|
65
|
-
LOGGER.info(
|
|
66
|
-
{
|
|
67
|
-
port,
|
|
68
|
-
apiPath: WS_PATHNAME,
|
|
69
|
-
browserRpcPath: BROWSER_RPC_PATHNAME,
|
|
70
|
-
signerAddress: getAttestorAddress(SelectedServiceSignatureType)
|
|
71
|
-
},
|
|
72
|
-
"WS server listening"
|
|
73
|
-
);
|
|
74
|
-
const wssClose = wss.close.bind(wss);
|
|
75
|
-
wss.close = (cb) => {
|
|
76
|
-
wssClose(() => http.close(cb));
|
|
77
|
-
bgpListener?.close();
|
|
78
|
-
};
|
|
79
|
-
return wss;
|
|
80
|
-
}
|
|
81
|
-
async function handleNewClient(ws, req, bgpListener) {
|
|
82
|
-
promisifySend(ws);
|
|
83
|
-
const client = await AttestorServerSocket.acceptConnection(
|
|
84
|
-
ws,
|
|
85
|
-
{ req, bgpListener, logger: LOGGER }
|
|
86
|
-
);
|
|
87
|
-
if (!client) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
ws.serverSocket = client;
|
|
91
|
-
addKeepAlive(ws, LOGGER.child({ sessionId: client.sessionId }));
|
|
92
|
-
}
|
|
93
|
-
function handleUpgrade(request, socket, head) {
|
|
94
|
-
const { pathname } = new URL(request.url, "wss://base.url");
|
|
95
|
-
if (pathname === WS_PATHNAME) {
|
|
96
|
-
this.handleUpgrade(request, socket, head, (ws) => {
|
|
97
|
-
this.emit("connection", ws, request);
|
|
98
|
-
});
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
socket.destroy();
|
|
102
|
-
}
|
|
103
|
-
export {
|
|
104
|
-
createServer
|
|
105
|
-
};
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import { ClaimTeeBundleResponse } from "../../proto/api.js";
|
|
2
|
-
import { VerificationBundle } from "../../proto/tee-bundle.js";
|
|
3
|
-
import { substituteParamValues } from "../../providers/http/index.js";
|
|
4
|
-
import { assertValidProviderTranscript } from "../../server/utils/assert-valid-claim-request.js";
|
|
5
|
-
import { getAttestorAddress, niceParseJsonObject, signAsAttestor } from "../../server/utils/generics.js";
|
|
6
|
-
import { verifyOprfMpcOutputs } from "../../server/utils/tee-oprf-mpc-verification.js";
|
|
7
|
-
import { verifyOprfProofs } from "../../server/utils/tee-oprf-verification.js";
|
|
8
|
-
import { reconstructTlsTranscript } from "../../server/utils/tee-transcript-reconstruction.js";
|
|
9
|
-
import { verifyTeeBundle } from "../../server/utils/tee-verification.js";
|
|
10
|
-
import { AttestorError } from "../../utils/error.js";
|
|
11
|
-
import { createSignDataForClaim, getIdentifierFromClaimInfo } from "../../utils/index.js";
|
|
12
|
-
const claimTeeBundle = async (teeBundleRequest, { logger, client }) => {
|
|
13
|
-
const {
|
|
14
|
-
verificationBundle,
|
|
15
|
-
data
|
|
16
|
-
} = teeBundleRequest;
|
|
17
|
-
const res = ClaimTeeBundleResponse.create({ request: teeBundleRequest });
|
|
18
|
-
logger.info("Starting TEE bundle verification");
|
|
19
|
-
const teeData = await verifyTeeBundle(verificationBundle, logger);
|
|
20
|
-
const timestampS = Math.floor(teeData.kOutputPayload.timestampMs / 1e3);
|
|
21
|
-
logger.info("Verifying OPRF proofs");
|
|
22
|
-
const bundle = VerificationBundle.decode(verificationBundle);
|
|
23
|
-
const zkOprfResults = await verifyOprfProofs(
|
|
24
|
-
{ ...teeData, oprfVerifications: bundle.oprfVerifications },
|
|
25
|
-
logger
|
|
26
|
-
);
|
|
27
|
-
logger.info("Verifying OPRF MPC outputs");
|
|
28
|
-
const oprfMpcResults = verifyOprfMpcOutputs(
|
|
29
|
-
teeData.kOutputPayload,
|
|
30
|
-
teeData.tOutputPayload,
|
|
31
|
-
logger
|
|
32
|
-
);
|
|
33
|
-
const allOprfResults = validateAndCombineOprfResults(zkOprfResults, oprfMpcResults, logger);
|
|
34
|
-
logger.info("Starting TLS transcript reconstruction with OPRF replacements");
|
|
35
|
-
const transcriptData = await reconstructTlsTranscript(teeData, logger, allOprfResults);
|
|
36
|
-
logger.info("Creating plaintext transcript from TEE data");
|
|
37
|
-
const plaintextTranscript = createPlaintextTranscriptFromTeeData(transcriptData, logger);
|
|
38
|
-
logger.info("Running direct provider validation on TEE reconstructed data");
|
|
39
|
-
if (!data) {
|
|
40
|
-
throw new AttestorError("ERROR_INVALID_CLAIM", "No claim data provided in TEE bundle request");
|
|
41
|
-
}
|
|
42
|
-
const validatedClaim = await validateTeeProviderReceipt(
|
|
43
|
-
plaintextTranscript,
|
|
44
|
-
data,
|
|
45
|
-
logger,
|
|
46
|
-
{ version: client.metadata.clientVersion },
|
|
47
|
-
transcriptData.certificateInfo
|
|
48
|
-
);
|
|
49
|
-
const ctx = niceParseJsonObject(validatedClaim.context, "context");
|
|
50
|
-
ctx.pcr0_k = teeData.teekPcr0;
|
|
51
|
-
ctx.pcr0_t = teeData.teetPcr0;
|
|
52
|
-
ctx.tee_session_id = teeData.teeSessionId;
|
|
53
|
-
validatedClaim.context = JSON.stringify(ctx);
|
|
54
|
-
res.claim = {
|
|
55
|
-
...validatedClaim,
|
|
56
|
-
identifier: getIdentifierFromClaimInfo(validatedClaim),
|
|
57
|
-
// Use timestampS from TEE_K bundle for claim signing
|
|
58
|
-
timestampS,
|
|
59
|
-
// hardcode for compatibility with V1 claims
|
|
60
|
-
epoch: 1
|
|
61
|
-
};
|
|
62
|
-
logger.info({ claim: res.claim }, "TEE bundle claim validation successful");
|
|
63
|
-
res.signatures = {
|
|
64
|
-
attestorAddress: getAttestorAddress(
|
|
65
|
-
client.metadata.signatureType
|
|
66
|
-
),
|
|
67
|
-
claimSignature: res.claim ? await signAsAttestor(
|
|
68
|
-
createSignDataForClaim(res.claim),
|
|
69
|
-
client.metadata.signatureType
|
|
70
|
-
) : new Uint8Array(),
|
|
71
|
-
resultSignature: await signAsAttestor(
|
|
72
|
-
ClaimTeeBundleResponse.encode(res).finish(),
|
|
73
|
-
client.metadata.signatureType
|
|
74
|
-
)
|
|
75
|
-
};
|
|
76
|
-
logger.info("TEE bundle claim processing completed");
|
|
77
|
-
return res;
|
|
78
|
-
};
|
|
79
|
-
function createPlaintextTranscriptFromTeeData(transcriptData, logger) {
|
|
80
|
-
const transcript = [];
|
|
81
|
-
if (transcriptData.revealedRequest && transcriptData.revealedRequest.length > 0) {
|
|
82
|
-
transcript.push({
|
|
83
|
-
sender: "client",
|
|
84
|
-
message: transcriptData.revealedRequest
|
|
85
|
-
});
|
|
86
|
-
logger.debug("Added TEE revealed request to plaintext transcript", {
|
|
87
|
-
length: transcriptData.revealedRequest.length
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
if (transcriptData.reconstructedResponse && transcriptData.reconstructedResponse.length > 0) {
|
|
91
|
-
transcript.push({
|
|
92
|
-
sender: "server",
|
|
93
|
-
message: transcriptData.reconstructedResponse
|
|
94
|
-
});
|
|
95
|
-
logger.debug("Added TEE consolidated response to plaintext transcript", {
|
|
96
|
-
length: transcriptData.reconstructedResponse.length
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
if (transcriptData.certificateInfo) {
|
|
100
|
-
logger.info("Certificate information available for validation", {
|
|
101
|
-
commonName: transcriptData.certificateInfo.commonName,
|
|
102
|
-
issuerCommonName: transcriptData.certificateInfo.issuerCommonName,
|
|
103
|
-
dnsNames: transcriptData.certificateInfo.dnsNames,
|
|
104
|
-
notBefore: new Date(transcriptData.certificateInfo.notBeforeUnix * 1e3).toISOString(),
|
|
105
|
-
notAfter: new Date(transcriptData.certificateInfo.notAfterUnix * 1e3).toISOString()
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
logger.info("Created plaintext transcript from TEE data", {
|
|
109
|
-
totalMessages: transcript.length,
|
|
110
|
-
hasRequest: !!transcriptData.revealedRequest?.length,
|
|
111
|
-
hasResponse: !!transcriptData.reconstructedResponse?.length,
|
|
112
|
-
hasCertificateInfo: !!transcriptData.certificateInfo
|
|
113
|
-
});
|
|
114
|
-
return transcript;
|
|
115
|
-
}
|
|
116
|
-
async function validateTeeProviderReceipt(plaintextTranscript, claimInfo, logger, providerCtx, certificateInfo) {
|
|
117
|
-
logger.info("Starting direct TEE provider validation", {
|
|
118
|
-
provider: claimInfo.provider,
|
|
119
|
-
transcriptMessages: plaintextTranscript.length,
|
|
120
|
-
hasCertificateInfo: !!certificateInfo
|
|
121
|
-
});
|
|
122
|
-
if (certificateInfo) {
|
|
123
|
-
validateTlsCertificate(claimInfo, certificateInfo, logger);
|
|
124
|
-
}
|
|
125
|
-
const validatedClaim = await assertValidProviderTranscript(
|
|
126
|
-
plaintextTranscript,
|
|
127
|
-
claimInfo,
|
|
128
|
-
logger,
|
|
129
|
-
providerCtx
|
|
130
|
-
);
|
|
131
|
-
logger.info("TEE provider validation completed successfully", {
|
|
132
|
-
provider: validatedClaim.provider,
|
|
133
|
-
owner: validatedClaim.owner || "unknown"
|
|
134
|
-
});
|
|
135
|
-
return validatedClaim;
|
|
136
|
-
}
|
|
137
|
-
function isHostnameValidForCertificate(hostname, certName) {
|
|
138
|
-
if (hostname === certName) {
|
|
139
|
-
return true;
|
|
140
|
-
}
|
|
141
|
-
if (certName.startsWith("*.")) {
|
|
142
|
-
const wildcardDomain = certName.slice(2);
|
|
143
|
-
if (hostname.endsWith(wildcardDomain)) {
|
|
144
|
-
const subdomainPart = hostname.slice(0, -wildcardDomain.length);
|
|
145
|
-
if (subdomainPart.endsWith(".")) {
|
|
146
|
-
const subdomain = subdomainPart.slice(0, -1);
|
|
147
|
-
return !subdomain.includes(".");
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return false;
|
|
152
|
-
}
|
|
153
|
-
function validateTlsCertificate(claimInfo, certificateInfo, logger) {
|
|
154
|
-
let claimedHostname;
|
|
155
|
-
const paramsWithTemplates = niceParseJsonObject(claimInfo.parameters, "params");
|
|
156
|
-
const params = substituteParamValues(paramsWithTemplates, void 0, true).newParams;
|
|
157
|
-
if ("url" in params && typeof params.url === "string") {
|
|
158
|
-
claimedHostname = new URL(params.url).hostname;
|
|
159
|
-
}
|
|
160
|
-
if (!claimedHostname) {
|
|
161
|
-
logger.warn("Could not extract hostname from claim for certificate validation", {
|
|
162
|
-
provider: claimInfo.provider
|
|
163
|
-
});
|
|
164
|
-
throw new AttestorError(
|
|
165
|
-
"ERROR_INVALID_CLAIM",
|
|
166
|
-
"Certificate validation failed: hostname not found"
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
logger.info("Validating TLS certificate for claimed hostname", {
|
|
170
|
-
claimedHostname,
|
|
171
|
-
certificateCommonName: certificateInfo.commonName,
|
|
172
|
-
certificateDnsNames: certificateInfo.dnsNames
|
|
173
|
-
});
|
|
174
|
-
const isValidForHostname = isHostnameValidForCertificate(claimedHostname, certificateInfo.commonName) || certificateInfo.dnsNames.some((name) => isHostnameValidForCertificate(claimedHostname, name));
|
|
175
|
-
if (!isValidForHostname) {
|
|
176
|
-
throw new AttestorError(
|
|
177
|
-
"ERROR_INVALID_CLAIM",
|
|
178
|
-
`Certificate validation failed: hostname '${claimedHostname}' not valid for certificate (CN: ${certificateInfo.commonName}, SANs: ${certificateInfo.dnsNames.join(", ")})`
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
const now = Date.now() / 1e3;
|
|
182
|
-
if (now < certificateInfo.notBeforeUnix || now > certificateInfo.notAfterUnix) {
|
|
183
|
-
throw new AttestorError(
|
|
184
|
-
"ERROR_INVALID_CLAIM",
|
|
185
|
-
`Certificate validation failed: certificate not valid at current time (valid from ${new Date(certificateInfo.notBeforeUnix * 1e3).toISOString()} to ${new Date(certificateInfo.notAfterUnix * 1e3).toISOString()})`
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
logger.info("TLS certificate validation passed", {
|
|
189
|
-
claimedHostname,
|
|
190
|
-
validatedAgainst: isHostnameValidForCertificate(claimedHostname, certificateInfo.commonName) ? `CommonName: ${certificateInfo.commonName}` : `SAN: ${certificateInfo.dnsNames.find((name) => isHostnameValidForCertificate(claimedHostname, name))}`
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
function validateAndCombineOprfResults(zkOprfResults, oprfMpcResults, logger) {
|
|
194
|
-
const allOprfResults = [...zkOprfResults, ...oprfMpcResults];
|
|
195
|
-
if (allOprfResults.length === 0) {
|
|
196
|
-
return allOprfResults;
|
|
197
|
-
}
|
|
198
|
-
logger.info(`Combined ${zkOprfResults.length} ZK OPRF + ${oprfMpcResults.length} OPRF MPC results`);
|
|
199
|
-
const seen = {};
|
|
200
|
-
for (const result of zkOprfResults) {
|
|
201
|
-
seen[result.position] = { length: result.length, source: "zk" };
|
|
202
|
-
}
|
|
203
|
-
for (const result of oprfMpcResults) {
|
|
204
|
-
const existing = seen[result.position];
|
|
205
|
-
if (existing) {
|
|
206
|
-
if (existing.length !== result.length) {
|
|
207
|
-
throw new AttestorError(
|
|
208
|
-
"ERROR_INVALID_CLAIM",
|
|
209
|
-
`OPRF range conflict at position ${result.position}: ZK length ${existing.length} vs MPC length ${result.length}`
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
logger.warn(`Duplicate OPRF range at position ${result.position} from both ZK and MPC - using MPC result`);
|
|
213
|
-
}
|
|
214
|
-
for (const [pos, data] of Object.entries(seen)) {
|
|
215
|
-
const position = Number(pos);
|
|
216
|
-
const existingEnd = position + data.length;
|
|
217
|
-
const newEnd = result.position + result.length;
|
|
218
|
-
const overlaps = result.position < existingEnd && newEnd > position && result.position !== position;
|
|
219
|
-
if (overlaps) {
|
|
220
|
-
throw new AttestorError(
|
|
221
|
-
"ERROR_INVALID_CLAIM",
|
|
222
|
-
`Overlapping OPRF ranges: [${position}:${existingEnd}] (${data.source}) and [${result.position}:${newEnd}] (mpc)`
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
seen[result.position] = { length: result.length, source: "mpc" };
|
|
227
|
-
}
|
|
228
|
-
return allOprfResults;
|
|
229
|
-
}
|
|
230
|
-
export {
|
|
231
|
-
claimTeeBundle
|
|
232
|
-
};
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { MAX_CLAIM_TIMESTAMP_DIFF_S } from "../../config/index.js";
|
|
2
|
-
import { ClaimTunnelResponse } from "../../proto/api.js";
|
|
3
|
-
import { getApm } from "../../server/utils/apm.js";
|
|
4
|
-
import { assertTranscriptsMatch, assertValidClaimRequest } from "../../server/utils/assert-valid-claim-request.js";
|
|
5
|
-
import { getAttestorAddress, signAsAttestor } from "../../server/utils/generics.js";
|
|
6
|
-
import { AttestorError, createSignDataForClaim, getIdentifierFromClaimInfo, unixTimestampSeconds } from "../../utils/index.js";
|
|
7
|
-
const claimTunnel = async (claimRequest, { tx, logger, client }) => {
|
|
8
|
-
const {
|
|
9
|
-
request,
|
|
10
|
-
data: { timestampS } = {}
|
|
11
|
-
} = claimRequest;
|
|
12
|
-
const tunnel = client.getTunnel(request?.id);
|
|
13
|
-
try {
|
|
14
|
-
await tunnel.close();
|
|
15
|
-
} catch (err) {
|
|
16
|
-
logger.debug({ err }, "error closing tunnel");
|
|
17
|
-
}
|
|
18
|
-
if (tx) {
|
|
19
|
-
const transcriptBytes = tunnel.transcript.reduce(
|
|
20
|
-
(acc, { message }) => acc + message.length,
|
|
21
|
-
0
|
|
22
|
-
);
|
|
23
|
-
tx?.setLabel("transcriptBytes", transcriptBytes.toString());
|
|
24
|
-
}
|
|
25
|
-
if (tunnel.createRequest?.host !== request?.host || tunnel.createRequest?.port !== request?.port || tunnel.createRequest?.geoLocation !== request?.geoLocation || tunnel.createRequest?.proxySessionId !== request?.proxySessionId) {
|
|
26
|
-
throw AttestorError.badRequest("Tunnel request does not match");
|
|
27
|
-
}
|
|
28
|
-
assertTranscriptsMatch(claimRequest.transcript, tunnel.transcript);
|
|
29
|
-
const res = ClaimTunnelResponse.create({ request: claimRequest });
|
|
30
|
-
try {
|
|
31
|
-
const now = unixTimestampSeconds();
|
|
32
|
-
if (Math.floor(timestampS - now) > MAX_CLAIM_TIMESTAMP_DIFF_S) {
|
|
33
|
-
throw new AttestorError(
|
|
34
|
-
"ERROR_INVALID_CLAIM",
|
|
35
|
-
`Timestamp provided ${timestampS} is too far off. Current time is ${now}`
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
const assertTx = getApm()?.startTransaction("assertValidClaimRequest", { childOf: tx });
|
|
39
|
-
try {
|
|
40
|
-
const claim = await assertValidClaimRequest(
|
|
41
|
-
claimRequest,
|
|
42
|
-
client.metadata,
|
|
43
|
-
logger
|
|
44
|
-
);
|
|
45
|
-
res.claim = {
|
|
46
|
-
...claim,
|
|
47
|
-
identifier: getIdentifierFromClaimInfo(claim),
|
|
48
|
-
// hardcode for compatibility with V1 claims
|
|
49
|
-
epoch: 1
|
|
50
|
-
};
|
|
51
|
-
} catch (err) {
|
|
52
|
-
assertTx?.setOutcome("failure");
|
|
53
|
-
throw err;
|
|
54
|
-
} finally {
|
|
55
|
-
assertTx?.end();
|
|
56
|
-
}
|
|
57
|
-
} catch (err) {
|
|
58
|
-
logger.error({ err }, "invalid claim request");
|
|
59
|
-
const attestorErr = AttestorError.fromError(err, "ERROR_INVALID_CLAIM");
|
|
60
|
-
res.error = attestorErr.toProto();
|
|
61
|
-
}
|
|
62
|
-
res.signatures = {
|
|
63
|
-
attestorAddress: getAttestorAddress(
|
|
64
|
-
client.metadata.signatureType
|
|
65
|
-
),
|
|
66
|
-
claimSignature: res.claim ? await signAsAttestor(
|
|
67
|
-
createSignDataForClaim(res.claim),
|
|
68
|
-
client.metadata.signatureType
|
|
69
|
-
) : new Uint8Array(),
|
|
70
|
-
resultSignature: await signAsAttestor(
|
|
71
|
-
ClaimTunnelResponse.encode(res).finish(),
|
|
72
|
-
client.metadata.signatureType
|
|
73
|
-
)
|
|
74
|
-
};
|
|
75
|
-
client.removeTunnel(request.id);
|
|
76
|
-
return res;
|
|
77
|
-
};
|
|
78
|
-
export {
|
|
79
|
-
claimTunnel
|
|
80
|
-
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { EventLog } from "ethers";
|
|
2
|
-
import { getContracts } from "../../avs/utils/contracts.js";
|
|
3
|
-
import { getEnvVariable } from "../../utils/env.js";
|
|
4
|
-
import { AttestorError, ethersStructToPlainObject } from "../../utils/index.js";
|
|
5
|
-
const ACCEPT_CLAIM_PAYMENT_REQUESTS = getEnvVariable("ACCEPT_CLAIM_PAYMENT_REQUESTS") === "1";
|
|
6
|
-
const completeClaimOnChain = async ({ chainId: chainIdNum, taskIndex, completedTaskJson }) => {
|
|
7
|
-
if (!ACCEPT_CLAIM_PAYMENT_REQUESTS) {
|
|
8
|
-
throw new AttestorError(
|
|
9
|
-
"ERROR_PAYMENT_REFUSED",
|
|
10
|
-
"Payment requests are not accepted at this time"
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
const chainId = chainIdNum.toString();
|
|
14
|
-
const { contract } = getContracts(chainId.toString());
|
|
15
|
-
const task = JSON.parse(completedTaskJson);
|
|
16
|
-
const tx = await contract.taskCompleted(task, taskIndex);
|
|
17
|
-
const rslt = await tx.wait();
|
|
18
|
-
const logs = rslt?.logs ?? [];
|
|
19
|
-
const eventLogs = logs.filter((log) => log instanceof EventLog);
|
|
20
|
-
const obj = eventLogs[0]?.args;
|
|
21
|
-
const plainObj = ethersStructToPlainObject(obj);
|
|
22
|
-
return {
|
|
23
|
-
txHash: rslt?.hash ?? "",
|
|
24
|
-
taskCompletedObjectJson: JSON.stringify(plainObj)
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
export {
|
|
28
|
-
completeClaimOnChain
|
|
29
|
-
};
|