@zk-kit/sparse-merkle-tree
Version:
Sparse Merkle tree implementation in TypeScript.
10 lines (9 loc) • 4.52 kB
JavaScript
/**
* @module @zk-kit/sparse-merkle-tree
* @version 0.2.0
* @file Sparse Merkle tree implementation in TypeScript.
* @copyright Omar Desogus 2022
* @license MIT
* @see [Github]{@link https://github.com/appliedzkp/zk-kit/tree/main/packages/sparse-merkle-tree}
*/
var zkKitSparseMerkleTree=function(t){"use strict";function e(t){for(var e=Number("0x".concat(t[0])).toString(2),r=1;r<t.length;r+=1)e+=Number("0x".concat(t[r])).toString(2).padStart(4,"0");return e}function r(t){return("bigint"==typeof t?t.toString(2):e(t)).padStart(256,"0").split("").reverse().map(Number)}function i(t){for(var e=t.length-1;e>=0;e-=1)if(0!==Number("0x".concat(t[e])))return e;return-1}function n(t,e){for(var r=t.length<e.length?t:e,i=0;i<r.length;i+=1)if(t[i]!==e[i])return r.slice(0,i);return r.slice()}function o(t){return"string"==typeof t&&/^[0-9A-Fa-f]{1,64}$/.test(t)}var s=function(){function t(t,e){if(void 0===e&&(e=!1),e){if("function"!=typeof BigInt)throw new Error("Big numbers are not supported");if("bigint"!=typeof t([BigInt(1),BigInt(1)]))throw new Error("The hash function must return a big number")}else if(!o(t(["1","1"])))throw new Error("The hash function must return a hexadecimal");this.hash=t,this.bigNumbers=e,this.zeroNode=e?BigInt(0):"0",this.entryMark=e?BigInt(1):"1",this.nodes=new Map,this.root=this.zeroNode}return t.prototype.get=function(t){return this.checkParameterType(t),this.retrieveEntry(t).entry[1]},t.prototype.add=function(t,e){this.checkParameterType(t),this.checkParameterType(e);var i=this.retrieveEntry(t),n=i.entry,o=i.matchingEntry,s=i.siblings;if(void 0!==n[1])throw new Error('Key "'.concat(t,'" already exists'));var h=r(t),a=o?this.hash(o):this.zeroNode;if(s.length>0&&this.deleteOldNodes(a,h,s),o){for(var c=r(o[0]),u=s.length;c[u]===h[u];u+=1)s.push(this.zeroNode);s.push(a)}var d=this.hash([t,e,this.entryMark]);this.nodes.set(d,[t,e,this.entryMark]),this.root=this.addNewNodes(d,h,s)},t.prototype.update=function(t,e){this.checkParameterType(t),this.checkParameterType(e);var i=this.retrieveEntry(t),n=i.entry,o=i.siblings;if(void 0===n[1])throw new Error('Key "'.concat(t,'" does not exist'));var s=r(t),h=this.hash(n);this.nodes.delete(h),this.deleteOldNodes(h,s,o);var a=this.hash([t,e,this.entryMark]);this.nodes.set(a,[t,e,this.entryMark]),this.root=this.addNewNodes(a,s,o)},t.prototype.delete=function(t){this.checkParameterType(t);var e=this.retrieveEntry(t),n=e.entry,o=e.siblings;if(void 0===n[1])throw new Error('Key "'.concat(t,'" does not exist'));var s=r(t),h=this.hash(n);if(this.nodes.delete(h),this.root=this.zeroNode,o.length>0)if(this.deleteOldNodes(h,s,o),this.isLeaf(o[o.length-1])){var a=o.pop(),c=i(o);this.root=this.addNewNodes(a,s,o,c)}else this.root=this.addNewNodes(this.zeroNode,s,o)},t.prototype.createProof=function(t){this.checkParameterType(t);var e=this.retrieveEntry(t),r=e.entry;return{entry:r,matchingEntry:e.matchingEntry,siblings:e.siblings,root:this.root,membership:!!r[1]}},t.prototype.verifyProof=function(t){if(!t.matchingEntry){var e=r(t.entry[0]),i=void 0!==t.entry[1]?this.hash(t.entry):this.zeroNode;return this.calculateRoot(i,e,t.siblings)===t.root}var o=r(t.matchingEntry[0]),s=this.hash(t.matchingEntry);if(this.calculateRoot(s,o,t.siblings)===t.root){var h=n(e=r(t.entry[0]),o);return t.siblings.length<=h.length}return!1},t.prototype.retrieveEntry=function(t){for(var e=r(t),i=[],n=0,o=this.root;o!==this.zeroNode;n+=1){var s=this.nodes.get(o),h=e[n];if(s[2])return s[0]===t?{entry:s,siblings:i}:{entry:[t],matchingEntry:s,siblings:i};o=s[h],i.push(s[Number(!h)])}return{entry:[t],siblings:i}},t.prototype.calculateRoot=function(t,e,r){for(var i=r.length-1;i>=0;i-=1){var n=e[i]?[r[i],t]:[t,r[i]];t=this.hash(n)}return t},t.prototype.addNewNodes=function(t,e,r,i){for(void 0===i&&(i=r.length-1);i>=0;i-=1){var n=e[i]?[r[i],t]:[t,r[i]];t=this.hash(n),this.nodes.set(t,n)}return t},t.prototype.deleteOldNodes=function(t,e,r){for(var i=r.length-1;i>=0;i-=1){var n=e[i]?[r[i],t]:[t,r[i]];t=this.hash(n),this.nodes.delete(t)}},t.prototype.isLeaf=function(t){var e=this.nodes.get(t);return!(!e||!e[2])},t.prototype.checkParameterType=function(t){if(this.bigNumbers&&"bigint"!=typeof t)throw new Error("Parameter ".concat(t," must be a big number"));if(!this.bigNumbers&&!o(t))throw new Error("Parameter ".concat(t," must be a hexadecimal"))},t}();return t.SparseMerkleTree=s,t.checkHex=o,t.getFirstCommonElements=n,t.getIndexOfLastNonZeroElement=i,t.hexToBin=e,t.keyToPath=r,Object.defineProperty(t,"__esModule",{value:!0}),t}({});