twzrd-receipt-verifier 1.1.0 → 1.2.1

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
@@ -80,7 +80,7 @@ verified_tx, behavior_proof, minted_at}` (exact key order). The `wallet` is the
80
80
  first signed field but is **not** stored in the anchor - it is the `<wallet>.json`
81
81
  filename / the cNFT leaf owner - so pass `--wallet` or keep the filename. The
82
82
  signing key (`2ELSDx...`) is **built in** to the verifier (pinned in the audited
83
- package); override with `--pubkey`.
83
+ package); override with `--pubkey`, or fetch the published copy with `--fetch-key`.
84
84
 
85
85
  ```bash
86
86
  # fetch a receipt and verify it (wallet inferred from the filename, key built-in)
@@ -90,8 +90,17 @@ npx twzrd-receipt-verifier $W.json --self-test
90
90
 
91
91
  # or pass the wallet explicitly (e.g. when piping from stdin)
92
92
  npx twzrd-receipt-verifier anchor.json --wallet $W
93
+
94
+ # fetch the key from the published descriptor instead of the built-in copy
95
+ # (cross-check, or pin to whatever the live domain publishes)
96
+ npx twzrd-receipt-verifier $W.json --fetch-key
93
97
  ```
94
98
 
99
+ The key is published, machine-readable, at `https://api.twzrd.xyz/v1/receipts/pubkey`
100
+ (and `https://twzrd.xyz/.well-known/twzrd-receipt-pubkey`) with the full signing spec
101
+ (`public_key`, `signed_fields`, `scheme`, `tree`). It must equal the built-in key **and**
102
+ the on-chain verified creator of every cNFT in the tree - three independent sources.
103
+
95
104
  ```
96
105
  mode : cNFT (Bubblegum anchor)
97
106
  trusted pubkey : 2ELSDxLkb7dYrN6EUG69tNtULAq4Fo7WPvXyrZPmuFif [source: built-in genesis authority]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "twzrd-receipt-verifier",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Standalone offline verifier for TWZRD receipts: AO-Receipt V5/V6 (keccak256 leaf) and genesis cNFT receipts (Ed25519 over compact JSON). No trust in TWZRD servers or code.",
5
5
  "keywords": [
6
6
  "twzrd",
@@ -44,9 +44,12 @@ const DEFAULT_BASE_URL = 'https://intel.twzrd.xyz';
44
44
  const KECCAK_EMPTY = 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470';
45
45
  // Genesis cNFT receipt authority (airship). Baked in as the most paranoid form of
46
46
  // out-of-band pinning: the key ships in this audited package, never fetched live.
47
- // Override with --pubkey. Matches `verify_pubkey` in every genesis anchor and the
48
- // verified creator on every cNFT in tree 8QFdTqBkSeyuvp47dXdpwfWzXTuYSbAC64oT4soPGnXS.
47
+ // Override with --pubkey, or fetch the published copy with --fetch-key (cross-check).
48
+ // Matches `verify_pubkey` in every genesis anchor and the verified creator on every
49
+ // cNFT in tree 8QFdTqBkSeyuvp47dXdpwfWzXTuYSbAC64oT4soPGnXS.
49
50
  const DEFAULT_CNFT_PUBKEY = '2ELSDxLkb7dYrN6EUG69tNtULAq4Fo7WPvXyrZPmuFif';
51
+ // Where --fetch-key looks for the published cNFT key descriptor.
52
+ const DEFAULT_CNFT_BASE_URL = 'https://api.twzrd.xyz';
50
53
 
51
54
  function b58decode(s) { return Buffer.from(bs58.decode(s)); }
52
55
 
@@ -146,6 +149,32 @@ function fetchPublishedPubkey(baseUrl) {
146
149
  return fetchPath(0);
147
150
  }
148
151
 
152
+ // Fetch the published cNFT signing key descriptor (for --fetch-key). Returns the
153
+ // base58 pubkey. This trades package-trust for domain/TLS-trust; the built-in key is
154
+ // the default precisely because it needs no network. Use this to CROSS-CHECK the
155
+ // built-in, or to pin to whatever the live domain currently publishes.
156
+ function fetchCnftPubkey(baseUrl) {
157
+ const base = baseUrl.replace(/\/+$/, '');
158
+ const paths = ['/v1/receipts/pubkey', '/.well-known/twzrd-receipt-pubkey'];
159
+ const headers = { 'User-Agent': 'twzrd-receipt-verifier/cnft' };
160
+ function fetchPath(i) {
161
+ if (i >= paths.length) return Promise.reject(new Error('no cNFT pubkey endpoint responded'));
162
+ return new Promise((resolve, reject) => {
163
+ https.get(base + paths[i], { headers }, (res) => {
164
+ let body = '';
165
+ res.on('data', (c) => (body += c));
166
+ res.on('end', () => {
167
+ try {
168
+ const pk = JSON.parse(body).public_key;
169
+ if (pk) resolve(pk); else throw new Error('no public_key field');
170
+ } catch (e) { fetchPath(i + 1).then(resolve, reject); }
171
+ });
172
+ }).on('error', () => fetchPath(i + 1).then(resolve, reject));
173
+ });
174
+ }
175
+ return fetchPath(0);
176
+ }
177
+
149
178
  function verify(receipt, trustedPubkey) {
150
179
  const out = { leaf_valid: false, signature_valid: false, errors: [] };
151
180
  const pre = receipt.preimage || {};
@@ -275,14 +304,18 @@ TWZRD's published Ed25519 key and was not tampered with. Auto-detects two famili
275
304
  - cNFT Receipt (genesis anchor): compact-JSON payload, signed by ${DEFAULT_CNFT_PUBKEY.slice(0, 7)}... (built-in)
276
305
 
277
306
  usage:
278
- twzrd-receipt-verifier <receipt.json|-> [--pubkey KEY] [--wallet ADDR] [--base-url URL] [--max-age SECS] [--self-test]
307
+ twzrd-receipt-verifier <receipt.json|-> [--pubkey KEY] [--fetch-key] [--wallet ADDR] [--base-url URL] [--max-age SECS] [--self-test]
279
308
 
280
309
  arguments:
281
310
  <receipt.json> path to the receipt JSON, or "-" to read from stdin
282
311
  --pubkey KEY trust this base58 Ed25519 pubkey (out-of-band) instead of fetching/built-in
312
+ --fetch-key (cNFT only) fetch the signing key from the published well-known descriptor
313
+ (--base-url or ${DEFAULT_CNFT_BASE_URL}) instead of the built-in copy. Trades
314
+ package-trust for domain/TLS-trust; default stays built-in (no network).
283
315
  --wallet ADDR (cNFT only) the leaf-owner wallet, which is part of the signed payload but
284
316
  not stored in the anchor block. Inferred from a <wallet>.json filename if omitted.
285
- --base-url URL (trust-API only) where to fetch the published key (default: ${DEFAULT_BASE_URL})
317
+ --base-url URL where to fetch the key: trust-API default ${DEFAULT_BASE_URL}; cNFT (--fetch-key)
318
+ default ${DEFAULT_CNFT_BASE_URL}
286
319
  --max-age SECS replay-resistance policy: reject if the receipt's timestamp (preimage.timestamp_unix
287
320
  for trust-API, anchor.minted_at for cNFT) is older than SECS, OR is missing.
288
321
  Crypto is time-independent; this is opt-in relying-party policy.
@@ -290,10 +323,11 @@ arguments:
290
323
  -h, --help show this help
291
324
 
292
325
  exit code: 0 = VALID, 1 = INVALID / error
293
- trust-API key source: ${DEFAULT_BASE_URL}/.well-known/x402`;
326
+ trust-API key source: ${DEFAULT_BASE_URL}/.well-known/x402
327
+ cNFT key source: ${DEFAULT_CNFT_BASE_URL}/v1/receipts/pubkey`;
294
328
  if (args.includes('-h') || args.includes('--help')) { console.log(HELP); process.exit(0); }
295
329
  if (args.length === 0) {
296
- console.error('usage: twzrd-receipt-verifier <receipt.json|-> [--pubkey KEY] [--wallet ADDR] [--base-url URL] [--max-age SECS] [--self-test]');
330
+ console.error('usage: twzrd-receipt-verifier <receipt.json|-> [--pubkey KEY] [--fetch-key] [--wallet ADDR] [--base-url URL] [--max-age SECS] [--self-test]');
297
331
  console.error(' twzrd-receipt-verifier --help');
298
332
  process.exit(1);
299
333
  }
@@ -310,8 +344,16 @@ trust-API key source: ${DEFAULT_BASE_URL}/.well-known/x402`;
310
344
  // ── cNFT (Bubblegum anchor) receipt: Ed25519 over compact JSON, no keccak leaf ──
311
345
  if (isCnftReceipt(receipt)) {
312
346
  let trusted = getOpt('--pubkey'), keySrc;
313
- if (trusted) { keySrc = '--pubkey (out-of-band)'; }
314
- else { trusted = DEFAULT_CNFT_PUBKEY; keySrc = 'built-in genesis authority'; }
347
+ if (trusted) {
348
+ keySrc = '--pubkey (out-of-band)';
349
+ } else if (args.includes('--fetch-key')) {
350
+ const fetchBase = getOpt('--base-url') || DEFAULT_CNFT_BASE_URL;
351
+ trusted = await fetchCnftPubkey(fetchBase);
352
+ keySrc = `fetched from ${fetchBase}`;
353
+ } else {
354
+ trusted = DEFAULT_CNFT_PUBKEY;
355
+ keySrc = 'built-in genesis authority';
356
+ }
315
357
  const { wallet, src: walletSrc } = resolveWallet({
316
358
  explicitWallet: getOpt('--wallet'), receipt, receiptPath: receiptArg,
317
359
  });
@@ -339,6 +381,7 @@ trust-API key source: ${DEFAULT_BASE_URL}/.well-known/x402`;
339
381
  res.errors.forEach((e) => console.log(' - ' + e));
340
382
  let ok = !!res.valid;
341
383
  console.log(`RESULT : ${ok ? 'VALID (TWZRD-authored, untampered)' : 'INVALID'}`);
384
+ if (ok) console.log(' verified with the same library TWZRD uses internally (npm: twzrd-receipt-verifier)');
342
385
 
343
386
  if (selfTest) {
344
387
  const tampered = JSON.parse(raw);
@@ -387,6 +430,7 @@ trust-API key source: ${DEFAULT_BASE_URL}/.well-known/x402`;
387
430
  res.errors.forEach((e) => console.log(' - ' + e));
388
431
  let ok = !!res.valid;
389
432
  console.log(`RESULT : ${ok ? 'VALID (TWZRD-authored, untampered)' : 'INVALID'}`);
433
+ if (ok) console.log(' verified with the same library TWZRD uses internally (npm: twzrd-receipt-verifier)');
390
434
 
391
435
  if (selfTest) {
392
436
  const tampered = JSON.parse(raw);
@@ -406,7 +450,8 @@ trust-API key source: ${DEFAULT_BASE_URL}/.well-known/x402`;
406
450
  module.exports = {
407
451
  verify, recomputeLeaf,
408
452
  verifyCnft, cnftSignedPayload, isCnftReceipt, resolveWallet,
409
- DEFAULT_CNFT_PUBKEY, CNFT_SIGNED_FIELDS,
453
+ fetchCnftPubkey,
454
+ DEFAULT_CNFT_PUBKEY, DEFAULT_CNFT_BASE_URL, CNFT_SIGNED_FIELDS,
410
455
  };
411
456
 
412
457
  if (require.main === module) {