diff --git a/package.json b/package.json index 39e769b..bc6065a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fixed-merkle-tree", - "version": "0.3.4", + "version": "0.4.0", "description": "Fixed depth merkle tree implementation with sequential inserts", "main": "src/merkleTree.js", "scripts": { diff --git a/src/merkleTree.js b/src/merkleTree.js index ba68d17..4fc6b92 100644 --- a/src/merkleTree.js +++ b/src/merkleTree.js @@ -152,6 +152,36 @@ class MerkleTree { elements() { return this._layers[0].slice() } + + /** + * Serialize entire tree state including intermediate layers into a plain object + * 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() { + return { + levels: this.levels, + capacity: this.capacity, + zeroElement: this.zeroElement, + _zeros: this._zeros, + _layers: this._layers, + } + } + + /** + * 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 + return instance + } } module.exports = MerkleTree diff --git a/test/merkleTree.test.js b/test/merkleTree.test.js index 29e69b9..b941abc 100644 --- a/test/merkleTree.test.js +++ b/test/merkleTree.test.js @@ -202,4 +202,19 @@ describe('MerkleTree', () => { ]) }) }) + + describe('#serialize', () => { + it('should work', () => { + const src = new MerkleTree(10, [1, 2, 3]) + const data = src.serialize() + const dst = MerkleTree.deserialize(data) + + src.root().should.equal(dst.root()) + + src.insert(10) + dst.insert(10) + + src.root().should.equal(dst.root()) + }) + }) })