@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 +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/mmr/proof.d.ts +38 -0
- package/dist/mmr/proof.d.ts.map +1 -1
- package/dist/mmr/proof.js +83 -0
- package/package.json +1 -1
- package/src/index.ts +3 -1
- package/src/mmr/proof.ts +109 -0
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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";
|
package/dist/mmr/proof.d.ts
CHANGED
|
@@ -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
|
package/dist/mmr/proof.d.ts.map
CHANGED
|
@@ -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
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
|