-
-
Notifications
You must be signed in to change notification settings - Fork 12
/
generator.js
60 lines (47 loc) · 1.59 KB
/
generator.js
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
57
58
59
60
// a more low level interface to the merkle tree stream.
// useful for certain applications the require non-streamy access to the algos.
// versioned by the same semver as the stream interface.
const flat = require('flat-tree')
module.exports = class MerkleGenerator {
constructor (opts, roots) {
if (!opts || !opts.leaf || !opts.parent) throw new Error('opts.leaf and opts.parent required')
this.roots = roots || opts.roots || []
this.blocks = this.roots.length ? 1 + flat.rightSpan(this.roots[this.roots.length - 1].index) / 2 : 0
for (let i = 0; i < this.roots.length; i++) {
const r = this.roots[i]
if (r && !r.parent) r.parent = flat.parent(r.index)
}
this._leaf = opts.leaf
this._parent = opts.parent
}
next (data, nodes) {
if (!Buffer.isBuffer(data)) data = Buffer.from(data)
if (!nodes) nodes = []
const index = 2 * this.blocks++
let leaf = {
index: index,
parent: flat.parent(index),
hash: null,
size: data.length,
data: data
}
leaf.hash = this._leaf(leaf, this.roots)
this.roots.push(leaf)
nodes.push(leaf)
while (this.roots.length > 1) {
const left = this.roots[this.roots.length - 2]
const right = this.roots[this.roots.length - 1]
if (left.parent !== right.parent) break
this.roots.pop()
this.roots[this.roots.length - 1] = leaf = {
index: left.parent,
parent: flat.parent(left.parent),
hash: this._parent(left, right),
size: left.size + right.size,
data: null
}
nodes.push(leaf)
}
return nodes
}
}