@forestrie/receipt-verify 0.8.0 → 0.8.2
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/freshen-receipt.d.ts.map +1 -1
- package/dist/freshen-receipt.js +31 -14
- package/package.json +3 -3
- package/src/freshen-receipt.ts +30 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"freshen-receipt.d.ts","sourceRoot":"","sources":["../src/freshen-receipt.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"freshen-receipt.d.ts","sourceRoot":"","sources":["../src/freshen-receipt.ts"],"names":[],"mappings":"AAyDA,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,uBAAuB,CAAC;AAI/B,MAAM,MAAM,mBAAmB,GAAG;IAChC,iEAAiE;IACjE,eAAe,EAAE,UAAU,CAAC;IAC5B;uEACmE;IACnE,SAAS,EAAE,UAAU,CAAC;IACtB;;mFAE+E;IAC/E,iBAAiB,EAAE,SAAS,0BAA0B,EAAE,CAAC;IACzD;iEAC6D;IAC7D,eAAe,CAAC,EAAE,UAAU,EAAE,CAAC;IAC/B;wDACoD;IACpD,qBAAqB,EAAE,UAAU,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,wEAAwE;IACxE,OAAO,EAAE,UAAU,CAAC;IACpB,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AASF;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CAyJ/B"}
|
package/dist/freshen-receipt.js
CHANGED
|
@@ -3,23 +3,33 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A receipt goes stale when log growth buries the peak it commits to. Freshening
|
|
5
5
|
* re-anchors it to the CURRENT sealed state without tiles: extend the leaf's
|
|
6
|
-
* inclusion path from its old peak up to the
|
|
6
|
+
* inclusion path from its old peak up to the current accumulator using the
|
|
7
7
|
* checkpoint chain's consistency proofs (the tile-free source of the climb
|
|
8
8
|
* nodes), then attach that fresh path at header 396 to the LATEST checkpoint's
|
|
9
|
-
* pre-signed peak receipt. The result is a native receipt
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* finding: the calldata provider supplies the climb material tile-free, but the
|
|
13
|
-
* signature/cert comes from the latest `.sth`).
|
|
9
|
+
* pre-signed peak receipt. The result is a native receipt about the current
|
|
10
|
+
* state (the calldata provider supplies the climb material tile-free, but the
|
|
11
|
+
* signature/cert always comes from a latest `.sth`; plan-2607-32 Phase 3).
|
|
14
12
|
*
|
|
15
|
-
* Trust note
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
13
|
+
* Trust note — three orthogonal concerns (see forestrie-cli's TRUST-MODEL.md):
|
|
14
|
+
* - FRESHNESS is what freshen produces: the extended path recomputes the
|
|
15
|
+
* current accumulator peak (self-checked below); a caller may additionally
|
|
16
|
+
* bind that accumulator to a trusted chain read. This is the receipt's
|
|
17
|
+
* substance.
|
|
18
|
+
* - SEALING attestation: the emitted receipt necessarily carries the LATEST
|
|
19
|
+
* checkpoint's signature — its label-1000 owner→sealer delegation cert and
|
|
20
|
+
* pre-signed peak receipt. A freshened receipt is a NEW attestation of the
|
|
21
|
+
* current state, so the only signature it can carry is one over a checkpoint
|
|
22
|
+
* at the current size; attaching any other would be forgery. A rotation of
|
|
23
|
+
* the delegated-TO sealer key is routine and within the owner's authority, so
|
|
24
|
+
* freshen does NOT flag it — there is no signer-change gate (this supersedes
|
|
25
|
+
* the earlier `--allow-new-signer` sketch; plan-2607-32 F2). The old receipt's
|
|
26
|
+
* cert is irrelevant to the emitted artifact.
|
|
27
|
+
* - AUTHORITY (does the log chain to genesis) is NOT carried by this signature
|
|
28
|
+
* and NOT freshen's concern: it is the grant hierarchy, proven by grants + their
|
|
29
|
+
* inclusion proofs (and enforced on-chain at publish). Downstream `verify`
|
|
30
|
+
* picks the posture — `--genesis`/`--known-log-key` check the sealer chains to
|
|
31
|
+
* the owner; the accumulator rungs check freshness directly and treat the
|
|
32
|
+
* signature as vestigial.
|
|
23
33
|
*
|
|
24
34
|
* Two independent fail-closed guards keep a bad assembly from ever minting:
|
|
25
35
|
* - Cross-checks against the checkpoint being borrowed from: the supplied
|
|
@@ -138,6 +148,13 @@ export async function freshenReceipt(input) {
|
|
|
138
148
|
store.set(fullIndices[k], oldPath[k]);
|
|
139
149
|
}
|
|
140
150
|
for (const link of links) {
|
|
151
|
+
// A base-0 link (treeSize1 === 0) has no from-peaks to climb — a 0→N
|
|
152
|
+
// consistency proof carries `paths: []` (the whole accumulator is its
|
|
153
|
+
// right-peaks). Skip it: it contributes no store nodes, and calling
|
|
154
|
+
// `peakMMRIndexes(-1n)` would throw (`posHeight(0)`, FOR-414). A genesis-
|
|
155
|
+
// rooted `.sth` chain always starts with such a link.
|
|
156
|
+
if (link.treeSize1 === 0n)
|
|
157
|
+
continue;
|
|
141
158
|
const fromPeaks = peakMMRIndexes(link.treeSize1 - 1n);
|
|
142
159
|
fromPeaks.forEach((peakIndex, j) => {
|
|
143
160
|
const climb = link.paths[j];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forestrie/receipt-verify",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Offline SCITT grant receipt verification (ADR-0045)",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@noble/hashes": "^1.7.1",
|
|
31
|
-
"@forestrie/
|
|
32
|
-
"@forestrie/
|
|
31
|
+
"@forestrie/merklelog": "0.3.0",
|
|
32
|
+
"@forestrie/encoding": "0.5.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"esbuild": "^0.24.0",
|
package/src/freshen-receipt.ts
CHANGED
|
@@ -3,23 +3,33 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A receipt goes stale when log growth buries the peak it commits to. Freshening
|
|
5
5
|
* re-anchors it to the CURRENT sealed state without tiles: extend the leaf's
|
|
6
|
-
* inclusion path from its old peak up to the
|
|
6
|
+
* inclusion path from its old peak up to the current accumulator using the
|
|
7
7
|
* checkpoint chain's consistency proofs (the tile-free source of the climb
|
|
8
8
|
* nodes), then attach that fresh path at header 396 to the LATEST checkpoint's
|
|
9
|
-
* pre-signed peak receipt. The result is a native receipt
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* finding: the calldata provider supplies the climb material tile-free, but the
|
|
13
|
-
* signature/cert comes from the latest `.sth`).
|
|
9
|
+
* pre-signed peak receipt. The result is a native receipt about the current
|
|
10
|
+
* state (the calldata provider supplies the climb material tile-free, but the
|
|
11
|
+
* signature/cert always comes from a latest `.sth`; plan-2607-32 Phase 3).
|
|
14
12
|
*
|
|
15
|
-
* Trust note
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
13
|
+
* Trust note — three orthogonal concerns (see forestrie-cli's TRUST-MODEL.md):
|
|
14
|
+
* - FRESHNESS is what freshen produces: the extended path recomputes the
|
|
15
|
+
* current accumulator peak (self-checked below); a caller may additionally
|
|
16
|
+
* bind that accumulator to a trusted chain read. This is the receipt's
|
|
17
|
+
* substance.
|
|
18
|
+
* - SEALING attestation: the emitted receipt necessarily carries the LATEST
|
|
19
|
+
* checkpoint's signature — its label-1000 owner→sealer delegation cert and
|
|
20
|
+
* pre-signed peak receipt. A freshened receipt is a NEW attestation of the
|
|
21
|
+
* current state, so the only signature it can carry is one over a checkpoint
|
|
22
|
+
* at the current size; attaching any other would be forgery. A rotation of
|
|
23
|
+
* the delegated-TO sealer key is routine and within the owner's authority, so
|
|
24
|
+
* freshen does NOT flag it — there is no signer-change gate (this supersedes
|
|
25
|
+
* the earlier `--allow-new-signer` sketch; plan-2607-32 F2). The old receipt's
|
|
26
|
+
* cert is irrelevant to the emitted artifact.
|
|
27
|
+
* - AUTHORITY (does the log chain to genesis) is NOT carried by this signature
|
|
28
|
+
* and NOT freshen's concern: it is the grant hierarchy, proven by grants + their
|
|
29
|
+
* inclusion proofs (and enforced on-chain at publish). Downstream `verify`
|
|
30
|
+
* picks the posture — `--genesis`/`--known-log-key` check the sealer chains to
|
|
31
|
+
* the owner; the accumulator rungs check freshness directly and treat the
|
|
32
|
+
* signature as vestigial.
|
|
23
33
|
*
|
|
24
34
|
* Two independent fail-closed guards keep a bad assembly from ever minting:
|
|
25
35
|
* - Cross-checks against the checkpoint being borrowed from: the supplied
|
|
@@ -200,6 +210,12 @@ export async function freshenReceipt(
|
|
|
200
210
|
store.set(fullIndices[k]!, oldPath[k]!);
|
|
201
211
|
}
|
|
202
212
|
for (const link of links) {
|
|
213
|
+
// A base-0 link (treeSize1 === 0) has no from-peaks to climb — a 0→N
|
|
214
|
+
// consistency proof carries `paths: []` (the whole accumulator is its
|
|
215
|
+
// right-peaks). Skip it: it contributes no store nodes, and calling
|
|
216
|
+
// `peakMMRIndexes(-1n)` would throw (`posHeight(0)`, FOR-414). A genesis-
|
|
217
|
+
// rooted `.sth` chain always starts with such a link.
|
|
218
|
+
if (link.treeSize1 === 0n) continue;
|
|
203
219
|
const fromPeaks = peakMMRIndexes(link.treeSize1 - 1n);
|
|
204
220
|
fromPeaks.forEach((peakIndex, j) => {
|
|
205
221
|
const climb = link.paths[j];
|