-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmerkle.js
More file actions
56 lines (47 loc) · 1.43 KB
/
merkle.js
File metadata and controls
56 lines (47 loc) · 1.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
'use strict';
const createKeccakHash = require('keccak');
class Merkle {
constructor(data) {
this.isReady = false;
this.leaves = data.map(str => this._hash(this._getBuffer(str)));
this.levels = [];
}
makeTree() {
this.isReady = false;
this.levels.unshift(this.leaves);
while (this.levels[0].length > 1) {
this.levels.unshift(this._getNextLevel());
}
this.isReady = true;
}
getRoot() {
return this.isReady ? this.levels[0][0] : null;
}
getProof(index) {
let proof = [];
for (let i = this.levels.length - 1; i > 0; i--) {
let isRightNode = index % 2;
let siblingIndex = isRightNode ? (index - 1) : (index + 1);
proof.push(new Buffer(isRightNode ? [0x00] : [0x01]));
proof.push(this.levels[i][siblingIndex]);
index = Math.floor(index / 2);
}
return proof;
}
_hash(value) {
return createKeccakHash('keccak256').update(value).digest();
}
_getBuffer(value) {
return new Buffer(value, 'hex');
}
_getNextLevel() {
let nodes = [];
for (let i = 0; i < this.levels[0].length - 1; i += 2) {
let left = this.levels[0][i];
let right = this.levels[0][i + 1];
nodes.push(this._hash(Buffer.concat([left, right])));
}
return nodes;
}
}
module.exports = Merkle;