@xfuel/verify 0.1.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/dist/index.js ADDED
@@ -0,0 +1,405 @@
1
+ "use strict";
2
+ /**
3
+ * @xfuel/verify — Offline verification for Chit402 receipts.
4
+ *
5
+ * Verify payment binding and output commitment WITHOUT calling the Chit402 API.
6
+ * Third parties use this to confirm:
7
+ * 1. The receipt's payment binding matches on-chain settlement
8
+ * 2. The output hash commitment is correct
9
+ * 3. The issuer signature is valid (ES256/JWKS)
10
+ * 4. (Optional) The SP1 nullifier is anchored on-chain
11
+ *
12
+ * See docs/specs/RECEIPT_V2_SEMANTICS.md for the verification algorithm.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.canonicalSignedPayload = exports.BASE_SEPOLIA_RPC_URL = exports.BASE_RPC_URL = exports.ZK_VERIFIER_ADDRESS = exports.computeInferenceBinding = exports.computePaymentCommitment = void 0;
16
+ exports.canonicalIssuerPayload = canonicalIssuerPayload;
17
+ exports.verifyIssuerSignature = verifyIssuerSignature;
18
+ exports.verifyIssuerSignatureWithJwks = verifyIssuerSignatureWithJwks;
19
+ exports.verifyBinding = verifyBinding;
20
+ exports.verifyNullifier = verifyNullifier;
21
+ exports.hashCanonicalPayload = hashCanonicalPayload;
22
+ exports.verifyReceipt = verifyReceipt;
23
+ const ethers_1 = require("ethers");
24
+ const node_crypto_1 = require("node:crypto");
25
+ const binding_js_1 = require("./binding.js");
26
+ Object.defineProperty(exports, "computePaymentCommitment", { enumerable: true, get: function () { return binding_js_1.computePaymentCommitment; } });
27
+ Object.defineProperty(exports, "computeInferenceBinding", { enumerable: true, get: function () { return binding_js_1.computeInferenceBinding; } });
28
+ /** ZKVerifierSP1 contract on Base mainnet. */
29
+ exports.ZK_VERIFIER_ADDRESS = '0x9373499645292715a2275A78eD65B14215C41c06';
30
+ /** Default Base mainnet RPC. */
31
+ exports.BASE_RPC_URL = 'https://mainnet.base.org';
32
+ /** Base Sepolia testnet RPC. */
33
+ exports.BASE_SEPOLIA_RPC_URL = 'https://sepolia.base.org';
34
+ /** Minimal ABI for nullifier check. */
35
+ const ZK_VERIFIER_ABI = [
36
+ 'function usedNullifiers(bytes32) view returns (bool)',
37
+ ];
38
+ /**
39
+ * Canonical, order-stable payload an issuer signature covers.
40
+ * MUST match `canonicalSignedPayload` in services/gateway/src/receipt.js exactly.
41
+ *
42
+ * Signed fields (15 total):
43
+ * 1. task_id
44
+ * 2. payment.rail
45
+ * 3. payment.ref
46
+ * 4. payment.gross_amount
47
+ * 5. payment.net_amount
48
+ * 6. payment.fee_amount
49
+ * 7. payment.protocol_fee_bps ?? payment.fee_bps
50
+ * 8. payment.platform_fee
51
+ * 9. payment.platform_fee_bps
52
+ * 10. provider_cogs.actual
53
+ * 11. route.model
54
+ * 12. route.model_commitment.commitment
55
+ * 13. route.provider
56
+ * 14. output.hash
57
+ * 15. binding.expected_commitment
58
+ */
59
+ function canonicalIssuerPayload(receipt) {
60
+ return JSON.stringify([
61
+ receipt.task_id ?? null,
62
+ receipt.payment?.rail ?? null,
63
+ receipt.payment?.ref ?? null,
64
+ receipt.payment?.gross_amount ?? null,
65
+ receipt.payment?.net_amount ?? null,
66
+ receipt.payment?.fee_amount ?? null,
67
+ receipt.payment?.protocol_fee_bps ?? receipt.payment?.fee_bps ?? null,
68
+ receipt.payment?.platform_fee ?? null,
69
+ receipt.payment?.platform_fee_bps ?? null,
70
+ receipt.provider_cogs?.actual ?? null,
71
+ receipt.route?.model ?? null,
72
+ receipt.route?.model_commitment?.commitment ?? null,
73
+ receipt.route?.provider ?? null,
74
+ receipt.output?.hash ?? null,
75
+ receipt.binding?.expected_commitment ?? null,
76
+ ]);
77
+ }
78
+ /**
79
+ * Verify a receipt's ES256 issuer signature against a JWK (public key).
80
+ * This is the public-key verification path — no shared secret required.
81
+ *
82
+ * Verification steps:
83
+ * 1. GET /receipt/:taskId?format=json → receipt.issuer_signature
84
+ * 2. GET /.well-known/jwks.json → find key matching issuer_signature.kid
85
+ * 3. ES256 verify canonicalIssuerPayload(receipt) against the signature
86
+ *
87
+ * @param receipt - Receipt JSON with issuer_signature
88
+ * @param jwk - JWK public key { kty: 'EC', crv: 'P-256', x, y }
89
+ */
90
+ function verifyIssuerSignature(receipt, jwk) {
91
+ const sig = receipt.issuer_signature;
92
+ if (!sig || !sig.value) {
93
+ return { checked: false, valid: false, reason: 'no_issuer_signature' };
94
+ }
95
+ if (sig.alg !== 'ES256') {
96
+ return { checked: false, valid: false, reason: `unsupported_alg: ${sig.alg}` };
97
+ }
98
+ if (!jwk || jwk.kty !== 'EC' || jwk.crv !== 'P-256') {
99
+ return { checked: false, valid: false, reason: 'invalid_jwk' };
100
+ }
101
+ if (sig.kid && jwk.kid && sig.kid !== jwk.kid) {
102
+ return { checked: false, valid: false, reason: 'kid_mismatch' };
103
+ }
104
+ try {
105
+ const jwkInput = { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y };
106
+ const publicKey = (0, node_crypto_1.createPublicKey)({ key: jwkInput, format: 'jwk' });
107
+ const signature = Buffer.from(sig.value, 'base64url');
108
+ const payload = canonicalIssuerPayload(receipt);
109
+ const valid = (0, node_crypto_1.verify)('sha256', Buffer.from(payload, 'utf8'), {
110
+ key: publicKey,
111
+ dsaEncoding: 'ieee-p1363',
112
+ }, signature);
113
+ return { checked: true, valid, kid: sig.kid };
114
+ }
115
+ catch (err) {
116
+ return { checked: true, valid: false, kid: sig.kid, reason: `verify_error: ${err.message}` };
117
+ }
118
+ }
119
+ /**
120
+ * Verify a receipt's ES256 issuer signature against a JWKS (key set).
121
+ * Finds the matching key by kid and verifies.
122
+ *
123
+ * @param receipt - Receipt JSON with issuer_signature
124
+ * @param jwks - JWKS with keys array
125
+ */
126
+ function verifyIssuerSignatureWithJwks(receipt, jwks) {
127
+ const sig = receipt.issuer_signature;
128
+ if (!sig || !sig.value) {
129
+ return { checked: false, valid: false, reason: 'no_issuer_signature' };
130
+ }
131
+ if (!jwks || !Array.isArray(jwks.keys) || jwks.keys.length === 0) {
132
+ return { checked: false, valid: false, reason: 'empty_jwks' };
133
+ }
134
+ // Find matching key by kid, or try all ES256 keys if no kid on signature
135
+ const candidates = sig.kid
136
+ ? jwks.keys.filter(k => k.kid === sig.kid && k.alg === 'ES256')
137
+ : jwks.keys.filter(k => k.alg === 'ES256');
138
+ if (candidates.length === 0) {
139
+ return { checked: false, valid: false, reason: 'no_matching_key' };
140
+ }
141
+ for (const jwk of candidates) {
142
+ const result = verifyIssuerSignature(receipt, jwk);
143
+ if (result.valid) {
144
+ return result;
145
+ }
146
+ }
147
+ return { checked: true, valid: false, reason: 'signature_invalid' };
148
+ }
149
+ /**
150
+ * Verify a receipt's payment binding locally (no network required).
151
+ *
152
+ * This recomputes the commitment from the receipt's fields and compares
153
+ * it to the stored `binding.expected_commitment`.
154
+ */
155
+ function verifyBinding(receipt) {
156
+ const binding = receipt.binding;
157
+ if (!binding) {
158
+ return {
159
+ verified: false,
160
+ expected: null,
161
+ recomputed: null,
162
+ matches: false,
163
+ covers: [],
164
+ reason: 'No binding present on receipt (may be unmetered or TFUEL rail)',
165
+ };
166
+ }
167
+ const paymentRef = receipt.payment?.ref ?? null;
168
+ const taskId = receipt.task_id;
169
+ const rail = (binding.rail || receipt.payment?.rail || 'usdc');
170
+ const amount = binding.amount || receipt.payment?.net_amount || '0';
171
+ const covers = binding.covers || ['payment', 'settlement'];
172
+ // Determine if this is a PBR (includes model + output)
173
+ const bindsInference = covers.includes('inference') ||
174
+ !!(binding.model_commitment && binding.output_hash);
175
+ let recomputed;
176
+ try {
177
+ if (bindsInference) {
178
+ const result = (0, binding_js_1.computeInferenceBinding)({
179
+ paymentRef,
180
+ taskId,
181
+ rail,
182
+ amount,
183
+ modelCommitment: binding.model_commitment,
184
+ outputHash: binding.output_hash,
185
+ });
186
+ recomputed = result.commitment;
187
+ }
188
+ else {
189
+ const result = (0, binding_js_1.computePaymentCommitment)({
190
+ paymentRef,
191
+ taskId,
192
+ rail,
193
+ amount,
194
+ });
195
+ recomputed = result.commitment;
196
+ }
197
+ }
198
+ catch (err) {
199
+ return {
200
+ verified: false,
201
+ expected: binding.expected_commitment || null,
202
+ recomputed: null,
203
+ matches: false,
204
+ covers,
205
+ reason: `Failed to recompute commitment: ${err instanceof Error ? err.message : String(err)}`,
206
+ };
207
+ }
208
+ const expected = binding.expected_commitment || null;
209
+ const matches = !!(expected &&
210
+ recomputed &&
211
+ expected.toLowerCase() === recomputed.toLowerCase());
212
+ return {
213
+ verified: true,
214
+ expected,
215
+ recomputed,
216
+ matches,
217
+ covers,
218
+ reason: matches ? undefined : 'Commitment mismatch — receipt may be tampered',
219
+ };
220
+ }
221
+ /**
222
+ * Verify a receipt's nullifier is anchored on-chain.
223
+ *
224
+ * Requires network access to the Base RPC.
225
+ */
226
+ async function verifyNullifier(receipt, options = {}) {
227
+ const nullifier = receipt.proof?.nullifier ?? null;
228
+ if (!nullifier) {
229
+ return {
230
+ verified: false,
231
+ nullifier: null,
232
+ anchored: null,
233
+ reason: 'No nullifier present (Tier-1 receipt or proof pending)',
234
+ };
235
+ }
236
+ if (!/^0x[0-9a-fA-F]{64}$/.test(nullifier)) {
237
+ return {
238
+ verified: false,
239
+ nullifier,
240
+ anchored: null,
241
+ reason: 'Invalid nullifier format',
242
+ };
243
+ }
244
+ const rpcUrl = options.rpcUrl || exports.BASE_RPC_URL;
245
+ const verifierAddress = options.verifierAddress || exports.ZK_VERIFIER_ADDRESS;
246
+ try {
247
+ const provider = new ethers_1.JsonRpcProvider(rpcUrl);
248
+ const contract = new ethers_1.Contract(verifierAddress, ZK_VERIFIER_ABI, provider);
249
+ const isUsed = await contract.usedNullifiers(nullifier);
250
+ return {
251
+ verified: true,
252
+ nullifier,
253
+ anchored: isUsed,
254
+ reason: isUsed ? undefined : 'Nullifier not found on-chain (proof may not be submitted yet)',
255
+ };
256
+ }
257
+ catch (err) {
258
+ return {
259
+ verified: false,
260
+ nullifier,
261
+ anchored: null,
262
+ reason: `Chain query failed: ${err instanceof Error ? err.message : String(err)}`,
263
+ };
264
+ }
265
+ }
266
+ /**
267
+ * Canonical signed payload for HMAC verification.
268
+ * Alias of canonicalIssuerPayload — both must produce identical bytes.
269
+ */
270
+ exports.canonicalSignedPayload = canonicalIssuerPayload;
271
+ /**
272
+ * Hash the canonical payload (for ERC-8004 response_hash).
273
+ */
274
+ function hashCanonicalPayload(receipt) {
275
+ return (0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)((0, exports.canonicalSignedPayload)(receipt)));
276
+ }
277
+ /**
278
+ * Full receipt verification — binding + issuer signature + optional nullifier check.
279
+ *
280
+ * @param receipt The Chit402 receipt JSON
281
+ * @param options.jwks JWKS for issuer signature verification (no network fetch)
282
+ * @param options.checkNullifier Whether to verify nullifier on-chain (requires network)
283
+ * @param options.rpcUrl RPC URL for on-chain checks
284
+ */
285
+ async function verifyReceipt(receipt, options = {}) {
286
+ const errors = [];
287
+ // Verify binding locally
288
+ const binding = verifyBinding(receipt);
289
+ if (!binding.matches && binding.expected) {
290
+ errors.push('Payment binding mismatch');
291
+ }
292
+ // Verify issuer signature if JWKS provided
293
+ let issuer_signature;
294
+ if (options.jwks) {
295
+ issuer_signature = verifyIssuerSignatureWithJwks(receipt, options.jwks);
296
+ if (issuer_signature.checked && !issuer_signature.valid) {
297
+ errors.push(`Issuer signature invalid: ${issuer_signature.reason}`);
298
+ }
299
+ }
300
+ else if (receipt.issuer_signature) {
301
+ issuer_signature = {
302
+ checked: false,
303
+ valid: false,
304
+ kid: receipt.issuer_signature.kid,
305
+ reason: 'JWKS not provided — pass jwks option to verify issuer signature',
306
+ };
307
+ }
308
+ else {
309
+ issuer_signature = {
310
+ checked: false,
311
+ valid: false,
312
+ reason: 'No issuer signature present on receipt',
313
+ };
314
+ }
315
+ // Verify nullifier on-chain if requested
316
+ let nullifier;
317
+ if (options.checkNullifier && receipt.proof?.nullifier) {
318
+ nullifier = await verifyNullifier(receipt, {
319
+ rpcUrl: options.rpcUrl,
320
+ verifierAddress: options.verifierAddress,
321
+ });
322
+ if (nullifier.verified && nullifier.anchored === false) {
323
+ errors.push('Nullifier not anchored on-chain');
324
+ }
325
+ }
326
+ else {
327
+ nullifier = {
328
+ verified: false,
329
+ nullifier: receipt.proof?.nullifier ?? null,
330
+ anchored: null,
331
+ reason: options.checkNullifier
332
+ ? 'No nullifier present'
333
+ : 'On-chain check not requested',
334
+ };
335
+ }
336
+ // Extract frozen fields
337
+ const hub = receipt.route?.provider ?? null;
338
+ const model = receipt.route?.model ?? null;
339
+ const amount_usdc = receipt.payment?.gross_amount ?? null;
340
+ const tx = receipt.payment?.ref ?? null;
341
+ const output_hash = receipt.output?.hash ?? null;
342
+ // Determine overall status with strict signature semantics:
343
+ // - If JWKS provided and signature invalid/kid mismatch/no matching key → 'failed'
344
+ // - If receipt has issuer_signature but no JWKS provided → 'partial' (cannot verify)
345
+ // - Unsigned receipts can be 'partial' or 'verified' based on binding
346
+ let overall;
347
+ // Check for signature verification failure (JWKS provided but signature invalid)
348
+ const jwksProvided = !!options.jwks;
349
+ const hasIssuerSig = !!receipt.issuer_signature;
350
+ const issuerSigInvalid = jwksProvided && hasIssuerSig && !issuer_signature.valid;
351
+ // Binding failure
352
+ const bindingFailed = binding.expected && !binding.matches;
353
+ if (issuerSigInvalid || bindingFailed) {
354
+ // JWKS provided but signature invalid, OR binding mismatch → failed
355
+ overall = 'failed';
356
+ }
357
+ else if (hasIssuerSig && !jwksProvided) {
358
+ // Receipt has signature but no JWKS provided → partial (cannot verify signature)
359
+ overall = 'partial';
360
+ }
361
+ else if (binding.matches && (!options.checkNullifier || nullifier.anchored)) {
362
+ // Binding matches, signature OK (or no signature), nullifier OK → verified
363
+ overall = 'verified';
364
+ }
365
+ else if (binding.matches || issuer_signature.valid || (nullifier.verified && nullifier.anchored)) {
366
+ // At least one check passed → partial
367
+ overall = 'partial';
368
+ }
369
+ else if (!binding.expected && !receipt.proof?.nullifier && !hasIssuerSig) {
370
+ // No binding/sig/nullifier to verify (unmetered/demo) → partial
371
+ overall = 'partial';
372
+ }
373
+ else {
374
+ overall = 'failed';
375
+ }
376
+ return {
377
+ receipt_id: receipt.task_id,
378
+ binding,
379
+ issuer_signature,
380
+ nullifier,
381
+ output_hash,
382
+ hub,
383
+ model,
384
+ amount_usdc,
385
+ tx,
386
+ overall,
387
+ errors,
388
+ };
389
+ }
390
+ exports.default = {
391
+ verifyBinding,
392
+ verifyIssuerSignature,
393
+ verifyIssuerSignatureWithJwks,
394
+ verifyNullifier,
395
+ verifyReceipt,
396
+ computePaymentCommitment: binding_js_1.computePaymentCommitment,
397
+ computeInferenceBinding: binding_js_1.computeInferenceBinding,
398
+ canonicalIssuerPayload,
399
+ canonicalSignedPayload: exports.canonicalSignedPayload,
400
+ hashCanonicalPayload,
401
+ ZK_VERIFIER_ADDRESS: exports.ZK_VERIFIER_ADDRESS,
402
+ BASE_RPC_URL: exports.BASE_RPC_URL,
403
+ BASE_SEPOLIA_RPC_URL: exports.BASE_SEPOLIA_RPC_URL,
404
+ };
405
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@xfuel/verify",
3
+ "version": "0.1.0",
4
+ "description": "Offline verification for Chit402 receipts — verify payment binding and output hash without calling the API",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "bin": {
8
+ "xfuel-verify": "./dist/cli.js"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.js"
15
+ }
16
+ },
17
+ "sideEffects": false,
18
+ "engines": {
19
+ "node": ">=18"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "homepage": "https://github.com/XFuel-Lab/chit402/tree/main/packages/verify#readme",
30
+ "bugs": {
31
+ "url": "https://github.com/XFuel-Lab/chit402/issues"
32
+ },
33
+ "scripts": {
34
+ "build": "tsc",
35
+ "test": "node --test test/*.test.mjs",
36
+ "prepublishOnly": "npm run build && npm test"
37
+ },
38
+ "keywords": [
39
+ "chit402",
40
+ "xfuel",
41
+ "verify",
42
+ "receipt",
43
+ "x402",
44
+ "usdc",
45
+ "base",
46
+ "offline",
47
+ "zk"
48
+ ],
49
+ "author": "XFuel Lab",
50
+ "license": "Apache-2.0",
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "https://github.com/XFuel-Lab/chit402.git",
54
+ "directory": "packages/verify"
55
+ },
56
+ "dependencies": {
57
+ "ethers": "^6.16.0"
58
+ },
59
+ "devDependencies": {
60
+ "@types/node": "^22.0.0",
61
+ "typescript": "^5.9.3"
62
+ }
63
+ }