UNPKG

postchain-client

Version:

Client library for accessing a Postchain node through REST.

1,601 lines (1,576 loc) 171 kB
'use strict'; var require$$0$1 = require('buffer'); var bn_js = require('bn.js'); var crypto = require('crypto'); var secp256k1 = require('secp256k1'); var cloneDeep = require('lodash/cloneDeep'); var events = require('events'); var zod = require('zod'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var crypto__namespace = /*#__PURE__*/_interopNamespaceDefault(crypto); var secp256k1__namespace = /*#__PURE__*/_interopNamespaceDefault(secp256k1); function getAugmentedNamespace(n) { if (n.__esModule) return n; var f = n.default; if (typeof f == "function") { var a = function a () { if (this instanceof a) { var args = [null]; args.push.apply(args, arguments); var Ctor = Function.bind.apply(f, args); return new Ctor(); } return f.apply(this, arguments); }; a.prototype = f.prototype; } else a = {}; Object.defineProperty(a, '__esModule', {value: true}); Object.keys(n).forEach(function (k) { var d = Object.getOwnPropertyDescriptor(n, k); Object.defineProperty(a, k, d.get ? d : { enumerable: true, get: function () { return n[k]; } }); }); return a; } // eslint-disable-next-line @typescript-eslint/no-var-requires const asn = require("@chromia/asn1/lib/asn1"); const ASNDictPair = asn.define("DictPair", function () { this.seq().obj(this.key("name").utf8str(), this.key("value").use(rawGTV)); }); const rawGTV = asn.define("GtvValue", function () { this.choice({ null: this.explicit(0).null_(), byteArray: this.explicit(1).octstr(), string: this.explicit(2).utf8str(), integer: this.explicit(3).int(), dict: this.explicit(4).seqof(ASNDictPair), array: this.explicit(5).seqof(rawGTV), bigInteger: this.explicit(6).int(), }); }); asn.define("Buffer", function () { this.octstr(); }); class CustomError extends Error { constructor(message, status) { super(message); this.name = this.constructor.name; this.status = status; } } class UnexpectedArgumentTypeError extends CustomError { constructor(typedArg) { super(`Cannot parse typedArg ${JSON.stringify(typedArg)}. Unknown type ${typedArg.type}`, 400); } } class MissingGtxException extends CustomError { constructor() { super(`Missing instance of gtx protocol (used for communicating with postchain) to add operation to`, 400); } } class AlreadySignedTransactionException extends CustomError { constructor(operation) { super(`Cannot add ${operation} calls to an already signed gtx`, 400); } } class NumberOfSignersAndSignaturesException extends CustomError { constructor() { super(`Not matching number of signers and signatures`, 400); } } class MissingSignerException extends CustomError { constructor() { super(`No such signer, remember to add signer to transaction before adding a signature`, 400); } } var __rest = (undefined && undefined.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; function pgBytes(buffer) { if (!require$$0$1.Buffer.isBuffer(buffer)) { throw new PgBytesInputException(buffer); } return `\\x${buffer.toString("hex")}`; } /** * Converts hex string to Buffer * @param key: string * @returns {Buffer} */ function toBuffer(key) { return require$$0$1.Buffer.from(key, "hex"); } /** * Converts Buffer to hex string * @param buffer: Buffer * @returns {string} */ function toString(buffer) { return buffer.toString("hex").toUpperCase(); } function toQueryObjectGTV(nameOrObject, queryArguments) { let name; if (typeof nameOrObject === "string") { name = nameOrObject; return [name, Object.assign({}, queryArguments)]; } else { const objectCopy = Object.assign({}, nameOrObject); const { type } = objectCopy, restProps = __rest(objectCopy, ["type"]); return [type, restProps]; } } class PgBytesInputException extends Error { constructor(buffer) { super(`util.pgBytes expects a buffer, but got ${typeof buffer}`); } } function ensureBuffer(value) { if (value instanceof require$$0$1.Buffer) { return value; } else { return toBuffer(value); } } function checkGtvType(value) { try { if (value == null) { return true; } if (require$$0$1.Buffer.isBuffer(value)) { return true; } if (typeof value === "string") { return true; } if (typeof value === "number") { if (!Number.isInteger(value)) { throw Error("User error: Only integers are supported"); } return true; } if (typeof value === "bigint") { return true; } if (value.constructor === Array) { value.map((item) => checkGtvType(item)); return true; } if (typeof value === "object") { Object.keys(value).map(function (key) { checkGtvType(value[key]); }); return true; } } catch (error) { throw new Error(`Failed to check type: ${error}`); } return false; } function rawGtxToGtx(rawGtx) { const rawGtxBody = rawGtx[0]; const signatures = rawGtx[1]; const gtxBody = { blockchainRid: rawGtxBody[0], operations: rawGtxBody[1].map((operation) => ({ opName: operation[0], args: operation[1], })), signers: rawGtxBody[2], }; return { blockchainRid: gtxBody.blockchainRid, operations: gtxBody.operations, signers: gtxBody.signers, signatures, }; } function rawGtxToRawGtxBody(rawGtx) { return rawGtx[0]; } function checkGtxType(value) { try { rawGtxToGtx(value); return true; } catch (error) { return false; } } function removeDuplicateSigners(signers) { const signersAsString = []; signers.forEach((item) => { const itemAsString = item.toString("hex"); if (!signersAsString.includes(itemAsString)) { signersAsString.push(itemAsString); } }); const result = []; signersAsString.forEach((item) => { result.push(require$$0$1.Buffer.from(item, "hex")); }); return result; } function matchRellErrorString(rellError) { const parsed = rellError.match(/\[([^\]]+)\]\sOperation\s'([^']+)'\sfailed:\s(.+)$/); if (!parsed) return {}; const [rellLine, operation, shortReason] = parsed.slice(1); return { shortReason, rellLine, operation }; } var formatter = /*#__PURE__*/Object.freeze({ __proto__: null, PgBytesInputException: PgBytesInputException, checkGtvType: checkGtvType, checkGtxType: checkGtxType, ensureBuffer: ensureBuffer, matchRellErrorString: matchRellErrorString, pgBytes: pgBytes, rawGtxToGtx: rawGtxToGtx, rawGtxToRawGtxBody: rawGtxToRawGtxBody, removeDuplicateSigners: removeDuplicateSigners, toBuffer: toBuffer, toQueryObjectGTV: toQueryObjectGTV, toString: toString }); function encodeValue(rawGtv) { return rawGTV.encode(createTypedArg(rawGtv)); } function encodeValueGtx(rawGtx) { return encodeValue(rawGtx); } function decodeValue(bytes) { //TODO add a try catch to catch asn1 errors to be more readable error const obj = rawGTV.decode(bytes); return parseValue(obj); } function decodeValueGtx(bytes) { const decodedValue = decodeValue(bytes); if (!checkGtxType(decodedValue)) { throw new Error(`Unexpected type of value: ${decodedValue}, expected decoded value to be of type RawGtx`); } return decodedValue; } function parseValue(typedArg) { var _a, _b; if (typedArg.type === "null") { return null; } else if (typedArg.type === "byteArray") { return typedArg.value; } else if (typedArg.type === "string") { return typedArg.value; } else if (typedArg.type === "integer") { return Number(typedArg.value); } else if (typedArg.type === "array") { const arrayValue = typedArg.value; return arrayValue.map((item) => parseValue(item)); } else if (typedArg.type === "bigInteger") { return BigInt((_b = (_a = typedArg.value) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : ""); } else if (typedArg.type === "dict") { const arrayValue = typedArg.value; const result = {}; arrayValue.forEach((pair) => { result[pair.name] = parseValue(pair.value); }); return result; } else { throw new UnexpectedArgumentTypeError(typedArg); } } function createTypedArg(value) { try { if (value == null) { return { type: "null", value: null }; } if (require$$0$1.Buffer.isBuffer(value)) { return { type: "byteArray", value: value }; } if (typeof value === "boolean") { return { type: "integer", value: value ? 1 : 0 }; } if (typeof value === "string") { return { type: "string", value: value }; } if (typeof value === "number") { if (!Number.isInteger(value)) { throw Error("User error: Only integers are supported"); } return { type: "integer", value: new bn_js.BN(value) }; } if (typeof value === "bigint") { return { type: "bigInteger", value: new bn_js.BN(value.toString()) }; } if (value.constructor === Array) { return { type: "array", value: value.map((item) => createTypedArg(item)), }; } if (typeof value === "object") { let valueAsDictPair = value; if (isDictPairWithStringKey(valueAsDictPair)) { valueAsDictPair = sortDictPairByKey(valueAsDictPair); } return { type: "dict", value: Object.keys(valueAsDictPair).map(function (key) { return { name: key, value: createTypedArg(valueAsDictPair[key]) }; }), }; } } catch (error) { const message = value ? value.toString() : "RawGtv"; throw new Error(`Failed to encode ${message}: ${error}`); } throw new Error(`value ${value} have unsupported type: ${typeof value}`); } function isDictPairWithStringKey(obj) { for (const key in obj) { if (typeof key !== "string") { return false; } } return true; } function sortDictPairByKey(dict) { const sortedArray = Object.entries(dict).sort(([keyA], [keyB]) => { if (keyA < keyB) { return -1; } if (keyA > keyB) { return 1; } return 0; }); const sortedDict = {}; for (const [key, value] of sortedArray) { sortedDict[key] = value; } return sortedDict; } var serialization$1 = /*#__PURE__*/Object.freeze({ __proto__: null, createTypedArg: createTypedArg, decodeValue: decodeValue, decodeValueGtx: decodeValueGtx, encodeValue: encodeValue, encodeValueGtx: encodeValueGtx, parseValue: parseValue }); var require$$1 = /*@__PURE__*/getAugmentedNamespace(serialization$1); var require$$0 = /*@__PURE__*/getAugmentedNamespace(formatter); var util$1 = require$$0; function PathElement(previous) { this.previous = previous; } PathElement.prototype.getSearchKey = function () { }; function PathLeafElement$3(previous) { PathElement.call(this, previous); } PathLeafElement$3.prototype = Object.create(PathElement.prototype); PathLeafElement$3.prototype.constructor = PathLeafElement$3; PathLeafElement$3.prototype.equals = function (other) { if (this === other) return true; if (typeof this !== typeof other) return false; return true; }; function SearchablePathElement(previous) { PathElement.call(this, previous); } SearchablePathElement.prototype = Object.create(PathElement.prototype); SearchablePathElement.prototype.constructor = SearchablePathElement; SearchablePathElement.prototype.getSearchKey = function () { }; /** * * @param {SearchablePathElement} previous * @param {number} index */ function ArrayPathElement(previous, index) { SearchablePathElement.call(this, previous); this.index = index; } ArrayPathElement.prototype = Object.create(SearchablePathElement.prototype); ArrayPathElement.prototype.constructor = ArrayPathElement; ArrayPathElement.prototype.getSearchKey = function () { return this.index; }; /** * @param {ArrayPathElement} other */ ArrayPathElement.prototype.equals = function (other) { if (this === other) return true; if (typeof this !== typeof other) return false; if (this.index != other.index) return false; return true; }; /** * * @param {SearchablePathElement} previous * @param {string} key */ function DictPathElement(previous, key) { SearchablePathElement.call(this, previous); this.key = key; } DictPathElement.prototype = Object.create(SearchablePathElement.prototype); DictPathElement.prototype.constructor = DictPathElement; DictPathElement.prototype.getSearchKey = function () { return this.key; }; /** * @param {DictPathElement} other */ DictPathElement.prototype.equals = function (other) { if (this === other) return true; if (typeof this !== typeof other) return false; if (this.key != other.key) return false; return true; }; /** * * @param {Array} pathElements */ function Path(pathElements) { this.pathElements = pathElements; } /** * */ Path.prototype.getCurrentPathElement = function () { return this.pathElements[0]; }; /** * */ Path.prototype.size = function () { return this.pathElements.length; }; /** * */ Path.prototype.tail = function () { if (this.pathElements.length == 0) { throw new Error("Impossible to tail this array"); } else { var tail = this.pathElements.slice(1); return new Path(tail); } }; Path.prototype.debugString = function () { var sb = ""; this.pathElements.forEach(elem => { if (elem instanceof SearchablePathElement) { sb = sb + "-> " + elem.getSearchKey(); } else if (elem instanceof PathLeafElement$3) { sb = sb + "-> Leaf"; } }); return sb; }; /** * @param {Path} other */ Path.prototype.equals = function (other) { if (this === other) return true; if (typeof this != typeof other) return false; return this.pathElements == other.pathElements; }; /** * @param {number} index * @param {Path} path */ var getTailIfFirstElementIsArrayOfThisIndex = function (index, path) { return getTail(index, path); }; /** * * @param {string} key * @param {Path} path */ var getTailIfFirstElementIsDictOfThisKey = function (key, path) { return getTail(key, path); }; /** * * @param {string|number} searchKey * @param {Path} path */ var getTail = function (searchKey, path) { if (searchKey === null) { throw new Error("Have to provide a search key"); } try { var firstElement = path.pathElements[0]; if (firstElement instanceof SearchablePathElement) { if (firstElement.getSearchKey() == searchKey) { return path.tail(); } } } catch (err) { util$1.logError("Why are we dropping first element of an empty path? " + err); return null; } return null; }; /** * * @param {Array} paths */ function PathSet$1(paths) { this.paths = paths; } /** * */ PathSet$1.prototype.isEmpty = function () { return this.paths.length == 0; }; /** * */ PathSet$1.prototype.getPathLeafOrElseAnyCurrentPathElement = function () { var leafElem = null; var currElem = null; var prev = { "path": null, "elem": null, }; this.paths.forEach(path => { currElem = path.getCurrentPathElement(); if (currElem instanceof PathLeafElement$3) { leafElem = currElem; } prev = this.errorCheckUnequalParent(path, currElem, prev.path, prev.elem); }); if (leafElem != null) { return leafElem; } else { return currElem; // It doesn't matter which one we return (Next step we will get the "previous" from this one) } }; /** * Yeah, this might be a completely un-needed check (but it MIGHT save us later on if we forget this rule). * What we are looking for here is an impossible state where two paths in the same set don't have the same parent. * (Since we usually only have one path in a path set, this check should be cheap) * * @param {Path} currPath * @param {PathElement} currElem * @param {Path} prevPath * @param {PathElement} prevElem */ PathSet$1.prototype.errorCheckUnequalParent = function (currPath, currElem, prevPath, prevElem) { if (prevElem != null) { // weird: javascript cannot compare null == null then we have to compare each with null separately :( if (currElem.previous == null && prevElem.previous == null) { return { "path": currPath, "elem": currElem }; } else if ((currElem.previous == null && prevElem.previous != null) || (currElem.previous != null && prevElem.previous == null)) { throw new Error("Something is wrong, these paths do not have the same parent. (" + currPath + ") (" + prevPath + ")"); } else if (!currElem.previous.equals(prevElem.previous)) { throw new Error("Something is wrong, these paths do not have the same parent. (" + currPath + ") (" + prevPath + ")"); } } return { "path": currPath, "elem": currElem }; }; /** * */ PathSet$1.prototype.keepOnlyArrayPaths = function () { var filteredPaths = this.paths.filter(path => { return path.pathElements[0] instanceof ArrayPathElement; }); return new PathSet$1(filteredPaths); }; /** * */ PathSet$1.prototype.keepOnlyDictPaths = function () { var filteredPaths = this.paths.filter(path => { return path.pathElements[0] instanceof DictPathElement; }); return new PathSet$1(filteredPaths); }; /** * */ PathSet$1.prototype.getTailIfFirstElementIsArrayOfThisIndexFromList = function (index) { return this.getTailFromList(index, getTailIfFirstElementIsArrayOfThisIndex); }; /** * */ PathSet$1.prototype.getTailIfFirstElementIsDictOfThisKeyFromList = function (key) { return this.getTailFromList(key, getTailIfFirstElementIsDictOfThisKey); }; /** * */ PathSet$1.prototype.getTailFromList = function (searchKey, filterFunc) { var retPaths = new Array(); this.paths.forEach(path => { var newPath = filterFunc(searchKey, path); if (newPath != null) { retPaths.push(newPath); } }); return new PathSet$1(retPaths); }; /** * * @param {Array} arr */ var buildPathFromArray = function (arr) { var pathElements = new Array(); var lastPathElem = null; arr.forEach(item => { var newElem = null; if (typeof item === 'number') { newElem = new ArrayPathElement(lastPathElem, item); } else if (typeof item === 'string') { newElem = new DictPathElement(lastPathElem, item); } else { throw new Error("A path structure must only consist of Ints and Strings, not " + item); } pathElements.push(newElem); lastPathElem = newElem; }); var lastOne = lastPathElem; pathElements.push(new PathLeafElement$3(lastOne)); return new Path(pathElements); }; var path = { Path, PathElement, PathLeafElement: PathLeafElement$3, ArrayPathElement, SearchablePathElement, DictPathElement, PathSet: PathSet$1, getTailIfFirstElementIsArrayOfThisIndex, buildPathFromArray }; var PathLeafElement$2 = path.PathLeafElement; const HASH_PREFIX_NODE$1 = 0; const HASH_PREFIX_LEAF$1 = 1; const HASH_PREFIX_NODE_ARRAY$1 = 7; const HASH_PREFIX_NODE_DICT$1 = 8; /** * */ function BinaryTreeElement() { this.pathElem = null; } BinaryTreeElement.prototype.isPath = function () { return this.pathElem != null; }; BinaryTreeElement.prototype.isPathLeaf = function () { if (this.pathElem == null) { return false; } if (this.pathElem instanceof PathLeafElement$2) { return true; } else { return false; } }; BinaryTreeElement.prototype.setPathElement = function (pathElem) { this.pathElem = pathElem; }; BinaryTreeElement.prototype.getPrefixByte = function () { return HASH_PREFIX_NODE$1; }; /** * * @param {BinaryTreeElement} left * @param {BinaryTreeElement} right */ function Node$2(left, right) { this.left = left; this.right = right; } Node$2.prototype = Object.create(BinaryTreeElement.prototype); Node$2.prototype.constructor = Node$2; Node$2.prototype.getPrefixByte = function () { return HASH_PREFIX_NODE$1; }; /** * * @param {BinaryTreeElement} left * @param {BinaryTreeElement} right * @param {*} content * @param {PathSet} pathElem */ function SubTreeRootNode$1(left, right, content, pathElem) { Node$2.call(this, left, right); this.content = content; BinaryTreeElement.prototype.setPathElement.call(this, pathElem); } SubTreeRootNode$1.prototype = Object.create(Node$2.prototype); SubTreeRootNode$1.prototype.constructor = SubTreeRootNode$1; /** * * @param {*} content * @param {PathElement} pathElem */ function Leaf$2(content, pathElem = null) { this.content = content; if (pathElem != null) { if (pathElem instanceof PathLeafElement$2) { BinaryTreeElement.prototype.setPathElement.call(this, pathElem); } else { throw new Error("The path and object structure does not match! We are at a leaf, but the path expects a sub structure."); } } } Leaf$2.prototype = Object.create(BinaryTreeElement.prototype); Leaf$2.prototype.constructor = Leaf$2; Leaf$2.prototype.getPrefixByte = function () { return HASH_PREFIX_LEAF$1; }; function EmptyLeaf$2() { } EmptyLeaf$2.prototype = Object.create(BinaryTreeElement.prototype); EmptyLeaf$2.prototype.constructor = EmptyLeaf$2; /** * Wrapper class for the root object. * @param {BinaryTreeElement} root */ function BinaryTree$1(root) { this.root = root; } BinaryTree$1.prototype.maxLevel = function () { return this.maxLevelInternal(this.root); }; BinaryTree$1.prototype.maxLevelInternal = function (node) { if (node instanceof EmptyLeaf$2) { return 0; } else if (node instanceof Leaf$2) { return 1; } else if (node instanceof Node$2) { return Math.max(this.maxLevelInternal(node.left), this.maxLevelInternal(node.right)) + 1; } else { throw new Error("What is this type? " + typeof node); } }; /** * Represents the top of a sub tree generated by a [Array] * * @param {*} left * @param {*} right * @param {*} content * @param {*} size * @param {PathElement} pathElem */ function ArrayHeadNode$2(left, right, content, size, pathElem = null) { SubTreeRootNode$1.call(this, left, right, content, pathElem); this.size = size; } ArrayHeadNode$2.prototype = Object.create(SubTreeRootNode$1.prototype); ArrayHeadNode$2.prototype.constructor = ArrayHeadNode$2; ArrayHeadNode$2.prototype.getPrefixByte = function () { return HASH_PREFIX_NODE_ARRAY$1; }; /** * Represents the top a sub tree generated by a [Dictionary] * @param {*} left * @param {*} right * @param {*} content * @param {*} size * @param {PathElement} pathElem */ function DictHeadNode$2(left, right, content, size, pathElem = null) { SubTreeRootNode$1.call(this, left, right, content, pathElem); this.size = size; } DictHeadNode$2.prototype = Object.create(SubTreeRootNode$1.prototype); DictHeadNode$2.prototype.constructor = DictHeadNode$2; DictHeadNode$2.prototype.getPrefixByte = function () { return HASH_PREFIX_NODE_DICT$1; }; var binarytree = { HASH_PREFIX_NODE: HASH_PREFIX_NODE$1, HASH_PREFIX_LEAF: HASH_PREFIX_LEAF$1, HASH_PREFIX_NODE_ARRAY: HASH_PREFIX_NODE_ARRAY$1, HASH_PREFIX_NODE_DICT: HASH_PREFIX_NODE_DICT$1, Node: Node$2, Leaf: Leaf$2, EmptyLeaf: EmptyLeaf$2, SubTreeRootNode: SubTreeRootNode$1, BinaryTreeElement, BinaryTree: BinaryTree$1, ArrayHeadNode: ArrayHeadNode$2, DictHeadNode: DictHeadNode$2 }; class PrivKeyFormatException extends Error { constructor(privKey) { super(`Invalid key length. Expected 32, but got ${privKey.length}`); } } class MissingPrivKeyArgumentException extends Error { constructor() { super(`Missing argument privKey`); } } function createPublicKey(privKey) { validatePrivKeyFormat(privKey); return require$$0$1.Buffer.from(secp256k1__namespace.publicKeyCreate(privKey, true).buffer); } function randomBytes(size) { return crypto__namespace.randomBytes(size); } function sha256(buffer) { return crypto__namespace.createHash("sha256").update(buffer).digest(); } const hash256 = sha256; function hashConcat(items) { return hash256(require$$0$1.Buffer.concat(items)); } /** * @param content the content that the signature signs. It will be digested before validating. * @param pubKey The pubKey to validate the signature with * @param signature the signature to validate * * @return true if signature ok, false otherwise */ function checkSignature(content, pubKey, signature) { const digest = hash256(content); return checkDigestSignature(digest, pubKey, signature); } /** * @param digest the signed digest. It will not be digested before validating. * @param pubKey The pubKey to validate the signature with * @param signature the signature to validate * * @return true if signature ok, false otherwise */ function checkDigestSignature(digest, pubKey, signature) { if (!signature) return false; return secp256k1__namespace.ecdsaVerify(signature, digest, pubKey); } /** * @param content to sign. It will be digested before signing. * @param privKey The private key to sign the content with * * @return the signature */ function sign$1(content, privKey) { validatePrivKeyFormat(privKey); const digestBuffer = sha256(content); return signDigest(digestBuffer, privKey); } /** * @param digestBuffer to sign. It will not be digested before signing. * @param privKey The private key to sign the digest with * * @return the signature */ function signDigest(digestBuffer, privKey) { return require$$0$1.Buffer.from(secp256k1__namespace.ecdsaSign(digestBuffer, privKey).signature); } /** * Creates a key pair (which usually represents one user) * @param privKey to create key pair based on * @returns {{pubKey: Buffer, privKey: Buffer}} */ function makeKeyPair(privKey) { let pubKey; if (privKey) { privKey = ensureBuffer(privKey); pubKey = createPublicKey(privKey); } else { do { privKey = randomBytes(32); } while (!secp256k1__namespace.privateKeyVerify(privKey)); pubKey = require$$0$1.Buffer.from(secp256k1__namespace.publicKeyCreate(privKey).buffer); } return { pubKey, privKey }; } /** * Generates a 16bytes TUID (Text unique ID) (a 32characters long string) * @returns string */ function makeTuid() { return randomBytes(16).toString("hex"); } /** * Verify that keypair is correct. Providing the private key, this function returns its associated public key * @param privKey: Buffer * @returns {{pubKey: Buffer, privKey: Buffer}} */ function verifyKeyPair(privKey) { validatePrivKeyFormat(privKey); const pubKey = require$$0$1.Buffer.from(secp256k1__namespace.publicKeyCreate(privKey).buffer); return { pubKey, privKey }; } function validatePrivKeyFormat(privKey) { if (!privKey) { throw new MissingPrivKeyArgumentException(); } if (!require$$0$1.Buffer.isBuffer(privKey) || privKey.length !== 32) { throw new PrivKeyFormatException(privKey); } } var encryption$1 = /*#__PURE__*/Object.freeze({ __proto__: null, checkDigestSignature: checkDigestSignature, checkSignature: checkSignature, createPublicKey: createPublicKey, hash256: hash256, hashConcat: hashConcat, makeKeyPair: makeKeyPair, makeTuid: makeTuid, randomBytes: randomBytes, sha256: sha256, sign: sign$1, signDigest: signDigest, verifyKeyPair: verifyKeyPair }); var require$$3 = /*@__PURE__*/getAugmentedNamespace(encryption$1); const { Buffer: Buffer$3 } = require$$0$1; var serialization = require$$1; var HASH_PREFIX_LEAF = binarytree.HASH_PREFIX_LEAF; var encryption = require$$3; function CryptoSystem() { } CryptoSystem.prototype.digest = function (buffer) { return encryption.hash256(buffer); }; /** * * @param {Buffer} buffer * @param {CryptoSystem} cryptoSystem */ function hashingFun(buffer, cryptoSystem) { if (cryptoSystem === null) { throw new Error("In this case we need the CryptoSystem to calculate the hash"); } else { return cryptoSystem.digest(buffer); } } /** * * @param {CryptoSystem} cryptoSystem */ function MerkleHashCalculator(cryptoSystem) { this.cryptoSystem = cryptoSystem; } /** * @param {number} prefix * @param {Buffer} hashLeft * @param {Buffer} hashRight */ MerkleHashCalculator.prototype.calculateNodeHash = function (prefix, hashLeft, hashRight) { return this.calculateNodeHashInternal(prefix, hashLeft, hashRight, hashingFun); }; /** * @param {*} value */ MerkleHashCalculator.prototype.calculateLeafHash = function (value) { return this.calculateHashOfValueInternal(value, serialization.encodeValue, hashingFun); }; /** * @param {number} prefix * @param {Buffer} hashLeft * @param {Buffer} hashRight */ MerkleHashCalculator.prototype.calculateNodeHashInternal = function (prefix, hashLeft, hashRight, hashFunc) { var buf = Buffer$3.alloc(1); buf.writeInt8(prefix); var bufferSum = Buffer$3.concat([buf, hashLeft, hashRight]); return hashFunc(bufferSum, this.cryptoSystem); }; MerkleHashCalculator.prototype.calculateHashOfValueInternal = function (valuetoHash, serializeFun, hashFunc) { var buf = Buffer$3.alloc(1); buf.writeInt8(HASH_PREFIX_LEAF); var bufferSum = Buffer$3.concat([buf, serializeFun(valuetoHash)]); return hashFunc(bufferSum, this.cryptoSystem); }; MerkleHashCalculator.prototype.isContainerProofValueLeaf = function (value) { if (value == null) { return false; } if (value.constructor === Array || typeof value === 'object') { return true; } else { return false; } }; var merklehashcalculator = { MerkleHashCalculator, CryptoSystem }; var util = require$$0; const { Buffer: Buffer$2 } = require$$0$1; var PathSet = path.PathSet; var PathLeafElement$1 = path.PathLeafElement; var EmptyLeaf$1 = binarytree.EmptyLeaf; var Leaf$1 = binarytree.Leaf; var Node$1 = binarytree.Node; var BinaryTree = binarytree.BinaryTree; var ArrayHeadNode$1 = binarytree.ArrayHeadNode; var DictHeadNode$1 = binarytree.DictHeadNode; const NO_PATHS = new PathSet([]); /** * The factory does the conversion between list of elements and tree of elements. * * Note: The idea is that you should sub class for each type of element you want to build. */ function BinaryTreeFactory$1() { } /** * Transforms the incoming leaf into an [BinaryTreeElement] * The idea with this function is that it can be recursive (if the leaf in turn is complex object with sub objects). * * Note: If we don't have a path here we can try to find the leaf in the cache. * * @param leaf the raw data we should wrap in a leaf * @param paths a collection of proof paths that might point to this leaf * @return the resulting [BinaryTreeElement] the leaf got converted to */ BinaryTreeFactory$1.prototype.handleLeaf = function (leaf, paths, isRoot = false) { if (paths.length == 0 && !isRoot) { return this.innerHandleLeaf(leaf, this.getEmptyPathSet()); } else { return this.innerHandleLeaf(leaf, paths); } }; /** * */ BinaryTreeFactory$1.prototype.getEmptyPathSet = function () { return NO_PATHS; }; /** * At this point we should have looked in cache. * * @param leaf we should turn into a tree element * @param {PathSet} paths * @return the tree element we created. */ BinaryTreeFactory$1.prototype.innerHandleLeaf = function (leaf, paths) { if (leaf == null) { return this.handlePrimitiveLeaf(leaf, paths); } if (Buffer$2.isBuffer(leaf)) { return this.handlePrimitiveLeaf(leaf, paths); } if (typeof leaf === 'string') { return this.handlePrimitiveLeaf(leaf, paths); } if (typeof leaf === 'number') { return this.handlePrimitiveLeaf(leaf, paths); } if (typeof leaf === 'bigint') { return this.handlePrimitiveLeaf(leaf, paths); } if (typeof leaf === 'boolean') { return this.handlePrimitiveLeaf(leaf ? 1 : 0, paths); } if (leaf.constructor === Array) { return this.buildFromArray(leaf, paths); } if (typeof leaf === 'object') { return this.buildFromDictionary(leaf, paths); } else { throw new Error("Unsupported data type"); } }; /** * Just like [handleLeaf] but we know that this leaf should not be a complex type, but something we can * immediately wrap * * @param leaf * @param {PathSet} paths */ BinaryTreeFactory$1.prototype.handlePrimitiveLeaf = function (leaf, paths) { var pathElem = paths.getPathLeafOrElseAnyCurrentPathElement(); if (pathElem != null && !(pathElem instanceof PathLeafElement$1)) { throw new Error("Path does not match the tree structure. We are at a leaf " + leaf + " but found path element " + pathElem); } return new Leaf$1(leaf, pathElem); }; /** * Calls itself until the return value only holds 1 element * * Note: This method can only create standard [Node] that fills up the area between the "top" and the leaves. * These "in-between" nodes cannot be "path leaf" or have any interesting properties. * * @param layer What layer we aim calculate * @param inList The args of nodes we should build from * @return All [BinaryTreeElement] nodes of the next layer */ BinaryTreeFactory$1.prototype.buildHigherLayer = function (layer, inList) { if (inList.length === 0) { throw new Error("Cannot work on empty arrays. Layer: " + layer); } else if (inList.length === 1) { return inList; } var returnArray = new Array(); var nrOfNodesToCreate = Math.floor(inList.length / 2); var leftValue = null; var isLeft = true; for (var i = 0; i < inList.length; i++) { if (isLeft) { leftValue = inList[i]; isLeft = false; } else { var tempNode = new Node$1(leftValue, inList[i]); returnArray.push(tempNode); nrOfNodesToCreate--; isLeft = true; leftValue = null; } } if (!isLeft) { // If there is odd number of nodes, then move the last node up one level returnArray.push(leftValue); } // Extra check if (nrOfNodesToCreate != 0) { util.logDebug("Why didn't we build exactly the correct amount? Layer: " + layer + " , residue: " + nrOfNodesToCreate + " , input args size: " + inList.length + "."); } return this.buildHigherLayer((layer + 1), returnArray); }; BinaryTreeFactory$1.prototype.build = function (data) { return this.buildWithPath(data, NO_PATHS); }; /** * @param {PathSet} paths */ BinaryTreeFactory$1.prototype.buildWithPath = function (data, paths) { var result = this.handleLeaf(data, paths, true); return new BinaryTree(result); }; /** * @param {Array} array * @param {PathSet} paths */ BinaryTreeFactory$1.prototype.buildFromArray = function (array, paths) { var pathElem = paths.getPathLeafOrElseAnyCurrentPathElement(); // 1. Build leaf layer if (array.length == 0) { return new ArrayHeadNode$1(new EmptyLeaf$1(), new EmptyLeaf$1(), array, 0, 0, pathElem); } var leafArray = this.buildLeafElements(array, paths); // 2. Build all higher layers var result = this.buildHigherLayer(1, leafArray); // 3. Fix and return the root node var orgRoot = result[0]; if (orgRoot instanceof Node$1) { return new ArrayHeadNode$1(orgRoot.left, orgRoot.right, array, array.length, pathElem); } if (orgRoot instanceof Leaf$1) { return this.buildFromOneLeaf(array, orgRoot, pathElem); } else { throw new Error("Should not find element of this type here"); } }; /** * */ BinaryTreeFactory$1.prototype.buildFromOneLeaf = function (array, orgRoot, pathElem) { if (array.length > 1) { throw new Error("How come we got a leaf returned when we had " + array.length + " elements is the args?"); } else { return new ArrayHeadNode$1(orgRoot, new EmptyLeaf$1(), array, array.length, pathElem); } }; /** * @param {PathSet} paths */ BinaryTreeFactory$1.prototype.buildLeafElements = function (leafList, paths) { var leafArray = new Array(); var onlyArrayPaths = paths.keepOnlyArrayPaths(); // For performance, since we will loop soon for (var i = 0; i < leafList.length; i++) { var pathsRelevantForThisLeaf = onlyArrayPaths.getTailIfFirstElementIsArrayOfThisIndexFromList(i); var leaf = leafList[i]; var binaryTreeElement = this.handleLeaf(leaf, pathsRelevantForThisLeaf); leafArray.push(binaryTreeElement); } return leafArray; }; /** * @param {PathSet} paths */ BinaryTreeFactory$1.prototype.buildFromDictionary = function (dict, paths) { var pathElem = paths.getPathLeafOrElseAnyCurrentPathElement(); // Needs to be sorted, or else the order is undefined var keys = Object.keys(dict).sort(); if (keys.length == 0) { return new DictHeadNode$1(new EmptyLeaf$1(), new EmptyLeaf$1(), dict, keys.length, 0, pathElem); } // 1. Build first (leaf) layer var leafArray = this.buildLeafElementFromDict(keys, dict, paths); // 2. Build all higher layers var result = this.buildHigherLayer(1, leafArray); // 3. Fix and return the root node var orgRoot = result[0]; if (orgRoot instanceof Node$1) { return new DictHeadNode$1(orgRoot.left, orgRoot.right, dict, keys.length, pathElem); } else { throw new Error("Should not find element of this type here: " + typeof orgRoot); } }; /** * @param {PathSet} paths */ BinaryTreeFactory$1.prototype.buildLeafElementFromDict = function (keys, dict, paths) { var leafArray = new Array(); var onlyDictPaths = paths.keepOnlyDictPaths(); // For performance, since we will loop soon for (var i = 0; i < keys.length; i++) { // The key cannot not be proved, so NO_PATHS var key = keys[i]; var keyElement = this.handleLeaf(key, NO_PATHS); leafArray.push(keyElement); var content = dict[key]; var pathsRelevantForThisLeaf = onlyDictPaths.getTailIfFirstElementIsDictOfThisKeyFromList(key); var contentElement = this.handleLeaf(content, pathsRelevantForThisLeaf); leafArray.push(contentElement); } return leafArray; }; var binarytreefactory = { BinaryTreeFactory: BinaryTreeFactory$1 }; var HASH_PREFIX_NODE = binarytree.HASH_PREFIX_NODE; var HASH_PREFIX_NODE_ARRAY = binarytree.HASH_PREFIX_NODE_ARRAY; var HASH_PREFIX_NODE_DICT = binarytree.HASH_PREFIX_NODE_DICT; /** * */ function MerkleProofElement() { } /** * * @param {Buffer} prefix * @param {MerkleProofElement} left * @param {MerkleProofElement} right */ function ProofNode$1(prefix, left, right) { this.prefix = prefix; this.left = left; this.right = right; } ProofNode$1.prototype = Object.create(MerkleProofElement.prototype); ProofNode$1.prototype.constructor = ProofNode$1; /** * * @param {MerkleProofElement} left * @param {MerkleProofElement} right */ function ProofNodeSimple$1(left, right) { ProofNode$1.call(this, HASH_PREFIX_NODE, left, right); } ProofNodeSimple$1.prototype = Object.create(ProofNode$1.prototype); ProofNodeSimple$1.prototype.constructor = ProofNodeSimple$1; /** * * @param {*} content * @param {SearchablePathElement} pathElem */ function ProofValueLeaf$2(content, pathElem) { this.content = content; this.pathElem = pathElem; } ProofValueLeaf$2.prototype = Object.create(MerkleProofElement.prototype); ProofValueLeaf$2.prototype.constructor = ProofValueLeaf$2; /** * * @param {Buffer} merkleHash */ function ProofHashedLeaf$2(merkleHash) { this.merkleHash = merkleHash; } ProofHashedLeaf$2.prototype = Object.create(MerkleProofElement.prototype); ProofHashedLeaf$2.prototype.constructor = ProofHashedLeaf$2; /** * @param {ProofHashedLeaf} other */ ProofHashedLeaf$2.prototype.equals = function (other) { if (other instanceof ProofHashedLeaf$2) { return this.merkleHash.equals(other.merkleHash); } else { return false; } }; /** * * @param {MerkleProofElement} left * @param {MerkleProofElement} right * @param {SearchablePathElement} pathElem */ function ProofNodeArrayHead$1(left, right, pathElem = null) { ProofNode$1.call(this, HASH_PREFIX_NODE_ARRAY, left, right); this.pathElem = pathElem; } ProofNodeArrayHead$1.prototype = Object.create(ProofNode$1.prototype); ProofNodeArrayHead$1.prototype.constructor = ProofNodeArrayHead$1; /** * * @param {MerkleProofElement} left * @param {MerkleProofElement} right * @param {SearchablePathElement} pathElem */ function ProofNodeDictHead$1(left, right, pathElem = null) { ProofNode$1.call(this, HASH_PREFIX_NODE_DICT, left, right); this.pathElem = pathElem; } ProofNodeDictHead$1.prototype = Object.create(ProofNode$1.prototype); ProofNodeDictHead$1.prototype.constructor = ProofNodeDictHead$1; /** * * @param {MerkleProofElement} root */ function MerkleProofTree$1(root) { this.root = root; } MerkleProofTree$1.prototype.maxLevel = function () { return this.maxLevelInternal(this.root); }; /** * @param {MerkleProofElement} node */ MerkleProofTree$1.prototype.maxLevelInternal = function (node) { if (node instanceof ProofValueLeaf$2) { return 1; } else if (node instanceof ProofHashedLeaf$2) { return 1; } else if (node instanceof ProofNode$1) { return Math.max(this.maxLevelInternal(node.left), this.maxLevelInternal(node.right)) + 1; } else { throw new Error("Should be able to handle node type: " + typeof node); } }; var merkleprooftree = { ProofNode: ProofNode$1, ProofNodeSimple: ProofNodeSimple$1, ProofHashedLeaf: ProofHashedLeaf$2, ProofValueLeaf: ProofValueLeaf$2, ProofNodeArrayHead: ProofNodeArrayHead$1, ProofNodeDictHead: ProofNodeDictHead$1, MerkleProofElement, MerkleProofTree: MerkleProofTree$1 }; const { Buffer: Buffer$1 } = require$$0$1; var Node = binarytree.Node; var Leaf = binarytree.Leaf; var EmptyLeaf = binarytree.EmptyLeaf; var ProofHashedLeaf$1 = merkleprooftree.ProofHashedLeaf; var ProofValueLeaf$1 = merkleprooftree.ProofValueLeaf; var MerkleProofTree = merkleprooftree.MerkleProofTree; var ProofNodeArrayHead = merkleprooftree.ProofNodeArrayHead; var ProofNodeDictHead = merkleprooftree.ProofNodeDictHead; var PathLeafElement = path.PathLeafElement; var SubTreeRootNode = binarytree.SubTreeRootNode; var ArrayHeadNode = binarytree.ArrayHeadNode; var DictHeadNode = binarytree.DictHeadNode; var ProofNodeSimple = merkleprooftree.ProofNodeSimple; const EMPTY_HASH = new Buffer$1.alloc(32); /** * */ function MerkleProofTreeFactory$1() { } /** * @param {BinaryTree} originalTree */ MerkleProofTreeFactory$1.prototype.buildFromBinaryTree = function (originalTree, calculator) { var rootElem = this.buildFromBinaryTreeInternal(originalTree.root, calculator); return new MerkleProofTree(rootElem); }; /** * @param {BinaryTreeElement} elem * @param {*} calculator */ MerkleProofTreeFactory$1.prototype.buildFromBinaryTreeInternal = function (elem, calculator) { if (elem instanceof EmptyLeaf) { return new ProofHashedLeaf$1(EMPTY_HASH); } else if (elem instanceof Leaf) { var pathElem = elem.pathElem; if (pathElem != null) { if (pathElem instanceof PathLeafElement) { return new ProofValueLeaf$1(elem.content, pathElem.previous); } else { throw new Error("The path and structure don't match. We are at a leaf, but path elem is not a leaf: " + pathElem); } } else { // make a hash var hash = calculator.calculateLeafHash(elem.content); return new ProofHashedLeaf$1(hash); } } else if (elem instanceof SubTreeRootNode) { var pathElem = elem.pathElem; if (pathElem != null) { if (pathElem instanceof PathLeafElement) { // Don't convert it return new ProofValueLeaf$1(elem.content, pathElem.previous); } else { return this.convertNode(elem, calculator); } } else { return this.convertNode(elem, calculator); } } else if (elem instanceof Node) { return this.convertNode(elem, calculator); } else { throw new Error("Cannot handle " + elem); } }; /** * @param {Node} node */ MerkleProofTreeFactory$1.prototype.convertNode = function (node, calculator) { var left = this.buildFromBinaryTreeInternal(node.left, calculator); var right = this.buildFromBinaryTreeInternal(node.right, calculator); if (left instanceof ProofHashedLeaf$1 && right instanceof ProofHashedLeaf$1) { var addedHash = calculator.calculateNodeHash(node.getPrefixByte(), left.merkleHash, right.merkleHash); return new ProofHashedLeaf$1(addedHash); } else { return this.buildNodeOfCorrectType(node, left, right); } }; /** * @param {ArrayHeadNode} node */ MerkleProofTreeFactory$1.prototype.extractSearchablePathElement = function (node) { var pathElem = node.pathElem; if (pathElem != null) { return pathElem.previous; } else { return null; } }; /** * @param {Node} node * @param {MerkleProofElement} left * @param {MerkleProofElement} right */ MerkleProofTreeFactory$1.prototype.buildNodeOfCorrectType = function (node, left, right) { if (node instanceof ArrayHeadNode) { return new ProofNodeArrayHead(left, right, this.extractSearchablePathElement(node)); } else if (node instanceof DictHeadNode) { return new ProofNodeDictHead(left, right, this.extractSearchablePathElement(node)); } else if (node instanceof Node) { return new ProofNodeSimple(left, right); } else { throw new Error("Should have taken care of this node type: " + node); } }; var merkleprooftreefactory = { MerkleProofTreeFactory: MerkleProofTreeFactory$1 }; /** * * @param {Buffer} merkleHash */ function MerkleHashSummary$1(merkleHash) { this.merkleHash = merkleHash; } /** * @param {MerkleHashSummary} other */ MerkleHashSummary$1.prototype.equals = function (other) { if (this === other) return true; if (typeof this != typeof other) return false; if (this.merkleHash.compare(other.merkleHash) === 0) { return true; } return false; }; var merklehashcarrier = { MerkleHashSummary: MerkleHashSummary$1 }; var ProofHashedLeaf = merkleprooftree.ProofHashedLeaf; var ProofValueLeaf = merkleprooftree.ProofValueLeaf; var ProofNode = merkleprooftree.ProofNode; var MerkleHashSummary = merklehashcarrier.MerkleHashSummary; /** * * @param {BinaryTreeFactory} treeFactory * @param {MerkleProofTreeFactory} proofFactory */ function MerkleHashSummaryFactory$1(treeFactory, proofFactory) { this.treeFactory = treeFactory; this.proofFactory = proofFactory; } /** * @param {any} value * @param {MerkleHashCalculator} calculator */ MerkleHashSummaryFactory$1.prototype.calculateMerkleRoot = function (value, calculator) { var binaryTree = this.treeFactory.build(value); var proofTree = this.proofFactory.buildFromBinaryTree(binaryTree, calculator); return this.calculateMerkleRootOfTree(proofTree, calculator); }; /** * @param {MerkleProofTree} value * @param {MerkleHashCalculator} calculator */ MerkleHashSummaryFactory$1.prototype.calculateMerkleTreeRoot = function (tree, calculator) { return this.calculateMerkleRootOfTree(tree, calculator); }; /** * @param {MerkleProofTree} proofTree * @param {MerkleHashCalculator} calculator */ MerkleHashSummaryFactory$1.prototype.calculateMerkleRootOfTree = function (proofTree, calculator) { var calculatedSummary = this.calculateMerkleRootInternal(proofTree.root, calculator); return new MerkleHashSummary(calculatedSummary); }; /** * @param {MerkleProofElement} currentElement * @param {MerkleHashCalculator} calculator */ MerkleHashSummaryFactory$1.prototype.calculateMerkleRootInternal = function (currentElement, calcul