txdb. refactor. fixes.

This commit is contained in:
Christopher Jeffrey 2016-03-04 04:57:29 -08:00
parent 55a7842f59
commit 57f37bba3c

View File

@ -281,71 +281,19 @@ TXPool.prototype._add = function add(tx, map, callback, force) {
unlock();
if (callback)
callback(err, result);
};
}
this.getTX(hash, function(err, existing) {
// Attempt to confirm tx before adding it.
this._confirm(tx, map, function(err, existing) {
if (err)
return done(err);
// Ignore if we already have this tx.
if (existing)
return done(null, true);
batch = self.db.batch();
if (existing) {
// Tricky - update the tx and coin in storage,
// and remove pending flag to mark as confirmed.
if (existing.ts === 0 && tx.ts !== 0) {
assert(tx.height >= 0);
assert(existing.ps > 0);
batch.put(prefix + 't/t/' + hash, tx.toExtended());
batch.del(prefix + 't/p/t/' + hash);
batch.put(prefix + 't/h/h/' + pad32(tx.height) + '/' + hash, DUMMY);
batch.del(prefix + 't/s/s/' + pad32(existing.ps) + '/' + hash);
batch.put(prefix + 't/s/s/' + pad32(tx.ts) + '/' + hash, DUMMY);
map.all.forEach(function(id) {
batch.del(prefix + 't/p/a/' + id + '/' + hash);
batch.put(
prefix + 't/h/a/' + id + '/' + pad32(tx.height) + '/' + hash, DUMMY);
batch.del(
prefix + 't/s/a/' + id + '/' + pad32(existing.ps) + '/' + hash);
batch.put(
prefix + 't/s/a/' + id + '/' + pad32(tx.ts) + '/' + hash, DUMMY);
});
utils.forEachSerial(tx.outputs, function(output, next, i) {
self.getCoin(hash, i, function(err, coin) {
if (err)
return next(err);
if (!coin)
return next();
coin.height = tx.height;
batch.put(prefix + 'u/t/' + hash + '/' + i, coin.toRaw());
next();
});
}, function(err) {
if (err)
return done(err);
batch.write(function(err) {
if (err)
return done(err);
self.emit('confirmed', tx, map);
self.emit('tx', tx, map);
return done(null, true);
});
});
return;
}
return done(null, false);
}
batch.put(prefix + 't/t/' + hash, tx.toExtended());
if (tx.ts === 0) {
@ -547,6 +495,85 @@ TXPool.prototype._add = function add(tx, map, callback, force) {
});
};
TXPool.prototype._confirm = function _confirm(tx, map, callback) {
var self = this;
var prefix = this.prefix + '/';
var hash = tx.hash('hex');
var batch;
this.getTX(hash, function(err, existing) {
if (err)
return callback(err);
// Haven't seen this tx before, add it.
if (!existing)
return callback(null, false);
// Existing tx is already confirmed. Ignore.
if (existing.ts !== 0)
return callback(null, true);
// The incoming tx won't confirm the existing one anyway. Ignore.
if (tx.ts === 0)
return callback(null, true);
batch = self.db.batch();
// Tricky - update the tx and coin in storage,
// and remove pending flag to mark as confirmed.
assert(tx.height >= 0);
assert(existing.ps > 0);
batch.put(prefix + 't/t/' + hash, tx.toExtended());
batch.del(prefix + 't/p/t/' + hash);
batch.put(prefix + 't/h/h/' + pad32(tx.height) + '/' + hash, DUMMY);
batch.del(prefix + 't/s/s/' + pad32(existing.ps) + '/' + hash);
batch.put(prefix + 't/s/s/' + pad32(tx.ts) + '/' + hash, DUMMY);
map.all.forEach(function(id) {
batch.del(prefix + 't/p/a/' + id + '/' + hash);
batch.put(prefix + 't/h/a/' + id + '/' + pad32(tx.height) + '/' + hash, DUMMY);
batch.del(prefix + 't/s/a/' + id + '/' + pad32(existing.ps) + '/' + hash);
batch.put(prefix + 't/s/a/' + id + '/' + pad32(tx.ts) + '/' + hash, DUMMY);
});
utils.forEachSerial(tx.outputs, function(output, next, i) {
var address = output.getAddress();
// Only update coins if this output is ours.
if (!address || !map[address].length)
return next();
self.getCoin(hash, i, function(err, coin) {
if (err)
return next(err);
if (!coin)
return next();
coin.height = tx.height;
batch.put(prefix + 'u/t/' + hash + '/' + i, coin.toRaw());
next();
});
}, function(err) {
if (err)
return callback(err);
batch.write(function(err) {
if (err)
return callback(err);
self.emit('confirmed', tx, map);
self.emit('tx', tx, map);
return callback(null, true);
});
});
});
};
TXPool.prototype.remove = function remove(hash, callback) {
var self = this;
@ -640,14 +667,15 @@ TXPool.prototype._remove = function remove(tx, map, callback) {
if (!input.output)
return;
if (address) {
map[address].forEach(function(id) {
batch.put(prefix + 'u/a/' + id
+ '/' + input.prevout.hash
+ '/' + input.prevout.index,
DUMMY);
});
}
if (!address || !map[address].length)
return;
map[address].forEach(function(id) {
batch.put(prefix + 'u/a/' + id
+ '/' + input.prevout.hash
+ '/' + input.prevout.index,
DUMMY);
});
batch.put(prefix + 'u/t/'
+ input.prevout.hash
@ -660,11 +688,12 @@ TXPool.prototype._remove = function remove(tx, map, callback) {
tx.outputs.forEach(function(output, i) {
var address = output.getAddress();
if (address) {
map[address].forEach(function(id) {
batch.del(prefix + 'u/a/' + id + '/' + hash + '/' + i);
});
}
if (!address || !map[address].length)
return;
map[address].forEach(function(id) {
batch.del(prefix + 'u/a/' + id + '/' + hash + '/' + i);
});
batch.del(prefix + 'u/t/' + hash + '/' + i);
});
@ -680,78 +709,6 @@ TXPool.prototype._remove = function remove(tx, map, callback) {
});
};
TXPool.prototype._confirm = function _confirm(tx, map, callback) {
var self = this;
var prefix = this.prefix + '/';
var hash = tx.hash('hex');
var height = tx.height;
var ts = tx.ts;
var batch;
this.getTX(hash, function(err, existing) {
if (err)
return done(err);
batch = self.db.batch();
if (!existing)
return callback(null, false);
if (!(existing.ts === 0 && tx.ts !== 0))
return callback(null, true);
// Tricky - update the tx and coin in storage,
// and remove pending flag to mark as confirmed.
assert(tx.height >= 0);
assert(existing.ps > 0);
batch.put(prefix + 't/t/' + hash, tx.toExtended());
batch.del(prefix + 't/p/t/' + hash);
batch.put(prefix + 't/h/h/' + pad32(tx.height) + '/' + hash, DUMMY);
batch.del(prefix + 't/s/s/' + pad32(existing.ps) + '/' + hash);
batch.put(prefix + 't/s/s/' + pad32(tx.ts) + '/' + hash, DUMMY);
map.all.forEach(function(id) {
batch.del(prefix + 't/p/a/' + id + '/' + hash);
batch.put(
prefix + 't/h/a/' + id + '/' + pad32(tx.height) + '/' + hash, DUMMY);
batch.del(
prefix + 't/s/a/' + id + '/' + pad32(existing.ps) + '/' + hash);
batch.put(
prefix + 't/s/a/' + id + '/' + pad32(tx.ts) + '/' + hash, DUMMY);
});
utils.forEachSerial(tx.outputs, function(output, next, i) {
self.getCoin(hash, i, function(err, coin) {
if (err)
return next(err);
if (!coin)
return next();
coin.height = tx.height;
batch.put(prefix + 'u/t/' + hash + '/' + i, coin.toRaw());
next();
});
}, function(err) {
if (err)
return done(err);
batch.write(function(err) {
if (err)
return done(err);
self.emit('confirmed', tx, map);
self.emit('tx', tx, map);
return callback(null, true);
});
});
});
};
TXPool.prototype.unconfirm = function unconfirm(hash, callback) {
var self = this;
@ -823,6 +780,9 @@ TXPool.prototype._unconfirm = function unconfirm(tx, map, callback) {
if (!coin)
return next();
if (!address || !map[address].length)
return next();
coin.height = tx.height;
batch.put(prefix + 'u/t/' + hash + '/' + i, coin.toRaw());