mirror of
https://github.com/tornadocash/fixed-merkle-tree.git
synced 2024-11-22 09:47:15 +01:00
Update lib
This commit is contained in:
parent
df1bee33f9
commit
fb8974a0a0
36
lib/BaseTree.d.ts
vendored
36
lib/BaseTree.d.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
import { Element, HashFunction, ProofPath } from './';
|
import { Element, HashFunction, ProofPath, MultiProofPath } from './';
|
||||||
export declare class BaseTree {
|
export declare class BaseTree {
|
||||||
levels: number;
|
levels: number;
|
||||||
protected _hashFn: HashFunction<Element>;
|
protected _hashFn: HashFunction<Element>;
|
||||||
@ -37,6 +37,40 @@ export declare class BaseTree {
|
|||||||
* @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index
|
* @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index
|
||||||
*/
|
*/
|
||||||
path(index: number): ProofPath;
|
path(index: number): ProofPath;
|
||||||
|
/**
|
||||||
|
* Return the indices for the next layer in the multiPath calculation
|
||||||
|
* @param {number} indices A list of leaf indices
|
||||||
|
* @returns {number[]} the new list of indices
|
||||||
|
*/
|
||||||
|
static nextLayerMultiPathIndices(indices: number[]): number[];
|
||||||
|
/**
|
||||||
|
* Get merkle path to a list of leaves
|
||||||
|
* @param {number} indices A list of leaf indices to generate path for
|
||||||
|
* @returns {{pathElements: Element[], leafIndices: number[]}} An object containing adjacent elements and leaves indices
|
||||||
|
*/
|
||||||
|
multiPath(indices: number[]): MultiProofPath;
|
||||||
|
/**
|
||||||
|
* Verifies a merkle proof
|
||||||
|
* @param {Element} root the root of the merkle tree
|
||||||
|
* @param {number} levels the number of levels of the tree
|
||||||
|
* @param {HashFunction<Element>} hashFn hash function
|
||||||
|
* @param {Element} leaf the leaf to be verified
|
||||||
|
* @param {Element[]} pathElements adjacent path elements
|
||||||
|
* @param {number[]} pathIndices left-right indices
|
||||||
|
* @returns {Boolean} whether the proof is valid for the given root
|
||||||
|
*/
|
||||||
|
static verifyProof(root: Element, levels: number, hashFn: HashFunction<Element>, leaf: Element, pathElements: Element[], pathIndices: number[]): boolean;
|
||||||
|
/**
|
||||||
|
* Verifies a merkle multiproof
|
||||||
|
* @param {Element} root the root of the merkle tree
|
||||||
|
* @param {number} levels the number of levels of the tree
|
||||||
|
* @param {HashFunction<Element>} hashFn hash function
|
||||||
|
* @param {Element[]} leaves the list of leaves to be verified
|
||||||
|
* @param {Element[]} pathElements multiproof path elements
|
||||||
|
* @param {number[]} leafIndices multiproof leaf indices
|
||||||
|
* @returns {Boolean} whether the proof is valid for the given root
|
||||||
|
*/
|
||||||
|
static verifyMultiProof(root: Element, levels: number, hashFn: HashFunction<Element>, leaves: Element[], pathElements: Element[], leafIndices: number[]): boolean;
|
||||||
protected _buildZeros(): void;
|
protected _buildZeros(): void;
|
||||||
protected _processNodes(nodes: Element[], layerIndex: number): any[];
|
protected _processNodes(nodes: Element[], layerIndex: number): any[];
|
||||||
protected _processUpdate(index: number): void;
|
protected _processUpdate(index: number): void;
|
||||||
|
120
lib/BaseTree.js
120
lib/BaseTree.js
@ -117,6 +117,126 @@ class BaseTree {
|
|||||||
pathRoot: this.root,
|
pathRoot: this.root,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Return the indices for the next layer in the multiPath calculation
|
||||||
|
* @param {number} indices A list of leaf indices
|
||||||
|
* @returns {number[]} the new list of indices
|
||||||
|
*/
|
||||||
|
static nextLayerMultiPathIndices(indices) {
|
||||||
|
const nextIndices = new Set();
|
||||||
|
for (let i = 0; i < indices.length; i++) {
|
||||||
|
nextIndices.add(indices[i] >> 1);
|
||||||
|
}
|
||||||
|
return [...nextIndices];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get merkle path to a list of leaves
|
||||||
|
* @param {number} indices A list of leaf indices to generate path for
|
||||||
|
* @returns {{pathElements: Element[], leafIndices: number[]}} An object containing adjacent elements and leaves indices
|
||||||
|
*/
|
||||||
|
multiPath(indices) {
|
||||||
|
let pathElements = [];
|
||||||
|
let layerIndices = indices;
|
||||||
|
for (let level = 0; level < this.levels; level++) {
|
||||||
|
// find whether there is a neighbor idx that is not in layerIndices
|
||||||
|
const proofElements = layerIndices.reduce((elements, idx) => {
|
||||||
|
const leafIndex = idx ^ 1;
|
||||||
|
if (!layerIndices.includes(leafIndex)) {
|
||||||
|
if (leafIndex < this._layers[level].length) {
|
||||||
|
elements.push(this._layers[level][leafIndex]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
elements.push(this._zeros[level]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return elements;
|
||||||
|
}, []);
|
||||||
|
pathElements = pathElements.concat(proofElements);
|
||||||
|
layerIndices = BaseTree.nextLayerMultiPathIndices(layerIndices);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
pathElements,
|
||||||
|
leafIndices: indices,
|
||||||
|
pathRoot: this.root,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Verifies a merkle proof
|
||||||
|
* @param {Element} root the root of the merkle tree
|
||||||
|
* @param {number} levels the number of levels of the tree
|
||||||
|
* @param {HashFunction<Element>} hashFn hash function
|
||||||
|
* @param {Element} leaf the leaf to be verified
|
||||||
|
* @param {Element[]} pathElements adjacent path elements
|
||||||
|
* @param {number[]} pathIndices left-right indices
|
||||||
|
* @returns {Boolean} whether the proof is valid for the given root
|
||||||
|
*/
|
||||||
|
static verifyProof(root, levels, hashFn, leaf, pathElements, pathIndices) {
|
||||||
|
const layerProofs = [];
|
||||||
|
for (let level = 0; level < levels; level++) {
|
||||||
|
let elem = level == 0 ? leaf : layerProofs[level - 1];
|
||||||
|
if (pathIndices[level] == 0) {
|
||||||
|
layerProofs[level] = hashFn(elem, pathElements[level]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
layerProofs[level] = hashFn(pathElements[level], elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return root === layerProofs[levels - 1];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Verifies a merkle multiproof
|
||||||
|
* @param {Element} root the root of the merkle tree
|
||||||
|
* @param {number} levels the number of levels of the tree
|
||||||
|
* @param {HashFunction<Element>} hashFn hash function
|
||||||
|
* @param {Element[]} leaves the list of leaves to be verified
|
||||||
|
* @param {Element[]} pathElements multiproof path elements
|
||||||
|
* @param {number[]} leafIndices multiproof leaf indices
|
||||||
|
* @returns {Boolean} whether the proof is valid for the given root
|
||||||
|
*/
|
||||||
|
static verifyMultiProof(root, levels, hashFn, leaves, pathElements, leafIndices) {
|
||||||
|
let layerElements = leaves;
|
||||||
|
let layerIndices = leafIndices;
|
||||||
|
const proofElements = pathElements;
|
||||||
|
const layerProofs = [];
|
||||||
|
for (let level = 0; level < levels; level++) {
|
||||||
|
for (let i = 0; i < layerIndices.length; i++) {
|
||||||
|
let layerHash;
|
||||||
|
const elIndex = layerIndices[i];
|
||||||
|
const leafIndex = elIndex ^ 1;
|
||||||
|
if (layerIndices.includes(leafIndex)) {
|
||||||
|
if (elIndex % 2 === 0) {
|
||||||
|
layerHash = hashFn(layerElements[0], layerElements[1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
layerHash = hashFn(layerElements[1], layerElements[0]);
|
||||||
|
}
|
||||||
|
layerElements.splice(0, 2); // remove 1st and 2nd element
|
||||||
|
i++; // skip next idx
|
||||||
|
layerProofs.push(layerHash);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (elIndex % 2 === 0) {
|
||||||
|
layerHash = hashFn(layerElements[0], proofElements[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
layerHash = hashFn(proofElements[0], layerElements[0]);
|
||||||
|
}
|
||||||
|
layerElements.shift(); // remove 1st element
|
||||||
|
layerProofs.push(layerHash);
|
||||||
|
if (proofElements.shift() === undefined) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layerIndices = BaseTree.nextLayerMultiPathIndices(layerIndices);
|
||||||
|
layerElements = layerProofs;
|
||||||
|
if (proofElements.length == 0 && layerElements.length == 2) {
|
||||||
|
layerProofs[0] = hashFn(layerProofs[0], layerProofs[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return root === layerProofs[0];
|
||||||
|
}
|
||||||
_buildZeros() {
|
_buildZeros() {
|
||||||
this._zeros = [this.zeroElement];
|
this._zeros = [this.zeroElement];
|
||||||
for (let i = 1; i <= this.levels; i++) {
|
for (let i = 1; i <= this.levels; i++) {
|
||||||
|
3
lib/FixedMerkleTree.d.ts
vendored
3
lib/FixedMerkleTree.d.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
import { Element, HashFunction, MerkleTreeOptions, ProofPath, SerializedTreeState, TreeEdge, TreeSlice } from './';
|
import { Element, HashFunction, MerkleTreeOptions, ProofPath, MultiProofPath, SerializedTreeState, TreeEdge, TreeSlice } from './';
|
||||||
import { BaseTree } from './BaseTree';
|
import { BaseTree } from './BaseTree';
|
||||||
export default class MerkleTree extends BaseTree {
|
export default class MerkleTree extends BaseTree {
|
||||||
constructor(levels: number, elements?: Element[], { hashFunction, zeroElement, }?: MerkleTreeOptions);
|
constructor(levels: number, elements?: Element[], { hashFunction, zeroElement, }?: MerkleTreeOptions);
|
||||||
@ -10,6 +10,7 @@ export default class MerkleTree extends BaseTree {
|
|||||||
bulkInsert(elements: Element[]): void;
|
bulkInsert(elements: Element[]): void;
|
||||||
indexOf(element: Element, comparator?: <T>(arg0: T, arg1: T) => boolean): number;
|
indexOf(element: Element, comparator?: <T>(arg0: T, arg1: T) => boolean): number;
|
||||||
proof(element: Element): ProofPath;
|
proof(element: Element): ProofPath;
|
||||||
|
multiProof(elements: Element[]): MultiProofPath;
|
||||||
getTreeEdge(edgeIndex: number): TreeEdge;
|
getTreeEdge(edgeIndex: number): TreeEdge;
|
||||||
/**
|
/**
|
||||||
* 🪓
|
* 🪓
|
||||||
|
@ -59,6 +59,13 @@ class MerkleTree extends BaseTree_1.BaseTree {
|
|||||||
const index = this.indexOf(element);
|
const index = this.indexOf(element);
|
||||||
return this.path(index);
|
return this.path(index);
|
||||||
}
|
}
|
||||||
|
multiProof(elements) {
|
||||||
|
const indexes = [];
|
||||||
|
for (let i = 0; i < elements.length; i++) {
|
||||||
|
indexes.push(this.indexOf(elements[i]));
|
||||||
|
}
|
||||||
|
return this.multiPath(indexes);
|
||||||
|
}
|
||||||
getTreeEdge(edgeIndex) {
|
getTreeEdge(edgeIndex) {
|
||||||
const edgeElement = this._layers[0][edgeIndex];
|
const edgeElement = this._layers[0][edgeIndex];
|
||||||
if (edgeElement === undefined) {
|
if (edgeElement === undefined) {
|
||||||
|
5
lib/index.d.ts
vendored
5
lib/index.d.ts
vendored
@ -29,6 +29,11 @@ export declare type ProofPath = {
|
|||||||
pathPositions: number[];
|
pathPositions: number[];
|
||||||
pathRoot: Element;
|
pathRoot: Element;
|
||||||
};
|
};
|
||||||
|
export declare type MultiProofPath = {
|
||||||
|
pathElements: Element[];
|
||||||
|
leafIndices: number[];
|
||||||
|
pathRoot: Element;
|
||||||
|
};
|
||||||
export declare type TreeEdge = {
|
export declare type TreeEdge = {
|
||||||
edgeElement: Element;
|
edgeElement: Element;
|
||||||
edgePath: ProofPath;
|
edgePath: ProofPath;
|
||||||
|
Loading…
Reference in New Issue
Block a user