save tip as part of block db operations

This commit is contained in:
Patrick Nagurny 2015-09-29 15:20:05 -04:00
parent 68b0120319
commit 3fa1340ef3
1 changed files with 61 additions and 88 deletions

View File

@ -62,7 +62,8 @@ util.inherits(DB, Service);
DB.dependencies = ['bitcoind'];
DB.PREFIXES = {
BLOCKS: new Buffer('01', 'hex')
BLOCKS: new Buffer('01', 'hex'),
TIP: new Buffer('04', 'hex')
};
/**
@ -109,45 +110,14 @@ DB.prototype.start = function(callback) {
});
});
// Does our database already have a tip?
self.getMetadata(function(err, metadata) {
self.loadTip(function(err) {
if(err) {
return callback(err);
} else if(!metadata || !metadata.tip) {
self.tip = self.genesis;
self.tip.__height = 0;
self.connectBlock(self.genesis, function(err) {
if(err) {
return callback(err);
}
self.emit('addblock', self.genesis);
self.saveMetadata();
self.sync();
self.emit('ready');
setImmediate(callback);
});
} else {
self.getBlock(metadata.tip, function(err, tip) {
if(err) {
log.warn(
'Database is in an inconsistent state, a reindex is needed. Could not get current tip:',
metadata.tip
);
return callback(err);
}
self.tip = tip;
var blockIndex = self.node.services.bitcoind.getBlockIndex(self.tip.hash);
if (!blockIndex) {
return callback(new Error('Could not get height for tip.'));
}
self.tip.__height = blockIndex.height;
self.sync();
self.emit('ready');
setImmediate(callback);
});
}
self.sync();
self.emit('ready');
setImmediate(callback);
});
};
@ -220,6 +190,52 @@ DB.prototype.getAPIMethods = function() {
return methods;
};
DB.prototype.loadTip = function(callback) {
var self = this;
var options = {
keyEncoding: 'binary',
valueEncoding: 'binary'
};
self.store.get(DB.PREFIXES.TIP, options, function(err, tipData) {
if(err && err instanceof levelup.errors.NotFoundError) {
self.tip = self.genesis;
self.tip.__height = 0;
self.connectBlock(self.genesis, function(err) {
if(err) {
return callback(err);
}
self.emit('addblock', self.genesis);
callback();
});
return;
} else if(err) {
return callback(err);
}
var hash = tipData.toString('hex');
self.getBlock(hash, function(err, tip) {
if(err) {
log.warn('Database is in an inconsistent state, a reindex is needed. Could not get current tip:',
hash
);
return callback(err);
}
self.tip = tip;
var blockIndex = self.node.services.bitcoind.getBlockIndex(self.tip.hash);
if(!blockIndex) {
return callback(new Error('Could not get height for tip.'));
}
self.tip.__height = blockIndex.height;
callback();
});
});
};
/**
* Will get a block from bitcoind and give a Bitcore Block
* @param {String|Number} hash - A block hash or block height
@ -404,54 +420,6 @@ DB.prototype.getPrevHash = function(blockHash, callback) {
});
};
/**
* Saves metadata to the database
* @param {Function} callback - A function that accepts: Error
*/
DB.prototype.saveMetadata = function(callback) {
var self = this;
function defaultCallback(err) {
if (err) {
self.emit('error', err);
}
}
callback = callback || defaultCallback;
var metadata = {
tip: self.tip ? self.tip.hash : null
};
this.store.put('metadata', JSON.stringify(metadata), {}, callback);
};
/**
* Retrieves metadata from the database
* @param {Function} callback - A function that accepts: Error and Object
*/
DB.prototype.getMetadata = function(callback) {
var self = this;
self.store.get('metadata', {}, function(err, data) {
if (err instanceof levelup.errors.NotFoundError) {
return callback(null, {});
} else if (err) {
return callback(err);
}
var metadata;
try {
metadata = JSON.parse(data);
} catch(e) {
return callback(new Error('Could not parse metadata'));
}
callback(null, metadata);
});
};
/**
* Connects a block to the database and add indexes
* @param {Block} block - The bitcore block
@ -506,6 +474,14 @@ DB.prototype.runAllBlockHandlers = function(block, add, callback) {
this.subscriptions.block[i].emit('db/block', block.hash);
}
// Update tip
var tipHash = add ? new Buffer(block.hash, 'hex') : BufferUtil.reverse(block.header.prevHash);
operations.push({
type: 'put',
key: DB.PREFIXES.TIP,
value: tipHash
});
// Update block index
operations.push({
type: add ? 'put' : 'del',
@ -668,7 +644,6 @@ DB.prototype.syncRewind = function(block, done) {
// Set the new tip
previousTip.__height = self.tip.__height - 1;
self.tip = previousTip;
self.saveMetadata();
self.emit('removeblock', tip);
removeDone();
});
@ -725,8 +700,6 @@ DB.prototype.sync = function() {
return done(err);
}
self.tip = block;
log.debug('Saving metadata');
self.saveMetadata();
log.debug('Chain added block to main chain');
self.emit('addblock', block);
setImmediate(done);