Add IncrementalMerkleTree class

This commit is contained in:
Miguel Mota 2022-11-20 00:45:55 -08:00
parent 2f686b2e18
commit fcc01f71b3
No known key found for this signature in database
GPG Key ID: 67EC1161588A00F9
15 changed files with 1713 additions and 353 deletions

View File

@ -6,6 +6,8 @@
* **Base**
↳ [IncrementalMerkleTree](_src_incrementalmerkletree_.incrementalmerkletree.md)
↳ [MerkleMountainRange](_src_merklemountainrange_.merklemountainrange.md)
↳ [MerkleTree](_src_merkletree_.merkletree.md)
@ -14,17 +16,17 @@
### Methods
* [_bufferIndexOf](_src_base_.base.md#protected-_bufferindexof)
* [_isHexString](_src_base_.base.md#protected-_ishexstring)
* [_log2](_src_base_.base.md#protected-_log2)
* [_zip](_src_base_.base.md#protected-_zip)
* [bigNumberify](_src_base_.base.md#bignumberify)
* [binarySearch](_src_base_.base.md#binarysearch)
* [bufferIndexOf](_src_base_.base.md#protected-bufferindexof)
* [bufferToHex](_src_base_.base.md#buffertohex)
* [bufferify](_src_base_.base.md#bufferify)
* [bufferifyFn](_src_base_.base.md#bufferifyfn)
* [isHexString](_src_base_.base.md#protected-ishexstring)
* [linearSearch](_src_base_.base.md#linearsearch)
* [log2](_src_base_.base.md#protected-log2)
* [print](_src_base_.base.md#print)
* [zip](_src_base_.base.md#protected-zip)
* [bigNumberify](_src_base_.base.md#static-bignumberify)
* [binarySearch](_src_base_.base.md#static-binarysearch)
* [bufferToHex](_src_base_.base.md#static-buffertohex)
@ -36,99 +38,6 @@
## Methods
### `Protected` _bufferIndexOf
**_bufferIndexOf**(`array`: Buffer[], `element`: Buffer, `isSorted`: boolean): *number*
bufferIndexOf
**`desc`** Returns the first index of which given buffer is found in array.
**`example`**
```js
const index = tree.bufferIndexOf(haystack, needle)
```
**Parameters:**
Name | Type | Default |
------ | ------ | ------ |
`array` | Buffer[] | - |
`element` | Buffer | - |
`isSorted` | boolean | false |
**Returns:** *number*
- Index number
___
### `Protected` _isHexString
**_isHexString**(`value`: string): *boolean*
isHexString
**`desc`** Returns true if value is a hex string.
**`example`**
```js
console.log(MerkleTree.isHexString('0x1234'))
```
**Parameters:**
Name | Type |
------ | ------ |
`value` | string |
**Returns:** *boolean*
___
### `Protected` _log2
**_log2**(`n`: number): *number*
log2
**`desc`** Returns the log2 of number.
**Parameters:**
Name | Type |
------ | ------ |
`n` | number |
**Returns:** *number*
___
### `Protected` _zip
**_zip**(`a`: any[], `b`: any[]): *any[][]*
zip
**`desc`** Returns true if value is a hex string.
**`example`**
```js
const zipped = tree.zip(['a', 'b'],['A', 'B'])
console.log(zipped) // [ [ 'a', 'A' ], [ 'b', 'B' ] ]
```
**Parameters:**
Name | Type | Description |
------ | ------ | ------ |
`a` | any[] | first array |
`b` | any[] | second array |
**Returns:** *any[][]*
___
### bigNumberify
**bigNumberify**(`value`: any): *BigInt*
@ -183,6 +92,33 @@ Name | Type |
___
### `Protected` bufferIndexOf
**bufferIndexOf**(`array`: Buffer[], `element`: Buffer, `isSorted`: boolean): *number*
bufferIndexOf
**`desc`** Returns the first index of which given buffer is found in array.
**`example`**
```js
const index = tree.bufferIndexOf(haystack, needle)
```
**Parameters:**
Name | Type | Default |
------ | ------ | ------ |
`array` | Buffer[] | - |
`element` | Buffer | - |
`isSorted` | boolean | false |
**Returns:** *number*
- Index number
___
### bufferToHex
**bufferToHex**(`value`: Buffer, `withPrefix`: boolean): *string*
@ -253,6 +189,29 @@ Name | Type |
___
### `Protected` isHexString
**isHexString**(`value`: string): *boolean*
isHexString
**`desc`** Returns true if value is a hex string.
**`example`**
```js
console.log(MerkleTree.isHexString('0x1234'))
```
**Parameters:**
Name | Type |
------ | ------ |
`value` | string |
**Returns:** *boolean*
___
### linearSearch
**linearSearch**(`array`: Buffer[], `element`: Buffer, `eqChecker`: function): *number*
@ -293,6 +252,24 @@ Name | Type |
___
### `Protected` log2
**log2**(`n`: number): *number*
log2
**`desc`** Returns the log2 of number.
**Parameters:**
Name | Type |
------ | ------ |
`n` | number |
**Returns:** *number*
___
### print
**print**(): *void*
@ -310,6 +287,31 @@ tree.print()
___
### `Protected` zip
**zip**(`a`: any[], `b`: any[]): *any[][]*
zip
**`desc`** Returns true if value is a hex string.
**`example`**
```js
const zipped = tree.zip(['a', 'b'],['A', 'B'])
console.log(zipped) // [ [ 'a', 'A' ], [ 'b', 'B' ] ]
```
**Parameters:**
Name | Type | Description |
------ | ------ | ------ |
`a` | any[] | first array |
`b` | any[] | second array |
**Returns:** *any[][]*
___
### `Static` bigNumberify
**bigNumberify**(`value`: any): *BigInt*

View File

@ -0,0 +1,780 @@
[merkletreejs](../README.md) [Globals](../globals.md) ["src/IncrementalMerkleTree"](../modules/_src_incrementalmerkletree_.md) [IncrementalMerkleTree](_src_incrementalmerkletree_.incrementalmerkletree.md)
# Class: IncrementalMerkleTree
## Hierarchy
* [Base](_src_base_.base.md)
↳ **IncrementalMerkleTree**
## Index
### Constructors
* [constructor](_src_incrementalmerkletree_.incrementalmerkletree.md#constructor)
### Methods
* [bigNumberify](_src_incrementalmerkletree_.incrementalmerkletree.md#bignumberify)
* [binarySearch](_src_incrementalmerkletree_.incrementalmerkletree.md#binarysearch)
* [bufferIndexOf](_src_incrementalmerkletree_.incrementalmerkletree.md#protected-bufferindexof)
* [bufferToHex](_src_incrementalmerkletree_.incrementalmerkletree.md#buffertohex)
* [bufferify](_src_incrementalmerkletree_.incrementalmerkletree.md#bufferify)
* [bufferifyFn](_src_incrementalmerkletree_.incrementalmerkletree.md#bufferifyfn)
* [computeRoot](_src_incrementalmerkletree_.incrementalmerkletree.md#computeroot)
* [copyList](_src_incrementalmerkletree_.incrementalmerkletree.md#copylist)
* [delete](_src_incrementalmerkletree_.incrementalmerkletree.md#delete)
* [getArity](_src_incrementalmerkletree_.incrementalmerkletree.md#getarity)
* [getDepth](_src_incrementalmerkletree_.incrementalmerkletree.md#getdepth)
* [getHexLayers](_src_incrementalmerkletree_.incrementalmerkletree.md#gethexlayers)
* [getHexRoot](_src_incrementalmerkletree_.incrementalmerkletree.md#gethexroot)
* [getLayers](_src_incrementalmerkletree_.incrementalmerkletree.md#getlayers)
* [getLayersAsObject](_src_incrementalmerkletree_.incrementalmerkletree.md#getlayersasobject)
* [getLeaves](_src_incrementalmerkletree_.incrementalmerkletree.md#getleaves)
* [getMaxLeaves](_src_incrementalmerkletree_.incrementalmerkletree.md#getmaxleaves)
* [getProof](_src_incrementalmerkletree_.incrementalmerkletree.md#getproof)
* [getRoot](_src_incrementalmerkletree_.incrementalmerkletree.md#getroot)
* [indexOf](_src_incrementalmerkletree_.incrementalmerkletree.md#indexof)
* [insert](_src_incrementalmerkletree_.incrementalmerkletree.md#insert)
* [isHexString](_src_incrementalmerkletree_.incrementalmerkletree.md#protected-ishexstring)
* [linearSearch](_src_incrementalmerkletree_.incrementalmerkletree.md#linearsearch)
* [log2](_src_incrementalmerkletree_.incrementalmerkletree.md#protected-log2)
* [print](_src_incrementalmerkletree_.incrementalmerkletree.md#print)
* [toString](_src_incrementalmerkletree_.incrementalmerkletree.md#tostring)
* [toTreeString](_src_incrementalmerkletree_.incrementalmerkletree.md#protected-totreestring)
* [update](_src_incrementalmerkletree_.incrementalmerkletree.md#update)
* [verify](_src_incrementalmerkletree_.incrementalmerkletree.md#verify)
* [zip](_src_incrementalmerkletree_.incrementalmerkletree.md#protected-zip)
* [bigNumberify](_src_incrementalmerkletree_.incrementalmerkletree.md#static-bignumberify)
* [binarySearch](_src_incrementalmerkletree_.incrementalmerkletree.md#static-binarysearch)
* [bufferToHex](_src_incrementalmerkletree_.incrementalmerkletree.md#static-buffertohex)
* [bufferify](_src_incrementalmerkletree_.incrementalmerkletree.md#static-bufferify)
* [hexZeroPad](_src_incrementalmerkletree_.incrementalmerkletree.md#static-hexzeropad)
* [isHexString](_src_incrementalmerkletree_.incrementalmerkletree.md#static-ishexstring)
* [linearSearch](_src_incrementalmerkletree_.incrementalmerkletree.md#static-linearsearch)
* [print](_src_incrementalmerkletree_.incrementalmerkletree.md#static-print)
## Constructors
### constructor
\+ **new IncrementalMerkleTree**(`hashFn`: any, `options`: [Options](../interfaces/_src_incrementalmerkletree_.options.md)): *[IncrementalMerkleTree](_src_incrementalmerkletree_.incrementalmerkletree.md)*
**Parameters:**
Name | Type |
------ | ------ |
`hashFn` | any |
`options` | [Options](../interfaces/_src_incrementalmerkletree_.options.md) |
**Returns:** *[IncrementalMerkleTree](_src_incrementalmerkletree_.incrementalmerkletree.md)*
## Methods
### bigNumberify
**bigNumberify**(`value`: any): *BigInt*
*Inherited from [Base](_src_base_.base.md).[bigNumberify](_src_base_.base.md#bignumberify)*
**Parameters:**
Name | Type |
------ | ------ |
`value` | any |
**Returns:** *BigInt*
___
### binarySearch
**binarySearch**(`array`: Buffer[], `element`: Buffer, `compareFunction`: function): *number*
*Inherited from [Base](_src_base_.base.md).[binarySearch](_src_base_.base.md#static-binarysearch)*
binarySearch
**`desc`** Returns the first index of which given item is found in array using binary search.
**`example`**
```js
const index = tree.binarySearch(array, element, Buffer.compare)
```
**Parameters:**
**array**: *Buffer[]*
Array of items.
**element**: *Buffer*
Item to find.
**compareFunction**: *function*
▸ (`a`: unknown, `b`: unknown): *number*
**Parameters:**
Name | Type |
------ | ------ |
`a` | unknown |
`b` | unknown |
**Returns:** *number*
- Index number
___
### `Protected` bufferIndexOf
**bufferIndexOf**(`array`: Buffer[], `element`: Buffer, `isSorted`: boolean): *number*
*Inherited from [Base](_src_base_.base.md).[bufferIndexOf](_src_base_.base.md#protected-bufferindexof)*
bufferIndexOf
**`desc`** Returns the first index of which given buffer is found in array.
**`example`**
```js
const index = tree.bufferIndexOf(haystack, needle)
```
**Parameters:**
Name | Type | Default |
------ | ------ | ------ |
`array` | Buffer[] | - |
`element` | Buffer | - |
`isSorted` | boolean | false |
**Returns:** *number*
- Index number
___
### bufferToHex
**bufferToHex**(`value`: Buffer, `withPrefix`: boolean): *string*
*Inherited from [Base](_src_base_.base.md).[bufferToHex](_src_base_.base.md#buffertohex)*
bufferToHex
**`desc`** Returns a hex string with 0x prefix for given buffer.
**`example`**
```js
const hexStr = tree.bufferToHex(Buffer.from('A'))
```
**Parameters:**
Name | Type | Default |
------ | ------ | ------ |
`value` | Buffer | - |
`withPrefix` | boolean | true |
**Returns:** *string*
___
### bufferify
**bufferify**(`value`: any): *Buffer*
*Inherited from [Base](_src_base_.base.md).[bufferify](_src_base_.base.md#static-bufferify)*
bufferify
**`desc`** Returns a buffer type for the given value.
**`example`**
```js
const buf = tree.bufferify('0x1234')
```
**Parameters:**
Name | Type |
------ | ------ |
`value` | any |
**Returns:** *Buffer*
___
### bufferifyFn
**bufferifyFn**(`f`: any): *any*
*Inherited from [Base](_src_base_.base.md).[bufferifyFn](_src_base_.base.md#bufferifyfn)*
bufferifyFn
**`desc`** Returns a function that will bufferify the return value.
**`example`**
```js
const fn = tree.bufferifyFn((value) => sha256(value))
```
**Parameters:**
Name | Type |
------ | ------ |
`f` | any |
**Returns:** *any*
___
### computeRoot
**computeRoot**(): *any*
**Returns:** *any*
___
### copyList
**copyList**(`list`: any[]): *bigint[]*
**Parameters:**
Name | Type |
------ | ------ |
`list` | any[] |
**Returns:** *bigint[]*
___
### delete
**delete**(`index`: number): *void*
**Parameters:**
Name | Type |
------ | ------ |
`index` | number |
**Returns:** *void*
___
### getArity
**getArity**(): *number*
**Returns:** *number*
___
### getDepth
**getDepth**(): *number*
**Returns:** *number*
___
### getHexLayers
**getHexLayers**(): *string[]*
**Returns:** *string[]*
___
### getHexRoot
**getHexRoot**(): *string*
**Returns:** *string*
___
### getLayers
**getLayers**(): *any[]*
**Returns:** *any[]*
___
### getLayersAsObject
**getLayersAsObject**(): *any*
**Returns:** *any*
___
### getLeaves
**getLeaves**(): *bigint[]*
**Returns:** *bigint[]*
___
### getMaxLeaves
**getMaxLeaves**(): *number*
**Returns:** *number*
___
### getProof
**getProof**(`index`: number): *any*
**Parameters:**
Name | Type |
------ | ------ |
`index` | number |
**Returns:** *any*
___
### getRoot
**getRoot**(): *any*
**Returns:** *any*
___
### indexOf
**indexOf**(`leaf`: any): *number*
**Parameters:**
Name | Type |
------ | ------ |
`leaf` | any |
**Returns:** *number*
___
### insert
**insert**(`leaf`: any): *void*
**Parameters:**
Name | Type |
------ | ------ |
`leaf` | any |
**Returns:** *void*
___
### `Protected` isHexString
**isHexString**(`value`: string): *boolean*
*Inherited from [Base](_src_base_.base.md).[isHexString](_src_base_.base.md#static-ishexstring)*
isHexString
**`desc`** Returns true if value is a hex string.
**`example`**
```js
console.log(MerkleTree.isHexString('0x1234'))
```
**Parameters:**
Name | Type |
------ | ------ |
`value` | string |
**Returns:** *boolean*
___
### linearSearch
**linearSearch**(`array`: Buffer[], `element`: Buffer, `eqChecker`: function): *number*
*Inherited from [Base](_src_base_.base.md).[linearSearch](_src_base_.base.md#static-linearsearch)*
linearSearch
**`desc`** Returns the first index of which given item is found in array using linear search.
**`example`**
```js
const index = tree.linearSearch(array, element, (a, b) => a === b)
```
**Parameters:**
**array**: *Buffer[]*
Array of items.
**element**: *Buffer*
Item to find.
**eqChecker**: *function*
▸ (`a`: unknown, `b`: unknown): *boolean*
**Parameters:**
Name | Type |
------ | ------ |
`a` | unknown |
`b` | unknown |
**Returns:** *number*
- Index number
___
### `Protected` log2
**log2**(`n`: number): *number*
*Inherited from [Base](_src_base_.base.md).[log2](_src_base_.base.md#protected-log2)*
log2
**`desc`** Returns the log2 of number.
**Parameters:**
Name | Type |
------ | ------ |
`n` | number |
**Returns:** *number*
___
### print
**print**(): *void*
*Inherited from [Base](_src_base_.base.md).[print](_src_base_.base.md#print)*
print
**`desc`** Prints out a visual representation of the merkle tree.
**`example`**
```js
tree.print()
```
**Returns:** *void*
___
### toString
**toString**(): *string*
**Returns:** *string*
___
### `Protected` toTreeString
**toTreeString**(): *string*
**Returns:** *string*
___
### update
**update**(`index`: number, `newLeaf`: any): *void*
**Parameters:**
Name | Type |
------ | ------ |
`index` | number |
`newLeaf` | any |
**Returns:** *void*
___
### verify
**verify**(`proof`: any): *boolean*
**Parameters:**
Name | Type |
------ | ------ |
`proof` | any |
**Returns:** *boolean*
___
### `Protected` zip
**zip**(`a`: any[], `b`: any[]): *any[][]*
*Inherited from [Base](_src_base_.base.md).[zip](_src_base_.base.md#protected-zip)*
zip
**`desc`** Returns true if value is a hex string.
**`example`**
```js
const zipped = tree.zip(['a', 'b'],['A', 'B'])
console.log(zipped) // [ [ 'a', 'A' ], [ 'b', 'B' ] ]
```
**Parameters:**
Name | Type | Description |
------ | ------ | ------ |
`a` | any[] | first array |
`b` | any[] | second array |
**Returns:** *any[][]*
___
### `Static` bigNumberify
**bigNumberify**(`value`: any): *BigInt*
*Inherited from [Base](_src_base_.base.md).[bigNumberify](_src_base_.base.md#bignumberify)*
**Parameters:**
Name | Type |
------ | ------ |
`value` | any |
**Returns:** *BigInt*
___
### `Static` binarySearch
**binarySearch**(`array`: Buffer[], `element`: Buffer, `compareFunction`: function): *number*
*Inherited from [Base](_src_base_.base.md).[binarySearch](_src_base_.base.md#static-binarysearch)*
binarySearch
**`desc`** Returns the first index of which given item is found in array using binary search.
**`example`**
```js
const index = MerkleTree.binarySearch(array, element, Buffer.compare)
```
**Parameters:**
**array**: *Buffer[]*
Array of items.
**element**: *Buffer*
Item to find.
**compareFunction**: *function*
▸ (`a`: unknown, `b`: unknown): *number*
**Parameters:**
Name | Type |
------ | ------ |
`a` | unknown |
`b` | unknown |
**Returns:** *number*
- Index number
___
### `Static` bufferToHex
**bufferToHex**(`value`: Buffer, `withPrefix`: boolean): *string*
*Inherited from [Base](_src_base_.base.md).[bufferToHex](_src_base_.base.md#buffertohex)*
bufferToHex
**`desc`** Returns a hex string with 0x prefix for given buffer.
**`example`**
```js
const hexStr = MerkleTree.bufferToHex(Buffer.from('A'))
```
**Parameters:**
Name | Type | Default |
------ | ------ | ------ |
`value` | Buffer | - |
`withPrefix` | boolean | true |
**Returns:** *string*
___
### `Static` bufferify
**bufferify**(`value`: any): *Buffer*
*Inherited from [Base](_src_base_.base.md).[bufferify](_src_base_.base.md#static-bufferify)*
bufferify
**`desc`** Returns a buffer type for the given value.
**`example`**
```js
const buf = MerkleTree.bufferify('0x1234')
```
**Parameters:**
Name | Type |
------ | ------ |
`value` | any |
**Returns:** *Buffer*
___
### `Static` hexZeroPad
**hexZeroPad**(`hexStr`: string, `length`: number): *string*
*Inherited from [Base](_src_base_.base.md).[hexZeroPad](_src_base_.base.md#static-hexzeropad)*
**Parameters:**
Name | Type |
------ | ------ |
`hexStr` | string |
`length` | number |
**Returns:** *string*
___
### `Static` isHexString
**isHexString**(`v`: string): *boolean*
*Inherited from [Base](_src_base_.base.md).[isHexString](_src_base_.base.md#static-ishexstring)*
isHexString
**`desc`** Returns true if value is a hex string.
**`example`**
```js
console.log(MerkleTree.isHexString('0x1234'))
```
**Parameters:**
Name | Type |
------ | ------ |
`v` | string |
**Returns:** *boolean*
___
### `Static` linearSearch
**linearSearch**(`array`: Buffer[], `element`: Buffer, `eqChecker`: function): *number*
*Inherited from [Base](_src_base_.base.md).[linearSearch](_src_base_.base.md#static-linearsearch)*
linearSearch
**`desc`** Returns the first index of which given item is found in array using linear search.
**`example`**
```js
const index = MerkleTree.linearSearch(array, element, (a, b) => a === b)
```
**Parameters:**
**array**: *Buffer[]*
Array of items.
**element**: *Buffer*
Item to find.
**eqChecker**: *function*
▸ (`a`: unknown, `b`: unknown): *boolean*
**Parameters:**
Name | Type |
------ | ------ |
`a` | unknown |
`b` | unknown |
**Returns:** *number*
- Index number
___
### `Static` print
**print**(`tree`: any): *void*
*Inherited from [Base](_src_base_.base.md).[print](_src_base_.base.md#print)*
print
**`desc`** Prints out a visual representation of the given merkle tree.
**`example`**
```js
MerkleTree.print(tree)
```
**Parameters:**
Name | Type | Description |
------ | ------ | ------ |
`tree` | any | Merkle tree instance. |
**Returns:** *void*

View File

@ -29,13 +29,10 @@
### Methods
* [_bufferIndexOf](_src_merklemountainrange_.merklemountainrange.md#protected-_bufferindexof)
* [_isHexString](_src_merklemountainrange_.merklemountainrange.md#protected-_ishexstring)
* [_log2](_src_merklemountainrange_.merklemountainrange.md#protected-_log2)
* [_zip](_src_merklemountainrange_.merklemountainrange.md#protected-_zip)
* [append](_src_merklemountainrange_.merklemountainrange.md#append)
* [bigNumberify](_src_merklemountainrange_.merklemountainrange.md#bignumberify)
* [binarySearch](_src_merklemountainrange_.merklemountainrange.md#binarysearch)
* [bufferIndexOf](_src_merklemountainrange_.merklemountainrange.md#protected-bufferindexof)
* [bufferToHex](_src_merklemountainrange_.merklemountainrange.md#buffertohex)
* [bufferify](_src_merklemountainrange_.merklemountainrange.md#bufferify)
* [bufferifyFn](_src_merklemountainrange_.merklemountainrange.md#bufferifyfn)
@ -51,8 +48,10 @@
* [hashBranch](_src_merklemountainrange_.merklemountainrange.md#hashbranch)
* [hashLeaf](_src_merklemountainrange_.merklemountainrange.md#hashleaf)
* [heightAt](_src_merklemountainrange_.merklemountainrange.md#heightat)
* [isHexString](_src_merklemountainrange_.merklemountainrange.md#protected-ishexstring)
* [isLeaf](_src_merklemountainrange_.merklemountainrange.md#isleaf)
* [linearSearch](_src_merklemountainrange_.merklemountainrange.md#linearsearch)
* [log2](_src_merklemountainrange_.merklemountainrange.md#protected-log2)
* [mountainHeight](_src_merklemountainrange_.merklemountainrange.md#mountainheight)
* [numOfPeaks](_src_merklemountainrange_.merklemountainrange.md#numofpeaks)
* [peakBagging](_src_merklemountainrange_.merklemountainrange.md#peakbagging)
@ -62,6 +61,7 @@
* [print](_src_merklemountainrange_.merklemountainrange.md#print)
* [rollUp](_src_merklemountainrange_.merklemountainrange.md#rollup)
* [verify](_src_merklemountainrange_.merklemountainrange.md#verify)
* [zip](_src_merklemountainrange_.merklemountainrange.md#protected-zip)
* [bigNumberify](_src_merklemountainrange_.merklemountainrange.md#static-bignumberify)
* [binarySearch](_src_merklemountainrange_.merklemountainrange.md#static-binarysearch)
* [bufferToHex](_src_merklemountainrange_.merklemountainrange.md#static-buffertohex)
@ -139,107 +139,6 @@ ___
## Methods
### `Protected` _bufferIndexOf
**_bufferIndexOf**(`array`: Buffer[], `element`: Buffer, `isSorted`: boolean): *number*
*Inherited from [Base](_src_base_.base.md).[_bufferIndexOf](_src_base_.base.md#protected-_bufferindexof)*
bufferIndexOf
**`desc`** Returns the first index of which given buffer is found in array.
**`example`**
```js
const index = tree.bufferIndexOf(haystack, needle)
```
**Parameters:**
Name | Type | Default |
------ | ------ | ------ |
`array` | Buffer[] | - |
`element` | Buffer | - |
`isSorted` | boolean | false |
**Returns:** *number*
- Index number
___
### `Protected` _isHexString
**_isHexString**(`value`: string): *boolean*
*Inherited from [Base](_src_base_.base.md).[_isHexString](_src_base_.base.md#protected-_ishexstring)*
isHexString
**`desc`** Returns true if value is a hex string.
**`example`**
```js
console.log(MerkleTree.isHexString('0x1234'))
```
**Parameters:**
Name | Type |
------ | ------ |
`value` | string |
**Returns:** *boolean*
___
### `Protected` _log2
**_log2**(`n`: number): *number*
*Inherited from [Base](_src_base_.base.md).[_log2](_src_base_.base.md#protected-_log2)*
log2
**`desc`** Returns the log2 of number.
**Parameters:**
Name | Type |
------ | ------ |
`n` | number |
**Returns:** *number*
___
### `Protected` _zip
**_zip**(`a`: any[], `b`: any[]): *any[][]*
*Inherited from [Base](_src_base_.base.md).[_zip](_src_base_.base.md#protected-_zip)*
zip
**`desc`** Returns true if value is a hex string.
**`example`**
```js
const zipped = tree.zip(['a', 'b'],['A', 'B'])
console.log(zipped) // [ [ 'a', 'A' ], [ 'b', 'B' ] ]
```
**Parameters:**
Name | Type | Description |
------ | ------ | ------ |
`a` | any[] | first array |
`b` | any[] | second array |
**Returns:** *any[][]*
___
### append
**append**(`data`: Buffer | string): *void*
@ -315,6 +214,35 @@ Name | Type |
___
### `Protected` bufferIndexOf
**bufferIndexOf**(`array`: Buffer[], `element`: Buffer, `isSorted`: boolean): *number*
*Inherited from [Base](_src_base_.base.md).[bufferIndexOf](_src_base_.base.md#protected-bufferindexof)*
bufferIndexOf
**`desc`** Returns the first index of which given buffer is found in array.
**`example`**
```js
const index = tree.bufferIndexOf(haystack, needle)
```
**Parameters:**
Name | Type | Default |
------ | ------ | ------ |
`array` | Buffer[] | - |
`element` | Buffer | - |
`isSorted` | boolean | false |
**Returns:** *number*
- Index number
___
### bufferToHex
**bufferToHex**(`value`: Buffer, `withPrefix`: boolean): *string*
@ -573,6 +501,31 @@ Name | Type |
___
### `Protected` isHexString
**isHexString**(`value`: string): *boolean*
*Inherited from [Base](_src_base_.base.md).[isHexString](_src_base_.base.md#static-ishexstring)*
isHexString
**`desc`** Returns true if value is a hex string.
**`example`**
```js
console.log(MerkleTree.isHexString('0x1234'))
```
**Parameters:**
Name | Type |
------ | ------ |
`value` | string |
**Returns:** *boolean*
___
### isLeaf
**isLeaf**(`index`: number): *boolean*
@ -631,6 +584,26 @@ Name | Type |
___
### `Protected` log2
**log2**(`n`: number): *number*
*Inherited from [Base](_src_base_.base.md).[log2](_src_base_.base.md#protected-log2)*
log2
**`desc`** Returns the log2 of number.
**Parameters:**
Name | Type |
------ | ------ |
`n` | number |
**Returns:** *number*
___
### mountainHeight
**mountainHeight**(`size`: number): *number*
@ -779,6 +752,33 @@ Name | Type |
___
### `Protected` zip
**zip**(`a`: any[], `b`: any[]): *any[][]*
*Inherited from [Base](_src_base_.base.md).[zip](_src_base_.base.md#protected-zip)*
zip
**`desc`** Returns true if value is a hex string.
**`example`**
```js
const zipped = tree.zip(['a', 'b'],['A', 'B'])
console.log(zipped) // [ [ 'a', 'A' ], [ 'b', 'B' ] ]
```
**Parameters:**
Name | Type | Description |
------ | ------ | ------ |
`a` | any[] | first array |
`b` | any[] | second array |
**Returns:** *any[][]*
___
### `Static` bigNumberify
**bigNumberify**(`value`: any): *BigInt*

View File

@ -20,15 +20,11 @@ Class reprensenting a Merkle Tree
### Methods
* [_bufferIndexOf](_src_merkletree_.merkletree.md#protected-_bufferindexof)
* [_isHexString](_src_merkletree_.merkletree.md#protected-_ishexstring)
* [_log2](_src_merkletree_.merkletree.md#protected-_log2)
* [_toTreeString](_src_merkletree_.merkletree.md#protected-_totreestring)
* [_zip](_src_merkletree_.merkletree.md#protected-_zip)
* [addLeaf](_src_merkletree_.merkletree.md#addleaf)
* [addLeaves](_src_merkletree_.merkletree.md#addleaves)
* [bigNumberify](_src_merkletree_.merkletree.md#bignumberify)
* [binarySearch](_src_merkletree_.merkletree.md#binarysearch)
* [bufferIndexOf](_src_merkletree_.merkletree.md#protected-bufferindexof)
* [bufferToHex](_src_merkletree_.merkletree.md#buffertohex)
* [bufferify](_src_merkletree_.merkletree.md#bufferify)
* [bufferifyFn](_src_merkletree_.merkletree.md#bufferifyfn)
@ -57,14 +53,18 @@ Class reprensenting a Merkle Tree
* [getProofs](_src_merkletree_.merkletree.md#getproofs)
* [getProofsDFS](_src_merkletree_.merkletree.md#getproofsdfs)
* [getRoot](_src_merkletree_.merkletree.md#getroot)
* [isHexString](_src_merkletree_.merkletree.md#protected-ishexstring)
* [isUnevenTree](_src_merkletree_.merkletree.md#isuneventree)
* [linearSearch](_src_merkletree_.merkletree.md#linearsearch)
* [log2](_src_merkletree_.merkletree.md#protected-log2)
* [print](_src_merkletree_.merkletree.md#print)
* [resetTree](_src_merkletree_.merkletree.md#resettree)
* [toString](_src_merkletree_.merkletree.md#tostring)
* [toTreeString](_src_merkletree_.merkletree.md#protected-totreestring)
* [verify](_src_merkletree_.merkletree.md#verify)
* [verifyMultiProof](_src_merkletree_.merkletree.md#verifymultiproof)
* [verifyMultiProofWithFlags](_src_merkletree_.merkletree.md#verifymultiproofwithflags)
* [zip](_src_merkletree_.merkletree.md#protected-zip)
* [bigNumberify](_src_merkletree_.merkletree.md#static-bignumberify)
* [binarySearch](_src_merkletree_.merkletree.md#static-binarysearch)
* [bufferToHex](_src_merkletree_.merkletree.md#static-buffertohex)
@ -119,124 +119,6 @@ Name | Type | Default | Description |
## Methods
### `Protected` _bufferIndexOf
**_bufferIndexOf**(`array`: Buffer[], `element`: Buffer, `isSorted`: boolean): *number*
*Inherited from [Base](_src_base_.base.md).[_bufferIndexOf](_src_base_.base.md#protected-_bufferindexof)*
bufferIndexOf
**`desc`** Returns the first index of which given buffer is found in array.
**`example`**
```js
const index = tree.bufferIndexOf(haystack, needle)
```
**Parameters:**
Name | Type | Default |
------ | ------ | ------ |
`array` | Buffer[] | - |
`element` | Buffer | - |
`isSorted` | boolean | false |
**Returns:** *number*
- Index number
___
### `Protected` _isHexString
**_isHexString**(`value`: string): *boolean*
*Inherited from [Base](_src_base_.base.md).[_isHexString](_src_base_.base.md#protected-_ishexstring)*
isHexString
**`desc`** Returns true if value is a hex string.
**`example`**
```js
console.log(MerkleTree.isHexString('0x1234'))
```
**Parameters:**
Name | Type |
------ | ------ |
`value` | string |
**Returns:** *boolean*
___
### `Protected` _log2
**_log2**(`n`: number): *number*
*Inherited from [Base](_src_base_.base.md).[_log2](_src_base_.base.md#protected-_log2)*
log2
**`desc`** Returns the log2 of number.
**Parameters:**
Name | Type |
------ | ------ |
`n` | number |
**Returns:** *number*
___
### `Protected` _toTreeString
**_toTreeString**(): *string*
toTreeString
**`desc`** Returns a visual representation of the merkle tree as a string.
**`example`**
```js
console.log(tree.toTreeString())
```
**Returns:** *string*
___
### `Protected` _zip
**_zip**(`a`: any[], `b`: any[]): *any[][]*
*Inherited from [Base](_src_base_.base.md).[_zip](_src_base_.base.md#protected-_zip)*
zip
**`desc`** Returns true if value is a hex string.
**`example`**
```js
const zipped = tree.zip(['a', 'b'],['A', 'B'])
console.log(zipped) // [ [ 'a', 'A' ], [ 'b', 'B' ] ]
```
**Parameters:**
Name | Type | Description |
------ | ------ | ------ |
`a` | any[] | first array |
`b` | any[] | second array |
**Returns:** *any[][]*
___
### addLeaf
**addLeaf**(`leaf`: [TLeaf](../modules/_src_merkletree_.md#tleaf), `shouldHash`: boolean): *void*
@ -343,6 +225,35 @@ Name | Type |
___
### `Protected` bufferIndexOf
**bufferIndexOf**(`array`: Buffer[], `element`: Buffer, `isSorted`: boolean): *number*
*Inherited from [Base](_src_base_.base.md).[bufferIndexOf](_src_base_.base.md#protected-bufferindexof)*
bufferIndexOf
**`desc`** Returns the first index of which given buffer is found in array.
**`example`**
```js
const index = tree.bufferIndexOf(haystack, needle)
```
**Parameters:**
Name | Type | Default |
------ | ------ | ------ |
`array` | Buffer[] | - |
`element` | Buffer | - |
`isSorted` | boolean | false |
**Returns:** *number*
- Index number
___
### bufferToHex
**bufferToHex**(`value`: Buffer, `withPrefix`: boolean): *string*
@ -972,6 +883,31 @@ const root = tree.getRoot()
___
### `Protected` isHexString
**isHexString**(`value`: string): *boolean*
*Inherited from [Base](_src_base_.base.md).[isHexString](_src_base_.base.md#static-ishexstring)*
isHexString
**`desc`** Returns true if value is a hex string.
**`example`**
```js
console.log(MerkleTree.isHexString('0x1234'))
```
**Parameters:**
Name | Type |
------ | ------ |
`value` | string |
**Returns:** *boolean*
___
### isUnevenTree
**isUnevenTree**(`treeLayers?`: any[]): *boolean*
@ -1028,6 +964,26 @@ Name | Type |
___
### `Protected` log2
**log2**(`n`: number): *number*
*Inherited from [Base](_src_base_.base.md).[log2](_src_base_.base.md#protected-log2)*
log2
**`desc`** Returns the log2 of number.
**Parameters:**
Name | Type |
------ | ------ |
`n` | number |
**Returns:** *number*
___
### print
**print**(): *void*
@ -1081,6 +1037,23 @@ console.log(tree.toString())
___
### `Protected` toTreeString
**toTreeString**(): *string*
toTreeString
**`desc`** Returns a visual representation of the merkle tree as a string.
**`example`**
```js
console.log(tree.toTreeString())
```
**Returns:** *string*
___
### verify
**verify**(`proof`: any[], `targetNode`: Buffer | string, `root`: Buffer | string): *boolean*
@ -1160,6 +1133,33 @@ Name | Type |
___
### `Protected` zip
**zip**(`a`: any[], `b`: any[]): *any[][]*
*Inherited from [Base](_src_base_.base.md).[zip](_src_base_.base.md#protected-zip)*
zip
**`desc`** Returns true if value is a hex string.
**`example`**
```js
const zipped = tree.zip(['a', 'b'],['A', 'B'])
console.log(zipped) // [ [ 'a', 'A' ], [ 'b', 'B' ] ]
```
**Parameters:**
Name | Type | Description |
------ | ------ | ------ |
`a` | any[] | first array |
`b` | any[] | second array |
**Returns:** *any[][]*
___
### `Static` bigNumberify
**bigNumberify**(`value`: any): *BigInt*

View File

@ -7,6 +7,7 @@
### Modules
* ["src/Base"](modules/_src_base_.md)
* ["src/IncrementalMerkleTree"](modules/_src_incrementalmerkletree_.md)
* ["src/MerkleMountainRange"](modules/_src_merklemountainrange_.md)
* ["src/MerkleTree"](modules/_src_merkletree_.md)
* ["src/index"](modules/_src_index_.md)

View File

@ -0,0 +1,33 @@
[merkletreejs](../README.md) [Globals](../globals.md) ["src/IncrementalMerkleTree"](../modules/_src_incrementalmerkletree_.md) [Options](_src_incrementalmerkletree_.options.md)
# Interface: Options
## Hierarchy
* **Options**
## Index
### Properties
* [arity](_src_incrementalmerkletree_.options.md#optional-arity)
* [depth](_src_incrementalmerkletree_.options.md#optional-depth)
* [zeroValue](_src_incrementalmerkletree_.options.md#optional-zerovalue)
## Properties
### `Optional` arity
**arity**? : *number*
___
### `Optional` depth
**depth**? : *number*
___
### `Optional` zeroValue
**zeroValue**? : *any*

View File

@ -0,0 +1,13 @@
[merkletreejs](../README.md) [Globals](../globals.md) ["src/IncrementalMerkleTree"](_src_incrementalmerkletree_.md)
# Module: "src/IncrementalMerkleTree"
## Index
### Classes
* [IncrementalMerkleTree](../classes/_src_incrementalmerkletree_.incrementalmerkletree.md)
### Interfaces
* [Options](../interfaces/_src_incrementalmerkletree_.options.md)

View File

@ -6,10 +6,17 @@
### References
* [IncrementalMerkleTree](_src_index_.md#incrementalmerkletree)
* [MerkleMountainRange](_src_index_.md#merklemountainrange)
## References
### IncrementalMerkleTree
**IncrementalMerkleTree**:
___
### MerkleMountainRange
**MerkleMountainRange**:

View File

@ -26,7 +26,7 @@ export class Base {
*const index = tree.bufferIndexOf(haystack, needle)
*```
*/
protected _bufferIndexOf (
protected bufferIndexOf (
array: Buffer[],
element: Buffer,
isSorted: boolean = false
@ -308,7 +308,7 @@ export class Base {
return v
}
if (this._isHexString(v)) {
if (this.isHexString(v)) {
return Buffer.from(v.replace('0x', ''), 'hex')
}
@ -345,7 +345,7 @@ export class Base {
*console.log(MerkleTree.isHexString('0x1234'))
*```
*/
protected _isHexString (value: string): boolean {
protected isHexString (value: string): boolean {
return Base.isHexString(value)
}
@ -355,8 +355,8 @@ export class Base {
* @param {Number} value
* @return {Number}
*/
protected _log2 (n: number): number {
return n === 1 ? 0 : 1 + this._log2((n / 2) | 0)
protected log2 (n: number): number {
return n === 1 ? 0 : 1 + this.log2((n / 2) | 0)
}
/**
@ -372,7 +372,7 @@ export class Base {
*console.log(zipped) // [ [ 'a', 'A' ], [ 'b', 'B' ] ]
*```
*/
protected _zip (a: any[], b: any[]): any[][] {
protected zip (a: any[], b: any[]): any[][] {
return a.map((e, i) => [e, b[i]])
}

View File

@ -0,0 +1,314 @@
import Base from './Base'
import treeify from 'treeify'
export interface Options {
depth?: number
// how many inputs per node
arity?: number
zeroValue?: any
}
export class IncrementalMerkleTree extends Base {
private depth?: number
private arity?: number
private zeroes?: any[]
private root?: any
private nodes?: any[]
private hashFn: any
private zeroValue: any
constructor (hashFn: any, options: Options) {
super()
this.hashFn = hashFn
if (options.depth) {
this.depth = options.depth
}
if (options.arity) {
this.arity = options.arity
}
if (this.depth < 1) {
throw new Error('depth must be greater than 0')
}
if (this.arity < 1) {
throw new Error('arity must be greater than 0')
}
const nodes = []
let zeroValue = options.zeroValue
this.zeroValue = zeroValue
this.zeroes = []
if (this.depth) {
for (let i = 0; i < this.depth; i++) {
this.zeroes.push(zeroValue)
nodes[i] = []
zeroValue = this.hashFn(Array(this.arity).fill(zeroValue))
}
}
this.nodes = nodes
this.root = zeroValue
}
getRoot () {
return this.root
}
getHexRoot () {
return this.bufferToHex(this.bufferify(this.getRoot()))
}
insert (leaf: any) {
if (this.depth && this.arity) {
if (this.nodes[0].length >= this.getMaxLeaves()) {
throw new Error('tree is full')
}
}
let node = leaf
let index = this.nodes[0].length
for (let level = 0; level < this.depth; level += 1) {
const position = index % this.arity
const levelStartIndex = index - position
const levelEndIndex = levelStartIndex + this.arity
const children = []
this.nodes[level][index] = node
for (let i = levelStartIndex; i < levelEndIndex; i += 1) {
if (i < this.nodes[level].length) {
children.push(this.nodes[level][i])
} else {
children.push(this.zeroes[level])
}
}
node = this.hashFn(children)
index = Math.floor(index / this.arity)
}
this.root = node
}
delete (index: number) {
this.update(index, this.zeroValue)
}
update (index: number, newLeaf: any) {
if (index < 0 || index >= this.nodes[0].length) {
throw new Error('out of bounds')
}
let node = newLeaf
for (let level = 0; level < this.depth; level += 1) {
const position = index % this.arity
const levelStartIndex = index - position
const levelEndIndex = levelStartIndex + this.arity
const children = []
this.nodes[level][index] = node
for (let i = levelStartIndex; i < levelEndIndex; i += 1) {
if (i < this.nodes[level].length) {
children.push(this.nodes[level][i])
} else {
children.push(this.zeroes[level])
}
}
node = this.hashFn(children)
index = Math.floor(index / this.arity)
}
this.root = node
}
getDepth (): number {
return this.depth
}
getArity (): number {
return this.arity
}
getMaxLeaves (): number {
return this.depth ** this.arity
}
indexOf (leaf: any): number {
return this.nodes[0].indexOf(leaf)
}
getLeaves () {
const leaves = this.copyList(this.nodes[0])
const index = this.nodes[0].length
for (let i = index; i < this.getMaxLeaves(); i++) {
leaves[i] = this.zeroValue
}
return leaves
}
copyList (list: any[]) {
return list.map((x: any) => BigInt(x))
}
getLayers ():any[] {
const layers = []
for (const list of this.nodes) {
layers.push(this.copyList(list))
}
if (layers[0].length < this.getMaxLeaves()) {
let index = layers[0].length
for (let i = index; i < this.getMaxLeaves(); i++) {
layers[0][i] = this.zeroValue
}
for (let level = 0; level < this.depth; level++) {
const position = index % this.arity
const levelStartIndex = index - position
const levelEndIndex = levelStartIndex + this.arity
for (let i = levelStartIndex; i < levelEndIndex; i++) {
if (i >= layers[level].length) {
layers[level][i] = this.zeroes[level]
}
}
index = Math.floor(index / this.arity)
}
}
layers.push([this.root])
return layers
}
getHexLayers ():string[] {
return this.getLayers().reduce((acc: string[][], item: Buffer[]) => {
if (Array.isArray(item)) {
acc.push(item.map(layer => this.bufferToHex(this.bufferify(layer))))
} else {
acc.push(item)
}
return acc
}, [])
}
getLayersAsObject ():any {
const layers: any[] = this.getLayers().map((layer: any) => layer.map((value: any) => this.bufferToHex(this.bufferify(value), false)))
const objs = []
for (let i = 0; i < layers.length; i++) {
const arr = []
for (let j = 0; j < layers[i].length; j++) {
const obj = { [layers[i][j]]: null }
if (objs.length) {
obj[layers[i][j]] = {}
const a = objs.shift()
const akey = Object.keys(a)[0]
obj[layers[i][j]][akey] = a[akey]
if (objs.length) {
const b = objs.shift()
const bkey = Object.keys(b)[0]
obj[layers[i][j]][bkey] = b[bkey]
}
}
arr.push(obj)
}
objs.push(...arr)
}
return objs[0]
}
computeRoot () {
let node : any
let index = this.nodes[0].length
for (let level = 0; level < this.depth; level += 1) {
const position = index % this.arity
const levelStartIndex = index - position
const levelEndIndex = levelStartIndex + this.arity
const children = []
for (let i = levelStartIndex; i < levelEndIndex; i += 1) {
if (i < this.nodes[level].length) {
children.push(this.nodes[level][i])
} else {
children.push(this.zeroes[level])
}
}
node = this.hashFn(children)
index = Math.floor(index / this.arity)
}
return node
}
getProof (index: number): any {
if (index < 0 || index >= this.nodes[0].length) {
throw new Error('The leaf does not exist in this tree')
}
const siblings: Node[][] = []
const pathIndices: number[] = []
const leafIndex = index
for (let level = 0; level < this.depth; level += 1) {
const position = index % this.arity
const levelStartIndex = index - position
const levelEndIndex = levelStartIndex + this.arity
pathIndices[level] = position
siblings[level] = []
for (let i = levelStartIndex; i < levelEndIndex; i += 1) {
if (i !== index) {
if (i < this.nodes[level].length) {
siblings[level].push(this.nodes[level][i])
} else {
siblings[level].push(this.zeroes[level])
}
}
}
index = Math.floor(index / this.arity)
}
return { root: this.root, leaf: this.nodes[0][leafIndex], pathIndices, siblings }
}
verify (proof: any): boolean {
let node = proof.leaf
for (let i = 0; i < proof.siblings.length; i += 1) {
const children = proof.siblings[i].slice()
children.splice(proof.pathIndices[i], 0, node)
node = this.hashFn(children)
}
return proof.root === node
}
toString ():string {
return this.toTreeString()
}
protected toTreeString ():string {
const obj = this.getLayersAsObject()
return treeify.asTree(obj, true)
}
}
if (typeof window !== 'undefined') {
;(window as any).IncrementalMerkleTree = IncrementalMerkleTree
}
export default IncrementalMerkleTree

View File

@ -305,7 +305,7 @@ export class MerkleMountainRange extends Base {
// find the mountain where the target index belongs to
let cursor = 0
let targetPeak
let targetPeak : number
const peakIndexes = this.getPeakIndexes(width)
for (let i = 0; i < peakIndexes.length; i++) {
@ -341,7 +341,7 @@ export class MerkleMountainRange extends Base {
}
// calculate the summit hash climbing up again
let node
let node : any
while (height < path.length) {
// move cursor
cursor = path[height]
@ -489,4 +489,8 @@ export class MerkleMountainRange extends Base {
}
}
if (typeof window !== 'undefined') {
;(window as any).MerkleMountainRange = MerkleMountainRange
}
export default MerkleMountainRange

View File

@ -5,7 +5,7 @@ import treeify from 'treeify'
import Base from './Base'
// TODO: Clean up and DRY up code
// Disclaimer: The multiproof code is unaudited and may possibly contain serious issues. It's in a hacky state as is and it's begging for a rewrite!
// Disclaimer: The multiproof code is unaudited and may possibly contain serious issues. It's in a hacky state as is and needs to be rewritten.
type TValue = Buffer | BigInt | string | number | null | undefined
type THashFnResult = Buffer | string
@ -150,11 +150,11 @@ export class MerkleTree extends Base {
}
}
this.layers = [this.leaves]
this._createHashes(this.leaves)
this.createHashes(this.leaves)
}
private _createHashes (nodes: any[]) {
private createHashes (nodes: any[]) {
this.layers = [nodes]
while (nodes.length > 1) {
const layerIndex = this.layers.length
@ -273,7 +273,7 @@ export class MerkleTree extends Base {
}
}
return this.leaves.filter(leaf => this._bufferIndexOf(values, leaf, this.sortLeaves) !== -1)
return this.leaves.filter(leaf => this.bufferIndexOf(values, leaf, this.sortLeaves) !== -1)
}
return this.leaves
@ -920,7 +920,7 @@ export class MerkleTree extends Base {
els = els.sort(Buffer.compare)
}
let ids = els.map((el) => this._bufferIndexOf(this.leaves, el, this.sortLeaves)).sort((a, b) => a === b ? 0 : a > b ? 1 : -1)
let ids = els.map((el) => this.bufferIndexOf(this.leaves, el, this.sortLeaves)).sort((a, b) => a === b ? 0 : a > b ? 1 : -1)
if (!ids.every((idx) => idx !== -1)) {
throw new Error('Element does not exist in Merkle tree')
}
@ -933,7 +933,7 @@ export class MerkleTree extends Base {
const layer = this.layers[i]
for (let j = 0; j < ids.length; j++) {
const idx = ids[j]
const pairElement = this._getPairNode(layer, idx)
const pairElement = this.getPairNode(layer, idx)
hashes.push(layer[idx])
if (pairElement) {
@ -950,7 +950,7 @@ export class MerkleTree extends Base {
return proof.filter((value) => !hashes.includes(value))
}
return this.getProofIndices(indices, this._log2((tree.length / 2) | 0)).map(index => tree[index])
return this.getProofIndices(indices, Math.log2((tree.length / 2) | 0)).map(index => tree[index])
}
private getMultiProofForUnevenTree (tree?: any[], indices?: any[]):Buffer[] {
@ -1043,7 +1043,7 @@ export class MerkleTree extends Base {
if (leaves.every(Number.isInteger)) {
ids = [...leaves].sort((a, b) => a === b ? 0 : a > b ? 1 : -1) // Indices where passed
} else {
ids = leaves.map((el) => this._bufferIndexOf(this.leaves, el, this.sortLeaves)).sort((a, b) => a === b ? 0 : a > b ? 1 : -1)
ids = leaves.map((el) => this.bufferIndexOf(this.leaves, el, this.sortLeaves)).sort((a, b) => a === b ? 0 : a > b ? 1 : -1)
}
if (!ids.every((idx: number) => idx !== -1)) {
@ -1059,7 +1059,7 @@ export class MerkleTree extends Base {
ids = ids.reduce((ids, idx) => {
const skipped = tested.includes(layer[idx])
if (!skipped) {
const pairElement = this._getPairNode(layer, idx)
const pairElement = this.getPairNode(layer, idx)
const proofUsed = _proofs.includes(layer[idx]) || _proofs.includes(pairElement)
pairElement && flags.push(!proofUsed)
tested.push(layer[idx])
@ -1186,10 +1186,10 @@ export class MerkleTree extends Base {
proof = (proof as any[]).map(leaf => this.bufferify(leaf))
const tree = {}
for (const [index, leaf] of this._zip(proofIndices, proofLeaves)) {
for (const [index, leaf] of this.zip(proofIndices, proofLeaves)) {
tree[(2 ** depth) + index] = leaf
}
for (const [index, proofitem] of this._zip(this.getProofIndices(proofIndices, depth), proof)) {
for (const [index, proofitem] of this.zip(this.getProofIndices(proofIndices, depth), proof)) {
tree[index] = proofitem
}
let indexqueue = Object.keys(tree).map(value => +value).sort((a, b) => a - b)
@ -1360,7 +1360,7 @@ export class MerkleTree extends Base {
*const node = tree.getPairNode(layer, index)
*```
*/
private _getPairNode (layer: Buffer[], idx: number):Buffer {
private getPairNode (layer: Buffer[], idx: number):Buffer {
const pairIdx = idx % 2 === 0 ? idx + 1 : idx - 1
if (pairIdx < layer.length) {
@ -1379,7 +1379,7 @@ export class MerkleTree extends Base {
*console.log(tree.toTreeString())
*```
*/
protected _toTreeString ():string {
protected toTreeString ():string {
const obj = this.getLayersAsObject()
return treeify.asTree(obj, true)
}
@ -1393,7 +1393,7 @@ export class MerkleTree extends Base {
*```
*/
toString ():string {
return this._toTreeString()
return this.toTreeString()
}
isUnevenTree (treeLayers?: any[]) {
@ -1406,7 +1406,7 @@ export class MerkleTree extends Base {
}
private calculateRootForUnevenTree (leafIndices: number[], leafHashes: any[], totalLeavesCount: number, proofHashes: any[]) {
const leafTuples = this._zip(leafIndices, leafHashes).sort(([indexA], [indexB]) => indexA - indexB)
const leafTuples = this.zip(leafIndices, leafHashes).sort(([indexA], [indexB]) => indexA - indexB)
const leafTupleIndices = leafTuples.map(([index]) => index)
const proofIndices = this.getProofIndicesForUnevenTree(leafTupleIndices, totalLeavesCount)
@ -1416,7 +1416,7 @@ export class MerkleTree extends Base {
const indices = proofIndices[i]
const sliceStart = nextSliceStart
nextSliceStart += indices.length
proofTuplesByLayers[i] = this._zip(indices, proofHashes.slice(sliceStart, nextSliceStart))
proofTuplesByLayers[i] = this.zip(indices, proofHashes.slice(sliceStart, nextSliceStart))
}
const tree = [leafTuples]

View File

@ -1,4 +1,5 @@
import MerkleTree from './MerkleTree'
export { MerkleTree }
export { MerkleMountainRange } from './MerkleMountainRange'
export { IncrementalMerkleTree } from './IncrementalMerkleTree'
export default MerkleTree

View File

@ -0,0 +1,205 @@
const test = require('tape')
const { IncrementalMerkleTree } = require('../')
const { buildPoseidon } = require('circomlibjs')
test('poseidon - 2 depth 2 arity', async t => {
t.plan(18)
const _poseidon = await buildPoseidon()
const poseidon = (inputs) => {
const hash = _poseidon(inputs.map(IncrementalMerkleTree.bigNumberify))
const bn = IncrementalMerkleTree.bigNumberify(_poseidon.F.toString(hash))
return bn
}
const tree = new IncrementalMerkleTree(poseidon, {
depth: 2,
arity: 2,
zeroValue: BigInt(0)
})
t.equal(tree.getDepth(), 2)
t.equal(tree.getArity(), 2)
t.equal(tree.getMaxLeaves(), 4)
t.equal(tree.getHexRoot(), '0x1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1')
tree.insert(poseidon([BigInt(1)]))
t.equal(tree.getHexRoot(), '0x19da8f56a40748020782233bc94fd32e81ba9bb9884e8848310878aa205b0497')
t.deepEqual(tree.getLayers(),
[
[
18586133768512220936620570745912940619677854269274689475585506675881198879027n,
0n,
0n,
0n
],
[
5094515486147324152810396339294786824839256615363920109013032939290670981070n,
14744269619966411208579211824598458697587494354926760081771325075741142829156n
],
[
11693983160260563097655073427752835408055631740894534147682792587184540681367n
]
]
)
tree.insert(poseidon([BigInt(2)]))
t.equal(tree.getHexRoot(), '0x2c2ea920619c56f8dba3b19e5c3d76d346527e772ef6d90ef0dd323631ef1cb6')
t.equal(tree.indexOf(poseidon([BigInt(2)])), 1)
tree.delete(1)
t.equal(tree.getHexRoot(), '0x19da8f56a40748020782233bc94fd32e81ba9bb9884e8848310878aa205b0497')
tree.update(0, poseidon([BigInt(3)]))
t.equal(tree.getHexRoot(), '0x2e94d2b74c9ea1cafeb6da975a5475e7d4c848e6cb3346484b146d5cfaec87eb')
tree.update(1, poseidon([BigInt(2)]))
t.deepEqual(tree.getLeaves(),
[
6018413527099068561047958932369318610297162528491556075919075208700178480084n,
8645981980787649023086883978738420856660271013038108762834452721572614684349n,
0n,
0n
]
)
t.deepEqual(tree.getLayers(),
[
[
6018413527099068561047958932369318610297162528491556075919075208700178480084n,
8645981980787649023086883978738420856660271013038108762834452721572614684349n,
0n,
0n
],
[
14909064445584595308539830952419236478129618691160103903001052664000042483490n,
14744269619966411208579211824598458697587494354926760081771325075741142829156n
],
[
3510912107467918110461523845783070983430853155915191132694596979334180474120n
]
])
tree.insert(poseidon([BigInt(3)]))
t.deepEqual(tree.getLayers(),
[
[
6018413527099068561047958932369318610297162528491556075919075208700178480084n,
8645981980787649023086883978738420856660271013038108762834452721572614684349n,
6018413527099068561047958932369318610297162528491556075919075208700178480084n,
0n
],
[
14909064445584595308539830952419236478129618691160103903001052664000042483490n,
21239441820082410876343833288590122027808783310040459823992255344659808702818n
],
[
13634681385965571274925238151540568262573782028276541919047631799812805578309n
]
])
tree.insert(poseidon([BigInt(4)]))
t.deepEqual(tree.getLayers(),
[
[
6018413527099068561047958932369318610297162528491556075919075208700178480084n,
8645981980787649023086883978738420856660271013038108762834452721572614684349n,
6018413527099068561047958932369318610297162528491556075919075208700178480084n,
9900412353875306532763997210486973311966982345069434572804920993370933366268n
],
[
14909064445584595308539830952419236478129618691160103903001052664000042483490n,
15866811995824089293749468808478915337040145970836273016636380754543464442080n
],
[
16131156821127350901643174230980638228438939582106721266118265564186720968083n
]
])
t.equal(tree.getRoot(), 16131156821127350901643174230980638228438939582106721266118265564186720968083n)
t.equal(tree.getHexRoot(), '0x23a9e944fc7d734b6ef70b73c9ecc9ae97051b709c29f41339b039b701e99d93')
t.deepEqual(tree.getLayersAsObject(),
{
'23a9e944fc7d734b6ef70b73c9ecc9ae97051b709c29f41339b039b701e99d93': {
'20f63b3f6cf280e6a4a488a825d7fdc948ee0a02a2714a532f6d0e747bbfbf22': {
d4e4d24b890fe6799be4cf57ad13078ec0fbaa9fe91423ba8bbd0c2d7043bd: null,
'131d73cf6b30079aca0dff6a561cd0ee50b540879abe379a25a06b24bde2bebd': null
},
'23144c1e7794f62515c2ccbaee3076d2e40b673fcba5da8a6457387e054068e0': {
d4e4d24b890fe6799be4cf57ad13078ec0fbaa9fe91423ba8bbd0c2d7043bd: null,
'15e36f4ff92e2211fa8ed9f7af707f6c8c0f1442252a85150d2b8d2038890dfc': null
}
}
}
)
t.equal(tree.toString(),
`└─ 23a9e944fc7d734b6ef70b73c9ecc9ae97051b709c29f41339b039b701e99d93
20f63b3f6cf280e6a4a488a825d7fdc948ee0a02a2714a532f6d0e747bbfbf22
d4e4d24b890fe6799be4cf57ad13078ec0fbaa9fe91423ba8bbd0c2d7043bd
131d73cf6b30079aca0dff6a561cd0ee50b540879abe379a25a06b24bde2bebd
23144c1e7794f62515c2ccbaee3076d2e40b673fcba5da8a6457387e054068e0
d4e4d24b890fe6799be4cf57ad13078ec0fbaa9fe91423ba8bbd0c2d7043bd
15e36f4ff92e2211fa8ed9f7af707f6c8c0f1442252a85150d2b8d2038890dfc
`)
})
test('poseidon - 2 depth 3 arity', async t => {
t.plan(3)
const _poseidon = await buildPoseidon()
const poseidon = (inputs) => {
const hash = _poseidon(inputs.map(IncrementalMerkleTree.bigNumberify))
const bn = IncrementalMerkleTree.bigNumberify(_poseidon.F.toString(hash))
return bn
}
const tree = new IncrementalMerkleTree(poseidon, {
depth: 2,
arity: 3,
zeroValue: BigInt(0)
})
t.equal(tree.getDepth(), 2)
t.equal(tree.getArity(), 3)
tree.insert(poseidon([BigInt(1)]))
tree.insert(poseidon([BigInt(2)]))
tree.insert(poseidon([BigInt(3)]))
tree.insert(poseidon([BigInt(4)]))
tree.insert(poseidon([BigInt(5)]))
tree.insert(poseidon([BigInt(6)]))
tree.insert(poseidon([BigInt(7)]))
tree.insert(poseidon([BigInt(8)]))
t.equal(tree.getHexRoot(), '0xe38e8da4dd7c981fb9e47ca06a88447d3111a3796e2ed8ecc0c80c341b945a')
})
test('poseidon - proof', async t => {
t.plan(4)
const _poseidon = await buildPoseidon()
const poseidon = (inputs) => {
const hash = _poseidon(inputs.map(IncrementalMerkleTree.bigNumberify))
const bn = IncrementalMerkleTree.bigNumberify(_poseidon.F.toString(hash))
return bn
}
const tree = new IncrementalMerkleTree(poseidon, {
depth: 2,
arity: 2,
zeroValue: BigInt(0)
})
t.equal(tree.getDepth(), 2)
t.equal(tree.getArity(), 2)
tree.insert(poseidon([BigInt(1)]))
tree.insert(poseidon([BigInt(2)]))
tree.insert(poseidon([BigInt(3)]))
tree.insert(poseidon([BigInt(4)]))
const proof = tree.getProof(2)
t.deepEqual(proof,
{
root: 4924824719679653695544344112002466960362482050425504983922056625160325123496n,
leaf: 6018413527099068561047958932369318610297162528491556075919075208700178480084n,
pathIndices: [0, 1],
siblings: [
[
9900412353875306532763997210486973311966982345069434572804920993370933366268n
],
[
10058687713083746196667355667918512760470030038024584531967182749893253193558n
]
]
}
)
t.true(tree.verify(proof))
})

View File

@ -1327,10 +1327,10 @@ test.skip('1M leaves keccak256', t => {
test('poseidon hash', async t => {
t.plan(4)
const _poseidon = await buildPoseidon()
const poseidon = await buildPoseidon()
const poseidonHash = (inputs) => {
const hash = _poseidon(inputs.map(MerkleTree.bigNumberify))
const bn = MerkleTree.bigNumberify(_poseidon.F.toString(hash))
const hash = poseidon(inputs.map(MerkleTree.bigNumberify))
const bn = MerkleTree.bigNumberify(poseidon.F.toString(hash))
return MerkleTree.bufferify(bn)
}