@forestrie/receipt-verify 1.1.0 → 2.0.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/attach-transparent-statement-receipt.d.ts +5 -1
- package/dist/attach-transparent-statement-receipt.d.ts.map +1 -1
- package/dist/attach-transparent-statement-receipt.js +7 -3
- package/dist/build-receipt-offline.d.ts +8 -1
- package/dist/build-receipt-offline.d.ts.map +1 -1
- package/dist/build-receipt-offline.js +31 -24
- package/dist/checkpoint-chain.d.ts +130 -17
- package/dist/checkpoint-chain.d.ts.map +1 -1
- package/dist/checkpoint-chain.js +216 -117
- package/dist/decode-checkpoint-consistency-proof.d.ts +38 -0
- package/dist/decode-checkpoint-consistency-proof.d.ts.map +1 -0
- package/dist/decode-checkpoint-consistency-proof.js +108 -0
- package/dist/freshen-receipt.d.ts +23 -6
- package/dist/freshen-receipt.d.ts.map +1 -1
- package/dist/freshen-receipt.js +29 -17
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/parse-receipt.d.ts.map +1 -1
- package/dist/parse-receipt.js +2 -3
- package/package.json +3 -3
- package/src/attach-transparent-statement-receipt.ts +10 -3
- package/src/build-receipt-offline.ts +41 -22
- package/src/checkpoint-chain.ts +279 -136
- package/src/decode-checkpoint-consistency-proof.ts +136 -0
- package/src/freshen-receipt.ts +56 -25
- package/src/index.ts +2 -0
- package/src/parse-receipt.ts +2 -4
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* SCITT transparent statement unprotected receipt label (grants.md §3.2).
|
|
3
|
+
* Alias of {@link COSE_LABEL_VDP} — kept exported under this name for
|
|
4
|
+
* existing callers.
|
|
5
|
+
*/
|
|
2
6
|
export declare const HEADER_RECEIPT = 396;
|
|
3
7
|
export declare function attachReceiptAndIdtimestampToTransparentStatement(statementBytes: Uint8Array, receiptCborBytes: Uint8Array, idtimestampBe8: Uint8Array): Uint8Array;
|
|
4
8
|
//# sourceMappingURL=attach-transparent-statement-receipt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attach-transparent-statement-receipt.d.ts","sourceRoot":"","sources":["../src/attach-transparent-statement-receipt.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"attach-transparent-statement-receipt.d.ts","sourceRoot":"","sources":["../src/attach-transparent-statement-receipt.ts"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,eAAO,MAAM,cAAc,MAAiB,CAAC;AAE7C,wBAAgB,iDAAiD,CAC/D,cAAc,EAAE,UAAU,EAC1B,gBAAgB,EAAE,UAAU,EAC5B,cAAc,EAAE,UAAU,GACzB,UAAU,CAWZ"}
|
|
@@ -6,10 +6,14 @@
|
|
|
6
6
|
* Golden vectors for receipt construction/verification are tracked by
|
|
7
7
|
* FOR-289.
|
|
8
8
|
*/
|
|
9
|
-
import { mergeUnprotectedIntoCoseSign1 } from "@forestrie/encoding";
|
|
9
|
+
import { COSE_LABEL_VDP, mergeUnprotectedIntoCoseSign1, } from "@forestrie/encoding";
|
|
10
10
|
import { HEADER_IDTIMESTAMP } from "./forest-genesis-labels.js";
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* SCITT transparent statement unprotected receipt label (grants.md §3.2).
|
|
13
|
+
* Alias of {@link COSE_LABEL_VDP} — kept exported under this name for
|
|
14
|
+
* existing callers.
|
|
15
|
+
*/
|
|
16
|
+
export const HEADER_RECEIPT = COSE_LABEL_VDP;
|
|
13
17
|
export function attachReceiptAndIdtimestampToTransparentStatement(statementBytes, receiptCborBytes, idtimestampBe8) {
|
|
14
18
|
if (idtimestampBe8.length !== 8) {
|
|
15
19
|
throw new Error("idtimestamp must be 8 bytes (big-endian)");
|
|
@@ -28,7 +28,14 @@ export type ParsedCheckpoint = {
|
|
|
28
28
|
unprotected: Map<number, unknown>;
|
|
29
29
|
/** Pre-signed peak receipts (label -65931), or null when absent. */
|
|
30
30
|
peakReceipts: unknown[] | null;
|
|
31
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Sealed tree size: the SIGNED `tree-size-2` from the checkpoint's
|
|
33
|
+
* PROTECTED header (ADR-0066 D1 as amended, label -65933), not the
|
|
34
|
+
* unprotected consistency proof's declared value. `null` when the
|
|
35
|
+
* checkpoint carries no embedded consistency proof or no signed
|
|
36
|
+
* tree-size-2 — such a checkpoint is not verifiable and callers must
|
|
37
|
+
* treat it exactly as they would a checkpoint with no proof at all.
|
|
38
|
+
*/
|
|
32
39
|
mmrSize: bigint | null;
|
|
33
40
|
delegationCert: Uint8Array | null;
|
|
34
41
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-receipt-offline.d.ts","sourceRoot":"","sources":["../src/build-receipt-offline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"build-receipt-offline.d.ts","sourceRoot":"","sources":["../src/build-receipt-offline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AASH,OAAO,EAIL,mBAAmB,EAEnB,KAAK,eAAe,EAErB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,oBAAoB,CAAC;AAO5B;;;;GAIG;AACH,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAC/B,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,oEAAoE;IACpE,YAAY,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B;;;;;;;OAOG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,EAAE,UAAU,GAAG,IAAI,CAAC;CACnC,CAAC;AAEF,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,eAAe,EAAE,UAAU,GAAG,gBAAgB,CAqB7E;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,EAAE,UAAU,CAAC;IACxB,eAAe,EAAE,UAAU,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,UAAU,CAyCZ;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,UAAU,EAAE,GAClB,UAAU,CA4CZ;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,mEAAmE;IACnE,IAAI,EAAE,UAAU,CAAC;IACjB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,EAAE,UAAU,CAAC;CACvB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,WAAW,EAAE,UAAU,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAwBnC"}
|
|
@@ -14,14 +14,13 @@
|
|
|
14
14
|
* at an externally attested tree size (e.g. Univocity `logState` on Base
|
|
15
15
|
* Sepolia) and compare the computed peak with the published accumulator.
|
|
16
16
|
*/
|
|
17
|
-
import { decodeCborDeterministic, encodeCborDeterministic, } from "@forestrie/encoding";
|
|
17
|
+
import { COSE_LABEL_PEAK_RECEIPTS, COSE_LABEL_VDP, decodeCborDeterministic, encodeCborDeterministic, readProtectedTreeSize2, } from "@forestrie/encoding";
|
|
18
18
|
import { calculateRoot, inclusionProof, massifIndexFromMMRIndex, openMassifNodeStore, peakIndexForLeafProof, } from "@forestrie/merklelog";
|
|
19
19
|
import { requireCoseSign1, toHeaderMap, unwrapCoseSign1Tag, } from "./parse-receipt.js";
|
|
20
|
+
import { decodeConsistencyProofFromUnprotected } from "./decode-checkpoint-consistency-proof.js";
|
|
20
21
|
import { SubtleHasher } from "./subtle-hasher.js";
|
|
21
|
-
|
|
22
|
-
const SEAL_PEAK_RECEIPTS_LABEL = -65931;
|
|
22
|
+
/** Not in scope for the shared cose-labels module (FOR-568 §4.1). */
|
|
23
23
|
const DELEGATION_CERT_LABEL = 1000;
|
|
24
|
-
const VDP_CONSISTENCY_PROOF_KEY = -2;
|
|
25
24
|
/**
|
|
26
25
|
* Re-exported for compatibility. The MMR proof math and massif node store now
|
|
27
26
|
* live in `@forestrie/merklelog` (plan-2607-15 §4, phase 2); receipt-verify
|
|
@@ -33,7 +32,7 @@ export function parseCheckpoint(checkpointBytes) {
|
|
|
33
32
|
const decoded = decodeCborDeterministic(checkpointBytes);
|
|
34
33
|
const coseSign1 = requireCoseSign1(unwrapCoseSign1Tag(decoded));
|
|
35
34
|
const unprotected = toHeaderMap(coseSign1[1]);
|
|
36
|
-
const peakReceiptsRaw = unprotected.get(
|
|
35
|
+
const peakReceiptsRaw = unprotected.get(COSE_LABEL_PEAK_RECEIPTS);
|
|
37
36
|
const peakReceipts = Array.isArray(peakReceiptsRaw) ? peakReceiptsRaw : null;
|
|
38
37
|
const delegationCertRaw = unprotected.get(DELEGATION_CERT_LABEL);
|
|
39
38
|
const delegationCert = delegationCertRaw instanceof Uint8Array && delegationCertRaw.length > 0
|
|
@@ -43,7 +42,7 @@ export function parseCheckpoint(checkpointBytes) {
|
|
|
43
42
|
coseSign1,
|
|
44
43
|
unprotected,
|
|
45
44
|
peakReceipts,
|
|
46
|
-
mmrSize: sealedSizeFromCheckpoint(unprotected),
|
|
45
|
+
mmrSize: sealedSizeFromCheckpoint(coseSign1, unprotected),
|
|
47
46
|
delegationCert,
|
|
48
47
|
};
|
|
49
48
|
}
|
|
@@ -114,7 +113,7 @@ export function assembleReceiptFromProof(checkpoint, mmrIndex, proof) {
|
|
|
114
113
|
const verifiableProofs = new Map([
|
|
115
114
|
[-1, [inclusionProofEntry]],
|
|
116
115
|
]);
|
|
117
|
-
receiptUnprotected.set(
|
|
116
|
+
receiptUnprotected.set(COSE_LABEL_VDP, verifiableProofs);
|
|
118
117
|
// Peak receipts are signed with detached payload; emit nil so verify uses
|
|
119
118
|
// the peak derived from the inclusion proof.
|
|
120
119
|
const assembled = [
|
|
@@ -155,26 +154,34 @@ function cborBytes(value) {
|
|
|
155
154
|
return encodeCborDeterministic(value);
|
|
156
155
|
}
|
|
157
156
|
/**
|
|
158
|
-
* Sealed mmr size from a format-v3 checkpoint: tree-size-2
|
|
159
|
-
*
|
|
160
|
-
*
|
|
157
|
+
* Sealed mmr size from a format-v3 checkpoint: the SIGNED `tree-size-2`
|
|
158
|
+
* (ADR-0066 D1 as amended, label -65933) from the PROTECTED header — not the
|
|
159
|
+
* unprotected consistency proof's declared value, which a checkpoint without
|
|
160
|
+
* a signing key could freely restate (ADR-0066's "keyless first checkpoint"
|
|
161
|
+
* case). A consistency proof must still be present (an unsigned checkpoint
|
|
162
|
+
* with no proof is not sealed at all); its declared sizes are not otherwise
|
|
163
|
+
* used here — {@link checkpointConsistencyProof} in `checkpoint-chain.ts`
|
|
164
|
+
* is the validating decode that requires the two to agree.
|
|
165
|
+
*
|
|
166
|
+
* Lenient by design: an absent proof, a malformed proof, or an absent or
|
|
167
|
+
* malformed signed tree-size-2 all yield `null` rather than a throw, so a
|
|
168
|
+
* caller of {@link parseCheckpoint} sees exactly the same "not verifiable"
|
|
169
|
+
* outcome either way.
|
|
161
170
|
*/
|
|
162
|
-
function sealedSizeFromCheckpoint(unprotected) {
|
|
163
|
-
|
|
164
|
-
|
|
171
|
+
function sealedSizeFromCheckpoint(coseSign1, unprotected) {
|
|
172
|
+
let declared;
|
|
173
|
+
try {
|
|
174
|
+
declared = decodeConsistencyProofFromUnprotected(unprotected);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
165
177
|
return null;
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (!(proofBstr instanceof Uint8Array))
|
|
178
|
+
}
|
|
179
|
+
if (declared === null)
|
|
169
180
|
return null;
|
|
170
|
-
|
|
171
|
-
|
|
181
|
+
try {
|
|
182
|
+
return readProtectedTreeSize2(coseSign1[0]);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
172
185
|
return null;
|
|
173
|
-
const treeSize2 = proof[1];
|
|
174
|
-
if (typeof treeSize2 === "bigint")
|
|
175
|
-
return treeSize2;
|
|
176
|
-
if (typeof treeSize2 === "number" && Number.isSafeInteger(treeSize2)) {
|
|
177
|
-
return BigInt(treeSize2);
|
|
178
186
|
}
|
|
179
|
-
return null;
|
|
180
187
|
}
|
|
@@ -1,28 +1,101 @@
|
|
|
1
|
-
/** Draft-bryce consistency proof embedded in a v3 checkpoint.
|
|
1
|
+
/** Draft-bryce consistency proof embedded in a v3 checkpoint. `treeSize2` is
|
|
2
|
+
* cross-checked against the checkpoint's SIGNED tree-size-2 (ADR-0066 D1 as
|
|
3
|
+
* amended); `treeSize1` is unsigned prover context, not cross-checked here —
|
|
4
|
+
* see {@link verifyCheckpointChain}, which compares it with the trusted
|
|
5
|
+
* origin instead. */
|
|
2
6
|
export type CheckpointConsistencyProof = {
|
|
3
7
|
treeSize1: bigint;
|
|
4
8
|
treeSize2: bigint;
|
|
9
|
+
/** Signed `tree-size-2` (protected header label -65933); equal to
|
|
10
|
+
* {@link treeSize2} — {@link checkpointConsistencyProof} enforces this. */
|
|
11
|
+
signedTreeSize2: bigint;
|
|
5
12
|
/** One inclusion path per tree-size-1 peak, proven at tree-size-2. */
|
|
6
13
|
paths: Uint8Array[][];
|
|
7
14
|
/** New peaks not covered by the proven roots (draft `right-peaks`). */
|
|
8
15
|
rightPeaks: Uint8Array[];
|
|
9
16
|
};
|
|
10
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* The checkpoint's SIGNED `tree-size-2` (protected header, ADR-0066 D1 as
|
|
19
|
+
* amended) differs from the declared `tree-size-2` of its embedded
|
|
20
|
+
* (unprotected) consistency proof. Distinct from a structurally malformed
|
|
21
|
+
* proof: {@link verifyCheckpointChain} reports this as `"size_mismatch"`,
|
|
22
|
+
* not `"proof_malformed"`.
|
|
23
|
+
*/
|
|
24
|
+
export declare class CheckpointSignedSizeMismatchError extends Error {
|
|
25
|
+
constructor(message: string);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The checkpoint's ES256 signature is the malleable high-s twin (`s > n/2`,
|
|
29
|
+
* `n` the P-256 group order): go-merklelog rejects these for checkpoint
|
|
30
|
+
* COSE_Sign1 signatures because the univocity contract's P-256 verifier
|
|
31
|
+
* does, so a receipt that verified here while carrying a high-s signature
|
|
32
|
+
* could be one the chain refuses (FOR-568 rollout item 4). Checked here,
|
|
33
|
+
* before any WebCrypto verify is attempted, so a rejected signature never
|
|
34
|
+
* reaches {@link verifyCheckpointChain}'s `verifySignature` callback. Scoped
|
|
35
|
+
* to the checkpoint receipt path only — this module never touches the WebAuthn
|
|
36
|
+
* (-65800) or session-key-endorsement (-65801) signature paths, which stay
|
|
37
|
+
* governed by their own canonical-form rules.
|
|
38
|
+
*/
|
|
39
|
+
export declare class CheckpointHighSSignatureError extends Error {
|
|
40
|
+
constructor(message: string);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Decode the embedded consistency proof (`vdp` 396 key -2) and require its
|
|
44
|
+
* declared `tree-size-2` to equal the checkpoint's SIGNED `tree-size-2` from
|
|
45
|
+
* the protected header (ADR-0066 D1 as amended, D5.5, label -65933).
|
|
46
|
+
* `tree-size-1` is not signed and is not checked here (D2 is withdrawn); see
|
|
47
|
+
* {@link verifyCheckpointChain} for its comparison against the trusted
|
|
48
|
+
* origin.
|
|
49
|
+
*
|
|
50
|
+
* Also rejects a malleable high-s ES256 signature (see
|
|
51
|
+
* {@link CheckpointHighSSignatureError}) before any fold or WebCrypto verify
|
|
52
|
+
* work — a checkpoint signed with any other algorithm (e.g. KS256) is not
|
|
53
|
+
* subject to this check, since it does not go through the P-256 WebCrypto
|
|
54
|
+
* path this guards.
|
|
55
|
+
*
|
|
56
|
+
* @throws {Error} when the protected header carries no consistency proof,
|
|
57
|
+
* the proof is structurally malformed (see
|
|
58
|
+
* {@link decodeConsistencyProofFromUnprotected}), or the protected header
|
|
59
|
+
* carries no signed tree-size-2 label
|
|
60
|
+
* @throws {CheckpointSignedSizeMismatchError} when the signed tree-size-2
|
|
61
|
+
* differs from the declared proof's tree-size-2
|
|
62
|
+
* @throws {CheckpointHighSSignatureError} when the checkpoint is ES256-signed
|
|
63
|
+
* with a high-s (malleable) signature
|
|
64
|
+
*/
|
|
11
65
|
export declare function checkpointConsistencyProof(checkpointBytes: Uint8Array): CheckpointConsistencyProof;
|
|
12
66
|
/**
|
|
13
|
-
* One fold step: from the
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
67
|
+
* One fold step: from the CALLER-TRUSTED accumulator at `sizeFrom`, produce
|
|
68
|
+
* the `proof.treeSize2` accumulator via the size-driven
|
|
69
|
+
* {@link consistentRootsForSizes} (ADR-0066 D5) — `roots` (the proven
|
|
70
|
+
* prefix) followed by the proof's supplied right-peaks (the target peaks no
|
|
71
|
+
* path reaches).
|
|
72
|
+
*
|
|
73
|
+
* `sizeFrom` is a parameter, not read off `proof`, because the fold must run
|
|
74
|
+
* against a size the CALLER already trusts (the previous link's verified
|
|
75
|
+
* `treeSize2`, or the caller's anchor for a first link) — reading it from
|
|
76
|
+
* the proof instead would let an unsigned or substituted proof dictate its
|
|
77
|
+
* own starting point. `proof.treeSize1` must equal it regardless: the two
|
|
78
|
+
* disagreeing means this proof does not continue from the state being
|
|
79
|
+
* folded, not a mere shape defect, so it is checked before any fold work.
|
|
80
|
+
*
|
|
81
|
+
* @throws {Error} when `proof.treeSize1 !== sizeFrom`, or when the proof
|
|
82
|
+
* supplies a right-peaks count other than
|
|
83
|
+
* {@link consistentRootsForSizes}'s `expectedRight`
|
|
84
|
+
* @throws {ConsistencyShapeError} (`@forestrie/merklelog`) when the proof
|
|
85
|
+
* does not have the shape MMR(sizeFrom) -> MMR(proof.treeSize2) implies
|
|
17
86
|
*/
|
|
18
|
-
export declare function computeCheckpointAccumulator(proof: CheckpointConsistencyProof, accumulatorFrom: Uint8Array[]): Promise<Uint8Array[]>;
|
|
87
|
+
export declare function computeCheckpointAccumulator(proof: CheckpointConsistencyProof, accumulatorFrom: Uint8Array[], sizeFrom: bigint): Promise<Uint8Array[]>;
|
|
19
88
|
/** Detached payload the checkpoint signature covers (ADR-0046): the raw
|
|
20
89
|
* concatenation of the accumulator peaks in contract order. */
|
|
21
90
|
export declare function accumulatorPayload(accumulator: Uint8Array[]): Uint8Array;
|
|
22
91
|
export type CheckpointChainLink = {
|
|
23
92
|
treeSize1: bigint;
|
|
24
93
|
treeSize2: bigint;
|
|
94
|
+
/** Signed `tree-size-2` (protected header label -65933; ADR-0066 D1 as
|
|
95
|
+
* amended). */
|
|
96
|
+
signedTreeSize2: bigint;
|
|
25
97
|
accumulator: Uint8Array[];
|
|
98
|
+
/** Always `true`: a link is recorded only after its signature verified. */
|
|
26
99
|
signatureOk: boolean;
|
|
27
100
|
};
|
|
28
101
|
export type CheckpointChainResult = {
|
|
@@ -31,7 +104,24 @@ export type CheckpointChainResult = {
|
|
|
31
104
|
accumulator: Uint8Array[];
|
|
32
105
|
} | {
|
|
33
106
|
ok: false;
|
|
34
|
-
reason: "empty_chain" | "
|
|
107
|
+
reason: "empty_chain" | "signature"
|
|
108
|
+
/**
|
|
109
|
+
* The checkpoint's ES256 signature is the malleable high-s twin (see
|
|
110
|
+
* {@link CheckpointHighSSignatureError}) — rejected before any
|
|
111
|
+
* WebCrypto verify, so it is distinct from `"signature"` (a
|
|
112
|
+
* canonical-form low-s signature that did not verify).
|
|
113
|
+
*/
|
|
114
|
+
| "signature_malleable" | "proof_malformed"
|
|
115
|
+
/**
|
|
116
|
+
* Two sizes that must be equal are not. Either a checkpoint's SIGNED
|
|
117
|
+
* `tree-size-2` disagrees with its declared consistency-proof
|
|
118
|
+
* `tree-size-2` (ADR-0066 D1 as amended, D5.5), or a link's declared
|
|
119
|
+
* `tree-size-1` disagrees with the size the fold starts from — the
|
|
120
|
+
* caller's `trustedBase.size` (0 with no `trustedBase`) for the
|
|
121
|
+
* first link, the previous link's `tree-size-2` after that.
|
|
122
|
+
* `detail` names both sizes.
|
|
123
|
+
*/
|
|
124
|
+
| "size_mismatch";
|
|
35
125
|
/** Index of the offending checkpoint. */
|
|
36
126
|
at: number;
|
|
37
127
|
detail: string;
|
|
@@ -41,20 +131,43 @@ export type CheckpointChainResult = {
|
|
|
41
131
|
* Verify a retained checkpoint chain (ascending massif order) and fold out
|
|
42
132
|
* the final authenticated accumulator.
|
|
43
133
|
*
|
|
44
|
-
* - The first link
|
|
45
|
-
*
|
|
46
|
-
* chain rooted in an
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
134
|
+
* - The first link's trusted starting size is `trustedBase?.size ?? 0n`
|
|
135
|
+
* (base 0 for a whole-log chain) with `trustedBase?.accumulator ?? []`
|
|
136
|
+
* as the fold's starting accumulator (a suffix chain rooted in an
|
|
137
|
+
* already-trusted accumulator supplies both).
|
|
138
|
+
* - A supplied `trustedBase` must describe a state an MMR can be in: its
|
|
139
|
+
* `size` a complete MMR size, and its `accumulator` holding one peak per
|
|
140
|
+
* peak of that size. `peaksBitmap` rounds an incomplete size DOWN to the
|
|
141
|
+
* largest MMR below it, so without the completeness check a size of 5
|
|
142
|
+
* folds the 4 -> N shape while every link reports a base of 5 — a node
|
|
143
|
+
* count no MMR has. Both are `proof_malformed`.
|
|
144
|
+
* - The first link's declared `tree-size-1` must equal that trusted
|
|
145
|
+
* starting size, and every subsequent link's must equal the previous
|
|
146
|
+
* link's sealed `tree-size-2`; either disagreement is `size_mismatch`.
|
|
147
|
+
* `tree-size-1` itself is never compared with a signed value (D2 is
|
|
148
|
+
* withdrawn): only this trusted-origin comparison applies. Because it is
|
|
149
|
+
* unsigned, the reason it produces carries no more meaning than the size
|
|
150
|
+
* disagreement itself (ADR-0066 D6: no pre-FOR-410 state is supported, so
|
|
151
|
+
* there is no drift condition to fall back from).
|
|
152
|
+
* - Each checkpoint's SIGNED `tree-size-2` (ADR-0066 D1 as amended) must
|
|
153
|
+
* equal its declared consistency-proof `tree-size-2`
|
|
154
|
+
* ({@link checkpointConsistencyProof}); a disagreement is
|
|
155
|
+
* `size_mismatch`.
|
|
50
156
|
* - Each link's signature is checked over its computed accumulator via
|
|
51
157
|
* the injected verifier (the caller owns trust resolution — genesis
|
|
52
|
-
* roots, caller-known keys, or the label-1000 delegation path).
|
|
158
|
+
* roots, caller-known keys, or the label-1000 delegation path). A link
|
|
159
|
+
* joins `links` only once its signature has verified, so on any failure
|
|
160
|
+
* `links` is the verified prefix and never holds an accumulator nothing
|
|
161
|
+
* attested.
|
|
53
162
|
*/
|
|
54
163
|
export declare function verifyCheckpointChain(opts: {
|
|
55
164
|
checkpoints: Uint8Array[];
|
|
56
165
|
verifySignature: (checkpointBytes: Uint8Array, detachedPayload: Uint8Array) => Promise<boolean>;
|
|
57
|
-
/** Trusted base
|
|
58
|
-
|
|
166
|
+
/** Trusted base for a suffix chain (a whole-log chain has base size 0 and
|
|
167
|
+
* an empty accumulator, which is also the default when this is absent). */
|
|
168
|
+
trustedBase?: {
|
|
169
|
+
size: bigint;
|
|
170
|
+
accumulator: Uint8Array[];
|
|
171
|
+
};
|
|
59
172
|
}): Promise<CheckpointChainResult>;
|
|
60
173
|
//# sourceMappingURL=checkpoint-chain.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint-chain.d.ts","sourceRoot":"","sources":["../src/checkpoint-chain.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"checkpoint-chain.d.ts","sourceRoot":"","sources":["../src/checkpoint-chain.ts"],"names":[],"mappings":"AAwDA;;;;qBAIqB;AACrB,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB;+EAC2E;IAC3E,eAAe,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC;IACtB,uEAAuE;IACvE,UAAU,EAAE,UAAU,EAAE,CAAC;CAC1B,CAAC;AAEF;;;;;;GAMG;AACH,qBAAa,iCAAkC,SAAQ,KAAK;gBAC9C,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,0BAA0B,CACxC,eAAe,EAAE,UAAU,GAC1B,0BAA0B,CAgC5B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,0BAA0B,EACjC,eAAe,EAAE,UAAU,EAAE,EAC7B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,EAAE,CAAC,CAoBvB;AAED;+DAC+D;AAC/D,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,UAAU,CAQxE;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB;mBACe;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,2EAA2E;IAC3E,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAAC,WAAW,EAAE,UAAU,EAAE,CAAA;CAAE,GACrE;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EACF,aAAa,GACb,WAAW;IACb;;;;;OAKG;OACD,qBAAqB,GACrB,iBAAiB;IACnB;;;;;;;;OAQG;OACD,eAAe,CAAC;IACpB,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,mBAAmB,EAAE,CAAC;CAC9B,CAAC;AAEN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,eAAe,EAAE,CACf,eAAe,EAAE,UAAU,EAC3B,eAAe,EAAE,UAAU,KACxB,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB;+EAC2E;IAC3E,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC;CAC3D,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAoIjC"}
|