mirror of
https://github.com/tornadocash/fixed-merkle-tree.git
synced 2024-11-27 20:20:12 +01:00
initial typescript edit
This commit is contained in:
parent
e3c54ea818
commit
4501cae4d6
65
.eslintrc
65
.eslintrc
@ -1,26 +1,57 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"mocha": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"ignorePatterns": [
|
||||
"test/*.spec.ts",
|
||||
"lib"
|
||||
],
|
||||
"rules": {
|
||||
"indent": ["error", 2],
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"quotes": ["error", "single"],
|
||||
"semi": ["error", "never"],
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/consistent-type-definitions": [
|
||||
"error",
|
||||
"type"
|
||||
],
|
||||
"indent": [
|
||||
"error",
|
||||
2
|
||||
],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
],
|
||||
"semi": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"object-curly-spacing": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"comma-dangle": [
|
||||
"error",
|
||||
"always-multiline"
|
||||
],
|
||||
"require-await": "error"
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
}
|
||||
}
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1 +1,5 @@
|
||||
node_modules
|
||||
build
|
||||
lib
|
||||
yarn-error.log
|
||||
.idea
|
||||
|
5454
package-lock.json
generated
5454
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
19
package.json
19
package.json
@ -3,9 +3,11 @@
|
||||
"version": "0.6.1",
|
||||
"description": "Fixed depth merkle tree implementation with sequential inserts",
|
||||
"repository": "https://github.com/tornadocash/fixed-merkle-tree.git",
|
||||
"main": "src/merkleTree.js",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"test": "mocha",
|
||||
"test": "ts-mocha 'test/*.spec.ts'",
|
||||
"build": "tsc",
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"keywords": [
|
||||
@ -19,13 +21,18 @@
|
||||
"src/*"
|
||||
],
|
||||
"dependencies": {
|
||||
"snarkjs": "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5",
|
||||
"circomlib": "git+https://github.com/tornadocash/circomlib.git#5beb6aee94923052faeecea40135d45b6ce6172c"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^10.1.0",
|
||||
"@types/expect": "^24.3.0",
|
||||
"@types/mocha": "^9.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.0",
|
||||
"@typescript-eslint/parser": "^5.12.0",
|
||||
"chai": "^4.2.0",
|
||||
"eslint": "^7.5.0",
|
||||
"mocha": "^8.1.0"
|
||||
"eslint": "^8.9.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"mocha": "^9.2.1",
|
||||
"ts-mocha": "^9.0.2",
|
||||
"typescript": "^4.5.5"
|
||||
}
|
||||
}
|
||||
|
@ -1,34 +1,28 @@
|
||||
import { mimcsponge } from 'circomlib'
|
||||
|
||||
// keccak256("tornado") % BN254_FIELD_SIZE
|
||||
const DEFAULT_ZERO = '21663839004416932945382355908790599225266501822907911457504978515578255421292'
|
||||
const defaultHash = require('./mimc')
|
||||
|
||||
// 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
|
||||
const defaultHash = (left: Element, right: Element): string => mimcsponge.multiHash([BigInt(left), BigInt(right)]).toString()
|
||||
|
||||
/**
|
||||
* @callback hashFunction
|
||||
* @param left Left leaf
|
||||
* @param right Right leaf
|
||||
*/
|
||||
/**
|
||||
* Merkle tree
|
||||
*/
|
||||
class MerkleTree {
|
||||
/**
|
||||
* Constructor
|
||||
* @param {number} levels Number of levels in the tree
|
||||
* @param {Array} [elements] Initial elements
|
||||
* @param {Object} options
|
||||
* @param {hashFunction} [options.hashFunction] Function used to hash 2 leaves
|
||||
* @param [options.zeroElement] Value for non-existent leaves
|
||||
*/
|
||||
constructor(levels, elements = [], { hashFunction, zeroElement = DEFAULT_ZERO } = {}) {
|
||||
export default class MerkleTree {
|
||||
levels: number
|
||||
capacity: number
|
||||
private _hash: HashFunction
|
||||
private zeroElement: Element
|
||||
private _zeros: Element[]
|
||||
private _layers: Array<Element[]>
|
||||
|
||||
constructor(levels: number, elements: Element[] = [], {
|
||||
hashFunction = defaultHash,
|
||||
zeroElement = DEFAULT_ZERO,
|
||||
}: MerkleTreeOptions = {}) {
|
||||
this.levels = levels
|
||||
this.capacity = 2 ** levels
|
||||
if (elements.length > this.capacity) {
|
||||
throw new Error('Tree is full')
|
||||
}
|
||||
this._hash = hashFunction || defaultHash
|
||||
this._hash = hashFunction
|
||||
this.zeroElement = zeroElement
|
||||
this._zeros = []
|
||||
this._zeros[0] = zeroElement
|
||||
@ -56,17 +50,16 @@ class MerkleTree {
|
||||
|
||||
/**
|
||||
* Get tree root
|
||||
* @returns {*}
|
||||
*/
|
||||
root() {
|
||||
return this._layers[this.levels].length > 0 ? this._layers[this.levels][0] : this._zeros[this.levels]
|
||||
root(): string {
|
||||
return `${this._layers[this.levels].length > 0 ? this._layers[this.levels][0] : this._zeros[this.levels]}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert new element into the tree
|
||||
* @param element Element to insert
|
||||
*/
|
||||
insert(element) {
|
||||
insert(element: Element) {
|
||||
if (this._layers[0].length >= this.capacity) {
|
||||
throw new Error('Tree is full')
|
||||
}
|
||||
@ -77,7 +70,7 @@ class MerkleTree {
|
||||
* Insert multiple elements into the tree.
|
||||
* @param {Array} elements Elements to insert
|
||||
*/
|
||||
bulkInsert(elements) {
|
||||
bulkInsert(elements: Element[]) {
|
||||
if (!elements.length) {
|
||||
return
|
||||
}
|
||||
@ -109,7 +102,7 @@ class MerkleTree {
|
||||
* @param {number} index Index of element to change
|
||||
* @param element Updated element value
|
||||
*/
|
||||
update(index, element) {
|
||||
update(index: number, element: Element) {
|
||||
if (isNaN(Number(index)) || index < 0 || index > this._layers[0].length || index >= this.capacity) {
|
||||
throw new Error('Insert index out of bounds: ' + index)
|
||||
}
|
||||
@ -130,17 +123,18 @@ class MerkleTree {
|
||||
* @param {number} index Leaf index to generate path for
|
||||
* @returns {{pathElements: Object[], pathIndex: number[]}} An object containing adjacent elements and left-right index
|
||||
*/
|
||||
path(index) {
|
||||
path(index: Element) {
|
||||
if (isNaN(Number(index)) || index < 0 || index >= this._layers[0].length) {
|
||||
throw new Error('Index out of bounds: ' + index)
|
||||
}
|
||||
const pathElements = []
|
||||
const pathIndices = []
|
||||
let elIndex = +index
|
||||
const pathElements: Element[] = []
|
||||
const pathIndices: number[] = []
|
||||
for (let level = 0; level < this.levels; level++) {
|
||||
pathIndices[level] = index % 2
|
||||
pathIndices[level] = elIndex % 2
|
||||
pathElements[level] =
|
||||
(index ^ 1) < this._layers[level].length ? this._layers[level][index ^ 1] : this._zeros[level]
|
||||
index >>= 1
|
||||
(elIndex ^ 1) < this._layers[level].length ? this._layers[level][elIndex ^ 1] : this._zeros[level]
|
||||
elIndex >>= 1
|
||||
}
|
||||
return {
|
||||
pathElements,
|
||||
@ -154,17 +148,16 @@ class MerkleTree {
|
||||
* @param comparator A function that checks leaf value equality
|
||||
* @returns {number} Index if element is found, otherwise -1
|
||||
*/
|
||||
indexOf(element, comparator) {
|
||||
indexOf(element: Element, comparator?: <T, R> (arg0: T, arg1: T) => R): number {
|
||||
if (comparator) {
|
||||
return this._layers[0].findIndex((el) => comparator(element, el))
|
||||
return this._layers[0].findIndex((el) => comparator<Element, number>(element, el))
|
||||
} else {
|
||||
return this._layers[0].indexOf(element)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of non-zero tree elements
|
||||
* @returns {Object[]}
|
||||
* Returns a copy of non-zero tree elements.
|
||||
*/
|
||||
elements() {
|
||||
return this._layers[0].slice()
|
||||
@ -172,7 +165,6 @@ class MerkleTree {
|
||||
|
||||
/**
|
||||
* Returns a copy of n-th zero elements array
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
zeros() {
|
||||
return this._zeros.slice()
|
||||
@ -183,7 +175,7 @@ class MerkleTree {
|
||||
* Deserializing it back will not require to recompute any hashes
|
||||
* Elements are not converted to a plain type, this is responsibility of the caller
|
||||
*/
|
||||
serialize() {
|
||||
serialize(): SerializedTreeState {
|
||||
return {
|
||||
levels: this.levels,
|
||||
_zeros: this._zeros,
|
||||
@ -195,18 +187,27 @@ class MerkleTree {
|
||||
* Deserialize data into a MerkleTree instance
|
||||
* Make sure to provide the same hashFunction as was used in the source tree,
|
||||
* otherwise the tree state will be invalid
|
||||
*
|
||||
* @param data
|
||||
* @param hashFunction
|
||||
* @returns {MerkleTree}
|
||||
*/
|
||||
static deserialize(data, hashFunction) {
|
||||
const instance = Object.assign(Object.create(this.prototype), data)
|
||||
instance._hash = hashFunction || defaultHash
|
||||
instance.capacity = 2 ** instance.levels
|
||||
instance.zeroElement = instance._zeros[0]
|
||||
return instance
|
||||
static deserialize(data: SerializedTreeState, hashFunction?: HashFunction): MerkleTree {
|
||||
return new MerkleTree(data.levels, data._layers[0], { hashFunction, zeroElement: data._zeros[0] })
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MerkleTree
|
||||
export type HashFunction = {
|
||||
(left: string | number, right: string | number): string
|
||||
}
|
||||
export type MerkleTreeOptions = {
|
||||
hashFunction?: HashFunction
|
||||
zeroElement?: Element
|
||||
}
|
||||
|
||||
export type Element = string | number
|
||||
|
||||
export type SerializedTreeState = {
|
||||
levels: number,
|
||||
_zeros: Array<Element>,
|
||||
_layers: Array<Element[]>
|
||||
}
|
||||
export type Mimcsponge = {
|
||||
multiHash: (arr: BigInt[], key?: Element, numOutputs?) => string
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
const { mimcsponge } = require('circomlib')
|
||||
const { bigInt } = require('snarkjs')
|
||||
module.exports = (left, right) => mimcsponge.multiHash([bigInt(left), bigInt(right)]).toString()
|
@ -1,26 +1,28 @@
|
||||
const MerkleTree = require('../src/merkleTree')
|
||||
require('chai').should()
|
||||
import MerkleTree from '../src'
|
||||
import { assert, should } from 'chai'
|
||||
|
||||
describe('MerkleTree', () => {
|
||||
|
||||
describe('#constructor', () => {
|
||||
|
||||
it('should have correct zero root', () => {
|
||||
const tree = new MerkleTree(10)
|
||||
return tree.root().should.equal('14030416097908897320437553787826300082392928432242046897689557706485311282736')
|
||||
const tree = new MerkleTree(10, [])
|
||||
return should().equal(tree.root(), '14030416097908897320437553787826300082392928432242046897689557706485311282736')
|
||||
})
|
||||
|
||||
it('should have correct 1 element root', () => {
|
||||
const tree = new MerkleTree(10, [1])
|
||||
tree.root().should.equal('8423266420989796135179818298985240707844287090553672312129988553683991994663')
|
||||
should().equal(tree.root(), '8423266420989796135179818298985240707844287090553672312129988553683991994663')
|
||||
})
|
||||
|
||||
it('should have correct even elements root', () => {
|
||||
const tree = new MerkleTree(10, [1, 2])
|
||||
tree.root().should.equal('6632020347849276860492323008882350357301732786233864934344775324188835172576')
|
||||
should().equal(tree.root(), '6632020347849276860492323008882350357301732786233864934344775324188835172576')
|
||||
})
|
||||
|
||||
it('should have correct odd elements root', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3])
|
||||
tree.root().should.equal('13605252518346649016266481317890801910232739395710162921320863289825142055129')
|
||||
should().equal(tree.root(), '13605252518346649016266481317890801910232739395710162921320863289825142055129')
|
||||
})
|
||||
|
||||
it('should be able to create a full tree', () => {
|
||||
@ -29,7 +31,7 @@ describe('MerkleTree', () => {
|
||||
|
||||
it('should fail to create tree with too many elements', () => {
|
||||
const call = () => new MerkleTree(2, [1, 2, 3, 4, 5])
|
||||
call.should.throw('Tree is full')
|
||||
should().throw(call, 'Tree is full')
|
||||
})
|
||||
})
|
||||
|
||||
@ -37,19 +39,19 @@ describe('MerkleTree', () => {
|
||||
it('should insert into empty tree', () => {
|
||||
const tree = new MerkleTree(10)
|
||||
tree.insert(42)
|
||||
tree.root().should.equal('5305397050004975530787056746976521882221645950652996479084366175595194436378')
|
||||
should().equal(tree.root(), '5305397050004975530787056746976521882221645950652996479084366175595194436378')
|
||||
})
|
||||
|
||||
it('should insert into odd tree', () => {
|
||||
const tree = new MerkleTree(10, [1])
|
||||
tree.insert(42)
|
||||
tree.root().should.equal('4732716818150428188641303198013632061441036732749853605989871103991103096471')
|
||||
should().equal(tree.root(), '4732716818150428188641303198013632061441036732749853605989871103991103096471')
|
||||
})
|
||||
|
||||
it('should insert into even tree', () => {
|
||||
const tree = new MerkleTree(10, [1, 2])
|
||||
tree.insert(42)
|
||||
tree.root().should.equal('6204016789747878948181936326719724987136198810274146408545977300318734508764')
|
||||
should().equal(tree.root(), '6204016789747878948181936326719724987136198810274146408545977300318734508764')
|
||||
})
|
||||
|
||||
it('should insert last element', () => {
|
||||
@ -60,7 +62,7 @@ describe('MerkleTree', () => {
|
||||
it('should fail to insert when tree is full', () => {
|
||||
const tree = new MerkleTree(2, [1, 2, 3, 4])
|
||||
const call = () => tree.insert(5)
|
||||
call.should.throw('Tree is full')
|
||||
should().throw(call, 'Tree is full')
|
||||
})
|
||||
})
|
||||
|
||||
@ -68,7 +70,7 @@ describe('MerkleTree', () => {
|
||||
it('should work', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3])
|
||||
tree.bulkInsert([4, 5, 6])
|
||||
tree.root().should.equal('10132905325673518287563057607527946096399700874345297651940963130460267058606')
|
||||
should().equal(tree.root(), '10132905325673518287563057607527946096399700874345297651940963130460267058606')
|
||||
})
|
||||
|
||||
it('should give the same result as sequental inserts', () => {
|
||||
@ -92,7 +94,7 @@ describe('MerkleTree', () => {
|
||||
for (const item of inserted) {
|
||||
tree2.insert(item)
|
||||
}
|
||||
tree1.root().should.equal(tree2.root())
|
||||
should().equal(tree1.root(), tree2.root())
|
||||
}
|
||||
}
|
||||
}).timeout(10000)
|
||||
@ -105,7 +107,7 @@ describe('MerkleTree', () => {
|
||||
it('should fail to insert too many elements', () => {
|
||||
const tree = new MerkleTree(2, [1, 2])
|
||||
const call = () => tree.bulkInsert([3, 4, 5])
|
||||
call.should.throw('Tree is full')
|
||||
should().throw(call, 'Tree is full')
|
||||
})
|
||||
})
|
||||
|
||||
@ -113,56 +115,57 @@ describe('MerkleTree', () => {
|
||||
it('should update first element', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4, 5])
|
||||
tree.update(0, 42)
|
||||
tree.root().should.equal('153077538697962715163231177553585573790587443799974092612333826693999310199')
|
||||
should().equal(tree.root(), '153077538697962715163231177553585573790587443799974092612333826693999310199')
|
||||
})
|
||||
|
||||
it('should update last element', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4, 5])
|
||||
tree.update(4, 42)
|
||||
tree.root().should.equal('1955192134603843666100093417117434845771298375724087600313714421260719033775')
|
||||
should().equal(tree.root(), '1955192134603843666100093417117434845771298375724087600313714421260719033775')
|
||||
})
|
||||
|
||||
it('should update odd element', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4, 5])
|
||||
tree.update(1, 42)
|
||||
tree.root().should.equal('6642888742811380760154112624880866754768235565211186414088321870395007150538')
|
||||
should().equal(tree.root(), '6642888742811380760154112624880866754768235565211186414088321870395007150538')
|
||||
})
|
||||
|
||||
it('should update even element', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4, 5])
|
||||
tree.update(2, 42)
|
||||
tree.root().should.equal('11739358667442647096377238675718917508981868161724701476635082606510350785683')
|
||||
should().equal(tree.root(), '11739358667442647096377238675718917508981868161724701476635082606510350785683')
|
||||
})
|
||||
|
||||
it('should update extra element', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4])
|
||||
tree.update(4, 5)
|
||||
tree.root().should.equal('6341751103515285836339987888606244815365572869367801108789753151704260302930')
|
||||
should().equal(tree.root(), '6341751103515285836339987888606244815365572869367801108789753151704260302930')
|
||||
})
|
||||
|
||||
it('should fail to update incorrect index', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4, 5]);
|
||||
(() => tree.update(-1, 42)).should.throw('Insert index out of bounds: -1');
|
||||
(() => tree.update(6, 42)).should.throw('Insert index out of bounds: 6');
|
||||
(() => tree.update('qwe', 42)).should.throw('Insert index out of bounds: qwe')
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4, 5])
|
||||
should().throw((() => tree.update(-1, 42)), 'Insert index out of bounds: -1')
|
||||
should().throw((() => tree.update(6, 42)), 'Insert index out of bounds: 6')
|
||||
// @ts-ignore
|
||||
should().throw((() => tree.update('qwe', 42)), 'Insert index out of bounds: qwe')
|
||||
})
|
||||
|
||||
it('should fail to update over capacity', () => {
|
||||
const tree = new MerkleTree(2, [1, 2, 3, 4])
|
||||
const call = () => tree.update(4, 42)
|
||||
call.should.throw('Insert index out of bounds: 4')
|
||||
should().throw(call, 'Insert index out of bounds: 4')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#indexOf', () => {
|
||||
it('should find index', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4, 5])
|
||||
tree.indexOf(3).should.equal(2)
|
||||
should().equal(tree.indexOf(3), 2)
|
||||
})
|
||||
|
||||
it('should return -1 for non existent element', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4, 5])
|
||||
tree.indexOf(42).should.equal(-1)
|
||||
should().equal(tree.indexOf(42), -1)
|
||||
})
|
||||
})
|
||||
|
||||
@ -170,8 +173,8 @@ describe('MerkleTree', () => {
|
||||
it('should work for even index', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4, 5])
|
||||
const path = tree.path(2)
|
||||
path.pathIndices.should.be.deep.equal([0, 1, 0, 0, 0, 0, 0, 0, 0, 0])
|
||||
path.pathElements.should.be.deep.equal([
|
||||
assert.deepEqual(path.pathIndices, [0, 1, 0, 0, 0, 0, 0, 0, 0, 0])
|
||||
assert.deepEqual(path.pathElements, [
|
||||
4,
|
||||
'19814528709687996974327303300007262407299502847885145507292406548098437687919',
|
||||
'21305827034995891902714687670641862055126514524916463201449278400604999416145',
|
||||
@ -188,8 +191,8 @@ describe('MerkleTree', () => {
|
||||
it('should work for odd index', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4, 5])
|
||||
const path = tree.path(3)
|
||||
path.pathIndices.should.be.deep.equal([1, 1, 0, 0, 0, 0, 0, 0, 0, 0])
|
||||
path.pathElements.should.be.deep.equal([
|
||||
assert.deepEqual(path.pathIndices, [1, 1, 0, 0, 0, 0, 0, 0, 0, 0])
|
||||
assert.deepEqual(path.pathElements, [
|
||||
3,
|
||||
'19814528709687996974327303300007262407299502847885145507292406548098437687919',
|
||||
'21305827034995891902714687670641862055126514524916463201449278400604999416145',
|
||||
@ -204,17 +207,17 @@ describe('MerkleTree', () => {
|
||||
})
|
||||
|
||||
it('should fail on incorrect index', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4]);
|
||||
(() => tree.path(-1)).should.throw('Index out of bounds: -1');
|
||||
(() => tree.path(5)).should.throw('Index out of bounds: 5');
|
||||
(() => tree.path('qwe')).should.throw('Index out of bounds: qwe')
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4])
|
||||
should().throw((() => tree.path(-1)), 'Index out of bounds: -1')
|
||||
should().throw((() => tree.path(5)), 'Index out of bounds: 5')
|
||||
should().throw((() => tree.path('qwe')), 'Index out of bounds: qwe')
|
||||
})
|
||||
|
||||
it('should work for correct string index', () => {
|
||||
const tree = new MerkleTree(10, [1, 2, 3, 4, 5])
|
||||
const path = tree.path('2')
|
||||
path.pathIndices.should.be.deep.equal([0, 1, 0, 0, 0, 0, 0, 0, 0, 0])
|
||||
path.pathElements.should.be.deep.equal([
|
||||
assert.deepEqual(path.pathIndices, [0, 1, 0, 0, 0, 0, 0, 0, 0, 0])
|
||||
assert.deepEqual(path.pathElements, [
|
||||
4,
|
||||
'19814528709687996974327303300007262407299502847885145507292406548098437687919',
|
||||
'21305827034995891902714687670641862055126514524916463201449278400604999416145',
|
||||
@ -231,16 +234,15 @@ describe('MerkleTree', () => {
|
||||
|
||||
describe('#serialize', () => {
|
||||
it('should work', () => {
|
||||
const src = new MerkleTree(10, [1, 2, 3])
|
||||
const src = new MerkleTree(10, [1, 2, 3, 4, 5, 6, 7, 8, 9])
|
||||
const data = src.serialize()
|
||||
const dst = MerkleTree.deserialize(data)
|
||||
|
||||
src.root().should.equal(dst.root())
|
||||
should().equal(src.root(), dst.root())
|
||||
|
||||
src.insert(10)
|
||||
dst.insert(10)
|
||||
|
||||
src.root().should.equal(dst.root())
|
||||
should().equal(src.root(), dst.root())
|
||||
})
|
||||
})
|
||||
})
|
26
tsconfig.json
Normal file
26
tsconfig.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"es2019"
|
||||
],
|
||||
"target": "es2018",
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "Node",
|
||||
"outDir": "./lib",
|
||||
"rootDir": "src",
|
||||
"esModuleInterop": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"declaration": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"types",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user