walletdb: improve block handling.

This commit is contained in:
Christopher Jeffrey 2016-10-23 22:24:00 -07:00
parent 37e3219c4c
commit 11a7515bfd
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 41 additions and 34 deletions

View File

@ -1170,15 +1170,17 @@ WalletDB.prototype._rescan = co(function* rescan(chaindb, height) {
} }
blocks = this.height - height; blocks = this.height - height;
assert(blocks >= 0);
if (blocks < 0)
throw new Error('Cannot rescan future blocks.');
if (this.prune) { if (this.prune) {
if (blocks <= this.network.block.keepBlocks) if (blocks > this.network.block.keepBlocks)
yield this.rollback(height); throw new Error('Cannot roll back beyond keepBlocks.');
} else {
yield this.rollback(height);
} }
yield this.rollback(height);
hashes = yield this.getHashes(); hashes = yield this.getHashes();
this.logger.info('Scanning for %d addresses.', hashes.length); this.logger.info('Scanning for %d addresses.', hashes.length);
@ -1588,16 +1590,6 @@ WalletDB.prototype.rollback = co(function* rollback(height) {
WalletDB.prototype.addBlock = co(function* addBlock(entry, txs) { WalletDB.prototype.addBlock = co(function* addBlock(entry, txs) {
var unlock = yield this.txLock.lock(); var unlock = yield this.txLock.lock();
try { try {
yield this.rollback(entry.height - 1);
if (entry.height <= this.height) {
this.logger.warning('Node is connecting low blocks in wallet.');
return 0;
}
if (entry.height !== this.height + 1)
throw new Error('Bad connection (height mismatch).');
return yield this._addBlock(entry, txs); return yield this._addBlock(entry, txs);
} finally { } finally {
unlock(); unlock();
@ -1615,6 +1607,13 @@ WalletDB.prototype._addBlock = co(function* addBlock(entry, txs) {
var total = 0; var total = 0;
var i, block, tx; var i, block, tx;
// Special case for the guh-naysis block.
if (entry.hash === this.network.genesis.hash)
return;
if (entry.height !== this.height + 1)
throw new Error('Bad connection (height mismatch).');
if (this.options.useCheckpoints) { if (this.options.useCheckpoints) {
if (entry.height <= this.network.checkpoints.lastHeight) { if (entry.height <= this.network.checkpoints.lastHeight) {
block = WalletBlock.fromEntry(entry); block = WalletBlock.fromEntry(entry);
@ -1655,16 +1654,6 @@ WalletDB.prototype._addBlock = co(function* addBlock(entry, txs) {
WalletDB.prototype.removeBlock = co(function* removeBlock(entry) { WalletDB.prototype.removeBlock = co(function* removeBlock(entry) {
var unlock = yield this.txLock.lock(); var unlock = yield this.txLock.lock();
try { try {
yield this.rollback(entry.height);
if (entry.height > this.height) {
this.logger.warning('Node is disconnecting high blocks in wallet.');
return 0;
}
if (entry.height !== this.height)
throw new Error('Bad disconnection (height mismatch).');
return yield this._removeBlock(entry); return yield this._removeBlock(entry);
} finally { } finally {
unlock(); unlock();
@ -1680,13 +1669,17 @@ WalletDB.prototype.removeBlock = co(function* removeBlock(entry) {
WalletDB.prototype._removeBlock = co(function* removeBlock(entry) { WalletDB.prototype._removeBlock = co(function* removeBlock(entry) {
var block = yield this.getBlock(entry.height); var block = yield this.getBlock(entry.height);
var i, tx, prev; var prev = yield this.getBlock(entry.height - 1);
var i, tx;
if (!block) if (!block)
return 0; throw new Error('Bad disconnection (block not found).');
prev = yield this.getBlock(entry.height - 1); if (!prev)
assert(prev); throw new Error('Bad disconnection (no previous block).');
if (entry.height !== this.height)
throw new Error('Bad disconnection (height mismatch).');
if (block.txs.length === 0) { if (block.txs.length === 0) {
yield this.setBlock(prev); yield this.setBlock(prev);

View File

@ -19,12 +19,26 @@ var KEY2 = 'xprv9s21ZrQH143K3mqiSThzPtWAabQ22Pjp3uSNnZ53A5bQ4udp'
+ 'faKekc2m4AChLYH1XDzANhrSdxHYWUeTWjYJwFwWFyHkTMnMeAcW4JyRCZa'; + 'faKekc2m4AChLYH1XDzANhrSdxHYWUeTWjYJwFwWFyHkTMnMeAcW4JyRCZa';
var globalHeight = 1; var globalHeight = 1;
var globalTime = utils.now();
function nextBlock(height) { function nextBlock(height) {
var hash; var hash, prev;
height = height != null ? height : globalHeight++;
if (height == null)
height = globalHeight++;
hash = crypto.hash256(utils.U32(height)).toString('hex'); hash = crypto.hash256(utils.U32(height)).toString('hex');
return new WalletBlock(hash, height++, utils.now()); prev = crypto.hash256(utils.U32(height - 1)).toString('hex');
return {
hash: hash,
height: height,
prevBlock: prev,
ts: globalTime + height,
merkleRoot: constants.NULL_HASH,
nonce: 0,
bits: 0
};
} }
function dummy(hash) { function dummy(hash) {
@ -709,9 +723,9 @@ describe('Wallet', function() {
// Simulate a confirmation // Simulate a confirmation
var block = nextBlock(); var block = nextBlock();
utx.ts = block.ts;
utx.height = block.height; utx.height = block.height;
utx.block = block.hash; utx.block = block.hash;
utx.ts = block.ts;
utx.index = 0; utx.index = 0;
assert.equal(w1[depth], 1); assert.equal(w1[depth], 1);
@ -752,9 +766,9 @@ describe('Wallet', function() {
// Simulate a confirmation // Simulate a confirmation
var block = nextBlock(); var block = nextBlock();
send.ts = block.ts;
send.height = block.height; send.height = block.height;
send.block = block.hash; send.block = block.hash;
send.ts = block.ts;
send.index = 0; send.index = 0;
yield walletdb.addBlock(block, [send]); yield walletdb.addBlock(block, [send]);