UNPKG

@crpdo/merkle

Version:

A dynamic, in-memory merkle tree implementation in js

238 lines (205 loc) 7.5 kB
const Merkle = require('../lib/merkle') describe('Merkle', () => { let merkle const testValue1 = 'Hello' const testValue2 = 'World' const hashLength = 32 before(() => merkle = new Merkle([testValue1, testValue2])) describe('constructor()', () => { it('should construct properly', () => { expect(merkle).to.be.instanceOf(Merkle) }) it('should compute root correctly', () => { const root = merkle.getRoot() expect(root).to.not.be.null }) it('should append values correctly', () => { const newTestValue = 'Test' merkle.append(newTestValue) expect(merkle.getLeafCount()).to.equal(3) }) it('should retrieve leaf correctly', () => { const leaf = merkle.getLeaf(0) expect(leaf).to.equal(testValue1) }) it('should generate proof correctly', () => { const proof = merkle.getProof(0) expect(proof).to.not.be.null expect(proof).to.have.property('proof') expect(proof.proof).to.be.an('array') expect(proof).to.have.property('target') expect(proof.target).to.be.a('string') expect(proof).to.have.property('index') expect(proof.index).to.be.finite expect(proof).to.have.property('root') expect(proof.root).to.be.a('string') }) it('should verify proof correctly', () => { const proof = merkle.getProof(0) const isVerified = merkle.verifyProof(proof) expect(isVerified).to.be.true }) it('should commit changes correctly', () => { merkle.append('Test') const { root, stack } = merkle.commit() expect(root).to.not.be.null expect(stack).to.not.be.null }) it('should throw an error when committing without a checkpoint', () => { merkle = new Merkle([testValue1, testValue2], false) expect(() => merkle.commit()).to.throw('No checkpoint to commit') }) it('should revert changes correctly', () => { merkle.append('Test') merkle.checkpoint() merkle.append('Another Test') const root = merkle.revert() expect(root).to.equal(merkle.getRoot()) }) it('should throw an error when reverting without a checkpoint', () => { merkle = new Merkle([testValue1, testValue2], false) expect(() => merkle.revert()).to.throw('No checkpoint to revert to') }) it('should create Merkle instance correctly', () => { expect(merkle).to.be.instanceOf(Merkle) expect(merkle.levels[0].length).to.equal(2) expect(merkle.levels[0][0]).to.equal(testValue1) expect(merkle.levels[0][1]).to.equal(testValue2) }) }) describe('static getRoot()', () => { it('should return the root of the levels', () => { const root = Merkle.getRoot(merkle.levels) expect(root).to.be.a('string') }) it('should mutate the levels when mutate is true', () => { const levelsCopy = merkle.levels.slice() const root = Merkle.getRoot(levelsCopy, true) expect(root).to.be.a('string') expect(levelsCopy.length).to.equal(merkle.levels.length - 1) }) }) describe('getRoot()', () => { it('should return the root of the Merkle tree instance', () => { const root = merkle.getRoot() expect(root).to.be.a('string') }) }) describe('genRoot()', () => { it('should generate and set the root of the Merkle tree instance', () => { const root = merkle.genRoot() expect(root).to.be.a('string') expect(root).to.equal(merkle.root) }) }) describe('derive()', () => { it('should generate new levels and root for the Merkle tree', () => { const prevMerkle = new Merkle([testValue1]) const nextMerkle = new Merkle([testValue1, testValue2]) const prevRoot = prevMerkle.getRoot() const nextRoot = nextMerkle.getRoot() expect(prevRoot).to.not.equal(nextRoot) }) }) describe('static derive()', () => { it('should return new levels for the Merkle tree', () => { const levels = [testValue1, testValue2] const undos = [] const newLevels = Merkle.derive(levels, undos, hashLength) expect(newLevels).to.be.an('array') expect(newLevels[0]).to.include(testValue1) expect(newLevels[0]).to.include(testValue2) }) }) describe('static _derive()', () => { it('should return new levels for the Merkle tree', () => { const levels = [testValue1, testValue2] const undos = [] const newLevels = Merkle._derive([levels], undos, hashLength) expect(newLevels).to.be.an('array') expect(newLevels[0]).to.include(testValue1) expect(newLevels[0]).to.include(testValue2) }) }) describe('static append()', () => { it('should append a value and return the new levels', () => { const levelsCopy = merkle.levels.slice() const newLevels = Merkle.append('Test', levelsCopy) expect(newLevels).to.be.an('array') expect(newLevels[0]).to.include('Test') }) }) describe('append()', () => { it('should append a value and generate a new root', () => { const oldRoot = merkle.genRoot() merkle.append('Test') const newRoot = merkle.getRoot() expect(oldRoot).to.not.equal(newRoot) }) }) describe('getLeaf()', () => { it('should retrieve leaf correctly', () => { const leaf = merkle.getLeaf(0) expect(leaf).to.equal(testValue1) }) }) describe('getLeafCount()', () => { it('should get the correct leaf count', () => { const count = merkle.getLeafCount() expect(count).to.equal(2) }) }) describe('getIndex()', () => { it('should get the correct index of a leaf', () => { const index = merkle.getIndex(testValue1) expect(index).to.equal(0) }) it('should return -1 if leaf not found', () => { const index = merkle.getIndex('NotALeaf') expect(index).to.equal(-1) }) }) describe('depth', () => { it('should return the correct depth', () => { const depth = merkle.depth expect(depth).to.equal(2) // the depth should be 2 for a Merkle tree with two leaves }) }) describe('peek()', () => { before(() => merkle = new Merkle([testValue1, testValue2])) it('should return the last key when no parameter is given', () => { const key = merkle.peek() const firstKey = Object.keys(merkle.stacks)[0] expect(key).to.not.be.empty expect(key).to.equal(firstKey) }) it('should return the correct key when a parameter is given', () => { merkle.checkpoint() const keys = Object.keys(merkle.stacks) const key = merkle.peek(0) expect(key).to.equal(keys[0]) // the key should be the first key when the parameter is 0 }) }) describe('checkpoint()', () => { it('should create a new checkpoint correctly', () => { const checkpoint = merkle.checkpoint() expect(checkpoint).to.not.be.empty expect(checkpoint.root).to.not.be.empty expect(checkpoint.stack).to.be.an('array') expect(checkpoint.stack).to.be.empty expect(merkle.stacks).to.have.property(checkpoint.root) }) }) describe('hash()', () => { it('should return hashed value for given input', () => { const hash = merkle.hash(testValue1) expect(hash).to.be.a('string') }) }) describe('static hash()', () => { it('should return hashed value for given input', () => { const hash = Merkle.hash(testValue1) expect(hash).to.be.a('string') }) }) })