@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,461 +1,432 @@
1
- import { asciiToUint8Array } from "@reclaimprotocol/tls";
2
- import { makeRpcTlsTunnel } from "../client/tunnels/make-rpc-tls-tunnel.js";
3
- import { getAttestorClientFromPool } from "../client/utils/attestor-pool.js";
1
+ import { asciiToUint8Array } from '@reclaimprotocol/tls';
2
+ import { makeRpcTlsTunnel } from "./tunnels/make-rpc-tls-tunnel.js";
3
+ import { getAttestorClientFromPool } from "./utils/attestor-pool.js";
4
4
  import { DEFAULT_HTTPS_PORT, PROVIDER_CTX, TOPRF_DOMAIN_SEPARATOR } from "../config/index.js";
5
5
  import { ClaimTunnelRequest } from "../proto/api.js";
6
6
  import { providers } from "../providers/index.js";
7
- import {
8
- AttestorError,
9
- binaryHashToStr,
10
- canonicalStringify,
11
- generateTunnelId,
12
- getBlocksToReveal,
13
- getEngineProto,
14
- getProviderValue,
15
- isApplicationData,
16
- logger as LOGGER,
17
- makeDefaultOPRFOperator,
18
- makeHttpResponseParser,
19
- preparePacketsForReveal,
20
- redactSlices,
21
- uint8ArrayToStr,
22
- unixTimestampSeconds
23
- } from "../utils/index.js";
7
+ import { AttestorError, binaryHashToStr, canonicalStringify, generateTunnelId, getBlocksToReveal, getEngineProto, getProviderValue, isApplicationData, logger as LOGGER, makeDefaultOPRFOperator, makeHttpResponseParser, preparePacketsForReveal, redactSlices, uint8ArrayToStr, unixTimestampSeconds } from "../utils/index.js";
24
8
  import { executeWithRetries } from "../utils/retries.js";
25
9
  import { SIGNATURES } from "../utils/signatures/index.js";
26
10
  import { getDefaultTlsOptions } from "../utils/tls.js";
27
- function createClaimOnAttestor({
28
- logger: _logger,
29
- maxRetries = 3,
30
- ...opts
31
- }) {
32
- const logger = _logger || ("logger" in opts.client ? opts.client.logger : LOGGER);
33
- return executeWithRetries(
34
- (attempt) => _createClaimOnAttestor({
35
- ...opts,
36
- logger: attempt ? logger.child({ attempt }) : logger
37
- }),
38
- { maxRetries, logger, shouldRetry }
39
- );
11
+ /**
12
+ * Create a claim on the attestor
13
+ */
14
+ export function createClaimOnAttestor({ logger: _logger, maxRetries = 3, ...opts }) {
15
+ const logger = _logger
16
+ // if the client has already been initialised
17
+ // and no logger is provided, use the client's logger
18
+ // otherwise default to the global logger
19
+ || ('logger' in opts.client ? opts.client.logger : LOGGER);
20
+ return executeWithRetries(attempt => (_createClaimOnAttestor({
21
+ ...opts,
22
+ logger: attempt ? logger.child({ attempt }) : logger
23
+ })), { maxRetries, logger, shouldRetry });
40
24
  }
41
25
  function shouldRetry(err) {
42
- if (err instanceof TypeError) {
43
- return false;
44
- }
45
- if (err?.message?.includes("stream ended before")) {
46
- return true;
47
- }
48
- return err instanceof AttestorError && err.code !== "ERROR_INVALID_CLAIM" && err.code !== "ERROR_BAD_REQUEST" && err.code !== "ERROR_AUTHENTICATION_FAILED" && err.code !== "ERROR_TOPRF_OUT_OF_BOUNDS";
26
+ if (err instanceof TypeError) {
27
+ return false;
28
+ }
29
+ // possibly a network error, or the server
30
+ // closed the connection before we received the full data
31
+ if (err?.message?.includes('stream ended before')) {
32
+ return true;
33
+ }
34
+ return err instanceof AttestorError
35
+ && err.code !== 'ERROR_INVALID_CLAIM'
36
+ && err.code !== 'ERROR_BAD_REQUEST'
37
+ && err.code !== 'ERROR_AUTHENTICATION_FAILED'
38
+ && err.code !== 'ERROR_TOPRF_OUT_OF_BOUNDS';
49
39
  }
50
- async function _createClaimOnAttestor({
51
- name,
52
- params,
53
- secretParams,
54
- context,
55
- onStep,
56
- ownerPrivateKey,
57
- client: clientInit,
58
- logger = LOGGER,
59
- timestampS,
60
- updateProviderParams,
61
- updateParametersFromOprfData = true,
62
- ...zkOpts
63
- }) {
64
- const provider = providers[name];
65
- const hostPort = getProviderValue(params, provider.hostPort, secretParams);
66
- const geoLocation = getProviderValue(params, provider.geoLocation, secretParams);
67
- const proxySessionId = getProviderValue(params, provider.proxySessionId, secretParams);
68
- const providerTlsOpts = getProviderValue(
69
- params,
70
- provider.additionalClientOptions
71
- );
72
- const tlsOpts = {
73
- ...getDefaultTlsOptions(),
74
- fetchCertificateBytes: fetchCertificateBytesFromAttestor,
75
- ...providerTlsOpts
76
- };
77
- const { zkEngine = "snarkjs" } = zkOpts;
78
- let redactionMode = getProviderValue(params, provider.writeRedactionMode);
79
- const [host, port] = hostPort.split(":");
80
- const resParser = makeHttpResponseParser();
81
- let client;
82
- let lastMsgRevealed = false;
83
- const revealMap = /* @__PURE__ */ new Map();
84
- onStep?.({ name: "connecting" });
85
- let endedHttpRequest;
86
- const createTunnelReq = {
87
- host,
88
- port: port ? +port : DEFAULT_HTTPS_PORT,
89
- geoLocation,
90
- proxySessionId,
91
- id: generateTunnelId()
92
- };
93
- logger = logger.child({ tunnelId: createTunnelReq.id });
94
- const authRequest = "authRequest" in clientInit ? typeof clientInit.authRequest === "function" ? await clientInit.authRequest() : clientInit.authRequest : void 0;
95
- const tunnel = await makeRpcTlsTunnel({
96
- tlsOpts,
97
- connect: (connectMsgs) => {
98
- let created = false;
99
- if ("metadata" in clientInit) {
100
- client = clientInit;
101
- } else {
102
- client = getAttestorClientFromPool(
103
- clientInit.url,
104
- () => {
105
- created = true;
106
- return {
107
- authRequest,
108
- initMessages: connectMsgs,
109
- logger
110
- };
111
- }
112
- );
113
- }
114
- if (!created) {
115
- client.waitForInit().then(() => client.sendMessage(...connectMsgs)).catch((err) => {
116
- logger.error(
117
- { err },
118
- "error in sending init msgs"
119
- );
120
- });
121
- }
122
- return client;
123
- },
124
- logger,
125
- request: createTunnelReq,
126
- onMessage(data) {
127
- logger.debug({ bytes: data.length }, "recv data from server");
128
- resParser.onChunk(data);
129
- if (resParser.res.complete) {
130
- logger?.debug("got complete HTTP response from server");
131
- setTimeout(() => {
132
- endedHttpRequest?.();
133
- }, 100);
134
- }
135
- },
136
- onClose(err) {
137
- const level = err ? "error" : "debug";
138
- logger?.[level]({ err }, "tls session ended");
139
- endedHttpRequest?.(err);
140
- try {
141
- resParser.streamEnded();
142
- } catch {
143
- }
40
+ async function _createClaimOnAttestor({ name, params, secretParams, context, onStep, ownerPrivateKey, client: clientInit, logger = LOGGER, timestampS, updateProviderParams, updateParametersFromOprfData = true, ...zkOpts }) {
41
+ const provider = providers[name];
42
+ const hostPort = getProviderValue(params, provider.hostPort, secretParams);
43
+ const geoLocation = getProviderValue(params, provider.geoLocation, secretParams);
44
+ const proxySessionId = getProviderValue(params, provider.proxySessionId, secretParams);
45
+ const providerTlsOpts = getProviderValue(params, provider.additionalClientOptions);
46
+ const tlsOpts = {
47
+ ...getDefaultTlsOptions(),
48
+ fetchCertificateBytes: fetchCertificateBytesFromAttestor,
49
+ ...providerTlsOpts
50
+ };
51
+ const { zkEngine = 'snarkjs' } = zkOpts;
52
+ let redactionMode = getProviderValue(params, provider.writeRedactionMode);
53
+ const [host, port] = hostPort.split(':');
54
+ const resParser = makeHttpResponseParser();
55
+ let client;
56
+ let lastMsgRevealed = false;
57
+ const revealMap = new Map();
58
+ onStep?.({ name: 'connecting' });
59
+ let endedHttpRequest;
60
+ const createTunnelReq = {
61
+ host,
62
+ port: port ? +port : DEFAULT_HTTPS_PORT,
63
+ geoLocation,
64
+ proxySessionId,
65
+ id: generateTunnelId()
66
+ };
67
+ logger = logger.child({ tunnelId: createTunnelReq.id });
68
+ const authRequest = 'authRequest' in clientInit
69
+ ? (typeof clientInit.authRequest === 'function'
70
+ ? await clientInit.authRequest()
71
+ : clientInit.authRequest)
72
+ : undefined;
73
+ const tunnel = await makeRpcTlsTunnel({
74
+ tlsOpts,
75
+ connect: (connectMsgs) => {
76
+ let created = false;
77
+ if ('metadata' in clientInit) {
78
+ client = clientInit;
79
+ }
80
+ else {
81
+ client = getAttestorClientFromPool(clientInit.url, () => {
82
+ created = true;
83
+ return {
84
+ authRequest: authRequest,
85
+ initMessages: connectMsgs,
86
+ logger
87
+ };
88
+ });
89
+ }
90
+ if (!created) {
91
+ client
92
+ .waitForInit()
93
+ .then(() => client.sendMessage(...connectMsgs))
94
+ .catch(err => {
95
+ logger.error({ err }, 'error in sending init msgs');
96
+ });
97
+ }
98
+ return client;
99
+ },
100
+ logger,
101
+ request: createTunnelReq,
102
+ onMessage(data) {
103
+ logger.debug({ bytes: data.length }, 'recv data from server');
104
+ resParser.onChunk(data);
105
+ if (resParser.res.complete) {
106
+ logger?.debug('got complete HTTP response from server');
107
+ // wait a little bit to make sure the client has
108
+ // finished writing the response
109
+ setTimeout(() => {
110
+ endedHttpRequest?.();
111
+ }, 100);
112
+ }
113
+ },
114
+ onClose(err) {
115
+ const level = err ? 'error' : 'debug';
116
+ logger?.[level]({ err }, 'tls session ended');
117
+ endedHttpRequest?.(err);
118
+ try {
119
+ resParser.streamEnded();
120
+ }
121
+ catch { }
122
+ },
123
+ });
124
+ const { version: tlsVersion, cipherSuite } = tunnel.tls.getMetadata();
125
+ if (tlsVersion === 'TLS1_2' && redactionMode !== 'zk') {
126
+ redactionMode = 'zk';
127
+ logger.info('TLS1.2 detected, defaulting to zk redaction mode');
144
128
  }
145
- });
146
- const {
147
- version: tlsVersion,
148
- cipherSuite
149
- } = tunnel.tls.getMetadata();
150
- if (tlsVersion === "TLS1_2" && redactionMode !== "zk") {
151
- redactionMode = "zk";
152
- logger.info("TLS1.2 detected, defaulting to zk redaction mode");
153
- }
154
- const {
155
- redactions,
156
- data: requestStr
157
- } = provider.createRequest(
129
+ const { redactions, data: requestStr } = provider.createRequest(
158
130
  // @ts-ignore
159
- secretParams,
160
- params,
161
- logger
162
- );
163
- const requestData = typeof requestStr === "string" ? asciiToUint8Array(requestStr) : requestStr;
164
- logger.debug(
165
- { redactions: redactions.length },
166
- "generated request"
167
- );
168
- const waitForAllData = new Promise(
169
- (resolve, reject) => {
170
- endedHttpRequest = (err) => err ? reject(err) : resolve();
131
+ secretParams, params, logger);
132
+ const requestData = typeof requestStr === 'string'
133
+ ? asciiToUint8Array(requestStr)
134
+ : requestStr;
135
+ logger.debug({ redactions: redactions.length }, 'generated request');
136
+ const waitForAllData = new Promise((resolve, reject) => {
137
+ endedHttpRequest = err => (err ? reject(err) : resolve());
138
+ });
139
+ onStep?.({ name: 'sending-request-data' });
140
+ try {
141
+ if (redactionMode === 'zk') {
142
+ await writeRedactedZk();
143
+ }
144
+ else {
145
+ await writeRedactedWithKeyUpdate();
146
+ }
147
+ logger.info('wrote request to server');
171
148
  }
172
- );
173
- onStep?.({ name: "sending-request-data" });
174
- try {
175
- if (redactionMode === "zk") {
176
- await writeRedactedZk();
177
- } else {
178
- await writeRedactedWithKeyUpdate();
149
+ catch (err) {
150
+ // wait for complete stream end when the session is closed
151
+ // mid-write, as this means the server could not process
152
+ // our request due to some error. Hope the stream end
153
+ // error will be more descriptive
154
+ logger.error({ err }, 'session errored during write, waiting for stream end');
179
155
  }
180
- logger.info("wrote request to server");
181
- } catch (err) {
182
- logger.error(
183
- { err },
184
- "session errored during write, waiting for stream end"
185
- );
186
- }
187
- onStep?.({ name: "waiting-for-response" });
188
- await waitForAllData;
189
- await tunnel.close();
190
- logger.info("session closed, processing response");
191
- if (updateProviderParams) {
192
- const { params: updatedParms, secretParams: updatedSecretParms } = await updateProviderParams(tunnel.transcript, tlsVersion ?? "TLS1_2");
193
- params = { ...params, ...updatedParms };
194
- secretParams = { ...secretParams, ...updatedSecretParms };
195
- }
196
- const signatureAlg = SIGNATURES[client.metadata.signatureType];
197
- let serverIV;
198
- let clientIV;
199
- const [serverBlock] = getLastBlocks("server", 1);
200
- if (serverBlock?.message.type === "ciphertext") {
201
- serverIV = serverBlock.message.fixedIv;
202
- }
203
- const [clientBlock] = getLastBlocks("client", 1);
204
- if (clientBlock?.message.type === "ciphertext") {
205
- clientIV = clientBlock.message.fixedIv;
206
- }
207
- const transcript = await generateTranscript();
208
- const claimTunnelReq = ClaimTunnelRequest.create({
209
- request: createTunnelReq,
210
- data: {
211
- provider: name,
212
- parameters: canonicalStringify(params),
213
- context: canonicalStringify(context),
214
- timestampS: timestampS ?? unixTimestampSeconds(),
215
- owner: getAddress()
216
- },
217
- transcript,
218
- zkEngine: getEngineProto(zkEngine),
219
- fixedServerIV: serverIV,
220
- fixedClientIV: clientIV
221
- });
222
- onStep?.({ name: "waiting-for-verification" });
223
- const claimTunnelBytes = ClaimTunnelRequest.encode(claimTunnelReq).finish();
224
- const requestSignature = await signatureAlg.sign(claimTunnelBytes, ownerPrivateKey);
225
- claimTunnelReq.signatures = { requestSignature };
226
- const result = await client.rpc("claimTunnel", claimTunnelReq);
227
- logger.info({ success: !!result.claim }, "recv claim response");
228
- return result;
229
- async function fetchCertificateBytesFromAttestor(url) {
230
- if (!client) {
231
- throw new Error("attestor client not initialized");
156
+ onStep?.({ name: 'waiting-for-response' });
157
+ await waitForAllData;
158
+ await tunnel.close();
159
+ logger.info('session closed, processing response');
160
+ // update the response selections
161
+ if (updateProviderParams) {
162
+ const { params: updatedParms, secretParams: updatedSecretParms } = await updateProviderParams(tunnel.transcript, tlsVersion ?? 'TLS1_2');
163
+ params = { ...params, ...updatedParms };
164
+ secretParams = { ...secretParams, ...updatedSecretParms };
232
165
  }
233
- const result2 = await client.rpc("fetchCertificateBytes", { url });
234
- return result2.bytes;
235
- }
236
- async function writeRedactedWithKeyUpdate() {
237
- let currentIndex = 0;
238
- for (const section of redactions) {
239
- const block2 = requestData.slice(currentIndex, section.fromIndex);
240
- if (block2.length) {
241
- await writeWithReveal(block2, true);
242
- }
243
- const redacted = requestData.slice(section.fromIndex, section.toIndex);
244
- await writeWithReveal(redacted, false);
245
- currentIndex = section.toIndex;
166
+ const signatureAlg = SIGNATURES[client.metadata.signatureType];
167
+ let serverIV;
168
+ let clientIV;
169
+ const [serverBlock] = getLastBlocks('server', 1);
170
+ if (serverBlock?.message.type === 'ciphertext') {
171
+ serverIV = serverBlock.message.fixedIv;
246
172
  }
247
- const lastBlockStart = redactions?.[redactions.length - 1]?.toIndex || 0;
248
- const block = requestData.slice(lastBlockStart);
249
- if (block.length) {
250
- await writeWithReveal(block, true);
173
+ const [clientBlock] = getLastBlocks('client', 1);
174
+ if (clientBlock?.message.type === 'ciphertext') {
175
+ clientIV = clientBlock.message.fixedIv;
251
176
  }
252
- }
253
- async function writeRedactedZk() {
254
- let blocksWritten = tunnel.transcript.length;
255
- await tunnel.tls.write(requestData);
256
- blocksWritten = tunnel.transcript.length - blocksWritten;
257
- setRevealOfLastSentBlocks(
258
- {
259
- type: "zk",
260
- redactedPlaintext: redactSlices(requestData, redactions)
261
- },
262
- blocksWritten
263
- );
264
- }
265
- async function writeWithReveal(data, reveal) {
266
- if (reveal !== lastMsgRevealed) {
267
- await tunnel.tls.updateTrafficKeys();
177
+ const transcript = await generateTranscript();
178
+ // now that we have the full transcript, we need
179
+ // to generate the ZK proofs & send them to the attestor
180
+ // to verify & sign our claim
181
+ const claimTunnelReq = ClaimTunnelRequest.create({
182
+ request: createTunnelReq,
183
+ data: {
184
+ provider: name,
185
+ parameters: canonicalStringify(params),
186
+ context: canonicalStringify(context),
187
+ timestampS: timestampS ?? unixTimestampSeconds(),
188
+ owner: getAddress(),
189
+ },
190
+ transcript: transcript,
191
+ zkEngine: getEngineProto(zkEngine),
192
+ fixedServerIV: serverIV,
193
+ fixedClientIV: clientIV,
194
+ });
195
+ onStep?.({ name: 'waiting-for-verification' });
196
+ const claimTunnelBytes = ClaimTunnelRequest
197
+ .encode(claimTunnelReq).finish();
198
+ const requestSignature = await signatureAlg
199
+ .sign(claimTunnelBytes, ownerPrivateKey);
200
+ claimTunnelReq.signatures = { requestSignature };
201
+ const result = await client.rpc('claimTunnel', claimTunnelReq);
202
+ logger.info({ success: !!result.claim }, 'recv claim response');
203
+ return result;
204
+ async function fetchCertificateBytesFromAttestor(url) {
205
+ if (!client) {
206
+ throw new Error('attestor client not initialized');
207
+ }
208
+ const result = await client.rpc('fetchCertificateBytes', { url });
209
+ return result.bytes;
268
210
  }
269
- let blocksWritten = tunnel.transcript.length;
270
- await tunnel.write(data);
271
- blocksWritten = tunnel.transcript.length - blocksWritten;
272
- setRevealOfLastSentBlocks(reveal ? { type: "complete" } : void 0, blocksWritten);
273
- lastMsgRevealed = reveal;
274
- }
275
- function setRevealOfLastSentBlocks(reveal, nBlocks = 1) {
276
- const lastBlocks = getLastBlocks("client", nBlocks);
277
- if (!lastBlocks.length) {
278
- return;
211
+ async function writeRedactedWithKeyUpdate() {
212
+ let currentIndex = 0;
213
+ for (const section of redactions) {
214
+ const block = requestData
215
+ .slice(currentIndex, section.fromIndex);
216
+ if (block.length) {
217
+ await writeWithReveal(block, true);
218
+ }
219
+ const redacted = requestData
220
+ .slice(section.fromIndex, section.toIndex);
221
+ await writeWithReveal(redacted, false);
222
+ currentIndex = section.toIndex;
223
+ }
224
+ // write if redactions were there
225
+ const lastBlockStart = redactions?.[redactions.length - 1]
226
+ ?.toIndex || 0;
227
+ const block = requestData.slice(lastBlockStart);
228
+ if (block.length) {
229
+ await writeWithReveal(block, true);
230
+ }
279
231
  }
280
- for (const block of lastBlocks) {
281
- setRevealOfMessage(block.message, reveal);
232
+ async function writeRedactedZk() {
233
+ let blocksWritten = tunnel.transcript.length;
234
+ await tunnel.tls.write(requestData);
235
+ blocksWritten = tunnel.transcript.length - blocksWritten;
236
+ setRevealOfLastSentBlocks({
237
+ type: 'zk',
238
+ redactedPlaintext: redactSlices(requestData, redactions)
239
+ }, blocksWritten);
282
240
  }
283
- }
284
- function getLastBlocks(sender, nBlocks) {
285
- const lastBlocks = [];
286
- for (let i = tunnel.transcript.length - 1; i >= 0; i--) {
287
- const block = tunnel.transcript[i];
288
- if (block.sender === sender) {
289
- lastBlocks.push(block);
290
- if (lastBlocks.length === nBlocks) {
291
- break;
241
+ /**
242
+ * Write data to the tunnel, with the option to mark the packet
243
+ * as revealable to the attestor or not
244
+ */
245
+ async function writeWithReveal(data, reveal) {
246
+ // if the reveal state has changed, update the traffic keys
247
+ // to not accidentally reveal a packet not meant to be revealed
248
+ // and vice versa
249
+ if (reveal !== lastMsgRevealed) {
250
+ await tunnel.tls.updateTrafficKeys();
292
251
  }
293
- }
252
+ let blocksWritten = tunnel.transcript.length;
253
+ await tunnel.write(data);
254
+ blocksWritten = tunnel.transcript.length - blocksWritten;
255
+ // now we mark the packet to be revealed to the attestor
256
+ setRevealOfLastSentBlocks(reveal ? { type: 'complete' } : undefined, blocksWritten);
257
+ lastMsgRevealed = reveal;
294
258
  }
295
- return lastBlocks;
296
- }
297
- async function generateTranscript() {
298
- await addServerSideReveals();
299
- const startMs = Date.now();
300
- const revealedMessages = await preparePacketsForReveal(
301
- tunnel.transcript,
302
- revealMap,
303
- {
304
- logger,
305
- cipherSuite,
306
- onZkProgress(done, total) {
307
- const timeSinceStartMs = Date.now() - startMs;
308
- const timePerBlockMs = timeSinceStartMs / done;
309
- const timeLeftMs = timePerBlockMs * (total - done);
310
- onStep?.({
311
- name: "generating-zk-proofs",
312
- proofsDone: done,
313
- proofsTotal: total,
314
- approxTimeLeftS: Math.round(timeLeftMs / 1e3)
315
- });
316
- },
317
- ...zkOpts
318
- }
319
- );
320
- return revealedMessages;
321
- }
322
- async function addServerSideReveals() {
323
- const allPackets = tunnel.transcript;
324
- let serverPacketsToReveal = "all";
325
- const packets = [];
326
- const serverBlocks = [];
327
- for (const b of allPackets) {
328
- if (b.message.type !== "ciphertext" || !isApplicationData(b.message, tlsVersion)) {
329
- continue;
330
- }
331
- const plaintext = tlsVersion === "TLS1_3" ? b.message.plaintext.slice(0, -1) : b.message.plaintext;
332
- packets.push({
333
- message: plaintext,
334
- sender: b.sender
335
- });
336
- if (b.sender === "server") {
337
- serverBlocks.push({
338
- plaintext,
339
- message: b.message
340
- });
341
- }
259
+ function setRevealOfLastSentBlocks(reveal, nBlocks = 1) {
260
+ const lastBlocks = getLastBlocks('client', nBlocks);
261
+ if (!lastBlocks.length) {
262
+ return;
263
+ }
264
+ for (const block of lastBlocks) {
265
+ setRevealOfMessage(block.message, reveal);
266
+ }
342
267
  }
343
- if (provider.getResponseRedactions) {
344
- serverPacketsToReveal = await getBlocksToReveal(
345
- serverBlocks,
346
- (total) => provider.getResponseRedactions({
347
- response: total,
348
- params,
349
- logger,
350
- ctx: PROVIDER_CTX
351
- }),
352
- performOprf
353
- );
268
+ function getLastBlocks(sender, nBlocks) {
269
+ // set the correct index for the server blocks
270
+ const lastBlocks = [];
271
+ for (let i = tunnel.transcript.length - 1; i >= 0; i--) {
272
+ const block = tunnel.transcript[i];
273
+ if (block.sender === sender) {
274
+ lastBlocks.push(block);
275
+ if (lastBlocks.length === nBlocks) {
276
+ break;
277
+ }
278
+ }
279
+ }
280
+ return lastBlocks;
281
+ }
282
+ /**
283
+ * Generate transcript with reveal data for the attestor to verify
284
+ */
285
+ async function generateTranscript() {
286
+ await addServerSideReveals();
287
+ const startMs = Date.now();
288
+ const revealedMessages = await preparePacketsForReveal(tunnel.transcript, revealMap, {
289
+ logger,
290
+ cipherSuite: cipherSuite,
291
+ onZkProgress(done, total) {
292
+ const timeSinceStartMs = Date.now() - startMs;
293
+ const timePerBlockMs = timeSinceStartMs / done;
294
+ const timeLeftMs = timePerBlockMs * (total - done);
295
+ onStep?.({
296
+ name: 'generating-zk-proofs',
297
+ proofsDone: done,
298
+ proofsTotal: total,
299
+ approxTimeLeftS: Math.round(timeLeftMs / 1000),
300
+ });
301
+ },
302
+ ...zkOpts,
303
+ });
304
+ return revealedMessages;
354
305
  }
355
- const revealedPackets = packets.filter((p) => p.sender === "client");
356
- if (serverPacketsToReveal === "all") {
357
- for (const { message, sender } of allPackets) {
358
- if (sender === "server") {
359
- setRevealOfMessage(message, { type: "complete" });
306
+ /**
307
+ * Add reveals for server side blocks, using
308
+ * the provider's redaction function if available.
309
+ * Otherwise, opts to reveal all server side blocks.
310
+ */
311
+ async function addServerSideReveals() {
312
+ const allPackets = tunnel.transcript;
313
+ let serverPacketsToReveal = 'all';
314
+ const packets = [];
315
+ const serverBlocks = [];
316
+ for (const b of allPackets) {
317
+ if (b.message.type !== 'ciphertext'
318
+ || !isApplicationData(b.message, tlsVersion)) {
319
+ continue;
320
+ }
321
+ const plaintext = tlsVersion === 'TLS1_3'
322
+ ? b.message.plaintext.slice(0, -1)
323
+ : b.message.plaintext;
324
+ packets.push({
325
+ message: plaintext,
326
+ sender: b.sender
327
+ });
328
+ if (b.sender === 'server') {
329
+ serverBlocks.push({
330
+ plaintext: plaintext,
331
+ message: b.message
332
+ });
333
+ }
334
+ }
335
+ if (provider.getResponseRedactions) {
336
+ serverPacketsToReveal = await getBlocksToReveal(serverBlocks, total => provider.getResponseRedactions({
337
+ response: total,
338
+ params,
339
+ logger,
340
+ ctx: PROVIDER_CTX
341
+ }), performOprf);
360
342
  }
361
- }
362
- revealedPackets.push(...packets.filter((p) => p.sender === "server"));
363
- } else {
364
- for (const {
365
- block,
366
- redactedPlaintext,
367
- overshotToprfFromPrevBlock,
368
- toprfs,
369
- oprfRawMarkers
370
- } of serverPacketsToReveal) {
371
- setRevealOfMessage(block.message, {
372
- type: "zk",
373
- redactedPlaintext,
374
- toprfs,
375
- oprfRawMarkers,
376
- overshotToprfFromPrevBlock
343
+ const revealedPackets = packets
344
+ .filter(p => p.sender === 'client');
345
+ if (serverPacketsToReveal === 'all') {
346
+ // reveal all server side blocks
347
+ for (const { message, sender } of allPackets) {
348
+ if (sender === 'server') {
349
+ setRevealOfMessage(message, { type: 'complete' });
350
+ }
351
+ }
352
+ revealedPackets.push(...packets.filter(p => p.sender === 'server'));
353
+ }
354
+ else {
355
+ for (const { block, redactedPlaintext, overshotToprfFromPrevBlock, toprfs, oprfRawMarkers } of serverPacketsToReveal) {
356
+ setRevealOfMessage(block.message, {
357
+ type: 'zk',
358
+ redactedPlaintext,
359
+ toprfs,
360
+ oprfRawMarkers,
361
+ overshotToprfFromPrevBlock
362
+ });
363
+ revealedPackets.push({ sender: 'server', message: redactedPlaintext });
364
+ if (updateParametersFromOprfData && toprfs) {
365
+ let strParams = canonicalStringify(params);
366
+ for (const toprf of toprfs) {
367
+ const ogText = uint8ArrayToStr(toprf.plaintext);
368
+ const hashedText = binaryHashToStr(toprf.nullifier, toprf.dataLocation.length);
369
+ strParams = strParams.replaceAll(ogText, hashedText);
370
+ }
371
+ params = JSON.parse(strParams);
372
+ }
373
+ }
374
+ }
375
+ await provider.assertValidProviderReceipt({
376
+ receipt: revealedPackets,
377
+ params: {
378
+ ...params,
379
+ // provide secret params for proper
380
+ // request body validation
381
+ secretParams,
382
+ },
383
+ logger,
384
+ ctx: PROVIDER_CTX
377
385
  });
378
- revealedPackets.push(
379
- { sender: "server", message: redactedPlaintext }
380
- );
381
- if (updateParametersFromOprfData && toprfs) {
382
- let strParams = canonicalStringify(params);
383
- for (const toprf of toprfs) {
384
- const ogText = uint8ArrayToStr(toprf.plaintext);
385
- const hashedText = binaryHashToStr(
386
- toprf.nullifier,
387
- toprf.dataLocation.length
388
- );
389
- strParams = strParams.replaceAll(ogText, hashedText);
390
- }
391
- params = JSON.parse(strParams);
386
+ // reveal all handshake blocks
387
+ // so the attestor can verify there was no
388
+ // hanky-panky
389
+ for (const p of allPackets) {
390
+ if (p.message.type !== 'ciphertext') {
391
+ continue;
392
+ }
393
+ // break the moment we hit the first
394
+ // application data packet
395
+ if (isApplicationData(p.message, tlsVersion)) {
396
+ break;
397
+ }
398
+ setRevealOfMessage(p.message, { type: 'complete' });
392
399
  }
393
- }
394
400
  }
395
- await provider.assertValidProviderReceipt({
396
- receipt: revealedPackets,
397
- params: {
398
- ...params,
399
- // provide secret params for proper
400
- // request body validation
401
- secretParams
402
- },
403
- logger,
404
- ctx: PROVIDER_CTX
405
- });
406
- for (const p of allPackets) {
407
- if (p.message.type !== "ciphertext") {
408
- continue;
409
- }
410
- if (isApplicationData(p.message, tlsVersion)) {
411
- break;
412
- }
413
- setRevealOfMessage(p.message, { type: "complete" });
401
+ async function performOprf(plaintext) {
402
+ logger.info({ length: plaintext.length }, 'generating OPRF...');
403
+ const oprfOperator = zkOpts.oprfOperators?.['chacha20']
404
+ || makeDefaultOPRFOperator('chacha20', zkEngine, logger);
405
+ const reqData = await oprfOperator.generateOPRFRequestData(plaintext, TOPRF_DOMAIN_SEPARATOR, logger);
406
+ const res = await client.rpc('toprf', {
407
+ maskedData: reqData.maskedData,
408
+ engine: getEngineProto(zkEngine)
409
+ });
410
+ const nullifier = await oprfOperator.finaliseOPRF(client.initResponse.toprfPublicKey, reqData, [res]);
411
+ const data = {
412
+ nullifier,
413
+ responses: [res],
414
+ mask: reqData.mask,
415
+ dataLocation: undefined,
416
+ plaintext
417
+ };
418
+ return data;
414
419
  }
415
- }
416
- async function performOprf(plaintext) {
417
- logger.info({ length: plaintext.length }, "generating OPRF...");
418
- const oprfOperator = zkOpts.oprfOperators?.["chacha20"] || makeDefaultOPRFOperator(
419
- "chacha20",
420
- zkEngine,
421
- logger
422
- );
423
- const reqData = await oprfOperator.generateOPRFRequestData(
424
- plaintext,
425
- TOPRF_DOMAIN_SEPARATOR,
426
- logger
427
- );
428
- const res = await client.rpc("toprf", {
429
- maskedData: reqData.maskedData,
430
- engine: getEngineProto(zkEngine)
431
- });
432
- const nullifier = await oprfOperator.finaliseOPRF(
433
- client.initResponse.toprfPublicKey,
434
- reqData,
435
- [res]
436
- );
437
- const data = {
438
- nullifier,
439
- responses: [res],
440
- mask: reqData.mask,
441
- dataLocation: void 0,
442
- plaintext
443
- };
444
- return data;
445
- }
446
- function setRevealOfMessage(message, reveal) {
447
- if (reveal) {
448
- revealMap.set(message, reveal);
449
- return;
420
+ function setRevealOfMessage(message, reveal) {
421
+ if (reveal) {
422
+ revealMap.set(message, reveal);
423
+ return;
424
+ }
425
+ revealMap.delete(message);
426
+ }
427
+ function getAddress() {
428
+ const { getAddress, getPublicKey } = signatureAlg;
429
+ const pubKey = getPublicKey(ownerPrivateKey);
430
+ return getAddress(pubKey);
450
431
  }
451
- revealMap.delete(message);
452
- }
453
- function getAddress() {
454
- const { getAddress: getAddress2, getPublicKey } = signatureAlg;
455
- const pubKey = getPublicKey(ownerPrivateKey);
456
- return getAddress2(pubKey);
457
- }
458
432
  }
459
- export {
460
- createClaimOnAttestor
461
- };