UNPKG

@0xcert/merkle

Version:

Implementation of basic functions of binary Merkle tree.

97 lines 4.72 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Merkle = exports.MerkleHasherPosition = void 0; var MerkleHasherPosition; (function (MerkleHasherPosition) { MerkleHasherPosition[MerkleHasherPosition["VALUE"] = 0] = "VALUE"; MerkleHasherPosition[MerkleHasherPosition["LEAF"] = 1] = "LEAF"; MerkleHasherPosition[MerkleHasherPosition["NODE"] = 2] = "NODE"; })(MerkleHasherPosition = exports.MerkleHasherPosition || (exports.MerkleHasherPosition = {})); class Merkle { constructor(options) { this._options = Object.assign({ hasher: (v) => v, noncer: () => '' }, options); } hash(value, path, position) { return this._options.hasher(value, path, position); } nonce(path) { return this._options.noncer(path); } notarize(data, prepend = []) { return __awaiter(this, void 0, void 0, function* () { const values = [...data]; const nonces = []; const empty = yield this._options.noncer([...prepend, values.length]); const nodes = [yield this._options.hasher(empty, [...prepend, values.length], MerkleHasherPosition.NODE)]; for (let i = values.length - 1; i >= 0; i--) { const right = nodes[0]; nonces.unshift(yield this._options.noncer([...prepend, i])); const value = yield this._options.hasher(values[i], [...prepend, i], MerkleHasherPosition.VALUE); nodes.unshift(yield this._options.hasher(`${value}${nonces[0]}`, [...prepend, i], MerkleHasherPosition.LEAF)); const left = nodes[0]; nodes.unshift(yield this._options.hasher(`${left}${right}`, [...prepend, i], MerkleHasherPosition.NODE)); } return { values: values.map((value, index) => ({ index, value, nonce: nonces[index] })), nodes: nodes.map((hash, index) => ({ index, hash })), }; }); } disclose(recipe, expose) { return __awaiter(this, void 0, void 0, function* () { const size = Math.max(...expose.map((i) => i + 1), 0); const values = []; const nodes = [ recipe.nodes.find((n) => n.index === size * 2), ]; for (let i = size - 1; i >= 0; i--) { if (expose.indexOf(i) !== -1) { values.unshift(recipe.values.find((n) => n.index === i)); } else { nodes.unshift(recipe.nodes.find((n) => n.index === i * 2 + 1)); } } return { values, nodes }; }); } imprint(recipe) { return __awaiter(this, void 0, void 0, function* () { const nodes = [ ...yield Promise.all(recipe.values.map((v, i) => __awaiter(this, void 0, void 0, function* () { const value = yield this._options.hasher(v.value, [i], MerkleHasherPosition.VALUE); return { index: v.index * 2 + 1, hash: yield this._options.hasher(`${value}${v.nonce}`, [i], MerkleHasherPosition.LEAF), value: v.value, }; }))), ...recipe.nodes, ]; const size = Math.max(...nodes.map((n) => n.index + 1), 0); for (let i = size - 1; i >= 0; i -= 2) { const right = nodes.find((n) => n.index === i); const left = nodes.find((n) => n.index === i - 1); if (right && left) { nodes.unshift({ index: i - 2, hash: yield this._options.hasher(`${left.hash}${right.hash}`, [i], MerkleHasherPosition.NODE), }); } } const root = nodes.find((n) => n.index === 0); return root ? root.hash : null; }); } } exports.Merkle = Merkle; //# sourceMappingURL=merkle.js.map