UNPKG

ts-mls

Version:

[![CI](https://github.com/LukaJCB/ts-mls/actions/workflows/ci.yml/badge.svg)](https://github.com/LukaJCB/ts-mls/actions/workflows/ci.yml) [![npm version](https://badge.fury.io/js/ts-mls.svg)](https://badge.fury.io/js/ts-mls) [![Coverage Status](https://co

70 lines 3.18 kB
import { encodeUint32, decodeUint32 } from "./codec/number"; import { encodeOptional, decodeOptional } from "./codec/optional"; import { mapDecoders, flatMapDecoder } from "./codec/tlsDecoder"; import { contramapEncoders } from "./codec/tlsEncoder"; import { encodeVarLenData, decodeVarLenData } from "./codec/variableLength"; import { encodeLeafNode, decodeLeafNode } from "./leafNode"; import { InternalError } from "./mlsError"; import { encodeNodeType, decodeNodeType } from "./nodeType"; import { encodeParentNode, decodeParentNode } from "./parentNode"; import { rootFromNodeWidth, isLeaf, nodeToLeafIndex, left, right } from "./treemath"; export const encodeLeafNodeHashInput = contramapEncoders([encodeNodeType, encodeUint32, encodeOptional(encodeLeafNode)], (input) => [input.nodeType, input.leafIndex, input.leafNode]); export const decodeLeafNodeHashInput = mapDecoders([decodeUint32, decodeOptional(decodeLeafNode)], (leafIndex, leafNode) => ({ nodeType: "leaf", leafIndex, leafNode, })); export const encodeParentNodeHashInput = contramapEncoders([encodeNodeType, encodeOptional(encodeParentNode), encodeVarLenData, encodeVarLenData], (input) => [input.nodeType, input.parentNode, input.leftHash, input.rightHash]); export const decodeParentNodeHashInput = mapDecoders([decodeOptional(decodeParentNode), decodeVarLenData, decodeVarLenData], (parentNode, leftHash, rightHash) => ({ nodeType: "parent", parentNode, leftHash, rightHash, })); export const encodeTreeHashInput = (input) => { switch (input.nodeType) { case "leaf": return encodeLeafNodeHashInput(input); case "parent": return encodeParentNodeHashInput(input); } }; export const decodeTreeHashInput = flatMapDecoder(decodeNodeType, (nodeType) => { switch (nodeType) { case "leaf": return decodeLeafNodeHashInput; case "parent": return decodeParentNodeHashInput; } }); export async function treeHashRoot(tree, h) { return treeHash(tree, rootFromNodeWidth(tree.length), h); } export async function treeHash(tree, subtreeIndex, h) { if (isLeaf(subtreeIndex)) { const leafNode = tree[subtreeIndex]; if (leafNode?.nodeType === "parent") throw new InternalError("Somehow found parent node in leaf position"); const input = encodeLeafNodeHashInput({ nodeType: "leaf", leafIndex: nodeToLeafIndex(subtreeIndex), leafNode: leafNode?.leaf, }); return await h.digest(input); } else { const parentNode = tree[subtreeIndex]; if (parentNode?.nodeType === "leaf") throw new InternalError("Somehow found leaf node in parent position"); const leftHash = await treeHash(tree, left(subtreeIndex), h); const rightHash = await treeHash(tree, right(subtreeIndex), h); const input = { nodeType: "parent", parentNode: parentNode?.parent, leftHash: leftHash, rightHash: rightHash, }; return await h.digest(encodeParentNodeHashInput(input)); } } //# sourceMappingURL=treeHash.js.map