mirror of
https://github.com/tornadocash/fixed-merkle-tree.git
synced 2024-11-22 01:37:09 +01:00
init partial tree
This commit is contained in:
parent
5f036748a9
commit
e6a1ce979c
12
src/index.ts
12
src/index.ts
@ -13,7 +13,7 @@ export default class MerkleTree {
|
|||||||
|
|
||||||
levels: number
|
levels: number
|
||||||
capacity: number
|
capacity: number
|
||||||
private _hash: HashFunction
|
private _hashFn: HashFunction
|
||||||
private zeroElement: Element
|
private zeroElement: Element
|
||||||
private _zeros: Element[]
|
private _zeros: Element[]
|
||||||
private _layers: Array<Element[]>
|
private _layers: Array<Element[]>
|
||||||
@ -27,12 +27,12 @@ export default class MerkleTree {
|
|||||||
if (elements.length > this.capacity) {
|
if (elements.length > this.capacity) {
|
||||||
throw new Error('Tree is full')
|
throw new Error('Tree is full')
|
||||||
}
|
}
|
||||||
this._hash = hashFunction
|
this._hashFn = hashFunction
|
||||||
this.zeroElement = zeroElement
|
this.zeroElement = zeroElement
|
||||||
this._zeros = []
|
this._zeros = []
|
||||||
this._zeros[0] = zeroElement
|
this._zeros[0] = zeroElement
|
||||||
for (let i = 1; i <= levels; i++) {
|
for (let i = 1; i <= levels; i++) {
|
||||||
this._zeros[i] = this._hash(this._zeros[i - 1], this._zeros[i - 1])
|
this._zeros[i] = this._hashFn(this._zeros[i - 1], this._zeros[i - 1])
|
||||||
}
|
}
|
||||||
this._layers = []
|
this._layers = []
|
||||||
this._layers[0] = elements.slice()
|
this._layers[0] = elements.slice()
|
||||||
@ -43,7 +43,7 @@ export default class MerkleTree {
|
|||||||
for (let level = 1; level <= this.levels; level++) {
|
for (let level = 1; level <= this.levels; level++) {
|
||||||
this._layers[level] = []
|
this._layers[level] = []
|
||||||
for (let i = 0; i < Math.ceil(this._layers[level - 1].length / 2); i++) {
|
for (let i = 0; i < Math.ceil(this._layers[level - 1].length / 2); i++) {
|
||||||
this._layers[level][i] = this._hash(
|
this._layers[level][i] = this._hashFn(
|
||||||
this._layers[level - 1][i * 2],
|
this._layers[level - 1][i * 2],
|
||||||
i * 2 + 1 < this._layers[level - 1].length
|
i * 2 + 1 < this._layers[level - 1].length
|
||||||
? this._layers[level - 1][i * 2 + 1]
|
? this._layers[level - 1][i * 2 + 1]
|
||||||
@ -93,7 +93,7 @@ export default class MerkleTree {
|
|||||||
while (index % 2 === 1) {
|
while (index % 2 === 1) {
|
||||||
level++
|
level++
|
||||||
index >>= 1
|
index >>= 1
|
||||||
this._layers[level][index] = this._hash(
|
this._layers[level][index] = this._hashFn(
|
||||||
this._layers[level - 1][index * 2],
|
this._layers[level - 1][index * 2],
|
||||||
this._layers[level - 1][index * 2 + 1],
|
this._layers[level - 1][index * 2 + 1],
|
||||||
)
|
)
|
||||||
@ -114,7 +114,7 @@ export default class MerkleTree {
|
|||||||
this._layers[0][index] = element
|
this._layers[0][index] = element
|
||||||
for (let level = 1; level <= this.levels; level++) {
|
for (let level = 1; level <= this.levels; level++) {
|
||||||
index >>= 1
|
index >>= 1
|
||||||
this._layers[level][index] = this._hash(
|
this._layers[level][index] = this._hashFn(
|
||||||
this._layers[level - 1][index * 2],
|
this._layers[level - 1][index * 2],
|
||||||
index * 2 + 1 < this._layers[level - 1].length
|
index * 2 + 1 < this._layers[level - 1].length
|
||||||
? this._layers[level - 1][index * 2 + 1]
|
? this._layers[level - 1][index * 2 + 1]
|
||||||
|
52
src/partialMerkleTree.ts
Normal file
52
src/partialMerkleTree.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { Element, HashFunction, ProofPath } from './index'
|
||||||
|
|
||||||
|
type LeafWithIndex = { index: number, data: Element }
|
||||||
|
|
||||||
|
export class PartialMerkleTree {
|
||||||
|
levels: number
|
||||||
|
private _hash: HashFunction
|
||||||
|
private zeroElement: Element
|
||||||
|
private _zeros: Element[]
|
||||||
|
private _layers: Array<Element[]>
|
||||||
|
private _leaves: Element[]
|
||||||
|
private _leavesAfterEdge: Element[]
|
||||||
|
private _edgeLeaf: LeafWithIndex
|
||||||
|
private _root: string
|
||||||
|
private _hashFn: HashFunction
|
||||||
|
private _edgeLeafProof: ProofPath
|
||||||
|
|
||||||
|
constructor(edgeLeafProof: ProofPath, edgeLeaf: LeafWithIndex, leaves: Element[], root: string, hashFn: HashFunction) {
|
||||||
|
this._edgeLeafProof = edgeLeafProof
|
||||||
|
this._edgeLeaf = edgeLeaf
|
||||||
|
this._leavesAfterEdge = leaves
|
||||||
|
this._root = root
|
||||||
|
this._hashFn = hashFn
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get capacity() {
|
||||||
|
return this.levels ** 2
|
||||||
|
}
|
||||||
|
|
||||||
|
private _buildTree(): void {
|
||||||
|
const edgeLeafIndex = this._edgeLeaf.index
|
||||||
|
this._leaves = [...Array.from({ length: edgeLeafIndex - 1 }, () => null), ...this._leavesAfterEdge]
|
||||||
|
this._layers = [this._leaves]
|
||||||
|
this._rebuild()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_rebuild() {
|
||||||
|
for (let level = 1; level <= this.levels; level++) {
|
||||||
|
this._layers[level] = []
|
||||||
|
for (let i = 0; i < Math.ceil(this._layers[level - 1].length / 2); i++) {
|
||||||
|
this._layers[level][i] = this._hash(
|
||||||
|
this._layers[level - 1][i * 2],
|
||||||
|
i * 2 + 1 < this._layers[level - 1].length
|
||||||
|
? this._layers[level - 1][i * 2 + 1]
|
||||||
|
: this._zeros[level - 1],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user