@xfuel/verify 0.3.4 → 0.4.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/LICENSE +201 -201
- package/README.md +82 -252
- package/cli.js +40 -0
- package/index.cjs +8 -0
- package/index.d.ts +5 -0
- package/index.js +7 -0
- package/package.json +61 -67
- package/dist/anchor-trust.d.ts +0 -129
- package/dist/anchor-trust.d.ts.map +0 -1
- package/dist/anchor-trust.js +0 -395
- package/dist/anchor-trust.js.map +0 -1
- package/dist/anchor-witness.d.ts +0 -265
- package/dist/anchor-witness.d.ts.map +0 -1
- package/dist/anchor-witness.js +0 -818
- package/dist/anchor-witness.js.map +0 -1
- package/dist/base-payer.d.ts +0 -65
- package/dist/base-payer.d.ts.map +0 -1
- package/dist/base-payer.js +0 -222
- package/dist/base-payer.js.map +0 -1
- package/dist/binding.d.ts +0 -52
- package/dist/binding.d.ts.map +0 -1
- package/dist/binding.js +0 -80
- package/dist/binding.js.map +0 -1
- package/dist/canonical-preimage.d.ts +0 -9
- package/dist/canonical-preimage.d.ts.map +0 -1
- package/dist/canonical-preimage.js +0 -25
- package/dist/canonical-preimage.js.map +0 -1
- package/dist/carry-forward.d.ts +0 -79
- package/dist/carry-forward.d.ts.map +0 -1
- package/dist/carry-forward.js +0 -184
- package/dist/carry-forward.js.map +0 -1
- package/dist/cli.d.ts +0 -19
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -1479
- package/dist/cli.js.map +0 -1
- package/dist/epoch.d.ts +0 -143
- package/dist/epoch.d.ts.map +0 -1
- package/dist/epoch.js +0 -352
- package/dist/epoch.js.map +0 -1
- package/dist/head-binding.d.ts +0 -24
- package/dist/head-binding.d.ts.map +0 -1
- package/dist/head-binding.js +0 -61
- package/dist/head-binding.js.map +0 -1
- package/dist/index.d.ts +0 -569
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -1597
- package/dist/index.js.map +0 -1
- package/dist/issuer-history.d.ts +0 -110
- package/dist/issuer-history.d.ts.map +0 -1
- package/dist/issuer-history.js +0 -348
- package/dist/issuer-history.js.map +0 -1
- package/dist/issuer-pin.d.ts +0 -126
- package/dist/issuer-pin.d.ts.map +0 -1
- package/dist/issuer-pin.js +0 -567
- package/dist/issuer-pin.js.map +0 -1
- package/dist/jcs.d.ts +0 -8
- package/dist/jcs.d.ts.map +0 -1
- package/dist/jcs.js +0 -64
- package/dist/jcs.js.map +0 -1
- package/dist/jws.d.ts +0 -46
- package/dist/jws.d.ts.map +0 -1
- package/dist/jws.js +0 -129
- package/dist/jws.js.map +0 -1
- package/dist/payer.d.ts +0 -65
- package/dist/payer.d.ts.map +0 -1
- package/dist/payer.js +0 -148
- package/dist/payer.js.map +0 -1
- package/dist/preimage.d.ts +0 -78
- package/dist/preimage.d.ts.map +0 -1
- package/dist/preimage.js +0 -363
- package/dist/preimage.js.map +0 -1
- package/dist/receipt-lane.d.ts +0 -235
- package/dist/receipt-lane.d.ts.map +0 -1
- package/dist/receipt-lane.js +0 -446
- package/dist/receipt-lane.js.map +0 -1
- package/dist/refusal.d.ts +0 -93
- package/dist/refusal.d.ts.map +0 -1
- package/dist/refusal.js +0 -248
- package/dist/refusal.js.map +0 -1
- package/dist/request-binding.d.ts +0 -7
- package/dist/request-binding.d.ts.map +0 -1
- package/dist/request-binding.js +0 -26
- package/dist/request-binding.js.map +0 -1
- package/dist/row-hash.d.ts +0 -22
- package/dist/row-hash.d.ts.map +0 -1
- package/dist/row-hash.js +0 -26
- package/dist/row-hash.js.map +0 -1
- package/dist/shell.d.ts +0 -65
- package/dist/shell.d.ts.map +0 -1
- package/dist/shell.js +0 -268
- package/dist/shell.js.map +0 -1
- package/dist/solana-payer.d.ts +0 -99
- package/dist/solana-payer.d.ts.map +0 -1
- package/dist/solana-payer.js +0 -258
- package/dist/solana-payer.js.map +0 -1
- package/dist/v11-receipt.d.ts +0 -21
- package/dist/v11-receipt.d.ts.map +0 -1
- package/dist/v11-receipt.js +0 -351
- package/dist/v11-receipt.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,252 +1,82 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
Offline verification for Chit402 receipts — verify payment binding and output commitment without calling the API.
|
|
4
|
-
|
|
5
|
-
npm:
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Usage
|
|
14
|
-
|
|
15
|
-
### Library
|
|
16
|
-
|
|
17
|
-
```typescript
|
|
18
|
-
import { verifyReceipt, verifyBinding, verifyNullifier } from '
|
|
19
|
-
|
|
20
|
-
// Verify a receipt offline (binding only, no network)
|
|
21
|
-
const receipt = { /* Chit402 receipt JSON */ };
|
|
22
|
-
const result = verifyBinding(receipt);
|
|
23
|
-
console.log(result.matches); // true if binding verified
|
|
24
|
-
|
|
25
|
-
// Full verification including on-chain nullifier check
|
|
26
|
-
const fullResult = await verifyReceipt(receipt, { checkNullifier: true });
|
|
27
|
-
console.log(fullResult.overall); // 'verified' | 'partial' | 'failed'
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
#
|
|
44
|
-
npx
|
|
45
|
-
|
|
46
|
-
#
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
|
67
|
-
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
1. **JWKS by kid** — a key in `--jwks-file`, `--jwks-url`, or `--fetch-jwks`
|
|
84
|
-
(allowlisted host, default `api.chit402.com`) whose `kid` matches the JWS.
|
|
85
|
-
2. **Pinned thumbprint** — the embedded `issuer_jwk` is used only when its
|
|
86
|
-
RFC 7638 thumbprint equals a trusted kid. The default offline pin is the
|
|
87
|
-
production kid `IvFpmC-vPhkY_v0vidsrWVT9uzlE5XWKZgAEOeJTq1Q`. Override with
|
|
88
|
-
`--trusted-kid`, or disable with `--no-trusted-kid`.
|
|
89
|
-
|
|
90
|
-
The epoch record and the tree head use those same sources, with or without `--rpc`. `xfuel-verify receipt.json inclusion.json head.json` checks the head signature and the inclusion proof offline. `--rpc` adds the chain checks. An embedded key still has to match the trusted-kid pin, or the kid has to be in a verified issuer-history entry. The head's signed `anchors.base.from` and `anchors.solana.fee_payer` must be on the anchor-wallet list (the package pin, or a verified `/.well-known/anchor-wallets.json`). The chain sender and fee payer must be those wallets. `--version` prints the package version.
|
|
91
|
-
|
|
92
|
-
Anchor mode also checks a content-addressed issuer pin when the receipt or the head carries `issuer_key_pin`, or when you pass `--issuer-pin`. The pin is a 40-hex commit plus the SHA-256 of `docs/well-known/issuer-key.json`. A branch name is not fetched. A claimed pin requires `issuer_signature.jws` verified under that key. Unsigned envelope kids do not satisfy the check. The registration self-signature is checked when the file has one. A claimed era with no pin fails `ISSUER_PIN_DOWNGRADE`. Receipts that do not claim the era skip this check. The pin chain is Base Sepolia (`eip155:84532`). See [issuer-key-pin.md](../../docs/product/issuer-key-pin.md).
|
|
93
|
-
|
|
94
|
-
`issuer_jwk` on the receipt is not a trust root. A copy re-signed with an
|
|
95
|
-
arbitrary P-256 key reports `key untrusted` (`issuer_signature.valid === false`),
|
|
96
|
-
including when `--jwks-file` points at the real JWKS.
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
# Explicit offline. The default command fetches issuer history.
|
|
100
|
-
npx xfuel-verify receipt.json --no-issuer-history
|
|
101
|
-
|
|
102
|
-
# Recompute a published canonical preimage and check the kid window.
|
|
103
|
-
# curl -f stops on HTTP errors. Most receipts have no /preimage (a 404).
|
|
104
|
-
# A missing preimage is not a verification failure: omit --canonical-preimage.
|
|
105
|
-
curl -fsS "https://api.chit402.com/receipt/RECEIPT_ID?format=json" -o receipt.json
|
|
106
|
-
curl -fsS "https://api.chit402.com/.well-known/issuer-history.json?version=1" -o issuer-history.json
|
|
107
|
-
if curl -fsS "https://api.chit402.com/receipt/RECEIPT_ID/preimage" -o preimage.json; then
|
|
108
|
-
npx xfuel-verify receipt.json --canonical-preimage preimage.json --issuer-history-file issuer-history.json
|
|
109
|
-
else
|
|
110
|
-
npx xfuel-verify receipt.json --issuer-history-file issuer-history.json
|
|
111
|
-
fi
|
|
112
|
-
|
|
113
|
-
# Trust the published JWKS instead of (or in addition to) the pin
|
|
114
|
-
curl -o issuer-jwks.json https://api.chit402.com/.well-known/jwks.json
|
|
115
|
-
npx xfuel-verify receipt.json --jwks-file issuer-jwks.json --no-trusted-kid
|
|
116
|
-
|
|
117
|
-
# Fetch the issuer JWKS (https://api.chit402.com/.well-known/jwks.json)
|
|
118
|
-
npx xfuel-verify receipt.json --fetch-jwks
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
import { verifyReceipt } from '@xfuel/verify';
|
|
123
|
-
|
|
124
|
-
const result = await verifyReceipt(receipt);
|
|
125
|
-
console.log(result.issuer_signature.valid); // true only for a trusted key
|
|
126
|
-
console.log(result.issuer_signature.key_trusted);
|
|
127
|
-
console.log(result.amount_usdc); // from verified claims, not the outer copy
|
|
128
|
-
console.log(result.claim_mismatches); // any signed path whose outer copy disagrees
|
|
129
|
-
console.log(result.unsigned_fields); // outer paths the signature does not cover
|
|
130
|
-
console.log(result.verified_scope); // 'signed_claims'
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
Amount, payer, payee, asset, and tx are read from the verified JWS claims.
|
|
134
|
-
Every signed path is compared with the outer receipt. A mismatch fails.
|
|
135
|
-
Paths the signature does not cover are `unsigned_fields` and are printed as
|
|
136
|
-
`UNVERIFIED`. Overall does not verify them. The outer document `schema` is
|
|
137
|
-
not a copy of the JWS `schema`. `--check-payer` on Base confirms payer, payee,
|
|
138
|
-
asset, and amount in the USDC `Transfer` log.
|
|
139
|
-
|
|
140
|
-
`xfuel-verify receipt.json inclusion.json head.json` also runs those receipt
|
|
141
|
-
checks. A matching inclusion proof does not make a tampered receipt VERIFIED.
|
|
142
|
-
|
|
143
|
-
A paid USDC receipt whose signed `binding.expected_commitment` is null is
|
|
144
|
-
reported as “No payment-binding commitment”, not as an unmetered or TFUEL receipt.
|
|
145
|
-
|
|
146
|
-
The CLI does **not** fetch JWKS unless `--fetch-jwks` or `--jwks-url` is set.
|
|
147
|
-
Exit code 1 is returned when the key is untrusted, the signature is invalid, or
|
|
148
|
-
a signed claim disagrees with the outer copy.
|
|
149
|
-
|
|
150
|
-
## Frozen Fields
|
|
151
|
-
|
|
152
|
-
These fields are immutable once set and verifiable by any third party:
|
|
153
|
-
|
|
154
|
-
- `task_id` — unique task identifier
|
|
155
|
-
- `route.provider` — compute hub (theta-edgecloud, akash-network)
|
|
156
|
-
- `route.model` — model that served the request
|
|
157
|
-
- `payment.gross_amount` — total charged in USDC atomic units
|
|
158
|
-
- `payment.ref` — settlement reference (network:txHash)
|
|
159
|
-
- `output.hash` — commitment to model output
|
|
160
|
-
- `proof.nullifier` — single-use nullifier anchored on-chain
|
|
161
|
-
|
|
162
|
-
## Verification Algorithm
|
|
163
|
-
|
|
164
|
-
The binding commitment is computed as:
|
|
165
|
-
|
|
166
|
-
```solidity
|
|
167
|
-
// Payment-only binding
|
|
168
|
-
keccak256(abi.encodePacked(
|
|
169
|
-
keccak256(payment_ref),
|
|
170
|
-
keccak256(task_id),
|
|
171
|
-
rail_discriminant, // 1=usdc, 2=tfuel
|
|
172
|
-
amount
|
|
173
|
-
))
|
|
174
|
-
|
|
175
|
-
// PBR (Payment-Bound Receipt) — includes model + output
|
|
176
|
-
keccak256(abi.encodePacked(
|
|
177
|
-
keccak256(payment_ref),
|
|
178
|
-
keccak256(task_id),
|
|
179
|
-
rail_discriminant,
|
|
180
|
-
amount,
|
|
181
|
-
model_commitment,
|
|
182
|
-
output_hash
|
|
183
|
-
))
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
This matches `SP1ProofHooks.computePaymentCommitment` on-chain.
|
|
187
|
-
|
|
188
|
-
## Exit Codes (CLI)
|
|
189
|
-
|
|
190
|
-
| Code | Meaning |
|
|
191
|
-
|------|---------|
|
|
192
|
-
| 0 | Verified |
|
|
193
|
-
| 1 | Verification failed |
|
|
194
|
-
| 2 | Partial (binding ok, nullifier not checked) |
|
|
195
|
-
| 3 | Input error |
|
|
196
|
-
|
|
197
|
-
## API Reference
|
|
198
|
-
|
|
199
|
-
### `verifyBinding(receipt)`
|
|
200
|
-
|
|
201
|
-
Verify payment binding locally. Returns:
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
{
|
|
205
|
-
verified: boolean;
|
|
206
|
-
expected: string | null;
|
|
207
|
-
recomputed: string | null;
|
|
208
|
-
matches: boolean;
|
|
209
|
-
covers: string[];
|
|
210
|
-
reason?: string;
|
|
211
|
-
}
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### `verifyNullifier(receipt, options?)`
|
|
215
|
-
|
|
216
|
-
Verify nullifier is anchored on-chain. Requires network access.
|
|
217
|
-
|
|
218
|
-
```typescript
|
|
219
|
-
{
|
|
220
|
-
verified: boolean;
|
|
221
|
-
nullifier: string | null;
|
|
222
|
-
anchored: boolean | null;
|
|
223
|
-
reason?: string;
|
|
224
|
-
}
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### `verifyReceipt(receipt, options?)`
|
|
228
|
-
|
|
229
|
-
Full verification combining binding and optional nullifier check.
|
|
230
|
-
|
|
231
|
-
```typescript
|
|
232
|
-
{
|
|
233
|
-
receipt_id: string;
|
|
234
|
-
binding: BindingVerification;
|
|
235
|
-
nullifier: NullifierVerification;
|
|
236
|
-
output_hash: string | null;
|
|
237
|
-
hub: string | null;
|
|
238
|
-
model: string | null;
|
|
239
|
-
amount_usdc: string | null;
|
|
240
|
-
tx: string | null;
|
|
241
|
-
overall: 'verified' | 'partial' | 'failed';
|
|
242
|
-
errors: string[];
|
|
243
|
-
}
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
## Build digest
|
|
247
|
-
|
|
248
|
-
`npm run digest` writes `BUILD_DIGEST.txt`. That file is the SHA-256 of the sorted `src/**/*.ts` listing, not a bit-reproducible `tsc` binary. The same sources produce the same digest. The receipt-tree genesis leaf copies this digest so a holder can see which verifier source the issuer vouches for. It does not prove the process that served the receipt ran that exact binary.
|
|
249
|
-
|
|
250
|
-
## License
|
|
251
|
-
|
|
252
|
-
Apache-2.0
|
|
1
|
+
# chit402-verify
|
|
2
|
+
|
|
3
|
+
Offline verification for Chit402 receipts — verify payment binding and output commitment without calling the API.
|
|
4
|
+
|
|
5
|
+
npm: `chit402-verify` · License: Apache-2.0 · Docs: https://chit402.com
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install chit402-verify
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Library
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { verifyReceipt, verifyBinding, verifyNullifier } from 'chit402-verify';
|
|
19
|
+
|
|
20
|
+
// Verify a receipt offline (binding only, no network)
|
|
21
|
+
const receipt = { /* Chit402 receipt JSON */ };
|
|
22
|
+
const result = verifyBinding(receipt);
|
|
23
|
+
console.log(result.matches); // true if binding verified
|
|
24
|
+
|
|
25
|
+
// Full verification including on-chain nullifier check
|
|
26
|
+
const fullResult = await verifyReceipt(receipt, { checkNullifier: true });
|
|
27
|
+
console.log(fullResult.overall); // 'verified' | 'partial' | 'failed'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### CLI
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Local binding verification (no network required)
|
|
34
|
+
npx chit402-verify receipt.json
|
|
35
|
+
|
|
36
|
+
# Hash the canonical object (must match signed payload_hash) and read not_after
|
|
37
|
+
# from a pinned issuer-history snapshot. Both flags are offline.
|
|
38
|
+
npx chit402-verify receipt.json --canonical-preimage preimage.json --issuer-history issuer-history.json
|
|
39
|
+
|
|
40
|
+
# With on-chain nullifier check (requires network)
|
|
41
|
+
npx chit402-verify receipt.json --check-nullifier
|
|
42
|
+
|
|
43
|
+
# Output as JSON
|
|
44
|
+
npx chit402-verify receipt.json --json
|
|
45
|
+
|
|
46
|
+
# From stdin
|
|
47
|
+
curl -s https://api.chit402.com/receipt/task-123?format=json | npx chit402-verify -
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## What This Verifies
|
|
51
|
+
|
|
52
|
+
| Check | Requires Network? | Description |
|
|
53
|
+
|-------|-------------------|-------------|
|
|
54
|
+
| Payment binding | No | Recompute commitment from receipt fields |
|
|
55
|
+
| Issuer signature | No, unless `--fetch-jwks` | ES256. Trusted via JWKS (by kid) or the pinned production kid. Embedded `issuer_jwk` alone is not enough. |
|
|
56
|
+
| Output hash | No | Hash is on the receipt |
|
|
57
|
+
| On-chain settlement | Yes | Query Base RPC for tx |
|
|
58
|
+
| Nullifier anchor | Yes | Query ZKVerifierSP1 contract |
|
|
59
|
+
| Canonical preimage | No | `--canonical-preimage` is SHA-256'd and matched to signed `payload_hash` |
|
|
60
|
+
| Issuer history | No, with `--issuer-history` | `iat` is inside the kid's `not_before` / `not_after`. A payload v10 pin must match |
|
|
61
|
+
|
|
62
|
+
## Exit Codes (CLI)
|
|
63
|
+
|
|
64
|
+
| Code | Meaning |
|
|
65
|
+
|------|---------|
|
|
66
|
+
| 0 | Verified |
|
|
67
|
+
| 1 | Verification failed |
|
|
68
|
+
| 2 | Partial (binding ok, nullifier not checked) |
|
|
69
|
+
| 3 | Input error |
|
|
70
|
+
|
|
71
|
+
## Publish
|
|
72
|
+
|
|
73
|
+
`publishConfig` sets `access` to `public` and does not name an owner. On the registry, `chit402-verify` (latest `0.2.0`) and `@xfuel/verify` (latest `0.2.1`) are both maintained by the npm user `xfuel`. Publish `@xfuel/verify` first. `npm whoami` must print `xfuel`. A `404` on `PUT https://registry.npmjs.org/chit402-verify` is that login, not a missing package and not a new scope: the name already exists.
|
|
74
|
+
|
|
75
|
+
## Documentation
|
|
76
|
+
|
|
77
|
+
- [Chit402 Docs](https://chit402.com)
|
|
78
|
+
- [API Reference](https://api.chit402.com)
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
Apache-2.0
|
package/cli.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* chit402-verify CLI — Chit402 receipt verification
|
|
4
|
+
*
|
|
5
|
+
* @xfuel/verify is a thin alias. The verifier is chit402-verify.
|
|
6
|
+
*/
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
import { spawn } from 'node:child_process';
|
|
9
|
+
import { constants as osConstants } from 'node:os';
|
|
10
|
+
|
|
11
|
+
const require = createRequire(import.meta.url);
|
|
12
|
+
const verifyCliPath = require.resolve('chit402-verify/dist/cli.js');
|
|
13
|
+
|
|
14
|
+
const child = spawn(process.execPath, [verifyCliPath, ...process.argv.slice(2)], {
|
|
15
|
+
stdio: 'inherit',
|
|
16
|
+
env: process.env,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Forward termination signals so killing the wrapper (CI timeout, supervisor) also stops the verifier.
|
|
20
|
+
const FORWARDED = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT'];
|
|
21
|
+
for (const sig of FORWARDED) {
|
|
22
|
+
process.on(sig, () => {
|
|
23
|
+
try { child.kill(sig); } catch { /* child already gone */ }
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Mirror the verifier's result exactly. A verifier killed by a signal (crash, heap-OOM abort,
|
|
28
|
+
// timeout) must never look like success: exit 128 + signal number, as a shell would report it.
|
|
29
|
+
child.on('exit', (code, signal) => {
|
|
30
|
+
if (signal) {
|
|
31
|
+
const n = osConstants.signals[signal];
|
|
32
|
+
process.exit(typeof n === 'number' ? 128 + n : 1);
|
|
33
|
+
}
|
|
34
|
+
process.exit(typeof code === 'number' ? code : 1);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
child.on('error', (err) => {
|
|
38
|
+
console.error('Failed to start chit402-verify:', err.message);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
});
|
package/index.cjs
ADDED
package/index.d.ts
ADDED
package/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,67 +1,61 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@xfuel/verify",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
},
|
|
63
|
-
"devDependencies": {
|
|
64
|
-
"@types/node": "^22.0.0",
|
|
65
|
-
"typescript": "^5.9.3"
|
|
66
|
-
}
|
|
67
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@xfuel/verify",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Alias of chit402-verify. The xfuel-verify bin stays.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.js",
|
|
7
|
+
"types": "./index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"xfuel-verify": "cli.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./index.d.ts",
|
|
14
|
+
"import": "./index.js",
|
|
15
|
+
"require": "./index.cjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"index.js",
|
|
24
|
+
"index.cjs",
|
|
25
|
+
"index.d.ts",
|
|
26
|
+
"cli.js",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public",
|
|
32
|
+
"provenance": true
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"test": "node test.mjs"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"chit402",
|
|
39
|
+
"verify",
|
|
40
|
+
"receipt",
|
|
41
|
+
"x402",
|
|
42
|
+
"usdc",
|
|
43
|
+
"base",
|
|
44
|
+
"offline",
|
|
45
|
+
"zk"
|
|
46
|
+
],
|
|
47
|
+
"author": "XFuel Lab",
|
|
48
|
+
"license": "Apache-2.0",
|
|
49
|
+
"homepage": "https://chit402.com",
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/XFuel-Lab/chit402/issues"
|
|
52
|
+
},
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/XFuel-Lab/chit402.git",
|
|
56
|
+
"directory": "packages/aliases/chit402-verify"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"chit402-verify": "0.4.0"
|
|
60
|
+
}
|
|
61
|
+
}
|
package/dist/anchor-trust.d.ts
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bind an anchored tree head to the issuer.
|
|
3
|
-
*
|
|
4
|
-
* Anchor mode trusts a head only when its ES256 `issuer_signature` verifies
|
|
5
|
-
* under the same rules as a receipt: a JWKS key matched by kid, an embedded
|
|
6
|
-
* key whose RFC 7638 thumbprint is a pinned kid, or a kid in a verified
|
|
7
|
-
* issuer-history document. The signed payload must match the outer fields
|
|
8
|
-
* the anchor check uses.
|
|
9
|
-
*
|
|
10
|
-
* The Base sender and the Solana fee payer in that payload must be on the
|
|
11
|
-
* issuer's anchor-wallet list, and the transactions the RPC returns must
|
|
12
|
-
* have been sent by those wallets.
|
|
13
|
-
*
|
|
14
|
-
* The list is the package pin, plus wallets inside a verified
|
|
15
|
-
* `chit402.anchor_wallets.v1` document or a verified issuer-history
|
|
16
|
-
* payload's `anchor_wallets`. Two later sources are named and not read:
|
|
17
|
-
* the Base `ChitIssuerRoot` registry (draft #485) and the DNS TXT at
|
|
18
|
-
* `_issuer.chit402.com`. This module does not embed a registry address
|
|
19
|
-
* and does not resolve DNS.
|
|
20
|
-
*/
|
|
21
|
-
import { type Es256Jwk } from './jws.js';
|
|
22
|
-
import { type IssuerHistoryDocument } from './issuer-history.js';
|
|
23
|
-
/** Confirmed sender of Base tx 0x1d8d7ea255170c8d4b87bef9382e13555dded2072fd877ce35f995f1ab54ee09. */
|
|
24
|
-
export declare const PINNED_BASE_ANCHOR_WALLET = "0x1844D1F5FE42aff1Cce6F776514Fd40374079582";
|
|
25
|
-
/** Fee payer of Solana memo 61RHMsPPseUc35v5oxDEtANEDCvXk5fmxZdrFDMknGWc5m7U8YhMfz4En1eFFj3z9n67ZtMiha1zkwnneL2LUiXk. */
|
|
26
|
-
export declare const PINNED_SOLANA_ANCHOR_FEE_PAYER = "BHTnbPu6UZ7zQZ7Qpkpz4LcUQbMN73YDsMtvaNXpEioD";
|
|
27
|
-
/** A head signed before `anchors.base.from` and `anchors.solana.fee_payer` existed. Never VERIFIED. */
|
|
28
|
-
export declare const LEGACY_HEAD_UNPINNED_SIGNER = "LEGACY_HEAD_UNPINNED_SIGNER";
|
|
29
|
-
export declare const ANCHOR_WALLETS_SCHEMA = "chit402.anchor_wallets.v1";
|
|
30
|
-
export declare const ANCHOR_WALLETS_JWT_TYP = "chit402-anchor-wallets+jwt";
|
|
31
|
-
/** Sources this version does not query. A later build can fill the same list. */
|
|
32
|
-
export declare const ANCHOR_WALLET_SOURCES_NOT_CONSULTED: readonly ["issuer_root", "dns"];
|
|
33
|
-
export declare const HEAD_TRUST_MESSAGES: Record<string, string>;
|
|
34
|
-
interface JwksLike {
|
|
35
|
-
keys?: Es256Jwk[];
|
|
36
|
-
}
|
|
37
|
-
export interface TreeHeadDocument {
|
|
38
|
-
schema?: string;
|
|
39
|
-
payload_version?: number;
|
|
40
|
-
root?: string | null;
|
|
41
|
-
tree_size?: number | null;
|
|
42
|
-
epoch?: number | null;
|
|
43
|
-
prev_epoch_root?: string | null;
|
|
44
|
-
prev_epoch_size?: number | null;
|
|
45
|
-
published_at?: string | null;
|
|
46
|
-
anchors?: {
|
|
47
|
-
base?: {
|
|
48
|
-
status?: string | null;
|
|
49
|
-
tx?: string | null;
|
|
50
|
-
calldata?: string | null;
|
|
51
|
-
chain_id?: number | null;
|
|
52
|
-
from?: string | null;
|
|
53
|
-
} | null;
|
|
54
|
-
solana?: {
|
|
55
|
-
status?: string | null;
|
|
56
|
-
signature?: string | null;
|
|
57
|
-
slot?: number | null;
|
|
58
|
-
cluster?: string | null;
|
|
59
|
-
memo?: string | null;
|
|
60
|
-
fee_payer?: string | null;
|
|
61
|
-
} | null;
|
|
62
|
-
} | null;
|
|
63
|
-
issuer_signature?: {
|
|
64
|
-
jws?: string;
|
|
65
|
-
kid?: string;
|
|
66
|
-
issuer_jwk?: Es256Jwk;
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
export interface HeadTrustResult {
|
|
70
|
-
ok: boolean;
|
|
71
|
-
reason: string | null;
|
|
72
|
-
message: string | null;
|
|
73
|
-
kid: string | null;
|
|
74
|
-
trust: 'jwks' | 'pinned_kid' | 'issuer_history' | null;
|
|
75
|
-
payload: Record<string, unknown> | null;
|
|
76
|
-
}
|
|
77
|
-
export interface AnchorWalletList {
|
|
78
|
-
base: string[];
|
|
79
|
-
solana: string[];
|
|
80
|
-
sources: Array<'pin' | 'well_known' | 'issuer_history'>;
|
|
81
|
-
not_consulted: readonly ['issuer_root', 'dns'];
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* True when a verified head anchors a chain but the signature does not name
|
|
85
|
-
* that chain's signer. Those fields were added after the epoch-1 head and
|
|
86
|
-
* after the epoch-2 head signed at 07:43 ET on 2026-10-07. A pending side
|
|
87
|
-
* is not this case.
|
|
88
|
-
*/
|
|
89
|
-
export declare function headOmitsPinnedSigner(payload: Record<string, unknown> | null | undefined): boolean;
|
|
90
|
-
/** Signed payload must carry the same root, size, epoch, and anchors the check uses. */
|
|
91
|
-
export declare function headClaimsMatch(outer: TreeHeadDocument, payload: Record<string, unknown>): string | null;
|
|
92
|
-
export declare function verifyTreeHeadTrust(head: TreeHeadDocument | null | undefined, { jwks, trustedKids, issuerHistory, strictIssuerHistory, }?: {
|
|
93
|
-
jwks?: JwksLike;
|
|
94
|
-
trustedKids?: readonly string[];
|
|
95
|
-
issuerHistory?: IssuerHistoryDocument | null;
|
|
96
|
-
strictIssuerHistory?: boolean;
|
|
97
|
-
}): HeadTrustResult;
|
|
98
|
-
export declare function verifyAnchorWalletDocument(doc: {
|
|
99
|
-
schema?: string;
|
|
100
|
-
base?: unknown;
|
|
101
|
-
solana?: unknown;
|
|
102
|
-
issuer_signature?: {
|
|
103
|
-
jws?: string;
|
|
104
|
-
issuer_jwk?: Es256Jwk;
|
|
105
|
-
};
|
|
106
|
-
} | null | undefined, { jwks, trustedKids }?: {
|
|
107
|
-
jwks?: JwksLike;
|
|
108
|
-
trustedKids?: readonly string[];
|
|
109
|
-
}): {
|
|
110
|
-
ok: true;
|
|
111
|
-
base: string[];
|
|
112
|
-
solana: string[];
|
|
113
|
-
} | {
|
|
114
|
-
ok: false;
|
|
115
|
-
reason: string;
|
|
116
|
-
};
|
|
117
|
-
export declare function compileAnchorWallets({ jwks, trustedKids, issuerHistory, published, }?: {
|
|
118
|
-
jwks?: JwksLike;
|
|
119
|
-
trustedKids?: readonly string[];
|
|
120
|
-
issuerHistory?: IssuerHistoryDocument | null;
|
|
121
|
-
published?: {
|
|
122
|
-
base: string[];
|
|
123
|
-
solana: string[];
|
|
124
|
-
} | null;
|
|
125
|
-
}): AnchorWalletList;
|
|
126
|
-
export declare function walletListed(list: readonly string[], value: string, chain: 'base' | 'solana'): boolean;
|
|
127
|
-
export declare function sameBaseAddress(left: string, right: string): boolean;
|
|
128
|
-
export {};
|
|
129
|
-
//# sourceMappingURL=anchor-trust.d.ts.map
|