1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const client_common_1 = require("@neo-one/client-common");
|
4 | const utils_1 = require("@neo-one/utils");
|
5 | exports.InvalidMerkleTreeException = utils_1.makeErrorWithCode('INVALID_MERKLE_TREE', () => 'Invalid Merkle tree. (no nodes found)');
|
6 | class 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 | }
|
27 | const 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 | };
|
53 | const 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 | };
|
73 | const 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 | };
|
83 | const depthFirstSearch = (node) => {
|
84 | const mutableHashes = [];
|
85 | depthFirstSearchWorker(node, mutableHashes);
|
86 | return mutableHashes;
|
87 | };
|
88 | class 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 | }
|
114 | exports.MerkleTree = MerkleTree;
|
115 |
|
116 | //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIk1lcmtsZVRyZWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFDQSwwREFBaUU7QUFDakUsMENBQW1EO0FBRXRDLFFBQUEsMEJBQTBCLEdBQUcseUJBQWlCLENBQ3pELHFCQUFxQixFQUNyQixHQUFHLEVBQUUsQ0FBQyx1Q0FBdUMsQ0FDOUMsQ0FBQztBQUVGLE1BQU0sY0FBYztJQU1sQixZQUFtQixFQUNqQixJQUFJLEVBQ0osU0FBUyxFQUNULFVBQVUsRUFDVixNQUFNLEdBTVA7UUFDQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUMzQixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUN2QixDQUFDO0lBRU0sS0FBSyxDQUFDLE1BQXVCO1FBQ2xDLE1BQU0sSUFBSSxHQUFHLElBQUksY0FBYyxDQUFDO1lBQzlCLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtZQUNmLE1BQU07U0FDUCxDQUFDLENBQUM7UUFFSCxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFO1lBQ2hDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDN0M7UUFDRCxJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssU0FBUyxFQUFFO1lBQ2pDLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDL0M7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7Q0FDRjtBQUVELE1BQU0sS0FBSyxHQUFHLENBQUMsUUFBbUMsRUFBa0IsRUFBRTtJQUNwRSxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUM7SUFDeEIsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUN2QixNQUFNLElBQUksa0NBQTBCLEVBQUUsQ0FBQztLQUN4QztJQUNELElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDdkIsT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDbEI7SUFFRCxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUM7SUFDbkIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFFbkQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQ2xDLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFaEMsTUFBTSxVQUFVLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUMvRSxNQUFNLElBQUksR0FBRyxJQUFJLGNBQWMsQ0FBQztZQUM5QixJQUFJLEVBQUUsc0JBQU0sQ0FBQyxPQUFPLENBQ2xCLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxzQkFBTSxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsc0JBQU0sQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FDakc7WUFDRCxTQUFTO1lBQ1QsVUFBVTtTQUNYLENBQUMsQ0FBQztRQUVILE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUM7UUFDbEIsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBRTVCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssTUFBTSxDQUFDLE1BQU0sRUFBRTtZQUMvQixNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1NBQ2pDO0tBQ0Y7SUFFRCxPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUN4QixDQUFDLENBQUM7QUFFRixNQUFNLElBQUksR0FBRyxDQUFDLElBQW9CLEVBQUUsS0FBYSxFQUFFLEtBQWEsRUFBRSxLQUF5QixFQUFFLEVBQUU7SUFDN0YsTUFBTSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFDdkMsSUFBSSxLQUFLLEtBQUssQ0FBQyxJQUFJLFNBQVMsS0FBSyxTQUFTLEVBQUU7UUFDMUMsT0FBTztLQUNSO0lBRUQsSUFBSSxLQUFLLEtBQUssQ0FBQyxFQUFFO1FBQ2YsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRTtZQUM5QyxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztZQUMzQixJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztTQUM3QjtLQUNGO1NBQU0sSUFBSSxVQUFVLEtBQUssU0FBUyxFQUFFO1FBQ25DLElBQUksQ0FBQyxTQUFTLEVBQUUsS0FBSyxHQUFHLENBQUMsRUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzdDLElBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNsRCxJQUFJLFNBQVMsQ0FBQyxTQUFTLEtBQUssU0FBUyxJQUFJLFVBQVUsQ0FBQyxVQUFVLEtBQUssU0FBUyxFQUFFO1lBQzVFLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1lBQzNCLElBQUksQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDO1NBQzdCO0tBQ0Y7QUFDSCxDQUFDLENBQUM7QUFFRixNQUFNLHNCQUFzQixHQUFHLENBQUMsSUFBb0IsRUFBRSxhQUF3QixFQUFRLEVBQUU7SUFDdEYsTUFBTSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFDdkMsSUFBSSxTQUFTLEtBQUssU0FBUyxJQUFJLFVBQVUsS0FBSyxTQUFTLEVBQUU7UUFDdkQsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDL0I7U0FBTTtRQUNMLHNCQUFzQixDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUNqRCxzQkFBc0IsQ0FBQyxVQUFVLEVBQUUsYUFBYSxDQUFDLENBQUM7S0FDbkQ7QUFDSCxDQUFDLENBQUM7QUFFRixNQUFNLGdCQUFnQixHQUFHLENBQUMsSUFBb0IsRUFBc0IsRUFBRTtJQUNwRSxNQUFNLGFBQWEsR0FBYyxFQUFFLENBQUM7SUFDcEMsc0JBQXNCLENBQUMsSUFBSSxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBRTVDLE9BQU8sYUFBYSxDQUFDO0FBQ3ZCLENBQUMsQ0FBQztBQUVGLE1BQWEsVUFBVTtJQUNkLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBMEI7UUFDbEQsTUFBTSxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFOUIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztJQUN4QixDQUFDO0lBS0QsWUFBbUIsWUFBaUQ7UUFDbEUsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQztZQUNyQyxDQUFDLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksY0FBYyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2pFLENBQUMsQ0FBRSxZQUErQixDQUFDO1FBQ3JDLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBRWYsS0FBSyxJQUFJLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQzlFLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDO1NBQ2pCO0lBQ0gsQ0FBQztJQUVNLElBQUksQ0FBQyxLQUF5QjtRQUNuQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbkMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNoQyxDQUFDO0lBRU0sZ0JBQWdCO1FBQ3JCLE9BQU8sZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFTSxXQUFXO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDakMsQ0FBQztDQUNGO0FBbkNELGdDQW1DQyIsImZpbGUiOiJuZW8tb25lLW5vZGUtY29yZS9zcmMvY3J5cHRvL01lcmtsZVRyZWUuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB0c2xpbnQ6ZGlzYWJsZSByZWFkb25seS1rZXl3b3JkIG5vLW9iamVjdC1tdXRhdGlvbiBuby1hcnJheS1tdXRhdGlvblxuaW1wb3J0IHsgY29tbW9uLCBjcnlwdG8sIFVJbnQyNTYgfSBmcm9tICdAbmVvLW9uZS9jbGllbnQtY29tbW9uJztcbmltcG9ydCB7IG1ha2VFcnJvcldpdGhDb2RlIH0gZnJvbSAnQG5lby1vbmUvdXRpbHMnO1xuXG5leHBvcnQgY29uc3QgSW52YWxpZE1lcmtsZVRyZWVFeGNlcHRpb24gPSBtYWtlRXJyb3JXaXRoQ29kZShcbiAgJ0lOVkFMSURfTUVSS0xFX1RSRUUnLFxuICAoKSA9PiAnSW52YWxpZCBNZXJrbGUgdHJlZS4gKG5vIG5vZGVzIGZvdW5kKScsXG4pO1xuXG5jbGFzcyBNZXJrbGVUcmVlTm9kZSB7XG4gIHB1YmxpYyByZWFkb25seSBoYXNoOiBVSW50MjU2O1xuICBwdWJsaWMgbGVmdENoaWxkOiBNZXJrbGVUcmVlTm9kZSB8IHVuZGVmaW5lZDtcbiAgcHVibGljIHJpZ2h0Q2hpbGQ6IE1lcmtsZVRyZWVOb2RlIHwgdW5kZWZpbmVkO1xuICBwdWJsaWMgcGFyZW50OiBNZXJrbGVUcmVlTm9kZSB8IHVuZGVmaW5lZDtcblxuICBwdWJsaWMgY29uc3RydWN0b3Ioe1xuICAgIGhhc2gsXG4gICAgbGVmdENoaWxkLFxuICAgIHJpZ2h0Q2hpbGQsXG4gICAgcGFyZW50LFxuICB9OiB7XG4gICAgcmVhZG9ubHkgaGFzaDogVUludDI1NjtcbiAgICByZWFkb25seSBsZWZ0Q2hpbGQ/OiBNZXJrbGVUcmVlTm9kZTtcbiAgICByZWFkb25seSByaWdodENoaWxkPzogTWVya2xlVHJlZU5vZGU7XG4gICAgcmVhZG9ubHkgcGFyZW50PzogTWVya2xlVHJlZU5vZGU7XG4gIH0pIHtcbiAgICB0aGlzLmhhc2ggPSBoYXNoO1xuICAgIHRoaXMubGVmdENoaWxkID0gbGVmdENoaWxkO1xuICAgIHRoaXMucmlnaHRDaGlsZCA9IHJpZ2h0Q2hpbGQ7XG4gICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gIH1cblxuICBwdWJsaWMgY2xvbmUocGFyZW50PzogTWVya2xlVHJlZU5vZGUpOiBNZXJrbGVUcmVlTm9kZSB7XG4gICAgY29uc3Qgc2VsZiA9IG5ldyBNZXJrbGVUcmVlTm9kZSh7XG4gICAgICBoYXNoOiB0aGlzLmhhc2gsXG4gICAgICBwYXJlbnQsXG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5sZWZ0Q2hpbGQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgc2VsZi5sZWZ0Q2hpbGQgPSB0aGlzLmxlZnRDaGlsZC5jbG9uZShzZWxmKTtcbiAgICB9XG4gICAgaWYgKHRoaXMucmlnaHRDaGlsZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBzZWxmLnJpZ2h0Q2hpbGQgPSB0aGlzLnJpZ2h0Q2hpbGQuY2xvbmUoc2VsZik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbGY7XG4gIH1cbn1cblxuY29uc3QgYnVpbGQgPSAobGVhdmVzSW46IHJlYWRvbmx5IE1lcmtsZVRyZWVOb2RlW10pOiBNZXJrbGVUcmVlTm9kZSA9PiB7XG4gIGNvbnN0IGxlYXZlcyA9IGxlYXZlc0luO1xuICBpZiAobGVhdmVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHRocm93IG5ldyBJbnZhbGlkTWVya2xlVHJlZUV4Y2VwdGlvbigpO1xuICB9XG4gIGlmIChsZWF2ZXMubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIGxlYXZlc1swXTtcbiAgfVxuXG4gIGNvbnN0IHBhcmVudHMgPSBbXTtcbiAgY29uc3QgbGVuZ3RoID0gTWF0aC5mbG9vcigobGVhdmVzLmxlbmd0aCArIDEpIC8gMik7XG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1sb29wLXN0YXRlbWVudFxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgY29uc3QgbGVmdENoaWxkID0gbGVhdmVzW2kgKiAyXTtcblxuICAgIGNvbnN0IHJpZ2h0Q2hpbGQgPSBpICogMiArIDEgPT09IGxlYXZlcy5sZW5ndGggPyBsZWZ0Q2hpbGQgOiBsZWF2ZXNbaSAqIDIgKyAxXTtcbiAgICBjb25zdCBub2RlID0gbmV3IE1lcmtsZVRyZWVOb2RlKHtcbiAgICAgIGhhc2g6IGNyeXB0by5oYXNoMjU2KFxuICAgICAgICBCdWZmZXIuY29uY2F0KFtjb21tb24udUludDI1NlRvQnVmZmVyKGxlZnRDaGlsZC5oYXNoKSwgY29tbW9uLnVJbnQyNTZUb0J1ZmZlcihyaWdodENoaWxkLmhhc2gpXSksXG4gICAgICApLFxuICAgICAgbGVmdENoaWxkLFxuICAgICAgcmlnaHRDaGlsZCxcbiAgICB9KTtcblxuICAgIHBhcmVudHNbaV0gPSBub2RlO1xuICAgIGxlYXZlc1tpICogMl0ucGFyZW50ID0gbm9kZTtcblxuICAgIGlmIChpICogMiArIDEgIT09IGxlYXZlcy5sZW5ndGgpIHtcbiAgICAgIGxlYXZlc1tpICogMiArIDFdLnBhcmVudCA9IG5vZGU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1aWxkKHBhcmVudHMpO1xufTtcblxuY29uc3QgdHJpbSA9IChub2RlOiBNZXJrbGVUcmVlTm9kZSwgaW5kZXg6IG51bWJlciwgZGVwdGg6IG51bWJlciwgZmxhZ3M6IHJlYWRvbmx5IGJvb2xlYW5bXSkgPT4ge1xuICBjb25zdCB7IGxlZnRDaGlsZCwgcmlnaHRDaGlsZCB9ID0gbm9kZTtcbiAgaWYgKGRlcHRoID09PSAxIHx8IGxlZnRDaGlsZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKGRlcHRoID09PSAyKSB7XG4gICAgaWYgKCFmbGFnc1tpbmRleCAqIDJdICYmICFmbGFnc1tpbmRleCAqIDIgKyAxXSkge1xuICAgICAgbm9kZS5sZWZ0Q2hpbGQgPSB1bmRlZmluZWQ7XG4gICAgICBub2RlLnJpZ2h0Q2hpbGQgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9IGVsc2UgaWYgKHJpZ2h0Q2hpbGQgIT09IHVuZGVmaW5lZCkge1xuICAgIHRyaW0obGVmdENoaWxkLCBpbmRleCAqIDIsIGRlcHRoIC0gMSwgZmxhZ3MpO1xuICAgIHRyaW0ocmlnaHRDaGlsZCwgaW5kZXggKiAyICsgMSwgZGVwdGggLSAxLCBmbGFncyk7XG4gICAgaWYgKGxlZnRDaGlsZC5sZWZ0Q2hpbGQgPT09IHVuZGVmaW5lZCAmJiByaWdodENoaWxkLnJpZ2h0Q2hpbGQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgbm9kZS5sZWZ0Q2hpbGQgPSB1bmRlZmluZWQ7XG4gICAgICBub2RlLnJpZ2h0Q2hpbGQgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG59O1xuXG5jb25zdCBkZXB0aEZpcnN0U2VhcmNoV29ya2VyID0gKG5vZGU6IE1lcmtsZVRyZWVOb2RlLCBtdXRhYmxlSGFzaGVzOiBVSW50MjU2W10pOiB2b2lkID0+IHtcbiAgY29uc3QgeyBsZWZ0Q2hpbGQsIHJpZ2h0Q2hpbGQgfSA9IG5vZGU7XG4gIGlmIChsZWZ0Q2hpbGQgPT09IHVuZGVmaW5lZCB8fCByaWdodENoaWxkID09PSB1bmRlZmluZWQpIHtcbiAgICBtdXRhYmxlSGFzaGVzLnB1c2gobm9kZS5oYXNoKTtcbiAgfSBlbHNlIHtcbiAgICBkZXB0aEZpcnN0U2VhcmNoV29ya2VyKGxlZnRDaGlsZCwgbXV0YWJsZUhhc2hlcyk7XG4gICAgZGVwdGhGaXJzdFNlYXJjaFdvcmtlcihyaWdodENoaWxkLCBtdXRhYmxlSGFzaGVzKTtcbiAgfVxufTtcblxuY29uc3QgZGVwdGhGaXJzdFNlYXJjaCA9IChub2RlOiBNZXJrbGVUcmVlTm9kZSk6IHJlYWRvbmx5IFVJbnQyNTZbXSA9PiB7XG4gIGNvbnN0IG11dGFibGVIYXNoZXM6IFVJbnQyNTZbXSA9IFtdO1xuICBkZXB0aEZpcnN0U2VhcmNoV29ya2VyKG5vZGUsIG11dGFibGVIYXNoZXMpO1xuXG4gIHJldHVybiBtdXRhYmxlSGFzaGVzO1xufTtcblxuZXhwb3J0IGNsYXNzIE1lcmtsZVRyZWUge1xuICBwdWJsaWMgc3RhdGljIGNvbXB1dGVSb290KGhhc2hlczogcmVhZG9ubHkgVUludDI1NltdKTogVUludDI1NiB7XG4gICAgY29uc3QgdHJlZSA9IG5ldyB0aGlzKGhhc2hlcyk7XG5cbiAgICByZXR1cm4gdHJlZS5yb290Lmhhc2g7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgcm9vdDogTWVya2xlVHJlZU5vZGU7XG4gIHB1YmxpYyByZWFkb25seSBkZXB0aDogbnVtYmVyO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihoYXNoZXNPck5vZGU6IHJlYWRvbmx5IFVJbnQyNTZbXSB8IE1lcmtsZVRyZWVOb2RlKSB7XG4gICAgdGhpcy5yb290ID0gQXJyYXkuaXNBcnJheShoYXNoZXNPck5vZGUpXG4gICAgICA/IGJ1aWxkKGhhc2hlc09yTm9kZS5tYXAoKGhhc2gpID0+IG5ldyBNZXJrbGVUcmVlTm9kZSh7IGhhc2ggfSkpKVxuICAgICAgOiAoaGFzaGVzT3JOb2RlIGFzIE1lcmtsZVRyZWVOb2RlKTtcbiAgICB0aGlzLmRlcHRoID0gMTtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tbG9vcC1zdGF0ZW1lbnQgbm8tbGV0XG4gICAgZm9yIChsZXQgbm9kZSA9IHRoaXMucm9vdDsgbm9kZS5sZWZ0Q2hpbGQgIT09IHVuZGVmaW5lZDsgbm9kZSA9IG5vZGUubGVmdENoaWxkKSB7XG4gICAgICB0aGlzLmRlcHRoICs9IDE7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHRyaW0oZmxhZ3M6IHJlYWRvbmx5IGJvb2xlYW5bXSk6IE1lcmtsZVRyZWUge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMucm9vdC5jbG9uZSgpO1xuICAgIHRyaW0ocmVzdWx0LCAwLCB0aGlzLmRlcHRoLCBmbGFncyk7XG5cbiAgICByZXR1cm4gbmV3IE1lcmtsZVRyZWUocmVzdWx0KTtcbiAgfVxuXG4gIHB1YmxpYyBkZXB0aEZpcnN0U2VhcmNoKCk6IHJlYWRvbmx5IFVJbnQyNTZbXSB7XG4gICAgcmV0dXJuIGRlcHRoRmlyc3RTZWFyY2godGhpcy5yb290KTtcbiAgfVxuXG4gIHB1YmxpYyB0b0hhc2hBcnJheSgpOiByZWFkb25seSBVSW50MjU2W10ge1xuICAgIHJldHVybiB0aGlzLmRlcHRoRmlyc3RTZWFyY2goKTtcbiAgfVxufVxuIl19
|