@orangecheck/stamp-cli 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 +11 -2
- package/dist/cli.js +74 -20
- package/dist/cli.js.map +1 -1
- package/package.json +59 -56
package/README.md
CHANGED
|
@@ -30,7 +30,8 @@ $ stamp canonical blogpost.md --addr bc1qalice...
|
|
|
30
30
|
# Verify a stamp:
|
|
31
31
|
$ stamp verify blogpost.md.stamp blogpost.md --require-anchor
|
|
32
32
|
|
|
33
|
-
#
|
|
33
|
+
# Anchor an existing stamp, or upgrade its pending proof once the
|
|
34
|
+
# calendars have reached a block (rewrites the .stamp only on change):
|
|
34
35
|
$ stamp anchor blogpost.md.stamp
|
|
35
36
|
```
|
|
36
37
|
|
|
@@ -62,12 +63,20 @@ $ stamp verify blogpost.md.stamp blogpost.md --json
|
|
|
62
63
|
"content_mime": "text/markdown",
|
|
63
64
|
"content_length": 12843,
|
|
64
65
|
"content_checked": true,
|
|
65
|
-
"anchor": "confirmed at block 890123",
|
|
66
|
+
"anchor": "confirmed at block 890123 (checked against the block header)",
|
|
67
|
+
"anchor_state": "anchored",
|
|
66
68
|
"signature_checked": true,
|
|
67
69
|
"stake": null
|
|
68
70
|
}
|
|
69
71
|
```
|
|
70
72
|
|
|
73
|
+
A confirmed anchor is checked per SPEC §6.3: the proof must commit to the
|
|
74
|
+
stamp id, and the block header at the claimed height (from
|
|
75
|
+
`--headers-url`, default `https://mempool.space/api`) must hash to the claimed
|
|
76
|
+
block hash and carry the proof's Merkle root. A proof that does not chain
|
|
77
|
+
exits 2 with `E_BAD_ANCHOR`. If no header can be fetched the claim is reported
|
|
78
|
+
as unverified, and `--require-anchor` fails.
|
|
79
|
+
|
|
71
80
|
On failure, exits `2` with an error code:
|
|
72
81
|
|
|
73
82
|
```
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { submitToCalendars, toStampOts, mempoolHeaderSource, makeAnchorVerifier, upgradeProof, fromStampOts } from '@orangecheck/stamp-ots';
|
|
2
3
|
import { createHash } from 'crypto';
|
|
3
4
|
import { mkdir, writeFile, stat, readFile } from 'fs/promises';
|
|
4
5
|
import { basename } from 'path';
|
|
5
6
|
import { canonicalMessage, stamp, verify } from '@orangecheck/stamp-core';
|
|
6
7
|
import { Command } from 'commander';
|
|
7
|
-
import { submitToCalendars, toStampOts } from '@orangecheck/stamp-ots';
|
|
8
8
|
import { execFile } from 'child_process';
|
|
9
9
|
import { promisify } from 'util';
|
|
10
10
|
import { createInterface } from 'readline/promises';
|
|
@@ -18,6 +18,42 @@ var __export = (target, all) => {
|
|
|
18
18
|
for (var name in all)
|
|
19
19
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
20
20
|
};
|
|
21
|
+
async function checkAnchorClaim(env, headers) {
|
|
22
|
+
const ots = env.ots;
|
|
23
|
+
if (!ots) return { state: "none" };
|
|
24
|
+
if (ots.status !== "confirmed" || ots.block_height === null || !ots.block_hash) {
|
|
25
|
+
return { state: "pending" };
|
|
26
|
+
}
|
|
27
|
+
const blockHeight = ots.block_height;
|
|
28
|
+
let header = null;
|
|
29
|
+
try {
|
|
30
|
+
header = await headers.getHeaderAt(blockHeight);
|
|
31
|
+
} catch {
|
|
32
|
+
header = null;
|
|
33
|
+
}
|
|
34
|
+
if (!header) {
|
|
35
|
+
return { state: "unverified", blockHeight, message: "block header source unreachable" };
|
|
36
|
+
}
|
|
37
|
+
const verify2 = makeAnchorVerifier({ headerSource: { getHeaderAt: async () => header } });
|
|
38
|
+
const ok = await verify2(ots.proof, blockHeight, ots.block_hash, env.id);
|
|
39
|
+
return ok ? { state: "anchored", blockHeight } : { state: "fail", blockHeight, message: `OTS proof does not chain to block ${blockHeight}` };
|
|
40
|
+
}
|
|
41
|
+
async function advanceOts(env, opts) {
|
|
42
|
+
if (!env.ots) {
|
|
43
|
+
const proof = await submitToCalendars(env.id, { fetch: opts.fetch });
|
|
44
|
+
return { ...env, ots: toStampOts(proof) };
|
|
45
|
+
}
|
|
46
|
+
if (env.ots.status === "confirmed") return env;
|
|
47
|
+
const next = await upgradeProof(fromStampOts(env.ots), env.id, {
|
|
48
|
+
headerSource: opts.headers,
|
|
49
|
+
fetch: opts.fetch
|
|
50
|
+
});
|
|
51
|
+
return { ...env, ots: toStampOts(next) };
|
|
52
|
+
}
|
|
53
|
+
var init_anchor_check = __esm({
|
|
54
|
+
"src/anchor-check.ts"() {
|
|
55
|
+
}
|
|
56
|
+
});
|
|
21
57
|
async function readBytes(path) {
|
|
22
58
|
const buf = await readFile(path);
|
|
23
59
|
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
@@ -154,12 +190,20 @@ async function runVerify(opts) {
|
|
|
154
190
|
});
|
|
155
191
|
process.exit(2);
|
|
156
192
|
}
|
|
157
|
-
const
|
|
158
|
-
|
|
193
|
+
const anchor = await checkAnchorClaim(
|
|
194
|
+
envelope,
|
|
195
|
+
mempoolHeaderSource({ baseUrl: opts.headersUrl })
|
|
196
|
+
);
|
|
197
|
+
if (anchor.state === "fail") {
|
|
198
|
+
emit(opts.json, { ok: false, code: "E_BAD_ANCHOR", message: anchor.message });
|
|
199
|
+
process.exit(2);
|
|
200
|
+
}
|
|
201
|
+
const anchorLabel = anchor.state === "anchored" ? `confirmed at block ${anchor.blockHeight} (checked against the block header)` : anchor.state === "unverified" ? `claims block ${anchor.blockHeight}, unverified: ${anchor.message}` : anchor.state;
|
|
202
|
+
if (opts.requireAnchor && anchor.state !== "anchored") {
|
|
159
203
|
emit(opts.json, {
|
|
160
204
|
ok: false,
|
|
161
205
|
code: "E_NO_ANCHOR",
|
|
162
|
-
message: `required
|
|
206
|
+
message: `required a verified OTS anchor, got ${anchor.state}`
|
|
163
207
|
});
|
|
164
208
|
process.exit(2);
|
|
165
209
|
}
|
|
@@ -173,17 +217,20 @@ async function runVerify(opts) {
|
|
|
173
217
|
content_length: envelope.content.length,
|
|
174
218
|
content_checked: Boolean(contentBytes),
|
|
175
219
|
anchor: anchorLabel,
|
|
220
|
+
anchor_state: anchor.state,
|
|
176
221
|
signature_checked: !opts.skipSignature,
|
|
177
222
|
stake: envelope.stake
|
|
178
223
|
});
|
|
179
224
|
}
|
|
180
225
|
var init_verify = __esm({
|
|
181
226
|
"src/commands/verify.ts"() {
|
|
227
|
+
init_anchor_check();
|
|
182
228
|
init_util();
|
|
183
229
|
}
|
|
184
230
|
});
|
|
185
231
|
|
|
186
232
|
// src/commands/anchor.ts
|
|
233
|
+
init_anchor_check();
|
|
187
234
|
init_util();
|
|
188
235
|
async function runAnchor(opts) {
|
|
189
236
|
if (!await pathExists(opts.stampPath)) die(`no such file: ${opts.stampPath}`);
|
|
@@ -196,20 +243,26 @@ async function runAnchor(opts) {
|
|
|
196
243
|
});
|
|
197
244
|
return;
|
|
198
245
|
}
|
|
246
|
+
let next;
|
|
199
247
|
try {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
await writeFile(opts.stampPath, JSON.stringify(next, null, 2) + "\n", "utf8");
|
|
203
|
-
emit(opts.json, {
|
|
204
|
-
ok: true,
|
|
205
|
-
id: next.id,
|
|
206
|
-
status: next.ots?.status,
|
|
207
|
-
calendars: next.ots?.calendars ?? [],
|
|
208
|
-
written: opts.stampPath
|
|
248
|
+
next = await advanceOts(envelope, {
|
|
249
|
+
headers: mempoolHeaderSource({ baseUrl: opts.headersUrl })
|
|
209
250
|
});
|
|
210
251
|
} catch (e) {
|
|
211
|
-
die(`OTS submission failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
252
|
+
die(`OTS ${envelope.ots ? "upgrade" : "submission"} failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
212
253
|
}
|
|
254
|
+
const changed = JSON.stringify(next.ots) !== JSON.stringify(envelope.ots);
|
|
255
|
+
if (changed) {
|
|
256
|
+
await writeFile(opts.stampPath, JSON.stringify(next, null, 2) + "\n", "utf8");
|
|
257
|
+
}
|
|
258
|
+
emit(opts.json, {
|
|
259
|
+
ok: true,
|
|
260
|
+
id: next.id,
|
|
261
|
+
status: next.ots?.status,
|
|
262
|
+
block_height: next.ots?.block_height ?? null,
|
|
263
|
+
calendars: next.ots?.calendars ?? [],
|
|
264
|
+
written: changed ? opts.stampPath : null
|
|
265
|
+
});
|
|
213
266
|
}
|
|
214
267
|
|
|
215
268
|
// src/commands/git-tag.ts
|
|
@@ -389,7 +442,7 @@ init_util();
|
|
|
389
442
|
var invoked = basename(process.argv[1] ?? "stamp");
|
|
390
443
|
var program = new Command();
|
|
391
444
|
if (invoked.startsWith("git-stamp")) {
|
|
392
|
-
program.name("git-stamp").description("Stamp git tags with your Bitcoin address, anchored to Bitcoin.").version("0.
|
|
445
|
+
program.name("git-stamp").description("Stamp git tags with your Bitcoin address, anchored to Bitcoin.").version("0.2.0");
|
|
393
446
|
program.command("tag <tagname>").description("Sign and (optionally) anchor a stamp over <tagname>^{tree}").requiredOption("--addr <address>", "Bitcoin address").option("--sig <signature>", "BIP-322 signature (non-interactive mode)").option("--no-anchor", "Skip OTS calendar submission").option("--json", "Emit JSON").action(async (tag, opts) => {
|
|
394
447
|
await runGitTag({
|
|
395
448
|
tag,
|
|
@@ -399,7 +452,7 @@ if (invoked.startsWith("git-stamp")) {
|
|
|
399
452
|
json: Boolean(opts.json)
|
|
400
453
|
});
|
|
401
454
|
});
|
|
402
|
-
program.command("verify <tagname>").description("Verify the stamp stored under .git/stamps/<tagname>.stamp").option("--require-anchor", "Fail unless the OTS
|
|
455
|
+
program.command("verify <tagname>").description("Verify the stamp stored under .git/stamps/<tagname>.stamp").option("--require-anchor", "Fail unless the OTS anchor is confirmed and checked against the block header").option("--json", "Emit JSON").action(async (tag, opts) => {
|
|
403
456
|
await runGitVerify({
|
|
404
457
|
tag,
|
|
405
458
|
requireAnchor: Boolean(opts.requireAnchor),
|
|
@@ -407,7 +460,7 @@ if (invoked.startsWith("git-stamp")) {
|
|
|
407
460
|
});
|
|
408
461
|
});
|
|
409
462
|
} else {
|
|
410
|
-
program.name("stamp").description("OC Stamp \u2014 sign anything with your Bitcoin address, anchor to Bitcoin.").version("0.
|
|
463
|
+
program.name("stamp").description("OC Stamp \u2014 sign anything with your Bitcoin address, anchor to Bitcoin.").version("0.2.0");
|
|
411
464
|
program.command("file <path>").description("Sign a file and write <path>.stamp alongside").requiredOption("--addr <address>", "Bitcoin address").option("--mime <type>", "Override the MIME type (default: inferred from extension)").option("--signed-at <iso>", "Override signed_at (default: now)").option("--sig <signature>", "BIP-322 signature (non-interactive mode)").option("--no-anchor", "Skip OTS calendar submission").option("--out <path>", "Output path (default: <path>.stamp)").option("--json", "Emit JSON").action(async (path, opts) => {
|
|
412
465
|
await runStampFile({
|
|
413
466
|
path,
|
|
@@ -420,17 +473,18 @@ if (invoked.startsWith("git-stamp")) {
|
|
|
420
473
|
json: Boolean(opts.json)
|
|
421
474
|
});
|
|
422
475
|
});
|
|
423
|
-
program.command("verify <stamp> [content]").description("Run the full SPEC \xA78 verification").option("--require-anchor", "Fail unless the OTS
|
|
476
|
+
program.command("verify <stamp> [content]").description("Run the full SPEC \xA78 verification").option("--require-anchor", "Fail unless the OTS anchor is confirmed and checked against the block header").option("--skip-signature", "Skip BIP-322 verification (for CI smoke tests only)").option("--headers-url <url>", "Esplora API for block headers (default: https://mempool.space/api)").option("--json", "Emit JSON").action(async (stampPath, contentPath, opts) => {
|
|
424
477
|
await runVerify({
|
|
425
478
|
stampPath,
|
|
426
479
|
contentPath,
|
|
427
480
|
requireAnchor: Boolean(opts.requireAnchor),
|
|
428
481
|
skipSignature: Boolean(opts.skipSignature),
|
|
482
|
+
headersUrl: opts.headersUrl,
|
|
429
483
|
json: Boolean(opts.json)
|
|
430
484
|
});
|
|
431
485
|
});
|
|
432
|
-
program.command("anchor <stamp>").description("Submit
|
|
433
|
-
await runAnchor({ stampPath, json: Boolean(opts.json) });
|
|
486
|
+
program.command("anchor <stamp>").description("Submit a stamp to OTS calendars, or upgrade its pending proof").option("--headers-url <url>", "Esplora API for block headers (default: https://mempool.space/api)").option("--json", "Emit JSON").action(async (stampPath, opts) => {
|
|
487
|
+
await runAnchor({ stampPath, headersUrl: opts.headersUrl, json: Boolean(opts.json) });
|
|
434
488
|
});
|
|
435
489
|
program.command("canonical <path>").description("Print the canonical message a stamp over <path> would sign (dry run)").requiredOption("--addr <address>", "Bitcoin address").option("--mime <type>", "Override the MIME type").option("--signed-at <iso>", "Override signed_at (default: now)").action(async (path, opts) => {
|
|
436
490
|
const { hash, length } = await hashFile(path);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/util.ts","../src/commands/verify.ts","../src/commands/anchor.ts","../src/commands/git-tag.ts","../src/commands/stamp-file.ts","../src/cli.ts"],"names":["createHash","submitToCalendars","toStampOts","writeFile","runVerify","canonicalMessage","createInterface","stamp","basename"],"mappings":"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","file":"cli.js","sourcesContent":["// Shared helpers for stamp-cli commands.\n\nimport { createHash } from 'node:crypto';\nimport { readFile, stat } from 'node:fs/promises';\nimport { basename } from 'node:path';\n\n/** Read a path into bytes. */\nexport async function readBytes(path: string): Promise<Uint8Array> {\n const buf = await readFile(path);\n return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);\n}\n\n/**\n * Stream-hash a path with SHA-256. For very large content we want to avoid\n * loading the whole file into memory; for small files the cost is negligible.\n */\nexport async function hashFile(path: string): Promise<{ hash: string; length: number }> {\n const bytes = await readBytes(path);\n const h = createHash('sha256').update(bytes).digest('hex');\n return { hash: 'sha256:' + h, length: bytes.byteLength };\n}\n\n/** Infer a conservative MIME from a filename. Falls back to application/octet-stream. */\nexport function mimeFromPath(path: string): string {\n const name = basename(path).toLowerCase();\n const ext = name.split('.').pop();\n switch (ext) {\n case 'md':\n case 'markdown':\n return 'text/markdown';\n case 'txt':\n return 'text/plain';\n case 'html':\n case 'htm':\n return 'text/html';\n case 'json':\n return 'application/json';\n case 'pdf':\n return 'application/pdf';\n case 'png':\n return 'image/png';\n case 'jpg':\n case 'jpeg':\n return 'image/jpeg';\n case 'gif':\n return 'image/gif';\n case 'webp':\n return 'image/webp';\n case 'mp3':\n return 'audio/mpeg';\n case 'mp4':\n return 'video/mp4';\n case 'wav':\n return 'audio/wav';\n case 'zip':\n return 'application/zip';\n case 'tar':\n return 'application/x-tar';\n case 'gz':\n return 'application/gzip';\n default:\n return 'application/octet-stream';\n }\n}\n\nexport async function pathExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read JSON from a path or `-` for stdin.\n */\nexport async function readJson<T = unknown>(pathOrDash: string): Promise<T> {\n let text: string;\n if (pathOrDash === '-' || pathOrDash === '/dev/stdin') {\n text = await readStdin();\n } else {\n text = (await readFile(pathOrDash, 'utf8')) as string;\n }\n return JSON.parse(text) as T;\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n let data = '';\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', (chunk) => {\n data += chunk;\n });\n process.stdin.on('end', () => resolve(data));\n process.stdin.on('error', reject);\n });\n}\n\n/** Emit structured output. */\nexport function emit(json: boolean, result: Record<string, unknown>): void {\n if (json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n for (const [k, v] of Object.entries(result)) {\n console.log(`${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`);\n }\n }\n}\n\nexport function die(msg: string, code = 1): never {\n console.error(`error: ${msg}`);\n process.exit(code);\n}\n","// `stamp verify <stamp-path> [content-path]` — run the full SPEC §8\n// verification algorithm locally. Structured JSON output with `--json`.\n\nimport { verify, type StampEnvelope } from '@orangecheck/stamp-core';\n\nimport { die, emit, hashFile, pathExists, readBytes, readJson } from '../util.js';\n\nexport interface VerifyOptions {\n stampPath: string;\n contentPath?: string;\n requireAnchor: boolean;\n /**\n * If set, skip the BIP-322 signature verification. Mostly useful for CI\n * smoke tests with placeholder signatures; production verification should\n * never pass this.\n */\n skipSignature: boolean;\n json: boolean;\n}\n\nexport async function runVerify(opts: VerifyOptions): Promise<void> {\n if (!(await pathExists(opts.stampPath))) die(`no such file: ${opts.stampPath}`);\n\n const envelope = await readJson<StampEnvelope>(opts.stampPath);\n\n let contentBytes: Uint8Array | undefined;\n if (opts.contentPath) {\n if (!(await pathExists(opts.contentPath))) die(`no such file: ${opts.contentPath}`);\n contentBytes = await readBytes(opts.contentPath);\n }\n\n // Lazy-load bip322-js so it's only pulled in when needed (heavy dep).\n let verifyBip322: ((msg: string, sig: string, addr: string) => Promise<boolean>) | undefined;\n if (!opts.skipSignature) {\n const mod = (await import('bip322-js')) as unknown as {\n Verifier?: { verifySignature(a: string, m: string, s: string): boolean };\n default?: { Verifier?: { verifySignature(a: string, m: string, s: string): boolean } };\n };\n const Verifier = mod.Verifier ?? mod.default?.Verifier;\n if (!Verifier) die('bip322-js Verifier export not found');\n verifyBip322 = async (m, s, a) => {\n try {\n return Verifier.verifySignature(a, m, s);\n } catch {\n return false;\n }\n };\n }\n\n const r = await verify({\n envelope,\n content: contentBytes,\n verifyBip322,\n skipSignatureVerification: opts.skipSignature,\n });\n\n if (!r.ok) {\n emit(opts.json, {\n ok: false,\n code: r.code,\n message: r.message,\n });\n process.exit(2);\n }\n\n const anchorLabel =\n r.anchor.status === 'none'\n ? 'none'\n : r.anchor.status === 'pending'\n ? 'pending'\n : `confirmed at block ${r.anchor.blockHeight}`;\n\n if (opts.requireAnchor && r.anchor.status !== 'confirmed') {\n emit(opts.json, {\n ok: false,\n code: 'E_NO_ANCHOR',\n message: `required confirmed OTS anchor, got ${r.anchor.status}`,\n });\n process.exit(2);\n }\n\n emit(opts.json, {\n ok: true,\n id: r.id,\n signer: envelope.signer.address,\n signed_at: envelope.signed_at,\n content_hash: envelope.content.hash,\n content_mime: envelope.content.mime,\n content_length: envelope.content.length,\n content_checked: Boolean(contentBytes),\n anchor: anchorLabel,\n signature_checked: !opts.skipSignature,\n stake: envelope.stake,\n });\n void hashFile;\n}\n","// `stamp anchor <stamp-path>` — submit (or re-submit) an existing stamp's id\n// to OTS calendars. If the proof is already confirmed, no-op. If it's\n// pending, try to upgrade via the listed calendars.\n\nimport { writeFile } from 'node:fs/promises';\n\nimport { submitToCalendars, toStampOts } from '@orangecheck/stamp-ots';\nimport type { StampEnvelope } from '@orangecheck/stamp-core';\n\nimport { die, emit, pathExists, readJson } from '../util.js';\n\nexport interface AnchorOptions {\n stampPath: string;\n json: boolean;\n}\n\nexport async function runAnchor(opts: AnchorOptions): Promise<void> {\n if (!(await pathExists(opts.stampPath))) die(`no such file: ${opts.stampPath}`);\n const envelope = await readJson<StampEnvelope>(opts.stampPath);\n\n if (envelope.ots?.status === 'confirmed') {\n emit(opts.json, {\n ok: true,\n already: 'confirmed',\n block_height: envelope.ots.block_height,\n });\n return;\n }\n\n try {\n const proof = await submitToCalendars(envelope.id);\n const next: StampEnvelope = { ...envelope, ots: toStampOts(proof) };\n await writeFile(opts.stampPath, JSON.stringify(next, null, 2) + '\\n', 'utf8');\n emit(opts.json, {\n ok: true,\n id: next.id,\n status: next.ots?.status,\n calendars: next.ots?.calendars ?? [],\n written: opts.stampPath,\n });\n } catch (e) {\n die(`OTS submission failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n}\n","// `git-stamp tag <tagname>` — stamp a git tag's tree. Meant to be invoked as\n// `git-stamp tag v1.2.3` (the same binary as `stamp`; we detect the alias\n// from argv[1] basename and also accept explicit `git tag` subcommand).\n//\n// The stamp covers the `git rev-parse <tag>^{tree}` output concatenated with\n// the tag name and object id, so changing any of (tree contents, tag object,\n// or tag name) invalidates the envelope.\n\nimport { execFile } from 'node:child_process';\nimport { writeFile, mkdir } from 'node:fs/promises';\nimport { promisify } from 'node:util';\n\nimport { createHash } from 'node:crypto';\nimport { canonicalMessage, stamp, type StampEnvelope } from '@orangecheck/stamp-core';\nimport { submitToCalendars, toStampOts } from '@orangecheck/stamp-ots';\n\nimport { die, emit } from '../util.js';\nimport { createInterface } from 'node:readline/promises';\n\nconst exec = promisify(execFile);\n\nexport interface GitTagOptions {\n tag: string;\n address: string;\n sig?: string;\n anchor: boolean;\n json: boolean;\n}\n\nasync function gitCapture(args: string[]): Promise<string> {\n const { stdout } = await exec('git', args);\n return stdout.trim();\n}\n\nexport async function runGitTag(opts: GitTagOptions): Promise<void> {\n // Validate that we're inside a git repo.\n try {\n await gitCapture(['rev-parse', '--is-inside-work-tree']);\n } catch {\n die('not inside a git work tree');\n }\n\n // Resolve the tag to its commit + tree, and the tag object itself.\n let treeId: string;\n let tagObjectId: string;\n try {\n treeId = await gitCapture(['rev-parse', `${opts.tag}^{tree}`]);\n tagObjectId = await gitCapture(['rev-parse', opts.tag]);\n } catch (e) {\n die(`cannot resolve git tag ${opts.tag}: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n // Canonical content = \"oc-stamp/git-tag:v1\\n\" + tag + \"\\n\" + object_id + \"\\n\" + tree_id.\n // Hashed into content.hash; the whole thing is what the stamp commits to.\n const contentBytes = new TextEncoder().encode(\n `oc-stamp/git-tag:v1\\ntag: ${opts.tag}\\nobject: ${tagObjectId}\\ntree: ${treeId}\\n`\n );\n const contentHash = 'sha256:' + createHash('sha256').update(contentBytes).digest('hex');\n const contentLength = contentBytes.byteLength;\n const mime = 'application/x-git-tag';\n const signedAt = new Date().toISOString().replace(/\\.\\d+Z$/, 'Z');\n\n const msg = canonicalMessage({\n address: opts.address,\n content_hash: contentHash,\n content_length: contentLength,\n content_mime: mime,\n signed_at: signedAt,\n });\n\n let signature: string;\n if (opts.sig) {\n signature = opts.sig;\n } else {\n console.error('\\nSign this message with your Bitcoin wallet (BIP-322):\\n');\n console.error('─'.repeat(60));\n console.error(msg);\n console.error('─'.repeat(60));\n console.error();\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n try {\n signature = (await rl.question('paste signature (base64): ')).trim();\n } finally {\n rl.close();\n }\n if (!signature) die('no signature provided');\n }\n\n const envelope: StampEnvelope = await stamp({\n content: { hash: contentHash, length: contentLength },\n mime,\n signer: {\n address: opts.address,\n signMessage: async () => signature,\n },\n signedAt: new Date(signedAt),\n });\n\n let final = envelope;\n if (opts.anchor) {\n try {\n const proof = await submitToCalendars(envelope.id);\n final = { ...envelope, ots: toStampOts(proof) };\n } catch (e) {\n console.error(\n `warning: OTS submission failed (${e instanceof Error ? e.message : String(e)}). ` +\n `The stamp is still valid; you can retry anchoring later with \\`stamp anchor\\`.`\n );\n }\n }\n\n // Store under .git/stamps/<tag>.stamp — keeps stamps co-located with the\n // repo history and discoverable by `git-stamp verify <tag>` without a\n // separate config.\n const gitDir = await gitCapture(['rev-parse', '--git-dir']);\n const stampsDir = `${gitDir}/stamps`;\n await mkdir(stampsDir, { recursive: true });\n const outPath = `${stampsDir}/${opts.tag}.stamp`;\n await writeFile(outPath, JSON.stringify(final, null, 2) + '\\n', 'utf8');\n\n emit(opts.json, {\n ok: true,\n tag: opts.tag,\n tree: treeId,\n object: tagObjectId,\n id: final.id,\n signer: final.signer.address,\n ots: final.ots?.status ?? 'not anchored',\n written: outPath,\n });\n}\n\nexport interface GitVerifyOptions {\n tag: string;\n requireAnchor: boolean;\n json: boolean;\n}\n\nexport async function runGitVerify(opts: GitVerifyOptions): Promise<void> {\n const gitDir = await gitCapture(['rev-parse', '--git-dir']);\n const stampPath = `${gitDir}/stamps/${opts.tag}.stamp`;\n const { runVerify } = await import('./verify.js');\n await runVerify({\n stampPath,\n requireAnchor: opts.requireAnchor,\n skipSignature: false,\n json: opts.json,\n });\n}\n","// `stamp file <path>` — sign a file with a BIP-322 signature from the user's\n// wallet, submit to OTS calendars, write <path>.stamp alongside.\n//\n// The signing step is done out-of-band: we print the canonical message and\n// wait for the user to paste the signature. Wallet CLIs vary too much to\n// automate reliably, so we keep the coupling loose and well-explained.\n\nimport { appendFile, writeFile } from 'node:fs/promises';\nimport { createInterface } from 'node:readline/promises';\n\nimport { canonicalMessage, stamp, type StampEnvelope, type StampStake } from '@orangecheck/stamp-core';\nimport { submitToCalendars, toStampOts } from '@orangecheck/stamp-ots';\n\nimport { die, emit, hashFile, mimeFromPath, pathExists } from '../util.js';\n\nexport interface StampFileOptions {\n path: string;\n address: string;\n mime?: string;\n signedAt?: string;\n stake?: StampStake;\n anchor: boolean;\n out?: string;\n /** If set, pass-through signature (no interactive prompt). */\n sig?: string;\n json: boolean;\n}\n\nexport async function runStampFile(opts: StampFileOptions): Promise<void> {\n if (!(await pathExists(opts.path))) die(`no such file: ${opts.path}`);\n\n const { hash, length } = await hashFile(opts.path);\n const mime = opts.mime ?? mimeFromPath(opts.path);\n const signedAt = opts.signedAt ?? new Date().toISOString().replace(/\\.\\d+Z$/, 'Z');\n\n const msg = canonicalMessage({\n address: opts.address,\n content_hash: hash,\n content_length: length,\n content_mime: mime,\n signed_at: signedAt,\n });\n\n let signature: string;\n if (opts.sig) {\n signature = opts.sig;\n } else {\n // Interactive: print the message, ask for the BIP-322 signature.\n console.error('\\nSign this message with your Bitcoin wallet (BIP-322):\\n');\n console.error('─'.repeat(60));\n console.error(msg);\n console.error('─'.repeat(60));\n console.error();\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n try {\n signature = (await rl.question('paste signature (base64): ')).trim();\n } finally {\n rl.close();\n }\n if (!signature) die('no signature provided');\n }\n\n const envelope: StampEnvelope = await stamp({\n content: { hash, length },\n mime,\n signer: {\n address: opts.address,\n signMessage: async () => signature,\n },\n signedAt: new Date(signedAt),\n stake: opts.stake,\n });\n\n let final = envelope;\n if (opts.anchor) {\n try {\n const proof = await submitToCalendars(envelope.id);\n final = { ...envelope, ots: toStampOts(proof) };\n } catch (e) {\n console.error(\n `warning: OTS submission failed (${e instanceof Error ? e.message : String(e)}). ` +\n `The stamp is still valid; you can retry anchoring later with \\`stamp anchor\\`.`\n );\n }\n }\n\n const outPath = opts.out ?? `${opts.path}.stamp`;\n await writeFile(outPath, JSON.stringify(final, null, 2) + '\\n', 'utf8');\n\n emit(opts.json, {\n ok: true,\n id: final.id,\n signer: final.signer.address,\n signed_at: final.signed_at,\n content_hash: final.content.hash,\n content_length: final.content.length,\n content_mime: final.content.mime,\n ots: final.ots\n ? `${final.ots.status} (${final.ots.calendars.length} calendar${final.ots.calendars.length === 1 ? '' : 's'})`\n : 'not anchored',\n written: outPath,\n });\n void appendFile;\n}\n","/**\n * @orangecheck/stamp-cli — shell interface to OC Stamp.\n *\n * stamp file <path> — sign a file, optionally anchor\n * stamp verify <stamp> [content] — full SPEC §8 verification\n * stamp anchor <stamp> — submit/re-submit to OTS calendars\n * stamp canonical <path> — print the canonical message (dry run)\n *\n * Git aliases (same binary, invoked as `git-stamp`):\n *\n * git-stamp tag <tagname> — stamp a git tag\n * git-stamp verify <tagname> — verify the stored stamp for a tag\n *\n * The `stamp` and `git-stamp` binaries share this entrypoint — we dispatch\n * on argv[1] basename so each alias shows only its relevant subcommands in\n * --help.\n */\n\nimport { basename } from 'node:path';\n\nimport { Command } from 'commander';\n\nimport { runAnchor } from './commands/anchor.js';\nimport { runGitTag, runGitVerify } from './commands/git-tag.js';\nimport { runStampFile } from './commands/stamp-file.js';\nimport { runVerify } from './commands/verify.js';\n\nimport { canonicalMessage } from '@orangecheck/stamp-core';\nimport { hashFile, mimeFromPath } from './util.js';\n\nconst invoked = basename(process.argv[1] ?? 'stamp');\n\nconst program = new Command();\n\nif (invoked.startsWith('git-stamp')) {\n // git-stamp alias: narrow, tag-focused surface.\n program\n .name('git-stamp')\n .description('Stamp git tags with your Bitcoin address, anchored to Bitcoin.')\n .version('0.1.0');\n\n program\n .command('tag <tagname>')\n .description('Sign and (optionally) anchor a stamp over <tagname>^{tree}')\n .requiredOption('--addr <address>', 'Bitcoin address')\n .option('--sig <signature>', 'BIP-322 signature (non-interactive mode)')\n .option('--no-anchor', 'Skip OTS calendar submission')\n .option('--json', 'Emit JSON')\n .action(async (tag, opts) => {\n await runGitTag({\n tag,\n address: opts.addr,\n sig: opts.sig,\n anchor: Boolean(opts.anchor),\n json: Boolean(opts.json),\n });\n });\n\n program\n .command('verify <tagname>')\n .description('Verify the stamp stored under .git/stamps/<tagname>.stamp')\n .option('--require-anchor', 'Fail unless the OTS proof is confirmed')\n .option('--json', 'Emit JSON')\n .action(async (tag, opts) => {\n await runGitVerify({\n tag,\n requireAnchor: Boolean(opts.requireAnchor),\n json: Boolean(opts.json),\n });\n });\n} else {\n program\n .name('stamp')\n .description('OC Stamp — sign anything with your Bitcoin address, anchor to Bitcoin.')\n .version('0.1.0');\n\n program\n .command('file <path>')\n .description('Sign a file and write <path>.stamp alongside')\n .requiredOption('--addr <address>', 'Bitcoin address')\n .option('--mime <type>', 'Override the MIME type (default: inferred from extension)')\n .option('--signed-at <iso>', 'Override signed_at (default: now)')\n .option('--sig <signature>', 'BIP-322 signature (non-interactive mode)')\n .option('--no-anchor', 'Skip OTS calendar submission')\n .option('--out <path>', 'Output path (default: <path>.stamp)')\n .option('--json', 'Emit JSON')\n .action(async (path, opts) => {\n await runStampFile({\n path,\n address: opts.addr,\n mime: opts.mime,\n signedAt: opts.signedAt,\n sig: opts.sig,\n anchor: Boolean(opts.anchor),\n out: opts.out,\n json: Boolean(opts.json),\n });\n });\n\n program\n .command('verify <stamp> [content]')\n .description('Run the full SPEC §8 verification')\n .option('--require-anchor', 'Fail unless the OTS proof is confirmed')\n .option('--skip-signature', 'Skip BIP-322 verification (for CI smoke tests only)')\n .option('--json', 'Emit JSON')\n .action(async (stampPath, contentPath, opts) => {\n await runVerify({\n stampPath,\n contentPath,\n requireAnchor: Boolean(opts.requireAnchor),\n skipSignature: Boolean(opts.skipSignature),\n json: Boolean(opts.json),\n });\n });\n\n program\n .command('anchor <stamp>')\n .description('Submit an existing stamp envelope to OTS calendars')\n .option('--json', 'Emit JSON')\n .action(async (stampPath, opts) => {\n await runAnchor({ stampPath, json: Boolean(opts.json) });\n });\n\n program\n .command('canonical <path>')\n .description('Print the canonical message a stamp over <path> would sign (dry run)')\n .requiredOption('--addr <address>', 'Bitcoin address')\n .option('--mime <type>', 'Override the MIME type')\n .option('--signed-at <iso>', 'Override signed_at (default: now)')\n .action(async (path, opts) => {\n const { hash, length } = await hashFile(path);\n const msg = canonicalMessage({\n address: opts.addr,\n content_hash: hash,\n content_length: length,\n content_mime: opts.mime ?? mimeFromPath(path),\n signed_at: opts.signedAt ?? new Date().toISOString().replace(/\\.\\d+Z$/, 'Z'),\n });\n process.stdout.write(msg);\n // No trailing newline — the canonical message itself has no trailing\n // LF after signed_at, and users pipe this directly into signing tools.\n });\n}\n\nprogram.parseAsync(process.argv).catch((err) => {\n console.error(`error: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/anchor-check.ts","../src/util.ts","../src/commands/verify.ts","../src/commands/anchor.ts","../src/commands/git-tag.ts","../src/commands/stamp-file.ts","../src/cli.ts"],"names":["verify","mempoolHeaderSource","createHash","submitToCalendars","toStampOts","writeFile","runVerify","canonicalMessage","createInterface","stamp","basename"],"mappings":"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","file":"cli.js","sourcesContent":["// SPEC §6.3 / §8 step 5 for the CLI: a claimed OTS anchor is only reported as\n// anchored once the proof chains to the block header at the claimed height.\n\nimport type { StampEnvelope } from '@orangecheck/stamp-core';\nimport {\n fromStampOts,\n makeAnchorVerifier,\n submitToCalendars,\n toStampOts,\n upgradeProof,\n type BlockHeaderSource,\n} from '@orangecheck/stamp-ots';\n\nexport type AnchorState = 'anchored' | 'unverified' | 'pending' | 'none' | 'fail';\n\nexport interface AnchorOutcome {\n state: AnchorState;\n blockHeight?: number;\n message?: string;\n}\n\n/**\n * Check the envelope's anchor claim. A header source that cannot answer leaves\n * the claim unverified (offline verifiers MAY defer, §6.3); a header that\n * answers and does not match fails it.\n */\nexport async function checkAnchorClaim(\n env: StampEnvelope,\n headers: BlockHeaderSource\n): Promise<AnchorOutcome> {\n const ots = env.ots;\n if (!ots) return { state: 'none' };\n if (ots.status !== 'confirmed' || ots.block_height === null || !ots.block_hash) {\n return { state: 'pending' };\n }\n const blockHeight = ots.block_height;\n let header: Uint8Array | null = null;\n try {\n header = await headers.getHeaderAt(blockHeight);\n } catch {\n header = null;\n }\n if (!header) {\n return { state: 'unverified', blockHeight, message: 'block header source unreachable' };\n }\n const verify = makeAnchorVerifier({ headerSource: { getHeaderAt: async () => header } });\n const ok = await verify(ots.proof, blockHeight, ots.block_hash, env.id);\n return ok\n ? { state: 'anchored', blockHeight }\n : { state: 'fail', blockHeight, message: `OTS proof does not chain to block ${blockHeight}` };\n}\n\n/**\n * The next OTS state for an envelope: submit when it has no proof, ask the\n * listed calendars to upgrade a pending one, leave a confirmed one alone.\n */\nexport async function advanceOts(\n env: StampEnvelope,\n opts: { headers: BlockHeaderSource; fetch?: typeof fetch }\n): Promise<StampEnvelope> {\n if (!env.ots) {\n const proof = await submitToCalendars(env.id, { fetch: opts.fetch });\n return { ...env, ots: toStampOts(proof) };\n }\n if (env.ots.status === 'confirmed') return env;\n const next = await upgradeProof(fromStampOts(env.ots), env.id, {\n headerSource: opts.headers,\n fetch: opts.fetch,\n });\n return { ...env, ots: toStampOts(next) };\n}\n","// Shared helpers for stamp-cli commands.\n\nimport { createHash } from 'node:crypto';\nimport { readFile, stat } from 'node:fs/promises';\nimport { basename } from 'node:path';\n\n/** Read a path into bytes. */\nexport async function readBytes(path: string): Promise<Uint8Array> {\n const buf = await readFile(path);\n return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);\n}\n\n/**\n * Stream-hash a path with SHA-256. For very large content we want to avoid\n * loading the whole file into memory; for small files the cost is negligible.\n */\nexport async function hashFile(path: string): Promise<{ hash: string; length: number }> {\n const bytes = await readBytes(path);\n const h = createHash('sha256').update(bytes).digest('hex');\n return { hash: 'sha256:' + h, length: bytes.byteLength };\n}\n\n/** Infer a conservative MIME from a filename. Falls back to application/octet-stream. */\nexport function mimeFromPath(path: string): string {\n const name = basename(path).toLowerCase();\n const ext = name.split('.').pop();\n switch (ext) {\n case 'md':\n case 'markdown':\n return 'text/markdown';\n case 'txt':\n return 'text/plain';\n case 'html':\n case 'htm':\n return 'text/html';\n case 'json':\n return 'application/json';\n case 'pdf':\n return 'application/pdf';\n case 'png':\n return 'image/png';\n case 'jpg':\n case 'jpeg':\n return 'image/jpeg';\n case 'gif':\n return 'image/gif';\n case 'webp':\n return 'image/webp';\n case 'mp3':\n return 'audio/mpeg';\n case 'mp4':\n return 'video/mp4';\n case 'wav':\n return 'audio/wav';\n case 'zip':\n return 'application/zip';\n case 'tar':\n return 'application/x-tar';\n case 'gz':\n return 'application/gzip';\n default:\n return 'application/octet-stream';\n }\n}\n\nexport async function pathExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read JSON from a path or `-` for stdin.\n */\nexport async function readJson<T = unknown>(pathOrDash: string): Promise<T> {\n let text: string;\n if (pathOrDash === '-' || pathOrDash === '/dev/stdin') {\n text = await readStdin();\n } else {\n text = (await readFile(pathOrDash, 'utf8')) as string;\n }\n return JSON.parse(text) as T;\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n let data = '';\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', (chunk) => {\n data += chunk;\n });\n process.stdin.on('end', () => resolve(data));\n process.stdin.on('error', reject);\n });\n}\n\n/** Emit structured output. */\nexport function emit(json: boolean, result: Record<string, unknown>): void {\n if (json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n for (const [k, v] of Object.entries(result)) {\n console.log(`${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`);\n }\n }\n}\n\nexport function die(msg: string, code = 1): never {\n console.error(`error: ${msg}`);\n process.exit(code);\n}\n","// `stamp verify <stamp-path> [content-path]` — run the full SPEC §8\n// verification algorithm locally. Structured JSON output with `--json`.\n\nimport { verify, type StampEnvelope } from '@orangecheck/stamp-core';\nimport { mempoolHeaderSource } from '@orangecheck/stamp-ots';\n\nimport { checkAnchorClaim } from '../anchor-check.js';\n\nimport { die, emit, hashFile, pathExists, readBytes, readJson } from '../util.js';\n\nexport interface VerifyOptions {\n stampPath: string;\n contentPath?: string;\n requireAnchor: boolean;\n /**\n * If set, skip the BIP-322 signature verification. Mostly useful for CI\n * smoke tests with placeholder signatures; production verification should\n * never pass this.\n */\n skipSignature: boolean;\n /** Esplora-compatible API for block headers. Default mempool.space. */\n headersUrl?: string;\n json: boolean;\n}\n\nexport async function runVerify(opts: VerifyOptions): Promise<void> {\n if (!(await pathExists(opts.stampPath))) die(`no such file: ${opts.stampPath}`);\n\n const envelope = await readJson<StampEnvelope>(opts.stampPath);\n\n let contentBytes: Uint8Array | undefined;\n if (opts.contentPath) {\n if (!(await pathExists(opts.contentPath))) die(`no such file: ${opts.contentPath}`);\n contentBytes = await readBytes(opts.contentPath);\n }\n\n // Lazy-load bip322-js so it's only pulled in when needed (heavy dep).\n let verifyBip322: ((msg: string, sig: string, addr: string) => Promise<boolean>) | undefined;\n if (!opts.skipSignature) {\n const mod = (await import('bip322-js')) as unknown as {\n Verifier?: { verifySignature(a: string, m: string, s: string): boolean };\n default?: { Verifier?: { verifySignature(a: string, m: string, s: string): boolean } };\n };\n const Verifier = mod.Verifier ?? mod.default?.Verifier;\n if (!Verifier) die('bip322-js Verifier export not found');\n verifyBip322 = async (m, s, a) => {\n try {\n return Verifier.verifySignature(a, m, s);\n } catch {\n return false;\n }\n };\n }\n\n const r = await verify({\n envelope,\n content: contentBytes,\n verifyBip322,\n skipSignatureVerification: opts.skipSignature,\n });\n\n if (!r.ok) {\n emit(opts.json, {\n ok: false,\n code: r.code,\n message: r.message,\n });\n process.exit(2);\n }\n\n const anchor = await checkAnchorClaim(\n envelope,\n mempoolHeaderSource({ baseUrl: opts.headersUrl })\n );\n if (anchor.state === 'fail') {\n emit(opts.json, { ok: false, code: 'E_BAD_ANCHOR', message: anchor.message });\n process.exit(2);\n }\n\n const anchorLabel =\n anchor.state === 'anchored'\n ? `confirmed at block ${anchor.blockHeight} (checked against the block header)`\n : anchor.state === 'unverified'\n ? `claims block ${anchor.blockHeight}, unverified: ${anchor.message}`\n : anchor.state;\n\n if (opts.requireAnchor && anchor.state !== 'anchored') {\n emit(opts.json, {\n ok: false,\n code: 'E_NO_ANCHOR',\n message: `required a verified OTS anchor, got ${anchor.state}`,\n });\n process.exit(2);\n }\n\n emit(opts.json, {\n ok: true,\n id: r.id,\n signer: envelope.signer.address,\n signed_at: envelope.signed_at,\n content_hash: envelope.content.hash,\n content_mime: envelope.content.mime,\n content_length: envelope.content.length,\n content_checked: Boolean(contentBytes),\n anchor: anchorLabel,\n anchor_state: anchor.state,\n signature_checked: !opts.skipSignature,\n stake: envelope.stake,\n });\n void hashFile;\n}\n","// `stamp anchor <stamp-path>` — advance a stamp's OTS proof: submit its id to\n// the calendars when it has none, ask the listed calendars to upgrade a\n// pending one, leave a confirmed one alone.\n\nimport { writeFile } from 'node:fs/promises';\n\nimport type { StampEnvelope } from '@orangecheck/stamp-core';\nimport { mempoolHeaderSource } from '@orangecheck/stamp-ots';\n\nimport { advanceOts } from '../anchor-check.js';\nimport { die, emit, pathExists, readJson } from '../util.js';\n\nexport interface AnchorOptions {\n stampPath: string;\n /** Esplora-compatible API for block headers. Default mempool.space. */\n headersUrl?: string;\n json: boolean;\n}\n\nexport async function runAnchor(opts: AnchorOptions): Promise<void> {\n if (!(await pathExists(opts.stampPath))) die(`no such file: ${opts.stampPath}`);\n const envelope = await readJson<StampEnvelope>(opts.stampPath);\n\n if (envelope.ots?.status === 'confirmed') {\n emit(opts.json, {\n ok: true,\n already: 'confirmed',\n block_height: envelope.ots.block_height,\n });\n return;\n }\n\n let next: StampEnvelope;\n try {\n next = await advanceOts(envelope, {\n headers: mempoolHeaderSource({ baseUrl: opts.headersUrl }),\n });\n } catch (e) {\n die(`OTS ${envelope.ots ? 'upgrade' : 'submission'} failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n const changed = JSON.stringify(next.ots) !== JSON.stringify(envelope.ots);\n if (changed) {\n await writeFile(opts.stampPath, JSON.stringify(next, null, 2) + '\\n', 'utf8');\n }\n emit(opts.json, {\n ok: true,\n id: next.id,\n status: next.ots?.status,\n block_height: next.ots?.block_height ?? null,\n calendars: next.ots?.calendars ?? [],\n written: changed ? opts.stampPath : null,\n });\n}\n","// `git-stamp tag <tagname>` — stamp a git tag's tree. Meant to be invoked as\n// `git-stamp tag v1.2.3` (the same binary as `stamp`; we detect the alias\n// from argv[1] basename and also accept explicit `git tag` subcommand).\n//\n// The stamp covers the `git rev-parse <tag>^{tree}` output concatenated with\n// the tag name and object id, so changing any of (tree contents, tag object,\n// or tag name) invalidates the envelope.\n\nimport { execFile } from 'node:child_process';\nimport { writeFile, mkdir } from 'node:fs/promises';\nimport { promisify } from 'node:util';\n\nimport { createHash } from 'node:crypto';\nimport { canonicalMessage, stamp, type StampEnvelope } from '@orangecheck/stamp-core';\nimport { submitToCalendars, toStampOts } from '@orangecheck/stamp-ots';\n\nimport { die, emit } from '../util.js';\nimport { createInterface } from 'node:readline/promises';\n\nconst exec = promisify(execFile);\n\nexport interface GitTagOptions {\n tag: string;\n address: string;\n sig?: string;\n anchor: boolean;\n json: boolean;\n}\n\nasync function gitCapture(args: string[]): Promise<string> {\n const { stdout } = await exec('git', args);\n return stdout.trim();\n}\n\nexport async function runGitTag(opts: GitTagOptions): Promise<void> {\n // Validate that we're inside a git repo.\n try {\n await gitCapture(['rev-parse', '--is-inside-work-tree']);\n } catch {\n die('not inside a git work tree');\n }\n\n // Resolve the tag to its commit + tree, and the tag object itself.\n let treeId: string;\n let tagObjectId: string;\n try {\n treeId = await gitCapture(['rev-parse', `${opts.tag}^{tree}`]);\n tagObjectId = await gitCapture(['rev-parse', opts.tag]);\n } catch (e) {\n die(`cannot resolve git tag ${opts.tag}: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n // Canonical content = \"oc-stamp/git-tag:v1\\n\" + tag + \"\\n\" + object_id + \"\\n\" + tree_id.\n // Hashed into content.hash; the whole thing is what the stamp commits to.\n const contentBytes = new TextEncoder().encode(\n `oc-stamp/git-tag:v1\\ntag: ${opts.tag}\\nobject: ${tagObjectId}\\ntree: ${treeId}\\n`\n );\n const contentHash = 'sha256:' + createHash('sha256').update(contentBytes).digest('hex');\n const contentLength = contentBytes.byteLength;\n const mime = 'application/x-git-tag';\n const signedAt = new Date().toISOString().replace(/\\.\\d+Z$/, 'Z');\n\n const msg = canonicalMessage({\n address: opts.address,\n content_hash: contentHash,\n content_length: contentLength,\n content_mime: mime,\n signed_at: signedAt,\n });\n\n let signature: string;\n if (opts.sig) {\n signature = opts.sig;\n } else {\n console.error('\\nSign this message with your Bitcoin wallet (BIP-322):\\n');\n console.error('─'.repeat(60));\n console.error(msg);\n console.error('─'.repeat(60));\n console.error();\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n try {\n signature = (await rl.question('paste signature (base64): ')).trim();\n } finally {\n rl.close();\n }\n if (!signature) die('no signature provided');\n }\n\n const envelope: StampEnvelope = await stamp({\n content: { hash: contentHash, length: contentLength },\n mime,\n signer: {\n address: opts.address,\n signMessage: async () => signature,\n },\n signedAt: new Date(signedAt),\n });\n\n let final = envelope;\n if (opts.anchor) {\n try {\n const proof = await submitToCalendars(envelope.id);\n final = { ...envelope, ots: toStampOts(proof) };\n } catch (e) {\n console.error(\n `warning: OTS submission failed (${e instanceof Error ? e.message : String(e)}). ` +\n `The stamp is still valid; you can retry anchoring later with \\`stamp anchor\\`.`\n );\n }\n }\n\n // Store under .git/stamps/<tag>.stamp — keeps stamps co-located with the\n // repo history and discoverable by `git-stamp verify <tag>` without a\n // separate config.\n const gitDir = await gitCapture(['rev-parse', '--git-dir']);\n const stampsDir = `${gitDir}/stamps`;\n await mkdir(stampsDir, { recursive: true });\n const outPath = `${stampsDir}/${opts.tag}.stamp`;\n await writeFile(outPath, JSON.stringify(final, null, 2) + '\\n', 'utf8');\n\n emit(opts.json, {\n ok: true,\n tag: opts.tag,\n tree: treeId,\n object: tagObjectId,\n id: final.id,\n signer: final.signer.address,\n ots: final.ots?.status ?? 'not anchored',\n written: outPath,\n });\n}\n\nexport interface GitVerifyOptions {\n tag: string;\n requireAnchor: boolean;\n json: boolean;\n}\n\nexport async function runGitVerify(opts: GitVerifyOptions): Promise<void> {\n const gitDir = await gitCapture(['rev-parse', '--git-dir']);\n const stampPath = `${gitDir}/stamps/${opts.tag}.stamp`;\n const { runVerify } = await import('./verify.js');\n await runVerify({\n stampPath,\n requireAnchor: opts.requireAnchor,\n skipSignature: false,\n json: opts.json,\n });\n}\n","// `stamp file <path>` — sign a file with a BIP-322 signature from the user's\n// wallet, submit to OTS calendars, write <path>.stamp alongside.\n//\n// The signing step is done out-of-band: we print the canonical message and\n// wait for the user to paste the signature. Wallet CLIs vary too much to\n// automate reliably, so we keep the coupling loose and well-explained.\n\nimport { appendFile, writeFile } from 'node:fs/promises';\nimport { createInterface } from 'node:readline/promises';\n\nimport { canonicalMessage, stamp, type StampEnvelope, type StampStake } from '@orangecheck/stamp-core';\nimport { submitToCalendars, toStampOts } from '@orangecheck/stamp-ots';\n\nimport { die, emit, hashFile, mimeFromPath, pathExists } from '../util.js';\n\nexport interface StampFileOptions {\n path: string;\n address: string;\n mime?: string;\n signedAt?: string;\n stake?: StampStake;\n anchor: boolean;\n out?: string;\n /** If set, pass-through signature (no interactive prompt). */\n sig?: string;\n json: boolean;\n}\n\nexport async function runStampFile(opts: StampFileOptions): Promise<void> {\n if (!(await pathExists(opts.path))) die(`no such file: ${opts.path}`);\n\n const { hash, length } = await hashFile(opts.path);\n const mime = opts.mime ?? mimeFromPath(opts.path);\n const signedAt = opts.signedAt ?? new Date().toISOString().replace(/\\.\\d+Z$/, 'Z');\n\n const msg = canonicalMessage({\n address: opts.address,\n content_hash: hash,\n content_length: length,\n content_mime: mime,\n signed_at: signedAt,\n });\n\n let signature: string;\n if (opts.sig) {\n signature = opts.sig;\n } else {\n // Interactive: print the message, ask for the BIP-322 signature.\n console.error('\\nSign this message with your Bitcoin wallet (BIP-322):\\n');\n console.error('─'.repeat(60));\n console.error(msg);\n console.error('─'.repeat(60));\n console.error();\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n try {\n signature = (await rl.question('paste signature (base64): ')).trim();\n } finally {\n rl.close();\n }\n if (!signature) die('no signature provided');\n }\n\n const envelope: StampEnvelope = await stamp({\n content: { hash, length },\n mime,\n signer: {\n address: opts.address,\n signMessage: async () => signature,\n },\n signedAt: new Date(signedAt),\n stake: opts.stake,\n });\n\n let final = envelope;\n if (opts.anchor) {\n try {\n const proof = await submitToCalendars(envelope.id);\n final = { ...envelope, ots: toStampOts(proof) };\n } catch (e) {\n console.error(\n `warning: OTS submission failed (${e instanceof Error ? e.message : String(e)}). ` +\n `The stamp is still valid; you can retry anchoring later with \\`stamp anchor\\`.`\n );\n }\n }\n\n const outPath = opts.out ?? `${opts.path}.stamp`;\n await writeFile(outPath, JSON.stringify(final, null, 2) + '\\n', 'utf8');\n\n emit(opts.json, {\n ok: true,\n id: final.id,\n signer: final.signer.address,\n signed_at: final.signed_at,\n content_hash: final.content.hash,\n content_length: final.content.length,\n content_mime: final.content.mime,\n ots: final.ots\n ? `${final.ots.status} (${final.ots.calendars.length} calendar${final.ots.calendars.length === 1 ? '' : 's'})`\n : 'not anchored',\n written: outPath,\n });\n void appendFile;\n}\n","/**\n * @orangecheck/stamp-cli — shell interface to OC Stamp.\n *\n * stamp file <path> — sign a file, optionally anchor\n * stamp verify <stamp> [content] — full SPEC §8 verification\n * stamp anchor <stamp> — submit to OTS calendars, or upgrade a pending proof\n * stamp canonical <path> — print the canonical message (dry run)\n *\n * Git aliases (same binary, invoked as `git-stamp`):\n *\n * git-stamp tag <tagname> — stamp a git tag\n * git-stamp verify <tagname> — verify the stored stamp for a tag\n *\n * The `stamp` and `git-stamp` binaries share this entrypoint — we dispatch\n * on argv[1] basename so each alias shows only its relevant subcommands in\n * --help.\n */\n\nimport { basename } from 'node:path';\n\nimport { Command } from 'commander';\n\nimport { runAnchor } from './commands/anchor.js';\nimport { runGitTag, runGitVerify } from './commands/git-tag.js';\nimport { runStampFile } from './commands/stamp-file.js';\nimport { runVerify } from './commands/verify.js';\n\nimport { canonicalMessage } from '@orangecheck/stamp-core';\nimport { hashFile, mimeFromPath } from './util.js';\n\nconst invoked = basename(process.argv[1] ?? 'stamp');\n\nconst program = new Command();\n\nif (invoked.startsWith('git-stamp')) {\n // git-stamp alias: narrow, tag-focused surface.\n program\n .name('git-stamp')\n .description('Stamp git tags with your Bitcoin address, anchored to Bitcoin.')\n .version('0.2.0');\n\n program\n .command('tag <tagname>')\n .description('Sign and (optionally) anchor a stamp over <tagname>^{tree}')\n .requiredOption('--addr <address>', 'Bitcoin address')\n .option('--sig <signature>', 'BIP-322 signature (non-interactive mode)')\n .option('--no-anchor', 'Skip OTS calendar submission')\n .option('--json', 'Emit JSON')\n .action(async (tag, opts) => {\n await runGitTag({\n tag,\n address: opts.addr,\n sig: opts.sig,\n anchor: Boolean(opts.anchor),\n json: Boolean(opts.json),\n });\n });\n\n program\n .command('verify <tagname>')\n .description('Verify the stamp stored under .git/stamps/<tagname>.stamp')\n .option('--require-anchor', 'Fail unless the OTS anchor is confirmed and checked against the block header')\n .option('--json', 'Emit JSON')\n .action(async (tag, opts) => {\n await runGitVerify({\n tag,\n requireAnchor: Boolean(opts.requireAnchor),\n json: Boolean(opts.json),\n });\n });\n} else {\n program\n .name('stamp')\n .description('OC Stamp — sign anything with your Bitcoin address, anchor to Bitcoin.')\n .version('0.2.0');\n\n program\n .command('file <path>')\n .description('Sign a file and write <path>.stamp alongside')\n .requiredOption('--addr <address>', 'Bitcoin address')\n .option('--mime <type>', 'Override the MIME type (default: inferred from extension)')\n .option('--signed-at <iso>', 'Override signed_at (default: now)')\n .option('--sig <signature>', 'BIP-322 signature (non-interactive mode)')\n .option('--no-anchor', 'Skip OTS calendar submission')\n .option('--out <path>', 'Output path (default: <path>.stamp)')\n .option('--json', 'Emit JSON')\n .action(async (path, opts) => {\n await runStampFile({\n path,\n address: opts.addr,\n mime: opts.mime,\n signedAt: opts.signedAt,\n sig: opts.sig,\n anchor: Boolean(opts.anchor),\n out: opts.out,\n json: Boolean(opts.json),\n });\n });\n\n program\n .command('verify <stamp> [content]')\n .description('Run the full SPEC §8 verification')\n .option('--require-anchor', 'Fail unless the OTS anchor is confirmed and checked against the block header')\n .option('--skip-signature', 'Skip BIP-322 verification (for CI smoke tests only)')\n .option('--headers-url <url>', 'Esplora API for block headers (default: https://mempool.space/api)')\n .option('--json', 'Emit JSON')\n .action(async (stampPath, contentPath, opts) => {\n await runVerify({\n stampPath,\n contentPath,\n requireAnchor: Boolean(opts.requireAnchor),\n skipSignature: Boolean(opts.skipSignature),\n headersUrl: opts.headersUrl,\n json: Boolean(opts.json),\n });\n });\n\n program\n .command('anchor <stamp>')\n .description('Submit a stamp to OTS calendars, or upgrade its pending proof')\n .option('--headers-url <url>', 'Esplora API for block headers (default: https://mempool.space/api)')\n .option('--json', 'Emit JSON')\n .action(async (stampPath, opts) => {\n await runAnchor({ stampPath, headersUrl: opts.headersUrl, json: Boolean(opts.json) });\n });\n\n program\n .command('canonical <path>')\n .description('Print the canonical message a stamp over <path> would sign (dry run)')\n .requiredOption('--addr <address>', 'Bitcoin address')\n .option('--mime <type>', 'Override the MIME type')\n .option('--signed-at <iso>', 'Override signed_at (default: now)')\n .action(async (path, opts) => {\n const { hash, length } = await hashFile(path);\n const msg = canonicalMessage({\n address: opts.addr,\n content_hash: hash,\n content_length: length,\n content_mime: opts.mime ?? mimeFromPath(path),\n signed_at: opts.signedAt ?? new Date().toISOString().replace(/\\.\\d+Z$/, 'Z'),\n });\n process.stdout.write(msg);\n // No trailing newline — the canonical message itself has no trailing\n // LF after signed_at, and users pipe this directly into signing tools.\n });\n}\n\nprogram.parseAsync(process.argv).catch((err) => {\n console.error(`error: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,58 +1,61 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
2
|
+
"name": "@orangecheck/stamp-cli",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Shell interface to OC Stamp — sign files and git tags with your Bitcoin address, anchor to Bitcoin, verify offline. Exposes `stamp` and `git-stamp` binaries.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"bitcoin",
|
|
7
|
+
"bip322",
|
|
8
|
+
"opentimestamps",
|
|
9
|
+
"provenance",
|
|
10
|
+
"oc-stamp",
|
|
11
|
+
"git-stamp",
|
|
12
|
+
"cli",
|
|
13
|
+
"orangecheck"
|
|
14
|
+
],
|
|
15
|
+
"author": "OrangeCheck",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/orangecheck/oc-packages.git",
|
|
20
|
+
"directory": "stamp-cli"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://stamp.ochk.io",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/orangecheck/oc-stamp-protocol/issues"
|
|
25
|
+
},
|
|
26
|
+
"type": "module",
|
|
27
|
+
"bin": {
|
|
28
|
+
"stamp": "./dist/cli.js",
|
|
29
|
+
"git-stamp": "./dist/cli.js"
|
|
30
|
+
},
|
|
31
|
+
"main": "./dist/cli.js",
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"dev": "tsup --watch",
|
|
40
|
+
"type-check": "tsc --noEmit",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"test:watch": "vitest",
|
|
43
|
+
"clean": "rm -rf dist",
|
|
44
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@orangecheck/stamp-core": "^1.0.0",
|
|
48
|
+
"@orangecheck/stamp-ots": "^0.3.0",
|
|
49
|
+
"bip322-js": "^3.0.0",
|
|
50
|
+
"commander": "^12.1.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "^22.10.2",
|
|
54
|
+
"tsup": "^8.3.5",
|
|
55
|
+
"typescript": "^5.7.2",
|
|
56
|
+
"vitest": "^4.1.11"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
}
|
|
58
61
|
}
|