keep all pending blocks off the heap.
This commit is contained in:
parent
41c84c1937
commit
4cea71fe65
@ -68,6 +68,7 @@ bcoin.tx = require('./bcoin/tx');
|
|||||||
bcoin.mtx = require('./bcoin/mtx');
|
bcoin.mtx = require('./bcoin/mtx');
|
||||||
bcoin.txpool = require('./bcoin/tx-pool');
|
bcoin.txpool = require('./bcoin/tx-pool');
|
||||||
bcoin.abstractblock = require('./bcoin/abstractblock');
|
bcoin.abstractblock = require('./bcoin/abstractblock');
|
||||||
|
bcoin.compactblock = require('./bcoin/compactblock');
|
||||||
bcoin.block = require('./bcoin/block');
|
bcoin.block = require('./bcoin/block');
|
||||||
bcoin.merkleblock = require('./bcoin/merkleblock');
|
bcoin.merkleblock = require('./bcoin/merkleblock');
|
||||||
bcoin.headers = require('./bcoin/headers');
|
bcoin.headers = require('./bcoin/headers');
|
||||||
|
|||||||
@ -456,6 +456,9 @@ Chain.prototype._verify = function _verify(block, prev) {
|
|||||||
var flags = constants.flags.MANDATORY_VERIFY_FLAGS;
|
var flags = constants.flags.MANDATORY_VERIFY_FLAGS;
|
||||||
var height, ts, i, tx, cb, coinbaseHeight, medianTime, locktimeMedian;
|
var height, ts, i, tx, cb, coinbaseHeight, medianTime, locktimeMedian;
|
||||||
|
|
||||||
|
if (!block.verify())
|
||||||
|
return flags;
|
||||||
|
|
||||||
// Skip the genesis block
|
// Skip the genesis block
|
||||||
if (block.isGenesis())
|
if (block.isGenesis())
|
||||||
return flags;
|
return flags;
|
||||||
@ -1018,7 +1021,7 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
|||||||
(function next(block) {
|
(function next(block) {
|
||||||
var hash = block.hash('hex');
|
var hash = block.hash('hex');
|
||||||
var prevHash = block.prevBlock;
|
var prevHash = block.prevBlock;
|
||||||
var prevHeight, height, entry, checkpoint, prev, orphan;
|
var prevHeight, height, checkpoint, prev, orphan;
|
||||||
|
|
||||||
// Find the previous block height/index.
|
// Find the previous block height/index.
|
||||||
prevHeight = self.db.getHeight(prevHash);
|
prevHeight = self.db.getHeight(prevHash);
|
||||||
@ -1115,24 +1118,12 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
|||||||
return done();
|
return done();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new chain entry.
|
|
||||||
entry = new bcoin.chainblock(self, {
|
|
||||||
hash: hash,
|
|
||||||
version: block.version,
|
|
||||||
prevBlock: prevHash,
|
|
||||||
merkleRoot: block.merkleRoot,
|
|
||||||
ts: block.ts,
|
|
||||||
bits: block.bits,
|
|
||||||
nonce: block.nonce,
|
|
||||||
height: prevHeight + 1
|
|
||||||
});
|
|
||||||
|
|
||||||
// Verify the checkpoint.
|
// Verify the checkpoint.
|
||||||
checkpoint = network.checkpoints[entry.height];
|
checkpoint = network.checkpoints[height];
|
||||||
if (checkpoint) {
|
if (checkpoint) {
|
||||||
self.emit('checkpoint', block, {
|
self.emit('checkpoint', block, {
|
||||||
height: entry.height,
|
height: height,
|
||||||
hash: entry.hash,
|
hash: hash,
|
||||||
checkpoint: checkpoint
|
checkpoint: checkpoint
|
||||||
}, peer);
|
}, peer);
|
||||||
|
|
||||||
@ -1142,14 +1133,14 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
|||||||
// so we don't do it. The misbehaving peer has
|
// so we don't do it. The misbehaving peer has
|
||||||
// been killed and hopefully we find a peer
|
// been killed and hopefully we find a peer
|
||||||
// who isn't trying to fool us.
|
// who isn't trying to fool us.
|
||||||
if (entry.hash !== checkpoint) {
|
if (hash !== checkpoint) {
|
||||||
self.purgeOrphans();
|
self.purgeOrphans();
|
||||||
self.purgePending();
|
self.purgePending();
|
||||||
|
|
||||||
self.emit('fork', block, {
|
self.emit('fork', block, {
|
||||||
height: entry.height,
|
height: height,
|
||||||
expected: checkpoint,
|
expected: checkpoint,
|
||||||
received: entry.hash,
|
received: hash,
|
||||||
checkpoint: true
|
checkpoint: true
|
||||||
}, peer);
|
}, peer);
|
||||||
|
|
||||||
@ -1171,26 +1162,46 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
|||||||
|
|
||||||
assert(prev);
|
assert(prev);
|
||||||
|
|
||||||
|
if (block.type === 'compactblock') {
|
||||||
|
block = block.toBlock(peer);
|
||||||
|
if (!block)
|
||||||
|
return done(new Error('Failed to parse block.'));
|
||||||
|
if (block._raw === initial._raw)
|
||||||
|
initial = block;
|
||||||
|
}
|
||||||
|
|
||||||
// Do "contextual" verification on our block
|
// Do "contextual" verification on our block
|
||||||
// now that we're certain its previous
|
// now that we're certain its previous
|
||||||
// block is in the chain.
|
// block is in the chain.
|
||||||
self._verifyContext(block, prev, function(err, verified) {
|
self._verifyContext(block, prev, function(err, verified) {
|
||||||
var existing;
|
var entry, existing;
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return done(err);
|
return done(err);
|
||||||
|
|
||||||
if (!verified) {
|
if (!verified) {
|
||||||
self.invalid[entry.hash] = true;
|
self.invalid[hash] = true;
|
||||||
self.emit('invalid', block, {
|
self.emit('invalid', block, {
|
||||||
height: entry.height,
|
height: height,
|
||||||
hash: entry.hash,
|
hash: hash,
|
||||||
seen: false,
|
seen: false,
|
||||||
chain: false
|
chain: false
|
||||||
}, peer);
|
}, peer);
|
||||||
return done();
|
return done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new chain entry.
|
||||||
|
entry = new bcoin.chainblock(self, {
|
||||||
|
hash: hash,
|
||||||
|
version: block.version,
|
||||||
|
prevBlock: block.prevBlock,
|
||||||
|
merkleRoot: block.merkleRoot,
|
||||||
|
ts: block.ts,
|
||||||
|
bits: block.bits,
|
||||||
|
nonce: block.nonce,
|
||||||
|
height: height
|
||||||
|
});
|
||||||
|
|
||||||
// Real fork resolution would just be this.
|
// Real fork resolution would just be this.
|
||||||
// if (entry.chainwork.cmp(self.tip.chainwork) > 0)
|
// if (entry.chainwork.cmp(self.tip.chainwork) > 0)
|
||||||
// return self.setBestChain(entry);
|
// return self.setBestChain(entry);
|
||||||
|
|||||||
51
lib/bcoin/compactblock.js
Normal file
51
lib/bcoin/compactblock.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* compactblock.js - compact block object for bcoin
|
||||||
|
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||||
|
* https://github.com/indutny/bcoin
|
||||||
|
*/
|
||||||
|
|
||||||
|
var bcoin = require('../bcoin');
|
||||||
|
var bn = require('bn.js');
|
||||||
|
var utils = bcoin.utils;
|
||||||
|
var assert = utils.assert;
|
||||||
|
var constants = bcoin.protocol.constants;
|
||||||
|
var network = bcoin.protocol.network;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CompactBlock
|
||||||
|
*/
|
||||||
|
|
||||||
|
function CompactBlock(data) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (!(this instanceof CompactBlock))
|
||||||
|
return new CompactBlock(data);
|
||||||
|
|
||||||
|
bcoin.abstractblock.call(this, data);
|
||||||
|
|
||||||
|
this.type = 'compactblock';
|
||||||
|
this.coinbaseHeight = data.coinbaseHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.inherits(CompactBlock, bcoin.abstractblock);
|
||||||
|
|
||||||
|
CompactBlock.prototype._verify = function _verify() {
|
||||||
|
return this.verifyHeaders();
|
||||||
|
};
|
||||||
|
|
||||||
|
CompactBlock.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
||||||
|
return this.coinbaseHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
CompactBlock.prototype.toBlock = function toBlock(peer) {
|
||||||
|
var block = peer.parser.parseBlock(this._raw);
|
||||||
|
if (!block)
|
||||||
|
return;
|
||||||
|
return new bcoin.block(block);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expose
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = CompactBlock;
|
||||||
@ -415,7 +415,7 @@ Peer.prototype._onPacket = function onPacket(packet) {
|
|||||||
return this._handleReject(payload);
|
return this._handleReject(payload);
|
||||||
|
|
||||||
if (cmd === 'block') {
|
if (cmd === 'block') {
|
||||||
payload = bcoin.block(payload);
|
payload = bcoin.compactblock(payload);
|
||||||
} else if (cmd === 'merkleblock') {
|
} else if (cmd === 'merkleblock') {
|
||||||
payload = bcoin.merkleblock(payload);
|
payload = bcoin.merkleblock(payload);
|
||||||
this.lastBlock = payload;
|
this.lastBlock = payload;
|
||||||
|
|||||||
@ -123,8 +123,11 @@ Parser.prototype.parsePayload = function parsePayload(cmd, p) {
|
|||||||
if (cmd === 'headers')
|
if (cmd === 'headers')
|
||||||
return this.parseHeaders(p);
|
return this.parseHeaders(p);
|
||||||
|
|
||||||
|
// if (cmd === 'block')
|
||||||
|
// return this.parseBlock(p);
|
||||||
|
|
||||||
if (cmd === 'block')
|
if (cmd === 'block')
|
||||||
return this.parseBlock(p);
|
return this.parseBlockCompact(p);
|
||||||
|
|
||||||
if (cmd === 'tx')
|
if (cmd === 'tx')
|
||||||
return this.parseTX(p);
|
return this.parseTX(p);
|
||||||
@ -358,6 +361,56 @@ Parser.prototype.parseBlock = function parseBlock(p) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Parser.prototype.parseBlockCompact = function parseBlockCompact(p) {
|
||||||
|
var height = -1;
|
||||||
|
var i, result, off, totalTX, tx;
|
||||||
|
var inCount, input, s, version;
|
||||||
|
|
||||||
|
if (p.length < 81)
|
||||||
|
return this._error('Invalid block size');
|
||||||
|
|
||||||
|
version = utils.read32(p, 0);
|
||||||
|
|
||||||
|
result = utils.readIntv(p, 80);
|
||||||
|
off = result.off;
|
||||||
|
totalTX = result.r;
|
||||||
|
|
||||||
|
if (version > 1 && totalTX > 0) {
|
||||||
|
if (p.length < off + 10)
|
||||||
|
return this._error('Invalid tx size');
|
||||||
|
|
||||||
|
inCount = utils.readIntv(p, off + 4);
|
||||||
|
off = inCount.off;
|
||||||
|
inCount = inCount.r;
|
||||||
|
|
||||||
|
if (inCount > 0) {
|
||||||
|
input = this.parseInput(p.slice(off));
|
||||||
|
if (!input)
|
||||||
|
return this._error('Invalid tx count for block');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input) {
|
||||||
|
s = bcoin.script.decode(input.script);
|
||||||
|
if (Buffer.isBuffer(s[0]))
|
||||||
|
height = bcoin.script.num(s[0], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
version: version,
|
||||||
|
prevBlock: p.slice(4, 36),
|
||||||
|
merkleRoot: p.slice(36, 68),
|
||||||
|
ts: utils.readU32(p, 68),
|
||||||
|
bits: utils.readU32(p, 72),
|
||||||
|
nonce: utils.readU32(p, 76),
|
||||||
|
totalTX: totalTX,
|
||||||
|
coinbaseHeight: height,
|
||||||
|
txs: [],
|
||||||
|
_raw: p,
|
||||||
|
_size: p.length
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
Parser.prototype.parseInput = function parseInput(p) {
|
Parser.prototype.parseInput = function parseInput(p) {
|
||||||
var scriptLen, off;
|
var scriptLen, off;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user