@ethereumjs/binarytree
Version:
Implementation of binary trees as used in Ethereum.
66 lines • 2.85 kB
JavaScript
import { bytesToHex, concatBytes, equalsBytes } from '@ethereumjs/util';
import { InternalBinaryNode } from "./node/internalNode.js";
import { StemBinaryNode } from "./node/stemNode.js";
import { decodeBinaryNode } from "./node/util.js";
/**
* Recursively walks down the tree from a given starting node and returns all the leaf values
* @param tree - The binary tree
* @param startingNode - The starting node
* @returns An array of key-value pairs containing the tree keys and associated values
*/
export const dumpLeafValues = async (tree, startingNode) => {
if (equalsBytes(startingNode, tree.EMPTY_TREE_ROOT) === true)
return;
// Retrieve starting node from DB
const rawNode = await tree['_db'].get(startingNode);
if (rawNode === undefined)
return;
const node = decodeBinaryNode(rawNode);
const entries = [];
if (node instanceof StemBinaryNode) {
for (const [idx, val] of node.values.entries()) {
if (val !== null) {
entries.push([bytesToHex(concatBytes(node.stem, Uint8Array.from([idx]))), bytesToHex(val)]);
}
}
return entries;
}
else {
const childPaths = node.children
.filter((value) => value !== null)
.map((value) => dumpLeafValues(tree, value.hash));
const res = (await Promise.all(childPaths)).filter((val) => val !== undefined);
return res.flat(1);
}
};
/**
* Recursively walks down the tree from a given starting node and returns all the node paths and hashes
* @param tree - The binary tree
* @param startingNode - The starting node
* @returns An array of key-value pairs containing the tree paths and associated hashes
*/
export const dumpNodeHashes = async (tree, startingNode) => {
let entries = [];
// Retrieve starting node from DB
const rawNode = await tree['_db'].get(startingNode);
if (rawNode === undefined)
return;
const node = decodeBinaryNode(rawNode);
// If current node is root, push '0x' for path and node hash for commitment
equalsBytes(startingNode, tree.root()) && entries.push(['0x', bytesToHex(startingNode)]);
if (node instanceof InternalBinaryNode) {
const children = node.children.filter((value) => value !== null);
// Push non-null children paths and hashes
for (const child of children) {
entries.push([child.path.join(''), bytesToHex(child.hash)]);
}
// Recursively call dumpNodeHashes on each child node
const childPaths = (await Promise.all(children.map((value) => dumpNodeHashes(tree, value.hash))))
.filter((val) => val !== undefined)
.flat(1);
// Add all child paths and hashes to entries
entries = [...entries, ...childPaths];
}
return entries;
};
//# sourceMappingURL=util.js.map