@orangecheck/stamp-ots 0.6.0 → 0.7.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 +2 -2
- package/dist/index.d.mts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +30 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +30 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/anchor.test.ts +34 -0
- package/src/anchor.ts +17 -8
- package/src/index.ts +1 -1
- package/src/stamp-core-verify.test.ts +15 -1
- package/src/upgrade.test.ts +48 -1
- package/src/upgrade.ts +28 -2
package/README.md
CHANGED
|
@@ -17,12 +17,12 @@ npm i @orangecheck/stamp-core @orangecheck/stamp-ots
|
|
|
17
17
|
OC Stamp envelopes carry an optional `ots` field that anchors the envelope `id` to a Bitcoin block via the [OpenTimestamps](https://opentimestamps.org) protocol. This package provides the thin client-side glue:
|
|
18
18
|
|
|
19
19
|
- **`submitToCalendars(id, opts)`** — POST the envelope's 32-byte digest to OTS calendars (`DEFAULT_CALENDARS` unless you pass `calendars`). Two must answer by default (SPEC §6.1); set `minSuccesses` to change that. Returns a pending `OtsProof` you can fold into the envelope's `ots` field.
|
|
20
|
-
- **`upgradeProof(proof, id, { headerSource })`** — ask each calendar for the continuation of its pending attestation (calendars index upgrades by that commitment) and graft it on. `headerSource` is required: the result is `confirmed` only once the proof reaches a Bitcoin block whose header has the proof's Merkle root, and stays `pending` until then.
|
|
20
|
+
- **`upgradeProof(proof, id, { headerSource })`** — ask each calendar for the continuation of its pending attestation (calendars index upgrades by that commitment) and graft it on. `headerSource` is required: the result is `confirmed` only once the proof reaches a Bitcoin block whose header has the proof's Merkle root, and stays `pending` until then. When no calendar answers at all (each failed or timed out), it throws `CalendarsUnreadError` instead: nothing was learned, and the proof may already be anchored.
|
|
21
21
|
- **`createCalendarClient(url)`** — low-level HTTP client implementing the minimal OTS calendar API (`POST /digest` with no Content-Type, so a browser sends no preflight; `GET /timestamp/<hex(commitment)>`).
|
|
22
22
|
- **`DEFAULT_CALENDARS`** — `alice.btc.calendar.opentimestamps.org`, `bob.btc.calendar.opentimestamps.org` and `finney.calendar.eternitywall.com`, the set SPEC §6.1 names.
|
|
23
23
|
- **`verifiedAnchor(proof, id, headerSource)`** — the lowest block the proof anchors `id` in, each Bitcoin attestation checked against the header at its height; ignores whatever height or status the stamp declares. `null` when none checks out; throws when headers cannot be read, so a failed lookup is never read as "no anchor".
|
|
24
24
|
- **`makeAnchorVerifier({ headerSource })`** — the `verifyOtsAnchor` hook for `verify()` from `@orangecheck/stamp-core`. It walks the proof with the built-in OTS parser and requires that the proof commits to the envelope id, attests at the declared height, and that the header at that height has the proof's Merkle root and hashes to the declared block hash.
|
|
25
|
-
- **`mempoolHeaderSource(opts)`** — block headers from an Esplora-compatible API (default `https://mempool.space/api`). Each header is checked against the declared block hash, so this source is trusted only to say which block sits at a height. Supply your own node or headers snapshot to remove that trust.
|
|
25
|
+
- **`mempoolHeaderSource(opts)`** — block headers from an Esplora-compatible API (default `https://mempool.space/api`). Each header is checked against the declared block hash, so this source is trusted only to say which block sits at a height. Supply your own node or headers snapshot to remove that trust. Each request times out after `timeoutMs` (default 15000) and then throws, as a header that could not be read.
|
|
26
26
|
- **`parseProof` / `parseDetached` / `serializeTimestamp` / `bitcoinAnchors` / `pendingCommitments`** — the OTS proof format, accepting both the bare timestamp carried in `ots.proof` and detached `.ots` files.
|
|
27
27
|
|
|
28
28
|
## Verify an anchor
|
package/dist/index.d.mts
CHANGED
|
@@ -62,6 +62,16 @@ interface UpgradeOptions {
|
|
|
62
62
|
timeoutMs?: number;
|
|
63
63
|
signal?: AbortSignal;
|
|
64
64
|
}
|
|
65
|
+
declare class CalendarsUnreadError extends Error {
|
|
66
|
+
readonly failures: {
|
|
67
|
+
calendar: string;
|
|
68
|
+
reason: string;
|
|
69
|
+
}[];
|
|
70
|
+
constructor(failures: {
|
|
71
|
+
calendar: string;
|
|
72
|
+
reason: string;
|
|
73
|
+
}[]);
|
|
74
|
+
}
|
|
65
75
|
declare function upgradeProof(current: OtsProof, idHex: string, opts: UpgradeOptions): Promise<OtsProof>;
|
|
66
76
|
declare function verifiedAnchor(proofB64: string, idHex: string, headerSource: BlockHeaderSource): Promise<{
|
|
67
77
|
blockHeight: number;
|
|
@@ -95,6 +105,7 @@ declare function makeDefaultAnchorVerifier(opts: {
|
|
|
95
105
|
interface MempoolHeaderSourceOptions {
|
|
96
106
|
baseUrl?: string;
|
|
97
107
|
fetch?: typeof fetch;
|
|
108
|
+
timeoutMs?: number;
|
|
98
109
|
}
|
|
99
110
|
declare function mempoolHeaderSource(opts?: MempoolHeaderSourceOptions): BlockHeaderSource;
|
|
100
111
|
|
|
@@ -144,4 +155,4 @@ declare function pendingCommitments(ts: OtsTimestamp): {
|
|
|
144
155
|
declare function mergeAt(ts: OtsTimestamp, upgrade: OtsTimestamp): boolean;
|
|
145
156
|
declare function serializeTimestamp(ts: OtsTimestamp): Uint8Array;
|
|
146
157
|
|
|
147
|
-
export { type AnchorVerificationInput, type AnchorVerificationResult, type AnchorVerifier, type AnchorVerifierConfig, type BlockHeaderSource, type CalendarClient, DEFAULT_CALENDARS, type HttpCalendarOptions, type MempoolHeaderSourceOptions, type OtsAttestation, type OtsOp, type OtsProof, type OtsProofStatus, type OtsTimestamp, type SubmitOptions, type UpgradeOptions, attestations, base64Decode, base64Encode, bitcoinAnchors, blockHashOf, createCalendarClient, fromStampOts, hexDecode, hexEncode, makeAnchorVerifier, makeDefaultAnchorVerifier, mempoolHeaderSource, mergeAt, parseDetached, parseProof, parseTimestamp, pendingCommitments, serializeTimestamp, submitToCalendars, toStampOts, upgradeProof, verifiedAnchor, walkOtsProof };
|
|
158
|
+
export { type AnchorVerificationInput, type AnchorVerificationResult, type AnchorVerifier, type AnchorVerifierConfig, type BlockHeaderSource, type CalendarClient, CalendarsUnreadError, DEFAULT_CALENDARS, type HttpCalendarOptions, type MempoolHeaderSourceOptions, type OtsAttestation, type OtsOp, type OtsProof, type OtsProofStatus, type OtsTimestamp, type SubmitOptions, type UpgradeOptions, attestations, base64Decode, base64Encode, bitcoinAnchors, blockHashOf, createCalendarClient, fromStampOts, hexDecode, hexEncode, makeAnchorVerifier, makeDefaultAnchorVerifier, mempoolHeaderSource, mergeAt, parseDetached, parseProof, parseTimestamp, pendingCommitments, serializeTimestamp, submitToCalendars, toStampOts, upgradeProof, verifiedAnchor, walkOtsProof };
|
package/dist/index.d.ts
CHANGED
|
@@ -62,6 +62,16 @@ interface UpgradeOptions {
|
|
|
62
62
|
timeoutMs?: number;
|
|
63
63
|
signal?: AbortSignal;
|
|
64
64
|
}
|
|
65
|
+
declare class CalendarsUnreadError extends Error {
|
|
66
|
+
readonly failures: {
|
|
67
|
+
calendar: string;
|
|
68
|
+
reason: string;
|
|
69
|
+
}[];
|
|
70
|
+
constructor(failures: {
|
|
71
|
+
calendar: string;
|
|
72
|
+
reason: string;
|
|
73
|
+
}[]);
|
|
74
|
+
}
|
|
65
75
|
declare function upgradeProof(current: OtsProof, idHex: string, opts: UpgradeOptions): Promise<OtsProof>;
|
|
66
76
|
declare function verifiedAnchor(proofB64: string, idHex: string, headerSource: BlockHeaderSource): Promise<{
|
|
67
77
|
blockHeight: number;
|
|
@@ -95,6 +105,7 @@ declare function makeDefaultAnchorVerifier(opts: {
|
|
|
95
105
|
interface MempoolHeaderSourceOptions {
|
|
96
106
|
baseUrl?: string;
|
|
97
107
|
fetch?: typeof fetch;
|
|
108
|
+
timeoutMs?: number;
|
|
98
109
|
}
|
|
99
110
|
declare function mempoolHeaderSource(opts?: MempoolHeaderSourceOptions): BlockHeaderSource;
|
|
100
111
|
|
|
@@ -144,4 +155,4 @@ declare function pendingCommitments(ts: OtsTimestamp): {
|
|
|
144
155
|
declare function mergeAt(ts: OtsTimestamp, upgrade: OtsTimestamp): boolean;
|
|
145
156
|
declare function serializeTimestamp(ts: OtsTimestamp): Uint8Array;
|
|
146
157
|
|
|
147
|
-
export { type AnchorVerificationInput, type AnchorVerificationResult, type AnchorVerifier, type AnchorVerifierConfig, type BlockHeaderSource, type CalendarClient, DEFAULT_CALENDARS, type HttpCalendarOptions, type MempoolHeaderSourceOptions, type OtsAttestation, type OtsOp, type OtsProof, type OtsProofStatus, type OtsTimestamp, type SubmitOptions, type UpgradeOptions, attestations, base64Decode, base64Encode, bitcoinAnchors, blockHashOf, createCalendarClient, fromStampOts, hexDecode, hexEncode, makeAnchorVerifier, makeDefaultAnchorVerifier, mempoolHeaderSource, mergeAt, parseDetached, parseProof, parseTimestamp, pendingCommitments, serializeTimestamp, submitToCalendars, toStampOts, upgradeProof, verifiedAnchor, walkOtsProof };
|
|
158
|
+
export { type AnchorVerificationInput, type AnchorVerificationResult, type AnchorVerifier, type AnchorVerifierConfig, type BlockHeaderSource, type CalendarClient, CalendarsUnreadError, DEFAULT_CALENDARS, type HttpCalendarOptions, type MempoolHeaderSourceOptions, type OtsAttestation, type OtsOp, type OtsProof, type OtsProofStatus, type OtsTimestamp, type SubmitOptions, type UpgradeOptions, attestations, base64Decode, base64Encode, bitcoinAnchors, blockHashOf, createCalendarClient, fromStampOts, hexDecode, hexEncode, makeAnchorVerifier, makeDefaultAnchorVerifier, mempoolHeaderSource, mergeAt, parseDetached, parseProof, parseTimestamp, pendingCommitments, serializeTimestamp, submitToCalendars, toStampOts, upgradeProof, verifiedAnchor, walkOtsProof };
|
package/dist/index.js
CHANGED
|
@@ -539,12 +539,15 @@ function makeAnchorVerifier(cfg) {
|
|
|
539
539
|
return { ok: true, merkleRoot: hexEncode(headerMerkle) };
|
|
540
540
|
};
|
|
541
541
|
return async (proofB64, blockHeight, blockHash, envelopeId) => {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
}
|
|
542
|
+
let proofBytes;
|
|
543
|
+
let digest;
|
|
544
|
+
try {
|
|
545
|
+
proofBytes = base64Decode(proofB64);
|
|
546
|
+
digest = hexDecode(envelopeId);
|
|
547
|
+
} catch {
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
const r = await verifier({ proofBytes, digest, blockHeight, blockHash });
|
|
548
551
|
return r.ok;
|
|
549
552
|
};
|
|
550
553
|
}
|
|
@@ -554,8 +557,9 @@ async function makeDefaultAnchorVerifier(opts) {
|
|
|
554
557
|
function mempoolHeaderSource(opts = {}) {
|
|
555
558
|
const base = (opts.baseUrl ?? "https://mempool.space/api").replace(/\/+$/, "");
|
|
556
559
|
const fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
560
|
+
const timeoutMs = opts.timeoutMs ?? 15e3;
|
|
557
561
|
const read = async (url, shape) => {
|
|
558
|
-
const r = await fetchImpl(url);
|
|
562
|
+
const r = await fetchImpl(url, { signal: AbortSignal.timeout(timeoutMs) });
|
|
559
563
|
if (r.status === 404) return null;
|
|
560
564
|
if (!r.ok) throw new Error(`header lookup failed: HTTP ${r.status} from ${url}`);
|
|
561
565
|
const text = (await r.text()).trim();
|
|
@@ -574,6 +578,15 @@ function mempoolHeaderSource(opts = {}) {
|
|
|
574
578
|
|
|
575
579
|
// src/upgrade.ts
|
|
576
580
|
var norm = (u) => u.replace(/\/+$/, "");
|
|
581
|
+
var CalendarsUnreadError = class extends Error {
|
|
582
|
+
constructor(failures) {
|
|
583
|
+
super(
|
|
584
|
+
`OTS: no calendar answered (${failures.map((f) => `${f.calendar}: ${f.reason}`).join("; ")})`
|
|
585
|
+
);
|
|
586
|
+
this.failures = failures;
|
|
587
|
+
this.name = "CalendarsUnreadError";
|
|
588
|
+
}
|
|
589
|
+
};
|
|
577
590
|
async function upgradeProof(current, idHex, opts) {
|
|
578
591
|
if (current.status === "confirmed") return current;
|
|
579
592
|
if (!opts?.headerSource) {
|
|
@@ -587,7 +600,7 @@ async function upgradeProof(current, idHex, opts) {
|
|
|
587
600
|
throw new Error("upgradeProof: proof has no pending attestation from a listed calendar");
|
|
588
601
|
}
|
|
589
602
|
const answered = [];
|
|
590
|
-
await Promise.allSettled(
|
|
603
|
+
const settled = await Promise.allSettled(
|
|
591
604
|
pending.map(async ({ uri, commitment }) => {
|
|
592
605
|
const client = createCalendarClient(uri, { fetch: opts.fetch, timeoutMs: opts.timeoutMs });
|
|
593
606
|
const bytes = await client.fetchProof(commitment, opts.signal);
|
|
@@ -597,6 +610,14 @@ async function upgradeProof(current, idHex, opts) {
|
|
|
597
610
|
);
|
|
598
611
|
const merged = serializeTimestamp(tree);
|
|
599
612
|
const anchor = await resolveAnchor(tree, opts.headerSource);
|
|
613
|
+
if (!anchor && pending.length > 0 && settled.every((r) => r.status === "rejected")) {
|
|
614
|
+
throw new CalendarsUnreadError(
|
|
615
|
+
pending.map(({ uri }, i) => ({
|
|
616
|
+
calendar: norm(uri),
|
|
617
|
+
reason: String(settled[i].reason?.message ?? settled[i])
|
|
618
|
+
}))
|
|
619
|
+
);
|
|
620
|
+
}
|
|
600
621
|
const calendars = [...answered, ...current.calendars.filter((c) => !answered.includes(norm(c)))];
|
|
601
622
|
if (anchor) {
|
|
602
623
|
return {
|
|
@@ -632,6 +653,7 @@ async function resolveAnchor(tree, headers) {
|
|
|
632
653
|
return null;
|
|
633
654
|
}
|
|
634
655
|
|
|
656
|
+
exports.CalendarsUnreadError = CalendarsUnreadError;
|
|
635
657
|
exports.DEFAULT_CALENDARS = DEFAULT_CALENDARS;
|
|
636
658
|
exports.attestations = attestations;
|
|
637
659
|
exports.base64Decode = base64Decode;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/base64.ts","../src/calendar.ts","../src/ots.ts","../src/submit.ts","../src/anchor.ts","../src/upgrade.ts"],"names":["sha256","ripemd160","sha1","keccak_256","tag"],"mappings":"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","file":"index.js","sourcesContent":["// Types for @orangecheck/stamp-ots.\n\nimport type { StampOts } from '@orangecheck/stamp-core';\n\nexport type OtsProofStatus = 'pending' | 'confirmed';\n\nexport interface OtsProof {\n status: OtsProofStatus;\n /** OTS timestamp rooted at the envelope id (or a detached .ots file), base64. */\n proof: string;\n /** Calendar URLs that contain this proof, in submission order. */\n calendars: string[];\n /** Bitcoin block height at which this proof is anchored (null if pending). */\n blockHeight: number | null;\n /** Bitcoin block hash (hex, lowercase) at the anchor block (null if pending). */\n blockHash: string | null;\n /** ISO 8601 UTC of the upgrade (null if pending). */\n upgradedAt: string | null;\n}\n\nexport interface CalendarClient {\n /** Base URL of the calendar, e.g. \"https://alice.btc.calendar.opentimestamps.org\". */\n readonly url: string;\n\n /**\n * Submit a 32-byte digest to the calendar for aggregation. Returns the raw\n * pending proof bytes.\n *\n * OTS calendar HTTP API: POST <url>/digest with the raw bytes as the body\n * and no Content-Type header, returns the proof bytes as the response body.\n * A Content-Type outside the CORS-safelisted ones makes a browser send a\n * preflight, which the public calendars refuse; createCalendarClient sends\n * none.\n */\n submit(digest: Uint8Array, signal?: AbortSignal): Promise<Uint8Array>;\n\n /**\n * Fetch the continuation of a pending proof. `commitment` is the message\n * at the calendar's pending attestation (see `pendingCommitments`), not\n * the submitted digest. Returns null if the calendar has nothing yet.\n *\n * OTS calendar HTTP API: GET <url>/timestamp/<hex(commitment)>, returns a\n * timestamp rooted at the commitment, or 404.\n */\n fetchProof(commitment: Uint8Array, signal?: AbortSignal): Promise<Uint8Array | null>;\n}\n\nexport interface AnchorVerificationInput {\n /** Raw OTS proof bytes (base64-decoded by the caller). */\n proofBytes: Uint8Array;\n /** 32-byte digest that the proof commits to. */\n digest: Uint8Array;\n /** Declared block height from the envelope. */\n blockHeight: number;\n /** Declared block hash (hex) from the envelope. */\n blockHash: string;\n /**\n * Optional block header source. If provided, the verifier uses this to\n * fetch the header at `blockHeight` and compare its Merkle root to the\n * one derived from walking the proof.\n *\n * If omitted, the verifier MAY still parse the proof and report\n * structural validity but CANNOT report a bound anchor.\n */\n headerSource?: BlockHeaderSource;\n}\n\nexport interface BlockHeaderSource {\n /**\n * The 80-byte raw block header at the given height, or null when there is\n * no block at that height. Throw when the header could not be read: a\n * failed lookup must never read as a missing block.\n */\n getHeaderAt(height: number): Promise<Uint8Array | null>;\n}\n\nexport type AnchorVerifier = (input: AnchorVerificationInput) => Promise<AnchorVerificationResult>;\n\nexport type AnchorVerificationResult =\n | { ok: true; merkleRoot: string }\n | { ok: false; reason: string };\n\n/**\n * Convert an OtsProof (library type) to the StampOts field shape that the\n * envelope carries. The two are isomorphic; this function exists to keep\n * stamp-core's type surface narrow.\n */\nexport function toStampOts(p: OtsProof): StampOts {\n return {\n status: p.status,\n proof: p.proof,\n calendars: p.calendars,\n block_height: p.blockHeight,\n block_hash: p.blockHash,\n upgraded_at: p.upgradedAt,\n };\n}\n\nexport function fromStampOts(s: StampOts): OtsProof {\n return {\n status: s.status,\n proof: s.proof,\n calendars: s.calendars,\n blockHeight: s.block_height,\n blockHash: s.block_hash,\n upgradedAt: s.upgraded_at,\n };\n}\n","// Minimal, dependency-free base64 <-> Uint8Array helpers. OTS proof bytes\n// are carried as base64 inside OC Stamp envelopes so they survive any text\n// transport (URL fragment, JSON, Nostr event content).\n\nconst B64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\nconst B64_DECODE_TABLE = (() => {\n const t = new Int16Array(128).fill(-1);\n for (let i = 0; i < B64_CHARS.length; i++) t[B64_CHARS.charCodeAt(i)] = i;\n t['='.charCodeAt(0)] = -2;\n return t;\n})();\n\nexport function base64Encode(bytes: Uint8Array): string {\n let out = '';\n let i = 0;\n for (; i + 2 < bytes.length; i += 3) {\n const a = bytes[i]!;\n const b = bytes[i + 1]!;\n const c = bytes[i + 2]!;\n out +=\n B64_CHARS[a >> 2]! +\n B64_CHARS[((a & 0x03) << 4) | (b >> 4)]! +\n B64_CHARS[((b & 0x0f) << 2) | (c >> 6)]! +\n B64_CHARS[c & 0x3f]!;\n }\n if (i < bytes.length) {\n const a = bytes[i]!;\n const b = i + 1 < bytes.length ? bytes[i + 1]! : 0;\n out += B64_CHARS[a >> 2]!;\n out += B64_CHARS[((a & 0x03) << 4) | (b >> 4)]!;\n out += i + 1 < bytes.length ? B64_CHARS[(b & 0x0f) << 2]! : '=';\n out += '=';\n }\n return out;\n}\n\nexport function base64Decode(s: string): Uint8Array {\n const str = s.replace(/\\s+/g, '');\n const len = str.length;\n if (len === 0) return new Uint8Array(0);\n if (len % 4 !== 0) throw new Error('base64: bad length');\n let padding = 0;\n if (str[len - 1] === '=') padding++;\n if (str[len - 2] === '=') padding++;\n const outLen = (len / 4) * 3 - padding;\n const out = new Uint8Array(outLen);\n let o = 0;\n for (let i = 0; i < len; i += 4) {\n const c0 = B64_DECODE_TABLE[str.charCodeAt(i)]!;\n const c1 = B64_DECODE_TABLE[str.charCodeAt(i + 1)]!;\n const c2 = B64_DECODE_TABLE[str.charCodeAt(i + 2)]!;\n const c3 = B64_DECODE_TABLE[str.charCodeAt(i + 3)]!;\n if (c0 < 0 || c1 < 0 || c2 < -2 || c3 < -2) throw new Error('base64: bad char');\n out[o++] = (c0 << 2) | (c1 >> 4);\n if (c2 >= 0) out[o++] = ((c1 & 0x0f) << 4) | (c2 >> 2);\n if (c3 >= 0) out[o++] = ((c2 & 0x03) << 6) | c3;\n }\n return out;\n}\n\nexport function hexDecode(s: string): Uint8Array {\n if (s.length % 2 !== 0) throw new Error('hex: odd length');\n const out = new Uint8Array(s.length / 2);\n for (let i = 0; i < out.length; i++) {\n const hi = parseInt(s[i * 2]!, 16);\n const lo = parseInt(s[i * 2 + 1]!, 16);\n if (Number.isNaN(hi) || Number.isNaN(lo)) throw new Error('hex: bad char');\n out[i] = (hi << 4) | lo;\n }\n return out;\n}\n\nexport function hexEncode(bytes: Uint8Array): string {\n const HEX = '0123456789abcdef';\n let out = '';\n for (let i = 0; i < bytes.length; i++) {\n const b = bytes[i]!;\n out += HEX[(b >> 4) & 0x0f]! + HEX[b & 0x0f]!;\n }\n return out;\n}\n","// HTTP client for an OpenTimestamps calendar. Implements the minimal subset\n// of the calendar protocol that an OC Stamp implementation needs:\n//\n// POST <url>/digest body = raw digest bytes -> pending proof bytes\n// GET <url>/timestamp/<hex(commitment)> -> continuation, or 404\n//\n// The client moves bytes only; ./ots.ts parses them.\n\nimport type { CalendarClient } from './types.js';\nimport { hexEncode } from './base64.js';\n\nexport const DEFAULT_CALENDARS: readonly string[] = [\n 'https://alice.btc.calendar.opentimestamps.org',\n 'https://bob.btc.calendar.opentimestamps.org',\n 'https://finney.calendar.eternitywall.com',\n];\n\nexport interface HttpCalendarOptions {\n /**\n * Custom fetch implementation. Defaults to global `fetch`. Useful in\n * environments that need a specific adapter (Node < 18, Cloudflare\n * Workers, proxies).\n */\n fetch?: typeof fetch;\n /** Request timeout in milliseconds. Default 30_000. */\n timeoutMs?: number;\n}\n\nexport function createCalendarClient(url: string, opts: HttpCalendarOptions = {}): CalendarClient {\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (typeof fetchImpl !== 'function') {\n throw new Error(\n '@orangecheck/stamp-ots: no fetch implementation available. Pass one via { fetch }.'\n );\n }\n const timeoutMs = opts.timeoutMs ?? 30_000;\n const base = url.replace(/\\/$/, '');\n\n return {\n url: base,\n async submit(digest, signal) {\n if (digest.byteLength !== 32) {\n throw new Error('OTS: digest must be exactly 32 bytes');\n }\n const ac = withTimeout(signal, timeoutMs);\n // Uint8Array is a valid fetch body at runtime in Node 18+ and all\n // modern browsers, but TypeScript's DOM typings don't accept it\n // directly under `strict` + `noUncheckedIndexedAccess`. The cast is\n // narrow and intentional.\n // No Content-Type: a non-safelisted type makes browsers send a\n // CORS preflight, and OTS calendars answer OPTIONS with 501.\n const resp = await fetchImpl(`${base}/digest`, {\n method: 'POST',\n body: digest as unknown as BodyInit,\n signal: ac.signal,\n });\n ac.clear();\n if (!resp.ok) {\n throw new Error(`OTS calendar ${base} submit failed: HTTP ${resp.status}`);\n }\n const buf = await resp.arrayBuffer();\n return new Uint8Array(buf);\n },\n async fetchProof(commitment, signal) {\n if (commitment.byteLength === 0 || commitment.byteLength > 64) {\n throw new Error('OTS: commitment must be 1-64 bytes');\n }\n const ac = withTimeout(signal, timeoutMs);\n const resp = await fetchImpl(`${base}/timestamp/${hexEncode(commitment)}`, {\n method: 'GET',\n headers: { Accept: 'application/vnd.opentimestamps.v1' },\n signal: ac.signal,\n });\n ac.clear();\n if (resp.status === 404) return null;\n if (!resp.ok) {\n throw new Error(`OTS calendar ${base} fetchProof failed: HTTP ${resp.status}`);\n }\n const buf = await resp.arrayBuffer();\n return new Uint8Array(buf);\n },\n };\n}\n\nfunction withTimeout(parent: AbortSignal | undefined, ms: number): { signal: AbortSignal; clear: () => void } {\n const ac = new AbortController();\n const onParent = () => ac.abort((parent as AbortSignal & { reason?: unknown }).reason);\n if (parent) {\n if (parent.aborted) ac.abort((parent as AbortSignal & { reason?: unknown }).reason);\n else parent.addEventListener('abort', onParent, { once: true });\n }\n const t = setTimeout(() => ac.abort(new Error(`OTS request timed out after ${ms}ms`)), ms);\n return {\n signal: ac.signal,\n clear: () => {\n clearTimeout(t);\n if (parent) parent.removeEventListener('abort', onParent);\n },\n };\n}\n","// OpenTimestamps proof format: parse, walk, serialize, merge.\n//\n// Follows python-opentimestamps (core/timestamp.py, core/op.py,\n// core/notary.py). Two encodings are accepted:\n//\n// - a bare timestamp rooted at the digest (what an OTS calendar returns from\n// POST /digest, and what OC Stamp envelopes carry in `ots.proof`);\n// - a detached `.ots` file (magic header + file-hash op + digest + timestamp).\n\nimport { ripemd160, sha1 } from '@noble/hashes/legacy';\nimport { sha256 } from '@noble/hashes/sha2';\nimport { keccak_256 } from '@noble/hashes/sha3';\n\nimport { hexEncode } from './base64.js';\n\nconst HEADER_MAGIC = new Uint8Array([\n 0x00, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x00,\n 0x00, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0xbf, 0x89, 0xe2, 0xe8, 0x84, 0xe8, 0x92, 0x94,\n]);\n\nconst TAG_BITCOIN = '0588960d73d71901';\nconst TAG_PENDING = '83dfe30d2ef90c8e';\n\nconst MAX_DEPTH = 256;\nconst MAX_MSG = 4096;\n\nexport type OtsOp =\n | { kind: 'sha256' | 'ripemd160' | 'sha1' | 'keccak256' | 'reverse' | 'hexlify' }\n | { kind: 'append' | 'prepend'; arg: Uint8Array };\n\nexport type OtsAttestation =\n | { kind: 'bitcoin'; height: number }\n | { kind: 'pending'; uri: string }\n | { kind: 'unknown'; tag: string; payload: Uint8Array };\n\nexport interface OtsTimestamp {\n /** The message at this node: the digest after every op on the path to it. */\n msg: Uint8Array;\n attestations: OtsAttestation[];\n ops: { op: OtsOp; child: OtsTimestamp }[];\n}\n\nclass Reader {\n private pos = 0;\n constructor(private readonly buf: Uint8Array) {}\n byte(): number {\n if (this.pos >= this.buf.length) throw new Error('ots: unexpected end of proof');\n return this.buf[this.pos++]!;\n }\n bytes(n: number): Uint8Array {\n if (n < 0 || this.pos + n > this.buf.length) throw new Error('ots: unexpected end of proof');\n const out = this.buf.subarray(this.pos, this.pos + n);\n this.pos += n;\n return out;\n }\n varuint(): number {\n let value = 0;\n let shift = 0;\n for (;;) {\n const b = this.byte();\n value += (b & 0x7f) * 2 ** shift;\n if (!(b & 0x80)) return value;\n shift += 7;\n if (shift > 49) throw new Error('ots: varuint too large');\n }\n }\n varbytes(max: number): Uint8Array {\n const n = this.varuint();\n if (n > max) throw new Error('ots: varbytes too long');\n return this.bytes(n);\n }\n get done(): boolean {\n return this.pos === this.buf.length;\n }\n}\n\nconst UNARY: Record<number, OtsOp['kind']> = {\n 0x02: 'sha1',\n 0x03: 'ripemd160',\n 0x08: 'sha256',\n 0x67: 'keccak256',\n 0xf2: 'reverse',\n 0xf3: 'hexlify',\n};\n\nexport function applyOp(op: OtsOp, msg: Uint8Array): Uint8Array {\n switch (op.kind) {\n case 'sha256':\n return sha256(msg);\n case 'ripemd160':\n return ripemd160(msg);\n case 'sha1':\n return sha1(msg);\n case 'keccak256':\n return keccak_256(msg);\n case 'reverse':\n return new Uint8Array(msg).reverse();\n case 'hexlify':\n return new TextEncoder().encode(hexEncode(msg));\n case 'append':\n return concat(msg, op.arg);\n case 'prepend':\n return concat(op.arg, msg);\n }\n}\n\nfunction readOp(r: Reader, tag: number): OtsOp {\n const unary = UNARY[tag];\n if (unary) return { kind: unary } as OtsOp;\n if (tag === 0xf0) return { kind: 'append', arg: r.varbytes(MAX_MSG) };\n if (tag === 0xf1) return { kind: 'prepend', arg: r.varbytes(MAX_MSG) };\n throw new Error(`ots: unknown op tag 0x${tag.toString(16)}`);\n}\n\nfunction readAttestation(r: Reader): OtsAttestation {\n const tag = hexEncode(r.bytes(8));\n const payload = r.varbytes(8192);\n const p = new Reader(payload);\n if (tag === TAG_BITCOIN) return { kind: 'bitcoin', height: p.varuint() };\n if (tag === TAG_PENDING) return { kind: 'pending', uri: new TextDecoder().decode(p.varbytes(1000)) };\n return { kind: 'unknown', tag, payload };\n}\n\nfunction readTimestamp(r: Reader, msg: Uint8Array, depth: number): OtsTimestamp {\n if (depth > MAX_DEPTH) throw new Error('ots: proof too deep');\n const node: OtsTimestamp = { msg, attestations: [], ops: [] };\n const item = (tag: number) => {\n if (tag === 0x00) {\n node.attestations.push(readAttestation(r));\n return;\n }\n const op = readOp(r, tag);\n const next = applyOp(op, msg);\n if (next.length > MAX_MSG) throw new Error('ots: message too long');\n node.ops.push({ op, child: readTimestamp(r, next, depth + 1) });\n };\n let tag = r.byte();\n while (tag === 0xff) {\n item(r.byte());\n tag = r.byte();\n }\n item(tag);\n return node;\n}\n\n/** Parse a bare timestamp whose root message is `digest`. */\nexport function parseTimestamp(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp {\n const r = new Reader(bytes);\n const ts = readTimestamp(r, digest, 0);\n if (!r.done) throw new Error('ots: trailing bytes after timestamp');\n return ts;\n}\n\nexport function isDetached(bytes: Uint8Array): boolean {\n return bytes.length > HEADER_MAGIC.length && bytesEqual(bytes.subarray(0, HEADER_MAGIC.length), HEADER_MAGIC);\n}\n\n/** Parse a detached `.ots` file. Only sha256 file digests are accepted. */\nexport function parseDetached(bytes: Uint8Array): { digest: Uint8Array; timestamp: OtsTimestamp } {\n if (!isDetached(bytes)) throw new Error('ots: missing detached-file header');\n const r = new Reader(bytes.subarray(HEADER_MAGIC.length));\n const major = r.varuint();\n if (major !== 1) throw new Error(`ots: unsupported file version ${major}`);\n if (r.byte() !== 0x08) throw new Error('ots: only sha256 file digests are supported');\n const digest = new Uint8Array(r.bytes(32));\n const timestamp = readTimestamp(r, digest, 0);\n if (!r.done) throw new Error('ots: trailing bytes after timestamp');\n return { digest, timestamp };\n}\n\n/**\n * Parse either encoding and require that it commits to `digest`. A detached\n * file for some other digest is rejected rather than walked.\n */\nexport function parseProof(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp {\n if (!isDetached(bytes)) return parseTimestamp(bytes, digest);\n const d = parseDetached(bytes);\n if (!bytesEqual(d.digest, digest)) throw new Error('ots: proof commits to a different digest');\n return d.timestamp;\n}\n\n/** Every attestation in the tree with the message it attests to. */\nexport function attestations(ts: OtsTimestamp): { msg: Uint8Array; attestation: OtsAttestation }[] {\n const out: { msg: Uint8Array; attestation: OtsAttestation }[] = [];\n const walk = (n: OtsTimestamp) => {\n for (const a of n.attestations) out.push({ msg: n.msg, attestation: a });\n for (const { child } of n.ops) walk(child);\n };\n walk(ts);\n return out;\n}\n\n/**\n * Bitcoin attestations, lowest height first. `merkleRoot` is the message at\n * the attestation, which equals the block header's Merkle root in header\n * byte order.\n */\nexport function bitcoinAnchors(ts: OtsTimestamp): { blockHeight: number; merkleRoot: Uint8Array }[] {\n return attestations(ts)\n .flatMap(({ msg, attestation }) =>\n attestation.kind === 'bitcoin' ? [{ blockHeight: attestation.height, merkleRoot: msg }] : []\n )\n .sort((a, b) => a.blockHeight - b.blockHeight);\n}\n\n/** Pending calendar attestations: where to ask, and the commitment to ask for. */\nexport function pendingCommitments(ts: OtsTimestamp): { uri: string; commitment: Uint8Array }[] {\n return attestations(ts).flatMap(({ msg, attestation }) =>\n attestation.kind === 'pending' ? [{ uri: attestation.uri, commitment: msg }] : []\n );\n}\n\n/**\n * Graft `upgrade` (a timestamp rooted at some node's message) onto the node\n * with that message, as python-opentimestamps' Timestamp.merge does. Returns\n * false when no node carries that message.\n */\nexport function mergeAt(ts: OtsTimestamp, upgrade: OtsTimestamp): boolean {\n if (bytesEqual(ts.msg, upgrade.msg)) {\n for (const a of upgrade.attestations) {\n if (!ts.attestations.some((b) => attestationKey(b) === attestationKey(a))) ts.attestations.push(a);\n }\n for (const { op, child } of upgrade.ops) {\n const same = ts.ops.find((o) => opKey(o.op) === opKey(op));\n if (same) mergeAt(same.child, child);\n else ts.ops.push({ op, child });\n }\n return true;\n }\n return ts.ops.some(({ child }) => mergeAt(child, upgrade));\n}\n\nfunction writeVaruint(out: number[], n: number) {\n do {\n let b = n % 128;\n n = Math.floor(n / 128);\n if (n > 0) b |= 0x80;\n out.push(b);\n } while (n > 0);\n}\n\nfunction writeVarbytes(out: number[], bytes: Uint8Array) {\n writeVaruint(out, bytes.length);\n out.push(...bytes);\n}\n\nconst OP_TAG: Record<OtsOp['kind'], number> = {\n sha1: 0x02,\n ripemd160: 0x03,\n sha256: 0x08,\n keccak256: 0x67,\n append: 0xf0,\n prepend: 0xf1,\n reverse: 0xf2,\n hexlify: 0xf3,\n};\n\nfunction writeAttestation(out: number[], a: OtsAttestation) {\n const payload: number[] = [];\n let tag: string;\n if (a.kind === 'bitcoin') {\n tag = TAG_BITCOIN;\n writeVaruint(payload, a.height);\n } else if (a.kind === 'pending') {\n tag = TAG_PENDING;\n writeVarbytes(payload, new TextEncoder().encode(a.uri));\n } else {\n tag = a.tag;\n payload.push(...a.payload);\n }\n out.push(0x00);\n for (let i = 0; i < 16; i += 2) out.push(parseInt(tag.slice(i, i + 2), 16));\n writeVarbytes(out, new Uint8Array(payload));\n}\n\nfunction writeTimestamp(out: number[], ts: OtsTimestamp) {\n const items: (() => void)[] = [\n ...ts.attestations.map((a) => () => writeAttestation(out, a)),\n ...ts.ops.map(({ op, child }) => () => {\n out.push(OP_TAG[op.kind]);\n if (op.kind === 'append' || op.kind === 'prepend') writeVarbytes(out, op.arg);\n writeTimestamp(out, child);\n }),\n ];\n if (items.length === 0) throw new Error('ots: cannot serialize an empty timestamp node');\n items.forEach((write, i) => {\n if (i < items.length - 1) out.push(0xff);\n write();\n });\n}\n\n/** Serialize as a bare timestamp (the encoding carried in `ots.proof`). */\nexport function serializeTimestamp(ts: OtsTimestamp): Uint8Array {\n const out: number[] = [];\n writeTimestamp(out, ts);\n return new Uint8Array(out);\n}\n\nfunction attestationKey(a: OtsAttestation): string {\n if (a.kind === 'bitcoin') return `b:${a.height}`;\n if (a.kind === 'pending') return `p:${a.uri}`;\n return `u:${a.tag}:${hexEncode(a.payload)}`;\n}\n\nfunction opKey(op: OtsOp): string {\n return 'arg' in op ? `${op.kind}:${hexEncode(op.arg)}` : op.kind;\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n}\n\nexport function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.byteLength !== b.byteLength) return false;\n for (let i = 0; i < a.byteLength; i++) if (a[i] !== b[i]) return false;\n return true;\n}\n","// Submit an envelope id to one or more OTS calendars. Returns a pending proof.\n// See SPEC.md §6.1.\n//\n// The submission strategy: try each calendar in parallel and keep every\n// receipt. A stamp that only reaches one calendar is a single point of failure\n// for upgrade, so by default two must answer (SPEC §6.1's SHOULD).\n\nimport { base64Encode, hexDecode } from './base64.js';\nimport { createCalendarClient, DEFAULT_CALENDARS } from './calendar.js';\nimport { mergeAt, parseTimestamp, serializeTimestamp, type OtsTimestamp } from './ots.js';\nimport type { CalendarClient, OtsProof } from './types.js';\n\nexport interface SubmitOptions {\n /**\n * Calendars to submit to. Defaults to DEFAULT_CALENDARS. Can be strings\n * (URLs) or pre-built CalendarClient instances.\n */\n calendars?: readonly (string | CalendarClient)[];\n /**\n * Minimum number of calendars that must answer with a readable receipt.\n * Defaults to 2, as SPEC §6.1 recommends, or to the number of calendars\n * when fewer are given. If fewer answer, submitToCalendars throws.\n */\n minSuccesses?: number;\n /** Optional custom fetch passed through to calendar clients. */\n fetch?: typeof fetch;\n /** Request timeout per calendar. Default 30_000ms. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\n/**\n * Submit the envelope `id` (64-hex) to OTS calendars and return an OtsProof in\n * pending state. The caller merges this into the envelope's `ots` field.\n *\n * Each calendar answers with its own pending timestamp for the digest. They are\n * merged into one proof, so upgrade (see upgrade.ts) can ask any calendar that\n * answered. A calendar whose answer does not parse counts as a failure.\n */\nexport async function submitToCalendars(idHex: string, opts: SubmitOptions = {}): Promise<OtsProof> {\n const digest = hexDecode(idHex);\n if (digest.byteLength !== 32) {\n throw new Error('submitToCalendars: idHex must be 32 bytes (64 hex chars)');\n }\n\n const clients = (opts.calendars ?? DEFAULT_CALENDARS).map((c) =>\n typeof c === 'string'\n ? createCalendarClient(c, { fetch: opts.fetch, timeoutMs: opts.timeoutMs })\n : c\n );\n if (clients.length === 0) {\n throw new Error('submitToCalendars: at least one calendar is required');\n }\n const minSuccesses = Math.max(1, opts.minSuccesses ?? Math.min(2, clients.length));\n\n const settled = await Promise.allSettled(\n clients.map(async (c) => {\n const proof = await c.submit(digest, opts.signal);\n return { url: c.url, proof };\n })\n );\n const successes = settled\n .filter((r): r is PromiseFulfilledResult<{ url: string; proof: Uint8Array }> => r.status === 'fulfilled')\n .map((r) => r.value);\n const failures = settled\n .filter((r): r is PromiseRejectedResult => r.status === 'rejected')\n .map((r) => (r.reason instanceof Error ? r.reason.message : String(r.reason)));\n\n if (successes.length < minSuccesses) {\n // AggregateError would be nicer but targets ES2021; Error keeps us at ES2020.\n const msg = `OTS submission did not reach ${minSuccesses} calendar(s). Errors: ${failures.join('; ')}`;\n const err = new Error(msg) as Error & { errors: string[] };\n err.errors = failures;\n throw err;\n }\n\n // Keep every calendar's receipt in one proof, so any of them can upgrade it.\n let tree: OtsTimestamp | null = null;\n const merged: string[] = [];\n for (const s of successes) {\n let receipt: OtsTimestamp;\n try {\n receipt = parseTimestamp(s.proof, digest);\n } catch (e) {\n failures.push(`${s.url}: unreadable proof (${e instanceof Error ? e.message : String(e)})`);\n continue;\n }\n if (tree) mergeAt(tree, receipt);\n else tree = receipt;\n merged.push(s.url);\n }\n if (!tree || merged.length < minSuccesses) {\n const msg = `OTS submission did not reach ${minSuccesses} calendar(s). Errors: ${failures.join('; ')}`;\n const err = new Error(msg) as Error & { errors: string[] };\n err.errors = failures;\n throw err;\n }\n return {\n status: 'pending',\n proof: base64Encode(serializeTimestamp(tree)),\n calendars: merged,\n blockHeight: null,\n blockHash: null,\n upgradedAt: null,\n };\n}\n","// Anchor verification. See SPEC.md §6.3.\n//\n// A confirmed anchor holds when all three are true:\n// 1. the proof commits to the envelope id and walks to a Bitcoin\n// attestation at the declared height;\n// 2. the message at that attestation equals the Merkle root in the block\n// header at that height;\n// 3. that header double-SHA256es to the declared block hash.\n//\n// The resulting function is what `@orangecheck/stamp-core` expects at the\n// `verifyOtsAnchor` input of `verify()`.\n\nimport { sha256 } from '@noble/hashes/sha2';\n\nimport { base64Decode, hexDecode, hexEncode } from './base64.js';\nimport { bitcoinAnchors, bytesEqual, parseProof } from './ots.js';\nimport type {\n AnchorVerificationInput,\n AnchorVerificationResult,\n AnchorVerifier,\n BlockHeaderSource,\n} from './types.js';\n\nexport interface AnchorVerifierConfig {\n /**\n * Parse the proof bytes and return the Merkle root the proof walks to,\n * plus its block height. Optional: the built-in OTS parser is used when\n * omitted. `blockHeight` is the declared height, for proofs that carry\n * attestations at more than one height.\n */\n walkProof?: (input: {\n proofBytes: Uint8Array;\n digest: Uint8Array;\n blockHeight?: number;\n }) => Promise<{ merkleRoot: Uint8Array; blockHeight: number } | null>;\n /**\n * Source of Bitcoin block headers: a full node, SPV, a headers snapshot,\n * or `mempoolHeaderSource()`. This is the verifier's trust anchor.\n */\n headerSource: BlockHeaderSource;\n}\n\n/** Built-in walker: parse the OTS proof and pick the Bitcoin attestation. */\nexport async function walkOtsProof(input: {\n proofBytes: Uint8Array;\n digest: Uint8Array;\n blockHeight?: number;\n}): Promise<{ merkleRoot: Uint8Array; blockHeight: number } | null> {\n try {\n const anchors = bitcoinAnchors(parseProof(input.proofBytes, input.digest));\n return anchors.find((a) => a.blockHeight === input.blockHeight) ?? anchors[0] ?? null;\n } catch {\n return null;\n }\n}\n\n/** Block hash (display hex) of an 80-byte header. */\nexport function blockHashOf(header: Uint8Array): string {\n return hexEncode(sha256(sha256(header)).reverse());\n}\n\nexport function makeAnchorVerifier(\n cfg: AnchorVerifierConfig\n): (proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean> {\n const walkProof = cfg.walkProof ?? walkOtsProof;\n const verifier: AnchorVerifier = async (\n input: AnchorVerificationInput\n ): Promise<AnchorVerificationResult> => {\n const walked = await walkProof({\n proofBytes: input.proofBytes,\n digest: input.digest,\n blockHeight: input.blockHeight,\n });\n if (!walked) {\n return { ok: false, reason: 'proof could not be walked to a Bitcoin commitment' };\n }\n if (walked.blockHeight !== input.blockHeight) {\n return {\n ok: false,\n reason: `proof anchors at block ${walked.blockHeight}, envelope declares ${input.blockHeight}`,\n };\n }\n const header = await cfg.headerSource.getHeaderAt(input.blockHeight);\n if (!header || header.byteLength !== 80) {\n return { ok: false, reason: `no block header available at height ${input.blockHeight}` };\n }\n if (blockHashOf(header) !== input.blockHash.toLowerCase()) {\n return { ok: false, reason: 'block header does not hash to the declared block hash' };\n }\n // OTS attests to the Merkle root in header byte order (offset 36).\n const headerMerkle = header.subarray(36, 68);\n if (!bytesEqual(headerMerkle, walked.merkleRoot)) {\n return { ok: false, reason: 'block header Merkle root does not match walked proof root' };\n }\n return { ok: true, merkleRoot: hexEncode(headerMerkle) };\n };\n\n return async (proofB64, blockHeight, blockHash, envelopeId) => {\n const r = await verifier({\n proofBytes: base64Decode(proofB64),\n digest: hexDecode(envelopeId),\n blockHeight,\n blockHash,\n });\n return r.ok;\n };\n}\n\n/**\n * Anchor verifier using the built-in OTS parser. Kept async for callers of the\n * 0.1 API, which lazily loaded an optional parser here.\n */\nexport async function makeDefaultAnchorVerifier(opts: {\n headerSource: BlockHeaderSource;\n}): Promise<\n (proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean>\n> {\n return makeAnchorVerifier({ headerSource: opts.headerSource });\n}\n\nexport interface MempoolHeaderSourceOptions {\n /** Esplora-compatible API base. Default https://mempool.space/api. */\n baseUrl?: string;\n fetch?: typeof fetch;\n}\n\n/**\n * Block headers from an Esplora-compatible API. The verifier checks each\n * header against the declared block hash, so this source is trusted only to\n * report which block is at a height.\n */\nexport function mempoolHeaderSource(opts: MempoolHeaderSourceOptions = {}): BlockHeaderSource {\n const base = (opts.baseUrl ?? 'https://mempool.space/api').replace(/\\/+$/, '');\n const fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);\n // Null only when the explorer says there is no such block (404). Any other\n // failure throws: a header that could not be read is not a missing block.\n const read = async (url: string, shape: RegExp): Promise<string | null> => {\n const r = await fetchImpl(url);\n if (r.status === 404) return null;\n if (!r.ok) throw new Error(`header lookup failed: HTTP ${r.status} from ${url}`);\n const text = (await r.text()).trim();\n if (!shape.test(text)) throw new Error(`header lookup failed: unexpected answer from ${url}`);\n return text;\n };\n return {\n async getHeaderAt(height) {\n const hash = await read(`${base}/block-height/${height}`, /^[0-9a-f]{64}$/);\n if (hash === null) return null;\n const hex = await read(`${base}/block/${hash}/header`, /^[0-9a-f]{160}$/);\n return hex === null ? null : hexDecode(hex);\n },\n };\n}\n","// Upgrade a pending OTS proof to a confirmed one. See SPEC.md §6.2.\n//\n// A pending proof ends in calendar attestations, each naming a calendar and\n// the commitment (the message at that leaf) the calendar will later anchor.\n// Calendars index upgrades by that commitment, not by the submitted digest.\n// For each pending leaf we ask its calendar for the continuation, graft it on,\n// and report the proof as confirmed once it reaches a Bitcoin attestation\n// whose block header checks out.\n\nimport { blockHashOf } from './anchor.js';\nimport { base64Decode, base64Encode, hexDecode } from './base64.js';\nimport { createCalendarClient } from './calendar.js';\nimport {\n bitcoinAnchors,\n bytesEqual,\n mergeAt,\n parseProof,\n parseTimestamp,\n pendingCommitments,\n serializeTimestamp,\n} from './ots.js';\nimport type { BlockHeaderSource, OtsProof } from './types.js';\n\nexport interface UpgradeOptions {\n /**\n * Where block headers come from (`mempoolHeaderSource()`, your node, or a\n * headers snapshot). Required: the proof is reported `confirmed` only when\n * the header at its attested height has the proof's Merkle root, and that\n * header gives `blockHash`. Until such a header is found the proof stays\n * `pending`, with whatever the calendars added merged in.\n */\n headerSource: BlockHeaderSource;\n /** Optional custom fetch passed through to calendar clients. */\n fetch?: typeof fetch;\n /** Request timeout per calendar. Default 30_000ms. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\nconst norm = (u: string) => u.replace(/\\/+$/, '');\n\nexport async function upgradeProof(\n current: OtsProof,\n idHex: string,\n opts: UpgradeOptions\n): Promise<OtsProof> {\n if (current.status === 'confirmed') return current; // idempotent\n if (!opts?.headerSource) {\n throw new Error('upgradeProof: pass headerSource; a proof is confirmed only against a block header');\n }\n\n const before = base64Decode(current.proof);\n const tree = parseProof(before, hexDecode(idHex));\n\n // Only ask calendars this proof was submitted to.\n const listed = new Set(current.calendars.map(norm));\n const pending = pendingCommitments(tree).filter((p) => listed.has(norm(p.uri)));\n if (pending.length === 0 && bitcoinAnchors(tree).length === 0) {\n throw new Error('upgradeProof: proof has no pending attestation from a listed calendar');\n }\n\n const answered: string[] = [];\n await Promise.allSettled(\n pending.map(async ({ uri, commitment }) => {\n const client = createCalendarClient(uri, { fetch: opts.fetch, timeoutMs: opts.timeoutMs });\n const bytes = await client.fetchProof(commitment, opts.signal);\n if (!bytes) return;\n if (mergeAt(tree, parseTimestamp(bytes, commitment))) answered.push(norm(uri));\n })\n );\n\n const merged = serializeTimestamp(tree);\n const anchor = await resolveAnchor(tree, opts.headerSource);\n const calendars = [...answered, ...current.calendars.filter((c) => !answered.includes(norm(c)))];\n\n if (anchor) {\n return {\n status: 'confirmed',\n proof: base64Encode(merged),\n calendars,\n blockHeight: anchor.blockHeight,\n blockHash: anchor.blockHash,\n upgradedAt: new Date().toISOString().replace(/\\.\\d+Z$/, 'Z'),\n };\n }\n if (!bytesEqual(merged, before)) {\n return { ...current, proof: base64Encode(merged), calendars };\n }\n return current;\n}\n\n/**\n * The lowest Bitcoin block a proof anchors `idHex` in, checked against\n * `headerSource`: the proof is walked from `idHex`, and an attestation counts\n * only if the header at its height has the proof's Merkle root. Whatever\n * height or status the stamp declares is not read. Null when no attestation\n * checks out, or the proof does not parse from `idHex`.\n */\nexport async function verifiedAnchor(\n proofB64: string,\n idHex: string,\n headerSource: BlockHeaderSource\n): Promise<{ blockHeight: number; blockHash: string } | null> {\n let tree: ReturnType<typeof parseTimestamp>;\n try {\n tree = parseProof(base64Decode(proofB64), hexDecode(idHex));\n } catch {\n return null;\n }\n return resolveAnchor(tree, headerSource);\n}\n\nasync function resolveAnchor(\n tree: ReturnType<typeof parseTimestamp>,\n headers: BlockHeaderSource\n): Promise<{ blockHeight: number; blockHash: string } | null> {\n for (const a of bitcoinAnchors(tree)) {\n const header = await headers.getHeaderAt(a.blockHeight);\n if (header && header.byteLength === 80 && bytesEqual(header.subarray(36, 68), a.merkleRoot)) {\n return { blockHeight: a.blockHeight, blockHash: blockHashOf(header) };\n }\n }\n return null;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/base64.ts","../src/calendar.ts","../src/ots.ts","../src/submit.ts","../src/anchor.ts","../src/upgrade.ts"],"names":["sha256","ripemd160","sha1","keccak_256","tag"],"mappings":"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","file":"index.js","sourcesContent":["// Types for @orangecheck/stamp-ots.\n\nimport type { StampOts } from '@orangecheck/stamp-core';\n\nexport type OtsProofStatus = 'pending' | 'confirmed';\n\nexport interface OtsProof {\n status: OtsProofStatus;\n /** OTS timestamp rooted at the envelope id (or a detached .ots file), base64. */\n proof: string;\n /** Calendar URLs that contain this proof, in submission order. */\n calendars: string[];\n /** Bitcoin block height at which this proof is anchored (null if pending). */\n blockHeight: number | null;\n /** Bitcoin block hash (hex, lowercase) at the anchor block (null if pending). */\n blockHash: string | null;\n /** ISO 8601 UTC of the upgrade (null if pending). */\n upgradedAt: string | null;\n}\n\nexport interface CalendarClient {\n /** Base URL of the calendar, e.g. \"https://alice.btc.calendar.opentimestamps.org\". */\n readonly url: string;\n\n /**\n * Submit a 32-byte digest to the calendar for aggregation. Returns the raw\n * pending proof bytes.\n *\n * OTS calendar HTTP API: POST <url>/digest with the raw bytes as the body\n * and no Content-Type header, returns the proof bytes as the response body.\n * A Content-Type outside the CORS-safelisted ones makes a browser send a\n * preflight, which the public calendars refuse; createCalendarClient sends\n * none.\n */\n submit(digest: Uint8Array, signal?: AbortSignal): Promise<Uint8Array>;\n\n /**\n * Fetch the continuation of a pending proof. `commitment` is the message\n * at the calendar's pending attestation (see `pendingCommitments`), not\n * the submitted digest. Returns null if the calendar has nothing yet.\n *\n * OTS calendar HTTP API: GET <url>/timestamp/<hex(commitment)>, returns a\n * timestamp rooted at the commitment, or 404.\n */\n fetchProof(commitment: Uint8Array, signal?: AbortSignal): Promise<Uint8Array | null>;\n}\n\nexport interface AnchorVerificationInput {\n /** Raw OTS proof bytes (base64-decoded by the caller). */\n proofBytes: Uint8Array;\n /** 32-byte digest that the proof commits to. */\n digest: Uint8Array;\n /** Declared block height from the envelope. */\n blockHeight: number;\n /** Declared block hash (hex) from the envelope. */\n blockHash: string;\n /**\n * Optional block header source. If provided, the verifier uses this to\n * fetch the header at `blockHeight` and compare its Merkle root to the\n * one derived from walking the proof.\n *\n * If omitted, the verifier MAY still parse the proof and report\n * structural validity but CANNOT report a bound anchor.\n */\n headerSource?: BlockHeaderSource;\n}\n\nexport interface BlockHeaderSource {\n /**\n * The 80-byte raw block header at the given height, or null when there is\n * no block at that height. Throw when the header could not be read: a\n * failed lookup must never read as a missing block.\n */\n getHeaderAt(height: number): Promise<Uint8Array | null>;\n}\n\nexport type AnchorVerifier = (input: AnchorVerificationInput) => Promise<AnchorVerificationResult>;\n\nexport type AnchorVerificationResult =\n | { ok: true; merkleRoot: string }\n | { ok: false; reason: string };\n\n/**\n * Convert an OtsProof (library type) to the StampOts field shape that the\n * envelope carries. The two are isomorphic; this function exists to keep\n * stamp-core's type surface narrow.\n */\nexport function toStampOts(p: OtsProof): StampOts {\n return {\n status: p.status,\n proof: p.proof,\n calendars: p.calendars,\n block_height: p.blockHeight,\n block_hash: p.blockHash,\n upgraded_at: p.upgradedAt,\n };\n}\n\nexport function fromStampOts(s: StampOts): OtsProof {\n return {\n status: s.status,\n proof: s.proof,\n calendars: s.calendars,\n blockHeight: s.block_height,\n blockHash: s.block_hash,\n upgradedAt: s.upgraded_at,\n };\n}\n","// Minimal, dependency-free base64 <-> Uint8Array helpers. OTS proof bytes\n// are carried as base64 inside OC Stamp envelopes so they survive any text\n// transport (URL fragment, JSON, Nostr event content).\n\nconst B64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\nconst B64_DECODE_TABLE = (() => {\n const t = new Int16Array(128).fill(-1);\n for (let i = 0; i < B64_CHARS.length; i++) t[B64_CHARS.charCodeAt(i)] = i;\n t['='.charCodeAt(0)] = -2;\n return t;\n})();\n\nexport function base64Encode(bytes: Uint8Array): string {\n let out = '';\n let i = 0;\n for (; i + 2 < bytes.length; i += 3) {\n const a = bytes[i]!;\n const b = bytes[i + 1]!;\n const c = bytes[i + 2]!;\n out +=\n B64_CHARS[a >> 2]! +\n B64_CHARS[((a & 0x03) << 4) | (b >> 4)]! +\n B64_CHARS[((b & 0x0f) << 2) | (c >> 6)]! +\n B64_CHARS[c & 0x3f]!;\n }\n if (i < bytes.length) {\n const a = bytes[i]!;\n const b = i + 1 < bytes.length ? bytes[i + 1]! : 0;\n out += B64_CHARS[a >> 2]!;\n out += B64_CHARS[((a & 0x03) << 4) | (b >> 4)]!;\n out += i + 1 < bytes.length ? B64_CHARS[(b & 0x0f) << 2]! : '=';\n out += '=';\n }\n return out;\n}\n\nexport function base64Decode(s: string): Uint8Array {\n const str = s.replace(/\\s+/g, '');\n const len = str.length;\n if (len === 0) return new Uint8Array(0);\n if (len % 4 !== 0) throw new Error('base64: bad length');\n let padding = 0;\n if (str[len - 1] === '=') padding++;\n if (str[len - 2] === '=') padding++;\n const outLen = (len / 4) * 3 - padding;\n const out = new Uint8Array(outLen);\n let o = 0;\n for (let i = 0; i < len; i += 4) {\n const c0 = B64_DECODE_TABLE[str.charCodeAt(i)]!;\n const c1 = B64_DECODE_TABLE[str.charCodeAt(i + 1)]!;\n const c2 = B64_DECODE_TABLE[str.charCodeAt(i + 2)]!;\n const c3 = B64_DECODE_TABLE[str.charCodeAt(i + 3)]!;\n if (c0 < 0 || c1 < 0 || c2 < -2 || c3 < -2) throw new Error('base64: bad char');\n out[o++] = (c0 << 2) | (c1 >> 4);\n if (c2 >= 0) out[o++] = ((c1 & 0x0f) << 4) | (c2 >> 2);\n if (c3 >= 0) out[o++] = ((c2 & 0x03) << 6) | c3;\n }\n return out;\n}\n\nexport function hexDecode(s: string): Uint8Array {\n if (s.length % 2 !== 0) throw new Error('hex: odd length');\n const out = new Uint8Array(s.length / 2);\n for (let i = 0; i < out.length; i++) {\n const hi = parseInt(s[i * 2]!, 16);\n const lo = parseInt(s[i * 2 + 1]!, 16);\n if (Number.isNaN(hi) || Number.isNaN(lo)) throw new Error('hex: bad char');\n out[i] = (hi << 4) | lo;\n }\n return out;\n}\n\nexport function hexEncode(bytes: Uint8Array): string {\n const HEX = '0123456789abcdef';\n let out = '';\n for (let i = 0; i < bytes.length; i++) {\n const b = bytes[i]!;\n out += HEX[(b >> 4) & 0x0f]! + HEX[b & 0x0f]!;\n }\n return out;\n}\n","// HTTP client for an OpenTimestamps calendar. Implements the minimal subset\n// of the calendar protocol that an OC Stamp implementation needs:\n//\n// POST <url>/digest body = raw digest bytes -> pending proof bytes\n// GET <url>/timestamp/<hex(commitment)> -> continuation, or 404\n//\n// The client moves bytes only; ./ots.ts parses them.\n\nimport type { CalendarClient } from './types.js';\nimport { hexEncode } from './base64.js';\n\nexport const DEFAULT_CALENDARS: readonly string[] = [\n 'https://alice.btc.calendar.opentimestamps.org',\n 'https://bob.btc.calendar.opentimestamps.org',\n 'https://finney.calendar.eternitywall.com',\n];\n\nexport interface HttpCalendarOptions {\n /**\n * Custom fetch implementation. Defaults to global `fetch`. Useful in\n * environments that need a specific adapter (Node < 18, Cloudflare\n * Workers, proxies).\n */\n fetch?: typeof fetch;\n /** Request timeout in milliseconds. Default 30_000. */\n timeoutMs?: number;\n}\n\nexport function createCalendarClient(url: string, opts: HttpCalendarOptions = {}): CalendarClient {\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (typeof fetchImpl !== 'function') {\n throw new Error(\n '@orangecheck/stamp-ots: no fetch implementation available. Pass one via { fetch }.'\n );\n }\n const timeoutMs = opts.timeoutMs ?? 30_000;\n const base = url.replace(/\\/$/, '');\n\n return {\n url: base,\n async submit(digest, signal) {\n if (digest.byteLength !== 32) {\n throw new Error('OTS: digest must be exactly 32 bytes');\n }\n const ac = withTimeout(signal, timeoutMs);\n // Uint8Array is a valid fetch body at runtime in Node 18+ and all\n // modern browsers, but TypeScript's DOM typings don't accept it\n // directly under `strict` + `noUncheckedIndexedAccess`. The cast is\n // narrow and intentional.\n // No Content-Type: a non-safelisted type makes browsers send a\n // CORS preflight, and OTS calendars answer OPTIONS with 501.\n const resp = await fetchImpl(`${base}/digest`, {\n method: 'POST',\n body: digest as unknown as BodyInit,\n signal: ac.signal,\n });\n ac.clear();\n if (!resp.ok) {\n throw new Error(`OTS calendar ${base} submit failed: HTTP ${resp.status}`);\n }\n const buf = await resp.arrayBuffer();\n return new Uint8Array(buf);\n },\n async fetchProof(commitment, signal) {\n if (commitment.byteLength === 0 || commitment.byteLength > 64) {\n throw new Error('OTS: commitment must be 1-64 bytes');\n }\n const ac = withTimeout(signal, timeoutMs);\n const resp = await fetchImpl(`${base}/timestamp/${hexEncode(commitment)}`, {\n method: 'GET',\n headers: { Accept: 'application/vnd.opentimestamps.v1' },\n signal: ac.signal,\n });\n ac.clear();\n if (resp.status === 404) return null;\n if (!resp.ok) {\n throw new Error(`OTS calendar ${base} fetchProof failed: HTTP ${resp.status}`);\n }\n const buf = await resp.arrayBuffer();\n return new Uint8Array(buf);\n },\n };\n}\n\nfunction withTimeout(parent: AbortSignal | undefined, ms: number): { signal: AbortSignal; clear: () => void } {\n const ac = new AbortController();\n const onParent = () => ac.abort((parent as AbortSignal & { reason?: unknown }).reason);\n if (parent) {\n if (parent.aborted) ac.abort((parent as AbortSignal & { reason?: unknown }).reason);\n else parent.addEventListener('abort', onParent, { once: true });\n }\n const t = setTimeout(() => ac.abort(new Error(`OTS request timed out after ${ms}ms`)), ms);\n return {\n signal: ac.signal,\n clear: () => {\n clearTimeout(t);\n if (parent) parent.removeEventListener('abort', onParent);\n },\n };\n}\n","// OpenTimestamps proof format: parse, walk, serialize, merge.\n//\n// Follows python-opentimestamps (core/timestamp.py, core/op.py,\n// core/notary.py). Two encodings are accepted:\n//\n// - a bare timestamp rooted at the digest (what an OTS calendar returns from\n// POST /digest, and what OC Stamp envelopes carry in `ots.proof`);\n// - a detached `.ots` file (magic header + file-hash op + digest + timestamp).\n\nimport { ripemd160, sha1 } from '@noble/hashes/legacy';\nimport { sha256 } from '@noble/hashes/sha2';\nimport { keccak_256 } from '@noble/hashes/sha3';\n\nimport { hexEncode } from './base64.js';\n\nconst HEADER_MAGIC = new Uint8Array([\n 0x00, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x00,\n 0x00, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0xbf, 0x89, 0xe2, 0xe8, 0x84, 0xe8, 0x92, 0x94,\n]);\n\nconst TAG_BITCOIN = '0588960d73d71901';\nconst TAG_PENDING = '83dfe30d2ef90c8e';\n\nconst MAX_DEPTH = 256;\nconst MAX_MSG = 4096;\n\nexport type OtsOp =\n | { kind: 'sha256' | 'ripemd160' | 'sha1' | 'keccak256' | 'reverse' | 'hexlify' }\n | { kind: 'append' | 'prepend'; arg: Uint8Array };\n\nexport type OtsAttestation =\n | { kind: 'bitcoin'; height: number }\n | { kind: 'pending'; uri: string }\n | { kind: 'unknown'; tag: string; payload: Uint8Array };\n\nexport interface OtsTimestamp {\n /** The message at this node: the digest after every op on the path to it. */\n msg: Uint8Array;\n attestations: OtsAttestation[];\n ops: { op: OtsOp; child: OtsTimestamp }[];\n}\n\nclass Reader {\n private pos = 0;\n constructor(private readonly buf: Uint8Array) {}\n byte(): number {\n if (this.pos >= this.buf.length) throw new Error('ots: unexpected end of proof');\n return this.buf[this.pos++]!;\n }\n bytes(n: number): Uint8Array {\n if (n < 0 || this.pos + n > this.buf.length) throw new Error('ots: unexpected end of proof');\n const out = this.buf.subarray(this.pos, this.pos + n);\n this.pos += n;\n return out;\n }\n varuint(): number {\n let value = 0;\n let shift = 0;\n for (;;) {\n const b = this.byte();\n value += (b & 0x7f) * 2 ** shift;\n if (!(b & 0x80)) return value;\n shift += 7;\n if (shift > 49) throw new Error('ots: varuint too large');\n }\n }\n varbytes(max: number): Uint8Array {\n const n = this.varuint();\n if (n > max) throw new Error('ots: varbytes too long');\n return this.bytes(n);\n }\n get done(): boolean {\n return this.pos === this.buf.length;\n }\n}\n\nconst UNARY: Record<number, OtsOp['kind']> = {\n 0x02: 'sha1',\n 0x03: 'ripemd160',\n 0x08: 'sha256',\n 0x67: 'keccak256',\n 0xf2: 'reverse',\n 0xf3: 'hexlify',\n};\n\nexport function applyOp(op: OtsOp, msg: Uint8Array): Uint8Array {\n switch (op.kind) {\n case 'sha256':\n return sha256(msg);\n case 'ripemd160':\n return ripemd160(msg);\n case 'sha1':\n return sha1(msg);\n case 'keccak256':\n return keccak_256(msg);\n case 'reverse':\n return new Uint8Array(msg).reverse();\n case 'hexlify':\n return new TextEncoder().encode(hexEncode(msg));\n case 'append':\n return concat(msg, op.arg);\n case 'prepend':\n return concat(op.arg, msg);\n }\n}\n\nfunction readOp(r: Reader, tag: number): OtsOp {\n const unary = UNARY[tag];\n if (unary) return { kind: unary } as OtsOp;\n if (tag === 0xf0) return { kind: 'append', arg: r.varbytes(MAX_MSG) };\n if (tag === 0xf1) return { kind: 'prepend', arg: r.varbytes(MAX_MSG) };\n throw new Error(`ots: unknown op tag 0x${tag.toString(16)}`);\n}\n\nfunction readAttestation(r: Reader): OtsAttestation {\n const tag = hexEncode(r.bytes(8));\n const payload = r.varbytes(8192);\n const p = new Reader(payload);\n if (tag === TAG_BITCOIN) return { kind: 'bitcoin', height: p.varuint() };\n if (tag === TAG_PENDING) return { kind: 'pending', uri: new TextDecoder().decode(p.varbytes(1000)) };\n return { kind: 'unknown', tag, payload };\n}\n\nfunction readTimestamp(r: Reader, msg: Uint8Array, depth: number): OtsTimestamp {\n if (depth > MAX_DEPTH) throw new Error('ots: proof too deep');\n const node: OtsTimestamp = { msg, attestations: [], ops: [] };\n const item = (tag: number) => {\n if (tag === 0x00) {\n node.attestations.push(readAttestation(r));\n return;\n }\n const op = readOp(r, tag);\n const next = applyOp(op, msg);\n if (next.length > MAX_MSG) throw new Error('ots: message too long');\n node.ops.push({ op, child: readTimestamp(r, next, depth + 1) });\n };\n let tag = r.byte();\n while (tag === 0xff) {\n item(r.byte());\n tag = r.byte();\n }\n item(tag);\n return node;\n}\n\n/** Parse a bare timestamp whose root message is `digest`. */\nexport function parseTimestamp(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp {\n const r = new Reader(bytes);\n const ts = readTimestamp(r, digest, 0);\n if (!r.done) throw new Error('ots: trailing bytes after timestamp');\n return ts;\n}\n\nexport function isDetached(bytes: Uint8Array): boolean {\n return bytes.length > HEADER_MAGIC.length && bytesEqual(bytes.subarray(0, HEADER_MAGIC.length), HEADER_MAGIC);\n}\n\n/** Parse a detached `.ots` file. Only sha256 file digests are accepted. */\nexport function parseDetached(bytes: Uint8Array): { digest: Uint8Array; timestamp: OtsTimestamp } {\n if (!isDetached(bytes)) throw new Error('ots: missing detached-file header');\n const r = new Reader(bytes.subarray(HEADER_MAGIC.length));\n const major = r.varuint();\n if (major !== 1) throw new Error(`ots: unsupported file version ${major}`);\n if (r.byte() !== 0x08) throw new Error('ots: only sha256 file digests are supported');\n const digest = new Uint8Array(r.bytes(32));\n const timestamp = readTimestamp(r, digest, 0);\n if (!r.done) throw new Error('ots: trailing bytes after timestamp');\n return { digest, timestamp };\n}\n\n/**\n * Parse either encoding and require that it commits to `digest`. A detached\n * file for some other digest is rejected rather than walked.\n */\nexport function parseProof(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp {\n if (!isDetached(bytes)) return parseTimestamp(bytes, digest);\n const d = parseDetached(bytes);\n if (!bytesEqual(d.digest, digest)) throw new Error('ots: proof commits to a different digest');\n return d.timestamp;\n}\n\n/** Every attestation in the tree with the message it attests to. */\nexport function attestations(ts: OtsTimestamp): { msg: Uint8Array; attestation: OtsAttestation }[] {\n const out: { msg: Uint8Array; attestation: OtsAttestation }[] = [];\n const walk = (n: OtsTimestamp) => {\n for (const a of n.attestations) out.push({ msg: n.msg, attestation: a });\n for (const { child } of n.ops) walk(child);\n };\n walk(ts);\n return out;\n}\n\n/**\n * Bitcoin attestations, lowest height first. `merkleRoot` is the message at\n * the attestation, which equals the block header's Merkle root in header\n * byte order.\n */\nexport function bitcoinAnchors(ts: OtsTimestamp): { blockHeight: number; merkleRoot: Uint8Array }[] {\n return attestations(ts)\n .flatMap(({ msg, attestation }) =>\n attestation.kind === 'bitcoin' ? [{ blockHeight: attestation.height, merkleRoot: msg }] : []\n )\n .sort((a, b) => a.blockHeight - b.blockHeight);\n}\n\n/** Pending calendar attestations: where to ask, and the commitment to ask for. */\nexport function pendingCommitments(ts: OtsTimestamp): { uri: string; commitment: Uint8Array }[] {\n return attestations(ts).flatMap(({ msg, attestation }) =>\n attestation.kind === 'pending' ? [{ uri: attestation.uri, commitment: msg }] : []\n );\n}\n\n/**\n * Graft `upgrade` (a timestamp rooted at some node's message) onto the node\n * with that message, as python-opentimestamps' Timestamp.merge does. Returns\n * false when no node carries that message.\n */\nexport function mergeAt(ts: OtsTimestamp, upgrade: OtsTimestamp): boolean {\n if (bytesEqual(ts.msg, upgrade.msg)) {\n for (const a of upgrade.attestations) {\n if (!ts.attestations.some((b) => attestationKey(b) === attestationKey(a))) ts.attestations.push(a);\n }\n for (const { op, child } of upgrade.ops) {\n const same = ts.ops.find((o) => opKey(o.op) === opKey(op));\n if (same) mergeAt(same.child, child);\n else ts.ops.push({ op, child });\n }\n return true;\n }\n return ts.ops.some(({ child }) => mergeAt(child, upgrade));\n}\n\nfunction writeVaruint(out: number[], n: number) {\n do {\n let b = n % 128;\n n = Math.floor(n / 128);\n if (n > 0) b |= 0x80;\n out.push(b);\n } while (n > 0);\n}\n\nfunction writeVarbytes(out: number[], bytes: Uint8Array) {\n writeVaruint(out, bytes.length);\n out.push(...bytes);\n}\n\nconst OP_TAG: Record<OtsOp['kind'], number> = {\n sha1: 0x02,\n ripemd160: 0x03,\n sha256: 0x08,\n keccak256: 0x67,\n append: 0xf0,\n prepend: 0xf1,\n reverse: 0xf2,\n hexlify: 0xf3,\n};\n\nfunction writeAttestation(out: number[], a: OtsAttestation) {\n const payload: number[] = [];\n let tag: string;\n if (a.kind === 'bitcoin') {\n tag = TAG_BITCOIN;\n writeVaruint(payload, a.height);\n } else if (a.kind === 'pending') {\n tag = TAG_PENDING;\n writeVarbytes(payload, new TextEncoder().encode(a.uri));\n } else {\n tag = a.tag;\n payload.push(...a.payload);\n }\n out.push(0x00);\n for (let i = 0; i < 16; i += 2) out.push(parseInt(tag.slice(i, i + 2), 16));\n writeVarbytes(out, new Uint8Array(payload));\n}\n\nfunction writeTimestamp(out: number[], ts: OtsTimestamp) {\n const items: (() => void)[] = [\n ...ts.attestations.map((a) => () => writeAttestation(out, a)),\n ...ts.ops.map(({ op, child }) => () => {\n out.push(OP_TAG[op.kind]);\n if (op.kind === 'append' || op.kind === 'prepend') writeVarbytes(out, op.arg);\n writeTimestamp(out, child);\n }),\n ];\n if (items.length === 0) throw new Error('ots: cannot serialize an empty timestamp node');\n items.forEach((write, i) => {\n if (i < items.length - 1) out.push(0xff);\n write();\n });\n}\n\n/** Serialize as a bare timestamp (the encoding carried in `ots.proof`). */\nexport function serializeTimestamp(ts: OtsTimestamp): Uint8Array {\n const out: number[] = [];\n writeTimestamp(out, ts);\n return new Uint8Array(out);\n}\n\nfunction attestationKey(a: OtsAttestation): string {\n if (a.kind === 'bitcoin') return `b:${a.height}`;\n if (a.kind === 'pending') return `p:${a.uri}`;\n return `u:${a.tag}:${hexEncode(a.payload)}`;\n}\n\nfunction opKey(op: OtsOp): string {\n return 'arg' in op ? `${op.kind}:${hexEncode(op.arg)}` : op.kind;\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n}\n\nexport function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.byteLength !== b.byteLength) return false;\n for (let i = 0; i < a.byteLength; i++) if (a[i] !== b[i]) return false;\n return true;\n}\n","// Submit an envelope id to one or more OTS calendars. Returns a pending proof.\n// See SPEC.md §6.1.\n//\n// The submission strategy: try each calendar in parallel and keep every\n// receipt. A stamp that only reaches one calendar is a single point of failure\n// for upgrade, so by default two must answer (SPEC §6.1's SHOULD).\n\nimport { base64Encode, hexDecode } from './base64.js';\nimport { createCalendarClient, DEFAULT_CALENDARS } from './calendar.js';\nimport { mergeAt, parseTimestamp, serializeTimestamp, type OtsTimestamp } from './ots.js';\nimport type { CalendarClient, OtsProof } from './types.js';\n\nexport interface SubmitOptions {\n /**\n * Calendars to submit to. Defaults to DEFAULT_CALENDARS. Can be strings\n * (URLs) or pre-built CalendarClient instances.\n */\n calendars?: readonly (string | CalendarClient)[];\n /**\n * Minimum number of calendars that must answer with a readable receipt.\n * Defaults to 2, as SPEC §6.1 recommends, or to the number of calendars\n * when fewer are given. If fewer answer, submitToCalendars throws.\n */\n minSuccesses?: number;\n /** Optional custom fetch passed through to calendar clients. */\n fetch?: typeof fetch;\n /** Request timeout per calendar. Default 30_000ms. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\n/**\n * Submit the envelope `id` (64-hex) to OTS calendars and return an OtsProof in\n * pending state. The caller merges this into the envelope's `ots` field.\n *\n * Each calendar answers with its own pending timestamp for the digest. They are\n * merged into one proof, so upgrade (see upgrade.ts) can ask any calendar that\n * answered. A calendar whose answer does not parse counts as a failure.\n */\nexport async function submitToCalendars(idHex: string, opts: SubmitOptions = {}): Promise<OtsProof> {\n const digest = hexDecode(idHex);\n if (digest.byteLength !== 32) {\n throw new Error('submitToCalendars: idHex must be 32 bytes (64 hex chars)');\n }\n\n const clients = (opts.calendars ?? DEFAULT_CALENDARS).map((c) =>\n typeof c === 'string'\n ? createCalendarClient(c, { fetch: opts.fetch, timeoutMs: opts.timeoutMs })\n : c\n );\n if (clients.length === 0) {\n throw new Error('submitToCalendars: at least one calendar is required');\n }\n const minSuccesses = Math.max(1, opts.minSuccesses ?? Math.min(2, clients.length));\n\n const settled = await Promise.allSettled(\n clients.map(async (c) => {\n const proof = await c.submit(digest, opts.signal);\n return { url: c.url, proof };\n })\n );\n const successes = settled\n .filter((r): r is PromiseFulfilledResult<{ url: string; proof: Uint8Array }> => r.status === 'fulfilled')\n .map((r) => r.value);\n const failures = settled\n .filter((r): r is PromiseRejectedResult => r.status === 'rejected')\n .map((r) => (r.reason instanceof Error ? r.reason.message : String(r.reason)));\n\n if (successes.length < minSuccesses) {\n // AggregateError would be nicer but targets ES2021; Error keeps us at ES2020.\n const msg = `OTS submission did not reach ${minSuccesses} calendar(s). Errors: ${failures.join('; ')}`;\n const err = new Error(msg) as Error & { errors: string[] };\n err.errors = failures;\n throw err;\n }\n\n // Keep every calendar's receipt in one proof, so any of them can upgrade it.\n let tree: OtsTimestamp | null = null;\n const merged: string[] = [];\n for (const s of successes) {\n let receipt: OtsTimestamp;\n try {\n receipt = parseTimestamp(s.proof, digest);\n } catch (e) {\n failures.push(`${s.url}: unreadable proof (${e instanceof Error ? e.message : String(e)})`);\n continue;\n }\n if (tree) mergeAt(tree, receipt);\n else tree = receipt;\n merged.push(s.url);\n }\n if (!tree || merged.length < minSuccesses) {\n const msg = `OTS submission did not reach ${minSuccesses} calendar(s). Errors: ${failures.join('; ')}`;\n const err = new Error(msg) as Error & { errors: string[] };\n err.errors = failures;\n throw err;\n }\n return {\n status: 'pending',\n proof: base64Encode(serializeTimestamp(tree)),\n calendars: merged,\n blockHeight: null,\n blockHash: null,\n upgradedAt: null,\n };\n}\n","// Anchor verification. See SPEC.md §6.3.\n//\n// A confirmed anchor holds when all three are true:\n// 1. the proof commits to the envelope id and walks to a Bitcoin\n// attestation at the declared height;\n// 2. the message at that attestation equals the Merkle root in the block\n// header at that height;\n// 3. that header double-SHA256es to the declared block hash.\n//\n// The resulting function is what `@orangecheck/stamp-core` expects at the\n// `verifyOtsAnchor` input of `verify()`.\n\nimport { sha256 } from '@noble/hashes/sha2';\n\nimport { base64Decode, hexDecode, hexEncode } from './base64.js';\nimport { bitcoinAnchors, bytesEqual, parseProof } from './ots.js';\nimport type {\n AnchorVerificationInput,\n AnchorVerificationResult,\n AnchorVerifier,\n BlockHeaderSource,\n} from './types.js';\n\nexport interface AnchorVerifierConfig {\n /**\n * Parse the proof bytes and return the Merkle root the proof walks to,\n * plus its block height. Optional: the built-in OTS parser is used when\n * omitted. `blockHeight` is the declared height, for proofs that carry\n * attestations at more than one height.\n */\n walkProof?: (input: {\n proofBytes: Uint8Array;\n digest: Uint8Array;\n blockHeight?: number;\n }) => Promise<{ merkleRoot: Uint8Array; blockHeight: number } | null>;\n /**\n * Source of Bitcoin block headers: a full node, SPV, a headers snapshot,\n * or `mempoolHeaderSource()`. This is the verifier's trust anchor.\n */\n headerSource: BlockHeaderSource;\n}\n\n/** Built-in walker: parse the OTS proof and pick the Bitcoin attestation. */\nexport async function walkOtsProof(input: {\n proofBytes: Uint8Array;\n digest: Uint8Array;\n blockHeight?: number;\n}): Promise<{ merkleRoot: Uint8Array; blockHeight: number } | null> {\n try {\n const anchors = bitcoinAnchors(parseProof(input.proofBytes, input.digest));\n return anchors.find((a) => a.blockHeight === input.blockHeight) ?? anchors[0] ?? null;\n } catch {\n return null;\n }\n}\n\n/** Block hash (display hex) of an 80-byte header. */\nexport function blockHashOf(header: Uint8Array): string {\n return hexEncode(sha256(sha256(header)).reverse());\n}\n\nexport function makeAnchorVerifier(\n cfg: AnchorVerifierConfig\n): (proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean> {\n const walkProof = cfg.walkProof ?? walkOtsProof;\n const verifier: AnchorVerifier = async (\n input: AnchorVerificationInput\n ): Promise<AnchorVerificationResult> => {\n const walked = await walkProof({\n proofBytes: input.proofBytes,\n digest: input.digest,\n blockHeight: input.blockHeight,\n });\n if (!walked) {\n return { ok: false, reason: 'proof could not be walked to a Bitcoin commitment' };\n }\n if (walked.blockHeight !== input.blockHeight) {\n return {\n ok: false,\n reason: `proof anchors at block ${walked.blockHeight}, envelope declares ${input.blockHeight}`,\n };\n }\n const header = await cfg.headerSource.getHeaderAt(input.blockHeight);\n if (!header || header.byteLength !== 80) {\n return { ok: false, reason: `no block header available at height ${input.blockHeight}` };\n }\n if (blockHashOf(header) !== input.blockHash.toLowerCase()) {\n return { ok: false, reason: 'block header does not hash to the declared block hash' };\n }\n // OTS attests to the Merkle root in header byte order (offset 36).\n const headerMerkle = header.subarray(36, 68);\n if (!bytesEqual(headerMerkle, walked.merkleRoot)) {\n return { ok: false, reason: 'block header Merkle root does not match walked proof root' };\n }\n return { ok: true, merkleRoot: hexEncode(headerMerkle) };\n };\n\n // Resolves false for a decided no. Throws only when the check could not be made\n // (the header source did not answer), which stamp-core reports as unchecked.\n return async (proofB64, blockHeight, blockHash, envelopeId) => {\n let proofBytes: Uint8Array;\n let digest: Uint8Array;\n try {\n proofBytes = base64Decode(proofB64);\n digest = hexDecode(envelopeId);\n } catch {\n return false;\n }\n const r = await verifier({ proofBytes, digest, blockHeight, blockHash });\n return r.ok;\n };\n}\n\n/**\n * Anchor verifier using the built-in OTS parser. Kept async for callers of the\n * 0.1 API, which lazily loaded an optional parser here.\n */\nexport async function makeDefaultAnchorVerifier(opts: {\n headerSource: BlockHeaderSource;\n}): Promise<\n (proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean>\n> {\n return makeAnchorVerifier({ headerSource: opts.headerSource });\n}\n\nexport interface MempoolHeaderSourceOptions {\n /** Esplora-compatible API base. Default https://mempool.space/api. */\n baseUrl?: string;\n fetch?: typeof fetch;\n /** Per request: a lookup that has not answered by then throws, as unread. Default 15_000ms. */\n timeoutMs?: number;\n}\n\n/**\n * Block headers from an Esplora-compatible API. The verifier checks each\n * header against the declared block hash, so this source is trusted only to\n * report which block is at a height.\n */\nexport function mempoolHeaderSource(opts: MempoolHeaderSourceOptions = {}): BlockHeaderSource {\n const base = (opts.baseUrl ?? 'https://mempool.space/api').replace(/\\/+$/, '');\n const fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);\n const timeoutMs = opts.timeoutMs ?? 15_000;\n // Null only when the explorer says there is no such block (404). Any other\n // failure throws: a header that could not be read is not a missing block,\n // and neither is an explorer that never answers.\n const read = async (url: string, shape: RegExp): Promise<string | null> => {\n const r = await fetchImpl(url, { signal: AbortSignal.timeout(timeoutMs) });\n if (r.status === 404) return null;\n if (!r.ok) throw new Error(`header lookup failed: HTTP ${r.status} from ${url}`);\n const text = (await r.text()).trim();\n if (!shape.test(text)) throw new Error(`header lookup failed: unexpected answer from ${url}`);\n return text;\n };\n return {\n async getHeaderAt(height) {\n const hash = await read(`${base}/block-height/${height}`, /^[0-9a-f]{64}$/);\n if (hash === null) return null;\n const hex = await read(`${base}/block/${hash}/header`, /^[0-9a-f]{160}$/);\n return hex === null ? null : hexDecode(hex);\n },\n };\n}\n","// Upgrade a pending OTS proof to a confirmed one. See SPEC.md §6.2.\n//\n// A pending proof ends in calendar attestations, each naming a calendar and\n// the commitment (the message at that leaf) the calendar will later anchor.\n// Calendars index upgrades by that commitment, not by the submitted digest.\n// For each pending leaf we ask its calendar for the continuation, graft it on,\n// and report the proof as confirmed once it reaches a Bitcoin attestation\n// whose block header checks out. A calendar's 404 is its \"not yet\"; when no\n// calendar answers at all, nothing is concluded and the upgrade throws.\n\nimport { blockHashOf } from './anchor.js';\nimport { base64Decode, base64Encode, hexDecode } from './base64.js';\nimport { createCalendarClient } from './calendar.js';\nimport {\n bitcoinAnchors,\n bytesEqual,\n mergeAt,\n parseProof,\n parseTimestamp,\n pendingCommitments,\n serializeTimestamp,\n} from './ots.js';\nimport type { BlockHeaderSource, OtsProof } from './types.js';\n\nexport interface UpgradeOptions {\n /**\n * Where block headers come from (`mempoolHeaderSource()`, your node, or a\n * headers snapshot). Required: the proof is reported `confirmed` only when\n * the header at its attested height has the proof's Merkle root, and that\n * header gives `blockHash`. Until such a header is found the proof stays\n * `pending`, with whatever the calendars added merged in.\n */\n headerSource: BlockHeaderSource;\n /** Optional custom fetch passed through to calendar clients. */\n fetch?: typeof fetch;\n /** Request timeout per calendar. Default 30_000ms. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\nconst norm = (u: string) => u.replace(/\\/+$/, '');\n\n/**\n * No calendar a pending proof names answered, so nothing was learned: the\n * proof may be anchored already. Thrown by `upgradeProof` instead of\n * returning the proof as still `pending`.\n */\nexport class CalendarsUnreadError extends Error {\n constructor(\n /** The calendars asked, with why each did not answer. */\n readonly failures: { calendar: string; reason: string }[]\n ) {\n super(\n `OTS: no calendar answered (${failures.map((f) => `${f.calendar}: ${f.reason}`).join('; ')})`\n );\n this.name = 'CalendarsUnreadError';\n }\n}\n\nexport async function upgradeProof(\n current: OtsProof,\n idHex: string,\n opts: UpgradeOptions\n): Promise<OtsProof> {\n if (current.status === 'confirmed') return current; // idempotent\n if (!opts?.headerSource) {\n throw new Error('upgradeProof: pass headerSource; a proof is confirmed only against a block header');\n }\n\n const before = base64Decode(current.proof);\n const tree = parseProof(before, hexDecode(idHex));\n\n // Only ask calendars this proof was submitted to.\n const listed = new Set(current.calendars.map(norm));\n const pending = pendingCommitments(tree).filter((p) => listed.has(norm(p.uri)));\n if (pending.length === 0 && bitcoinAnchors(tree).length === 0) {\n throw new Error('upgradeProof: proof has no pending attestation from a listed calendar');\n }\n\n const answered: string[] = [];\n const settled = await Promise.allSettled(\n pending.map(async ({ uri, commitment }) => {\n const client = createCalendarClient(uri, { fetch: opts.fetch, timeoutMs: opts.timeoutMs });\n const bytes = await client.fetchProof(commitment, opts.signal);\n if (!bytes) return;\n if (mergeAt(tree, parseTimestamp(bytes, commitment))) answered.push(norm(uri));\n })\n );\n\n const merged = serializeTimestamp(tree);\n const anchor = await resolveAnchor(tree, opts.headerSource);\n if (!anchor && pending.length > 0 && settled.every((r) => r.status === 'rejected')) {\n throw new CalendarsUnreadError(\n pending.map(({ uri }, i) => ({\n calendar: norm(uri),\n reason: String((settled[i] as PromiseRejectedResult).reason?.message ?? settled[i]),\n }))\n );\n }\n const calendars = [...answered, ...current.calendars.filter((c) => !answered.includes(norm(c)))];\n\n if (anchor) {\n return {\n status: 'confirmed',\n proof: base64Encode(merged),\n calendars,\n blockHeight: anchor.blockHeight,\n blockHash: anchor.blockHash,\n upgradedAt: new Date().toISOString().replace(/\\.\\d+Z$/, 'Z'),\n };\n }\n if (!bytesEqual(merged, before)) {\n return { ...current, proof: base64Encode(merged), calendars };\n }\n return current;\n}\n\n/**\n * The lowest Bitcoin block a proof anchors `idHex` in, checked against\n * `headerSource`: the proof is walked from `idHex`, and an attestation counts\n * only if the header at its height has the proof's Merkle root. Whatever\n * height or status the stamp declares is not read. Null when no attestation\n * checks out, or the proof does not parse from `idHex`.\n */\nexport async function verifiedAnchor(\n proofB64: string,\n idHex: string,\n headerSource: BlockHeaderSource\n): Promise<{ blockHeight: number; blockHash: string } | null> {\n let tree: ReturnType<typeof parseTimestamp>;\n try {\n tree = parseProof(base64Decode(proofB64), hexDecode(idHex));\n } catch {\n return null;\n }\n return resolveAnchor(tree, headerSource);\n}\n\nasync function resolveAnchor(\n tree: ReturnType<typeof parseTimestamp>,\n headers: BlockHeaderSource\n): Promise<{ blockHeight: number; blockHash: string } | null> {\n for (const a of bitcoinAnchors(tree)) {\n const header = await headers.getHeaderAt(a.blockHeight);\n if (header && header.byteLength === 80 && bytesEqual(header.subarray(36, 68), a.merkleRoot)) {\n return { blockHeight: a.blockHeight, blockHash: blockHashOf(header) };\n }\n }\n return null;\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -537,12 +537,15 @@ function makeAnchorVerifier(cfg) {
|
|
|
537
537
|
return { ok: true, merkleRoot: hexEncode(headerMerkle) };
|
|
538
538
|
};
|
|
539
539
|
return async (proofB64, blockHeight, blockHash, envelopeId) => {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
}
|
|
540
|
+
let proofBytes;
|
|
541
|
+
let digest;
|
|
542
|
+
try {
|
|
543
|
+
proofBytes = base64Decode(proofB64);
|
|
544
|
+
digest = hexDecode(envelopeId);
|
|
545
|
+
} catch {
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
548
|
+
const r = await verifier({ proofBytes, digest, blockHeight, blockHash });
|
|
546
549
|
return r.ok;
|
|
547
550
|
};
|
|
548
551
|
}
|
|
@@ -552,8 +555,9 @@ async function makeDefaultAnchorVerifier(opts) {
|
|
|
552
555
|
function mempoolHeaderSource(opts = {}) {
|
|
553
556
|
const base = (opts.baseUrl ?? "https://mempool.space/api").replace(/\/+$/, "");
|
|
554
557
|
const fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
558
|
+
const timeoutMs = opts.timeoutMs ?? 15e3;
|
|
555
559
|
const read = async (url, shape) => {
|
|
556
|
-
const r = await fetchImpl(url);
|
|
560
|
+
const r = await fetchImpl(url, { signal: AbortSignal.timeout(timeoutMs) });
|
|
557
561
|
if (r.status === 404) return null;
|
|
558
562
|
if (!r.ok) throw new Error(`header lookup failed: HTTP ${r.status} from ${url}`);
|
|
559
563
|
const text = (await r.text()).trim();
|
|
@@ -572,6 +576,15 @@ function mempoolHeaderSource(opts = {}) {
|
|
|
572
576
|
|
|
573
577
|
// src/upgrade.ts
|
|
574
578
|
var norm = (u) => u.replace(/\/+$/, "");
|
|
579
|
+
var CalendarsUnreadError = class extends Error {
|
|
580
|
+
constructor(failures) {
|
|
581
|
+
super(
|
|
582
|
+
`OTS: no calendar answered (${failures.map((f) => `${f.calendar}: ${f.reason}`).join("; ")})`
|
|
583
|
+
);
|
|
584
|
+
this.failures = failures;
|
|
585
|
+
this.name = "CalendarsUnreadError";
|
|
586
|
+
}
|
|
587
|
+
};
|
|
575
588
|
async function upgradeProof(current, idHex, opts) {
|
|
576
589
|
if (current.status === "confirmed") return current;
|
|
577
590
|
if (!opts?.headerSource) {
|
|
@@ -585,7 +598,7 @@ async function upgradeProof(current, idHex, opts) {
|
|
|
585
598
|
throw new Error("upgradeProof: proof has no pending attestation from a listed calendar");
|
|
586
599
|
}
|
|
587
600
|
const answered = [];
|
|
588
|
-
await Promise.allSettled(
|
|
601
|
+
const settled = await Promise.allSettled(
|
|
589
602
|
pending.map(async ({ uri, commitment }) => {
|
|
590
603
|
const client = createCalendarClient(uri, { fetch: opts.fetch, timeoutMs: opts.timeoutMs });
|
|
591
604
|
const bytes = await client.fetchProof(commitment, opts.signal);
|
|
@@ -595,6 +608,14 @@ async function upgradeProof(current, idHex, opts) {
|
|
|
595
608
|
);
|
|
596
609
|
const merged = serializeTimestamp(tree);
|
|
597
610
|
const anchor = await resolveAnchor(tree, opts.headerSource);
|
|
611
|
+
if (!anchor && pending.length > 0 && settled.every((r) => r.status === "rejected")) {
|
|
612
|
+
throw new CalendarsUnreadError(
|
|
613
|
+
pending.map(({ uri }, i) => ({
|
|
614
|
+
calendar: norm(uri),
|
|
615
|
+
reason: String(settled[i].reason?.message ?? settled[i])
|
|
616
|
+
}))
|
|
617
|
+
);
|
|
618
|
+
}
|
|
598
619
|
const calendars = [...answered, ...current.calendars.filter((c) => !answered.includes(norm(c)))];
|
|
599
620
|
if (anchor) {
|
|
600
621
|
return {
|
|
@@ -630,6 +651,6 @@ async function resolveAnchor(tree, headers) {
|
|
|
630
651
|
return null;
|
|
631
652
|
}
|
|
632
653
|
|
|
633
|
-
export { DEFAULT_CALENDARS, attestations, base64Decode, base64Encode, bitcoinAnchors, blockHashOf, createCalendarClient, fromStampOts, hexDecode, hexEncode, makeAnchorVerifier, makeDefaultAnchorVerifier, mempoolHeaderSource, mergeAt, parseDetached, parseProof, parseTimestamp, pendingCommitments, serializeTimestamp, submitToCalendars, toStampOts, upgradeProof, verifiedAnchor, walkOtsProof };
|
|
654
|
+
export { CalendarsUnreadError, DEFAULT_CALENDARS, attestations, base64Decode, base64Encode, bitcoinAnchors, blockHashOf, createCalendarClient, fromStampOts, hexDecode, hexEncode, makeAnchorVerifier, makeDefaultAnchorVerifier, mempoolHeaderSource, mergeAt, parseDetached, parseProof, parseTimestamp, pendingCommitments, serializeTimestamp, submitToCalendars, toStampOts, upgradeProof, verifiedAnchor, walkOtsProof };
|
|
634
655
|
//# sourceMappingURL=index.mjs.map
|
|
635
656
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/base64.ts","../src/calendar.ts","../src/ots.ts","../src/submit.ts","../src/anchor.ts","../src/upgrade.ts"],"names":["tag","sha256"],"mappings":"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","file":"index.mjs","sourcesContent":["// Types for @orangecheck/stamp-ots.\n\nimport type { StampOts } from '@orangecheck/stamp-core';\n\nexport type OtsProofStatus = 'pending' | 'confirmed';\n\nexport interface OtsProof {\n status: OtsProofStatus;\n /** OTS timestamp rooted at the envelope id (or a detached .ots file), base64. */\n proof: string;\n /** Calendar URLs that contain this proof, in submission order. */\n calendars: string[];\n /** Bitcoin block height at which this proof is anchored (null if pending). */\n blockHeight: number | null;\n /** Bitcoin block hash (hex, lowercase) at the anchor block (null if pending). */\n blockHash: string | null;\n /** ISO 8601 UTC of the upgrade (null if pending). */\n upgradedAt: string | null;\n}\n\nexport interface CalendarClient {\n /** Base URL of the calendar, e.g. \"https://alice.btc.calendar.opentimestamps.org\". */\n readonly url: string;\n\n /**\n * Submit a 32-byte digest to the calendar for aggregation. Returns the raw\n * pending proof bytes.\n *\n * OTS calendar HTTP API: POST <url>/digest with the raw bytes as the body\n * and no Content-Type header, returns the proof bytes as the response body.\n * A Content-Type outside the CORS-safelisted ones makes a browser send a\n * preflight, which the public calendars refuse; createCalendarClient sends\n * none.\n */\n submit(digest: Uint8Array, signal?: AbortSignal): Promise<Uint8Array>;\n\n /**\n * Fetch the continuation of a pending proof. `commitment` is the message\n * at the calendar's pending attestation (see `pendingCommitments`), not\n * the submitted digest. Returns null if the calendar has nothing yet.\n *\n * OTS calendar HTTP API: GET <url>/timestamp/<hex(commitment)>, returns a\n * timestamp rooted at the commitment, or 404.\n */\n fetchProof(commitment: Uint8Array, signal?: AbortSignal): Promise<Uint8Array | null>;\n}\n\nexport interface AnchorVerificationInput {\n /** Raw OTS proof bytes (base64-decoded by the caller). */\n proofBytes: Uint8Array;\n /** 32-byte digest that the proof commits to. */\n digest: Uint8Array;\n /** Declared block height from the envelope. */\n blockHeight: number;\n /** Declared block hash (hex) from the envelope. */\n blockHash: string;\n /**\n * Optional block header source. If provided, the verifier uses this to\n * fetch the header at `blockHeight` and compare its Merkle root to the\n * one derived from walking the proof.\n *\n * If omitted, the verifier MAY still parse the proof and report\n * structural validity but CANNOT report a bound anchor.\n */\n headerSource?: BlockHeaderSource;\n}\n\nexport interface BlockHeaderSource {\n /**\n * The 80-byte raw block header at the given height, or null when there is\n * no block at that height. Throw when the header could not be read: a\n * failed lookup must never read as a missing block.\n */\n getHeaderAt(height: number): Promise<Uint8Array | null>;\n}\n\nexport type AnchorVerifier = (input: AnchorVerificationInput) => Promise<AnchorVerificationResult>;\n\nexport type AnchorVerificationResult =\n | { ok: true; merkleRoot: string }\n | { ok: false; reason: string };\n\n/**\n * Convert an OtsProof (library type) to the StampOts field shape that the\n * envelope carries. The two are isomorphic; this function exists to keep\n * stamp-core's type surface narrow.\n */\nexport function toStampOts(p: OtsProof): StampOts {\n return {\n status: p.status,\n proof: p.proof,\n calendars: p.calendars,\n block_height: p.blockHeight,\n block_hash: p.blockHash,\n upgraded_at: p.upgradedAt,\n };\n}\n\nexport function fromStampOts(s: StampOts): OtsProof {\n return {\n status: s.status,\n proof: s.proof,\n calendars: s.calendars,\n blockHeight: s.block_height,\n blockHash: s.block_hash,\n upgradedAt: s.upgraded_at,\n };\n}\n","// Minimal, dependency-free base64 <-> Uint8Array helpers. OTS proof bytes\n// are carried as base64 inside OC Stamp envelopes so they survive any text\n// transport (URL fragment, JSON, Nostr event content).\n\nconst B64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\nconst B64_DECODE_TABLE = (() => {\n const t = new Int16Array(128).fill(-1);\n for (let i = 0; i < B64_CHARS.length; i++) t[B64_CHARS.charCodeAt(i)] = i;\n t['='.charCodeAt(0)] = -2;\n return t;\n})();\n\nexport function base64Encode(bytes: Uint8Array): string {\n let out = '';\n let i = 0;\n for (; i + 2 < bytes.length; i += 3) {\n const a = bytes[i]!;\n const b = bytes[i + 1]!;\n const c = bytes[i + 2]!;\n out +=\n B64_CHARS[a >> 2]! +\n B64_CHARS[((a & 0x03) << 4) | (b >> 4)]! +\n B64_CHARS[((b & 0x0f) << 2) | (c >> 6)]! +\n B64_CHARS[c & 0x3f]!;\n }\n if (i < bytes.length) {\n const a = bytes[i]!;\n const b = i + 1 < bytes.length ? bytes[i + 1]! : 0;\n out += B64_CHARS[a >> 2]!;\n out += B64_CHARS[((a & 0x03) << 4) | (b >> 4)]!;\n out += i + 1 < bytes.length ? B64_CHARS[(b & 0x0f) << 2]! : '=';\n out += '=';\n }\n return out;\n}\n\nexport function base64Decode(s: string): Uint8Array {\n const str = s.replace(/\\s+/g, '');\n const len = str.length;\n if (len === 0) return new Uint8Array(0);\n if (len % 4 !== 0) throw new Error('base64: bad length');\n let padding = 0;\n if (str[len - 1] === '=') padding++;\n if (str[len - 2] === '=') padding++;\n const outLen = (len / 4) * 3 - padding;\n const out = new Uint8Array(outLen);\n let o = 0;\n for (let i = 0; i < len; i += 4) {\n const c0 = B64_DECODE_TABLE[str.charCodeAt(i)]!;\n const c1 = B64_DECODE_TABLE[str.charCodeAt(i + 1)]!;\n const c2 = B64_DECODE_TABLE[str.charCodeAt(i + 2)]!;\n const c3 = B64_DECODE_TABLE[str.charCodeAt(i + 3)]!;\n if (c0 < 0 || c1 < 0 || c2 < -2 || c3 < -2) throw new Error('base64: bad char');\n out[o++] = (c0 << 2) | (c1 >> 4);\n if (c2 >= 0) out[o++] = ((c1 & 0x0f) << 4) | (c2 >> 2);\n if (c3 >= 0) out[o++] = ((c2 & 0x03) << 6) | c3;\n }\n return out;\n}\n\nexport function hexDecode(s: string): Uint8Array {\n if (s.length % 2 !== 0) throw new Error('hex: odd length');\n const out = new Uint8Array(s.length / 2);\n for (let i = 0; i < out.length; i++) {\n const hi = parseInt(s[i * 2]!, 16);\n const lo = parseInt(s[i * 2 + 1]!, 16);\n if (Number.isNaN(hi) || Number.isNaN(lo)) throw new Error('hex: bad char');\n out[i] = (hi << 4) | lo;\n }\n return out;\n}\n\nexport function hexEncode(bytes: Uint8Array): string {\n const HEX = '0123456789abcdef';\n let out = '';\n for (let i = 0; i < bytes.length; i++) {\n const b = bytes[i]!;\n out += HEX[(b >> 4) & 0x0f]! + HEX[b & 0x0f]!;\n }\n return out;\n}\n","// HTTP client for an OpenTimestamps calendar. Implements the minimal subset\n// of the calendar protocol that an OC Stamp implementation needs:\n//\n// POST <url>/digest body = raw digest bytes -> pending proof bytes\n// GET <url>/timestamp/<hex(commitment)> -> continuation, or 404\n//\n// The client moves bytes only; ./ots.ts parses them.\n\nimport type { CalendarClient } from './types.js';\nimport { hexEncode } from './base64.js';\n\nexport const DEFAULT_CALENDARS: readonly string[] = [\n 'https://alice.btc.calendar.opentimestamps.org',\n 'https://bob.btc.calendar.opentimestamps.org',\n 'https://finney.calendar.eternitywall.com',\n];\n\nexport interface HttpCalendarOptions {\n /**\n * Custom fetch implementation. Defaults to global `fetch`. Useful in\n * environments that need a specific adapter (Node < 18, Cloudflare\n * Workers, proxies).\n */\n fetch?: typeof fetch;\n /** Request timeout in milliseconds. Default 30_000. */\n timeoutMs?: number;\n}\n\nexport function createCalendarClient(url: string, opts: HttpCalendarOptions = {}): CalendarClient {\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (typeof fetchImpl !== 'function') {\n throw new Error(\n '@orangecheck/stamp-ots: no fetch implementation available. Pass one via { fetch }.'\n );\n }\n const timeoutMs = opts.timeoutMs ?? 30_000;\n const base = url.replace(/\\/$/, '');\n\n return {\n url: base,\n async submit(digest, signal) {\n if (digest.byteLength !== 32) {\n throw new Error('OTS: digest must be exactly 32 bytes');\n }\n const ac = withTimeout(signal, timeoutMs);\n // Uint8Array is a valid fetch body at runtime in Node 18+ and all\n // modern browsers, but TypeScript's DOM typings don't accept it\n // directly under `strict` + `noUncheckedIndexedAccess`. The cast is\n // narrow and intentional.\n // No Content-Type: a non-safelisted type makes browsers send a\n // CORS preflight, and OTS calendars answer OPTIONS with 501.\n const resp = await fetchImpl(`${base}/digest`, {\n method: 'POST',\n body: digest as unknown as BodyInit,\n signal: ac.signal,\n });\n ac.clear();\n if (!resp.ok) {\n throw new Error(`OTS calendar ${base} submit failed: HTTP ${resp.status}`);\n }\n const buf = await resp.arrayBuffer();\n return new Uint8Array(buf);\n },\n async fetchProof(commitment, signal) {\n if (commitment.byteLength === 0 || commitment.byteLength > 64) {\n throw new Error('OTS: commitment must be 1-64 bytes');\n }\n const ac = withTimeout(signal, timeoutMs);\n const resp = await fetchImpl(`${base}/timestamp/${hexEncode(commitment)}`, {\n method: 'GET',\n headers: { Accept: 'application/vnd.opentimestamps.v1' },\n signal: ac.signal,\n });\n ac.clear();\n if (resp.status === 404) return null;\n if (!resp.ok) {\n throw new Error(`OTS calendar ${base} fetchProof failed: HTTP ${resp.status}`);\n }\n const buf = await resp.arrayBuffer();\n return new Uint8Array(buf);\n },\n };\n}\n\nfunction withTimeout(parent: AbortSignal | undefined, ms: number): { signal: AbortSignal; clear: () => void } {\n const ac = new AbortController();\n const onParent = () => ac.abort((parent as AbortSignal & { reason?: unknown }).reason);\n if (parent) {\n if (parent.aborted) ac.abort((parent as AbortSignal & { reason?: unknown }).reason);\n else parent.addEventListener('abort', onParent, { once: true });\n }\n const t = setTimeout(() => ac.abort(new Error(`OTS request timed out after ${ms}ms`)), ms);\n return {\n signal: ac.signal,\n clear: () => {\n clearTimeout(t);\n if (parent) parent.removeEventListener('abort', onParent);\n },\n };\n}\n","// OpenTimestamps proof format: parse, walk, serialize, merge.\n//\n// Follows python-opentimestamps (core/timestamp.py, core/op.py,\n// core/notary.py). Two encodings are accepted:\n//\n// - a bare timestamp rooted at the digest (what an OTS calendar returns from\n// POST /digest, and what OC Stamp envelopes carry in `ots.proof`);\n// - a detached `.ots` file (magic header + file-hash op + digest + timestamp).\n\nimport { ripemd160, sha1 } from '@noble/hashes/legacy';\nimport { sha256 } from '@noble/hashes/sha2';\nimport { keccak_256 } from '@noble/hashes/sha3';\n\nimport { hexEncode } from './base64.js';\n\nconst HEADER_MAGIC = new Uint8Array([\n 0x00, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x00,\n 0x00, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0xbf, 0x89, 0xe2, 0xe8, 0x84, 0xe8, 0x92, 0x94,\n]);\n\nconst TAG_BITCOIN = '0588960d73d71901';\nconst TAG_PENDING = '83dfe30d2ef90c8e';\n\nconst MAX_DEPTH = 256;\nconst MAX_MSG = 4096;\n\nexport type OtsOp =\n | { kind: 'sha256' | 'ripemd160' | 'sha1' | 'keccak256' | 'reverse' | 'hexlify' }\n | { kind: 'append' | 'prepend'; arg: Uint8Array };\n\nexport type OtsAttestation =\n | { kind: 'bitcoin'; height: number }\n | { kind: 'pending'; uri: string }\n | { kind: 'unknown'; tag: string; payload: Uint8Array };\n\nexport interface OtsTimestamp {\n /** The message at this node: the digest after every op on the path to it. */\n msg: Uint8Array;\n attestations: OtsAttestation[];\n ops: { op: OtsOp; child: OtsTimestamp }[];\n}\n\nclass Reader {\n private pos = 0;\n constructor(private readonly buf: Uint8Array) {}\n byte(): number {\n if (this.pos >= this.buf.length) throw new Error('ots: unexpected end of proof');\n return this.buf[this.pos++]!;\n }\n bytes(n: number): Uint8Array {\n if (n < 0 || this.pos + n > this.buf.length) throw new Error('ots: unexpected end of proof');\n const out = this.buf.subarray(this.pos, this.pos + n);\n this.pos += n;\n return out;\n }\n varuint(): number {\n let value = 0;\n let shift = 0;\n for (;;) {\n const b = this.byte();\n value += (b & 0x7f) * 2 ** shift;\n if (!(b & 0x80)) return value;\n shift += 7;\n if (shift > 49) throw new Error('ots: varuint too large');\n }\n }\n varbytes(max: number): Uint8Array {\n const n = this.varuint();\n if (n > max) throw new Error('ots: varbytes too long');\n return this.bytes(n);\n }\n get done(): boolean {\n return this.pos === this.buf.length;\n }\n}\n\nconst UNARY: Record<number, OtsOp['kind']> = {\n 0x02: 'sha1',\n 0x03: 'ripemd160',\n 0x08: 'sha256',\n 0x67: 'keccak256',\n 0xf2: 'reverse',\n 0xf3: 'hexlify',\n};\n\nexport function applyOp(op: OtsOp, msg: Uint8Array): Uint8Array {\n switch (op.kind) {\n case 'sha256':\n return sha256(msg);\n case 'ripemd160':\n return ripemd160(msg);\n case 'sha1':\n return sha1(msg);\n case 'keccak256':\n return keccak_256(msg);\n case 'reverse':\n return new Uint8Array(msg).reverse();\n case 'hexlify':\n return new TextEncoder().encode(hexEncode(msg));\n case 'append':\n return concat(msg, op.arg);\n case 'prepend':\n return concat(op.arg, msg);\n }\n}\n\nfunction readOp(r: Reader, tag: number): OtsOp {\n const unary = UNARY[tag];\n if (unary) return { kind: unary } as OtsOp;\n if (tag === 0xf0) return { kind: 'append', arg: r.varbytes(MAX_MSG) };\n if (tag === 0xf1) return { kind: 'prepend', arg: r.varbytes(MAX_MSG) };\n throw new Error(`ots: unknown op tag 0x${tag.toString(16)}`);\n}\n\nfunction readAttestation(r: Reader): OtsAttestation {\n const tag = hexEncode(r.bytes(8));\n const payload = r.varbytes(8192);\n const p = new Reader(payload);\n if (tag === TAG_BITCOIN) return { kind: 'bitcoin', height: p.varuint() };\n if (tag === TAG_PENDING) return { kind: 'pending', uri: new TextDecoder().decode(p.varbytes(1000)) };\n return { kind: 'unknown', tag, payload };\n}\n\nfunction readTimestamp(r: Reader, msg: Uint8Array, depth: number): OtsTimestamp {\n if (depth > MAX_DEPTH) throw new Error('ots: proof too deep');\n const node: OtsTimestamp = { msg, attestations: [], ops: [] };\n const item = (tag: number) => {\n if (tag === 0x00) {\n node.attestations.push(readAttestation(r));\n return;\n }\n const op = readOp(r, tag);\n const next = applyOp(op, msg);\n if (next.length > MAX_MSG) throw new Error('ots: message too long');\n node.ops.push({ op, child: readTimestamp(r, next, depth + 1) });\n };\n let tag = r.byte();\n while (tag === 0xff) {\n item(r.byte());\n tag = r.byte();\n }\n item(tag);\n return node;\n}\n\n/** Parse a bare timestamp whose root message is `digest`. */\nexport function parseTimestamp(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp {\n const r = new Reader(bytes);\n const ts = readTimestamp(r, digest, 0);\n if (!r.done) throw new Error('ots: trailing bytes after timestamp');\n return ts;\n}\n\nexport function isDetached(bytes: Uint8Array): boolean {\n return bytes.length > HEADER_MAGIC.length && bytesEqual(bytes.subarray(0, HEADER_MAGIC.length), HEADER_MAGIC);\n}\n\n/** Parse a detached `.ots` file. Only sha256 file digests are accepted. */\nexport function parseDetached(bytes: Uint8Array): { digest: Uint8Array; timestamp: OtsTimestamp } {\n if (!isDetached(bytes)) throw new Error('ots: missing detached-file header');\n const r = new Reader(bytes.subarray(HEADER_MAGIC.length));\n const major = r.varuint();\n if (major !== 1) throw new Error(`ots: unsupported file version ${major}`);\n if (r.byte() !== 0x08) throw new Error('ots: only sha256 file digests are supported');\n const digest = new Uint8Array(r.bytes(32));\n const timestamp = readTimestamp(r, digest, 0);\n if (!r.done) throw new Error('ots: trailing bytes after timestamp');\n return { digest, timestamp };\n}\n\n/**\n * Parse either encoding and require that it commits to `digest`. A detached\n * file for some other digest is rejected rather than walked.\n */\nexport function parseProof(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp {\n if (!isDetached(bytes)) return parseTimestamp(bytes, digest);\n const d = parseDetached(bytes);\n if (!bytesEqual(d.digest, digest)) throw new Error('ots: proof commits to a different digest');\n return d.timestamp;\n}\n\n/** Every attestation in the tree with the message it attests to. */\nexport function attestations(ts: OtsTimestamp): { msg: Uint8Array; attestation: OtsAttestation }[] {\n const out: { msg: Uint8Array; attestation: OtsAttestation }[] = [];\n const walk = (n: OtsTimestamp) => {\n for (const a of n.attestations) out.push({ msg: n.msg, attestation: a });\n for (const { child } of n.ops) walk(child);\n };\n walk(ts);\n return out;\n}\n\n/**\n * Bitcoin attestations, lowest height first. `merkleRoot` is the message at\n * the attestation, which equals the block header's Merkle root in header\n * byte order.\n */\nexport function bitcoinAnchors(ts: OtsTimestamp): { blockHeight: number; merkleRoot: Uint8Array }[] {\n return attestations(ts)\n .flatMap(({ msg, attestation }) =>\n attestation.kind === 'bitcoin' ? [{ blockHeight: attestation.height, merkleRoot: msg }] : []\n )\n .sort((a, b) => a.blockHeight - b.blockHeight);\n}\n\n/** Pending calendar attestations: where to ask, and the commitment to ask for. */\nexport function pendingCommitments(ts: OtsTimestamp): { uri: string; commitment: Uint8Array }[] {\n return attestations(ts).flatMap(({ msg, attestation }) =>\n attestation.kind === 'pending' ? [{ uri: attestation.uri, commitment: msg }] : []\n );\n}\n\n/**\n * Graft `upgrade` (a timestamp rooted at some node's message) onto the node\n * with that message, as python-opentimestamps' Timestamp.merge does. Returns\n * false when no node carries that message.\n */\nexport function mergeAt(ts: OtsTimestamp, upgrade: OtsTimestamp): boolean {\n if (bytesEqual(ts.msg, upgrade.msg)) {\n for (const a of upgrade.attestations) {\n if (!ts.attestations.some((b) => attestationKey(b) === attestationKey(a))) ts.attestations.push(a);\n }\n for (const { op, child } of upgrade.ops) {\n const same = ts.ops.find((o) => opKey(o.op) === opKey(op));\n if (same) mergeAt(same.child, child);\n else ts.ops.push({ op, child });\n }\n return true;\n }\n return ts.ops.some(({ child }) => mergeAt(child, upgrade));\n}\n\nfunction writeVaruint(out: number[], n: number) {\n do {\n let b = n % 128;\n n = Math.floor(n / 128);\n if (n > 0) b |= 0x80;\n out.push(b);\n } while (n > 0);\n}\n\nfunction writeVarbytes(out: number[], bytes: Uint8Array) {\n writeVaruint(out, bytes.length);\n out.push(...bytes);\n}\n\nconst OP_TAG: Record<OtsOp['kind'], number> = {\n sha1: 0x02,\n ripemd160: 0x03,\n sha256: 0x08,\n keccak256: 0x67,\n append: 0xf0,\n prepend: 0xf1,\n reverse: 0xf2,\n hexlify: 0xf3,\n};\n\nfunction writeAttestation(out: number[], a: OtsAttestation) {\n const payload: number[] = [];\n let tag: string;\n if (a.kind === 'bitcoin') {\n tag = TAG_BITCOIN;\n writeVaruint(payload, a.height);\n } else if (a.kind === 'pending') {\n tag = TAG_PENDING;\n writeVarbytes(payload, new TextEncoder().encode(a.uri));\n } else {\n tag = a.tag;\n payload.push(...a.payload);\n }\n out.push(0x00);\n for (let i = 0; i < 16; i += 2) out.push(parseInt(tag.slice(i, i + 2), 16));\n writeVarbytes(out, new Uint8Array(payload));\n}\n\nfunction writeTimestamp(out: number[], ts: OtsTimestamp) {\n const items: (() => void)[] = [\n ...ts.attestations.map((a) => () => writeAttestation(out, a)),\n ...ts.ops.map(({ op, child }) => () => {\n out.push(OP_TAG[op.kind]);\n if (op.kind === 'append' || op.kind === 'prepend') writeVarbytes(out, op.arg);\n writeTimestamp(out, child);\n }),\n ];\n if (items.length === 0) throw new Error('ots: cannot serialize an empty timestamp node');\n items.forEach((write, i) => {\n if (i < items.length - 1) out.push(0xff);\n write();\n });\n}\n\n/** Serialize as a bare timestamp (the encoding carried in `ots.proof`). */\nexport function serializeTimestamp(ts: OtsTimestamp): Uint8Array {\n const out: number[] = [];\n writeTimestamp(out, ts);\n return new Uint8Array(out);\n}\n\nfunction attestationKey(a: OtsAttestation): string {\n if (a.kind === 'bitcoin') return `b:${a.height}`;\n if (a.kind === 'pending') return `p:${a.uri}`;\n return `u:${a.tag}:${hexEncode(a.payload)}`;\n}\n\nfunction opKey(op: OtsOp): string {\n return 'arg' in op ? `${op.kind}:${hexEncode(op.arg)}` : op.kind;\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n}\n\nexport function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.byteLength !== b.byteLength) return false;\n for (let i = 0; i < a.byteLength; i++) if (a[i] !== b[i]) return false;\n return true;\n}\n","// Submit an envelope id to one or more OTS calendars. Returns a pending proof.\n// See SPEC.md §6.1.\n//\n// The submission strategy: try each calendar in parallel and keep every\n// receipt. A stamp that only reaches one calendar is a single point of failure\n// for upgrade, so by default two must answer (SPEC §6.1's SHOULD).\n\nimport { base64Encode, hexDecode } from './base64.js';\nimport { createCalendarClient, DEFAULT_CALENDARS } from './calendar.js';\nimport { mergeAt, parseTimestamp, serializeTimestamp, type OtsTimestamp } from './ots.js';\nimport type { CalendarClient, OtsProof } from './types.js';\n\nexport interface SubmitOptions {\n /**\n * Calendars to submit to. Defaults to DEFAULT_CALENDARS. Can be strings\n * (URLs) or pre-built CalendarClient instances.\n */\n calendars?: readonly (string | CalendarClient)[];\n /**\n * Minimum number of calendars that must answer with a readable receipt.\n * Defaults to 2, as SPEC §6.1 recommends, or to the number of calendars\n * when fewer are given. If fewer answer, submitToCalendars throws.\n */\n minSuccesses?: number;\n /** Optional custom fetch passed through to calendar clients. */\n fetch?: typeof fetch;\n /** Request timeout per calendar. Default 30_000ms. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\n/**\n * Submit the envelope `id` (64-hex) to OTS calendars and return an OtsProof in\n * pending state. The caller merges this into the envelope's `ots` field.\n *\n * Each calendar answers with its own pending timestamp for the digest. They are\n * merged into one proof, so upgrade (see upgrade.ts) can ask any calendar that\n * answered. A calendar whose answer does not parse counts as a failure.\n */\nexport async function submitToCalendars(idHex: string, opts: SubmitOptions = {}): Promise<OtsProof> {\n const digest = hexDecode(idHex);\n if (digest.byteLength !== 32) {\n throw new Error('submitToCalendars: idHex must be 32 bytes (64 hex chars)');\n }\n\n const clients = (opts.calendars ?? DEFAULT_CALENDARS).map((c) =>\n typeof c === 'string'\n ? createCalendarClient(c, { fetch: opts.fetch, timeoutMs: opts.timeoutMs })\n : c\n );\n if (clients.length === 0) {\n throw new Error('submitToCalendars: at least one calendar is required');\n }\n const minSuccesses = Math.max(1, opts.minSuccesses ?? Math.min(2, clients.length));\n\n const settled = await Promise.allSettled(\n clients.map(async (c) => {\n const proof = await c.submit(digest, opts.signal);\n return { url: c.url, proof };\n })\n );\n const successes = settled\n .filter((r): r is PromiseFulfilledResult<{ url: string; proof: Uint8Array }> => r.status === 'fulfilled')\n .map((r) => r.value);\n const failures = settled\n .filter((r): r is PromiseRejectedResult => r.status === 'rejected')\n .map((r) => (r.reason instanceof Error ? r.reason.message : String(r.reason)));\n\n if (successes.length < minSuccesses) {\n // AggregateError would be nicer but targets ES2021; Error keeps us at ES2020.\n const msg = `OTS submission did not reach ${minSuccesses} calendar(s). Errors: ${failures.join('; ')}`;\n const err = new Error(msg) as Error & { errors: string[] };\n err.errors = failures;\n throw err;\n }\n\n // Keep every calendar's receipt in one proof, so any of them can upgrade it.\n let tree: OtsTimestamp | null = null;\n const merged: string[] = [];\n for (const s of successes) {\n let receipt: OtsTimestamp;\n try {\n receipt = parseTimestamp(s.proof, digest);\n } catch (e) {\n failures.push(`${s.url}: unreadable proof (${e instanceof Error ? e.message : String(e)})`);\n continue;\n }\n if (tree) mergeAt(tree, receipt);\n else tree = receipt;\n merged.push(s.url);\n }\n if (!tree || merged.length < minSuccesses) {\n const msg = `OTS submission did not reach ${minSuccesses} calendar(s). Errors: ${failures.join('; ')}`;\n const err = new Error(msg) as Error & { errors: string[] };\n err.errors = failures;\n throw err;\n }\n return {\n status: 'pending',\n proof: base64Encode(serializeTimestamp(tree)),\n calendars: merged,\n blockHeight: null,\n blockHash: null,\n upgradedAt: null,\n };\n}\n","// Anchor verification. See SPEC.md §6.3.\n//\n// A confirmed anchor holds when all three are true:\n// 1. the proof commits to the envelope id and walks to a Bitcoin\n// attestation at the declared height;\n// 2. the message at that attestation equals the Merkle root in the block\n// header at that height;\n// 3. that header double-SHA256es to the declared block hash.\n//\n// The resulting function is what `@orangecheck/stamp-core` expects at the\n// `verifyOtsAnchor` input of `verify()`.\n\nimport { sha256 } from '@noble/hashes/sha2';\n\nimport { base64Decode, hexDecode, hexEncode } from './base64.js';\nimport { bitcoinAnchors, bytesEqual, parseProof } from './ots.js';\nimport type {\n AnchorVerificationInput,\n AnchorVerificationResult,\n AnchorVerifier,\n BlockHeaderSource,\n} from './types.js';\n\nexport interface AnchorVerifierConfig {\n /**\n * Parse the proof bytes and return the Merkle root the proof walks to,\n * plus its block height. Optional: the built-in OTS parser is used when\n * omitted. `blockHeight` is the declared height, for proofs that carry\n * attestations at more than one height.\n */\n walkProof?: (input: {\n proofBytes: Uint8Array;\n digest: Uint8Array;\n blockHeight?: number;\n }) => Promise<{ merkleRoot: Uint8Array; blockHeight: number } | null>;\n /**\n * Source of Bitcoin block headers: a full node, SPV, a headers snapshot,\n * or `mempoolHeaderSource()`. This is the verifier's trust anchor.\n */\n headerSource: BlockHeaderSource;\n}\n\n/** Built-in walker: parse the OTS proof and pick the Bitcoin attestation. */\nexport async function walkOtsProof(input: {\n proofBytes: Uint8Array;\n digest: Uint8Array;\n blockHeight?: number;\n}): Promise<{ merkleRoot: Uint8Array; blockHeight: number } | null> {\n try {\n const anchors = bitcoinAnchors(parseProof(input.proofBytes, input.digest));\n return anchors.find((a) => a.blockHeight === input.blockHeight) ?? anchors[0] ?? null;\n } catch {\n return null;\n }\n}\n\n/** Block hash (display hex) of an 80-byte header. */\nexport function blockHashOf(header: Uint8Array): string {\n return hexEncode(sha256(sha256(header)).reverse());\n}\n\nexport function makeAnchorVerifier(\n cfg: AnchorVerifierConfig\n): (proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean> {\n const walkProof = cfg.walkProof ?? walkOtsProof;\n const verifier: AnchorVerifier = async (\n input: AnchorVerificationInput\n ): Promise<AnchorVerificationResult> => {\n const walked = await walkProof({\n proofBytes: input.proofBytes,\n digest: input.digest,\n blockHeight: input.blockHeight,\n });\n if (!walked) {\n return { ok: false, reason: 'proof could not be walked to a Bitcoin commitment' };\n }\n if (walked.blockHeight !== input.blockHeight) {\n return {\n ok: false,\n reason: `proof anchors at block ${walked.blockHeight}, envelope declares ${input.blockHeight}`,\n };\n }\n const header = await cfg.headerSource.getHeaderAt(input.blockHeight);\n if (!header || header.byteLength !== 80) {\n return { ok: false, reason: `no block header available at height ${input.blockHeight}` };\n }\n if (blockHashOf(header) !== input.blockHash.toLowerCase()) {\n return { ok: false, reason: 'block header does not hash to the declared block hash' };\n }\n // OTS attests to the Merkle root in header byte order (offset 36).\n const headerMerkle = header.subarray(36, 68);\n if (!bytesEqual(headerMerkle, walked.merkleRoot)) {\n return { ok: false, reason: 'block header Merkle root does not match walked proof root' };\n }\n return { ok: true, merkleRoot: hexEncode(headerMerkle) };\n };\n\n return async (proofB64, blockHeight, blockHash, envelopeId) => {\n const r = await verifier({\n proofBytes: base64Decode(proofB64),\n digest: hexDecode(envelopeId),\n blockHeight,\n blockHash,\n });\n return r.ok;\n };\n}\n\n/**\n * Anchor verifier using the built-in OTS parser. Kept async for callers of the\n * 0.1 API, which lazily loaded an optional parser here.\n */\nexport async function makeDefaultAnchorVerifier(opts: {\n headerSource: BlockHeaderSource;\n}): Promise<\n (proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean>\n> {\n return makeAnchorVerifier({ headerSource: opts.headerSource });\n}\n\nexport interface MempoolHeaderSourceOptions {\n /** Esplora-compatible API base. Default https://mempool.space/api. */\n baseUrl?: string;\n fetch?: typeof fetch;\n}\n\n/**\n * Block headers from an Esplora-compatible API. The verifier checks each\n * header against the declared block hash, so this source is trusted only to\n * report which block is at a height.\n */\nexport function mempoolHeaderSource(opts: MempoolHeaderSourceOptions = {}): BlockHeaderSource {\n const base = (opts.baseUrl ?? 'https://mempool.space/api').replace(/\\/+$/, '');\n const fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);\n // Null only when the explorer says there is no such block (404). Any other\n // failure throws: a header that could not be read is not a missing block.\n const read = async (url: string, shape: RegExp): Promise<string | null> => {\n const r = await fetchImpl(url);\n if (r.status === 404) return null;\n if (!r.ok) throw new Error(`header lookup failed: HTTP ${r.status} from ${url}`);\n const text = (await r.text()).trim();\n if (!shape.test(text)) throw new Error(`header lookup failed: unexpected answer from ${url}`);\n return text;\n };\n return {\n async getHeaderAt(height) {\n const hash = await read(`${base}/block-height/${height}`, /^[0-9a-f]{64}$/);\n if (hash === null) return null;\n const hex = await read(`${base}/block/${hash}/header`, /^[0-9a-f]{160}$/);\n return hex === null ? null : hexDecode(hex);\n },\n };\n}\n","// Upgrade a pending OTS proof to a confirmed one. See SPEC.md §6.2.\n//\n// A pending proof ends in calendar attestations, each naming a calendar and\n// the commitment (the message at that leaf) the calendar will later anchor.\n// Calendars index upgrades by that commitment, not by the submitted digest.\n// For each pending leaf we ask its calendar for the continuation, graft it on,\n// and report the proof as confirmed once it reaches a Bitcoin attestation\n// whose block header checks out.\n\nimport { blockHashOf } from './anchor.js';\nimport { base64Decode, base64Encode, hexDecode } from './base64.js';\nimport { createCalendarClient } from './calendar.js';\nimport {\n bitcoinAnchors,\n bytesEqual,\n mergeAt,\n parseProof,\n parseTimestamp,\n pendingCommitments,\n serializeTimestamp,\n} from './ots.js';\nimport type { BlockHeaderSource, OtsProof } from './types.js';\n\nexport interface UpgradeOptions {\n /**\n * Where block headers come from (`mempoolHeaderSource()`, your node, or a\n * headers snapshot). Required: the proof is reported `confirmed` only when\n * the header at its attested height has the proof's Merkle root, and that\n * header gives `blockHash`. Until such a header is found the proof stays\n * `pending`, with whatever the calendars added merged in.\n */\n headerSource: BlockHeaderSource;\n /** Optional custom fetch passed through to calendar clients. */\n fetch?: typeof fetch;\n /** Request timeout per calendar. Default 30_000ms. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\nconst norm = (u: string) => u.replace(/\\/+$/, '');\n\nexport async function upgradeProof(\n current: OtsProof,\n idHex: string,\n opts: UpgradeOptions\n): Promise<OtsProof> {\n if (current.status === 'confirmed') return current; // idempotent\n if (!opts?.headerSource) {\n throw new Error('upgradeProof: pass headerSource; a proof is confirmed only against a block header');\n }\n\n const before = base64Decode(current.proof);\n const tree = parseProof(before, hexDecode(idHex));\n\n // Only ask calendars this proof was submitted to.\n const listed = new Set(current.calendars.map(norm));\n const pending = pendingCommitments(tree).filter((p) => listed.has(norm(p.uri)));\n if (pending.length === 0 && bitcoinAnchors(tree).length === 0) {\n throw new Error('upgradeProof: proof has no pending attestation from a listed calendar');\n }\n\n const answered: string[] = [];\n await Promise.allSettled(\n pending.map(async ({ uri, commitment }) => {\n const client = createCalendarClient(uri, { fetch: opts.fetch, timeoutMs: opts.timeoutMs });\n const bytes = await client.fetchProof(commitment, opts.signal);\n if (!bytes) return;\n if (mergeAt(tree, parseTimestamp(bytes, commitment))) answered.push(norm(uri));\n })\n );\n\n const merged = serializeTimestamp(tree);\n const anchor = await resolveAnchor(tree, opts.headerSource);\n const calendars = [...answered, ...current.calendars.filter((c) => !answered.includes(norm(c)))];\n\n if (anchor) {\n return {\n status: 'confirmed',\n proof: base64Encode(merged),\n calendars,\n blockHeight: anchor.blockHeight,\n blockHash: anchor.blockHash,\n upgradedAt: new Date().toISOString().replace(/\\.\\d+Z$/, 'Z'),\n };\n }\n if (!bytesEqual(merged, before)) {\n return { ...current, proof: base64Encode(merged), calendars };\n }\n return current;\n}\n\n/**\n * The lowest Bitcoin block a proof anchors `idHex` in, checked against\n * `headerSource`: the proof is walked from `idHex`, and an attestation counts\n * only if the header at its height has the proof's Merkle root. Whatever\n * height or status the stamp declares is not read. Null when no attestation\n * checks out, or the proof does not parse from `idHex`.\n */\nexport async function verifiedAnchor(\n proofB64: string,\n idHex: string,\n headerSource: BlockHeaderSource\n): Promise<{ blockHeight: number; blockHash: string } | null> {\n let tree: ReturnType<typeof parseTimestamp>;\n try {\n tree = parseProof(base64Decode(proofB64), hexDecode(idHex));\n } catch {\n return null;\n }\n return resolveAnchor(tree, headerSource);\n}\n\nasync function resolveAnchor(\n tree: ReturnType<typeof parseTimestamp>,\n headers: BlockHeaderSource\n): Promise<{ blockHeight: number; blockHash: string } | null> {\n for (const a of bitcoinAnchors(tree)) {\n const header = await headers.getHeaderAt(a.blockHeight);\n if (header && header.byteLength === 80 && bytesEqual(header.subarray(36, 68), a.merkleRoot)) {\n return { blockHeight: a.blockHeight, blockHash: blockHashOf(header) };\n }\n }\n return null;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/base64.ts","../src/calendar.ts","../src/ots.ts","../src/submit.ts","../src/anchor.ts","../src/upgrade.ts"],"names":["tag","sha256"],"mappings":"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","file":"index.mjs","sourcesContent":["// Types for @orangecheck/stamp-ots.\n\nimport type { StampOts } from '@orangecheck/stamp-core';\n\nexport type OtsProofStatus = 'pending' | 'confirmed';\n\nexport interface OtsProof {\n status: OtsProofStatus;\n /** OTS timestamp rooted at the envelope id (or a detached .ots file), base64. */\n proof: string;\n /** Calendar URLs that contain this proof, in submission order. */\n calendars: string[];\n /** Bitcoin block height at which this proof is anchored (null if pending). */\n blockHeight: number | null;\n /** Bitcoin block hash (hex, lowercase) at the anchor block (null if pending). */\n blockHash: string | null;\n /** ISO 8601 UTC of the upgrade (null if pending). */\n upgradedAt: string | null;\n}\n\nexport interface CalendarClient {\n /** Base URL of the calendar, e.g. \"https://alice.btc.calendar.opentimestamps.org\". */\n readonly url: string;\n\n /**\n * Submit a 32-byte digest to the calendar for aggregation. Returns the raw\n * pending proof bytes.\n *\n * OTS calendar HTTP API: POST <url>/digest with the raw bytes as the body\n * and no Content-Type header, returns the proof bytes as the response body.\n * A Content-Type outside the CORS-safelisted ones makes a browser send a\n * preflight, which the public calendars refuse; createCalendarClient sends\n * none.\n */\n submit(digest: Uint8Array, signal?: AbortSignal): Promise<Uint8Array>;\n\n /**\n * Fetch the continuation of a pending proof. `commitment` is the message\n * at the calendar's pending attestation (see `pendingCommitments`), not\n * the submitted digest. Returns null if the calendar has nothing yet.\n *\n * OTS calendar HTTP API: GET <url>/timestamp/<hex(commitment)>, returns a\n * timestamp rooted at the commitment, or 404.\n */\n fetchProof(commitment: Uint8Array, signal?: AbortSignal): Promise<Uint8Array | null>;\n}\n\nexport interface AnchorVerificationInput {\n /** Raw OTS proof bytes (base64-decoded by the caller). */\n proofBytes: Uint8Array;\n /** 32-byte digest that the proof commits to. */\n digest: Uint8Array;\n /** Declared block height from the envelope. */\n blockHeight: number;\n /** Declared block hash (hex) from the envelope. */\n blockHash: string;\n /**\n * Optional block header source. If provided, the verifier uses this to\n * fetch the header at `blockHeight` and compare its Merkle root to the\n * one derived from walking the proof.\n *\n * If omitted, the verifier MAY still parse the proof and report\n * structural validity but CANNOT report a bound anchor.\n */\n headerSource?: BlockHeaderSource;\n}\n\nexport interface BlockHeaderSource {\n /**\n * The 80-byte raw block header at the given height, or null when there is\n * no block at that height. Throw when the header could not be read: a\n * failed lookup must never read as a missing block.\n */\n getHeaderAt(height: number): Promise<Uint8Array | null>;\n}\n\nexport type AnchorVerifier = (input: AnchorVerificationInput) => Promise<AnchorVerificationResult>;\n\nexport type AnchorVerificationResult =\n | { ok: true; merkleRoot: string }\n | { ok: false; reason: string };\n\n/**\n * Convert an OtsProof (library type) to the StampOts field shape that the\n * envelope carries. The two are isomorphic; this function exists to keep\n * stamp-core's type surface narrow.\n */\nexport function toStampOts(p: OtsProof): StampOts {\n return {\n status: p.status,\n proof: p.proof,\n calendars: p.calendars,\n block_height: p.blockHeight,\n block_hash: p.blockHash,\n upgraded_at: p.upgradedAt,\n };\n}\n\nexport function fromStampOts(s: StampOts): OtsProof {\n return {\n status: s.status,\n proof: s.proof,\n calendars: s.calendars,\n blockHeight: s.block_height,\n blockHash: s.block_hash,\n upgradedAt: s.upgraded_at,\n };\n}\n","// Minimal, dependency-free base64 <-> Uint8Array helpers. OTS proof bytes\n// are carried as base64 inside OC Stamp envelopes so they survive any text\n// transport (URL fragment, JSON, Nostr event content).\n\nconst B64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\nconst B64_DECODE_TABLE = (() => {\n const t = new Int16Array(128).fill(-1);\n for (let i = 0; i < B64_CHARS.length; i++) t[B64_CHARS.charCodeAt(i)] = i;\n t['='.charCodeAt(0)] = -2;\n return t;\n})();\n\nexport function base64Encode(bytes: Uint8Array): string {\n let out = '';\n let i = 0;\n for (; i + 2 < bytes.length; i += 3) {\n const a = bytes[i]!;\n const b = bytes[i + 1]!;\n const c = bytes[i + 2]!;\n out +=\n B64_CHARS[a >> 2]! +\n B64_CHARS[((a & 0x03) << 4) | (b >> 4)]! +\n B64_CHARS[((b & 0x0f) << 2) | (c >> 6)]! +\n B64_CHARS[c & 0x3f]!;\n }\n if (i < bytes.length) {\n const a = bytes[i]!;\n const b = i + 1 < bytes.length ? bytes[i + 1]! : 0;\n out += B64_CHARS[a >> 2]!;\n out += B64_CHARS[((a & 0x03) << 4) | (b >> 4)]!;\n out += i + 1 < bytes.length ? B64_CHARS[(b & 0x0f) << 2]! : '=';\n out += '=';\n }\n return out;\n}\n\nexport function base64Decode(s: string): Uint8Array {\n const str = s.replace(/\\s+/g, '');\n const len = str.length;\n if (len === 0) return new Uint8Array(0);\n if (len % 4 !== 0) throw new Error('base64: bad length');\n let padding = 0;\n if (str[len - 1] === '=') padding++;\n if (str[len - 2] === '=') padding++;\n const outLen = (len / 4) * 3 - padding;\n const out = new Uint8Array(outLen);\n let o = 0;\n for (let i = 0; i < len; i += 4) {\n const c0 = B64_DECODE_TABLE[str.charCodeAt(i)]!;\n const c1 = B64_DECODE_TABLE[str.charCodeAt(i + 1)]!;\n const c2 = B64_DECODE_TABLE[str.charCodeAt(i + 2)]!;\n const c3 = B64_DECODE_TABLE[str.charCodeAt(i + 3)]!;\n if (c0 < 0 || c1 < 0 || c2 < -2 || c3 < -2) throw new Error('base64: bad char');\n out[o++] = (c0 << 2) | (c1 >> 4);\n if (c2 >= 0) out[o++] = ((c1 & 0x0f) << 4) | (c2 >> 2);\n if (c3 >= 0) out[o++] = ((c2 & 0x03) << 6) | c3;\n }\n return out;\n}\n\nexport function hexDecode(s: string): Uint8Array {\n if (s.length % 2 !== 0) throw new Error('hex: odd length');\n const out = new Uint8Array(s.length / 2);\n for (let i = 0; i < out.length; i++) {\n const hi = parseInt(s[i * 2]!, 16);\n const lo = parseInt(s[i * 2 + 1]!, 16);\n if (Number.isNaN(hi) || Number.isNaN(lo)) throw new Error('hex: bad char');\n out[i] = (hi << 4) | lo;\n }\n return out;\n}\n\nexport function hexEncode(bytes: Uint8Array): string {\n const HEX = '0123456789abcdef';\n let out = '';\n for (let i = 0; i < bytes.length; i++) {\n const b = bytes[i]!;\n out += HEX[(b >> 4) & 0x0f]! + HEX[b & 0x0f]!;\n }\n return out;\n}\n","// HTTP client for an OpenTimestamps calendar. Implements the minimal subset\n// of the calendar protocol that an OC Stamp implementation needs:\n//\n// POST <url>/digest body = raw digest bytes -> pending proof bytes\n// GET <url>/timestamp/<hex(commitment)> -> continuation, or 404\n//\n// The client moves bytes only; ./ots.ts parses them.\n\nimport type { CalendarClient } from './types.js';\nimport { hexEncode } from './base64.js';\n\nexport const DEFAULT_CALENDARS: readonly string[] = [\n 'https://alice.btc.calendar.opentimestamps.org',\n 'https://bob.btc.calendar.opentimestamps.org',\n 'https://finney.calendar.eternitywall.com',\n];\n\nexport interface HttpCalendarOptions {\n /**\n * Custom fetch implementation. Defaults to global `fetch`. Useful in\n * environments that need a specific adapter (Node < 18, Cloudflare\n * Workers, proxies).\n */\n fetch?: typeof fetch;\n /** Request timeout in milliseconds. Default 30_000. */\n timeoutMs?: number;\n}\n\nexport function createCalendarClient(url: string, opts: HttpCalendarOptions = {}): CalendarClient {\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (typeof fetchImpl !== 'function') {\n throw new Error(\n '@orangecheck/stamp-ots: no fetch implementation available. Pass one via { fetch }.'\n );\n }\n const timeoutMs = opts.timeoutMs ?? 30_000;\n const base = url.replace(/\\/$/, '');\n\n return {\n url: base,\n async submit(digest, signal) {\n if (digest.byteLength !== 32) {\n throw new Error('OTS: digest must be exactly 32 bytes');\n }\n const ac = withTimeout(signal, timeoutMs);\n // Uint8Array is a valid fetch body at runtime in Node 18+ and all\n // modern browsers, but TypeScript's DOM typings don't accept it\n // directly under `strict` + `noUncheckedIndexedAccess`. The cast is\n // narrow and intentional.\n // No Content-Type: a non-safelisted type makes browsers send a\n // CORS preflight, and OTS calendars answer OPTIONS with 501.\n const resp = await fetchImpl(`${base}/digest`, {\n method: 'POST',\n body: digest as unknown as BodyInit,\n signal: ac.signal,\n });\n ac.clear();\n if (!resp.ok) {\n throw new Error(`OTS calendar ${base} submit failed: HTTP ${resp.status}`);\n }\n const buf = await resp.arrayBuffer();\n return new Uint8Array(buf);\n },\n async fetchProof(commitment, signal) {\n if (commitment.byteLength === 0 || commitment.byteLength > 64) {\n throw new Error('OTS: commitment must be 1-64 bytes');\n }\n const ac = withTimeout(signal, timeoutMs);\n const resp = await fetchImpl(`${base}/timestamp/${hexEncode(commitment)}`, {\n method: 'GET',\n headers: { Accept: 'application/vnd.opentimestamps.v1' },\n signal: ac.signal,\n });\n ac.clear();\n if (resp.status === 404) return null;\n if (!resp.ok) {\n throw new Error(`OTS calendar ${base} fetchProof failed: HTTP ${resp.status}`);\n }\n const buf = await resp.arrayBuffer();\n return new Uint8Array(buf);\n },\n };\n}\n\nfunction withTimeout(parent: AbortSignal | undefined, ms: number): { signal: AbortSignal; clear: () => void } {\n const ac = new AbortController();\n const onParent = () => ac.abort((parent as AbortSignal & { reason?: unknown }).reason);\n if (parent) {\n if (parent.aborted) ac.abort((parent as AbortSignal & { reason?: unknown }).reason);\n else parent.addEventListener('abort', onParent, { once: true });\n }\n const t = setTimeout(() => ac.abort(new Error(`OTS request timed out after ${ms}ms`)), ms);\n return {\n signal: ac.signal,\n clear: () => {\n clearTimeout(t);\n if (parent) parent.removeEventListener('abort', onParent);\n },\n };\n}\n","// OpenTimestamps proof format: parse, walk, serialize, merge.\n//\n// Follows python-opentimestamps (core/timestamp.py, core/op.py,\n// core/notary.py). Two encodings are accepted:\n//\n// - a bare timestamp rooted at the digest (what an OTS calendar returns from\n// POST /digest, and what OC Stamp envelopes carry in `ots.proof`);\n// - a detached `.ots` file (magic header + file-hash op + digest + timestamp).\n\nimport { ripemd160, sha1 } from '@noble/hashes/legacy';\nimport { sha256 } from '@noble/hashes/sha2';\nimport { keccak_256 } from '@noble/hashes/sha3';\n\nimport { hexEncode } from './base64.js';\n\nconst HEADER_MAGIC = new Uint8Array([\n 0x00, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x00,\n 0x00, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0xbf, 0x89, 0xe2, 0xe8, 0x84, 0xe8, 0x92, 0x94,\n]);\n\nconst TAG_BITCOIN = '0588960d73d71901';\nconst TAG_PENDING = '83dfe30d2ef90c8e';\n\nconst MAX_DEPTH = 256;\nconst MAX_MSG = 4096;\n\nexport type OtsOp =\n | { kind: 'sha256' | 'ripemd160' | 'sha1' | 'keccak256' | 'reverse' | 'hexlify' }\n | { kind: 'append' | 'prepend'; arg: Uint8Array };\n\nexport type OtsAttestation =\n | { kind: 'bitcoin'; height: number }\n | { kind: 'pending'; uri: string }\n | { kind: 'unknown'; tag: string; payload: Uint8Array };\n\nexport interface OtsTimestamp {\n /** The message at this node: the digest after every op on the path to it. */\n msg: Uint8Array;\n attestations: OtsAttestation[];\n ops: { op: OtsOp; child: OtsTimestamp }[];\n}\n\nclass Reader {\n private pos = 0;\n constructor(private readonly buf: Uint8Array) {}\n byte(): number {\n if (this.pos >= this.buf.length) throw new Error('ots: unexpected end of proof');\n return this.buf[this.pos++]!;\n }\n bytes(n: number): Uint8Array {\n if (n < 0 || this.pos + n > this.buf.length) throw new Error('ots: unexpected end of proof');\n const out = this.buf.subarray(this.pos, this.pos + n);\n this.pos += n;\n return out;\n }\n varuint(): number {\n let value = 0;\n let shift = 0;\n for (;;) {\n const b = this.byte();\n value += (b & 0x7f) * 2 ** shift;\n if (!(b & 0x80)) return value;\n shift += 7;\n if (shift > 49) throw new Error('ots: varuint too large');\n }\n }\n varbytes(max: number): Uint8Array {\n const n = this.varuint();\n if (n > max) throw new Error('ots: varbytes too long');\n return this.bytes(n);\n }\n get done(): boolean {\n return this.pos === this.buf.length;\n }\n}\n\nconst UNARY: Record<number, OtsOp['kind']> = {\n 0x02: 'sha1',\n 0x03: 'ripemd160',\n 0x08: 'sha256',\n 0x67: 'keccak256',\n 0xf2: 'reverse',\n 0xf3: 'hexlify',\n};\n\nexport function applyOp(op: OtsOp, msg: Uint8Array): Uint8Array {\n switch (op.kind) {\n case 'sha256':\n return sha256(msg);\n case 'ripemd160':\n return ripemd160(msg);\n case 'sha1':\n return sha1(msg);\n case 'keccak256':\n return keccak_256(msg);\n case 'reverse':\n return new Uint8Array(msg).reverse();\n case 'hexlify':\n return new TextEncoder().encode(hexEncode(msg));\n case 'append':\n return concat(msg, op.arg);\n case 'prepend':\n return concat(op.arg, msg);\n }\n}\n\nfunction readOp(r: Reader, tag: number): OtsOp {\n const unary = UNARY[tag];\n if (unary) return { kind: unary } as OtsOp;\n if (tag === 0xf0) return { kind: 'append', arg: r.varbytes(MAX_MSG) };\n if (tag === 0xf1) return { kind: 'prepend', arg: r.varbytes(MAX_MSG) };\n throw new Error(`ots: unknown op tag 0x${tag.toString(16)}`);\n}\n\nfunction readAttestation(r: Reader): OtsAttestation {\n const tag = hexEncode(r.bytes(8));\n const payload = r.varbytes(8192);\n const p = new Reader(payload);\n if (tag === TAG_BITCOIN) return { kind: 'bitcoin', height: p.varuint() };\n if (tag === TAG_PENDING) return { kind: 'pending', uri: new TextDecoder().decode(p.varbytes(1000)) };\n return { kind: 'unknown', tag, payload };\n}\n\nfunction readTimestamp(r: Reader, msg: Uint8Array, depth: number): OtsTimestamp {\n if (depth > MAX_DEPTH) throw new Error('ots: proof too deep');\n const node: OtsTimestamp = { msg, attestations: [], ops: [] };\n const item = (tag: number) => {\n if (tag === 0x00) {\n node.attestations.push(readAttestation(r));\n return;\n }\n const op = readOp(r, tag);\n const next = applyOp(op, msg);\n if (next.length > MAX_MSG) throw new Error('ots: message too long');\n node.ops.push({ op, child: readTimestamp(r, next, depth + 1) });\n };\n let tag = r.byte();\n while (tag === 0xff) {\n item(r.byte());\n tag = r.byte();\n }\n item(tag);\n return node;\n}\n\n/** Parse a bare timestamp whose root message is `digest`. */\nexport function parseTimestamp(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp {\n const r = new Reader(bytes);\n const ts = readTimestamp(r, digest, 0);\n if (!r.done) throw new Error('ots: trailing bytes after timestamp');\n return ts;\n}\n\nexport function isDetached(bytes: Uint8Array): boolean {\n return bytes.length > HEADER_MAGIC.length && bytesEqual(bytes.subarray(0, HEADER_MAGIC.length), HEADER_MAGIC);\n}\n\n/** Parse a detached `.ots` file. Only sha256 file digests are accepted. */\nexport function parseDetached(bytes: Uint8Array): { digest: Uint8Array; timestamp: OtsTimestamp } {\n if (!isDetached(bytes)) throw new Error('ots: missing detached-file header');\n const r = new Reader(bytes.subarray(HEADER_MAGIC.length));\n const major = r.varuint();\n if (major !== 1) throw new Error(`ots: unsupported file version ${major}`);\n if (r.byte() !== 0x08) throw new Error('ots: only sha256 file digests are supported');\n const digest = new Uint8Array(r.bytes(32));\n const timestamp = readTimestamp(r, digest, 0);\n if (!r.done) throw new Error('ots: trailing bytes after timestamp');\n return { digest, timestamp };\n}\n\n/**\n * Parse either encoding and require that it commits to `digest`. A detached\n * file for some other digest is rejected rather than walked.\n */\nexport function parseProof(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp {\n if (!isDetached(bytes)) return parseTimestamp(bytes, digest);\n const d = parseDetached(bytes);\n if (!bytesEqual(d.digest, digest)) throw new Error('ots: proof commits to a different digest');\n return d.timestamp;\n}\n\n/** Every attestation in the tree with the message it attests to. */\nexport function attestations(ts: OtsTimestamp): { msg: Uint8Array; attestation: OtsAttestation }[] {\n const out: { msg: Uint8Array; attestation: OtsAttestation }[] = [];\n const walk = (n: OtsTimestamp) => {\n for (const a of n.attestations) out.push({ msg: n.msg, attestation: a });\n for (const { child } of n.ops) walk(child);\n };\n walk(ts);\n return out;\n}\n\n/**\n * Bitcoin attestations, lowest height first. `merkleRoot` is the message at\n * the attestation, which equals the block header's Merkle root in header\n * byte order.\n */\nexport function bitcoinAnchors(ts: OtsTimestamp): { blockHeight: number; merkleRoot: Uint8Array }[] {\n return attestations(ts)\n .flatMap(({ msg, attestation }) =>\n attestation.kind === 'bitcoin' ? [{ blockHeight: attestation.height, merkleRoot: msg }] : []\n )\n .sort((a, b) => a.blockHeight - b.blockHeight);\n}\n\n/** Pending calendar attestations: where to ask, and the commitment to ask for. */\nexport function pendingCommitments(ts: OtsTimestamp): { uri: string; commitment: Uint8Array }[] {\n return attestations(ts).flatMap(({ msg, attestation }) =>\n attestation.kind === 'pending' ? [{ uri: attestation.uri, commitment: msg }] : []\n );\n}\n\n/**\n * Graft `upgrade` (a timestamp rooted at some node's message) onto the node\n * with that message, as python-opentimestamps' Timestamp.merge does. Returns\n * false when no node carries that message.\n */\nexport function mergeAt(ts: OtsTimestamp, upgrade: OtsTimestamp): boolean {\n if (bytesEqual(ts.msg, upgrade.msg)) {\n for (const a of upgrade.attestations) {\n if (!ts.attestations.some((b) => attestationKey(b) === attestationKey(a))) ts.attestations.push(a);\n }\n for (const { op, child } of upgrade.ops) {\n const same = ts.ops.find((o) => opKey(o.op) === opKey(op));\n if (same) mergeAt(same.child, child);\n else ts.ops.push({ op, child });\n }\n return true;\n }\n return ts.ops.some(({ child }) => mergeAt(child, upgrade));\n}\n\nfunction writeVaruint(out: number[], n: number) {\n do {\n let b = n % 128;\n n = Math.floor(n / 128);\n if (n > 0) b |= 0x80;\n out.push(b);\n } while (n > 0);\n}\n\nfunction writeVarbytes(out: number[], bytes: Uint8Array) {\n writeVaruint(out, bytes.length);\n out.push(...bytes);\n}\n\nconst OP_TAG: Record<OtsOp['kind'], number> = {\n sha1: 0x02,\n ripemd160: 0x03,\n sha256: 0x08,\n keccak256: 0x67,\n append: 0xf0,\n prepend: 0xf1,\n reverse: 0xf2,\n hexlify: 0xf3,\n};\n\nfunction writeAttestation(out: number[], a: OtsAttestation) {\n const payload: number[] = [];\n let tag: string;\n if (a.kind === 'bitcoin') {\n tag = TAG_BITCOIN;\n writeVaruint(payload, a.height);\n } else if (a.kind === 'pending') {\n tag = TAG_PENDING;\n writeVarbytes(payload, new TextEncoder().encode(a.uri));\n } else {\n tag = a.tag;\n payload.push(...a.payload);\n }\n out.push(0x00);\n for (let i = 0; i < 16; i += 2) out.push(parseInt(tag.slice(i, i + 2), 16));\n writeVarbytes(out, new Uint8Array(payload));\n}\n\nfunction writeTimestamp(out: number[], ts: OtsTimestamp) {\n const items: (() => void)[] = [\n ...ts.attestations.map((a) => () => writeAttestation(out, a)),\n ...ts.ops.map(({ op, child }) => () => {\n out.push(OP_TAG[op.kind]);\n if (op.kind === 'append' || op.kind === 'prepend') writeVarbytes(out, op.arg);\n writeTimestamp(out, child);\n }),\n ];\n if (items.length === 0) throw new Error('ots: cannot serialize an empty timestamp node');\n items.forEach((write, i) => {\n if (i < items.length - 1) out.push(0xff);\n write();\n });\n}\n\n/** Serialize as a bare timestamp (the encoding carried in `ots.proof`). */\nexport function serializeTimestamp(ts: OtsTimestamp): Uint8Array {\n const out: number[] = [];\n writeTimestamp(out, ts);\n return new Uint8Array(out);\n}\n\nfunction attestationKey(a: OtsAttestation): string {\n if (a.kind === 'bitcoin') return `b:${a.height}`;\n if (a.kind === 'pending') return `p:${a.uri}`;\n return `u:${a.tag}:${hexEncode(a.payload)}`;\n}\n\nfunction opKey(op: OtsOp): string {\n return 'arg' in op ? `${op.kind}:${hexEncode(op.arg)}` : op.kind;\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n}\n\nexport function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.byteLength !== b.byteLength) return false;\n for (let i = 0; i < a.byteLength; i++) if (a[i] !== b[i]) return false;\n return true;\n}\n","// Submit an envelope id to one or more OTS calendars. Returns a pending proof.\n// See SPEC.md §6.1.\n//\n// The submission strategy: try each calendar in parallel and keep every\n// receipt. A stamp that only reaches one calendar is a single point of failure\n// for upgrade, so by default two must answer (SPEC §6.1's SHOULD).\n\nimport { base64Encode, hexDecode } from './base64.js';\nimport { createCalendarClient, DEFAULT_CALENDARS } from './calendar.js';\nimport { mergeAt, parseTimestamp, serializeTimestamp, type OtsTimestamp } from './ots.js';\nimport type { CalendarClient, OtsProof } from './types.js';\n\nexport interface SubmitOptions {\n /**\n * Calendars to submit to. Defaults to DEFAULT_CALENDARS. Can be strings\n * (URLs) or pre-built CalendarClient instances.\n */\n calendars?: readonly (string | CalendarClient)[];\n /**\n * Minimum number of calendars that must answer with a readable receipt.\n * Defaults to 2, as SPEC §6.1 recommends, or to the number of calendars\n * when fewer are given. If fewer answer, submitToCalendars throws.\n */\n minSuccesses?: number;\n /** Optional custom fetch passed through to calendar clients. */\n fetch?: typeof fetch;\n /** Request timeout per calendar. Default 30_000ms. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\n/**\n * Submit the envelope `id` (64-hex) to OTS calendars and return an OtsProof in\n * pending state. The caller merges this into the envelope's `ots` field.\n *\n * Each calendar answers with its own pending timestamp for the digest. They are\n * merged into one proof, so upgrade (see upgrade.ts) can ask any calendar that\n * answered. A calendar whose answer does not parse counts as a failure.\n */\nexport async function submitToCalendars(idHex: string, opts: SubmitOptions = {}): Promise<OtsProof> {\n const digest = hexDecode(idHex);\n if (digest.byteLength !== 32) {\n throw new Error('submitToCalendars: idHex must be 32 bytes (64 hex chars)');\n }\n\n const clients = (opts.calendars ?? DEFAULT_CALENDARS).map((c) =>\n typeof c === 'string'\n ? createCalendarClient(c, { fetch: opts.fetch, timeoutMs: opts.timeoutMs })\n : c\n );\n if (clients.length === 0) {\n throw new Error('submitToCalendars: at least one calendar is required');\n }\n const minSuccesses = Math.max(1, opts.minSuccesses ?? Math.min(2, clients.length));\n\n const settled = await Promise.allSettled(\n clients.map(async (c) => {\n const proof = await c.submit(digest, opts.signal);\n return { url: c.url, proof };\n })\n );\n const successes = settled\n .filter((r): r is PromiseFulfilledResult<{ url: string; proof: Uint8Array }> => r.status === 'fulfilled')\n .map((r) => r.value);\n const failures = settled\n .filter((r): r is PromiseRejectedResult => r.status === 'rejected')\n .map((r) => (r.reason instanceof Error ? r.reason.message : String(r.reason)));\n\n if (successes.length < minSuccesses) {\n // AggregateError would be nicer but targets ES2021; Error keeps us at ES2020.\n const msg = `OTS submission did not reach ${minSuccesses} calendar(s). Errors: ${failures.join('; ')}`;\n const err = new Error(msg) as Error & { errors: string[] };\n err.errors = failures;\n throw err;\n }\n\n // Keep every calendar's receipt in one proof, so any of them can upgrade it.\n let tree: OtsTimestamp | null = null;\n const merged: string[] = [];\n for (const s of successes) {\n let receipt: OtsTimestamp;\n try {\n receipt = parseTimestamp(s.proof, digest);\n } catch (e) {\n failures.push(`${s.url}: unreadable proof (${e instanceof Error ? e.message : String(e)})`);\n continue;\n }\n if (tree) mergeAt(tree, receipt);\n else tree = receipt;\n merged.push(s.url);\n }\n if (!tree || merged.length < minSuccesses) {\n const msg = `OTS submission did not reach ${minSuccesses} calendar(s). Errors: ${failures.join('; ')}`;\n const err = new Error(msg) as Error & { errors: string[] };\n err.errors = failures;\n throw err;\n }\n return {\n status: 'pending',\n proof: base64Encode(serializeTimestamp(tree)),\n calendars: merged,\n blockHeight: null,\n blockHash: null,\n upgradedAt: null,\n };\n}\n","// Anchor verification. See SPEC.md §6.3.\n//\n// A confirmed anchor holds when all three are true:\n// 1. the proof commits to the envelope id and walks to a Bitcoin\n// attestation at the declared height;\n// 2. the message at that attestation equals the Merkle root in the block\n// header at that height;\n// 3. that header double-SHA256es to the declared block hash.\n//\n// The resulting function is what `@orangecheck/stamp-core` expects at the\n// `verifyOtsAnchor` input of `verify()`.\n\nimport { sha256 } from '@noble/hashes/sha2';\n\nimport { base64Decode, hexDecode, hexEncode } from './base64.js';\nimport { bitcoinAnchors, bytesEqual, parseProof } from './ots.js';\nimport type {\n AnchorVerificationInput,\n AnchorVerificationResult,\n AnchorVerifier,\n BlockHeaderSource,\n} from './types.js';\n\nexport interface AnchorVerifierConfig {\n /**\n * Parse the proof bytes and return the Merkle root the proof walks to,\n * plus its block height. Optional: the built-in OTS parser is used when\n * omitted. `blockHeight` is the declared height, for proofs that carry\n * attestations at more than one height.\n */\n walkProof?: (input: {\n proofBytes: Uint8Array;\n digest: Uint8Array;\n blockHeight?: number;\n }) => Promise<{ merkleRoot: Uint8Array; blockHeight: number } | null>;\n /**\n * Source of Bitcoin block headers: a full node, SPV, a headers snapshot,\n * or `mempoolHeaderSource()`. This is the verifier's trust anchor.\n */\n headerSource: BlockHeaderSource;\n}\n\n/** Built-in walker: parse the OTS proof and pick the Bitcoin attestation. */\nexport async function walkOtsProof(input: {\n proofBytes: Uint8Array;\n digest: Uint8Array;\n blockHeight?: number;\n}): Promise<{ merkleRoot: Uint8Array; blockHeight: number } | null> {\n try {\n const anchors = bitcoinAnchors(parseProof(input.proofBytes, input.digest));\n return anchors.find((a) => a.blockHeight === input.blockHeight) ?? anchors[0] ?? null;\n } catch {\n return null;\n }\n}\n\n/** Block hash (display hex) of an 80-byte header. */\nexport function blockHashOf(header: Uint8Array): string {\n return hexEncode(sha256(sha256(header)).reverse());\n}\n\nexport function makeAnchorVerifier(\n cfg: AnchorVerifierConfig\n): (proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean> {\n const walkProof = cfg.walkProof ?? walkOtsProof;\n const verifier: AnchorVerifier = async (\n input: AnchorVerificationInput\n ): Promise<AnchorVerificationResult> => {\n const walked = await walkProof({\n proofBytes: input.proofBytes,\n digest: input.digest,\n blockHeight: input.blockHeight,\n });\n if (!walked) {\n return { ok: false, reason: 'proof could not be walked to a Bitcoin commitment' };\n }\n if (walked.blockHeight !== input.blockHeight) {\n return {\n ok: false,\n reason: `proof anchors at block ${walked.blockHeight}, envelope declares ${input.blockHeight}`,\n };\n }\n const header = await cfg.headerSource.getHeaderAt(input.blockHeight);\n if (!header || header.byteLength !== 80) {\n return { ok: false, reason: `no block header available at height ${input.blockHeight}` };\n }\n if (blockHashOf(header) !== input.blockHash.toLowerCase()) {\n return { ok: false, reason: 'block header does not hash to the declared block hash' };\n }\n // OTS attests to the Merkle root in header byte order (offset 36).\n const headerMerkle = header.subarray(36, 68);\n if (!bytesEqual(headerMerkle, walked.merkleRoot)) {\n return { ok: false, reason: 'block header Merkle root does not match walked proof root' };\n }\n return { ok: true, merkleRoot: hexEncode(headerMerkle) };\n };\n\n // Resolves false for a decided no. Throws only when the check could not be made\n // (the header source did not answer), which stamp-core reports as unchecked.\n return async (proofB64, blockHeight, blockHash, envelopeId) => {\n let proofBytes: Uint8Array;\n let digest: Uint8Array;\n try {\n proofBytes = base64Decode(proofB64);\n digest = hexDecode(envelopeId);\n } catch {\n return false;\n }\n const r = await verifier({ proofBytes, digest, blockHeight, blockHash });\n return r.ok;\n };\n}\n\n/**\n * Anchor verifier using the built-in OTS parser. Kept async for callers of the\n * 0.1 API, which lazily loaded an optional parser here.\n */\nexport async function makeDefaultAnchorVerifier(opts: {\n headerSource: BlockHeaderSource;\n}): Promise<\n (proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean>\n> {\n return makeAnchorVerifier({ headerSource: opts.headerSource });\n}\n\nexport interface MempoolHeaderSourceOptions {\n /** Esplora-compatible API base. Default https://mempool.space/api. */\n baseUrl?: string;\n fetch?: typeof fetch;\n /** Per request: a lookup that has not answered by then throws, as unread. Default 15_000ms. */\n timeoutMs?: number;\n}\n\n/**\n * Block headers from an Esplora-compatible API. The verifier checks each\n * header against the declared block hash, so this source is trusted only to\n * report which block is at a height.\n */\nexport function mempoolHeaderSource(opts: MempoolHeaderSourceOptions = {}): BlockHeaderSource {\n const base = (opts.baseUrl ?? 'https://mempool.space/api').replace(/\\/+$/, '');\n const fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);\n const timeoutMs = opts.timeoutMs ?? 15_000;\n // Null only when the explorer says there is no such block (404). Any other\n // failure throws: a header that could not be read is not a missing block,\n // and neither is an explorer that never answers.\n const read = async (url: string, shape: RegExp): Promise<string | null> => {\n const r = await fetchImpl(url, { signal: AbortSignal.timeout(timeoutMs) });\n if (r.status === 404) return null;\n if (!r.ok) throw new Error(`header lookup failed: HTTP ${r.status} from ${url}`);\n const text = (await r.text()).trim();\n if (!shape.test(text)) throw new Error(`header lookup failed: unexpected answer from ${url}`);\n return text;\n };\n return {\n async getHeaderAt(height) {\n const hash = await read(`${base}/block-height/${height}`, /^[0-9a-f]{64}$/);\n if (hash === null) return null;\n const hex = await read(`${base}/block/${hash}/header`, /^[0-9a-f]{160}$/);\n return hex === null ? null : hexDecode(hex);\n },\n };\n}\n","// Upgrade a pending OTS proof to a confirmed one. See SPEC.md §6.2.\n//\n// A pending proof ends in calendar attestations, each naming a calendar and\n// the commitment (the message at that leaf) the calendar will later anchor.\n// Calendars index upgrades by that commitment, not by the submitted digest.\n// For each pending leaf we ask its calendar for the continuation, graft it on,\n// and report the proof as confirmed once it reaches a Bitcoin attestation\n// whose block header checks out. A calendar's 404 is its \"not yet\"; when no\n// calendar answers at all, nothing is concluded and the upgrade throws.\n\nimport { blockHashOf } from './anchor.js';\nimport { base64Decode, base64Encode, hexDecode } from './base64.js';\nimport { createCalendarClient } from './calendar.js';\nimport {\n bitcoinAnchors,\n bytesEqual,\n mergeAt,\n parseProof,\n parseTimestamp,\n pendingCommitments,\n serializeTimestamp,\n} from './ots.js';\nimport type { BlockHeaderSource, OtsProof } from './types.js';\n\nexport interface UpgradeOptions {\n /**\n * Where block headers come from (`mempoolHeaderSource()`, your node, or a\n * headers snapshot). Required: the proof is reported `confirmed` only when\n * the header at its attested height has the proof's Merkle root, and that\n * header gives `blockHash`. Until such a header is found the proof stays\n * `pending`, with whatever the calendars added merged in.\n */\n headerSource: BlockHeaderSource;\n /** Optional custom fetch passed through to calendar clients. */\n fetch?: typeof fetch;\n /** Request timeout per calendar. Default 30_000ms. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\nconst norm = (u: string) => u.replace(/\\/+$/, '');\n\n/**\n * No calendar a pending proof names answered, so nothing was learned: the\n * proof may be anchored already. Thrown by `upgradeProof` instead of\n * returning the proof as still `pending`.\n */\nexport class CalendarsUnreadError extends Error {\n constructor(\n /** The calendars asked, with why each did not answer. */\n readonly failures: { calendar: string; reason: string }[]\n ) {\n super(\n `OTS: no calendar answered (${failures.map((f) => `${f.calendar}: ${f.reason}`).join('; ')})`\n );\n this.name = 'CalendarsUnreadError';\n }\n}\n\nexport async function upgradeProof(\n current: OtsProof,\n idHex: string,\n opts: UpgradeOptions\n): Promise<OtsProof> {\n if (current.status === 'confirmed') return current; // idempotent\n if (!opts?.headerSource) {\n throw new Error('upgradeProof: pass headerSource; a proof is confirmed only against a block header');\n }\n\n const before = base64Decode(current.proof);\n const tree = parseProof(before, hexDecode(idHex));\n\n // Only ask calendars this proof was submitted to.\n const listed = new Set(current.calendars.map(norm));\n const pending = pendingCommitments(tree).filter((p) => listed.has(norm(p.uri)));\n if (pending.length === 0 && bitcoinAnchors(tree).length === 0) {\n throw new Error('upgradeProof: proof has no pending attestation from a listed calendar');\n }\n\n const answered: string[] = [];\n const settled = await Promise.allSettled(\n pending.map(async ({ uri, commitment }) => {\n const client = createCalendarClient(uri, { fetch: opts.fetch, timeoutMs: opts.timeoutMs });\n const bytes = await client.fetchProof(commitment, opts.signal);\n if (!bytes) return;\n if (mergeAt(tree, parseTimestamp(bytes, commitment))) answered.push(norm(uri));\n })\n );\n\n const merged = serializeTimestamp(tree);\n const anchor = await resolveAnchor(tree, opts.headerSource);\n if (!anchor && pending.length > 0 && settled.every((r) => r.status === 'rejected')) {\n throw new CalendarsUnreadError(\n pending.map(({ uri }, i) => ({\n calendar: norm(uri),\n reason: String((settled[i] as PromiseRejectedResult).reason?.message ?? settled[i]),\n }))\n );\n }\n const calendars = [...answered, ...current.calendars.filter((c) => !answered.includes(norm(c)))];\n\n if (anchor) {\n return {\n status: 'confirmed',\n proof: base64Encode(merged),\n calendars,\n blockHeight: anchor.blockHeight,\n blockHash: anchor.blockHash,\n upgradedAt: new Date().toISOString().replace(/\\.\\d+Z$/, 'Z'),\n };\n }\n if (!bytesEqual(merged, before)) {\n return { ...current, proof: base64Encode(merged), calendars };\n }\n return current;\n}\n\n/**\n * The lowest Bitcoin block a proof anchors `idHex` in, checked against\n * `headerSource`: the proof is walked from `idHex`, and an attestation counts\n * only if the header at its height has the proof's Merkle root. Whatever\n * height or status the stamp declares is not read. Null when no attestation\n * checks out, or the proof does not parse from `idHex`.\n */\nexport async function verifiedAnchor(\n proofB64: string,\n idHex: string,\n headerSource: BlockHeaderSource\n): Promise<{ blockHeight: number; blockHash: string } | null> {\n let tree: ReturnType<typeof parseTimestamp>;\n try {\n tree = parseProof(base64Decode(proofB64), hexDecode(idHex));\n } catch {\n return null;\n }\n return resolveAnchor(tree, headerSource);\n}\n\nasync function resolveAnchor(\n tree: ReturnType<typeof parseTimestamp>,\n headers: BlockHeaderSource\n): Promise<{ blockHeight: number; blockHash: string } | null> {\n for (const a of bitcoinAnchors(tree)) {\n const header = await headers.getHeaderAt(a.blockHeight);\n if (header && header.byteLength === 80 && bytesEqual(header.subarray(36, 68), a.merkleRoot)) {\n return { blockHeight: a.blockHeight, blockHash: blockHashOf(header) };\n }\n }\n return null;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orangecheck/stamp-ots",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "OpenTimestamps calendar client, proof helpers, and anchor-verification hooks for OC Stamp envelopes. See https://github.com/orangecheck/oc-stamp-protocol.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bitcoin",
|
package/src/anchor.test.ts
CHANGED
|
@@ -49,6 +49,21 @@ describe('makeAnchorVerifier with the built-in OTS parser', () => {
|
|
|
49
49
|
expect(await v(BARE_B64, BLOCK_HEIGHT, blockHashOf(hexDecode(altered)), HELLO_DIGEST)).toBe(false);
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
+
it('answers no for a proof or id that is not even encoded right', async () => {
|
|
53
|
+
expect(await verify('not base64!', BLOCK_HEIGHT, BLOCK_HASH, HELLO_DIGEST)).toBe(false);
|
|
54
|
+
expect(await verify(BARE_B64, BLOCK_HEIGHT, BLOCK_HASH, 'xyz')).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('throws, rather than answering no, when the header source does not answer', async () => {
|
|
58
|
+
// mempoolHeaderSource on a 503: the check could not be made, so stamp-core
|
|
59
|
+
// reports the anchor as unchecked, never as E_BAD_ANCHOR.
|
|
60
|
+
const down = mempoolHeaderSource({
|
|
61
|
+
fetch: (async () => new Response('down', { status: 503 })) as unknown as typeof fetch,
|
|
62
|
+
});
|
|
63
|
+
const v = makeAnchorVerifier({ headerSource: down });
|
|
64
|
+
await expect(v(BARE_B64, BLOCK_HEIGHT, BLOCK_HASH, HELLO_DIGEST)).rejects.toThrow(/HTTP 503/);
|
|
65
|
+
});
|
|
66
|
+
|
|
52
67
|
it('rejects the placeholder proof in the protocol test vectors', async () => {
|
|
53
68
|
const placeholder = 'AE9wZW5UaW1lc3RhbXBzAABDb25maXJtZWQtRml4dHVyZS1ibG9jay04OTAxMjMtbm90LWEtcmVhbC1wcm9vZg==';
|
|
54
69
|
expect(await verify(placeholder, 890123, BLOCK_HASH, HELLO_DIGEST)).toBe(false);
|
|
@@ -70,6 +85,25 @@ describe('mempoolHeaderSource', () => {
|
|
|
70
85
|
expect(calls[0]).toBe(`https://esplora.test/api/block-height/${BLOCK_HEIGHT}`);
|
|
71
86
|
});
|
|
72
87
|
|
|
88
|
+
it('throws when the explorer never answers, so a hung lookup is unread, not a stall', async () => {
|
|
89
|
+
// Answers only when its request is aborted, as a hung explorer does.
|
|
90
|
+
const hung = ((_url: string, init?: RequestInit) =>
|
|
91
|
+
new Promise((_, reject) =>
|
|
92
|
+
init?.signal?.addEventListener('abort', () => reject(init.signal!.reason))
|
|
93
|
+
)) as unknown as typeof fetch;
|
|
94
|
+
const src = mempoolHeaderSource({ fetch: hung, timeoutMs: 20 });
|
|
95
|
+
await expect(src.getHeaderAt(BLOCK_HEIGHT)).rejects.toThrow();
|
|
96
|
+
// The default bounds every request too.
|
|
97
|
+
const signals: (AbortSignal | undefined)[] = [];
|
|
98
|
+
const record = (async (_url: string, init?: RequestInit) => {
|
|
99
|
+
signals.push(init?.signal ?? undefined);
|
|
100
|
+
return new Response('', { status: 404 });
|
|
101
|
+
}) as unknown as typeof fetch;
|
|
102
|
+
await mempoolHeaderSource({ fetch: record }).getHeaderAt(BLOCK_HEIGHT);
|
|
103
|
+
expect(signals).toHaveLength(1);
|
|
104
|
+
expect(signals[0]).toBeInstanceOf(AbortSignal);
|
|
105
|
+
});
|
|
106
|
+
|
|
73
107
|
it('throws when the explorer fails, so a failed lookup never reads as no block', async () => {
|
|
74
108
|
for (const answer of [
|
|
75
109
|
() => new Response('busy', { status: 503 }),
|
package/src/anchor.ts
CHANGED
|
@@ -95,13 +95,18 @@ export function makeAnchorVerifier(
|
|
|
95
95
|
return { ok: true, merkleRoot: hexEncode(headerMerkle) };
|
|
96
96
|
};
|
|
97
97
|
|
|
98
|
+
// Resolves false for a decided no. Throws only when the check could not be made
|
|
99
|
+
// (the header source did not answer), which stamp-core reports as unchecked.
|
|
98
100
|
return async (proofB64, blockHeight, blockHash, envelopeId) => {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
101
|
+
let proofBytes: Uint8Array;
|
|
102
|
+
let digest: Uint8Array;
|
|
103
|
+
try {
|
|
104
|
+
proofBytes = base64Decode(proofB64);
|
|
105
|
+
digest = hexDecode(envelopeId);
|
|
106
|
+
} catch {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
const r = await verifier({ proofBytes, digest, blockHeight, blockHash });
|
|
105
110
|
return r.ok;
|
|
106
111
|
};
|
|
107
112
|
}
|
|
@@ -122,6 +127,8 @@ export interface MempoolHeaderSourceOptions {
|
|
|
122
127
|
/** Esplora-compatible API base. Default https://mempool.space/api. */
|
|
123
128
|
baseUrl?: string;
|
|
124
129
|
fetch?: typeof fetch;
|
|
130
|
+
/** Per request: a lookup that has not answered by then throws, as unread. Default 15_000ms. */
|
|
131
|
+
timeoutMs?: number;
|
|
125
132
|
}
|
|
126
133
|
|
|
127
134
|
/**
|
|
@@ -132,10 +139,12 @@ export interface MempoolHeaderSourceOptions {
|
|
|
132
139
|
export function mempoolHeaderSource(opts: MempoolHeaderSourceOptions = {}): BlockHeaderSource {
|
|
133
140
|
const base = (opts.baseUrl ?? 'https://mempool.space/api').replace(/\/+$/, '');
|
|
134
141
|
const fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
142
|
+
const timeoutMs = opts.timeoutMs ?? 15_000;
|
|
135
143
|
// Null only when the explorer says there is no such block (404). Any other
|
|
136
|
-
// failure throws: a header that could not be read is not a missing block
|
|
144
|
+
// failure throws: a header that could not be read is not a missing block,
|
|
145
|
+
// and neither is an explorer that never answers.
|
|
137
146
|
const read = async (url: string, shape: RegExp): Promise<string | null> => {
|
|
138
|
-
const r = await fetchImpl(url);
|
|
147
|
+
const r = await fetchImpl(url, { signal: AbortSignal.timeout(timeoutMs) });
|
|
139
148
|
if (r.status === 404) return null;
|
|
140
149
|
if (!r.ok) throw new Error(`header lookup failed: HTTP ${r.status} from ${url}`);
|
|
141
150
|
const text = (await r.text()).trim();
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { createCalendarClient, DEFAULT_CALENDARS } from './calendar.js';
|
|
|
4
4
|
export type { HttpCalendarOptions } from './calendar.js';
|
|
5
5
|
export { submitToCalendars } from './submit.js';
|
|
6
6
|
export type { SubmitOptions } from './submit.js';
|
|
7
|
-
export { upgradeProof, verifiedAnchor } from './upgrade.js';
|
|
7
|
+
export { CalendarsUnreadError, upgradeProof, verifiedAnchor } from './upgrade.js';
|
|
8
8
|
export type { UpgradeOptions } from './upgrade.js';
|
|
9
9
|
export {
|
|
10
10
|
blockHashOf,
|
|
@@ -5,7 +5,7 @@ import { verify, type StampEnvelope } from '@orangecheck/stamp-core';
|
|
|
5
5
|
import { sha256 } from '@noble/hashes/sha2';
|
|
6
6
|
import { describe, expect, it } from 'vitest';
|
|
7
7
|
|
|
8
|
-
import { blockHashOf, makeAnchorVerifier } from './anchor.js';
|
|
8
|
+
import { blockHashOf, makeAnchorVerifier, mempoolHeaderSource } from './anchor.js';
|
|
9
9
|
import { base64Encode, hexDecode } from './base64.js';
|
|
10
10
|
import { serializeTimestamp, type OtsTimestamp } from './ots.js';
|
|
11
11
|
|
|
@@ -71,4 +71,18 @@ describe('stamp-core verify() with makeAnchorVerifier', () => {
|
|
|
71
71
|
});
|
|
72
72
|
expect(r.ok ? 'ok' : r.code).toBe('E_BAD_ANCHOR');
|
|
73
73
|
});
|
|
74
|
+
|
|
75
|
+
it('reports the anchor unchecked, not E_BAD_ANCHOR, when the header source answers 503', async () => {
|
|
76
|
+
const down = mempoolHeaderSource({
|
|
77
|
+
fetch: (async () => new Response('down', { status: 503 })) as unknown as typeof fetch,
|
|
78
|
+
});
|
|
79
|
+
const r = await verify({
|
|
80
|
+
envelope: withOts(),
|
|
81
|
+
skipSignatureVerification: true,
|
|
82
|
+
verifyOtsAnchor: makeAnchorVerifier({ headerSource: down }),
|
|
83
|
+
});
|
|
84
|
+
expect(r.ok).toBe(true);
|
|
85
|
+
expect(r.ok && r.anchor).toMatchObject({ status: 'unchecked', blockHeight: HEIGHT, verified: false });
|
|
86
|
+
expect(r.ok && r.anchor.status === 'unchecked' && r.anchor.reason).toMatch(/HTTP 503/);
|
|
87
|
+
});
|
|
74
88
|
});
|
package/src/upgrade.test.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
HELLO_OTS_FILE,
|
|
12
12
|
} from './ots-fixture.test-helper.js';
|
|
13
13
|
import type { BlockHeaderSource, OtsProof } from './types.js';
|
|
14
|
-
import { upgradeProof, verifiedAnchor } from './upgrade.js';
|
|
14
|
+
import { CalendarsUnreadError, upgradeProof, verifiedAnchor } from './upgrade.js';
|
|
15
15
|
|
|
16
16
|
const CAL = 'https://cal.test';
|
|
17
17
|
const chain: BlockHeaderSource = {
|
|
@@ -107,6 +107,53 @@ describe('upgradeProof', () => {
|
|
|
107
107
|
});
|
|
108
108
|
expect(out).toEqual(current);
|
|
109
109
|
});
|
|
110
|
+
|
|
111
|
+
it('throws CalendarsUnreadError when no calendar answers, so silence never reads as not yet', async () => {
|
|
112
|
+
const { pending } = split(6);
|
|
113
|
+
for (const fetchImpl of [
|
|
114
|
+
async () => new Response('busy', { status: 503 }),
|
|
115
|
+
async () => {
|
|
116
|
+
throw new TypeError('fetch failed');
|
|
117
|
+
},
|
|
118
|
+
]) {
|
|
119
|
+
const err = await upgradeProof(pendingProof(pending), HELLO_DIGEST, {
|
|
120
|
+
headerSource: chain,
|
|
121
|
+
fetch: fetchImpl as unknown as typeof fetch,
|
|
122
|
+
}).catch((e: unknown) => e);
|
|
123
|
+
expect(err).toBeInstanceOf(CalendarsUnreadError);
|
|
124
|
+
expect((err as CalendarsUnreadError).failures).toEqual([
|
|
125
|
+
{ calendar: CAL, reason: expect.stringMatching(/HTTP 503|fetch failed/) },
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('confirms a proof that already reaches its block though no calendar answers', async () => {
|
|
131
|
+
const full = parseDetached(HELLO_OTS_FILE).timestamp;
|
|
132
|
+
full.attestations.push({ kind: 'pending', uri: CAL });
|
|
133
|
+
const out = await upgradeProof(pendingProof(full), HELLO_DIGEST, {
|
|
134
|
+
headerSource: chain,
|
|
135
|
+
fetch: (async () => new Response('busy', { status: 503 })) as unknown as typeof fetch,
|
|
136
|
+
});
|
|
137
|
+
expect(out.status).toBe('confirmed');
|
|
138
|
+
expect(out.blockHeight).toBe(BLOCK_HEIGHT);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('stays pending when one calendar says not yet and another does not answer', async () => {
|
|
142
|
+
const { pending } = split(6);
|
|
143
|
+
const other = 'https://cal2.test';
|
|
144
|
+
// A second calendar's attestation beside the first, as a proof sent to two calendars holds.
|
|
145
|
+
const leaf = (n: OtsTimestamp): OtsTimestamp => (n.ops.length ? leaf(n.ops[0]!.child) : n);
|
|
146
|
+
leaf(pending).attestations.push({ kind: 'pending', uri: other });
|
|
147
|
+
const current = pendingProof(pending, [CAL, other]);
|
|
148
|
+
const out = await upgradeProof(current, HELLO_DIGEST, {
|
|
149
|
+
headerSource: chain,
|
|
150
|
+
fetch: (async (url: string) =>
|
|
151
|
+
url.startsWith(other)
|
|
152
|
+
? new Response('busy', { status: 503 })
|
|
153
|
+
: new Response(null, { status: 404 })) as unknown as typeof fetch,
|
|
154
|
+
});
|
|
155
|
+
expect(out).toEqual(current);
|
|
156
|
+
});
|
|
110
157
|
});
|
|
111
158
|
|
|
112
159
|
describe('verifiedAnchor', () => {
|
package/src/upgrade.ts
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
// Calendars index upgrades by that commitment, not by the submitted digest.
|
|
6
6
|
// For each pending leaf we ask its calendar for the continuation, graft it on,
|
|
7
7
|
// and report the proof as confirmed once it reaches a Bitcoin attestation
|
|
8
|
-
// whose block header checks out.
|
|
8
|
+
// whose block header checks out. A calendar's 404 is its "not yet"; when no
|
|
9
|
+
// calendar answers at all, nothing is concluded and the upgrade throws.
|
|
9
10
|
|
|
10
11
|
import { blockHashOf } from './anchor.js';
|
|
11
12
|
import { base64Decode, base64Encode, hexDecode } from './base64.js';
|
|
@@ -39,6 +40,23 @@ export interface UpgradeOptions {
|
|
|
39
40
|
|
|
40
41
|
const norm = (u: string) => u.replace(/\/+$/, '');
|
|
41
42
|
|
|
43
|
+
/**
|
|
44
|
+
* No calendar a pending proof names answered, so nothing was learned: the
|
|
45
|
+
* proof may be anchored already. Thrown by `upgradeProof` instead of
|
|
46
|
+
* returning the proof as still `pending`.
|
|
47
|
+
*/
|
|
48
|
+
export class CalendarsUnreadError extends Error {
|
|
49
|
+
constructor(
|
|
50
|
+
/** The calendars asked, with why each did not answer. */
|
|
51
|
+
readonly failures: { calendar: string; reason: string }[]
|
|
52
|
+
) {
|
|
53
|
+
super(
|
|
54
|
+
`OTS: no calendar answered (${failures.map((f) => `${f.calendar}: ${f.reason}`).join('; ')})`
|
|
55
|
+
);
|
|
56
|
+
this.name = 'CalendarsUnreadError';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
42
60
|
export async function upgradeProof(
|
|
43
61
|
current: OtsProof,
|
|
44
62
|
idHex: string,
|
|
@@ -60,7 +78,7 @@ export async function upgradeProof(
|
|
|
60
78
|
}
|
|
61
79
|
|
|
62
80
|
const answered: string[] = [];
|
|
63
|
-
await Promise.allSettled(
|
|
81
|
+
const settled = await Promise.allSettled(
|
|
64
82
|
pending.map(async ({ uri, commitment }) => {
|
|
65
83
|
const client = createCalendarClient(uri, { fetch: opts.fetch, timeoutMs: opts.timeoutMs });
|
|
66
84
|
const bytes = await client.fetchProof(commitment, opts.signal);
|
|
@@ -71,6 +89,14 @@ export async function upgradeProof(
|
|
|
71
89
|
|
|
72
90
|
const merged = serializeTimestamp(tree);
|
|
73
91
|
const anchor = await resolveAnchor(tree, opts.headerSource);
|
|
92
|
+
if (!anchor && pending.length > 0 && settled.every((r) => r.status === 'rejected')) {
|
|
93
|
+
throw new CalendarsUnreadError(
|
|
94
|
+
pending.map(({ uri }, i) => ({
|
|
95
|
+
calendar: norm(uri),
|
|
96
|
+
reason: String((settled[i] as PromiseRejectedResult).reason?.message ?? settled[i]),
|
|
97
|
+
}))
|
|
98
|
+
);
|
|
99
|
+
}
|
|
74
100
|
const calendars = [...answered, ...current.calendars.filter((c) => !answered.includes(norm(c)))];
|
|
75
101
|
|
|
76
102
|
if (anchor) {
|