@forestrie/merklelog 0.2.1 → 0.3.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/index.d.ts CHANGED
@@ -22,6 +22,6 @@ export { bagPeaks, calculateRoot, verifyInclusion, verifyConsistency, consistent
22
22
  export { createSyncHasher } from "./mmr/algorithms-sync.js";
23
23
  export type { Proof, Peak } from "./mmr/types.js";
24
24
  export type { Hasher } from "./mmr/types.js";
25
- export { inclusionProof, peakMMRIndexes, peaksBitmap, peakIndexForLeafProof, indexHeight, firstMMRSize, massifIndexFromMMRIndex, peakStackMap, } from "./mmr/proof.js";
26
- export type { NodeGetter } from "./mmr/proof.js";
25
+ export { inclusionProof, inclusionProofPath, inclusionProofLocalExtend, peakMMRIndexes, peaksBitmap, peakIndexForLeafProof, indexHeight, firstMMRSize, massifIndexFromMMRIndex, peakStackMap, } from "./mmr/proof.js";
26
+ export type { NodeGetter, ConsistencyProofLocal } from "./mmr/proof.js";
27
27
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EACV,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,SAAS,GACV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EACL,SAAS,EACT,KAAK,EACL,KAAK,EACL,OAAO,EACP,wBAAwB,EACxB,cAAc,EACd,YAAY,EACZ,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,6BAA6B,EAC7B,6BAA6B,EAC7B,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAGvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChF,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG3E,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EACL,WAAW,EACX,MAAM,EACN,qBAAqB,EACrB,SAAS,EACT,WAAW,EACX,sBAAsB,EACtB,SAAS,EACT,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,QAAQ,EACR,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAClD,YAAY,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,EACL,cAAc,EACd,cAAc,EACd,WAAW,EACX,qBAAqB,EACrB,WAAW,EACX,YAAY,EACZ,uBAAuB,EACvB,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EACV,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,SAAS,GACV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EACL,SAAS,EACT,KAAK,EACL,KAAK,EACL,OAAO,EACP,wBAAwB,EACxB,cAAc,EACd,YAAY,EACZ,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,6BAA6B,EAC7B,6BAA6B,EAC7B,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAGvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChF,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG3E,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EACL,WAAW,EACX,MAAM,EACN,qBAAqB,EACrB,SAAS,EACT,WAAW,EACX,sBAAsB,EACtB,SAAS,EACT,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,QAAQ,EACR,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAClD,YAAY,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,yBAAyB,EACzB,cAAc,EACd,WAAW,EACX,qBAAqB,EACrB,WAAW,EACX,YAAY,EACZ,uBAAuB,EACvB,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -23,4 +23,4 @@ export { heightIndex, height, mmrIndexFromLeafIndex, leafIndex, mmrPosition, mmr
23
23
  export { bagPeaks, calculateRoot, verifyInclusion, verifyConsistency, consistentRoots, indexConsistencyProof, } from "./mmr/algorithms.js";
24
24
  export { createSyncHasher } from "./mmr/algorithms-sync.js";
25
25
  // MMR proof building (pure; store-agnostic) — plan-2607-15 §4 (go: mmr/proof.go, peaks.go)
26
- export { inclusionProof, peakMMRIndexes, peaksBitmap, peakIndexForLeafProof, indexHeight, firstMMRSize, massifIndexFromMMRIndex, peakStackMap, } from "./mmr/proof.js";
26
+ export { inclusionProof, inclusionProofPath, inclusionProofLocalExtend, peakMMRIndexes, peaksBitmap, peakIndexForLeafProof, indexHeight, firstMMRSize, massifIndexFromMMRIndex, peakStackMap, } from "./mmr/proof.js";
@@ -24,6 +24,44 @@ export declare function indexHeight(i: bigint): number;
24
24
  * @throws if `i > mmrLastIndex`.
25
25
  */
26
26
  export declare function inclusionProof(get: NodeGetter, mmrLastIndex: bigint, i: bigint): Uint8Array[];
27
+ /**
28
+ * The sibling *indices* of an inclusion proof for the node at MMR index `i` in
29
+ * the tree ending at `mmrLastIndex` — the index-only counterpart of
30
+ * {@link inclusionProof} (go-merklelog `mmr/proof.go` InclusionProofPath). The
31
+ * values at these indices, in order, are the proof. Store-free: pure position
32
+ * arithmetic, so a caller can assemble a proof's node values from any source
33
+ * (a receipt path, consistency-proof paths, tiles).
34
+ */
35
+ export declare function inclusionProofPath(mmrLastIndex: bigint, i: bigint): bigint[];
36
+ /**
37
+ * An inclusion proof that has been extended from MMR size A to size B: the size-B
38
+ * proof is an *extension* of the size-A proof, sharing its first `heightA`
39
+ * elements. (go-merklelog `mmr/proofrefresh.go` ConsistencyProofLocal.)
40
+ */
41
+ export type ConsistencyProofLocal = {
42
+ /** The node (leaf) MMR index being proven. */
43
+ logIndex: bigint;
44
+ /** Full inclusion path at size B; `path[0..heightA]` is the size-A proof. */
45
+ path: Uint8Array[];
46
+ sizeA: bigint;
47
+ /** Peak (root) index covering `logIndex` at size A. */
48
+ peakIndexA: bigint;
49
+ /** Length of the shared prefix — the size-A proof; the rest extends it. */
50
+ heightA: number;
51
+ sizeB: bigint;
52
+ /** Peak (root) index covering `logIndex` at size B. */
53
+ peakIndexB: bigint;
54
+ };
55
+ /**
56
+ * Extend the inclusion proof for node `i` from MMR size A to size B, reading
57
+ * sibling values from `get`. The result's `path` proves `i` at size B and shares
58
+ * its first `heightA` elements with the size-A proof — so a stale receipt's
59
+ * path (leaf → its old peak) is exactly `path[0..heightA]`, and the remainder is
60
+ * the tile-free extension. Direct port of go-merklelog `InclusionProofLocalExtend`.
61
+ *
62
+ * @throws if `mmrSizeB <= mmrSizeA`.
63
+ */
64
+ export declare function inclusionProofLocalExtend(get: NodeGetter, mmrSizeA: bigint, mmrSizeB: bigint, i: bigint): ConsistencyProofLocal;
27
65
  /**
28
66
  * Peaks bitmap for an MMR size: the numeric value equals the leaf count of the
29
67
  * largest valid MMR with size <= `mmrSize`; each set bit marks a perfect
@@ -1 +1 @@
1
- {"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../../src/mmr/proof.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,uEAAuE;AACvE,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,UAAU,CAAC;AA2CnD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,UAAU,EACf,YAAY,EAAE,MAAM,EACpB,CAAC,EAAE,MAAM,GACR,UAAU,EAAE,CAyBd;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAcnD;AAaD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,MAAM,CAIR;AAQD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAczD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUrD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,CAAC,EAAE,MAAM,GACR,MAAM,CAKR;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAWrB"}
1
+ {"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../../src/mmr/proof.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,uEAAuE;AACvE,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,UAAU,CAAC;AA2CnD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,UAAU,EACf,YAAY,EAAE,MAAM,EACpB,CAAC,EAAE,MAAM,GACR,UAAU,EAAE,CAyBd;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB5E;AAED;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,CAAC,EAAE,MAAM,GACR,qBAAqB,CA4CvB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAcnD;AAaD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,MAAM,CAIR;AAQD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAczD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUrD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,CAAC,EAAE,MAAM,GACR,MAAM,CAKR;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAWrB"}
package/dist/mmr/proof.js CHANGED
@@ -89,6 +89,89 @@ export function inclusionProof(get, mmrLastIndex, i) {
89
89
  g += 1n;
90
90
  }
91
91
  }
92
+ /**
93
+ * The sibling *indices* of an inclusion proof for the node at MMR index `i` in
94
+ * the tree ending at `mmrLastIndex` — the index-only counterpart of
95
+ * {@link inclusionProof} (go-merklelog `mmr/proof.go` InclusionProofPath). The
96
+ * values at these indices, in order, are the proof. Store-free: pure position
97
+ * arithmetic, so a caller can assemble a proof's node values from any source
98
+ * (a receipt path, consistency-proof paths, tiles).
99
+ */
100
+ export function inclusionProofPath(mmrLastIndex, i) {
101
+ let g = BigInt(indexHeight(i));
102
+ const proof = [];
103
+ for (;;) {
104
+ const siblingOffset = 2n << g;
105
+ let iSibling;
106
+ if (BigInt(indexHeight(i + 1n)) > g) {
107
+ iSibling = i - siblingOffset + 1n;
108
+ i += 1n;
109
+ }
110
+ else {
111
+ iSibling = i + siblingOffset - 1n;
112
+ i += siblingOffset;
113
+ }
114
+ if (iSibling > mmrLastIndex) {
115
+ return proof;
116
+ }
117
+ proof.push(iSibling);
118
+ g += 1n;
119
+ }
120
+ }
121
+ /**
122
+ * Extend the inclusion proof for node `i` from MMR size A to size B, reading
123
+ * sibling values from `get`. The result's `path` proves `i` at size B and shares
124
+ * its first `heightA` elements with the size-A proof — so a stale receipt's
125
+ * path (leaf → its old peak) is exactly `path[0..heightA]`, and the remainder is
126
+ * the tile-free extension. Direct port of go-merklelog `InclusionProofLocalExtend`.
127
+ *
128
+ * @throws if `mmrSizeB <= mmrSizeA`.
129
+ */
130
+ export function inclusionProofLocalExtend(get, mmrSizeA, mmrSizeB, i) {
131
+ if (mmrSizeB <= mmrSizeA) {
132
+ throw new Error(`mmrSizeB (${mmrSizeB}) must be greater than mmrSizeA (${mmrSizeA})`);
133
+ }
134
+ const logIndex = i;
135
+ const path = [];
136
+ let height = 0n;
137
+ let prevComplete = false;
138
+ let peakIndexA = 0n;
139
+ let heightA = 0;
140
+ while (i < mmrSizeB) {
141
+ const siblingOffset = (2n << height) - 1n; // go-merklelog SiblingOffset
142
+ let iSibling;
143
+ let delta;
144
+ if (BigInt(indexHeight(i + 1n)) > BigInt(indexHeight(i))) {
145
+ iSibling = i - siblingOffset;
146
+ delta = 1n;
147
+ }
148
+ else {
149
+ iSibling = i + siblingOffset;
150
+ delta = 2n << height;
151
+ }
152
+ // The first sibling that lies outside MMR(A) marks the end of the size-A
153
+ // proof: `i` is the size-A covering peak and the prefix so far is its proof.
154
+ if (iSibling >= mmrSizeA && !prevComplete) {
155
+ peakIndexA = i;
156
+ heightA = path.length;
157
+ prevComplete = true;
158
+ }
159
+ if (iSibling >= mmrSizeB)
160
+ break;
161
+ path.push(get(iSibling));
162
+ i += delta;
163
+ height += 1n;
164
+ }
165
+ return {
166
+ logIndex,
167
+ path,
168
+ sizeA: mmrSizeA,
169
+ peakIndexA,
170
+ heightA,
171
+ sizeB: mmrSizeB,
172
+ peakIndexB: i,
173
+ };
174
+ }
92
175
  /**
93
176
  * Peaks bitmap for an MMR size: the numeric value equals the leaf count of the
94
177
  * largest valid MMR with size <= `mmrSize`; each set bit marks a perfect
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forestrie/merklelog",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "MMR (merkle mountain range) proofs and massif storage format for Forestrie transparency logs",
package/src/index.ts CHANGED
@@ -81,6 +81,8 @@ export type { Hasher } from "./mmr/types.js";
81
81
  // MMR proof building (pure; store-agnostic) — plan-2607-15 §4 (go: mmr/proof.go, peaks.go)
82
82
  export {
83
83
  inclusionProof,
84
+ inclusionProofPath,
85
+ inclusionProofLocalExtend,
84
86
  peakMMRIndexes,
85
87
  peaksBitmap,
86
88
  peakIndexForLeafProof,
@@ -89,4 +91,4 @@ export {
89
91
  massifIndexFromMMRIndex,
90
92
  peakStackMap,
91
93
  } from "./mmr/proof.js";
92
- export type { NodeGetter } from "./mmr/proof.js";
94
+ export type { NodeGetter, ConsistencyProofLocal } from "./mmr/proof.js";
package/src/mmr/proof.ts CHANGED
@@ -100,6 +100,115 @@ export function inclusionProof(
100
100
  }
101
101
  }
102
102
 
103
+ /**
104
+ * The sibling *indices* of an inclusion proof for the node at MMR index `i` in
105
+ * the tree ending at `mmrLastIndex` — the index-only counterpart of
106
+ * {@link inclusionProof} (go-merklelog `mmr/proof.go` InclusionProofPath). The
107
+ * values at these indices, in order, are the proof. Store-free: pure position
108
+ * arithmetic, so a caller can assemble a proof's node values from any source
109
+ * (a receipt path, consistency-proof paths, tiles).
110
+ */
111
+ export function inclusionProofPath(mmrLastIndex: bigint, i: bigint): bigint[] {
112
+ let g = BigInt(indexHeight(i));
113
+ const proof: bigint[] = [];
114
+ for (;;) {
115
+ const siblingOffset = 2n << g;
116
+ let iSibling: bigint;
117
+ if (BigInt(indexHeight(i + 1n)) > g) {
118
+ iSibling = i - siblingOffset + 1n;
119
+ i += 1n;
120
+ } else {
121
+ iSibling = i + siblingOffset - 1n;
122
+ i += siblingOffset;
123
+ }
124
+ if (iSibling > mmrLastIndex) {
125
+ return proof;
126
+ }
127
+ proof.push(iSibling);
128
+ g += 1n;
129
+ }
130
+ }
131
+
132
+ /**
133
+ * An inclusion proof that has been extended from MMR size A to size B: the size-B
134
+ * proof is an *extension* of the size-A proof, sharing its first `heightA`
135
+ * elements. (go-merklelog `mmr/proofrefresh.go` ConsistencyProofLocal.)
136
+ */
137
+ export type ConsistencyProofLocal = {
138
+ /** The node (leaf) MMR index being proven. */
139
+ logIndex: bigint;
140
+ /** Full inclusion path at size B; `path[0..heightA]` is the size-A proof. */
141
+ path: Uint8Array[];
142
+ sizeA: bigint;
143
+ /** Peak (root) index covering `logIndex` at size A. */
144
+ peakIndexA: bigint;
145
+ /** Length of the shared prefix — the size-A proof; the rest extends it. */
146
+ heightA: number;
147
+ sizeB: bigint;
148
+ /** Peak (root) index covering `logIndex` at size B. */
149
+ peakIndexB: bigint;
150
+ };
151
+
152
+ /**
153
+ * Extend the inclusion proof for node `i` from MMR size A to size B, reading
154
+ * sibling values from `get`. The result's `path` proves `i` at size B and shares
155
+ * its first `heightA` elements with the size-A proof — so a stale receipt's
156
+ * path (leaf → its old peak) is exactly `path[0..heightA]`, and the remainder is
157
+ * the tile-free extension. Direct port of go-merklelog `InclusionProofLocalExtend`.
158
+ *
159
+ * @throws if `mmrSizeB <= mmrSizeA`.
160
+ */
161
+ export function inclusionProofLocalExtend(
162
+ get: NodeGetter,
163
+ mmrSizeA: bigint,
164
+ mmrSizeB: bigint,
165
+ i: bigint,
166
+ ): ConsistencyProofLocal {
167
+ if (mmrSizeB <= mmrSizeA) {
168
+ throw new Error(
169
+ `mmrSizeB (${mmrSizeB}) must be greater than mmrSizeA (${mmrSizeA})`,
170
+ );
171
+ }
172
+ const logIndex = i;
173
+ const path: Uint8Array[] = [];
174
+ let height = 0n;
175
+ let prevComplete = false;
176
+ let peakIndexA = 0n;
177
+ let heightA = 0;
178
+ while (i < mmrSizeB) {
179
+ const siblingOffset = (2n << height) - 1n; // go-merklelog SiblingOffset
180
+ let iSibling: bigint;
181
+ let delta: bigint;
182
+ if (BigInt(indexHeight(i + 1n)) > BigInt(indexHeight(i))) {
183
+ iSibling = i - siblingOffset;
184
+ delta = 1n;
185
+ } else {
186
+ iSibling = i + siblingOffset;
187
+ delta = 2n << height;
188
+ }
189
+ // The first sibling that lies outside MMR(A) marks the end of the size-A
190
+ // proof: `i` is the size-A covering peak and the prefix so far is its proof.
191
+ if (iSibling >= mmrSizeA && !prevComplete) {
192
+ peakIndexA = i;
193
+ heightA = path.length;
194
+ prevComplete = true;
195
+ }
196
+ if (iSibling >= mmrSizeB) break;
197
+ path.push(get(iSibling));
198
+ i += delta;
199
+ height += 1n;
200
+ }
201
+ return {
202
+ logIndex,
203
+ path,
204
+ sizeA: mmrSizeA,
205
+ peakIndexA,
206
+ heightA,
207
+ sizeB: mmrSizeB,
208
+ peakIndexB: i,
209
+ };
210
+ }
211
+
103
212
  /**
104
213
  * Peaks bitmap for an MMR size: the numeric value equals the leaf count of the
105
214
  * largest valid MMR with size <= `mmrSize`; each set bit marks a perfect