@orangecheck/stamp-ots 0.1.0 → 0.2.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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # @orangecheck/stamp-ots
2
2
 
3
+ > **Full reference:** [docs.ochk.io/sdk/stamp-ots](https://docs.ochk.io/sdk/stamp-ots) — auto-generated from the TypeScript source on every release.
4
+ > Hand-written prose below is the high-level overview; the docs site is the source of truth for every export, type, and signature.
5
+
6
+
3
7
  OpenTimestamps calendar client, proof helpers, and anchor-verification hooks for [OC Stamp](https://github.com/orangecheck/oc-stamp-protocol) envelopes.
4
8
 
5
9
  ## Install
@@ -13,31 +17,24 @@ npm i @orangecheck/stamp-core @orangecheck/stamp-ots
13
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:
14
18
 
15
19
  - **`submitToCalendars(id, opts)`** — POST the envelope's 32-byte digest to one or more OTS calendars. Returns a pending `OtsProof` you can fold into the envelope's `ots` field.
16
- - **`upgradeProof(proof, id, opts)`** — poll calendars for an upgraded proof once OTS has anchored the containing batch to a Bitcoin block. Returns a confirmed `OtsProof` when available.
17
- - **`createCalendarClient(url)`** — low-level HTTP client implementing the minimal OTS calendar API (`POST /digest`, `GET /timestamp/<hex>`).
18
- - **`makeAnchorVerifier({ walkProof, headerSource })`** — adapter that turns a proof-parser plus a block-header source into a function `verify()` (from `@orangecheck/stamp-core`) can call via its `verifyOtsAnchor` parameter.
19
-
20
- ## What it does NOT do
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. Returns a confirmed `OtsProof` once the proof reaches a Bitcoin block whose header checks out.
21
+ - **`createCalendarClient(url)`** — low-level HTTP client implementing the minimal OTS calendar API (`POST /digest`, `GET /timestamp/<hex(commitment)>`).
22
+ - **`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.
23
+ - **`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.
24
+ - **`parseProof` / `parseDetached` / `serializeTimestamp` / `bitcoinAnchors` / `pendingCommitments`** — the OTS proof format, accepting both the bare timestamp carried in `ots.proof` and detached `.ots` files.
21
25
 
22
- This package does **not** ship a full OpenTimestamps proof parser. Parsing the binary proof format (Merkle path chunks, calendar attestations, Bitcoin attestations) requires a larger, maintained library like `javascript-opentimestamps`. We keep this package's dependency surface narrow and expose `walkProof` as a plug-in point.
23
-
24
- Consumers who want fully-offline verification should combine:
26
+ ## Verify an anchor
25
27
 
26
28
  ```ts
27
29
  import { verify } from '@orangecheck/stamp-core';
28
- import { makeAnchorVerifier, adaptAnchorVerifier, base64Decode, hexDecode } from '@orangecheck/stamp-ots';
29
- import { myOtsParser, myHeaderSource } from './your-adapters';
30
-
31
- const anchor = makeAnchorVerifier({
32
- walkProof: myOtsParser,
33
- headerSource: myHeaderSource,
34
- });
30
+ import { makeAnchorVerifier, mempoolHeaderSource } from '@orangecheck/stamp-ots';
35
31
 
36
32
  const result = await verify({
37
33
  envelope: env,
38
- verifyOtsAnchor: adaptAnchorVerifier(anchor, (blockHash) => hexDecode(env.id)),
34
+ verifyOtsAnchor: makeAnchorVerifier({ headerSource: mempoolHeaderSource() }),
39
35
  verifyBip322: myBip322Verifier,
40
36
  });
37
+ // result.anchor.verified is true only when the proof checked out.
41
38
  ```
42
39
 
43
40
  ## Usage
@@ -57,11 +54,11 @@ const envWithOts = { ...env, ots: toStampOts(proof) };
57
54
  ### Upgrade later
58
55
 
59
56
  ```ts
60
- import { upgradeProof, fromStampOts, toStampOts } from '@orangecheck/stamp-ots';
57
+ import { fromStampOts, mempoolHeaderSource, toStampOts, upgradeProof } from '@orangecheck/stamp-ots';
61
58
 
62
59
  const current = fromStampOts(envWithOts.ots!);
63
60
  const upgraded = await upgradeProof(current, envWithOts.id, {
64
- parseAnchor: myOtsParser, // plug in your OTS proof parser
61
+ headerSource: mempoolHeaderSource(),
65
62
  });
66
63
  const envUpgraded = { ...envWithOts, ots: toStampOts(upgraded) };
67
64
  ```
@@ -70,7 +67,8 @@ const envUpgraded = { ...envWithOts, ots: toStampOts(upgraded) };
70
67
 
71
68
  - `submitToCalendars(id, opts)` / `upgradeProof(proof, id, opts)`
72
69
  - `createCalendarClient(url, opts)` / `DEFAULT_CALENDARS`
73
- - `makeAnchorVerifier(config)` / `adaptAnchorVerifier(verifier, digestLookup)`
70
+ - `makeAnchorVerifier(config)` / `makeDefaultAnchorVerifier(config)` / `mempoolHeaderSource(opts)` / `walkOtsProof(input)` / `blockHashOf(header)`
71
+ - `parseProof` / `parseDetached` / `parseTimestamp` / `serializeTimestamp` / `bitcoinAnchors` / `pendingCommitments` / `mergeAt` / `attestations`
74
72
  - `toStampOts(proof)` / `fromStampOts(stampOts)` — shape adapters
75
73
  - `base64Encode` / `base64Decode` / `hexEncode` / `hexDecode`
76
74
  - Types: `OtsProof`, `CalendarClient`, `AnchorVerifier`, `BlockHeaderSource`, etc.
package/dist/index.d.mts CHANGED
@@ -12,7 +12,7 @@ interface OtsProof {
12
12
  interface CalendarClient {
13
13
  readonly url: string;
14
14
  submit(digest: Uint8Array, signal?: AbortSignal): Promise<Uint8Array>;
15
- fetchProof(digest: Uint8Array, signal?: AbortSignal): Promise<Uint8Array | null>;
15
+ fetchProof(commitment: Uint8Array, signal?: AbortSignal): Promise<Uint8Array | null>;
16
16
  }
17
17
  interface AnchorVerificationInput {
18
18
  proofBytes: Uint8Array;
@@ -57,7 +57,8 @@ interface SubmitOptions {
57
57
  declare function submitToCalendars(idHex: string, opts?: SubmitOptions): Promise<OtsProof>;
58
58
 
59
59
  interface UpgradeOptions {
60
- parseAnchor: (proofBytes: Uint8Array) => Promise<{
60
+ headerSource?: BlockHeaderSource;
61
+ parseAnchor?: (proofBytes: Uint8Array) => Promise<{
61
62
  blockHeight: number;
62
63
  blockHash: string;
63
64
  } | null>;
@@ -68,16 +69,79 @@ interface UpgradeOptions {
68
69
  declare function upgradeProof(current: OtsProof, idHex: string, opts: UpgradeOptions): Promise<OtsProof>;
69
70
 
70
71
  interface AnchorVerifierConfig {
71
- walkProof: (input: {
72
+ walkProof?: (input: {
72
73
  proofBytes: Uint8Array;
73
74
  digest: Uint8Array;
75
+ blockHeight?: number;
74
76
  }) => Promise<{
75
77
  merkleRoot: Uint8Array;
76
78
  blockHeight: number;
77
79
  } | null>;
78
80
  headerSource: BlockHeaderSource;
79
81
  }
80
- declare function makeAnchorVerifier(cfg: AnchorVerifierConfig): AnchorVerifier;
81
- declare function adaptAnchorVerifier(verifier: AnchorVerifier, digestLookup: (blockHash: string) => Uint8Array): (proofB64: string, blockHeight: number, blockHash: string) => Promise<boolean>;
82
+ declare function walkOtsProof(input: {
83
+ proofBytes: Uint8Array;
84
+ digest: Uint8Array;
85
+ blockHeight?: number;
86
+ }): Promise<{
87
+ merkleRoot: Uint8Array;
88
+ blockHeight: number;
89
+ } | null>;
90
+ declare function blockHashOf(header: Uint8Array): string;
91
+ declare function makeAnchorVerifier(cfg: AnchorVerifierConfig): (proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean>;
92
+ declare function makeDefaultAnchorVerifier(opts: {
93
+ headerSource: BlockHeaderSource;
94
+ }): Promise<(proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean>>;
95
+ interface MempoolHeaderSourceOptions {
96
+ baseUrl?: string;
97
+ fetch?: typeof fetch;
98
+ }
99
+ declare function mempoolHeaderSource(opts?: MempoolHeaderSourceOptions): BlockHeaderSource;
100
+
101
+ type OtsOp = {
102
+ kind: 'sha256' | 'ripemd160' | 'sha1' | 'keccak256' | 'reverse' | 'hexlify';
103
+ } | {
104
+ kind: 'append' | 'prepend';
105
+ arg: Uint8Array;
106
+ };
107
+ type OtsAttestation = {
108
+ kind: 'bitcoin';
109
+ height: number;
110
+ } | {
111
+ kind: 'pending';
112
+ uri: string;
113
+ } | {
114
+ kind: 'unknown';
115
+ tag: string;
116
+ payload: Uint8Array;
117
+ };
118
+ interface OtsTimestamp {
119
+ msg: Uint8Array;
120
+ attestations: OtsAttestation[];
121
+ ops: {
122
+ op: OtsOp;
123
+ child: OtsTimestamp;
124
+ }[];
125
+ }
126
+ declare function parseTimestamp(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp;
127
+ declare function parseDetached(bytes: Uint8Array): {
128
+ digest: Uint8Array;
129
+ timestamp: OtsTimestamp;
130
+ };
131
+ declare function parseProof(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp;
132
+ declare function attestations(ts: OtsTimestamp): {
133
+ msg: Uint8Array;
134
+ attestation: OtsAttestation;
135
+ }[];
136
+ declare function bitcoinAnchors(ts: OtsTimestamp): {
137
+ blockHeight: number;
138
+ merkleRoot: Uint8Array;
139
+ }[];
140
+ declare function pendingCommitments(ts: OtsTimestamp): {
141
+ uri: string;
142
+ commitment: Uint8Array;
143
+ }[];
144
+ declare function mergeAt(ts: OtsTimestamp, upgrade: OtsTimestamp): boolean;
145
+ declare function serializeTimestamp(ts: OtsTimestamp): Uint8Array;
82
146
 
83
- export { type AnchorVerificationInput, type AnchorVerificationResult, type AnchorVerifier, type AnchorVerifierConfig, type BlockHeaderSource, type CalendarClient, DEFAULT_CALENDARS, type HttpCalendarOptions, type OtsProof, type OtsProofStatus, type SubmitOptions, type UpgradeOptions, adaptAnchorVerifier, base64Decode, base64Encode, createCalendarClient, fromStampOts, hexDecode, hexEncode, makeAnchorVerifier, submitToCalendars, toStampOts, upgradeProof };
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, walkOtsProof };
package/dist/index.d.ts CHANGED
@@ -12,7 +12,7 @@ interface OtsProof {
12
12
  interface CalendarClient {
13
13
  readonly url: string;
14
14
  submit(digest: Uint8Array, signal?: AbortSignal): Promise<Uint8Array>;
15
- fetchProof(digest: Uint8Array, signal?: AbortSignal): Promise<Uint8Array | null>;
15
+ fetchProof(commitment: Uint8Array, signal?: AbortSignal): Promise<Uint8Array | null>;
16
16
  }
17
17
  interface AnchorVerificationInput {
18
18
  proofBytes: Uint8Array;
@@ -57,7 +57,8 @@ interface SubmitOptions {
57
57
  declare function submitToCalendars(idHex: string, opts?: SubmitOptions): Promise<OtsProof>;
58
58
 
59
59
  interface UpgradeOptions {
60
- parseAnchor: (proofBytes: Uint8Array) => Promise<{
60
+ headerSource?: BlockHeaderSource;
61
+ parseAnchor?: (proofBytes: Uint8Array) => Promise<{
61
62
  blockHeight: number;
62
63
  blockHash: string;
63
64
  } | null>;
@@ -68,16 +69,79 @@ interface UpgradeOptions {
68
69
  declare function upgradeProof(current: OtsProof, idHex: string, opts: UpgradeOptions): Promise<OtsProof>;
69
70
 
70
71
  interface AnchorVerifierConfig {
71
- walkProof: (input: {
72
+ walkProof?: (input: {
72
73
  proofBytes: Uint8Array;
73
74
  digest: Uint8Array;
75
+ blockHeight?: number;
74
76
  }) => Promise<{
75
77
  merkleRoot: Uint8Array;
76
78
  blockHeight: number;
77
79
  } | null>;
78
80
  headerSource: BlockHeaderSource;
79
81
  }
80
- declare function makeAnchorVerifier(cfg: AnchorVerifierConfig): AnchorVerifier;
81
- declare function adaptAnchorVerifier(verifier: AnchorVerifier, digestLookup: (blockHash: string) => Uint8Array): (proofB64: string, blockHeight: number, blockHash: string) => Promise<boolean>;
82
+ declare function walkOtsProof(input: {
83
+ proofBytes: Uint8Array;
84
+ digest: Uint8Array;
85
+ blockHeight?: number;
86
+ }): Promise<{
87
+ merkleRoot: Uint8Array;
88
+ blockHeight: number;
89
+ } | null>;
90
+ declare function blockHashOf(header: Uint8Array): string;
91
+ declare function makeAnchorVerifier(cfg: AnchorVerifierConfig): (proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean>;
92
+ declare function makeDefaultAnchorVerifier(opts: {
93
+ headerSource: BlockHeaderSource;
94
+ }): Promise<(proofB64: string, blockHeight: number, blockHash: string, envelopeId: string) => Promise<boolean>>;
95
+ interface MempoolHeaderSourceOptions {
96
+ baseUrl?: string;
97
+ fetch?: typeof fetch;
98
+ }
99
+ declare function mempoolHeaderSource(opts?: MempoolHeaderSourceOptions): BlockHeaderSource;
100
+
101
+ type OtsOp = {
102
+ kind: 'sha256' | 'ripemd160' | 'sha1' | 'keccak256' | 'reverse' | 'hexlify';
103
+ } | {
104
+ kind: 'append' | 'prepend';
105
+ arg: Uint8Array;
106
+ };
107
+ type OtsAttestation = {
108
+ kind: 'bitcoin';
109
+ height: number;
110
+ } | {
111
+ kind: 'pending';
112
+ uri: string;
113
+ } | {
114
+ kind: 'unknown';
115
+ tag: string;
116
+ payload: Uint8Array;
117
+ };
118
+ interface OtsTimestamp {
119
+ msg: Uint8Array;
120
+ attestations: OtsAttestation[];
121
+ ops: {
122
+ op: OtsOp;
123
+ child: OtsTimestamp;
124
+ }[];
125
+ }
126
+ declare function parseTimestamp(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp;
127
+ declare function parseDetached(bytes: Uint8Array): {
128
+ digest: Uint8Array;
129
+ timestamp: OtsTimestamp;
130
+ };
131
+ declare function parseProof(bytes: Uint8Array, digest: Uint8Array): OtsTimestamp;
132
+ declare function attestations(ts: OtsTimestamp): {
133
+ msg: Uint8Array;
134
+ attestation: OtsAttestation;
135
+ }[];
136
+ declare function bitcoinAnchors(ts: OtsTimestamp): {
137
+ blockHeight: number;
138
+ merkleRoot: Uint8Array;
139
+ }[];
140
+ declare function pendingCommitments(ts: OtsTimestamp): {
141
+ uri: string;
142
+ commitment: Uint8Array;
143
+ }[];
144
+ declare function mergeAt(ts: OtsTimestamp, upgrade: OtsTimestamp): boolean;
145
+ declare function serializeTimestamp(ts: OtsTimestamp): Uint8Array;
82
146
 
83
- export { type AnchorVerificationInput, type AnchorVerificationResult, type AnchorVerifier, type AnchorVerifierConfig, type BlockHeaderSource, type CalendarClient, DEFAULT_CALENDARS, type HttpCalendarOptions, type OtsProof, type OtsProofStatus, type SubmitOptions, type UpgradeOptions, adaptAnchorVerifier, base64Decode, base64Encode, createCalendarClient, fromStampOts, hexDecode, hexEncode, makeAnchorVerifier, submitToCalendars, toStampOts, upgradeProof };
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, walkOtsProof };