@reclaimprotocol/attestor-core 5.0.4 → 5.0.5

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 (122) hide show
  1. package/LICENSE +660 -660
  2. package/browser/resources/attestor-browser.min.mjs +31 -31
  3. package/lib/server/tee/acme-http-server.d.ts +13 -0
  4. package/lib/server/tee/attestation-generate.d.ts +29 -0
  5. package/lib/server/tee/bootstrap.d.ts +11 -0
  6. package/lib/server/tee/cert-manager.d.ts +24 -0
  7. package/lib/server/tee/cloud-logging.d.ts +23 -0
  8. package/lib/server/tee/secret-loader.d.ts +10 -0
  9. package/lib/server/tee/secret-manager.d.ts +3 -0
  10. package/lib/utils/gcp-attestation.d.ts +23 -0
  11. package/package.json +3 -3
  12. package/lib/avs/abis/avsDirectoryABI.js +0 -340
  13. package/lib/avs/abis/delegationABI.js +0 -1
  14. package/lib/avs/abis/registryABI.js +0 -725
  15. package/lib/avs/client/create-claim-on-avs.js +0 -138
  16. package/lib/avs/config.js +0 -20
  17. package/lib/avs/contracts/ReclaimServiceManager.js +0 -1
  18. package/lib/avs/contracts/common.js +0 -1
  19. package/lib/avs/contracts/factories/ReclaimServiceManager__factory.js +0 -1169
  20. package/lib/avs/contracts/factories/index.js +0 -4
  21. package/lib/avs/contracts/index.js +0 -2
  22. package/lib/avs/types/index.js +0 -1
  23. package/lib/avs/utils/contracts.js +0 -33
  24. package/lib/avs/utils/register.js +0 -78
  25. package/lib/avs/utils/tasks.js +0 -40
  26. package/lib/client/create-claim.js +0 -433
  27. package/lib/client/index.js +0 -3
  28. package/lib/client/tunnels/make-rpc-tcp-tunnel.js +0 -51
  29. package/lib/client/tunnels/make-rpc-tls-tunnel.js +0 -131
  30. package/lib/client/utils/attestor-pool.js +0 -25
  31. package/lib/client/utils/client-socket.js +0 -98
  32. package/lib/client/utils/message-handler.js +0 -87
  33. package/lib/config/index.js +0 -44
  34. package/lib/external-rpc/benchmark.js +0 -69
  35. package/lib/external-rpc/event-bus.js +0 -14
  36. package/lib/external-rpc/handle-incoming-msg.js +0 -233
  37. package/lib/external-rpc/jsc-polyfills/1.js +0 -82
  38. package/lib/external-rpc/jsc-polyfills/2.js +0 -20
  39. package/lib/external-rpc/jsc-polyfills/event.js +0 -14
  40. package/lib/external-rpc/jsc-polyfills/index.js +0 -2
  41. package/lib/external-rpc/jsc-polyfills/ws.js +0 -81
  42. package/lib/external-rpc/setup-browser.js +0 -33
  43. package/lib/external-rpc/setup-jsc.js +0 -22
  44. package/lib/external-rpc/types.js +0 -1
  45. package/lib/external-rpc/utils.js +0 -100
  46. package/lib/external-rpc/zk.js +0 -63
  47. package/lib/mechain/abis/governanceABI.js +0 -458
  48. package/lib/mechain/abis/taskABI.js +0 -509
  49. package/lib/mechain/client/create-claim-on-mechain.js +0 -28
  50. package/lib/mechain/client/index.js +0 -1
  51. package/lib/mechain/constants/index.js +0 -3
  52. package/lib/mechain/index.js +0 -2
  53. package/lib/mechain/types/index.js +0 -1
  54. package/lib/proto/api.js +0 -4273
  55. package/lib/proto/tee-bundle.js +0 -1316
  56. package/lib/providers/http/index.js +0 -658
  57. package/lib/providers/http/patch-parse5-tree.js +0 -33
  58. package/lib/providers/http/utils.js +0 -324
  59. package/lib/providers/index.js +0 -4
  60. package/lib/scripts/fetch-ec2-metadata.d.ts +0 -1
  61. package/lib/server/create-server.js +0 -103
  62. package/lib/server/handlers/claimTeeBundle.js +0 -252
  63. package/lib/server/handlers/claimTunnel.js +0 -73
  64. package/lib/server/handlers/completeClaimOnChain.js +0 -22
  65. package/lib/server/handlers/createClaimOnChain.js +0 -26
  66. package/lib/server/handlers/createTaskOnMechain.js +0 -47
  67. package/lib/server/handlers/createTunnel.js +0 -93
  68. package/lib/server/handlers/disconnectTunnel.js +0 -5
  69. package/lib/server/handlers/fetchCertificateBytes.js +0 -41
  70. package/lib/server/handlers/index.js +0 -22
  71. package/lib/server/handlers/init.js +0 -32
  72. package/lib/server/handlers/toprf.js +0 -16
  73. package/lib/server/index.js +0 -4
  74. package/lib/server/socket.js +0 -109
  75. package/lib/server/tunnels/make-tcp-tunnel.js +0 -177
  76. package/lib/server/utils/apm.js +0 -36
  77. package/lib/server/utils/assert-valid-claim-request.js +0 -204
  78. package/lib/server/utils/config-env.js +0 -4
  79. package/lib/server/utils/dns.js +0 -18
  80. package/lib/server/utils/gcp-attestation.js +0 -289
  81. package/lib/server/utils/generics.js +0 -51
  82. package/lib/server/utils/iso.js +0 -256
  83. package/lib/server/utils/keep-alive.js +0 -38
  84. package/lib/server/utils/nitro-attestation.js +0 -325
  85. package/lib/server/utils/process-handshake.js +0 -215
  86. package/lib/server/utils/proxy-session.js +0 -6
  87. package/lib/server/utils/tee-oprf-mpc-verification.js +0 -90
  88. package/lib/server/utils/tee-oprf-verification.js +0 -174
  89. package/lib/server/utils/tee-transcript-reconstruction.js +0 -187
  90. package/lib/server/utils/tee-verification.js +0 -421
  91. package/lib/server/utils/validation.js +0 -38
  92. package/lib/types/bgp.js +0 -1
  93. package/lib/types/claims.js +0 -1
  94. package/lib/types/client.js +0 -1
  95. package/lib/types/general.js +0 -1
  96. package/lib/types/handlers.js +0 -1
  97. package/lib/types/index.js +0 -10
  98. package/lib/types/providers.gen.js +0 -10
  99. package/lib/types/providers.js +0 -1
  100. package/lib/types/rpc.js +0 -1
  101. package/lib/types/signatures.js +0 -1
  102. package/lib/types/tunnel.js +0 -1
  103. package/lib/types/zk.js +0 -1
  104. package/lib/utils/auth.js +0 -59
  105. package/lib/utils/b64-json.js +0 -17
  106. package/lib/utils/bgp-listener.js +0 -119
  107. package/lib/utils/claims.js +0 -99
  108. package/lib/utils/env.js +0 -15
  109. package/lib/utils/error.js +0 -50
  110. package/lib/utils/generics.js +0 -317
  111. package/lib/utils/http-parser.js +0 -246
  112. package/lib/utils/index.js +0 -13
  113. package/lib/utils/logger.js +0 -91
  114. package/lib/utils/prepare-packets.js +0 -62
  115. package/lib/utils/redactions.js +0 -148
  116. package/lib/utils/retries.js +0 -24
  117. package/lib/utils/signatures/eth.js +0 -29
  118. package/lib/utils/signatures/index.js +0 -7
  119. package/lib/utils/socket-base.js +0 -90
  120. package/lib/utils/tls.js +0 -58
  121. package/lib/utils/ws.js +0 -22
  122. package/lib/utils/zk.js +0 -577
@@ -1,246 +0,0 @@
1
- import { asciiToUint8Array, concatenateUint8Arrays } from '@reclaimprotocol/tls';
2
- import { findIndexInUint8Array, uint8ArrayToStr } from "./generics.js";
3
- import { REDACTION_CHAR_CODE } from "./redactions.js";
4
- const HTTP_HEADER_LINE_END = asciiToUint8Array('\r\n');
5
- /**
6
- * parses http/1.1 responses
7
- */
8
- export function makeHttpResponseParser() {
9
- /** the HTTP response data */
10
- const res = {
11
- statusCode: 0,
12
- statusMessage: '',
13
- headers: {},
14
- body: new Uint8Array(),
15
- complete: false,
16
- headersComplete: false,
17
- headerIndices: new Map(),
18
- headerEndIdx: 0
19
- };
20
- let remainingBodyBytes = 0;
21
- let isChunked = false;
22
- let remaining = new Uint8Array();
23
- let currentByteIdx = 0;
24
- return {
25
- res,
26
- /**
27
- * Parse the next chunk of data
28
- * @param data the data to parse
29
- */
30
- onChunk(data) {
31
- // concatenate the remaining data from the last chunk
32
- remaining = concatenateUint8Arrays([remaining, data]);
33
- // if we don't have the headers yet, keep reading lines
34
- // as each header is in a line
35
- if (!res.headersComplete) {
36
- for (let line = getLine(); typeof line !== 'undefined'; line = getLine()) {
37
- // first line is the HTTP version, status code & message
38
- if (!res.statusCode) {
39
- const [, statusCode, statusMessage] = line.match(/HTTP\/\d\.\d (\d+) (.*)/) || [];
40
- res.statusCode = Number(statusCode);
41
- res.statusMessage = statusMessage;
42
- res.statusLineEndIndex = currentByteIdx - HTTP_HEADER_LINE_END.length;
43
- }
44
- else if (line === '') { // empty line signifies end of headers
45
- res.headersComplete = true;
46
- res.headerEndIdx = currentByteIdx - 4;
47
- // if the response is chunked, we need to process the body differently
48
- if (res.headers['transfer-encoding']?.includes('chunked')) {
49
- isChunked = true;
50
- res.chunks = [];
51
- break;
52
- // if the response has a content-length, we know how many bytes to read
53
- }
54
- else if (res.headers['content-length']) {
55
- remainingBodyBytes = Number(res.headers['content-length']);
56
- break;
57
- }
58
- else {
59
- remainingBodyBytes = -1;
60
- break;
61
- // otherwise,
62
- // no content-length, no chunked transfer encoding
63
- // means wait till the stream ends
64
- // https://stackoverflow.com/a/11376887
65
- }
66
- }
67
- else if (!res.complete) { // parse the header
68
- const [key, value] = line.split(': ');
69
- res.headers[key.toLowerCase()] = value;
70
- res.headerIndices[key.toLowerCase()] = {
71
- fromIndex: currentByteIdx - line.length - HTTP_HEADER_LINE_END.length,
72
- toIndex: currentByteIdx - HTTP_HEADER_LINE_END.length
73
- };
74
- }
75
- else {
76
- throw new Error('got more data after response was complete');
77
- }
78
- }
79
- }
80
- if (res.headersComplete) {
81
- if (remainingBodyBytes) {
82
- readBody();
83
- // if no more body bytes to read,
84
- // and the response was not chunked we're done
85
- if (!remainingBodyBytes && !isChunked) {
86
- res.complete = true;
87
- }
88
- }
89
- if (res.headers['content-length'] === '0') {
90
- res.complete = true;
91
- }
92
- if (isChunked) {
93
- for (let line = getLine(); typeof line !== 'undefined'; line = getLine()) {
94
- if (line === '') {
95
- continue;
96
- }
97
- const chunkSize = Number.parseInt(line, 16);
98
- // if chunk size is 0, we're done
99
- if (!chunkSize) {
100
- res.complete = true;
101
- continue;
102
- }
103
- res.chunks?.push({
104
- fromIndex: currentByteIdx,
105
- toIndex: currentByteIdx + chunkSize,
106
- });
107
- // otherwise read the chunk
108
- remainingBodyBytes = chunkSize;
109
- readBody();
110
- // if we read all the data we had,
111
- // but there's still data left,
112
- // break the loop and wait for the next chunk
113
- if (remainingBodyBytes) {
114
- break;
115
- }
116
- }
117
- }
118
- }
119
- },
120
- /**
121
- * Call to prevent further parsing; indicating the end of the request
122
- * Checks that the response is valid & complete, otherwise throws an error
123
- */
124
- streamEnded() {
125
- if (!res.headersComplete) {
126
- throw new Error('stream ended before headers were complete');
127
- }
128
- if (remaining.length) {
129
- throw new Error('stream ended before remaining data arrived');
130
- }
131
- if (remainingBodyBytes > 0) {
132
- throw new Error('stream ended before all body bytes were received');
133
- }
134
- res.complete = true;
135
- }
136
- };
137
- function readBody() {
138
- if (res.complete) {
139
- throw new Error('got more data after response was complete');
140
- }
141
- if (!res.bodyStartIndex) {
142
- res.bodyStartIndex = currentByteIdx;
143
- }
144
- let bytesToCopy;
145
- if (remainingBodyBytes === -1) {
146
- // all bytes are body bytes
147
- bytesToCopy = remaining.length;
148
- }
149
- else {
150
- // take the number of bytes we need to read, or the number of bytes remaining
151
- // and append to the bytes of the body
152
- bytesToCopy = Math.min(remainingBodyBytes, remaining.length);
153
- remainingBodyBytes -= bytesToCopy;
154
- }
155
- res.body = concatenateUint8Arrays([
156
- res.body,
157
- remaining.slice(0, bytesToCopy)
158
- ]);
159
- remaining = remaining.slice(bytesToCopy);
160
- currentByteIdx += bytesToCopy;
161
- }
162
- function getLine() {
163
- // find end of line, if it exists
164
- // otherwise return undefined
165
- const idx = findIndexInUint8Array(remaining, HTTP_HEADER_LINE_END);
166
- if (idx === -1) {
167
- return undefined;
168
- }
169
- const line = uint8ArrayToStr(remaining.slice(0, idx));
170
- remaining = remaining.slice(idx + HTTP_HEADER_LINE_END.length);
171
- currentByteIdx += idx + HTTP_HEADER_LINE_END.length;
172
- return line;
173
- }
174
- }
175
- /**
176
- * Read the HTTP request from a TLS receipt transcript.
177
- * @param receipt the transcript to read from or application messages if they were extracted beforehand
178
- * @returns the parsed HTTP request
179
- */
180
- export function getHttpRequestDataFromTranscript(receipt) {
181
- const clientMsgs = receipt
182
- .filter(s => s.sender === 'client');
183
- // if the first message is redacted, we can't parse it
184
- // as we don't know what the request was
185
- if (clientMsgs[0].message[0] === REDACTION_CHAR_CODE) {
186
- throw new Error('First client message request is redacted. Cannot parse');
187
- }
188
- const request = {
189
- method: '',
190
- url: '',
191
- protocol: '',
192
- headers: {}
193
- };
194
- let requestBuffer = concatenateUint8Arrays(clientMsgs.map(m => m.message));
195
- // keep reading lines until we get to the end of the headers
196
- for (let line = getLine(); typeof line !== 'undefined'; line = getLine()) {
197
- if (line === '') {
198
- break;
199
- }
200
- if (!request.method) {
201
- const [, method, url, protocol] = line.match(/(\w+) (.*) (.*)/) || [];
202
- request.method = method.toLowerCase();
203
- request.url = url;
204
- request.protocol = protocol;
205
- }
206
- else {
207
- let keyIdx = line.indexOf(':');
208
- if (keyIdx === -1) {
209
- keyIdx = line.length - 1;
210
- }
211
- const key = line.slice(0, keyIdx)
212
- .toLowerCase()
213
- .trim();
214
- const value = line.slice(keyIdx + 1)
215
- .trim();
216
- const oldValue = request.headers[key];
217
- if (typeof oldValue === 'string') {
218
- request.headers[key] = [oldValue, value];
219
- }
220
- else if (Array.isArray(oldValue)) {
221
- oldValue.push(value);
222
- }
223
- else {
224
- request.headers[key] = value;
225
- }
226
- }
227
- }
228
- //the rest is request body
229
- if (requestBuffer.length) {
230
- request.body = requestBuffer;
231
- }
232
- if (!request.method) {
233
- throw new Error('Client request is incomplete');
234
- }
235
- return request;
236
- function getLine() {
237
- const idx = findIndexInUint8Array(requestBuffer, HTTP_HEADER_LINE_END);
238
- if (idx === -1) {
239
- return undefined;
240
- }
241
- const line = uint8ArrayToStr(requestBuffer.slice(0, idx));
242
- requestBuffer = requestBuffer
243
- .slice(idx + HTTP_HEADER_LINE_END.length);
244
- return line;
245
- }
246
- }
@@ -1,13 +0,0 @@
1
- export * from "./generics.js";
2
- export * from "./logger.js";
3
- export * from "./redactions.js";
4
- export * from "./http-parser.js";
5
- export * from "./zk.js";
6
- export * from "./claims.js";
7
- export * from "./error.js";
8
- export * from "./prepare-packets.js";
9
- export * from "./signatures/index.js";
10
- export * from "./auth.js";
11
- export * from "./b64-json.js";
12
- export * from "./bgp-listener.js";
13
- export * from "./tls.js";
@@ -1,91 +0,0 @@
1
- import { pino, stdTimeFunctions } from 'pino';
2
- import { getEnvVariable } from "./env.js";
3
- const PII_PROPERTIES = ['ownerPrivateKey', 'secretParams'];
4
- const redactedText = '[REDACTED]';
5
- const envLevel = getEnvVariable('LOG_LEVEL');
6
- export let logger = pino();
7
- makeLogger(false, envLevel);
8
- /**
9
- * Creates a logger instance with optional redaction of PII.
10
- * Replaces default logger
11
- * See PII_PROPERTIES for the list of properties that will be redacted.
12
- *
13
- * @param redactPii - whether to redact PII from logs
14
- * @param level - the log level to use
15
- * @param onLog - a callback to call when a log is written
16
- */
17
- export function makeLogger(redactPii, level, onLog) {
18
- const opts = {
19
- // Log human readable time stamps instead of epoch time
20
- timestamp: stdTimeFunctions.isoTime,
21
- };
22
- if (redactPii) {
23
- opts.formatters = { log: redact };
24
- opts.serializers = { redact };
25
- opts.browser = {
26
- write: {
27
- fatal: log => writeLog('fatal', log),
28
- error: log => writeLog('error', log),
29
- warn: log => writeLog('warn', log),
30
- info: log => writeLog('info', log),
31
- debug: log => writeLog('debug', log),
32
- trace: log => writeLog('trace', log),
33
- }
34
- };
35
- }
36
- const pLogger = pino(opts);
37
- pLogger.level = level || 'info';
38
- logger = pLogger;
39
- return pLogger;
40
- function writeLog(level, log) {
41
- log = redact(log);
42
- const { msg, ...obj } = log;
43
- if (console[level]) {
44
- console[level](obj, msg);
45
- }
46
- else {
47
- console.log(obj, msg);
48
- }
49
- onLog?.(level, log);
50
- }
51
- }
52
- function isObjectProperty(property) {
53
- return (typeof property) === 'object'
54
- && !Array.isArray(property)
55
- && property !== null;
56
- }
57
- function getReplacer() {
58
- // Store references to previously visited objects
59
- const references = new WeakSet();
60
- return function (key, value) {
61
- const isObject = (typeof value) === 'object' && value !== null;
62
- if (isObject) {
63
- if (references.has(value)) {
64
- return '[CIRCULAR]';
65
- }
66
- references.add(value);
67
- }
68
- return value;
69
- };
70
- }
71
- export function redact(json) {
72
- const isObject = isObjectProperty(json);
73
- if (!isObject && !Array.isArray(json)) {
74
- return json;
75
- }
76
- const redacted = JSON.parse(JSON.stringify(json, getReplacer()));
77
- for (const prop in redacted) {
78
- if (PII_PROPERTIES.includes(prop)) {
79
- redacted[prop] = redactedText;
80
- }
81
- if (Array.isArray(redacted[prop])) {
82
- for (const [index, value] of redacted[prop].entries()) {
83
- redacted[prop][index] = redact(value);
84
- }
85
- }
86
- else if (isObjectProperty(redacted[prop])) {
87
- redacted[prop] = redact(redacted[prop]);
88
- }
89
- }
90
- return redacted;
91
- }
@@ -1,62 +0,0 @@
1
- import { concatenateUint8Arrays, crypto } from '@reclaimprotocol/tls';
2
- import { TranscriptMessageSenderType } from "../proto/api.js";
3
- import { makeZkProofGenerator } from "./zk.js";
4
- /**
5
- * Prepares the packets for reveal to the server
6
- * according to the specified reveal type
7
- */
8
- export async function preparePacketsForReveal(tlsTranscript, reveals, { onZkProgress, ...opts }) {
9
- const transcript = [];
10
- const proofGenerator = await makeZkProofGenerator(opts);
11
- let zkPacketsDone = 0;
12
- await Promise.all(tlsTranscript.map(async ({ message, sender }, i) => {
13
- const msg = {
14
- sender: sender === 'client'
15
- ? TranscriptMessageSenderType.TRANSCRIPT_MESSAGE_SENDER_TYPE_CLIENT
16
- : TranscriptMessageSenderType.TRANSCRIPT_MESSAGE_SENDER_TYPE_SERVER,
17
- message: message.data,
18
- reveal: undefined
19
- };
20
- transcript.push(msg);
21
- const reveal = reveals.get(message);
22
- if (!reveal || message.type === 'plaintext') {
23
- return;
24
- }
25
- switch (reveal?.type) {
26
- case 'complete':
27
- msg.reveal = {
28
- directReveal: {
29
- key: await crypto.exportKey(message.encKey),
30
- iv: message.fixedIv,
31
- recordNumber: message.recordNumber,
32
- },
33
- };
34
- break;
35
- case 'zk':
36
- // the redacted section can be smaller than the actual
37
- // plaintext encrypted, in case of TLS1.3 as it has a
38
- // content type suffix
39
- reveal.redactedPlaintext = concatenateUint8Arrays([
40
- reveal.redactedPlaintext,
41
- message.plaintext.slice(reveal.redactedPlaintext.length)
42
- ]);
43
- await proofGenerator.addPacketToProve(message, reveal, (proofs, toprfs) => (msg.reveal = { zkReveal: { proofs, toprfs } }), () => {
44
- const next = tlsTranscript
45
- .slice(i + 1)
46
- .find(t => t.sender === sender);
47
- return next?.message;
48
- });
49
- break;
50
- default:
51
- // no reveal
52
- break;
53
- }
54
- }));
55
- const zkPacketsTotal = proofGenerator.getTotalChunksToProve();
56
- onZkProgress?.(zkPacketsDone, zkPacketsTotal);
57
- await proofGenerator.generateProofs(() => {
58
- zkPacketsDone += 1;
59
- onZkProgress?.(zkPacketsDone, zkPacketsTotal);
60
- });
61
- return transcript;
62
- }
@@ -1,148 +0,0 @@
1
- import { base64Encode } from '@bufbuild/protobuf/wire';
2
- import { concatenateUint8Arrays } from '@reclaimprotocol/tls';
3
- export const REDACTION_CHAR = '*';
4
- export const REDACTION_CHAR_CODE = REDACTION_CHAR.charCodeAt(0);
5
- /**
6
- * Check if a redacted string is congruent with the original string.
7
- * @param redacted the redacted content, redacted content is replaced by '*'
8
- * @param original the original content
9
- */
10
- export function isRedactionCongruent(redacted, original) {
11
- // eslint-disable-next-line unicorn/no-for-loop
12
- for (let i = 0; i < redacted.length; i++) {
13
- const element = redacted[i];
14
- const areSame = element === original[i]
15
- || (typeof element === 'string' && element === REDACTION_CHAR)
16
- || (typeof element === 'number' && element === REDACTION_CHAR_CODE);
17
- if (!areSame) {
18
- return false;
19
- }
20
- }
21
- return true;
22
- }
23
- /**
24
- * Is the string fully redacted?
25
- */
26
- export function isFullyRedacted(redacted) {
27
- for (const element of redacted) {
28
- if (element !== REDACTION_CHAR
29
- && element !== REDACTION_CHAR_CODE) {
30
- return false;
31
- }
32
- }
33
- return true;
34
- }
35
- /**
36
- * Given some plaintext blocks and a redaction function, return the blocks that
37
- * need to be revealed to the other party
38
- *
39
- * Use case: we get the response for a request in several blocks, and want to redact
40
- * pieces that go through multiple blocks. We can use this function to get the
41
- * blocks that need to be revealed to the other party
42
- *
43
- * @example if we received ["secret is 12","345","678. Thanks"]. We'd want
44
- * to redact the "12345678" and reveal the rest. We'd pass in the blocks and
45
- * the redact function will return the redactions, namely [10,19].
46
- * The function will return the blocks ["secret is **","***. Thanks"].
47
- * The middle block is fully redacted, so it's not returned
48
- *
49
- * @param blocks blocks to reveal
50
- * @param redact function that returns the redactions
51
- * @returns blocks to reveal
52
- */
53
- export async function getBlocksToReveal(blocks, redact, performOprf) {
54
- const slicesWithReveal = blocks.map(block => ({
55
- block,
56
- // copy the plaintext to avoid mutating the original
57
- redactedPlaintext: new Uint8Array(block.plaintext)
58
- }));
59
- const total = concatenateUint8Arrays(blocks.map(b => b.plaintext));
60
- const redactions = redact(total);
61
- if (!redactions.length) {
62
- return 'all';
63
- }
64
- let blockIdx = 0;
65
- let cursorInBlock = 0;
66
- let cursor = 0;
67
- for (const redaction of redactions) {
68
- await redactBlocks(redaction);
69
- }
70
- // only reveal blocks that have some data to reveal,
71
- // or are completely plaintext
72
- return slicesWithReveal
73
- .filter(s => !isFullyRedacted(s.redactedPlaintext));
74
- async function redactBlocks(slice) {
75
- while (cursor < slice.fromIndex) {
76
- advance();
77
- }
78
- if (slice.hash) {
79
- const plaintext = total.slice(slice.fromIndex, slice.toIndex);
80
- const { nullifier, responses, mask } = await performOprf(plaintext);
81
- // set the TOPRF claim on the first blocks this
82
- // redaction covers
83
- const toprf = {
84
- nullifier,
85
- responses,
86
- dataLocation: {
87
- fromIndex: cursorInBlock,
88
- length: slice.toIndex - slice.fromIndex
89
- },
90
- mask,
91
- plaintext
92
- };
93
- const startBlockIdx = blockIdx;
94
- const block = slicesWithReveal[blockIdx];
95
- block.toprfs ||= [];
96
- block.toprfs.push(toprf);
97
- const nullifierStr = binaryHashToStr(nullifier, toprf.dataLocation.length);
98
- let i = 0;
99
- let overshootLen = 0;
100
- while (cursor < slice.toIndex) {
101
- if (blockIdx !== startBlockIdx) {
102
- overshootLen += 1;
103
- }
104
- slicesWithReveal[blockIdx].redactedPlaintext[cursorInBlock]
105
- = nullifierStr.charCodeAt(i);
106
- advance();
107
- i += 1;
108
- }
109
- if (overshootLen) {
110
- slicesWithReveal[blockIdx]
111
- .overshotToprfFromPrevBlock = { length: overshootLen };
112
- }
113
- }
114
- while (cursor < slice.toIndex) {
115
- slicesWithReveal[blockIdx]
116
- .redactedPlaintext[cursorInBlock] = REDACTION_CHAR_CODE;
117
- advance();
118
- }
119
- }
120
- function advance() {
121
- cursor += 1;
122
- cursorInBlock += 1;
123
- if (cursorInBlock >= blocks[blockIdx].plaintext.length) {
124
- blockIdx += 1;
125
- cursorInBlock = 0;
126
- }
127
- }
128
- }
129
- /**
130
- * Redact the following slices from the total
131
- */
132
- export function redactSlices(total, slices) {
133
- const redacted = new Uint8Array(total);
134
- for (const slice of slices) {
135
- for (let i = slice.fromIndex; i < slice.toIndex; i++) {
136
- redacted[i] = REDACTION_CHAR_CODE;
137
- }
138
- }
139
- return redacted;
140
- }
141
- /**
142
- * Converts the binary hash to an ASCII string of the expected length.
143
- * If the hash is shorter than the expected length, it will be padded with
144
- * '0' characters. If it's longer, it will be truncated.
145
- */
146
- export function binaryHashToStr(hash, expLength) {
147
- return base64Encode(hash).padEnd(expLength, '0').slice(0, expLength);
148
- }
@@ -1,24 +0,0 @@
1
- /**
2
- * Execute a function, and upon failure -- retry
3
- * based on specified options.
4
- */
5
- export async function executeWithRetries(code, { maxRetries = 3, shouldRetry, logger, }) {
6
- let retries = 0;
7
- while (retries < maxRetries) {
8
- try {
9
- const result = await code(retries);
10
- return result;
11
- }
12
- catch (err) {
13
- retries += 1;
14
- if (retries >= maxRetries) {
15
- throw err;
16
- }
17
- if (!shouldRetry(err)) {
18
- throw err;
19
- }
20
- logger.info({ err, retries }, 'retrying failed operation');
21
- }
22
- }
23
- throw new Error('retries exhausted');
24
- }
@@ -1,29 +0,0 @@
1
- import { utils, Wallet } from 'ethers';
2
- const { computeAddress, computePublicKey } = utils;
3
- export const ETH_SIGNATURE_PROVIDER = {
4
- getPublicKey(privateKey) {
5
- const pub = computePublicKey(privateKey, true);
6
- return utils.arrayify(pub);
7
- },
8
- getAddress(publicKey) {
9
- return computeAddress(publicKey).toLowerCase();
10
- },
11
- async sign(data, privateKey) {
12
- const wallet = getEthWallet(privateKey);
13
- const signature = await wallet.signMessage(data);
14
- return utils.arrayify(signature);
15
- },
16
- async verify(data, signature, addressBytes) {
17
- const address = typeof addressBytes === 'string'
18
- ? addressBytes
19
- : utils.hexlify(addressBytes);
20
- const signerAddress = utils.verifyMessage(data, signature);
21
- return signerAddress.toLowerCase() === address.toLowerCase();
22
- }
23
- };
24
- function getEthWallet(privateKey) {
25
- if (!privateKey) {
26
- throw new Error('Private key missing');
27
- }
28
- return new Wallet(privateKey);
29
- }
@@ -1,7 +0,0 @@
1
- import { ServiceSignatureType } from "../../proto/api.js";
2
- import { ETH_SIGNATURE_PROVIDER } from "./eth.js";
3
- export const SIGNATURES = {
4
- [ServiceSignatureType.SERVICE_SIGNATURE_TYPE_ETH]: ETH_SIGNATURE_PROVIDER,
5
- };
6
- export const SelectedServiceSignatureType = ServiceSignatureType.SERVICE_SIGNATURE_TYPE_ETH;
7
- export const SelectedServiceSignature = SIGNATURES[SelectedServiceSignatureType];