@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.
@@ -1,4 +1,8 @@
1
- /** SCITT transparent statement unprotected receipt label (grants.md §3.2). */
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":"AAWA,8EAA8E;AAC9E,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC,wBAAgB,iDAAiD,CAC/D,cAAc,EAAE,UAAU,EAC1B,gBAAgB,EAAE,UAAU,EAC5B,cAAc,EAAE,UAAU,GACzB,UAAU,CAWZ"}
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
- /** SCITT transparent statement unprotected receipt label (grants.md §3.2). */
12
- export const HEADER_RECEIPT = 396;
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
- /** Sealed tree size (tree-size-2 of the embedded consistency proof). */
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;AAMH,OAAO,EAIL,mBAAmB,EAEnB,KAAK,eAAe,EAErB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,oBAAoB,CAAC;AAQ5B;;;;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,wEAAwE;IACxE,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"}
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
- const VDS_COSE_RECEIPT_PROOFS_TAG = 396;
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(SEAL_PEAK_RECEIPTS_LABEL);
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(VDS_COSE_RECEIPT_PROOFS_TAG, verifiableProofs);
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 of the consistency
159
- * proof (`bstr .cbor [tree-size-1, tree-size-2, paths, right-peaks]`) under
160
- * the verifiable-proofs unprotected header (label 396, key -2).
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
- const vdpRaw = unprotected.get(VDS_COSE_RECEIPT_PROOFS_TAG);
164
- if (vdpRaw === undefined || vdpRaw === null)
171
+ function sealedSizeFromCheckpoint(coseSign1, unprotected) {
172
+ let declared;
173
+ try {
174
+ declared = decodeConsistencyProofFromUnprotected(unprotected);
175
+ }
176
+ catch {
165
177
  return null;
166
- const vdp = toHeaderMap(vdpRaw);
167
- const proofBstr = vdp.get(VDP_CONSISTENCY_PROOF_KEY);
168
- if (!(proofBstr instanceof Uint8Array))
178
+ }
179
+ if (declared === null)
169
180
  return null;
170
- const proof = decodeCborDeterministic(proofBstr);
171
- if (!Array.isArray(proof) || proof.length < 2)
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
- /** Decode the embedded consistency proof (`vdp` 396 key -2). */
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 trusted accumulator at `proof.treeSize1`,
14
- * produce the `treeSize2` accumulator (draft: `consistent_roots` output
15
- * plus the supplied right-peaks). Structural sanity: the result must have
16
- * exactly the peak count of a size-`treeSize2` MMR.
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" | "legacy_chain_break" | "signature" | "proof_malformed";
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 must be boundary-based from 0 (a whole-log chain), or
45
- * the caller supplies `accumulatorFrom` matching its base (a suffix
46
- * chain rooted in an already-trusted accumulator).
47
- * - Every subsequent link's base must equal the previous link's sealed
48
- * size — a mismatch is the legacy (pre-FOR-410) drift signature and is
49
- * permanent for that log (`legacy_chain_break`).
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 accumulator for a suffix chain (absent: base must be 0). */
58
- accumulatorFrom?: Uint8Array[];
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":"AA6BA,iEAAiE;AACjE,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC;IACtB,uEAAuE;IACvE,UAAU,EAAE,UAAU,EAAE,CAAC;CAC1B,CAAC;AA2BF,gEAAgE;AAChE,wBAAgB,0BAA0B,CACxC,eAAe,EAAE,UAAU,GAC1B,0BAA0B,CA6C5B;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,0BAA0B,EACjC,eAAe,EAAE,UAAU,EAAE,GAC5B,OAAO,CAAC,UAAU,EAAE,CAAC,CAmBvB;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,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,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,oBAAoB,GACpB,WAAW,GACX,iBAAiB,CAAC;IACtB,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,mBAAmB,EAAE,CAAC;CAC9B,CAAC;AAEN;;;;;;;;;;;;;GAaG;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,4EAA4E;IAC5E,eAAe,CAAC,EAAE,UAAU,EAAE,CAAC;CAChC,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAiGjC"}
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"}