chain: return null on orphan blocks.
This commit is contained in:
parent
b265877b36
commit
beefcfba67
@ -1232,7 +1232,7 @@ Chain.prototype._add = co(function* add(block, flags) {
|
||||
assert(initial);
|
||||
assert(!result);
|
||||
this.storeOrphan(block);
|
||||
throw new VerifyError(block, 'invalid', 'bad-prevblk', 0);
|
||||
break;
|
||||
}
|
||||
|
||||
// Verify a checkpoint if there is one.
|
||||
|
||||
@ -1350,7 +1350,7 @@ RPC.prototype._submitwork = co(function* _submitwork(data) {
|
||||
|
||||
RPC.prototype.__submitwork = co(function* _submitwork(data) {
|
||||
var attempt = this.attempt;
|
||||
var block, header, cb, cur;
|
||||
var block, entry, header, cb, cur;
|
||||
|
||||
if (data.length !== 128)
|
||||
throw new RPCError('Invalid parameter.');
|
||||
@ -1393,7 +1393,7 @@ RPC.prototype.__submitwork = co(function* _submitwork(data) {
|
||||
attempt.commit(header.nonce);
|
||||
|
||||
try {
|
||||
yield this.chain.add(block);
|
||||
entry = yield this.chain.add(block);
|
||||
} catch (err) {
|
||||
if (err.type === 'VerifyError') {
|
||||
this.logger.warning('RPC block rejected: %s (%s).',
|
||||
@ -1403,6 +1403,12 @@ RPC.prototype.__submitwork = co(function* _submitwork(data) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (!entry) {
|
||||
this.logger.warning('RPC block rejected: %s (bad-prevblk).',
|
||||
block.rhash());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
@ -1497,10 +1503,12 @@ RPC.prototype._submitblock = co(function* submitblock(block) {
|
||||
});
|
||||
|
||||
RPC.prototype.__submitblock = co(function* submitblock(block) {
|
||||
var entry;
|
||||
|
||||
this.logger.info('Handling submitted block: %s.', block.rhash());
|
||||
|
||||
try {
|
||||
yield this.chain.add(block);
|
||||
entry = yield this.chain.add(block);
|
||||
} catch (err) {
|
||||
if (err.type === 'VerifyError') {
|
||||
this.logger.warning('RPC block rejected: %s (%s).',
|
||||
@ -1510,6 +1518,12 @@ RPC.prototype.__submitblock = co(function* submitblock(block) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (!entry) {
|
||||
this.logger.warning('RPC block rejected: %s (bad-prevblk).',
|
||||
block.rhash());
|
||||
return 'rejected: bad-prevblk';
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
@ -2033,7 +2047,7 @@ RPC.prototype._generateBlocks = co(function* _generateBlocks(blocks, address) {
|
||||
for (i = 0; i < blocks; i++) {
|
||||
block = yield this.miner.mineBlock(null, address);
|
||||
hashes.push(block.rhash());
|
||||
yield this.chain.add(block);
|
||||
assert(yield this.chain.add(block));
|
||||
}
|
||||
|
||||
return hashes;
|
||||
|
||||
@ -187,6 +187,11 @@ Miner.prototype.start = co(function* start() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!entry) {
|
||||
this.logger.warning('Mined a bad-prevblk (race condition?)');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.stopping)
|
||||
break;
|
||||
|
||||
|
||||
@ -1429,6 +1429,8 @@ Pool.prototype.handleBlockInv = co(function* handleBlockInv(peer, hashes) {
|
||||
var items = [];
|
||||
var i, hash;
|
||||
|
||||
assert(hashes.length > 0);
|
||||
|
||||
if (!this.syncing)
|
||||
return;
|
||||
|
||||
@ -1489,6 +1491,8 @@ Pool.prototype.handleBlockInv = co(function* handleBlockInv(peer, hashes) {
|
||||
*/
|
||||
|
||||
Pool.prototype.handleTXInv = co(function* handleTXInv(peer, hashes) {
|
||||
assert(hashes.length > 0);
|
||||
|
||||
if (this.syncing && !this.chain.synced)
|
||||
return;
|
||||
|
||||
@ -1969,6 +1973,7 @@ Pool.prototype.addBlock = co(function* addBlock(peer, block, flags) {
|
||||
|
||||
Pool.prototype._addBlock = co(function* addBlock(peer, block, flags) {
|
||||
var hash = block.hash('hex');
|
||||
var entry;
|
||||
|
||||
if (!this.syncing)
|
||||
return;
|
||||
@ -1984,19 +1989,9 @@ Pool.prototype._addBlock = co(function* addBlock(peer, block, flags) {
|
||||
peer.blockTime = util.ms();
|
||||
|
||||
try {
|
||||
yield this.chain.add(block, flags);
|
||||
entry = yield this.chain.add(block, flags);
|
||||
} catch (err) {
|
||||
if (err.type === 'VerifyError') {
|
||||
if (err.reason === 'bad-prevblk') {
|
||||
if (this.checkpoints) {
|
||||
peer.increaseBan(10);
|
||||
this.emit('error', err, peer);
|
||||
return;
|
||||
}
|
||||
this.logger.debug('Peer sent an orphan block. Resolving.');
|
||||
yield this.resolveOrphan(peer, hash);
|
||||
return;
|
||||
}
|
||||
peer.reject(block, err.code, err.reason, err.score);
|
||||
this.emit('error', err, peer);
|
||||
return;
|
||||
@ -2004,6 +1999,22 @@ Pool.prototype._addBlock = co(function* addBlock(peer, block, flags) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Block was orphaned.
|
||||
if (!entry) {
|
||||
if (this.checkpoints) {
|
||||
this.logger.warning(
|
||||
'Peer sent orphan block with getheaders (%s).',
|
||||
peer.hostname());
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.debug('Peer sent an orphan block. Resolving.');
|
||||
|
||||
yield this.resolveOrphan(peer, hash);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.logStatus(block);
|
||||
|
||||
yield this.resolveChain(peer, hash);
|
||||
|
||||
@ -28,12 +28,18 @@ describe('Chain', function() {
|
||||
|
||||
addBlock = co(function* addBlock(attempt) {
|
||||
var block = yield attempt.mineAsync();
|
||||
var entry;
|
||||
|
||||
try {
|
||||
yield chain.add(block);
|
||||
entry = yield chain.add(block);
|
||||
} catch (e) {
|
||||
assert(e.type === 'VerifyError');
|
||||
return e.reason;
|
||||
}
|
||||
|
||||
if (!entry)
|
||||
return 'bad-prevblk';
|
||||
|
||||
return 'OK';
|
||||
});
|
||||
|
||||
@ -86,7 +92,7 @@ describe('Chain', function() {
|
||||
for (i = 0; i < 200; i++) {
|
||||
block = yield miner.mineBlock();
|
||||
assert(block);
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
}
|
||||
|
||||
assert.equal(chain.height, 200);
|
||||
@ -115,8 +121,8 @@ describe('Chain', function() {
|
||||
hash1 = blk1.hash('hex');
|
||||
hash2 = blk2.hash('hex');
|
||||
|
||||
yield chain.add(blk1);
|
||||
yield chain.add(blk2);
|
||||
assert(yield chain.add(blk1));
|
||||
assert(yield chain.add(blk2));
|
||||
|
||||
assert(chain.tip.hash === hash1);
|
||||
|
||||
@ -157,7 +163,7 @@ describe('Chain', function() {
|
||||
forked = true;
|
||||
});
|
||||
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
|
||||
assert(forked);
|
||||
assert(chain.tip.hash === block.hash('hex'));
|
||||
@ -183,7 +189,7 @@ describe('Chain', function() {
|
||||
var block = yield miner.mineBlock();
|
||||
var hash, entry, result;
|
||||
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
|
||||
hash = block.hash('hex');
|
||||
entry = yield chain.db.getEntry(hash);
|
||||
@ -210,7 +216,7 @@ describe('Chain', function() {
|
||||
|
||||
block = yield attempt.mineAsync();
|
||||
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
|
||||
attempt = yield miner.createBlock();
|
||||
|
||||
@ -269,7 +275,7 @@ describe('Chain', function() {
|
||||
attempt.addTX(mtx.toTX(), mtx.view);
|
||||
|
||||
block = yield attempt.mineAsync();
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
|
||||
tx = block.txs[1];
|
||||
output = Coin.fromTX(tx, 2, chain.height);
|
||||
@ -325,7 +331,7 @@ describe('Chain', function() {
|
||||
|
||||
for (i = 0; i < 417; i++) {
|
||||
block = yield miner.mineBlock();
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
switch (chain.height) {
|
||||
case 288:
|
||||
prev = yield chain.tip.getPrevious();
|
||||
@ -367,7 +373,7 @@ describe('Chain', function() {
|
||||
var block = yield mineCSV(tx);
|
||||
var csv, attempt, rtx;
|
||||
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
|
||||
csv = block.txs[1];
|
||||
|
||||
@ -390,7 +396,7 @@ describe('Chain', function() {
|
||||
|
||||
block = yield attempt.mineAsync();
|
||||
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
}));
|
||||
|
||||
it('should fail csv with bad sequence', co(function* () {
|
||||
@ -418,7 +424,7 @@ describe('Chain', function() {
|
||||
it('should mine a block', co(function* () {
|
||||
var block = yield miner.mineBlock();
|
||||
assert(block);
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
}));
|
||||
|
||||
it('should fail csv lock checks', co(function* () {
|
||||
@ -426,7 +432,7 @@ describe('Chain', function() {
|
||||
var block = yield mineCSV(tx);
|
||||
var csv, attempt, rtx;
|
||||
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
|
||||
csv = block.txs[1];
|
||||
|
||||
@ -556,7 +562,7 @@ describe('Chain', function() {
|
||||
for (i = 0; i < 2001; i++) {
|
||||
block = yield miner.mineBlock();
|
||||
assert(block);
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
}
|
||||
|
||||
assert.equal(chain.height, 2636);
|
||||
@ -578,7 +584,7 @@ describe('Chain', function() {
|
||||
|
||||
block = yield attempt.mineAsync();
|
||||
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
}));
|
||||
|
||||
it('should mine fail to connect too much weight', co(function* () {
|
||||
@ -768,7 +774,7 @@ describe('Chain', function() {
|
||||
attempt.updateMerkle();
|
||||
|
||||
block = yield attempt.mineAsync();
|
||||
yield chain.add(block);
|
||||
assert(yield chain.add(block));
|
||||
}
|
||||
|
||||
assert.equal(chain.height, 2749);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user