@forestrie/forestrie-cli 0.10.0 → 0.11.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 +59 -3
- package/dist/cli.js +3716 -1682
- package/package.json +3 -3
- package/src/command.ts +2 -0
- package/src/commands/fetch-ks256-attestation.ts +52 -0
- package/src/commands/verify-grant.ts +8 -2
- package/src/commands/verify.ts +8 -2
- package/src/lib/known-log-key.ts +35 -0
- package/src/lib/verify-inputs.ts +1 -1
- package/src/lib/verify-report.ts +78 -0
- package/src/main/fetch-ks256-attestation.ts +245 -0
- package/src/main/verify.ts +169 -60
- package/src/options/fetch-ks256-attestation.ts +60 -0
- package/src/options/verify.ts +10 -2
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@ deploy, sign, register, and verify against a forestrie log:
|
|
|
17
17
|
| `decode-receipt` | Decode a COSE receipt — it is just COSE: Sign1 + MMR inclusion |
|
|
18
18
|
| `verify` | Verify a receipt offline — the same closer for every other subcommand |
|
|
19
19
|
| `fetch-accumulator` | Cache the on-chain accumulator as a `--known-accumulator` snapshot |
|
|
20
|
+
| `fetch-ks256-attestation` | Cache an ERC-1271 attestation for a KS256 contract root as a `--ks256-attestation` file |
|
|
20
21
|
|
|
21
22
|
**Status:** subcommands not yet implemented declare their real argument
|
|
22
23
|
surface and parse it, then exit non-zero with a structured `not_implemented`
|
|
@@ -334,9 +335,13 @@ signature — no operator trust required.
|
|
|
334
335
|
|
|
335
336
|
`verify` takes four named trust anchors — pass whichever you hold:
|
|
336
337
|
|
|
337
|
-
- **`--known-log-key`** — a caller-known log owner key (
|
|
338
|
-
`
|
|
339
|
-
|
|
338
|
+
- **`--known-log-key`** — a caller-known log owner key (env `KNOWN_LOG_KEY`):
|
|
339
|
+
base64 `x||y` (a 64-byte ES256 key) or a 20-byte KS256 address (`0x` + 40
|
|
340
|
+
hex, or base64); fully offline, checks the signature under a key you trust
|
|
341
|
+
out of band (the SCITT / SSH-known-hosts posture). A KS256 address asserts,
|
|
342
|
+
and does not prove, the key-to-log binding, and cannot root
|
|
343
|
+
`--checkpoint-chain` (which needs ES256). `--genesis` may accompany it: it
|
|
344
|
+
then supplies only the forest chain id an attestation must match.
|
|
340
345
|
- **`--genesis`** — a cached `genesis.cbor` (the univocity-instance root
|
|
341
346
|
registration). Roots a receipt whose signer chains to that root owner; for a
|
|
342
347
|
child log deeper in the hierarchy, reaching genesis is the grant-chain walk
|
|
@@ -362,6 +367,19 @@ and collapsing it into split-view is the specific confusion the trust model
|
|
|
362
367
|
warns against. Split-view is the load-bearing property; currency is at most the
|
|
363
368
|
`--rpc-url` "as of now" delta.
|
|
364
369
|
|
|
370
|
+
#### KS256 roots and `--ks256-attestation`
|
|
371
|
+
|
|
372
|
+
A genesis (or known-key) root that is a KS256 address verifies the receipt's
|
|
373
|
+
delegation certificate by ecrecover when the root is an EOA — pure, offline,
|
|
374
|
+
no chain call. A contract root (a Safe) cannot be recovered offline and fails
|
|
375
|
+
`ks256_root_not_recovered`; give `--ks256-attestation <file>` (from
|
|
376
|
+
`fetch-ks256-attestation`) and the certificate verifies as *valid under the
|
|
377
|
+
contract's signers at the attested block* — a narrower guarantee than a
|
|
378
|
+
signature by one key, reported as such. The attestation must bind the root
|
|
379
|
+
address, the certificate digest and signature, and the forest's genesis chain
|
|
380
|
+
id (`--genesis`; under `--known-log-key` without it the result is
|
|
381
|
+
`ks256_attestation_chain_unbound`). `verify` never calls the chain.
|
|
382
|
+
|
|
365
383
|
### `fetch-accumulator`
|
|
366
384
|
|
|
367
385
|
```bash
|
|
@@ -375,6 +393,44 @@ Reads `logState(logId)` pinned to a block and writes the
|
|
|
375
393
|
`(chainId, univocity, logId, size, blockNumber, blockHash)` — anyone with
|
|
376
394
|
RPC can re-run the read at that block and confirm or disprove it.
|
|
377
395
|
|
|
396
|
+
### `fetch-ks256-attestation`
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
forestrie fetch-ks256-attestation \
|
|
400
|
+
--receipt receipt.cbor --genesis genesis.cbor --rpc-url "$RPC_URL" \
|
|
401
|
+
--out attestation.cbor # [--root 0x… ] [--block <n>|latest]
|
|
402
|
+
|
|
403
|
+
forestrie verify --genesis genesis.cbor --ks256-attestation attestation.cbor …
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Resolves one block (`--block`, default latest; a block whose number differs
|
|
407
|
+
from an explicit `--block` is refused), then reads the contract's code and calls
|
|
408
|
+
its ERC-1271 `isValidSignature(digest, signature)` with the receipt's delegation
|
|
409
|
+
certificate, both pinned by that block's **hash** (EIP-1898,
|
|
410
|
+
`requireCanonical`), so the recorded `blockHash` is the state actually read.
|
|
411
|
+
The call must return exactly one 32-byte word equal to the ERC-1271 magic
|
|
412
|
+
value, `0x1626ba7e` followed by 28 zero bytes: extra data, non-zero padding or a
|
|
413
|
+
short result (including a fallback that echoes the calldata, whose selector is
|
|
414
|
+
that same magic) is refused, as is a revert; other RPC errors are reported as
|
|
415
|
+
RPC failures, not as the contract refusing. It writes canonical CBOR binding
|
|
416
|
+
`(chainId, address, digest, signature hash, blockNumber, blockHash, magic)` —
|
|
417
|
+
anyone with RPC can re-run the call at that block. `--root` overrides the
|
|
418
|
+
genesis root; `--genesis` also supplies the chain the RPC must match. It
|
|
419
|
+
refuses, writing nothing, an EOA root (no code: `verify` recovers it), a chain
|
|
420
|
+
differing from the genesis, a receipt with no delegation certificate or a
|
|
421
|
+
non-KS256 genesis root, and any result other than that magic word.
|
|
422
|
+
Use an archive node for an old `--block`.
|
|
423
|
+
|
|
424
|
+
**Trust.** An attestation is what the RPC you named reported; it is unsigned,
|
|
425
|
+
and `verify` cannot tell a fetched one from a forged one. So:
|
|
426
|
+
|
|
427
|
+
- **Fetch it yourself,** or accept one only from a party you would trust to
|
|
428
|
+
read the chain for you.
|
|
429
|
+
- **For more confidence, ask several independent RPCs** with the same
|
|
430
|
+
`--block` and check that each succeeds with the same `blockHash`.
|
|
431
|
+
- **Pick a block near the receipt's time.** The guarantee is "valid under the
|
|
432
|
+
contract's signers at that block", and owners can change after issuance.
|
|
433
|
+
|
|
378
434
|
## Use as a library: `decode-receipt`
|
|
379
435
|
|
|
380
436
|
The receipt decoder behind `forestrie decode-receipt` is exported as a
|