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.txpool = require('./bcoin/tx-pool');
|
||||
bcoin.abstractblock = require('./bcoin/abstractblock');
|
||||
bcoin.compactblock = require('./bcoin/compactblock');
|
||||
bcoin.block = require('./bcoin/block');
|
||||
bcoin.merkleblock = require('./bcoin/merkleblock');
|
||||
bcoin.headers = require('./bcoin/headers');
|
||||
|
||||
@ -456,6 +456,9 @@ Chain.prototype._verify = function _verify(block, prev) {
|
||||
var flags = constants.flags.MANDATORY_VERIFY_FLAGS;
|
||||
var height, ts, i, tx, cb, coinbaseHeight, medianTime, locktimeMedian;
|
||||
|
||||
if (!block.verify())
|
||||
return flags;
|
||||
|
||||
// Skip the genesis block
|
||||
if (block.isGenesis())
|
||||
return flags;
|
||||
@ -1018,7 +1021,7 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
||||
(function next(block) {
|
||||
var hash = block.hash('hex');
|
||||
var prevHash = block.prevBlock;
|
||||
var prevHeight, height, entry, checkpoint, prev, orphan;
|
||||
var prevHeight, height, checkpoint, prev, orphan;
|
||||
|
||||
// Find the previous block height/index.
|
||||
prevHeight = self.db.getHeight(prevHash);
|
||||
@ -1115,24 +1118,12 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
||||
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.
|
||||
checkpoint = network.checkpoints[entry.height];
|
||||
checkpoint = network.checkpoints[height];
|
||||
if (checkpoint) {
|
||||
self.emit('checkpoint', block, {
|
||||
height: entry.height,
|
||||
hash: entry.hash,
|
||||
height: height,
|
||||
hash: hash,
|
||||
checkpoint: checkpoint
|
||||
}, peer);
|
||||
|
||||
@ -1142,14 +1133,14 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
||||
// so we don't do it. The misbehaving peer has
|
||||
// been killed and hopefully we find a peer
|
||||
// who isn't trying to fool us.
|
||||
if (entry.hash !== checkpoint) {
|
||||
if (hash !== checkpoint) {
|
||||
self.purgeOrphans();
|
||||
self.purgePending();
|
||||
|
||||
self.emit('fork', block, {
|
||||
height: entry.height,
|
||||
height: height,
|
||||
expected: checkpoint,
|
||||
received: entry.hash,
|
||||
received: hash,
|
||||
checkpoint: true
|
||||
}, peer);
|
||||
|
||||
@ -1171,26 +1162,46 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
||||
|
||||
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
|
||||
// now that we're certain its previous
|
||||
// block is in the chain.
|
||||
self._verifyContext(block, prev, function(err, verified) {
|
||||
var existing;
|
||||
var entry, existing;
|
||||
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
if (!verified) {
|
||||
self.invalid[entry.hash] = true;
|
||||
self.invalid[hash] = true;
|
||||
self.emit('invalid', block, {
|
||||
height: entry.height,
|
||||
hash: entry.hash,
|
||||
height: height,
|
||||
hash: hash,
|
||||
seen: false,
|
||||
chain: false
|
||||
}, peer);
|
||||
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.
|
||||
// if (entry.chainwork.cmp(self.tip.chainwork) > 0)
|
||||
// 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);
|
||||
|
||||
if (cmd === 'block') {
|
||||
payload = bcoin.block(payload);
|
||||
payload = bcoin.compactblock(payload);
|
||||
} else if (cmd === 'merkleblock') {
|
||||
payload = bcoin.merkleblock(payload);
|
||||
this.lastBlock = payload;
|
||||
|
||||
@ -123,8 +123,11 @@ Parser.prototype.parsePayload = function parsePayload(cmd, p) {
|
||||
if (cmd === 'headers')
|
||||
return this.parseHeaders(p);
|
||||
|
||||
// if (cmd === 'block')
|
||||
// return this.parseBlock(p);
|
||||
|
||||
if (cmd === 'block')
|
||||
return this.parseBlock(p);
|
||||
return this.parseBlockCompact(p);
|
||||
|
||||
if (cmd === 'tx')
|
||||
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) {
|
||||
var scriptLen, off;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user