@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,45 +1,38 @@
1
- import { Ajv } from "ajv";
1
+ import { Ajv } from 'ajv';
2
2
  import { PROVIDER_SCHEMAS } from "../../types/providers.gen.js";
3
3
  import { AttestorError } from "../../utils/error.js";
4
4
  const PROVIDER_VALIDATOR_MAP = {};
5
5
  const AJV = new Ajv({
6
- allErrors: true,
7
- strict: true,
8
- strictRequired: false,
9
- formats: {
10
- binary(data) {
11
- return data instanceof Uint8Array || typeof Buffer !== "undefined" && Buffer.isBuffer(data);
12
- },
13
- url(data) {
14
- try {
15
- new URL(data);
16
- return true;
17
- } catch {
18
- return false;
19
- }
6
+ allErrors: true,
7
+ strict: true,
8
+ strictRequired: false,
9
+ formats: {
10
+ binary(data) {
11
+ return data instanceof Uint8Array
12
+ || (typeof Buffer !== 'undefined'
13
+ && Buffer.isBuffer(data));
14
+ },
15
+ url(data) {
16
+ try {
17
+ new URL(data);
18
+ return true;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
20
24
  }
21
- }
22
25
  });
23
- function assertValidateProviderParams(name, params) {
24
- let validate = PROVIDER_VALIDATOR_MAP[name];
25
- if (!validate) {
26
- const schema = PROVIDER_SCHEMAS[name]?.parameters;
27
- if (!schema) {
28
- throw new AttestorError(
29
- "ERROR_BAD_REQUEST",
30
- `Invalid provider name "${String(name)}"`
31
- );
26
+ export function assertValidateProviderParams(name, params) {
27
+ let validate = PROVIDER_VALIDATOR_MAP[name];
28
+ if (!validate) {
29
+ const schema = PROVIDER_SCHEMAS[name]?.parameters;
30
+ if (!schema) {
31
+ throw new AttestorError('ERROR_BAD_REQUEST', `Invalid provider name "${String(name)}"`);
32
+ }
33
+ validate = AJV.compile(schema);
34
+ }
35
+ if (!validate?.(params)) {
36
+ throw new AttestorError('ERROR_BAD_REQUEST', 'Params validation failed', { errors: JSON.stringify(validate.errors) });
32
37
  }
33
- validate = AJV.compile(schema);
34
- }
35
- if (!validate?.(params)) {
36
- throw new AttestorError(
37
- "ERROR_BAD_REQUEST",
38
- "Params validation failed",
39
- { errors: JSON.stringify(validate.errors) }
40
- );
41
- }
42
38
  }
43
- export {
44
- assertValidateProviderParams
45
- };
package/lib/types/bgp.js CHANGED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -2,6 +2,7 @@ import type { TLSConnectionOptions } from '@reclaimprotocol/tls';
2
2
  import type { AttestorVersion, ProviderClaimData } from '#src/proto/api.ts';
3
3
  import type { ArraySlice, Logger, RedactedOrHashedArraySlice } from '#src/types/general.ts';
4
4
  import type { ProvidersConfig } from '#src/types/providers.gen.ts';
5
+ import type { Awaitable } from '#src/types/signatures.ts';
5
6
  import type { Transcript } from '#src/types/tunnel.ts';
6
7
  export type AttestorData = {
7
8
  id: string;
@@ -114,11 +115,11 @@ export interface Provider<N extends ProviderName, Params = ProviderParams<N>, Se
114
115
  * Optionally return parameters extracted from the receipt
115
116
  * that will then be included in the claim context
116
117
  * */
117
- assertValidProviderReceipt(opts: AssertValidProviderReceipt<Params>): void | Promise<void> | {
118
+ assertValidProviderReceipt(opts: AssertValidProviderReceipt<Params>): Awaitable<{
118
119
  extractedParameters: {
119
120
  [key: string]: string;
120
121
  };
121
- };
122
+ } | undefined>;
122
123
  }
123
124
  export type ProofGenerationStep = {
124
125
  name: 'connecting';
@@ -1,16 +1,10 @@
1
- const HttpProviderParametersJson = { "title": "HttpProviderParameters", "type": "object", "required": ["url", "method", "responseMatches"], "properties": { "url": { "type": "string", "format": "url", "description": "which URL does the request have to be made to Has to be a valid https URL for eg. https://amazon.in/orders?q=abcd" }, "method": { "type": "string", "enum": ["GET", "POST", "PUT", "PATCH"] }, "geoLocation": { "type": "string", "nullable": true, "description": "Specify the geographical location from where to proxy the request. 2-letter ISO country code or parameter (public or secret)" }, "proxySessionId": { "type": "string", "nullable": true, "description": 'Specify the unique session id for allowing use of same proxy ip across multiple requests. Can be a smallcase alphanumeric string of length 8-14 characters. eg. "mystring12345", "something1234".' }, "headers": { "type": "object", "description": "Any additional headers to be sent with the request Note: these will be revealed to the attestor & won't be redacted from the transcript. To add hidden headers, use 'secretParams.headers' instead", "additionalProperties": { "type": "string" } }, "body": { "description": "Body of the HTTP request", "oneOf": [{ "type": "string", "format": "binary" }, { "type": "string" }] }, "writeRedactionMode": { "type": "string", "description": `If the API doesn't perform well with the "key-update" method of redaction, you can switch to "zk" mode by setting this to "zk"`, "enum": ["zk", "key-update"] }, "additionalClientOptions": { "type": "object", "description": "Apply TLS configuration when creating the tunnel to the attestor.", "nullable": true, "properties": { "supportedProtocolVersions": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "enum": ["TLS1_2", "TLS1_3"] } } } }, "responseMatches": { "type": "array", "minItems": 1, "uniqueItems": true, "description": "The attestor will use this list to check that the redacted response does indeed match all the provided strings/regexes", "items": { "type": "object", "required": ["value", "type"], "properties": { "value": { "type": "string", "description": '"regex": the response must match the regex "contains": the response must contain the provided\n string exactly' }, "type": { "type": "string", "description": "The string/regex to match against", "enum": ["regex", "contains"] }, "invert": { "type": "boolean", "description": "Inverses the matching logic. Fail when match is found and proceed otherwise" } }, "additionalProperties": false } }, "responseRedactions": { "type": "array", "uniqueItems": true, "description": 'which portions to select from a response. These are selected in order, xpath => jsonPath => regex * These redactions are done client side and only the selected portions are sent to the attestor. The attestor will only be able to see the selected portions alongside the first line of the HTTP response (i.e. "HTTP/1.1 200 OK") * To disable any redactions, pass an empty array', "items": { "type": "object", "properties": { "xPath": { "type": "string", "nullable": true, "description": 'expect an HTML response, and to contain a certain xpath for eg. "/html/body/div.a1/div.a2/span.a5"' }, "jsonPath": { "type": "string", "nullable": true, "description": "expect a JSON response, retrieve the item at this path using dot notation for e.g. 'email.addresses.0'" }, "regex": { "type": "string", "nullable": true, "description": "select a regex match from the response" }, "hash": { "type": "string", "description": `If provided, the value inside will be hashed instead of being redacted. Useful for cases where the data inside is an identifiying piece of information that you don't want to reveal to the attestor, eg. an email address.
2
- If the hash function produces more bytes than the original value, the hash will be truncated.
3
- Eg. if hash is enabled, the original value is "hello", and hashed is "a1b2c", then the attestor will only see "a1b2c".
4
- Note: if a regex with named groups is provided, only the named groups will be hashed.`, "enum": ["oprf", "oprf-mpc", "oprf-raw"] } }, "additionalProperties": false } }, "paramValues": { "type": "object", "description": "A map of parameter values which are user in form of {{param}} in URL, responseMatches, responseRedactions, body, geolocation. Those in URL, responseMatches & geo will be put into context and signed This value will NOT be included in provider hash", "additionalProperties": { "type": "string" } } }, "additionalProperties": false };
5
- const HttpProviderSecretParametersJson = { "title": "HttpProviderSecretParameters", "type": "object", "description": "Secret parameters to be used with HTTP provider. None of the values in this object will be shown to the attestor", "properties": { "cookieStr": { "type": "string", "description": "cookie string for authorisation." }, "authorisationHeader": { "type": "string", "description": "authorisation header value" }, "headers": { "type": "object", "description": "Headers that need to be hidden from the attestor", "additionalProperties": { "type": "string" } }, "paramValues": { "type": "object", "description": "A map of parameter values which are user in form of {{param}} in body these parameters will NOT be shown to attestor and extracted", "additionalProperties": { "type": "string" } } }, "additionalProperties": false };
6
- const PROVIDER_SCHEMAS = {
7
- http: {
8
- parameters: HttpProviderParametersJson,
9
- secretParameters: HttpProviderSecretParametersJson
10
- }
11
- };
12
- export {
13
- HttpProviderParametersJson,
14
- HttpProviderSecretParametersJson,
15
- PROVIDER_SCHEMAS
1
+ /* eslint-disable */
2
+ /* Generated file. Do not edit */
3
+ export const HttpProviderParametersJson = { "title": "HttpProviderParameters", "type": "object", "required": ["url", "method", "responseMatches"], "properties": { "url": { "type": "string", "format": "url", "description": "which URL does the request have to be made to Has to be a valid https URL for eg. https://amazon.in/orders?q=abcd" }, "method": { "type": "string", "enum": ["GET", "POST", "PUT", "PATCH"] }, "geoLocation": { "type": "string", "nullable": true, "description": "Specify the geographical location from where to proxy the request. 2-letter ISO country code or parameter (public or secret)" }, "proxySessionId": { "type": "string", "nullable": true, "description": "Specify the unique session id for allowing use of same proxy ip across multiple requests. Can be a smallcase alphanumeric string of length 8-14 characters. eg. \"mystring12345\", \"something1234\"." }, "headers": { "type": "object", "description": "Any additional headers to be sent with the request Note: these will be revealed to the attestor & won't be redacted from the transcript. To add hidden headers, use 'secretParams.headers' instead", "additionalProperties": { "type": "string" } }, "body": { "description": "Body of the HTTP request", "oneOf": [{ "type": "string", "format": "binary" }, { "type": "string" }] }, "writeRedactionMode": { "type": "string", "description": "If the API doesn't perform well with the \"key-update\" method of redaction, you can switch to \"zk\" mode by setting this to \"zk\"", "enum": ["zk", "key-update"] }, "additionalClientOptions": { "type": "object", "description": "Apply TLS configuration when creating the tunnel to the attestor.", "nullable": true, "properties": { "supportedProtocolVersions": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "enum": ["TLS1_2", "TLS1_3"] } } } }, "responseMatches": { "type": "array", "minItems": 1, "uniqueItems": true, "description": "The attestor will use this list to check that the redacted response does indeed match all the provided strings/regexes", "items": { "type": "object", "required": ["value", "type"], "properties": { "value": { "type": "string", "description": "\"regex\": the response must match the regex \"contains\": the response must contain the provided\n string exactly" }, "type": { "type": "string", "description": "The string/regex to match against", "enum": ["regex", "contains"] }, "invert": { "type": "boolean", "description": "Inverses the matching logic. Fail when match is found and proceed otherwise" } }, "additionalProperties": false } }, "responseRedactions": { "type": "array", "uniqueItems": true, "description": "which portions to select from a response. These are selected in order, xpath => jsonPath => regex * These redactions are done client side and only the selected portions are sent to the attestor. The attestor will only be able to see the selected portions alongside the first line of the HTTP response (i.e. \"HTTP/1.1 200 OK\") * To disable any redactions, pass an empty array", "items": { "type": "object", "properties": { "xPath": { "type": "string", "nullable": true, "description": "expect an HTML response, and to contain a certain xpath for eg. \"/html/body/div.a1/div.a2/span.a5\"" }, "jsonPath": { "type": "string", "nullable": true, "description": "expect a JSON response, retrieve the item at this path using dot notation for e.g. 'email.addresses.0'" }, "regex": { "type": "string", "nullable": true, "description": "select a regex match from the response" }, "hash": { "type": "string", "description": "If provided, the value inside will be hashed instead of being redacted. Useful for cases where the data inside is an identifiying piece of information that you don't want to reveal to the attestor, eg. an email address.\nIf the hash function produces more bytes than the original value, the hash will be truncated.\nEg. if hash is enabled, the original value is \"hello\", and hashed is \"a1b2c\", then the attestor will only see \"a1b2c\".\nNote: if a regex with named groups is provided, only the named groups will be hashed.", "enum": ["oprf", "oprf-mpc", "oprf-raw"] } }, "additionalProperties": false } }, "paramValues": { "type": "object", "description": "A map of parameter values which are user in form of {{param}} in URL, responseMatches, responseRedactions, body, geolocation. Those in URL, responseMatches & geo will be put into context and signed This value will NOT be included in provider hash", "additionalProperties": { "type": "string" } } }, "additionalProperties": false };
4
+ export const HttpProviderSecretParametersJson = { "title": "HttpProviderSecretParameters", "type": "object", "description": "Secret parameters to be used with HTTP provider. None of the values in this object will be shown to the attestor", "properties": { "cookieStr": { "type": "string", "description": "cookie string for authorisation." }, "authorisationHeader": { "type": "string", "description": "authorisation header value" }, "headers": { "type": "object", "description": "Headers that need to be hidden from the attestor", "additionalProperties": { "type": "string" } }, "paramValues": { "type": "object", "description": "A map of parameter values which are user in form of {{param}} in body these parameters will NOT be shown to attestor and extracted", "additionalProperties": { "type": "string" } } }, "additionalProperties": false };
5
+ export const PROVIDER_SCHEMAS = {
6
+ http: {
7
+ parameters: HttpProviderParametersJson,
8
+ secretParameters: HttpProviderSecretParametersJson
9
+ },
16
10
  };
@@ -0,0 +1 @@
1
+ export {};
package/lib/types/rpc.js CHANGED
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,5 @@
1
1
  export type PrivateKey = string;
2
- type Awaitable<T> = T | Promise<T>;
2
+ export type Awaitable<T> = T | Promise<T>;
3
3
  export type ServiceSignatureProvider = {
4
4
  /**
5
5
  * Returns public key in compressed (compact) format used in Reclaim RPC calls
@@ -25,4 +25,3 @@ export type ServiceSignatureProvider = {
25
25
  */
26
26
  verify(data: Uint8Array, signature: Uint8Array | string, addressBytes: Uint8Array | string): Awaitable<boolean>;
27
27
  };
28
- export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/lib/types/zk.js CHANGED
@@ -0,0 +1 @@
1
+ export {};
package/lib/utils/auth.js CHANGED
@@ -1,71 +1,59 @@
1
- import { getBytes } from "ethers";
1
+ import { getBytes } from 'ethers';
2
2
  import { DEFAULT_AUTH_EXPIRY_S } from "../config/index.js";
3
3
  import { AuthenticatedUserData } from "../proto/api.js";
4
- import { getEnvVariable } from "../utils/env.js";
5
- import { AttestorError } from "../utils/error.js";
6
- import { unixTimestampSeconds } from "../utils/generics.js";
7
- import { SelectedServiceSignature, SIGNATURES } from "../utils/signatures/index.js";
8
- async function assertValidAuthRequest(request, signatureType) {
9
- const publicKey = getEnvVariable("AUTHENTICATION_PUBLIC_KEY");
10
- if (!request) {
11
- if (publicKey) {
12
- throw new AttestorError(
13
- "ERROR_AUTHENTICATION_FAILED",
14
- "User must be authenticated"
15
- );
4
+ import { getEnvVariable } from "./env.js";
5
+ import { AttestorError } from "./error.js";
6
+ import { unixTimestampSeconds } from "./generics.js";
7
+ import { SelectedServiceSignature, SIGNATURES } from "./signatures/index.js";
8
+ export async function assertValidAuthRequest(request, signatureType) {
9
+ const publicKey = getEnvVariable('AUTHENTICATION_PUBLIC_KEY');
10
+ // nothing to verify
11
+ if (!request) {
12
+ // if pub key is provided -- but user didn't attempt to
13
+ // authenticate, then we should throw an error
14
+ if (publicKey) {
15
+ throw new AttestorError('ERROR_AUTHENTICATION_FAILED', 'User must be authenticated');
16
+ }
17
+ return;
18
+ }
19
+ if (!publicKey) {
20
+ throw new AttestorError('ERROR_BAD_REQUEST', 'The attestor is not configured for authentication');
21
+ }
22
+ const { signature, data } = request;
23
+ if (!data) {
24
+ throw new AttestorError('ERROR_AUTHENTICATION_FAILED', 'Missing data in auth request');
25
+ }
26
+ if (data.expiresAt < unixTimestampSeconds()) {
27
+ throw new AttestorError('ERROR_AUTHENTICATION_FAILED', 'Authentication request has expired');
28
+ }
29
+ const proto = AuthenticatedUserData.encode(data).finish();
30
+ const signatureAlg = SIGNATURES[signatureType];
31
+ const address = signatureAlg.getAddress(getBytes(publicKey));
32
+ const verified = await signatureAlg
33
+ .verify(proto, signature, address);
34
+ if (!verified) {
35
+ throw new AttestorError('ERROR_AUTHENTICATION_FAILED', 'Signature verification failed');
16
36
  }
17
- return;
18
- }
19
- if (!publicKey) {
20
- throw new AttestorError(
21
- "ERROR_BAD_REQUEST",
22
- "The attestor is not configured for authentication"
23
- );
24
- }
25
- const { signature, data } = request;
26
- if (!data) {
27
- throw new AttestorError(
28
- "ERROR_AUTHENTICATION_FAILED",
29
- "Missing data in auth request"
30
- );
31
- }
32
- if (data.expiresAt < unixTimestampSeconds()) {
33
- throw new AttestorError(
34
- "ERROR_AUTHENTICATION_FAILED",
35
- "Authentication request has expired"
36
- );
37
- }
38
- const proto = AuthenticatedUserData.encode(data).finish();
39
- const signatureAlg = SIGNATURES[signatureType];
40
- const address = signatureAlg.getAddress(
41
- getBytes(publicKey)
42
- );
43
- const verified = await signatureAlg.verify(proto, signature, address);
44
- if (!verified) {
45
- throw new AttestorError(
46
- "ERROR_AUTHENTICATION_FAILED",
47
- "Signature verification failed"
48
- );
49
- }
50
37
  }
51
- async function createAuthRequest(_data, privateKey) {
52
- const createdAt = unixTimestampSeconds();
53
- const data = {
54
- createdAt,
55
- expiresAt: createdAt + DEFAULT_AUTH_EXPIRY_S,
56
- id: "",
57
- hostWhitelist: [],
58
- ..._data
59
- };
60
- const proto = AuthenticatedUserData.encode(data).finish();
61
- const signature = await SelectedServiceSignature.sign(proto, privateKey);
62
- const request = {
63
- data,
64
- signature
65
- };
66
- return request;
38
+ /**
39
+ * Create an authentication request with the given data and private key,
40
+ * which can then be used to authenticate with the service.
41
+ */
42
+ export async function createAuthRequest(_data, privateKey) {
43
+ const createdAt = unixTimestampSeconds();
44
+ const data = {
45
+ createdAt,
46
+ expiresAt: createdAt + DEFAULT_AUTH_EXPIRY_S,
47
+ id: '',
48
+ hostWhitelist: [],
49
+ ..._data,
50
+ };
51
+ const proto = AuthenticatedUserData.encode(data).finish();
52
+ const signature = await SelectedServiceSignature
53
+ .sign(proto, privateKey);
54
+ const request = {
55
+ data,
56
+ signature
57
+ };
58
+ return request;
67
59
  }
68
- export {
69
- assertValidAuthRequest,
70
- createAuthRequest
71
- };
@@ -1,17 +1,17 @@
1
- import { decodeBase64, encodeBase64 } from "ethers";
2
- const B64_JSON_REPLACER = (key, value) => {
3
- if (value instanceof Uint8Array || typeof value === "object" && value && "buffer" in value && value.buffer instanceof ArrayBuffer) {
4
- return { type: "uint8array", value: encodeBase64(value) };
5
- }
6
- return value;
1
+ import { decodeBase64, encodeBase64 } from 'ethers';
2
+ export const B64_JSON_REPLACER = (key, value) => {
3
+ if (value instanceof Uint8Array
4
+ || (typeof value === 'object'
5
+ && value
6
+ && 'buffer' in value
7
+ && value.buffer instanceof ArrayBuffer)) {
8
+ return { type: 'uint8array', value: encodeBase64(value) };
9
+ }
10
+ return value;
7
11
  };
8
- const B64_JSON_REVIVER = (key, value) => {
9
- if (value?.type === "uint8array") {
10
- return decodeBase64(value.value);
11
- }
12
- return value;
13
- };
14
- export {
15
- B64_JSON_REPLACER,
16
- B64_JSON_REVIVER
12
+ export const B64_JSON_REVIVER = (key, value) => {
13
+ if (value?.type === 'uint8array') {
14
+ return decodeBase64(value.value);
15
+ }
16
+ return value;
17
17
  };
@@ -1,123 +1,119 @@
1
- import CIDR from "ip-cidr";
1
+ import CIDR from 'ip-cidr';
2
2
  import { BGP_WS_URL } from "../config/index.js";
3
- import { makeWebSocket } from "../utils/ws.js";
4
- const ANNOUNCEMENT_OVERLAP = "announcement-overlap";
3
+ import { makeWebSocket } from "./ws.js";
4
+ const ANNOUNCEMENT_OVERLAP = 'announcement-overlap';
5
5
  class BGPAnnouncementOverlapEvent extends Event {
6
- data;
7
- constructor(data) {
8
- super(ANNOUNCEMENT_OVERLAP);
9
- this.data = data;
10
- }
6
+ data;
7
+ constructor(data) {
8
+ super(ANNOUNCEMENT_OVERLAP);
9
+ this.data = data;
10
+ }
11
11
  }
12
- function createBgpListener(logger) {
13
- let ws;
14
- let closed = false;
15
- const targetIps = /* @__PURE__ */ new Set();
16
- const eventTarget = new EventTarget();
17
- openWs();
18
- return {
19
- onOverlap(ips, callback) {
20
- for (const ip of ips) {
21
- targetIps.add(ip);
22
- }
23
- eventTarget.addEventListener(
24
- ANNOUNCEMENT_OVERLAP,
25
- _callback
26
- );
27
- return () => {
28
- for (const ip of ips) {
29
- targetIps.delete(ip);
12
+ /**
13
+ * Listens for BGP announcements and emits events whenever
14
+ * an announcement overlaps with a target IP.
15
+ */
16
+ export function createBgpListener(logger) {
17
+ let ws;
18
+ let closed = false;
19
+ const targetIps = new Set();
20
+ const eventTarget = new EventTarget();
21
+ openWs();
22
+ return {
23
+ onOverlap(ips, callback) {
24
+ for (const ip of ips) {
25
+ targetIps.add(ip);
26
+ }
27
+ eventTarget.addEventListener(ANNOUNCEMENT_OVERLAP, _callback);
28
+ return () => {
29
+ for (const ip of ips) {
30
+ targetIps.delete(ip);
31
+ }
32
+ eventTarget.removeEventListener(ANNOUNCEMENT_OVERLAP, _callback);
33
+ };
34
+ function _callback(event) {
35
+ callback(event.data);
36
+ }
37
+ },
38
+ close() {
39
+ ws.onclose = null;
40
+ ws.onerror = null;
41
+ ws.close();
42
+ closed = true;
30
43
  }
31
- eventTarget.removeEventListener(
32
- ANNOUNCEMENT_OVERLAP,
33
- _callback
34
- );
35
- };
36
- function _callback(event) {
37
- callback(event.data);
38
- }
39
- },
40
- close() {
41
- ws.onclose = null;
42
- ws.onerror = null;
43
- ws.close();
44
- closed = true;
45
- }
46
- };
47
- function openWs() {
48
- logger.debug("connecting to BGP websocket");
49
- ws = makeWebSocket(BGP_WS_URL);
50
- ws.onopen = onOpen;
51
- ws.onerror = (ev) => onClose(ev);
52
- ws.onclose = () => onClose(new Error("Unexpected close"));
53
- ws.onmessage = ({ data }) => {
54
- const str = typeof data === "string" ? data : data.toString();
55
- try {
56
- onMessage(str);
57
- } catch (err) {
58
- logger.error({ data, err }, "error processing BGP message");
59
- }
60
44
  };
61
- }
62
- function onOpen() {
63
- const subscriptionMessage = {
64
- type: "ris_subscribe",
65
- data: {
66
- type: "UPDATE"
67
- }
68
- };
69
- ws.send(JSON.stringify(subscriptionMessage));
70
- logger.info("connected to BGP websocket");
71
- }
72
- function onClose(err) {
73
- if (closed) {
74
- return;
75
- }
76
- logger.info({ err }, "BGP websocket closed");
77
- if (!err) {
78
- return;
45
+ function openWs() {
46
+ logger.debug('connecting to BGP websocket');
47
+ ws = makeWebSocket(BGP_WS_URL);
48
+ ws.onopen = onOpen;
49
+ ws.onerror = (ev) => onClose(ev);
50
+ ws.onclose = () => onClose(new Error('Unexpected close'));
51
+ ws.onmessage = ({ data }) => {
52
+ const str = typeof data === 'string' ? data : data.toString();
53
+ try {
54
+ onMessage(str);
55
+ }
56
+ catch (err) {
57
+ logger.error({ data, err }, 'error processing BGP message');
58
+ }
59
+ };
79
60
  }
80
- logger.info("reconnecting to BGP websocket");
81
- openWs();
82
- }
83
- function onMessage(message) {
84
- const data = JSON.parse(message);
85
- const announcements = data?.data?.announcements;
86
- logger.trace({ data }, "got BGP update");
87
- if (!Array.isArray(announcements)) {
88
- return;
61
+ function onOpen() {
62
+ const subscriptionMessage = {
63
+ type: 'ris_subscribe',
64
+ data: {
65
+ type: 'UPDATE',
66
+ },
67
+ };
68
+ ws.send(JSON.stringify(subscriptionMessage));
69
+ logger.info('connected to BGP websocket');
89
70
  }
90
- const asPath = data?.data?.path;
91
- for (const announcement of announcements) {
92
- const prefixes = announcement?.prefixes;
93
- const nextHop = announcement?.["next_hop"];
94
- const hasPrefixes = prefixes?.length && (nextHop || asPath);
95
- if (!hasPrefixes) {
96
- return;
97
- }
98
- for (const prefix of prefixes) {
99
- if (!overlapsTargetIps(prefix)) {
100
- continue;
71
+ function onClose(err) {
72
+ if (closed) {
73
+ return;
101
74
  }
102
- eventTarget.dispatchEvent(
103
- new BGPAnnouncementOverlapEvent({ prefix })
104
- );
105
- }
75
+ logger.info({ err }, 'BGP websocket closed');
76
+ if (!err) {
77
+ return;
78
+ }
79
+ logger.info('reconnecting to BGP websocket');
80
+ openWs();
106
81
  }
107
- }
108
- function overlapsTargetIps(prefix) {
109
- if (prefix.endsWith("/0")) {
110
- return false;
82
+ function onMessage(message) {
83
+ const data = JSON.parse(message);
84
+ const announcements = data?.data?.announcements;
85
+ logger.trace({ data }, 'got BGP update');
86
+ if (!Array.isArray(announcements)) {
87
+ return;
88
+ }
89
+ const asPath = data?.data?.path;
90
+ for (const announcement of announcements) {
91
+ const prefixes = announcement?.prefixes;
92
+ const nextHop = announcement?.['next_hop'];
93
+ const hasPrefixes = prefixes?.length && (nextHop || asPath);
94
+ if (!hasPrefixes) {
95
+ return;
96
+ }
97
+ for (const prefix of prefixes) {
98
+ if (!overlapsTargetIps(prefix)) {
99
+ continue;
100
+ }
101
+ // emit event
102
+ eventTarget.dispatchEvent(new BGPAnnouncementOverlapEvent({ prefix }));
103
+ }
104
+ }
111
105
  }
112
- const cidr = new CIDR(prefix);
113
- for (const ip of targetIps) {
114
- if (cidr.contains(ip)) {
115
- return true;
116
- }
106
+ function overlapsTargetIps(prefix) {
107
+ // ignore all prefixes that end with /0
108
+ if (prefix.endsWith('/0')) {
109
+ return false;
110
+ }
111
+ const cidr = new CIDR(prefix);
112
+ for (const ip of targetIps) {
113
+ if (cidr.contains(ip)) {
114
+ return true;
115
+ }
116
+ }
117
+ return false;
117
118
  }
118
- return false;
119
- }
120
119
  }
121
- export {
122
- createBgpListener
123
- };