mirror of
https://github.com/tornadocash/fixed-merkle-tree.git
synced 2024-12-28 07:37:57 +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 {
|
||||
levels: number;
|
||||
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
|
||||
*/
|
||||
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 _processNodes(nodes: Element[], layerIndex: number): any[];
|
||||
protected _processUpdate(index: number): void;
|
||||
|
120
lib/BaseTree.js
120
lib/BaseTree.js
@ -117,6 +117,126 @@ class BaseTree {
|
||||
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() {
|
||||
this._zeros = [this.zeroElement];
|
||||
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';
|
||||
export default class MerkleTree extends BaseTree {
|
||||
constructor(levels: number, elements?: Element[], { hashFunction, zeroElement, }?: MerkleTreeOptions);
|
||||
@ -10,6 +10,7 @@ export default class MerkleTree extends BaseTree {
|
||||
bulkInsert(elements: Element[]): void;
|
||||
indexOf(element: Element, comparator?: <T>(arg0: T, arg1: T) => boolean): number;
|
||||
proof(element: Element): ProofPath;
|
||||
multiProof(elements: Element[]): MultiProofPath;
|
||||
getTreeEdge(edgeIndex: number): TreeEdge;
|
||||
/**
|
||||
* 🪓
|
||||
|
@ -59,6 +59,13 @@ class MerkleTree extends BaseTree_1.BaseTree {
|
||||
const index = this.indexOf(element);
|
||||
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) {
|
||||
const edgeElement = this._layers[0][edgeIndex];
|
||||
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[];
|
||||
pathRoot: Element;
|
||||
};
|
||||
export declare type MultiProofPath = {
|
||||
pathElements: Element[];
|
||||
leafIndices: number[];
|
||||
pathRoot: Element;
|
||||
};
|
||||
export declare type TreeEdge = {
|
||||
edgeElement: Element;
|
||||
edgePath: ProofPath;
|
||||
|
Loading…
Reference in New Issue
Block a user