@otskit/client 0.3.0 → 0.5.0
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/README.md +1 -1
- package/dist/index.cjs +130 -1515
- package/dist/index.d.cts +68 -47
- package/dist/index.d.ts +68 -47
- package/dist/index.js +133 -1505
- package/package.json +7 -5
package/dist/index.d.cts
CHANGED
|
@@ -4,7 +4,7 @@ export { Attestation, BitcoinAttestation, DetachedTimestampFile, PendingAttestat
|
|
|
4
4
|
/**
|
|
5
5
|
* Type definitions for the OpenTimestamps Client SDK
|
|
6
6
|
*/
|
|
7
|
-
/** Logger interface for observability */
|
|
7
|
+
/** Logger interface for observability. */
|
|
8
8
|
interface Logger {
|
|
9
9
|
debug(message: string, ...args: unknown[]): void;
|
|
10
10
|
info(message: string, ...args: unknown[]): void;
|
|
@@ -39,7 +39,7 @@ interface ResilienceOptions {
|
|
|
39
39
|
connectTimeoutMs: number;
|
|
40
40
|
retries: RetryOptions;
|
|
41
41
|
circuitBreaker: CircuitBreakerOptions;
|
|
42
|
-
/**
|
|
42
|
+
/** Maximum bytes allowed in the response body. Defaults to 100 KB. */
|
|
43
43
|
maxResponseBytes?: number;
|
|
44
44
|
}
|
|
45
45
|
/** Client configuration options */
|
|
@@ -55,12 +55,18 @@ interface ClientOptions {
|
|
|
55
55
|
/** Minimum successful calendar submissions required (default: 2) */
|
|
56
56
|
minimumSuccessfulSubmissions?: number;
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
58
|
+
* Base URL for the Esplora block explorer used by verify().
|
|
59
|
+
* Defaults to Blockstream (https://blockstream.info/api).
|
|
60
|
+
* Override to use a self-hosted or alternative explorer.
|
|
61
|
+
*/
|
|
62
|
+
esploraUrl?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Allows calendar URLs that resolve to private/reserved IPs.
|
|
59
65
|
*
|
|
60
|
-
* **
|
|
66
|
+
* **Do not enable in production.** Useful for local testing or corporate networks.
|
|
61
67
|
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
68
|
+
* Even when `false`, protection is best-effort against DNS rebinding (TOCTOU).
|
|
69
|
+
* For high-security environments, complement with network-level egress filtering.
|
|
64
70
|
*
|
|
65
71
|
* @default false
|
|
66
72
|
*/
|
|
@@ -99,7 +105,7 @@ interface VerificationNetworkError {
|
|
|
99
105
|
type VerificationResult = VerificationSuccess | VerificationPending | VerificationInvalid | VerificationNetworkError;
|
|
100
106
|
/** Type guard — verdadero si la verificación fue exitosa. */
|
|
101
107
|
declare const isVerified: (r: VerificationResult) => r is VerificationSuccess;
|
|
102
|
-
/** Default calendar servers */
|
|
108
|
+
/** Default calendar servers. Sourced from @otskit/core (single source of truth). */
|
|
103
109
|
declare const DEFAULT_CALENDARS: string[];
|
|
104
110
|
/** Default resilience configuration */
|
|
105
111
|
declare const DEFAULT_RESILIENCE: ResilienceOptions;
|
|
@@ -139,6 +145,7 @@ declare class OpenTimestampsClient {
|
|
|
139
145
|
private globalSignal?;
|
|
140
146
|
private minimumSuccessfulSubmissions;
|
|
141
147
|
private allowPrivateCalendars;
|
|
148
|
+
private esploraUrl;
|
|
142
149
|
/**
|
|
143
150
|
* Create a new OpenTimestamps client
|
|
144
151
|
*
|
|
@@ -265,7 +272,7 @@ declare class UpgradeError extends OpenTimestampsClientError {
|
|
|
265
272
|
}
|
|
266
273
|
/** Network-related error (timeout, all retries failed, etc.) */
|
|
267
274
|
declare class NetworkError extends OpenTimestampsClientError {
|
|
268
|
-
/** HTTP status code
|
|
275
|
+
/** HTTP status code when the failure originates from an HTTP response. */
|
|
269
276
|
readonly status?: number;
|
|
270
277
|
constructor(message: string, options?: {
|
|
271
278
|
cause?: Error;
|
|
@@ -276,16 +283,16 @@ declare class NetworkError extends OpenTimestampsClientError {
|
|
|
276
283
|
declare class CircuitBreakerError extends NetworkError {
|
|
277
284
|
constructor(calendar: string);
|
|
278
285
|
}
|
|
279
|
-
/**
|
|
286
|
+
/** The calendar does not yet know the queried commitment (HTTP 404). */
|
|
280
287
|
declare class CommitmentNotFoundError extends NetworkError {
|
|
281
288
|
}
|
|
282
|
-
/**
|
|
289
|
+
/** The calendar response exceeds the allowed size limit (DoS defense). */
|
|
283
290
|
declare class CalendarResponseTooLargeError extends NetworkError {
|
|
284
291
|
}
|
|
285
|
-
/**
|
|
292
|
+
/** Invalid Esplora response: empty, non-JSON, malformed, or too large (DoS defense). */
|
|
286
293
|
declare class EsploraResponseError extends NetworkError {
|
|
287
294
|
}
|
|
288
|
-
/**
|
|
295
|
+
/** Response exceeds the allowed byte limit (DoS defense). */
|
|
289
296
|
declare class SizeLimitExceededError extends NetworkError {
|
|
290
297
|
readonly maxBytes: number;
|
|
291
298
|
readonly actualBytes?: number;
|
|
@@ -306,8 +313,7 @@ declare enum CircuitState {
|
|
|
306
313
|
}
|
|
307
314
|
|
|
308
315
|
/**
|
|
309
|
-
*
|
|
310
|
-
* Funciona en Node.js 18+, browsers y edge runtimes.
|
|
316
|
+
* Fetch adapter for Node.js 20+.
|
|
311
317
|
*/
|
|
312
318
|
interface FetchRequest {
|
|
313
319
|
url: string;
|
|
@@ -341,64 +347,79 @@ declare class ResilientNetworkLayer {
|
|
|
341
347
|
}
|
|
342
348
|
|
|
343
349
|
/**
|
|
344
|
-
*
|
|
350
|
+
* Remote OpenTimestamps calendar client (real OTS protocol).
|
|
345
351
|
*/
|
|
346
352
|
|
|
347
|
-
/**
|
|
353
|
+
/** Maximum response size from a calendar server (DoS defense). */
|
|
348
354
|
declare const MAX_CALENDAR_RESPONSE_SIZE = 10000;
|
|
349
|
-
/**
|
|
355
|
+
/** Interface to a remote calendar server. */
|
|
350
356
|
declare class CalendarClient {
|
|
351
357
|
#private;
|
|
352
358
|
private readonly url;
|
|
353
359
|
private readonly networkLayer;
|
|
354
360
|
private readonly logger?;
|
|
355
361
|
constructor(url: string, networkLayer: ResilientNetworkLayer, logger?: Logger | undefined);
|
|
356
|
-
/**
|
|
362
|
+
/** Submits a digest to the calendar and returns the Timestamp that commits to it. */
|
|
357
363
|
submit(digest: Uint8Array, signal?: AbortSignal): Promise<Timestamp>;
|
|
358
|
-
/**
|
|
364
|
+
/** Asks the calendar for a more complete Timestamp for `commitment` (upgrade). */
|
|
359
365
|
getTimestamp(commitment: Uint8Array, signal?: AbortSignal): Promise<Timestamp>;
|
|
360
366
|
}
|
|
361
|
-
/**
|
|
367
|
+
/** Allowlist of trusted calendar URLs. */
|
|
362
368
|
declare class UrlWhitelist {
|
|
363
369
|
#private;
|
|
364
370
|
constructor(urls?: readonly string[]);
|
|
365
|
-
/**
|
|
371
|
+
/**
|
|
372
|
+
* Adds a pattern. If the URL has no scheme, both http:// and https:// variants are added.
|
|
373
|
+
* Throws TypeError if the pattern is not a valid string or is structurally invalid.
|
|
374
|
+
*/
|
|
366
375
|
add(url: string): void;
|
|
367
|
-
/**
|
|
376
|
+
/** Returns true if `url` matches any pattern in the allowlist. */
|
|
368
377
|
contains(url: string): boolean;
|
|
369
378
|
toString(): string;
|
|
370
379
|
}
|
|
371
|
-
/**
|
|
380
|
+
/**
|
|
381
|
+
* Default trusted calendars for verification/upgrade.
|
|
382
|
+
* Patterns sourced from @otskit/core (single source of truth).
|
|
383
|
+
*/
|
|
372
384
|
declare const DEFAULT_CALENDAR_WHITELIST: UrlWhitelist;
|
|
373
|
-
/**
|
|
385
|
+
/**
|
|
386
|
+
* Default aggregators to submit digests to when stamping.
|
|
387
|
+
* Sourced from @otskit/core (single source of truth).
|
|
388
|
+
*/
|
|
374
389
|
declare const DEFAULT_AGGREGATORS: readonly string[];
|
|
375
390
|
|
|
376
|
-
/**
|
|
391
|
+
/** Default public Esplora explorer (Bitcoin mainnet). */
|
|
377
392
|
declare const PUBLIC_ESPLORA_URL = "https://blockstream.info/api";
|
|
378
|
-
/**
|
|
393
|
+
/** Maximum size of an Esplora response (DoS defense). A JSON block header is a few hundred bytes. */
|
|
379
394
|
declare const MAX_ESPLORA_RESPONSE_SIZE = 100000;
|
|
380
395
|
interface EsploraClientOptions {
|
|
381
|
-
/** URL
|
|
396
|
+
/** Base URL of the explorer (defaults to Blockstream). Useful for pointing to a Litecoin Esplora. */
|
|
382
397
|
url?: string;
|
|
383
398
|
logger?: Logger;
|
|
384
399
|
}
|
|
385
|
-
/**
|
|
400
|
+
/** Client for a remote Esplora explorer. */
|
|
386
401
|
declare class EsploraClient {
|
|
387
402
|
#private;
|
|
388
403
|
constructor(networkLayer: ResilientNetworkLayer, options?: EsploraClientOptions);
|
|
389
|
-
/**
|
|
404
|
+
/** Returns the block hash (64-char hex, lowercase) at the given height. */
|
|
390
405
|
blockHash(height: number, signal?: AbortSignal): Promise<string>;
|
|
391
|
-
/**
|
|
406
|
+
/** Returns the block header (merkle root + timestamp) for the given hash. */
|
|
392
407
|
block(hash: string, signal?: AbortSignal): Promise<BlockHeader>;
|
|
408
|
+
/**
|
|
409
|
+
* Fetches the raw 80-byte block header for `hash` and self-authenticates it:
|
|
410
|
+
* sha256d(rawHeader) reversed must equal `hash`. This removes trust in the explorer's
|
|
411
|
+
* JSON layer — the raw header is cryptographically bound to the block hash we requested.
|
|
412
|
+
*/
|
|
413
|
+
rawBlockHeader(hash: string, signal?: AbortSignal): Promise<Uint8Array>;
|
|
393
414
|
}
|
|
394
415
|
/**
|
|
395
|
-
*
|
|
416
|
+
* Verifies a Bitcoin/Litecoin attestation against the corresponding block header.
|
|
396
417
|
*
|
|
397
|
-
* `digest`
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
418
|
+
* `digest` is the final tree commitment at the attestation point (32 bytes, must equal the
|
|
419
|
+
* block's merkle root). `explorer` must point to the correct chain (Blockstream for Bitcoin;
|
|
420
|
+
* a Litecoin Esplora for Litecoin). Returns the block time (epoch seconds) on success;
|
|
421
|
+
* throws `VerificationError` if the digest does not match or the attestation is not
|
|
422
|
+
* on-chain verifiable (`pending`/`unknown`). Fail-closed.
|
|
402
423
|
*/
|
|
403
424
|
declare function verifyTimestampAttestation(digest: Uint8Array, attestation: Attestation, explorer: EsploraClient, signal?: AbortSignal): Promise<number>;
|
|
404
425
|
|
|
@@ -406,21 +427,21 @@ declare function hashBuffer(data: Buffer | Uint8Array): Buffer;
|
|
|
406
427
|
declare function hashFile(path: string): Promise<Buffer>;
|
|
407
428
|
|
|
408
429
|
/**
|
|
409
|
-
* SSRF protection
|
|
430
|
+
* SSRF protection for user-configurable calendar URLs.
|
|
410
431
|
*
|
|
411
|
-
*
|
|
412
|
-
* - TOCTOU/DNS rebinding:
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
* - IPv4-mapped IPv6 (::ffff:x.x.x.x):
|
|
416
|
-
*
|
|
432
|
+
* KNOWN LIMITATIONS (documented intentionally):
|
|
433
|
+
* - TOCTOU / DNS rebinding: DNS validation happens BEFORE the connection.
|
|
434
|
+
* A server with TTL=0 can change its IP between validation and the actual fetch.
|
|
435
|
+
* Real mitigation requires network-level egress filtering.
|
|
436
|
+
* - IPv4-mapped IPv6 (::ffff:x.x.x.x): the ::ffff: prefix is blocked but the
|
|
437
|
+
* IPv4 component validation depends on the format Node.js returns.
|
|
417
438
|
*/
|
|
418
439
|
/**
|
|
419
|
-
*
|
|
420
|
-
*
|
|
440
|
+
* Validates that a calendar URL is safe for outbound HTTP requests.
|
|
441
|
+
* Blocks private/reserved IPs by default.
|
|
421
442
|
*
|
|
422
|
-
* @param allowPrivate
|
|
423
|
-
*
|
|
443
|
+
* @param allowPrivate When true, skips the IP range check.
|
|
444
|
+
* Useful for local testing or internal corporate networks.
|
|
424
445
|
*/
|
|
425
446
|
declare function assertSafeCalendarUrl(url: string, options: {
|
|
426
447
|
allowPrivate: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { Attestation, BitcoinAttestation, DetachedTimestampFile, PendingAttestat
|
|
|
4
4
|
/**
|
|
5
5
|
* Type definitions for the OpenTimestamps Client SDK
|
|
6
6
|
*/
|
|
7
|
-
/** Logger interface for observability */
|
|
7
|
+
/** Logger interface for observability. */
|
|
8
8
|
interface Logger {
|
|
9
9
|
debug(message: string, ...args: unknown[]): void;
|
|
10
10
|
info(message: string, ...args: unknown[]): void;
|
|
@@ -39,7 +39,7 @@ interface ResilienceOptions {
|
|
|
39
39
|
connectTimeoutMs: number;
|
|
40
40
|
retries: RetryOptions;
|
|
41
41
|
circuitBreaker: CircuitBreakerOptions;
|
|
42
|
-
/**
|
|
42
|
+
/** Maximum bytes allowed in the response body. Defaults to 100 KB. */
|
|
43
43
|
maxResponseBytes?: number;
|
|
44
44
|
}
|
|
45
45
|
/** Client configuration options */
|
|
@@ -55,12 +55,18 @@ interface ClientOptions {
|
|
|
55
55
|
/** Minimum successful calendar submissions required (default: 2) */
|
|
56
56
|
minimumSuccessfulSubmissions?: number;
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
58
|
+
* Base URL for the Esplora block explorer used by verify().
|
|
59
|
+
* Defaults to Blockstream (https://blockstream.info/api).
|
|
60
|
+
* Override to use a self-hosted or alternative explorer.
|
|
61
|
+
*/
|
|
62
|
+
esploraUrl?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Allows calendar URLs that resolve to private/reserved IPs.
|
|
59
65
|
*
|
|
60
|
-
* **
|
|
66
|
+
* **Do not enable in production.** Useful for local testing or corporate networks.
|
|
61
67
|
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
68
|
+
* Even when `false`, protection is best-effort against DNS rebinding (TOCTOU).
|
|
69
|
+
* For high-security environments, complement with network-level egress filtering.
|
|
64
70
|
*
|
|
65
71
|
* @default false
|
|
66
72
|
*/
|
|
@@ -99,7 +105,7 @@ interface VerificationNetworkError {
|
|
|
99
105
|
type VerificationResult = VerificationSuccess | VerificationPending | VerificationInvalid | VerificationNetworkError;
|
|
100
106
|
/** Type guard — verdadero si la verificación fue exitosa. */
|
|
101
107
|
declare const isVerified: (r: VerificationResult) => r is VerificationSuccess;
|
|
102
|
-
/** Default calendar servers */
|
|
108
|
+
/** Default calendar servers. Sourced from @otskit/core (single source of truth). */
|
|
103
109
|
declare const DEFAULT_CALENDARS: string[];
|
|
104
110
|
/** Default resilience configuration */
|
|
105
111
|
declare const DEFAULT_RESILIENCE: ResilienceOptions;
|
|
@@ -139,6 +145,7 @@ declare class OpenTimestampsClient {
|
|
|
139
145
|
private globalSignal?;
|
|
140
146
|
private minimumSuccessfulSubmissions;
|
|
141
147
|
private allowPrivateCalendars;
|
|
148
|
+
private esploraUrl;
|
|
142
149
|
/**
|
|
143
150
|
* Create a new OpenTimestamps client
|
|
144
151
|
*
|
|
@@ -265,7 +272,7 @@ declare class UpgradeError extends OpenTimestampsClientError {
|
|
|
265
272
|
}
|
|
266
273
|
/** Network-related error (timeout, all retries failed, etc.) */
|
|
267
274
|
declare class NetworkError extends OpenTimestampsClientError {
|
|
268
|
-
/** HTTP status code
|
|
275
|
+
/** HTTP status code when the failure originates from an HTTP response. */
|
|
269
276
|
readonly status?: number;
|
|
270
277
|
constructor(message: string, options?: {
|
|
271
278
|
cause?: Error;
|
|
@@ -276,16 +283,16 @@ declare class NetworkError extends OpenTimestampsClientError {
|
|
|
276
283
|
declare class CircuitBreakerError extends NetworkError {
|
|
277
284
|
constructor(calendar: string);
|
|
278
285
|
}
|
|
279
|
-
/**
|
|
286
|
+
/** The calendar does not yet know the queried commitment (HTTP 404). */
|
|
280
287
|
declare class CommitmentNotFoundError extends NetworkError {
|
|
281
288
|
}
|
|
282
|
-
/**
|
|
289
|
+
/** The calendar response exceeds the allowed size limit (DoS defense). */
|
|
283
290
|
declare class CalendarResponseTooLargeError extends NetworkError {
|
|
284
291
|
}
|
|
285
|
-
/**
|
|
292
|
+
/** Invalid Esplora response: empty, non-JSON, malformed, or too large (DoS defense). */
|
|
286
293
|
declare class EsploraResponseError extends NetworkError {
|
|
287
294
|
}
|
|
288
|
-
/**
|
|
295
|
+
/** Response exceeds the allowed byte limit (DoS defense). */
|
|
289
296
|
declare class SizeLimitExceededError extends NetworkError {
|
|
290
297
|
readonly maxBytes: number;
|
|
291
298
|
readonly actualBytes?: number;
|
|
@@ -306,8 +313,7 @@ declare enum CircuitState {
|
|
|
306
313
|
}
|
|
307
314
|
|
|
308
315
|
/**
|
|
309
|
-
*
|
|
310
|
-
* Funciona en Node.js 18+, browsers y edge runtimes.
|
|
316
|
+
* Fetch adapter for Node.js 20+.
|
|
311
317
|
*/
|
|
312
318
|
interface FetchRequest {
|
|
313
319
|
url: string;
|
|
@@ -341,64 +347,79 @@ declare class ResilientNetworkLayer {
|
|
|
341
347
|
}
|
|
342
348
|
|
|
343
349
|
/**
|
|
344
|
-
*
|
|
350
|
+
* Remote OpenTimestamps calendar client (real OTS protocol).
|
|
345
351
|
*/
|
|
346
352
|
|
|
347
|
-
/**
|
|
353
|
+
/** Maximum response size from a calendar server (DoS defense). */
|
|
348
354
|
declare const MAX_CALENDAR_RESPONSE_SIZE = 10000;
|
|
349
|
-
/**
|
|
355
|
+
/** Interface to a remote calendar server. */
|
|
350
356
|
declare class CalendarClient {
|
|
351
357
|
#private;
|
|
352
358
|
private readonly url;
|
|
353
359
|
private readonly networkLayer;
|
|
354
360
|
private readonly logger?;
|
|
355
361
|
constructor(url: string, networkLayer: ResilientNetworkLayer, logger?: Logger | undefined);
|
|
356
|
-
/**
|
|
362
|
+
/** Submits a digest to the calendar and returns the Timestamp that commits to it. */
|
|
357
363
|
submit(digest: Uint8Array, signal?: AbortSignal): Promise<Timestamp>;
|
|
358
|
-
/**
|
|
364
|
+
/** Asks the calendar for a more complete Timestamp for `commitment` (upgrade). */
|
|
359
365
|
getTimestamp(commitment: Uint8Array, signal?: AbortSignal): Promise<Timestamp>;
|
|
360
366
|
}
|
|
361
|
-
/**
|
|
367
|
+
/** Allowlist of trusted calendar URLs. */
|
|
362
368
|
declare class UrlWhitelist {
|
|
363
369
|
#private;
|
|
364
370
|
constructor(urls?: readonly string[]);
|
|
365
|
-
/**
|
|
371
|
+
/**
|
|
372
|
+
* Adds a pattern. If the URL has no scheme, both http:// and https:// variants are added.
|
|
373
|
+
* Throws TypeError if the pattern is not a valid string or is structurally invalid.
|
|
374
|
+
*/
|
|
366
375
|
add(url: string): void;
|
|
367
|
-
/**
|
|
376
|
+
/** Returns true if `url` matches any pattern in the allowlist. */
|
|
368
377
|
contains(url: string): boolean;
|
|
369
378
|
toString(): string;
|
|
370
379
|
}
|
|
371
|
-
/**
|
|
380
|
+
/**
|
|
381
|
+
* Default trusted calendars for verification/upgrade.
|
|
382
|
+
* Patterns sourced from @otskit/core (single source of truth).
|
|
383
|
+
*/
|
|
372
384
|
declare const DEFAULT_CALENDAR_WHITELIST: UrlWhitelist;
|
|
373
|
-
/**
|
|
385
|
+
/**
|
|
386
|
+
* Default aggregators to submit digests to when stamping.
|
|
387
|
+
* Sourced from @otskit/core (single source of truth).
|
|
388
|
+
*/
|
|
374
389
|
declare const DEFAULT_AGGREGATORS: readonly string[];
|
|
375
390
|
|
|
376
|
-
/**
|
|
391
|
+
/** Default public Esplora explorer (Bitcoin mainnet). */
|
|
377
392
|
declare const PUBLIC_ESPLORA_URL = "https://blockstream.info/api";
|
|
378
|
-
/**
|
|
393
|
+
/** Maximum size of an Esplora response (DoS defense). A JSON block header is a few hundred bytes. */
|
|
379
394
|
declare const MAX_ESPLORA_RESPONSE_SIZE = 100000;
|
|
380
395
|
interface EsploraClientOptions {
|
|
381
|
-
/** URL
|
|
396
|
+
/** Base URL of the explorer (defaults to Blockstream). Useful for pointing to a Litecoin Esplora. */
|
|
382
397
|
url?: string;
|
|
383
398
|
logger?: Logger;
|
|
384
399
|
}
|
|
385
|
-
/**
|
|
400
|
+
/** Client for a remote Esplora explorer. */
|
|
386
401
|
declare class EsploraClient {
|
|
387
402
|
#private;
|
|
388
403
|
constructor(networkLayer: ResilientNetworkLayer, options?: EsploraClientOptions);
|
|
389
|
-
/**
|
|
404
|
+
/** Returns the block hash (64-char hex, lowercase) at the given height. */
|
|
390
405
|
blockHash(height: number, signal?: AbortSignal): Promise<string>;
|
|
391
|
-
/**
|
|
406
|
+
/** Returns the block header (merkle root + timestamp) for the given hash. */
|
|
392
407
|
block(hash: string, signal?: AbortSignal): Promise<BlockHeader>;
|
|
408
|
+
/**
|
|
409
|
+
* Fetches the raw 80-byte block header for `hash` and self-authenticates it:
|
|
410
|
+
* sha256d(rawHeader) reversed must equal `hash`. This removes trust in the explorer's
|
|
411
|
+
* JSON layer — the raw header is cryptographically bound to the block hash we requested.
|
|
412
|
+
*/
|
|
413
|
+
rawBlockHeader(hash: string, signal?: AbortSignal): Promise<Uint8Array>;
|
|
393
414
|
}
|
|
394
415
|
/**
|
|
395
|
-
*
|
|
416
|
+
* Verifies a Bitcoin/Litecoin attestation against the corresponding block header.
|
|
396
417
|
*
|
|
397
|
-
* `digest`
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
418
|
+
* `digest` is the final tree commitment at the attestation point (32 bytes, must equal the
|
|
419
|
+
* block's merkle root). `explorer` must point to the correct chain (Blockstream for Bitcoin;
|
|
420
|
+
* a Litecoin Esplora for Litecoin). Returns the block time (epoch seconds) on success;
|
|
421
|
+
* throws `VerificationError` if the digest does not match or the attestation is not
|
|
422
|
+
* on-chain verifiable (`pending`/`unknown`). Fail-closed.
|
|
402
423
|
*/
|
|
403
424
|
declare function verifyTimestampAttestation(digest: Uint8Array, attestation: Attestation, explorer: EsploraClient, signal?: AbortSignal): Promise<number>;
|
|
404
425
|
|
|
@@ -406,21 +427,21 @@ declare function hashBuffer(data: Buffer | Uint8Array): Buffer;
|
|
|
406
427
|
declare function hashFile(path: string): Promise<Buffer>;
|
|
407
428
|
|
|
408
429
|
/**
|
|
409
|
-
* SSRF protection
|
|
430
|
+
* SSRF protection for user-configurable calendar URLs.
|
|
410
431
|
*
|
|
411
|
-
*
|
|
412
|
-
* - TOCTOU/DNS rebinding:
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
* - IPv4-mapped IPv6 (::ffff:x.x.x.x):
|
|
416
|
-
*
|
|
432
|
+
* KNOWN LIMITATIONS (documented intentionally):
|
|
433
|
+
* - TOCTOU / DNS rebinding: DNS validation happens BEFORE the connection.
|
|
434
|
+
* A server with TTL=0 can change its IP between validation and the actual fetch.
|
|
435
|
+
* Real mitigation requires network-level egress filtering.
|
|
436
|
+
* - IPv4-mapped IPv6 (::ffff:x.x.x.x): the ::ffff: prefix is blocked but the
|
|
437
|
+
* IPv4 component validation depends on the format Node.js returns.
|
|
417
438
|
*/
|
|
418
439
|
/**
|
|
419
|
-
*
|
|
420
|
-
*
|
|
440
|
+
* Validates that a calendar URL is safe for outbound HTTP requests.
|
|
441
|
+
* Blocks private/reserved IPs by default.
|
|
421
442
|
*
|
|
422
|
-
* @param allowPrivate
|
|
423
|
-
*
|
|
443
|
+
* @param allowPrivate When true, skips the IP range check.
|
|
444
|
+
* Useful for local testing or internal corporate networks.
|
|
424
445
|
*/
|
|
425
446
|
declare function assertSafeCalendarUrl(url: string, options: {
|
|
426
447
|
allowPrivate: boolean;
|