@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.
- package/browser/resources/attestor-browser.min.mjs +4512 -0
- package/lib/avs/abis/avsDirectoryABI.js +338 -341
- package/lib/avs/abis/delegationABI.js +1 -4
- package/lib/avs/abis/registryABI.js +719 -722
- package/lib/avs/client/create-claim-on-avs.js +129 -157
- package/lib/avs/config.js +18 -24
- package/lib/avs/contracts/ReclaimServiceManager.js +1 -0
- package/lib/avs/contracts/common.js +1 -0
- package/lib/avs/contracts/factories/ReclaimServiceManager__factory.js +1139 -1156
- package/lib/avs/contracts/factories/index.js +4 -4
- package/lib/avs/contracts/index.js +2 -6
- package/lib/avs/types/index.js +1 -0
- package/lib/avs/utils/contracts.js +30 -50
- package/lib/avs/utils/register.js +75 -70
- package/lib/avs/utils/tasks.js +38 -45
- package/lib/client/create-claim.js +402 -431
- package/lib/client/tunnels/make-rpc-tcp-tunnel.js +46 -48
- package/lib/client/tunnels/make-rpc-tls-tunnel.js +125 -121
- package/lib/client/utils/attestor-pool.js +23 -22
- package/lib/client/utils/client-socket.js +86 -109
- package/lib/client/utils/message-handler.js +79 -89
- package/lib/config/index.js +40 -58
- package/lib/external-rpc/benchmark.js +61 -74
- package/lib/external-rpc/event-bus.js +12 -15
- package/lib/external-rpc/handle-incoming-msg.js +216 -225
- package/lib/external-rpc/jsc-polyfills/1.js +70 -68
- package/lib/external-rpc/jsc-polyfills/2.js +17 -12
- package/lib/external-rpc/jsc-polyfills/event.js +10 -15
- package/lib/external-rpc/jsc-polyfills/index.js +2 -2
- package/lib/external-rpc/jsc-polyfills/ws.js +77 -79
- package/lib/external-rpc/setup-browser.js +28 -28
- package/lib/external-rpc/setup-jsc.js +17 -17
- package/lib/external-rpc/types.js +1 -0
- package/lib/external-rpc/utils.js +89 -89
- package/lib/external-rpc/zk.js +55 -50
- package/lib/index.js +2 -6
- package/lib/mechain/abis/governanceABI.js +457 -460
- package/lib/mechain/abis/taskABI.js +502 -505
- package/lib/mechain/client/create-claim-on-mechain.js +24 -29
- package/lib/mechain/constants/index.js +3 -8
- package/lib/mechain/types/index.js +1 -0
- package/lib/proto/api.js +4200 -4087
- package/lib/proto/tee-bundle.js +1261 -1241
- package/lib/providers/http/index.js +616 -603
- package/lib/providers/http/patch-parse5-tree.js +27 -29
- package/lib/providers/http/utils.js +289 -248
- package/lib/providers/index.js +3 -6
- package/lib/server/create-server.js +89 -91
- package/lib/server/handlers/claimTeeBundle.js +231 -211
- package/lib/server/handlers/claimTunnel.js +66 -73
- package/lib/server/handlers/completeClaimOnChain.js +20 -25
- package/lib/server/handlers/createClaimOnChain.js +21 -27
- package/lib/server/handlers/createTaskOnMechain.js +40 -50
- package/lib/server/handlers/createTunnel.js +85 -90
- package/lib/server/handlers/disconnectTunnel.js +4 -7
- package/lib/server/handlers/fetchCertificateBytes.js +37 -53
- package/lib/server/handlers/index.js +21 -24
- package/lib/server/handlers/init.js +27 -28
- package/lib/server/handlers/toprf.js +13 -16
- package/lib/server/socket.js +97 -100
- package/lib/server/tunnels/make-tcp-tunnel.js +161 -186
- package/lib/server/utils/apm.js +32 -25
- package/lib/server/utils/assert-valid-claim-request.js +305 -334
- package/lib/server/utils/config-env.js +2 -2
- package/lib/server/utils/dns.js +12 -18
- package/lib/server/utils/gcp-attestation.js +233 -181
- package/lib/server/utils/generics.d.ts +1 -1
- package/lib/server/utils/generics.js +43 -37
- package/lib/server/utils/iso.js +253 -256
- package/lib/server/utils/keep-alive.js +36 -36
- package/lib/server/utils/nitro-attestation.js +295 -220
- package/lib/server/utils/oprf-raw.js +48 -55
- package/lib/server/utils/process-handshake.js +200 -218
- package/lib/server/utils/proxy-session.js +5 -5
- package/lib/server/utils/tee-oprf-mpc-verification.js +82 -78
- package/lib/server/utils/tee-oprf-verification.js +165 -142
- package/lib/server/utils/tee-transcript-reconstruction.js +176 -129
- package/lib/server/utils/tee-verification.js +397 -334
- package/lib/server/utils/validation.js +30 -37
- package/lib/types/bgp.js +1 -0
- package/lib/types/claims.js +1 -0
- package/lib/types/client.js +1 -0
- package/lib/types/general.js +1 -0
- package/lib/types/handlers.js +1 -0
- package/lib/types/providers.d.ts +3 -2
- package/lib/types/providers.gen.js +9 -15
- package/lib/types/providers.js +1 -0
- package/lib/types/rpc.js +1 -0
- package/lib/types/signatures.d.ts +1 -2
- package/lib/types/signatures.js +1 -0
- package/lib/types/tunnel.js +1 -0
- package/lib/types/zk.js +1 -0
- package/lib/utils/auth.js +54 -66
- package/lib/utils/b64-json.js +15 -15
- package/lib/utils/bgp-listener.js +107 -111
- package/lib/utils/claims.js +89 -80
- package/lib/utils/env.js +13 -17
- package/lib/utils/error.js +43 -47
- package/lib/utils/generics.js +284 -235
- package/lib/utils/http-parser.js +232 -187
- package/lib/utils/logger.js +80 -71
- package/lib/utils/prepare-packets.js +69 -67
- package/lib/utils/redactions.js +163 -121
- package/lib/utils/retries.js +22 -24
- package/lib/utils/signatures/eth.js +29 -28
- package/lib/utils/signatures/index.js +5 -10
- package/lib/utils/socket-base.js +84 -88
- package/lib/utils/tls.js +28 -28
- package/lib/utils/ws.js +19 -19
- package/lib/utils/zk.js +542 -582
- package/package.json +12 -5
- package/lib/external-rpc/global.d.js +0 -0
- package/lib/scripts/build-browser.d.ts +0 -1
- package/lib/scripts/build-jsc.d.ts +0 -1
- package/lib/scripts/build-lib.d.ts +0 -1
- package/lib/scripts/check-avs-registration.d.ts +0 -1
- package/lib/scripts/check-avs-registration.js +0 -28
- package/lib/scripts/fallbacks/crypto.d.ts +0 -1
- package/lib/scripts/fallbacks/crypto.js +0 -4
- package/lib/scripts/fallbacks/empty.d.ts +0 -3
- package/lib/scripts/fallbacks/empty.js +0 -4
- package/lib/scripts/fallbacks/re2.d.ts +0 -1
- package/lib/scripts/fallbacks/re2.js +0 -7
- package/lib/scripts/fallbacks/snarkjs.d.ts +0 -1
- package/lib/scripts/fallbacks/snarkjs.js +0 -10
- package/lib/scripts/fallbacks/stwo.d.ts +0 -6
- package/lib/scripts/fallbacks/stwo.js +0 -159
- package/lib/scripts/generate-provider-types.d.ts +0 -5
- package/lib/scripts/generate-provider-types.js +0 -101
- package/lib/scripts/generate-receipt.d.ts +0 -9
- package/lib/scripts/generate-receipt.js +0 -101
- package/lib/scripts/generate-toprf-keys.d.ts +0 -1
- package/lib/scripts/generate-toprf-keys.js +0 -24
- package/lib/scripts/jsc-cli-rpc.d.ts +0 -1
- package/lib/scripts/jsc-cli-rpc.js +0 -35
- package/lib/scripts/register-avs-operator.d.ts +0 -1
- package/lib/scripts/register-avs-operator.js +0 -3
- package/lib/scripts/start-server.d.ts +0 -1
- package/lib/scripts/start-server.js +0 -11
- package/lib/scripts/update-avs-metadata.d.ts +0 -1
- package/lib/scripts/update-avs-metadata.js +0 -20
- package/lib/scripts/utils.d.ts +0 -1
- package/lib/scripts/utils.js +0 -10
- package/lib/scripts/whitelist-operator.d.ts +0 -1
- package/lib/scripts/whitelist-operator.js +0 -16
|
@@ -1,461 +1,432 @@
|
|
|
1
|
-
import { asciiToUint8Array } from
|
|
2
|
-
import { makeRpcTlsTunnel } from "
|
|
3
|
-
import { getAttestorClientFromPool } from "
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
|
-
|
|
281
|
-
|
|
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
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
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
(
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
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
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
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
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
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
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
)
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
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
|
-
};
|