UNPKG

15.6 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const client_common_1 = require("@neo-one/client-common");
4const utils_1 = require("@neo-one/utils");
5exports.InvalidMerkleTreeException = utils_1.makeErrorWithCode('INVALID_MERKLE_TREE', () => 'Invalid Merkle tree. (no nodes found)');
6class MerkleTreeNode {
7 constructor({ hash, leftChild, rightChild, parent, }) {
8 this.hash = hash;
9 this.leftChild = leftChild;
10 this.rightChild = rightChild;
11 this.parent = parent;
12 }
13 clone(parent) {
14 const self = new MerkleTreeNode({
15 hash: this.hash,
16 parent,
17 });
18 if (this.leftChild !== undefined) {
19 self.leftChild = this.leftChild.clone(self);
20 }
21 if (this.rightChild !== undefined) {
22 self.rightChild = this.rightChild.clone(self);
23 }
24 return self;
25 }
26}
27const build = (leavesIn) => {
28 const leaves = leavesIn;
29 if (leaves.length === 0) {
30 throw new exports.InvalidMerkleTreeException();
31 }
32 if (leaves.length === 1) {
33 return leaves[0];
34 }
35 const parents = [];
36 const length = Math.floor((leaves.length + 1) / 2);
37 for (let i = 0; i < length; i += 1) {
38 const leftChild = leaves[i * 2];
39 const rightChild = i * 2 + 1 === leaves.length ? leftChild : leaves[i * 2 + 1];
40 const node = new MerkleTreeNode({
41 hash: client_common_1.crypto.hash256(Buffer.concat([client_common_1.common.uInt256ToBuffer(leftChild.hash), client_common_1.common.uInt256ToBuffer(rightChild.hash)])),
42 leftChild,
43 rightChild,
44 });
45 parents[i] = node;
46 leaves[i * 2].parent = node;
47 if (i * 2 + 1 !== leaves.length) {
48 leaves[i * 2 + 1].parent = node;
49 }
50 }
51 return build(parents);
52};
53const trim = (node, index, depth, flags) => {
54 const { leftChild, rightChild } = node;
55 if (depth === 1 || leftChild === undefined) {
56 return;
57 }
58 if (depth === 2) {
59 if (!flags[index * 2] && !flags[index * 2 + 1]) {
60 node.leftChild = undefined;
61 node.rightChild = undefined;
62 }
63 }
64 else if (rightChild !== undefined) {
65 trim(leftChild, index * 2, depth - 1, flags);
66 trim(rightChild, index * 2 + 1, depth - 1, flags);
67 if (leftChild.leftChild === undefined && rightChild.rightChild === undefined) {
68 node.leftChild = undefined;
69 node.rightChild = undefined;
70 }
71 }
72};
73const depthFirstSearchWorker = (node, mutableHashes) => {
74 const { leftChild, rightChild } = node;
75 if (leftChild === undefined || rightChild === undefined) {
76 mutableHashes.push(node.hash);
77 }
78 else {
79 depthFirstSearchWorker(leftChild, mutableHashes);
80 depthFirstSearchWorker(rightChild, mutableHashes);
81 }
82};
83const depthFirstSearch = (node) => {
84 const mutableHashes = [];
85 depthFirstSearchWorker(node, mutableHashes);
86 return mutableHashes;
87};
88class MerkleTree {
89 static computeRoot(hashes) {
90 const tree = new this(hashes);
91 return tree.root.hash;
92 }
93 constructor(hashesOrNode) {
94 this.root = Array.isArray(hashesOrNode)
95 ? build(hashesOrNode.map((hash) => new MerkleTreeNode({ hash })))
96 : hashesOrNode;
97 this.depth = 1;
98 for (let node = this.root; node.leftChild !== undefined; node = node.leftChild) {
99 this.depth += 1;
100 }
101 }
102 trim(flags) {
103 const result = this.root.clone();
104 trim(result, 0, this.depth, flags);
105 return new MerkleTree(result);
106 }
107 depthFirstSearch() {
108 return depthFirstSearch(this.root);
109 }
110 toHashArray() {
111 return this.depthFirstSearch();
112 }
113}
114exports.MerkleTree = MerkleTree;
115
116//# sourceMappingURL=data:application/json;charset=utf8;base64,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QyxDQUFDO1FBRWYsS0FBSyxJQUFJLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQzlFLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDO1NBQ2pCO0lBQ0gsQ0FBQztJQUVNLElBQUksQ0FBQyxLQUF5QjtRQUNuQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbkMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNoQyxDQUFDO0lBRU0sZ0JBQWdCO1FBQ3JCLE9BQU8sZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFTSxXQUFXO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDakMsQ0FBQztDQUNGO0FBbkNELGdDQW1DQyIsImZpbGUiOiJuZW8tb25lLW5vZGUtY29yZS9zcmMvY3J5cHRvL01lcmtsZVRyZWUuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB0c2xpbnQ6ZGlzYWJsZSByZWFkb25seS1rZXl3b3JkIG5vLW9iamVjdC1tdXRhdGlvbiBuby1hcnJheS1tdXRhdGlvblxuaW1wb3J0IHsgY29tbW9uLCBjcnlwdG8sIFVJbnQyNTYgfSBmcm9tICdAbmVvLW9uZS9jbGllbnQtY29tbW9uJztcbmltcG9ydCB7IG1ha2VFcnJvcldpdGhDb2RlIH0gZnJvbSAnQG5lby1vbmUvdXRpbHMnO1xuXG5leHBvcnQgY29uc3QgSW52YWxpZE1lcmtsZVRyZWVFeGNlcHRpb24gPSBtYWtlRXJyb3JXaXRoQ29kZShcbiAgJ0lOVkFMSURfTUVSS0xFX1RSRUUnLFxuICAoKSA9PiAnSW52YWxpZCBNZXJrbGUgdHJlZS4gKG5vIG5vZGVzIGZvdW5kKScsXG4pO1xuXG5jbGFzcyBNZXJrbGVUcmVlTm9kZSB7XG4gIHB1YmxpYyByZWFkb25seSBoYXNoOiBVSW50MjU2O1xuICBwdWJsaWMgbGVmdENoaWxkOiBNZXJrbGVUcmVlTm9kZSB8IHVuZGVmaW5lZDtcbiAgcHVibGljIHJpZ2h0Q2hpbGQ6IE1lcmtsZVRyZWVOb2RlIHwgdW5kZWZpbmVkO1xuICBwdWJsaWMgcGFyZW50OiBNZXJrbGVUcmVlTm9kZSB8IHVuZGVmaW5lZDtcblxuICBwdWJsaWMgY29uc3RydWN0b3Ioe1xuICAgIGhhc2gsXG4gICAgbGVmdENoaWxkLFxuICAgIHJpZ2h0Q2hpbGQsXG4gICAgcGFyZW50LFxuICB9OiB7XG4gICAgcmVhZG9ubHkgaGFzaDogVUludDI1NjtcbiAgICByZWFkb25seSBsZWZ0Q2hpbGQ/OiBNZXJrbGVUcmVlTm9kZTtcbiAgICByZWFkb25seSByaWdodENoaWxkPzogTWVya2xlVHJlZU5vZGU7XG4gICAgcmVhZG9ubHkgcGFyZW50PzogTWVya2xlVHJlZU5vZGU7XG4gIH0pIHtcbiAgICB0aGlzLmhhc2ggPSBoYXNoO1xuICAgIHRoaXMubGVmdENoaWxkID0gbGVmdENoaWxkO1xuICAgIHRoaXMucmlnaHRDaGlsZCA9IHJpZ2h0Q2hpbGQ7XG4gICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gIH1cblxuICBwdWJsaWMgY2xvbmUocGFyZW50PzogTWVya2xlVHJlZU5vZGUpOiBNZXJrbGVUcmVlTm9kZSB7XG4gICAgY29uc3Qgc2VsZiA9IG5ldyBNZXJrbGVUcmVlTm9kZSh7XG4gICAgICBoYXNoOiB0aGlzLmhhc2gsXG4gICAgICBwYXJlbnQsXG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5sZWZ0Q2hpbGQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgc2VsZi5sZWZ0Q2hpbGQgPSB0aGlzLmxlZnRDaGlsZC5jbG9uZShzZWxmKTtcbiAgICB9XG4gICAgaWYgKHRoaXMucmlnaHRDaGlsZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBzZWxmLnJpZ2h0Q2hpbGQgPSB0aGlzLnJpZ2h0Q2hpbGQuY2xvbmUoc2VsZik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbGY7XG4gIH1cbn1cblxuY29uc3QgYnVpbGQgPSAobGVhdmVzSW46IHJlYWRvbmx5IE1lcmtsZVRyZWVOb2RlW10pOiBNZXJrbGVUcmVlTm9kZSA9PiB7XG4gIGNvbnN0IGxlYXZlcyA9IGxlYXZlc0luO1xuICBpZiAobGVhdmVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHRocm93IG5ldyBJbnZhbGlkTWVya2xlVHJlZUV4Y2VwdGlvbigpO1xuICB9XG4gIGlmIChsZWF2ZXMubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIGxlYXZlc1swXTtcbiAgfVxuXG4gIGNvbnN0IHBhcmVudHMgPSBbXTtcbiAgY29uc3QgbGVuZ3RoID0gTWF0aC5mbG9vcigobGVhdmVzLmxlbmd0aCArIDEpIC8gMik7XG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1sb29wLXN0YXRlbWVudFxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgY29uc3QgbGVmdENoaWxkID0gbGVhdmVzW2kgKiAyXTtcblxuICAgIGNvbnN0IHJpZ2h0Q2hpbGQgPSBpICogMiArIDEgPT09IGxlYXZlcy5sZW5ndGggPyBsZWZ0Q2hpbGQgOiBsZWF2ZXNbaSAqIDIgKyAxXTtcbiAgICBjb25zdCBub2RlID0gbmV3IE1lcmtsZVRyZWVOb2RlKHtcbiAgICAgIGhhc2g6IGNyeXB0by5oYXNoMjU2KFxuICAgICAgICBCdWZmZXIuY29uY2F0KFtjb21tb24udUludDI1NlRvQnVmZmVyKGxlZnRDaGlsZC5oYXNoKSwgY29tbW9uLnVJbnQyNTZUb0J1ZmZlcihyaWdodENoaWxkLmhhc2gpXSksXG4gICAgICApLFxuICAgICAgbGVmdENoaWxkLFxuICAgICAgcmlnaHRDaGlsZCxcbiAgICB9KTtcblxuICAgIHBhcmVudHNbaV0gPSBub2RlO1xuICAgIGxlYXZlc1tpICogMl0ucGFyZW50ID0gbm9kZTtcblxuICAgIGlmIChpICogMiArIDEgIT09IGxlYXZlcy5sZW5ndGgpIHtcbiAgICAgIGxlYXZlc1tpICogMiArIDFdLnBhcmVudCA9IG5vZGU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1aWxkKHBhcmVudHMpO1xufTtcblxuY29uc3QgdHJpbSA9IChub2RlOiBNZXJrbGVUcmVlTm9kZSwgaW5kZXg6IG51bWJlciwgZGVwdGg6IG51bWJlciwgZmxhZ3M6IHJlYWRvbmx5IGJvb2xlYW5bXSkgPT4ge1xuICBjb25zdCB7IGxlZnRDaGlsZCwgcmlnaHRDaGlsZCB9ID0gbm9kZTtcbiAgaWYgKGRlcHRoID09PSAxIHx8IGxlZnRDaGlsZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKGRlcHRoID09PSAyKSB7XG4gICAgaWYgKCFmbGFnc1tpbmRleCAqIDJdICYmICFmbGFnc1tpbmRleCAqIDIgKyAxXSkge1xuICAgICAgbm9kZS5sZWZ0Q2hpbGQgPSB1bmRlZmluZWQ7XG4gICAgICBub2RlLnJpZ2h0Q2hpbGQgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9IGVsc2UgaWYgKHJpZ2h0Q2hpbGQgIT09IHVuZGVmaW5lZCkge1xuICAgIHRyaW0obGVmdENoaWxkLCBpbmRleCAqIDIsIGRlcHRoIC0gMSwgZmxhZ3MpO1xuICAgIHRyaW0ocmlnaHRDaGlsZCwgaW5kZXggKiAyICsgMSwgZGVwdGggLSAxLCBmbGFncyk7XG4gICAgaWYgKGxlZnRDaGlsZC5sZWZ0Q2hpbGQgPT09IHVuZGVmaW5lZCAmJiByaWdodENoaWxkLnJpZ2h0Q2hpbGQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgbm9kZS5sZWZ0Q2hpbGQgPSB1bmRlZmluZWQ7XG4gICAgICBub2RlLnJpZ2h0Q2hpbGQgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG59O1xuXG5jb25zdCBkZXB0aEZpcnN0U2VhcmNoV29ya2VyID0gKG5vZGU6IE1lcmtsZVRyZWVOb2RlLCBtdXRhYmxlSGFzaGVzOiBVSW50MjU2W10pOiB2b2lkID0+IHtcbiAgY29uc3QgeyBsZWZ0Q2hpbGQsIHJpZ2h0Q2hpbGQgfSA9IG5vZGU7XG4gIGlmIChsZWZ0Q2hpbGQgPT09IHVuZGVmaW5lZCB8fCByaWdodENoaWxkID09PSB1bmRlZmluZWQpIHtcbiAgICBtdXRhYmxlSGFzaGVzLnB1c2gobm9kZS5oYXNoKTtcbiAgfSBlbHNlIHtcbiAgICBkZXB0aEZpcnN0U2VhcmNoV29ya2VyKGxlZnRDaGlsZCwgbXV0YWJsZUhhc2hlcyk7XG4gICAgZGVwdGhGaXJzdFNlYXJjaFdvcmtlcihyaWdodENoaWxkLCBtdXRhYmxlSGFzaGVzKTtcbiAgfVxufTtcblxuY29uc3QgZGVwdGhGaXJzdFNlYXJjaCA9IChub2RlOiBNZXJrbGVUcmVlTm9kZSk6IHJlYWRvbmx5IFVJbnQyNTZbXSA9PiB7XG4gIGNvbnN0IG11dGFibGVIYXNoZXM6IFVJbnQyNTZbXSA9IFtdO1xuICBkZXB0aEZpcnN0U2VhcmNoV29ya2VyKG5vZGUsIG11dGFibGVIYXNoZXMpO1xuXG4gIHJldHVybiBtdXRhYmxlSGFzaGVzO1xufTtcblxuZXhwb3J0IGNsYXNzIE1lcmtsZVRyZWUge1xuICBwdWJsaWMgc3RhdGljIGNvbXB1dGVSb290KGhhc2hlczogcmVhZG9ubHkgVUludDI1NltdKTogVUludDI1NiB7XG4gICAgY29uc3QgdHJlZSA9IG5ldyB0aGlzKGhhc2hlcyk7XG5cbiAgICByZXR1cm4gdHJlZS5yb290Lmhhc2g7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgcm9vdDogTWVya2xlVHJlZU5vZGU7XG4gIHB1YmxpYyByZWFkb25seSBkZXB0aDogbnVtYmVyO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihoYXNoZXNPck5vZGU6IHJlYWRvbmx5IFVJbnQyNTZbXSB8IE1lcmtsZVRyZWVOb2RlKSB7XG4gICAgdGhpcy5yb290ID0gQXJyYXkuaXNBcnJheShoYXNoZXNPck5vZGUpXG4gICAgICA/IGJ1aWxkKGhhc2hlc09yTm9kZS5tYXAoKGhhc2gpID0+IG5ldyBNZXJrbGVUcmVlTm9kZSh7IGhhc2ggfSkpKVxuICAgICAgOiAoaGFzaGVzT3JOb2RlIGFzIE1lcmtsZVRyZWVOb2RlKTtcbiAgICB0aGlzLmRlcHRoID0gMTtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tbG9vcC1zdGF0ZW1lbnQgbm8tbGV0XG4gICAgZm9yIChsZXQgbm9kZSA9IHRoaXMucm9vdDsgbm9kZS5sZWZ0Q2hpbGQgIT09IHVuZGVmaW5lZDsgbm9kZSA9IG5vZGUubGVmdENoaWxkKSB7XG4gICAgICB0aGlzLmRlcHRoICs9IDE7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHRyaW0oZmxhZ3M6IHJlYWRvbmx5IGJvb2xlYW5bXSk6IE1lcmtsZVRyZWUge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMucm9vdC5jbG9uZSgpO1xuICAgIHRyaW0ocmVzdWx0LCAwLCB0aGlzLmRlcHRoLCBmbGFncyk7XG5cbiAgICByZXR1cm4gbmV3IE1lcmtsZVRyZWUocmVzdWx0KTtcbiAgfVxuXG4gIHB1YmxpYyBkZXB0aEZpcnN0U2VhcmNoKCk6IHJlYWRvbmx5IFVJbnQyNTZbXSB7XG4gICAgcmV0dXJuIGRlcHRoRmlyc3RTZWFyY2godGhpcy5yb290KTtcbiAgfVxuXG4gIHB1YmxpYyB0b0hhc2hBcnJheSgpOiByZWFkb25seSBVSW50MjU2W10ge1xuICAgIHJldHVybiB0aGlzLmRlcHRoRmlyc3RTZWFyY2goKTtcbiAgfVxufVxuIl19