mirror of
https://github.com/tornadocash/fixed-merkle-tree.git
synced 2024-11-22 09:47:15 +01:00
docs
This commit is contained in:
parent
06b7ab5835
commit
2c1656ab49
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
This is a fixed depth merkle tree implementation with sequential inserts
|
This is a fixed depth merkle tree implementation with sequential inserts
|
||||||
|
|
||||||
|
Requires Node.js >= 14
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "merkle-tree",
|
"name": "merkle-tree",
|
||||||
"version": "1.0.0",
|
"version": "0.1.0",
|
||||||
"description": "",
|
"description": "Fixed depth merkle tree implementation with sequential inserts",
|
||||||
"main": "src/merkleTree.js",
|
"main": "src/merkleTree.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha",
|
"test": "mocha",
|
||||||
"lint": "eslint ."
|
"lint": "eslint ."
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": ["merkle", "tree", "merkleTree"],
|
||||||
"author": "Roman Semenov <semenov.roma@gmail.com>",
|
"author": "Roman Semenov <semenov.roma@gmail.com>",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -4,7 +4,23 @@ const defaultHash = require('./mimc')
|
|||||||
|
|
||||||
// todo ensure consistent types in tree and inserted elements?
|
// todo ensure consistent types in tree and inserted elements?
|
||||||
// todo make sha3 default hasher (and update tests) to get rid of mimc/snarkjs/circomlib dependency
|
// todo make sha3 default hasher (and update tests) to get rid of mimc/snarkjs/circomlib dependency
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @callback hashFunction
|
||||||
|
* @param left Left leaf
|
||||||
|
* @param right Right leaf
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Merkle tree
|
||||||
|
*/
|
||||||
class MerkleTree {
|
class MerkleTree {
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param {number} levels Number of levels in the tree
|
||||||
|
* @param {Array} [elements] Initial elements
|
||||||
|
* @param [zeroElement] Value for non-existent leaves
|
||||||
|
* @param {hashFunction} [hashFunction] Function used to hash 2 leaves
|
||||||
|
*/
|
||||||
constructor(levels, elements = [], zeroElement = DEFAULT_ZERO, hashFunction) {
|
constructor(levels, elements = [], zeroElement = DEFAULT_ZERO, hashFunction) {
|
||||||
this.levels = levels
|
this.levels = levels
|
||||||
this.capacity = 2 << levels
|
this.capacity = 2 << levels
|
||||||
@ -33,10 +49,18 @@ class MerkleTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get tree root
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
root() {
|
root() {
|
||||||
return this._layers[this.levels]?.[0] ?? this._zeros[this.levels]
|
return this._layers[this.levels]?.[0] ?? this._zeros[this.levels]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert new element into the tree
|
||||||
|
* @param element Element to insert
|
||||||
|
*/
|
||||||
insert(element) {
|
insert(element) {
|
||||||
if (this._layers[0].length >= this.capacity) {
|
if (this._layers[0].length >= this.capacity) {
|
||||||
throw new Error('Tree is full')
|
throw new Error('Tree is full')
|
||||||
@ -44,14 +68,23 @@ class MerkleTree {
|
|||||||
this.update(this._layers[0].length, element)
|
this.update(this._layers[0].length, element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert multiple elements into the tree. Tree will be fully rebuilt during this operation.
|
||||||
|
* @param {Array} elements Elements to insert
|
||||||
|
*/
|
||||||
bulkInsert(elements) {
|
bulkInsert(elements) {
|
||||||
if (this._layers[0].length + elements > this.capacity) {
|
if (this._layers[0].length + elements.length > this.capacity) {
|
||||||
throw new Error('Tree is full')
|
throw new Error('Tree is full')
|
||||||
}
|
}
|
||||||
this._layers[0].push(...elements)
|
this._layers[0].push(...elements)
|
||||||
this._rebuild()
|
this._rebuild()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change an element in the tree
|
||||||
|
* @param {number} index Index of element to change
|
||||||
|
* @param element Updated element value
|
||||||
|
*/
|
||||||
update(index, element) {
|
update(index, element) {
|
||||||
if (index < 0 || index > this._layers[0].length || index >= this.capacity) {
|
if (index < 0 || index > this._layers[0].length || index >= this.capacity) {
|
||||||
throw new Error('Insert index out of bounds: ' + index)
|
throw new Error('Insert index out of bounds: ' + index)
|
||||||
@ -66,6 +99,11 @@ class MerkleTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get merkle proof for a leaf
|
||||||
|
* @param index Leaf index to generate proof for
|
||||||
|
* @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index
|
||||||
|
*/
|
||||||
proof(index) {
|
proof(index) {
|
||||||
if (index < 0 || index >= this._layers[0].length) {
|
if (index < 0 || index >= this._layers[0].length) {
|
||||||
throw new Error('Index out of bounds: ' + index)
|
throw new Error('Index out of bounds: ' + index)
|
||||||
@ -83,6 +121,11 @@ class MerkleTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an element in the tree
|
||||||
|
* @param element An element to find
|
||||||
|
* @returns {number} Index if element is found, otherwise -1
|
||||||
|
*/
|
||||||
indexOf(element) {
|
indexOf(element) {
|
||||||
return this._layers[0].indexOf(element)
|
return this._layers[0].indexOf(element)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user