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