Update docs

This commit is contained in:
Miguel Mota 2021-12-06 15:24:10 -08:00
parent 503afa03eb
commit f4be5df429
No known key found for this signature in database
GPG Key ID: 67EC1161588A00F9
2 changed files with 119 additions and 51 deletions

View File

@ -60,7 +60,7 @@ export class MerkleTree extends Base {
* return crypto.createHash('sha256').update(data).digest()
*}
*
*const leaves = ['a', 'b', 'c'].map(x => keccak(x))
*const leaves = ['a', 'b', 'c'].map(value => keccak(value))
*
*const tree = new MerkleTree(leaves, sha256)
*```
@ -96,10 +96,10 @@ export class MerkleTree extends Base {
private processLeaves (leaves: TLeaf[]) {
if (this.hashLeaves) {
leaves = leaves.map(x => this.hashFn(x))
leaves = leaves.map(leaf => this.hashFn(leaf))
}
this.leaves = leaves.map(x => this.bufferify(x))
this.leaves = leaves.map(leaf => this.bufferify(leaf))
if (this.sortLeaves) {
this.leaves = this.leaves.sort(Buffer.compare)
}
@ -179,6 +179,40 @@ export class MerkleTree extends Base {
}
}
/**
* addLeaf
* @desc Adds a leaf to the tree and re-calculates layers.
* @param {String|Buffer} - Leaf
* @param {Boolean} - Set to true if the leaf should be hashed before being added to tree.
* @example
*```js
*tree.addLeaf(newLeaf)
*```
*/
addLeaf (leaf: TLeaf, shouldHash: boolean = false) {
if (shouldHash) {
leaf = this.hashFn(leaf)
}
this.processLeaves([...this.leaves, leaf])
}
/**
* addLeaves
* @desc Adds multiple leaves to the tree and re-calculates layers.
* @param {String[]|Buffer[]} - Array of leaves
* @param {Boolean} - Set to true if the leaves should be hashed before being added to tree.
* @example
*```js
*tree.addLeaves(newLeaves)
*```
*/
addLeaves (leaves: TLeaf[], shouldHash: boolean = false) {
if (shouldHash) {
leaves = leaves.map(leaf => this.hashFn(leaf))
}
this.processLeaves([...this.leaves, ...leaves])
}
/**
* getLeaves
* @desc Returns array of leaves of Merkle Tree.
@ -191,19 +225,28 @@ export class MerkleTree extends Base {
getLeaves (values?: any[]):Buffer[] {
if (Array.isArray(values)) {
if (this.hashLeaves) {
values = values.map(x => this.hashFn(x))
values = values.map(value => this.hashFn(value))
if (this.sortLeaves) {
values = values.sort(Buffer.compare)
}
}
return this.leaves.filter(x => this._bufferIndexOf(values, x) !== -1)
return this.leaves.filter(leaf => this._bufferIndexOf(values, leaf) !== -1)
}
return this.leaves
}
// TODO: docs
/**
* getLeaf
* @desc Returns the leaf at the given index.
* @param {Number} - Index number
* @return {Buffer}
* @example
*```js
*const leaf = tree.getLeaf(1)
*```
*/
getLeaf (index: number):Buffer {
if (index < 0 || index > this.leaves.length - 1) {
return Buffer.from([])
@ -212,8 +255,18 @@ export class MerkleTree extends Base {
return this.leaves[index]
}
// TODO: docs
getLeafIndex (target: Buffer):number {
/**
* getLeafIndex
* @desc Returns the index of the given leaf, or -1 if the leaf is not found.
* @param {String|Buffer} - Target leaf
* @return {number}
* @example
*```js
*const leaf = Buffer.from('abc')
*const index = tree.getLeafIndex(leaf)
*```
*/
getLeafIndex (target: TLeaf):number {
target = this.bufferify(target)
const leaves = this.getLeaves()
for (let i = 0; i < leaves.length; i++) {
@ -226,7 +279,15 @@ export class MerkleTree extends Base {
return -1
}
// TODO: docs
/**
* getLeafCount
* @desc Returns the total number of leaves.
* @return {number}
* @example
*```js
*const count = tree.getLeafCount()
*```
*/
getLeafCount (): number {
return this.leaves.length
}
@ -241,7 +302,7 @@ export class MerkleTree extends Base {
*```
*/
getHexLeaves ():string[] {
return this.leaves.map(x => this.bufferToHex(x))
return this.leaves.map(leaf => this.bufferToHex(leaf))
}
/**
@ -255,7 +316,7 @@ export class MerkleTree extends Base {
*```
*/
static marshalLeaves (leaves: any[]):string {
return JSON.stringify(leaves.map(x => MerkleTree.bufferToHex(x)), null, 2)
return JSON.stringify(leaves.map(leaf => MerkleTree.bufferToHex(leaf)), null, 2)
}
/**
@ -286,7 +347,7 @@ export class MerkleTree extends Base {
throw new Error('Expected JSON string to be array')
}
return parsed.map(x => MerkleTree.bufferify(x))
return parsed.map(leaf => MerkleTree.bufferify(leaf))
}
/**
@ -314,7 +375,7 @@ export class MerkleTree extends Base {
getHexLayers ():string[] {
return this.layers.reduce((acc: string[][], item: Buffer[]) => {
if (Array.isArray(item)) {
acc.push(item.map(x => this.bufferToHex(x)))
acc.push(item.map(value => this.bufferToHex(value)))
} else {
acc.push(item)
}
@ -358,10 +419,18 @@ export class MerkleTree extends Base {
*```
*/
getHexLayersFlat ():string[] {
return this.getLayersFlat().map(x => this.bufferToHex(x))
return this.getLayersFlat().map(layer => this.bufferToHex(layer))
}
// TODO: docs
/**
* getLayerCount
* @desc Returns the total number of layers.
* @return {number}
* @example
*```js
*const count = tree.getLayerCount()
*```
*/
getLayerCount ():number {
return this.getLayers().length
}
@ -411,7 +480,7 @@ export class MerkleTree extends Base {
*
* @example
*```js
*const leaves = ['a', 'b', 'a'].map(x => keccak(x))
*const leaves = ['a', 'b', 'a'].map(value => keccak(value))
*const tree = new MerkleTree(leaves, keccak)
*const proof = tree.getProof(leaves[2], 2)
*```
@ -474,7 +543,7 @@ export class MerkleTree extends Base {
*```
*/
getHexProof (leaf: Buffer | string, index?: number):string[] {
return this.getProof(leaf, index).map(x => this.bufferToHex(x.data))
return this.getProof(leaf, index).map(item => this.bufferToHex(item.data))
}
/**
@ -490,10 +559,10 @@ export class MerkleTree extends Base {
*```
*/
getPositionalHexProof (leaf: Buffer | string, index?: number): (string | number)[][] {
return this.getProof(leaf, index).map(x => {
return this.getProof(leaf, index).map(item => {
return [
x.position === 'left' ? 0 : 1,
this.bufferToHex(x.data)
item.position === 'left' ? 0 : 1,
this.bufferToHex(item.data)
]
})
}
@ -509,18 +578,18 @@ export class MerkleTree extends Base {
*```
*/
static marshalProof (proof: any[]):string {
const json = proof.map(x => {
if (typeof x === 'string') {
return x
const json = proof.map(item => {
if (typeof item === 'string') {
return item
}
if (Buffer.isBuffer(x)) {
return MerkleTree.bufferToHex(x)
if (Buffer.isBuffer(item)) {
return MerkleTree.bufferToHex(item)
}
return {
position: x.position,
data: MerkleTree.bufferToHex(x.data)
position: item.position,
data: MerkleTree.bufferToHex(item.data)
}
})
@ -555,13 +624,13 @@ export class MerkleTree extends Base {
throw new Error('Expected JSON string to be array')
}
return parsed.map(x => {
if (typeof x === 'string') {
return MerkleTree.bufferify(x)
} else if (x instanceof Object) {
return parsed.map(item => {
if (typeof item === 'string') {
return MerkleTree.bufferify(item)
} else if (item instanceof Object) {
return {
position: x.position,
data: MerkleTree.bufferify(x.data)
position: item.position,
data: MerkleTree.bufferify(item.data)
}
} else {
throw new Error('Expected item to be of type string or object')
@ -716,7 +785,7 @@ export class MerkleTree extends Base {
throw new Error('Element does not exist in Merkle tree')
}
const _proofs: Buffer[] = (proofs as any[]).map(x => this.bufferify(x))
const _proofs: Buffer[] = (proofs as any[]).map(item => this.bufferify(item))
const tested = []
const flags = []
@ -840,8 +909,8 @@ export class MerkleTree extends Base {
*/
verifyMultiProof (root: Buffer | string, indices: number[], leaves: Buffer[] | string[], depth: number, proof: Buffer[] | string[]):boolean {
root = this.bufferify(root)
leaves = (leaves as any[]).map(x => this.bufferify(x))
proof = (proof as any[]).map(x => this.bufferify(x))
leaves = (leaves as any[]).map(leaf => this.bufferify(leaf))
proof = (proof as any[]).map(leaf => this.bufferify(leaf))
const tree = {}
for (const [index, leaf] of this._zip(indices, leaves)) {
@ -850,7 +919,7 @@ export class MerkleTree extends Base {
for (const [index, proofitem] of this._zip(this.getProofIndices(indices, depth), proof)) {
tree[index] = proofitem
}
let indexqueue = Object.keys(tree).map(x => +x).sort((a, b) => a - b)
let indexqueue = Object.keys(tree).map(value => +value).sort((a, b) => a - b)
indexqueue = indexqueue.slice(0, indexqueue.length - 1)
let i = 0
while (i < indexqueue.length) {
@ -958,7 +1027,14 @@ export class MerkleTree extends Base {
return t.getMultiProof(tree, indices)
}
// TODO: docs
/**
* resetTree
* @desc Resets the tree by clearing the leaves and layers.
* @example
*```js
*tree.resetTree()
*```
*/
resetTree ():void {
this.leaves = []
this.layers = []
@ -1011,18 +1087,6 @@ export class MerkleTree extends Base {
toString ():string {
return this._toTreeString()
}
// TODO: docs
addLeaf (leaf: TLeaf, shouldHash: boolean = false) {
const leaves = this.leaves
leaves.push(leaf)
this.processLeaves(this.leaves)
}
// TODO: docs
addLeaves (leaves: TLeaf[], shouldHash: boolean = false) {
this.processLeaves(leaves)
}
}
if (typeof window !== 'undefined') {

View File

@ -1061,7 +1061,7 @@ test('addLeaf', t => {
})
test('addLeaves', t => {
t.plan(2)
t.plan(3)
const leaves = ['a', 'b', 'c'].map(x => keccak256(Buffer.from(x)))
const tree = new MerkleTree([], sha256)
@ -1073,6 +1073,10 @@ test('addLeaves', t => {
'0xb5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510',
'0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2'
])
const moreLeaves = ['d', 'e', 'f'].map(x => keccak256(Buffer.from(x)))
tree.addLeaves(moreLeaves)
t.equal(tree.getHexRoot(), '0xb9a721d82428976e0d500f97646bf273ec1dd9c2104b9328873a94fc3897aec6')
})
test('resetTree', t => {