@reclaimprotocol/attestor-core 5.0.1-beta.2 → 5.0.1-beta.22

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.
Files changed (145) hide show
  1. package/browser/resources/attestor-browser.min.mjs +4512 -0
  2. package/lib/avs/abis/avsDirectoryABI.js +338 -341
  3. package/lib/avs/abis/delegationABI.js +1 -4
  4. package/lib/avs/abis/registryABI.js +719 -722
  5. package/lib/avs/client/create-claim-on-avs.js +129 -157
  6. package/lib/avs/config.js +18 -24
  7. package/lib/avs/contracts/ReclaimServiceManager.js +1 -0
  8. package/lib/avs/contracts/common.js +1 -0
  9. package/lib/avs/contracts/factories/ReclaimServiceManager__factory.js +1139 -1156
  10. package/lib/avs/contracts/factories/index.js +4 -4
  11. package/lib/avs/contracts/index.js +2 -6
  12. package/lib/avs/types/index.js +1 -0
  13. package/lib/avs/utils/contracts.js +30 -50
  14. package/lib/avs/utils/register.js +75 -70
  15. package/lib/avs/utils/tasks.js +38 -45
  16. package/lib/client/create-claim.js +402 -431
  17. package/lib/client/tunnels/make-rpc-tcp-tunnel.js +46 -48
  18. package/lib/client/tunnels/make-rpc-tls-tunnel.js +125 -121
  19. package/lib/client/utils/attestor-pool.js +23 -22
  20. package/lib/client/utils/client-socket.js +86 -109
  21. package/lib/client/utils/message-handler.js +79 -89
  22. package/lib/config/index.js +40 -58
  23. package/lib/external-rpc/benchmark.js +61 -74
  24. package/lib/external-rpc/event-bus.js +12 -15
  25. package/lib/external-rpc/handle-incoming-msg.js +216 -225
  26. package/lib/external-rpc/jsc-polyfills/1.js +70 -68
  27. package/lib/external-rpc/jsc-polyfills/2.js +17 -12
  28. package/lib/external-rpc/jsc-polyfills/event.js +10 -15
  29. package/lib/external-rpc/jsc-polyfills/index.js +2 -2
  30. package/lib/external-rpc/jsc-polyfills/ws.js +77 -79
  31. package/lib/external-rpc/setup-browser.js +28 -28
  32. package/lib/external-rpc/setup-jsc.js +17 -17
  33. package/lib/external-rpc/types.js +1 -0
  34. package/lib/external-rpc/utils.js +89 -89
  35. package/lib/external-rpc/zk.js +55 -50
  36. package/lib/index.js +2 -6
  37. package/lib/mechain/abis/governanceABI.js +457 -460
  38. package/lib/mechain/abis/taskABI.js +502 -505
  39. package/lib/mechain/client/create-claim-on-mechain.js +24 -29
  40. package/lib/mechain/constants/index.js +3 -8
  41. package/lib/mechain/types/index.js +1 -0
  42. package/lib/proto/api.js +4200 -4087
  43. package/lib/proto/tee-bundle.js +1261 -1241
  44. package/lib/providers/http/index.js +616 -603
  45. package/lib/providers/http/patch-parse5-tree.js +27 -29
  46. package/lib/providers/http/utils.js +289 -248
  47. package/lib/providers/index.js +3 -6
  48. package/lib/server/create-server.js +89 -91
  49. package/lib/server/handlers/claimTeeBundle.js +231 -211
  50. package/lib/server/handlers/claimTunnel.js +66 -73
  51. package/lib/server/handlers/completeClaimOnChain.js +20 -25
  52. package/lib/server/handlers/createClaimOnChain.js +21 -27
  53. package/lib/server/handlers/createTaskOnMechain.js +40 -50
  54. package/lib/server/handlers/createTunnel.js +85 -90
  55. package/lib/server/handlers/disconnectTunnel.js +4 -7
  56. package/lib/server/handlers/fetchCertificateBytes.js +37 -53
  57. package/lib/server/handlers/index.js +21 -24
  58. package/lib/server/handlers/init.js +27 -28
  59. package/lib/server/handlers/toprf.js +13 -16
  60. package/lib/server/socket.js +97 -100
  61. package/lib/server/tunnels/make-tcp-tunnel.js +161 -186
  62. package/lib/server/utils/apm.js +32 -25
  63. package/lib/server/utils/assert-valid-claim-request.js +305 -334
  64. package/lib/server/utils/config-env.js +2 -2
  65. package/lib/server/utils/dns.js +12 -18
  66. package/lib/server/utils/gcp-attestation.js +233 -181
  67. package/lib/server/utils/generics.d.ts +1 -1
  68. package/lib/server/utils/generics.js +43 -37
  69. package/lib/server/utils/iso.js +253 -256
  70. package/lib/server/utils/keep-alive.js +36 -36
  71. package/lib/server/utils/nitro-attestation.js +295 -220
  72. package/lib/server/utils/oprf-raw.js +48 -55
  73. package/lib/server/utils/process-handshake.js +200 -218
  74. package/lib/server/utils/proxy-session.js +5 -5
  75. package/lib/server/utils/tee-oprf-mpc-verification.js +82 -78
  76. package/lib/server/utils/tee-oprf-verification.js +165 -142
  77. package/lib/server/utils/tee-transcript-reconstruction.js +176 -129
  78. package/lib/server/utils/tee-verification.js +397 -334
  79. package/lib/server/utils/validation.js +30 -37
  80. package/lib/types/bgp.js +1 -0
  81. package/lib/types/claims.js +1 -0
  82. package/lib/types/client.js +1 -0
  83. package/lib/types/general.js +1 -0
  84. package/lib/types/handlers.js +1 -0
  85. package/lib/types/providers.d.ts +3 -2
  86. package/lib/types/providers.gen.js +9 -15
  87. package/lib/types/providers.js +1 -0
  88. package/lib/types/rpc.js +1 -0
  89. package/lib/types/signatures.d.ts +1 -2
  90. package/lib/types/signatures.js +1 -0
  91. package/lib/types/tunnel.js +1 -0
  92. package/lib/types/zk.js +1 -0
  93. package/lib/utils/auth.js +54 -66
  94. package/lib/utils/b64-json.js +15 -15
  95. package/lib/utils/bgp-listener.js +107 -111
  96. package/lib/utils/claims.js +89 -80
  97. package/lib/utils/env.js +13 -17
  98. package/lib/utils/error.js +43 -47
  99. package/lib/utils/generics.js +284 -235
  100. package/lib/utils/http-parser.js +232 -187
  101. package/lib/utils/logger.js +80 -71
  102. package/lib/utils/prepare-packets.js +69 -67
  103. package/lib/utils/redactions.js +163 -121
  104. package/lib/utils/retries.js +22 -24
  105. package/lib/utils/signatures/eth.js +29 -28
  106. package/lib/utils/signatures/index.js +5 -10
  107. package/lib/utils/socket-base.js +84 -88
  108. package/lib/utils/tls.js +28 -28
  109. package/lib/utils/ws.js +19 -19
  110. package/lib/utils/zk.js +542 -582
  111. package/package.json +12 -5
  112. package/lib/external-rpc/global.d.js +0 -0
  113. package/lib/scripts/build-browser.d.ts +0 -1
  114. package/lib/scripts/build-jsc.d.ts +0 -1
  115. package/lib/scripts/build-lib.d.ts +0 -1
  116. package/lib/scripts/check-avs-registration.d.ts +0 -1
  117. package/lib/scripts/check-avs-registration.js +0 -28
  118. package/lib/scripts/fallbacks/crypto.d.ts +0 -1
  119. package/lib/scripts/fallbacks/crypto.js +0 -4
  120. package/lib/scripts/fallbacks/empty.d.ts +0 -3
  121. package/lib/scripts/fallbacks/empty.js +0 -4
  122. package/lib/scripts/fallbacks/re2.d.ts +0 -1
  123. package/lib/scripts/fallbacks/re2.js +0 -7
  124. package/lib/scripts/fallbacks/snarkjs.d.ts +0 -1
  125. package/lib/scripts/fallbacks/snarkjs.js +0 -10
  126. package/lib/scripts/fallbacks/stwo.d.ts +0 -6
  127. package/lib/scripts/fallbacks/stwo.js +0 -159
  128. package/lib/scripts/generate-provider-types.d.ts +0 -5
  129. package/lib/scripts/generate-provider-types.js +0 -101
  130. package/lib/scripts/generate-receipt.d.ts +0 -9
  131. package/lib/scripts/generate-receipt.js +0 -101
  132. package/lib/scripts/generate-toprf-keys.d.ts +0 -1
  133. package/lib/scripts/generate-toprf-keys.js +0 -24
  134. package/lib/scripts/jsc-cli-rpc.d.ts +0 -1
  135. package/lib/scripts/jsc-cli-rpc.js +0 -35
  136. package/lib/scripts/register-avs-operator.d.ts +0 -1
  137. package/lib/scripts/register-avs-operator.js +0 -3
  138. package/lib/scripts/start-server.d.ts +0 -1
  139. package/lib/scripts/start-server.js +0 -11
  140. package/lib/scripts/update-avs-metadata.d.ts +0 -1
  141. package/lib/scripts/update-avs-metadata.js +0 -20
  142. package/lib/scripts/utils.d.ts +0 -1
  143. package/lib/scripts/utils.js +0 -10
  144. package/lib/scripts/whitelist-operator.d.ts +0 -1
  145. package/lib/scripts/whitelist-operator.js +0 -16
@@ -1,29 +1,24 @@
1
- import { EventLog } from "ethers";
1
+ import { EventLog } from 'ethers';
2
2
  import { getContracts } from "../../avs/utils/contracts.js";
3
3
  import { getEnvVariable } from "../../utils/env.js";
4
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
5
+ const ACCEPT_CLAIM_PAYMENT_REQUESTS = getEnvVariable('ACCEPT_CLAIM_PAYMENT_REQUESTS') === '1';
6
+ export const completeClaimOnChain = async ({ chainId: chainIdNum, taskIndex, completedTaskJson }) => {
7
+ if (!ACCEPT_CLAIM_PAYMENT_REQUESTS) {
8
+ throw new AttestorError('ERROR_PAYMENT_REFUSED', 'Payment requests are not accepted at this time');
9
+ }
10
+ const chainId = chainIdNum.toString();
11
+ const { contract } = getContracts(chainId.toString());
12
+ const task = JSON.parse(completedTaskJson);
13
+ const tx = await contract.taskCompleted(task, taskIndex);
14
+ const rslt = await tx.wait();
15
+ // check task created event was emitted
16
+ const logs = rslt?.logs ?? [];
17
+ const eventLogs = logs.filter((log) => log instanceof EventLog);
18
+ const obj = eventLogs[0]?.args;
19
+ const plainObj = ethersStructToPlainObject(obj);
20
+ return {
21
+ txHash: rslt?.hash ?? '',
22
+ taskCompletedObjectJson: JSON.stringify(plainObj)
23
+ };
29
24
  };
@@ -2,31 +2,25 @@ import { getContracts } from "../../avs/utils/contracts.js";
2
2
  import { createNewClaimRequestOnChain } from "../../avs/utils/tasks.js";
3
3
  import { getEnvVariable } from "../../utils/env.js";
4
4
  import { AttestorError, ethersStructToPlainObject } from "../../utils/index.js";
5
- const ACCEPT_CLAIM_PAYMENT_REQUESTS = getEnvVariable("ACCEPT_CLAIM_PAYMENT_REQUESTS") === "1";
6
- const createClaimOnChain = async ({ chainId: chainIdNum, jsonCreateClaimRequest, requestSignature }) => {
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 { wallet } = getContracts(chainId.toString());
15
- const request = JSON.parse(jsonCreateClaimRequest);
16
- const { task, tx } = await createNewClaimRequestOnChain({
17
- request,
18
- owner: request.owner,
19
- payer: wallet,
20
- chainId,
21
- requestSignature
22
- });
23
- const plainTask = ethersStructToPlainObject(task);
24
- return {
25
- txHash: tx?.hash ?? "",
26
- taskIndex: Number(task.taskIndex),
27
- jsonTask: JSON.stringify(plainTask)
28
- };
29
- };
30
- export {
31
- createClaimOnChain
5
+ const ACCEPT_CLAIM_PAYMENT_REQUESTS = getEnvVariable('ACCEPT_CLAIM_PAYMENT_REQUESTS') === '1';
6
+ export const createClaimOnChain = async ({ chainId: chainIdNum, jsonCreateClaimRequest, requestSignature }) => {
7
+ if (!ACCEPT_CLAIM_PAYMENT_REQUESTS) {
8
+ throw new AttestorError('ERROR_PAYMENT_REFUSED', 'Payment requests are not accepted at this time');
9
+ }
10
+ const chainId = chainIdNum.toString();
11
+ const { wallet } = getContracts(chainId.toString());
12
+ const request = JSON.parse(jsonCreateClaimRequest);
13
+ const { task, tx } = await createNewClaimRequestOnChain({
14
+ request,
15
+ owner: request.owner,
16
+ payer: wallet,
17
+ chainId,
18
+ requestSignature: requestSignature
19
+ });
20
+ const plainTask = ethersStructToPlainObject(task);
21
+ return {
22
+ txHash: tx?.hash ?? '',
23
+ taskIndex: Number(task.taskIndex),
24
+ jsonTask: JSON.stringify(plainTask)
25
+ };
32
26
  };
@@ -1,57 +1,47 @@
1
- import { Contract, JsonRpcProvider, randomBytes, Wallet } from "ethers";
1
+ import { Contract, JsonRpcProvider, randomBytes, Wallet } from 'ethers';
2
2
  import { governanceABI } from "../../mechain/abis/governanceABI.js";
3
3
  import { taskABI } from "../../mechain/abis/taskABI.js";
4
4
  import { GOVERNANCE_CONTRACT_ADDRESS, RPC_URL, TASK_CONTRACT_ADDRESS } from "../../mechain/constants/index.js";
5
5
  import { getEnvVariable } from "../../utils/env.js";
6
- const createTaskOnMechain = async ({
7
- timestamp
8
- }) => {
9
- const { taskContract } = await getContracts();
10
- const seed = randomBytes(32);
11
- const result = await taskContract.createNewTaskRequest.staticCall(
12
- seed,
13
- timestamp
14
- );
15
- const taskId = result[0];
16
- const requiredAttestors = await taskContract.requiredAttestors();
17
- const hosts = [];
18
- for (let i = 0; i < requiredAttestors; i++) {
19
- hosts.push(result[1][i].host);
20
- }
21
- const tx = await taskContract.createNewTaskRequest(seed, timestamp);
22
- await tx.wait();
23
- return {
24
- taskId,
25
- requiredAttestors,
26
- hosts
27
- };
6
+ export const createTaskOnMechain = async ({ timestamp }) => {
7
+ const { taskContract } = await getContracts();
8
+ const seed = randomBytes(32);
9
+ // Perform a static call to fetch taskId and attestors for the next task
10
+ const result = await taskContract.createNewTaskRequest.staticCall(seed, timestamp);
11
+ const taskId = result[0];
12
+ // Fetch requiredAttestors to determine how many proofs to request
13
+ const requiredAttestors = await taskContract.requiredAttestors();
14
+ const hosts = [];
15
+ // Fetch attestors's WebSocket URI, e.g. wss://attestor.reclaimprotocol.org:444/ws
16
+ for (let i = 0; i < requiredAttestors; i++) {
17
+ hosts.push(result[1][i].host);
18
+ }
19
+ // Perform the call that was statically-called previously
20
+ const tx = await taskContract.createNewTaskRequest(seed, timestamp);
21
+ await tx.wait();
22
+ return {
23
+ taskId: taskId,
24
+ requiredAttestors: requiredAttestors,
25
+ hosts: hosts
26
+ };
28
27
  };
29
28
  async function getContracts() {
30
- const privateKey = getEnvVariable("MECHAIN_PRIVATE_KEY");
31
- const taskContractAddress = getEnvVariable("TASK_CONTRACT_ADDRESS") || TASK_CONTRACT_ADDRESS;
32
- const governanceContractAddress = getEnvVariable("GOVERNANCE_CONTRACT_ADDRESS") || GOVERNANCE_CONTRACT_ADDRESS;
33
- if (!privateKey) {
34
- throw new Error("MECHAIN_PRIVATE_KEY environment variable is not set");
35
- }
36
- try {
37
- const provider = new JsonRpcProvider(RPC_URL);
38
- await provider.getNetwork();
39
- const signer = new Wallet(privateKey, provider);
40
- const taskContract = new Contract(
41
- taskContractAddress,
42
- taskABI,
43
- signer
44
- );
45
- const governanceContract = new Contract(
46
- governanceContractAddress,
47
- governanceABI,
48
- signer
49
- );
50
- return { taskContract, governanceContract };
51
- } catch (error) {
52
- throw new Error(`Failed to initialize contracts: ${error.message || error}`);
53
- }
29
+ const privateKey = getEnvVariable('MECHAIN_PRIVATE_KEY');
30
+ const taskContractAddress = getEnvVariable('TASK_CONTRACT_ADDRESS') || TASK_CONTRACT_ADDRESS;
31
+ const governanceContractAddress = getEnvVariable('GOVERNANCE_CONTRACT_ADDRESS') || GOVERNANCE_CONTRACT_ADDRESS;
32
+ if (!privateKey) {
33
+ throw new Error('MECHAIN_PRIVATE_KEY environment variable is not set');
34
+ }
35
+ try {
36
+ const provider = new JsonRpcProvider(RPC_URL);
37
+ // Validate connection to provider
38
+ await provider.getNetwork();
39
+ const signer = new Wallet(privateKey, provider);
40
+ const taskContract = new Contract(taskContractAddress, taskABI, signer);
41
+ const governanceContract = new Contract(governanceContractAddress, governanceABI, signer);
42
+ return { taskContract, governanceContract };
43
+ }
44
+ catch (error) {
45
+ throw new Error(`Failed to initialize contracts: ${error.message || error}`);
46
+ }
54
47
  }
55
- export {
56
- createTaskOnMechain
57
- };
@@ -1,98 +1,93 @@
1
- import { makeTcpTunnel } from "../../server/tunnels/make-tcp-tunnel.js";
2
- import { getApm } from "../../server/utils/apm.js";
3
- import { resolveHostnames } from "../../server/utils/dns.js";
1
+ import { makeTcpTunnel } from "../tunnels/make-tcp-tunnel.js";
2
+ import { getApm } from "../utils/apm.js";
3
+ import { resolveHostnames } from "../utils/dns.js";
4
4
  import { AttestorError } from "../../utils/index.js";
5
- const createTunnel = async ({ id, ...opts }, { tx, logger, client }) => {
6
- if (client.tunnels[id]) {
7
- throw AttestorError.badRequest(`Tunnel "${id}" already exists`);
8
- }
9
- const allowedHosts = client.metadata?.auth?.data?.hostWhitelist;
10
- if (allowedHosts?.length && !allowedHosts.includes(opts.host)) {
11
- throw AttestorError.badRequest(
12
- `Host "${opts.host}" not allowed by auth request`
13
- );
14
- }
15
- let cancelBgp;
16
- const apm = getApm();
17
- const sessionTx = apm?.startTransaction("tunnelConnection", { childOf: tx });
18
- sessionTx?.setLabel("tunnelId", id.toString());
19
- sessionTx?.setLabel("hostPort", `${opts.host}:${opts.port}`);
20
- sessionTx?.setLabel("geoLocation", opts.geoLocation);
21
- sessionTx?.setLabel("proxySessionId", opts.proxySessionId);
22
- try {
23
- const tunnel = await makeTcpTunnel({
24
- ...opts,
25
- logger,
26
- onMessage(message) {
27
- if (!client.isOpen) {
28
- logger.warn("client is closed, dropping message");
29
- return;
5
+ export const createTunnel = async ({ id, ...opts }, { tx, logger, client }) => {
6
+ if (client.tunnels[id]) {
7
+ throw AttestorError.badRequest(`Tunnel "${id}" already exists`);
8
+ }
9
+ const allowedHosts = client.metadata?.auth?.data?.hostWhitelist;
10
+ if (allowedHosts?.length && !allowedHosts.includes(opts.host)) {
11
+ throw AttestorError.badRequest(`Host "${opts.host}" not allowed by auth request`);
12
+ }
13
+ let cancelBgp;
14
+ const apm = getApm();
15
+ const sessionTx = apm
16
+ ?.startTransaction('tunnelConnection', { childOf: tx });
17
+ sessionTx?.setLabel('tunnelId', id.toString());
18
+ sessionTx?.setLabel('hostPort', `${opts.host}:${opts.port}`);
19
+ sessionTx?.setLabel('geoLocation', opts.geoLocation);
20
+ sessionTx?.setLabel('proxySessionId', opts.proxySessionId);
21
+ try {
22
+ const tunnel = await makeTcpTunnel({
23
+ ...opts,
24
+ logger,
25
+ onMessage(message) {
26
+ if (!client.isOpen) {
27
+ logger.warn('client is closed, dropping message');
28
+ return;
29
+ }
30
+ return client
31
+ .sendMessage({ tunnelMessage: { tunnelId: id, message } });
32
+ },
33
+ onClose(err) {
34
+ cancelBgp?.();
35
+ if (err) {
36
+ apm?.captureError(err, { parent: sessionTx });
37
+ sessionTx?.setOutcome('failure');
38
+ }
39
+ else {
40
+ sessionTx?.setOutcome('success');
41
+ }
42
+ sessionTx?.end();
43
+ if (!client.isOpen) {
44
+ return;
45
+ }
46
+ client.sendMessage({
47
+ tunnelDisconnectEvent: {
48
+ tunnelId: id,
49
+ error: err
50
+ ? AttestorError
51
+ .fromError(err)
52
+ .toProto()
53
+ : undefined
54
+ }
55
+ })
56
+ .catch(err => {
57
+ logger.error({ err }, 'failed to send tunnel disconnect event');
58
+ });
59
+ },
60
+ });
61
+ try {
62
+ await checkForBgp(tunnel);
30
63
  }
31
- return client.sendMessage({ tunnelMessage: { tunnelId: id, message } });
32
- },
33
- onClose(err) {
34
- cancelBgp?.();
35
- if (err) {
36
- apm?.captureError(err, { parent: sessionTx });
37
- sessionTx?.setOutcome("failure");
38
- } else {
39
- sessionTx?.setOutcome("success");
64
+ catch (err) {
65
+ logger.warn({ err, host: opts.host }, 'failed to start BGP overlap check');
40
66
  }
67
+ client.tunnels[id] = tunnel;
68
+ return {};
69
+ }
70
+ catch (err) {
71
+ apm?.captureError(err, { parent: sessionTx });
72
+ sessionTx?.setOutcome('failure');
41
73
  sessionTx?.end();
42
- if (!client.isOpen) {
43
- return;
74
+ cancelBgp?.();
75
+ throw err;
76
+ }
77
+ async function checkForBgp(tunnel) {
78
+ if (!client.bgpListener) {
79
+ return;
44
80
  }
45
- client.sendMessage({
46
- tunnelDisconnectEvent: {
47
- tunnelId: id,
48
- error: err ? AttestorError.fromError(err).toProto() : void 0
49
- }
50
- }).catch((err2) => {
51
- logger.error(
52
- { err: err2 },
53
- "failed to send tunnel disconnect event"
54
- );
81
+ // listen to all IPs for the host -- in case any of them
82
+ // has a BGP announcement overlap, we'll close the tunnel
83
+ // so the user can retry
84
+ const ips = await resolveHostnames(opts.host);
85
+ cancelBgp = client.bgpListener.onOverlap(ips, (info) => {
86
+ logger.warn({ info, host: opts.host }, 'BGP announcement overlap detected');
87
+ // track how many times we've seen a BGP overlap
88
+ sessionTx?.addLabels({ bgpOverlap: true, ...info });
89
+ void tunnel?.close(new AttestorError('ERROR_BGP_ANNOUNCEMENT_OVERLAP', `BGP announcement overlap detected for ${opts.host}`));
55
90
  });
56
- }
57
- });
58
- try {
59
- await checkForBgp(tunnel);
60
- } catch (err) {
61
- logger.warn(
62
- { err, host: opts.host },
63
- "failed to start BGP overlap check"
64
- );
91
+ logger.debug({ ips }, 'checking for BGP overlap');
65
92
  }
66
- client.tunnels[id] = tunnel;
67
- return {};
68
- } catch (err) {
69
- apm?.captureError(err, { parent: sessionTx });
70
- sessionTx?.setOutcome("failure");
71
- sessionTx?.end();
72
- cancelBgp?.();
73
- throw err;
74
- }
75
- async function checkForBgp(tunnel) {
76
- if (!client.bgpListener) {
77
- return;
78
- }
79
- const ips = await resolveHostnames(opts.host);
80
- cancelBgp = client.bgpListener.onOverlap(ips, (info) => {
81
- logger.warn(
82
- { info, host: opts.host },
83
- "BGP announcement overlap detected"
84
- );
85
- sessionTx?.addLabels({ bgpOverlap: true, ...info });
86
- void tunnel?.close(
87
- new AttestorError(
88
- "ERROR_BGP_ANNOUNCEMENT_OVERLAP",
89
- `BGP announcement overlap detected for ${opts.host}`
90
- )
91
- );
92
- });
93
- logger.debug({ ips }, "checking for BGP overlap");
94
- }
95
- };
96
- export {
97
- createTunnel
98
93
  };
@@ -1,8 +1,5 @@
1
- const disconnectTunnel = async ({ id }, { client }) => {
2
- const tunnel = client.getTunnel(id);
3
- await tunnel.close();
4
- return {};
5
- };
6
- export {
7
- disconnectTunnel
1
+ export const disconnectTunnel = async ({ id }, { client }) => {
2
+ const tunnel = client.getTunnel(id);
3
+ await tunnel.close();
4
+ return {};
8
5
  };
@@ -1,57 +1,41 @@
1
- import { concatenateUint8Arrays, loadX509FromPem } from "@reclaimprotocol/tls";
1
+ import { concatenateUint8Arrays, loadX509FromPem } from '@reclaimprotocol/tls';
2
2
  import { CERT_ALLOWED_MIMETYPES, MAX_CERT_SIZE_BYTES } from "../../config/index.js";
3
3
  import { AttestorError } from "../../utils/error.js";
4
- const fetchCertificateBytes = async ({ url }) => {
5
- const res = await fetch(url, {
6
- redirect: "follow",
7
- signal: AbortSignal.timeout(1e4)
8
- });
9
- if (!res.ok) {
10
- res.body?.cancel("Not ok");
11
- throw new AttestorError(
12
- "ERROR_CERTIFICATE_FETCH_FAILED",
13
- `Failed to fetch certificate from URL: ${url}, status: ${res.status}`
14
- );
15
- }
16
- const contentType = res.headers.get("content-type");
17
- if (!contentType || !CERT_ALLOWED_MIMETYPES.includes(contentType)) {
18
- res.body?.cancel("Mismatch");
19
- throw new AttestorError(
20
- "ERROR_CERTIFICATE_FETCH_FAILED",
21
- `Invalid content-type when fetching certificate from URL: ${url}, content-type: ${contentType}`
22
- );
23
- }
24
- if (!res.body) {
25
- throw new AttestorError(
26
- "ERROR_CERTIFICATE_FETCH_FAILED",
27
- `No body in response when fetching certificate from URL: ${url}`
28
- );
29
- }
30
- let total = 0;
31
- const byteArr = [];
32
- for await (const chunk of res.body) {
33
- total += chunk.length;
34
- if (total > MAX_CERT_SIZE_BYTES) {
35
- res.body.cancel("Too many bytes");
36
- throw new AttestorError(
37
- "ERROR_CERTIFICATE_FETCH_FAILED",
38
- `Certificate size exceeds maximum limit of ${MAX_CERT_SIZE_BYTES}b`
39
- );
4
+ export const fetchCertificateBytes = async ({ url }) => {
5
+ const res = await fetch(url, {
6
+ redirect: 'follow',
7
+ signal: AbortSignal.timeout(10_000)
8
+ });
9
+ if (!res.ok) {
10
+ res.body?.cancel('Not ok');
11
+ throw new AttestorError('ERROR_CERTIFICATE_FETCH_FAILED', `Failed to fetch certificate from URL: ${url}, status: ${res.status}`);
40
12
  }
41
- byteArr.push(chunk);
42
- }
43
- const bytes = concatenateUint8Arrays(byteArr);
44
- try {
45
- const cert = loadX509FromPem(bytes);
46
- TLS_INTERMEDIATE_CA_CACHE[url] = cert;
47
- } catch (err) {
48
- throw new AttestorError(
49
- "ERROR_CERTIFICATE_FETCH_FAILED",
50
- `Failed to parse certificate, error: ${err.message}`
51
- );
52
- }
53
- return { bytes: concatenateUint8Arrays(byteArr) };
54
- };
55
- export {
56
- fetchCertificateBytes
13
+ const contentType = res.headers.get('content-type');
14
+ if (!contentType || !CERT_ALLOWED_MIMETYPES.includes(contentType)) {
15
+ res.body?.cancel('Mismatch');
16
+ throw new AttestorError('ERROR_CERTIFICATE_FETCH_FAILED', `Invalid content-type when fetching certificate from URL: ${url},`
17
+ + ` content-type: ${contentType}`);
18
+ }
19
+ if (!res.body) {
20
+ throw new AttestorError('ERROR_CERTIFICATE_FETCH_FAILED', `No body in response when fetching certificate from URL: ${url}`);
21
+ }
22
+ let total = 0;
23
+ const byteArr = [];
24
+ for await (const chunk of res.body) {
25
+ total += chunk.length;
26
+ if (total > MAX_CERT_SIZE_BYTES) {
27
+ res.body.cancel('Too many bytes');
28
+ throw new AttestorError('ERROR_CERTIFICATE_FETCH_FAILED', `Certificate size exceeds maximum limit of ${MAX_CERT_SIZE_BYTES}b`);
29
+ }
30
+ byteArr.push(chunk);
31
+ }
32
+ const bytes = concatenateUint8Arrays(byteArr);
33
+ try {
34
+ const cert = loadX509FromPem(bytes);
35
+ TLS_INTERMEDIATE_CA_CACHE[url] = cert;
36
+ }
37
+ catch (err) {
38
+ throw new AttestorError('ERROR_CERTIFICATE_FETCH_FAILED', `Failed to parse certificate, error: ${err.message}`);
39
+ }
40
+ return { bytes: concatenateUint8Arrays(byteArr) };
57
41
  };
@@ -1,25 +1,22 @@
1
- import { claimTeeBundle } from "../../server/handlers/claimTeeBundle.js";
2
- import { claimTunnel } from "../../server/handlers/claimTunnel.js";
3
- import { completeClaimOnChain } from "../../server/handlers/completeClaimOnChain.js";
4
- import { createClaimOnChain } from "../../server/handlers/createClaimOnChain.js";
5
- import { createTaskOnMechain } from "../../server/handlers/createTaskOnMechain.js";
6
- import { createTunnel } from "../../server/handlers/createTunnel.js";
7
- import { disconnectTunnel } from "../../server/handlers/disconnectTunnel.js";
8
- import { fetchCertificateBytes } from "../../server/handlers/fetchCertificateBytes.js";
9
- import { init } from "../../server/handlers/init.js";
10
- import { toprf } from "../../server/handlers/toprf.js";
11
- const HANDLERS = {
12
- createTunnel,
13
- disconnectTunnel,
14
- claimTunnel,
15
- claimTeeBundle,
16
- init,
17
- createClaimOnChain,
18
- completeClaimOnChain,
19
- toprf,
20
- createTaskOnMechain,
21
- fetchCertificateBytes
22
- };
23
- export {
24
- HANDLERS
1
+ import { claimTeeBundle } from "./claimTeeBundle.js";
2
+ import { claimTunnel } from "./claimTunnel.js";
3
+ import { completeClaimOnChain } from "./completeClaimOnChain.js";
4
+ import { createClaimOnChain } from "./createClaimOnChain.js";
5
+ import { createTaskOnMechain } from "./createTaskOnMechain.js";
6
+ import { createTunnel } from "./createTunnel.js";
7
+ import { disconnectTunnel } from "./disconnectTunnel.js";
8
+ import { fetchCertificateBytes } from "./fetchCertificateBytes.js";
9
+ import { init } from "./init.js";
10
+ import { toprf } from "./toprf.js";
11
+ export const HANDLERS = {
12
+ createTunnel,
13
+ disconnectTunnel,
14
+ claimTunnel,
15
+ claimTeeBundle,
16
+ init,
17
+ createClaimOnChain,
18
+ completeClaimOnChain,
19
+ toprf,
20
+ createTaskOnMechain,
21
+ fetchCertificateBytes
25
22
  };
@@ -1,33 +1,32 @@
1
- import { getBytes } from "ethers";
2
- import { getAttestorAddress } from "../../server/utils/generics.js";
1
+ import { getBytes } from 'ethers';
2
+ import { getAttestorAddress } from "../utils/generics.js";
3
3
  import { assertValidAuthRequest } from "../../utils/auth.js";
4
4
  import { getEnvVariable } from "../../utils/env.js";
5
5
  import { AttestorError } from "../../utils/index.js";
6
6
  import { SIGNATURES } from "../../utils/signatures/index.js";
7
- const TOPRF_PUBLIC_KEY = getEnvVariable("TOPRF_PUBLIC_KEY");
8
- const init = async (initRequest, { client }) => {
9
- if (client.isInitialised) {
10
- throw AttestorError.badRequest("Client already initialised");
11
- }
12
- if (!SIGNATURES[initRequest.signatureType]) {
13
- throw AttestorError.badRequest("Unsupported signature type");
14
- }
15
- if (initRequest.clientVersion <= 0) {
16
- throw AttestorError.badRequest("Unsupported client version");
17
- }
18
- await assertValidAuthRequest(initRequest.auth, initRequest.signatureType);
19
- if (initRequest.auth?.data) {
20
- client.logger = client.logger.child({
21
- userId: initRequest.auth.data.id
22
- });
23
- }
24
- client.metadata = initRequest;
25
- client.isInitialised = true;
26
- return {
27
- toprfPublicKey: TOPRF_PUBLIC_KEY ? getBytes(TOPRF_PUBLIC_KEY) : new Uint8Array(),
28
- attestorAddress: getAttestorAddress(initRequest.signatureType)
29
- };
30
- };
31
- export {
32
- init
7
+ const TOPRF_PUBLIC_KEY = getEnvVariable('TOPRF_PUBLIC_KEY');
8
+ export const init = async (initRequest, { client }) => {
9
+ if (client.isInitialised) {
10
+ throw AttestorError.badRequest('Client already initialised');
11
+ }
12
+ if (!SIGNATURES[initRequest.signatureType]) {
13
+ throw AttestorError.badRequest('Unsupported signature type');
14
+ }
15
+ if (initRequest.clientVersion <= 0) {
16
+ throw AttestorError.badRequest('Unsupported client version');
17
+ }
18
+ await assertValidAuthRequest(initRequest.auth, initRequest.signatureType);
19
+ if (initRequest.auth?.data) {
20
+ client.logger = client.logger.child({
21
+ userId: initRequest.auth.data.id
22
+ });
23
+ }
24
+ client.metadata = initRequest;
25
+ client.isInitialised = true;
26
+ return {
27
+ toprfPublicKey: TOPRF_PUBLIC_KEY
28
+ ? getBytes(TOPRF_PUBLIC_KEY)
29
+ : new Uint8Array(),
30
+ attestorAddress: getAttestorAddress(initRequest.signatureType)
31
+ };
33
32
  };
@@ -1,19 +1,16 @@
1
- import { getBytes } from "ethers";
1
+ import { getBytes } from 'ethers';
2
2
  import { getEnvVariable } from "../../utils/env.js";
3
3
  import { getEngineString, makeDefaultOPRFOperator } from "../../utils/index.js";
4
- const toprf = async ({ maskedData, engine }, { logger }) => {
5
- const PRIVATE_KEY_STR = getEnvVariable("TOPRF_SHARE_PRIVATE_KEY");
6
- const PUBLIC_KEY_STR = getEnvVariable("TOPRF_SHARE_PUBLIC_KEY");
7
- if (!PRIVATE_KEY_STR || !PUBLIC_KEY_STR) {
8
- throw new Error("private/public keys not set. Cannot execute OPRF");
9
- }
10
- const PRIVATE_KEY = getBytes(PRIVATE_KEY_STR);
11
- const PUBLIC_KEY = getBytes(PUBLIC_KEY_STR);
12
- const engineStr = getEngineString(engine);
13
- const operator = makeDefaultOPRFOperator("chacha20", engineStr, logger);
14
- const res = await operator.evaluateOPRF(PRIVATE_KEY, maskedData);
15
- return { ...res, publicKeyShare: PUBLIC_KEY };
16
- };
17
- export {
18
- toprf
4
+ export const toprf = async ({ maskedData, engine }, { logger }) => {
5
+ const PRIVATE_KEY_STR = getEnvVariable('TOPRF_SHARE_PRIVATE_KEY');
6
+ const PUBLIC_KEY_STR = getEnvVariable('TOPRF_SHARE_PUBLIC_KEY');
7
+ if (!PRIVATE_KEY_STR || !PUBLIC_KEY_STR) {
8
+ throw new Error('private/public keys not set. Cannot execute OPRF');
9
+ }
10
+ const PRIVATE_KEY = getBytes(PRIVATE_KEY_STR);
11
+ const PUBLIC_KEY = getBytes(PUBLIC_KEY_STR);
12
+ const engineStr = getEngineString(engine);
13
+ const operator = makeDefaultOPRFOperator('chacha20', engineStr, logger);
14
+ const res = await operator.evaluateOPRF(PRIVATE_KEY, maskedData);
15
+ return { ...res, publicKeyShare: PUBLIC_KEY };
19
16
  };