chaindb: chain state buffer hash.

This commit is contained in:
Christopher Jeffrey 2016-08-17 19:58:25 -07:00
parent bf20425e11
commit 8ee0cf8604
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -290,7 +290,7 @@ ChainDB.prototype._open = function open(callback) {
self.logger.info('Chain successfully loaded.'); self.logger.info('Chain successfully loaded.');
self.logger.info('Chain State: hash=%s tx=%d coin=%d value=%s.', self.logger.info('Chain State: hash=%s tx=%d coin=%d value=%s.',
utils.revHex(self.state.hash), self.state.rhash,
self.state.tx, self.state.tx,
self.state.coin, self.state.coin,
utils.btc(self.state.value) utils.btc(self.state.value)
@ -303,7 +303,7 @@ ChainDB.prototype._open = function open(callback) {
if (err) if (err)
return done(err); return done(err);
self.db.has(layout.h(self.network.genesis.hash), function(err, exists) { self.db.has(layout.e(self.network.genesis.hash), function(err, exists) {
if (err) if (err)
return done(err); return done(err);
@ -394,17 +394,29 @@ ChainDB.prototype.drop = function drop() {
ChainDB.prototype.commit = function commit(callback) { ChainDB.prototype.commit = function commit(callback) {
var self = this; var self = this;
assert(this.current); assert(this.current);
assert(this.pending); assert(this.pending);
this.current.write(function(err) { this.current.write(function(err) {
if (err) { if (err) {
self.current = null; self.current = null;
self.pending = null; self.pending = null;
return callback(err); return callback(err);
} }
self.current = null; self.current = null;
self.state = self.pending;
// Overwrite the entire state
// with our new best state
// only if it is committed.
// Note that alternate chain
// tips do not commit anything.
if (self.pending.committed)
self.state = self.pending;
self.pending = null; self.pending = null;
callback(); callback();
}); });
}; };
@ -689,7 +701,7 @@ ChainDB.prototype.save = function save(entry, block, view, connect, callback) {
self.drop(); self.drop();
return callback(err); return callback(err);
} }
self.put(layout.R, self.pending.mark(hash)); self.put(layout.R, self.pending.commit(hash));
self.commit(callback); self.commit(callback);
}); });
}; };
@ -742,22 +754,13 @@ ChainDB.prototype.reconnect = function reconnect(entry, block, view, callback) {
this.cacheHash.set(entry.hash, entry); this.cacheHash.set(entry.hash, entry);
this.cacheHeight.set(entry.height, entry); this.cacheHeight.set(entry.height, entry);
if (this.options.spv) {
this.put(layout.R, this.pending.mark(hash));
return this.commit(function(err) {
if (err)
return callback(err);
return callback(null, entry, block);
});
}
this.connectBlock(block, view, function(err) { this.connectBlock(block, view, function(err) {
if (err) { if (err) {
self.drop(); self.drop();
return callback(err); return callback(err);
} }
self.put(layout.R, self.pending.mark(hash)); self.put(layout.R, self.pending.commit(hash));
self.commit(function(err) { self.commit(function(err) {
if (err) if (err)
return callback(err); return callback(err);
@ -783,7 +786,7 @@ ChainDB.prototype.disconnect = function disconnect(entry, callback) {
this.cacheHeight.remove(entry.height); this.cacheHeight.remove(entry.height);
if (this.options.spv) { if (this.options.spv) {
this.put(layout.R, this.pending.mark(entry.prevBlock)); this.put(layout.R, this.pending.commit(entry.prevBlock));
return this.commit(function(err) { return this.commit(function(err) {
if (err) if (err)
return callback(err); return callback(err);
@ -808,7 +811,7 @@ ChainDB.prototype.disconnect = function disconnect(entry, callback) {
return callback(err); return callback(err);
} }
self.put(layout.R, self.pending.mark(entry.prevBlock)); self.put(layout.R, self.pending.commit(entry.prevBlock));
self.commit(function(err) { self.commit(function(err) {
if (err) if (err)
return callback(err); return callback(err);
@ -848,8 +851,10 @@ ChainDB.prototype.isMainChain = function isMainChain(hash, callback) {
query = hash; query = hash;
} }
if (hash === this.chain.tip.hash || hash === this.network.genesis.hash) if (hash === this.chain.tip.hash
|| hash === this.network.genesis.hash) {
return utils.asyncify(callback)(null, true); return utils.asyncify(callback)(null, true);
}
this.getHeight(query, function(err, height) { this.getHeight(query, function(err, height) {
if (err) if (err)
@ -901,7 +906,7 @@ ChainDB.prototype.reset = function reset(block, callback) {
self.start(); self.start();
if (tip.hash === entry.hash) { if (tip.hash === entry.hash) {
self.put(layout.R, self.pending.mark(tip.hash)); self.put(layout.R, self.pending.commit(tip.hash));
return self.commit(callback); return self.commit(callback);
} }
@ -985,9 +990,6 @@ ChainDB.prototype.removeBlock = function removeBlock(hash, callback) {
self.del(layout.b(block.hash())); self.del(layout.b(block.hash()));
if (self.options.spv)
return callback(null, block);
self.disconnectBlock(block, callback); self.disconnectBlock(block, callback);
}); });
}; };
@ -1082,7 +1084,7 @@ ChainDB.prototype.connectBlock = function connectBlock(block, view, callback) {
if (undo.written > 0) if (undo.written > 0)
this.put(layout.u(block.hash()), undo.render()); this.put(layout.u(block.hash()), undo.render());
this._pruneBlock(block, function(err) { this.pruneBlock(block, function(err) {
if (err) if (err)
return callback(err); return callback(err);
callback(null, block); callback(null, block);
@ -1727,7 +1729,7 @@ ChainDB.prototype.hasCoins = function hasCoins(hash, callback) {
* @param {Function} callback * @param {Function} callback
*/ */
ChainDB.prototype._pruneBlock = function _pruneBlock(block, callback) { ChainDB.prototype.pruneBlock = function pruneBlock(block, callback) {
var futureHeight, key; var futureHeight, key;
if (this.options.spv) if (this.options.spv)
@ -1764,15 +1766,24 @@ ChainDB.prototype._pruneBlock = function _pruneBlock(block, callback) {
}; };
function ChainState() { function ChainState() {
this.hash = null; this.tip = constants.ZERO_HASH;
this.tx = 0; this.tx = 0;
this.coin = 0; this.coin = 0;
this.value = 0; this.value = 0;
this.committed = false;
} }
ChainState.prototype.__defineGetter__('hash', function() {
return this.tip.toString('hex');
});
ChainState.prototype.__defineGetter__('rhash', function() {
return utils.revHex(this.hash);
});
ChainState.prototype.clone = function clone() { ChainState.prototype.clone = function clone() {
var state = new ChainState(); var state = new ChainState();
state.hash = this.hash; state.tip = this.tip;
state.tx = this.tx; state.tx = this.tx;
state.coin = this.coin; state.coin = this.coin;
state.value = this.value; state.value = this.value;
@ -1797,16 +1808,17 @@ ChainState.prototype.spend = function spend(coin) {
this.value -= coin.value; this.value -= coin.value;
}; };
ChainState.prototype.mark = function mark(hash) { ChainState.prototype.commit = function commit(hash) {
this.hash = hash; if (typeof hash === 'string')
if (typeof this.hash !== 'string') hash = new Buffer(hash, 'hex');
this.hash = this.hash.toString('hex'); this.tip = hash;
return this.toRaw(hash); this.committed = true;
return this.toRaw();
}; };
ChainState.prototype.toRaw = function toRaw(hash) { ChainState.prototype.toRaw = function toRaw() {
var p = new BufferWriter(); var p = new BufferWriter();
p.writeHash(hash || this.hash); p.writeHash(this.tip);
p.writeU64(this.tx); p.writeU64(this.tx);
p.writeU64(this.coin); p.writeU64(this.coin);
p.writeU64(this.value); p.writeU64(this.value);
@ -1816,7 +1828,7 @@ ChainState.prototype.toRaw = function toRaw(hash) {
ChainState.fromRaw = function fromRaw(data) { ChainState.fromRaw = function fromRaw(data) {
var state = new ChainState(); var state = new ChainState();
var p = new BufferReader(data); var p = new BufferReader(data);
state.hash = p.readHash('hex'); state.tip = p.readHash();
// XXX Allow just a hash until I write a migration. // XXX Allow just a hash until I write a migration.
if (p.left() > 0) { if (p.left() > 0) {
state.tx = p.readU53(); state.tx = p.readU53();