This repository has been archived by the owner on Dec 10, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 38
/
blockpool.js
94 lines (82 loc) · 2.24 KB
/
blockpool.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
'use strict'
const BN = require('ethereumjs-util').BN
const { defaultLogger } = require('../logging')
const defaultOptions = {
logger: defaultLogger
}
/**
* Pool of blockchain segments
* @memberof module:blockchain
*/
class BlockPool {
/**
* Create new block pool
* @param {Object} options constructor parameters
* @param {Chain} options.chain blockchain
* @param {Logger} [options.logger] Logger instance
*/
constructor (options) {
options = {...defaultOptions, ...options}
this.logger = options.logger
this.chain = options.chain
this.pool = new Map()
this.init()
}
init () {
this.opened = false
}
/**
* Size of pool
* @type {number}
*/
get size () {
return this.pool.size
}
/**
* Open block pool and wait for blockchain to open
* @return {Promise}
*/
async open () {
if (this.opened) {
return false
}
await this.chain.open()
this.opened = true
}
/**
* Add a blockchain segment to the pool. Returns a promise that resolves once
* the segment has been added to the pool. Segments are automatically inserted
* into the blockchain once prior gaps are filled.
* @param {Block[]} blocks list of sequential blocks
* @return {Promise}
*/
async add (blocks) {
if (!this.opened) {
return false
}
if (!Array.isArray(blocks)) {
blocks = [ blocks ]
}
let latest = this.chain.blocks.height
let first = new BN(blocks[0].header.number)
if (first.gt(latest.addn(1))) {
// if block segment arrived out of order, save it to the pool
this.pool.set(first.toString(), blocks)
return
}
while (blocks) {
// otherwise save headers and keep saving headers from header pool in order
let last = new BN(blocks[blocks.length - 1].header.number)
let hash = blocks[0].hash().toString('hex').slice(0, 8) + '...'
await this.chain.putBlocks(blocks)
this.logger.info(`Imported blocks count=${blocks.length} number=${first.toString(10)} hash=${hash}`)
latest = last
blocks = this.pool.get(last.addn(1).toString())
if (blocks) {
this.pool.delete(last.addn(1).toString())
first = new BN(blocks[0].header.number)
}
}
}
}
module.exports = BlockPool