txdb: refactor. clean up.
This commit is contained in:
parent
c582a0fad8
commit
63c9c81831
@ -284,10 +284,10 @@ config.parseArg = function parseArg(argv) {
|
|||||||
|
|
||||||
if (arg[0] === '-') {
|
if (arg[0] === '-') {
|
||||||
// e.g. -abc
|
// e.g. -abc
|
||||||
arg = arg.substring(1).split('');
|
arg = arg.substring(1);
|
||||||
|
|
||||||
for (i = 0; i < arg.length; i++) {
|
for (i = 0; i < arg.length; i++) {
|
||||||
key = arg[i].trim();
|
key = arg[i];
|
||||||
alias = config.alias.arg[key];
|
alias = config.alias.arg[key];
|
||||||
if (alias)
|
if (alias)
|
||||||
key = alias;
|
key = alias;
|
||||||
|
|||||||
@ -64,6 +64,7 @@ function TXDB(db, options) {
|
|||||||
this.busy = false;
|
this.busy = false;
|
||||||
this.jobs = [];
|
this.jobs = [];
|
||||||
this.locker = new bcoin.locker(this);
|
this.locker = new bcoin.locker(this);
|
||||||
|
this.current = null;
|
||||||
|
|
||||||
this.coinCache = new bcoin.lru(10000, 1);
|
this.coinCache = new bcoin.lru(10000, 1);
|
||||||
|
|
||||||
@ -90,6 +91,77 @@ TXDB.prototype._lock = function _lock(func, args, force) {
|
|||||||
return this.locker.lock(func, args, force);
|
return this.locker.lock(func, args, force);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a batch.
|
||||||
|
* @returns {Batch}
|
||||||
|
*/
|
||||||
|
|
||||||
|
TXDB.prototype.start = function start() {
|
||||||
|
assert(!this.current);
|
||||||
|
this.current = this.db.batch();
|
||||||
|
return this.current;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put key and value to current batch.
|
||||||
|
* @param {String} key
|
||||||
|
* @param {Buffer} value
|
||||||
|
*/
|
||||||
|
|
||||||
|
TXDB.prototype.put = function put(key, value) {
|
||||||
|
assert(this.current);
|
||||||
|
this.current.put(key, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete key from current batch.
|
||||||
|
* @param {String} key
|
||||||
|
*/
|
||||||
|
|
||||||
|
TXDB.prototype.del = function del(key) {
|
||||||
|
assert(this.current);
|
||||||
|
this.current.del(key);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current batch.
|
||||||
|
* @returns {Batch}
|
||||||
|
*/
|
||||||
|
|
||||||
|
TXDB.prototype.batch = function batch() {
|
||||||
|
assert(this.current);
|
||||||
|
return this.current;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop current batch.
|
||||||
|
* @returns {Batch}
|
||||||
|
*/
|
||||||
|
|
||||||
|
TXDB.prototype.drop = function drop() {
|
||||||
|
assert(this.current);
|
||||||
|
this.current.clear();
|
||||||
|
this.current = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commit current batch.
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
TXDB.prototype.commit = function commit(callback) {
|
||||||
|
var self = this;
|
||||||
|
assert(this.current);
|
||||||
|
this.current.write(function(err) {
|
||||||
|
if (err) {
|
||||||
|
self.current = null;
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
self.current = null;
|
||||||
|
return callback();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the bloom filter into memory.
|
* Load the bloom filter into memory.
|
||||||
* @private
|
* @private
|
||||||
@ -146,7 +218,7 @@ TXDB.prototype.getInfo = function getInfo(tx, callback) {
|
|||||||
if (!this.testFilter(addresses))
|
if (!this.testFilter(addresses))
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
this.mapAddresses(addresses, function(err, table) {
|
this.getTable(addresses, function(err, table) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -160,12 +232,12 @@ TXDB.prototype.getInfo = function getInfo(tx, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map address hashes to a wallet ID.
|
* Map address hashes to paths.
|
||||||
* @param {Hash[]} address - Address hashes.
|
* @param {Hash[]} address - Address hashes.
|
||||||
* @param {Function} callback - Returns [Error, {@link AddressTable}].
|
* @param {Function} callback - Returns [Error, {@link AddressTable}].
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.mapAddresses = function mapAddresses(address, callback) {
|
TXDB.prototype.getTable = function getTable(address, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var table = {};
|
var table = {};
|
||||||
var count = 0;
|
var count = 0;
|
||||||
@ -217,20 +289,21 @@ TXDB.prototype.mapAddresses = function mapAddresses(address, callback) {
|
|||||||
|
|
||||||
TXDB.prototype._addOrphan = function _addOrphan(key, outpoint, callback) {
|
TXDB.prototype._addOrphan = function _addOrphan(key, outpoint, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var batch = this.batch();
|
||||||
var p;
|
var p;
|
||||||
|
|
||||||
this.db.get('o/' + key, function(err, buf) {
|
this.db.get('o/' + key, function(err, data) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
p = new BufferWriter();
|
p = new BufferWriter();
|
||||||
|
|
||||||
if (buf)
|
if (data)
|
||||||
p.writeBytes(buf);
|
p.writeBytes(data);
|
||||||
|
|
||||||
p.writeBytes(outpoint);
|
p.writeBytes(outpoint);
|
||||||
|
|
||||||
self.batch().put('o/' + key, p.render());
|
batch.put('o/' + key, p.render());
|
||||||
|
|
||||||
return callback();
|
return callback();
|
||||||
});
|
});
|
||||||
@ -245,10 +318,10 @@ TXDB.prototype._addOrphan = function _addOrphan(key, outpoint, callback) {
|
|||||||
|
|
||||||
TXDB.prototype._getOrphans = function _getOrphans(key, callback) {
|
TXDB.prototype._getOrphans = function _getOrphans(key, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var out = [];
|
var items = [];
|
||||||
|
|
||||||
this.db.fetch('o/' + key, function(buf) {
|
this.db.fetch('o/' + key, function(data) {
|
||||||
var p = new BufferReader(buf);
|
var p = new BufferReader(data);
|
||||||
var orphans = [];
|
var orphans = [];
|
||||||
|
|
||||||
while (p.left())
|
while (p.left())
|
||||||
@ -267,7 +340,7 @@ TXDB.prototype._getOrphans = function _getOrphans(key, callback) {
|
|||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
|
|
||||||
out.push([orphan, tx]);
|
items.push([orphan, tx]);
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
@ -275,7 +348,7 @@ TXDB.prototype._getOrphans = function _getOrphans(key, callback) {
|
|||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
return callback(null, out);
|
return callback(null, items);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -296,7 +369,7 @@ TXDB.prototype.writeGenesis = function writeGenesis(callback) {
|
|||||||
|
|
||||||
callback = utils.wrap(callback, unlock);
|
callback = utils.wrap(callback, unlock);
|
||||||
|
|
||||||
self.db.has('R', function(err, result) {
|
this.db.has('R', function(err, result) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -304,6 +377,7 @@ TXDB.prototype.writeGenesis = function writeGenesis(callback) {
|
|||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
hash = new Buffer(self.network.genesis.hash, 'hex');
|
hash = new Buffer(self.network.genesis.hash, 'hex');
|
||||||
|
|
||||||
self.db.put('R', hash, callback);
|
self.db.put('R', hash, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -399,46 +473,6 @@ TXDB.prototype.removeBlock = function removeBlock(block, callback, force) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
TXDB.prototype.start = function start() {
|
|
||||||
assert(!this.current);
|
|
||||||
this.current = this.db.batch();
|
|
||||||
return this.current;
|
|
||||||
};
|
|
||||||
|
|
||||||
TXDB.prototype.put = function put(key, value) {
|
|
||||||
assert(this.current);
|
|
||||||
this.current.put(key, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
TXDB.prototype.del = function del(key, value) {
|
|
||||||
assert(this.current);
|
|
||||||
this.current.del(key);
|
|
||||||
};
|
|
||||||
|
|
||||||
TXDB.prototype.batch = function batch() {
|
|
||||||
assert(this.current);
|
|
||||||
return this.current;
|
|
||||||
};
|
|
||||||
|
|
||||||
TXDB.prototype.drop = function drop() {
|
|
||||||
assert(this.current);
|
|
||||||
this.current.clear();
|
|
||||||
this.current = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
TXDB.prototype.commit = function commit(callback) {
|
|
||||||
var self = this;
|
|
||||||
assert(this.current);
|
|
||||||
this.current.write(function(err) {
|
|
||||||
if (err) {
|
|
||||||
self.current = null;
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
self.current = null;
|
|
||||||
return callback();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a transaction to the database, map addresses
|
* Add a transaction to the database, map addresses
|
||||||
* to wallet IDs, potentially store orphans, resolve
|
* to wallet IDs, potentially store orphans, resolve
|
||||||
@ -456,7 +490,7 @@ TXDB.prototype.add = function add(tx, callback, force) {
|
|||||||
|
|
||||||
callback = utils.wrap(callback, unlock);
|
callback = utils.wrap(callback, unlock);
|
||||||
|
|
||||||
return this.getInfo(tx, function(err, info) {
|
this.getInfo(tx, function(err, info) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -469,12 +503,22 @@ TXDB.prototype.add = function add(tx, callback, force) {
|
|||||||
|
|
||||||
self.logger.debug(info.paths);
|
self.logger.debug(info.paths);
|
||||||
|
|
||||||
return self._add(tx, info, callback);
|
self._add(tx, info, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve coins for own inputs, remove
|
||||||
|
* double spenders, and verify inputs.
|
||||||
|
* @private
|
||||||
|
* @param {TX} tx
|
||||||
|
* @param {PathInfo} info
|
||||||
|
* @param {Function} callback - Returns [Error].
|
||||||
|
*/
|
||||||
|
|
||||||
TXDB.prototype._verify = function _verify(tx, info, callback) {
|
TXDB.prototype._verify = function _verify(tx, info, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
utils.forEachSerial(tx.inputs, function(input, next, i) {
|
utils.forEachSerial(tx.inputs, function(input, next, i) {
|
||||||
var prevout = input.prevout;
|
var prevout = input.prevout;
|
||||||
var address, paths;
|
var address, paths;
|
||||||
@ -555,12 +599,20 @@ TXDB.prototype._verify = function _verify(tx, info, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
TXDB.prototype._resolveOrphans = function _resolveOrphans(tx, i, callback) {
|
/**
|
||||||
|
* Attempt to resolve orphans for an output.
|
||||||
|
* @private
|
||||||
|
* @param {TX} tx
|
||||||
|
* @param {Number} index
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
TXDB.prototype._resolveOrphans = function _resolveOrphans(tx, index, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var batch = this.batch();
|
var batch = this.batch();
|
||||||
var hash = tx.hash('hex');
|
var hash = tx.hash('hex');
|
||||||
var output = tx.outputs[i];
|
var output = tx.outputs[index];
|
||||||
var key = hash + '/' + i;
|
var key = hash + '/' + index;
|
||||||
var coin;
|
var coin;
|
||||||
|
|
||||||
this._getOrphans(key, function(err, orphans) {
|
this._getOrphans(key, function(err, orphans) {
|
||||||
@ -572,12 +624,12 @@ TXDB.prototype._resolveOrphans = function _resolveOrphans(tx, i, callback) {
|
|||||||
|
|
||||||
batch.del('o/' + key);
|
batch.del('o/' + key);
|
||||||
|
|
||||||
coin = bcoin.coin.fromTX(tx, i);
|
coin = bcoin.coin.fromTX(tx, index);
|
||||||
|
|
||||||
// Add input to orphan
|
// Add input to orphan
|
||||||
utils.forEachSerial(orphans, function(pair, next) {
|
utils.forEachSerial(orphans, function(item, next) {
|
||||||
var input = pair[0];
|
var input = item[0];
|
||||||
var orphan = pair[1];
|
var orphan = item[1];
|
||||||
|
|
||||||
// Probably removed by some other means.
|
// Probably removed by some other means.
|
||||||
if (!orphan)
|
if (!orphan)
|
||||||
@ -586,7 +638,7 @@ TXDB.prototype._resolveOrphans = function _resolveOrphans(tx, i, callback) {
|
|||||||
orphan.inputs[input.index].coin = coin;
|
orphan.inputs[input.index].coin = coin;
|
||||||
|
|
||||||
assert(orphan.inputs[input.index].prevout.hash === hash);
|
assert(orphan.inputs[input.index].prevout.hash === hash);
|
||||||
assert(orphan.inputs[input.index].prevout.index === i);
|
assert(orphan.inputs[input.index].prevout.index === index);
|
||||||
|
|
||||||
// Verify that input script is correct, if not - add
|
// Verify that input script is correct, if not - add
|
||||||
// output to unspent and remove orphan from storage
|
// output to unspent and remove orphan from storage
|
||||||
@ -605,10 +657,19 @@ TXDB.prototype._resolveOrphans = function _resolveOrphans(tx, i, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add transaction, runs _confirm (separate batch) and
|
||||||
|
* verify (separate batch for double spenders).
|
||||||
|
* @private
|
||||||
|
* @param {TX} tx
|
||||||
|
* @param {PathInfo} info
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
|
||||||
TXDB.prototype._add = function add(tx, info, callback) {
|
TXDB.prototype._add = function add(tx, info, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var updated = false;
|
var updated = false;
|
||||||
var batch, hash, i, j, unlock, path, paths, id;
|
var batch, hash, i, j, path, paths, id;
|
||||||
|
|
||||||
if (tx.mutable)
|
if (tx.mutable)
|
||||||
tx = tx.toTX();
|
tx = tx.toTX();
|
||||||
@ -692,8 +753,10 @@ TXDB.prototype._add = function add(tx, info, callback) {
|
|||||||
|
|
||||||
next();
|
next();
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err)
|
if (err) {
|
||||||
|
self.drop();
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
// Add unspent outputs or resolve orphans
|
// Add unspent outputs or resolve orphans
|
||||||
utils.forEachSerial(tx.outputs, function(output, next, i) {
|
utils.forEachSerial(tx.outputs, function(output, next, i) {
|
||||||
@ -712,7 +775,7 @@ TXDB.prototype._add = function add(tx, info, callback) {
|
|||||||
|
|
||||||
self._resolveOrphans(tx, i, function(err, orphans) {
|
self._resolveOrphans(tx, i, function(err, orphans) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return next(err);
|
||||||
|
|
||||||
if (orphans)
|
if (orphans)
|
||||||
return next();
|
return next();
|
||||||
@ -736,8 +799,10 @@ TXDB.prototype._add = function add(tx, info, callback) {
|
|||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err)
|
if (err) {
|
||||||
|
self.drop();
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
self.commit(function(err) {
|
self.commit(function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
@ -834,20 +899,19 @@ TXDB.prototype._removeRecursive = function _removeRecursive(tx, callback) {
|
|||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
|
|
||||||
|
if (!spent)
|
||||||
|
return next();
|
||||||
|
|
||||||
// Remove all of the spender's spenders first.
|
// Remove all of the spender's spenders first.
|
||||||
if (spent) {
|
self.getTX(spent.hash, function(err, tx) {
|
||||||
return self.getTX(spent.hash, function(err, tx) {
|
if (err)
|
||||||
if (err)
|
return next(err);
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
if (!tx)
|
if (!tx)
|
||||||
return callback(new Error('Could not find spender.'));
|
return next(new Error('Could not find spender.'));
|
||||||
|
|
||||||
return self._removeRecursive(tx, next);
|
self._removeRecursive(tx, next);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
@ -856,14 +920,16 @@ TXDB.prototype._removeRecursive = function _removeRecursive(tx, callback) {
|
|||||||
self.start();
|
self.start();
|
||||||
|
|
||||||
// Remove the spender.
|
// Remove the spender.
|
||||||
self._lazyRemove(tx, function(err, res1, res2) {
|
self._lazyRemove(tx, function(err, result, info) {
|
||||||
if (err)
|
if (err) {
|
||||||
|
self.drop();
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
self.commit(function(err) {
|
self.commit(function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
callback(null, res1, res2);
|
return callback(null, result, info);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -880,7 +946,8 @@ TXDB.prototype.isDoubleSpend = function isDoubleSpend(tx, callback) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
utils.everySerial(tx.inputs, function(input, next) {
|
utils.everySerial(tx.inputs, function(input, next) {
|
||||||
self.isSpent(input.prevout.hash, input.prevout.index, function(err, spent) {
|
var prevout = input.prevout;
|
||||||
|
self.isSpent(prevout.hash, prevout.index, function(err, spent) {
|
||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
return next(null, !spent);
|
return next(null, !spent);
|
||||||
@ -901,7 +968,7 @@ TXDB.prototype.isDoubleSpend = function isDoubleSpend(tx, callback) {
|
|||||||
|
|
||||||
TXDB.prototype.isSpent = function isSpent(hash, index, callback) {
|
TXDB.prototype.isSpent = function isSpent(hash, index, callback) {
|
||||||
var key = 's/' + hash + '/' + index;
|
var key = 's/' + hash + '/' + index;
|
||||||
return this.db.fetch(key, function(data) {
|
this.db.fetch(key, function(data) {
|
||||||
return bcoin.outpoint.fromRaw(data);
|
return bcoin.outpoint.fromRaw(data);
|
||||||
}, callback);
|
}, callback);
|
||||||
};
|
};
|
||||||
@ -918,9 +985,8 @@ TXDB.prototype.isSpent = function isSpent(hash, index, callback) {
|
|||||||
|
|
||||||
TXDB.prototype._confirm = function _confirm(tx, info, callback) {
|
TXDB.prototype._confirm = function _confirm(tx, info, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var hash, batch, unlock, i, id;
|
var hash = tx.hash('hex');
|
||||||
|
var batch, i, id;
|
||||||
hash = tx.hash('hex');
|
|
||||||
|
|
||||||
this.getTX(hash, function(err, existing) {
|
this.getTX(hash, function(err, existing) {
|
||||||
if (err)
|
if (err)
|
||||||
@ -982,8 +1048,10 @@ TXDB.prototype._confirm = function _confirm(tx, info, callback) {
|
|||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err)
|
if (err) {
|
||||||
|
self.drop();
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
self.emit('confirmed', tx, info);
|
self.emit('confirmed', tx, info);
|
||||||
self.emit('tx', tx, info);
|
self.emit('tx', tx, info);
|
||||||
@ -1005,40 +1073,18 @@ TXDB.prototype._confirm = function _confirm(tx, info, callback) {
|
|||||||
|
|
||||||
TXDB.prototype.remove = function remove(hash, callback, force) {
|
TXDB.prototype.remove = function remove(hash, callback, force) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var unlock = this._lock(remove, [hash, callback], force);
|
||||||
|
|
||||||
if (hash.hash)
|
if (!unlock)
|
||||||
hash = hash.hash('hex');
|
return;
|
||||||
|
|
||||||
this.getTX(hash, function(err, tx) {
|
callback = utils.wrap(callback, unlock);
|
||||||
|
|
||||||
|
this._removeRecursive(hash, function(err, result, info) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
if (!tx)
|
return callback(null, !!result, info);
|
||||||
return callback(null, true);
|
|
||||||
|
|
||||||
assert(tx.hash('hex') === hash);
|
|
||||||
|
|
||||||
return self.getInfo(tx, function(err, info) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
if (!info)
|
|
||||||
return callback(null, false);
|
|
||||||
|
|
||||||
self.start();
|
|
||||||
|
|
||||||
return self._remove(tx, info, function(err, res1, res2) {
|
|
||||||
if (err) {
|
|
||||||
self.drop();
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
self.commit(function(err) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
callback(null, res1, res2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1059,7 +1105,7 @@ TXDB.prototype._lazyRemove = function lazyRemove(tx, callback) {
|
|||||||
if (!info)
|
if (!info)
|
||||||
return callback(null, false);
|
return callback(null, false);
|
||||||
|
|
||||||
return self._remove(tx, info, callback);
|
self._remove(tx, info, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1073,12 +1119,9 @@ TXDB.prototype._lazyRemove = function lazyRemove(tx, callback) {
|
|||||||
|
|
||||||
TXDB.prototype._remove = function remove(tx, info, callback) {
|
TXDB.prototype._remove = function remove(tx, info, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var unlock, hash, batch, i, j, path, id;
|
var hash = tx.hash('hex');
|
||||||
var key, paths, address, input, output, coin;
|
var batch = this.batch();
|
||||||
|
var i, j, path, id, key, paths, address, input, output, coin;
|
||||||
hash = tx.hash('hex');
|
|
||||||
|
|
||||||
batch = this.batch();
|
|
||||||
|
|
||||||
batch.del('t/' + hash);
|
batch.del('t/' + hash);
|
||||||
|
|
||||||
@ -1190,9 +1233,7 @@ TXDB.prototype.unconfirm = function unconfirm(hash, callback, force) {
|
|||||||
if (!tx)
|
if (!tx)
|
||||||
return callback(null, true);
|
return callback(null, true);
|
||||||
|
|
||||||
assert(tx.hash('hex') === hash);
|
self.getInfo(tx, function(err, info) {
|
||||||
|
|
||||||
return self.getInfo(tx, function(err, info) {
|
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -1201,7 +1242,7 @@ TXDB.prototype.unconfirm = function unconfirm(hash, callback, force) {
|
|||||||
|
|
||||||
self.start();
|
self.start();
|
||||||
|
|
||||||
return self._unconfirm(tx, info, function(err, res1, res2) {
|
self._unconfirm(tx, info, function(err, res1, res2) {
|
||||||
if (err) {
|
if (err) {
|
||||||
self.drop();
|
self.drop();
|
||||||
return callback(err);
|
return callback(err);
|
||||||
@ -1225,11 +1266,10 @@ TXDB.prototype.unconfirm = function unconfirm(hash, callback, force) {
|
|||||||
|
|
||||||
TXDB.prototype._unconfirm = function unconfirm(tx, info, callback, force) {
|
TXDB.prototype._unconfirm = function unconfirm(tx, info, callback, force) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var batch, unlock, hash, height, i, id;
|
var batch = this.batch();
|
||||||
|
var hash = tx.hash('hex');
|
||||||
batch = this.batch();
|
var height = tx.height;
|
||||||
hash = tx.hash('hex');
|
var i, id;
|
||||||
height = tx.height;
|
|
||||||
|
|
||||||
if (height !== -1)
|
if (height !== -1)
|
||||||
return callback(null, false, info);
|
return callback(null, false, info);
|
||||||
@ -1453,7 +1493,7 @@ TXDB.prototype.getRange = function getLast(id, options, callback) {
|
|||||||
id = null;
|
id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getRangeHashes(id, options, function(err, hashes) {
|
this.getRangeHashes(id, options, function(err, hashes) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -1492,7 +1532,7 @@ TXDB.prototype.getLast = function getLast(id, limit, callback) {
|
|||||||
id = null;
|
id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getRange(id, {
|
this.getRange(id, {
|
||||||
start: 0,
|
start: 0,
|
||||||
end: 0xffffffff,
|
end: 0xffffffff,
|
||||||
reverse: true,
|
reverse: true,
|
||||||
@ -1515,7 +1555,7 @@ TXDB.prototype.getHistory = function getHistory(id, callback) {
|
|||||||
id = null;
|
id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getHistoryHashes(id, function(err, hashes) {
|
this.getHistoryHashes(id, function(err, hashes) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -1554,7 +1594,7 @@ TXDB.prototype.getLastTime = function getLastTime(id, callback) {
|
|||||||
id = null;
|
id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getHistory(id, function(err, txs) {
|
this.getHistory(id, function(err, txs) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -1590,7 +1630,7 @@ TXDB.prototype.getUnconfirmed = function getUnconfirmed(id, callback) {
|
|||||||
id = null;
|
id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getUnconfirmedHashes(id, function(err, hashes) {
|
this.getUnconfirmedHashes(id, function(err, hashes) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -1630,7 +1670,7 @@ TXDB.prototype.getCoins = function getCoins(id, callback) {
|
|||||||
id = null;
|
id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getCoinHashes(id, function(err, hashes) {
|
this.getCoinHashes(id, function(err, hashes) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -1707,10 +1747,12 @@ TXDB.prototype.fillCoins = function fillCoins(tx, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
utils.forEachSerial(tx.inputs, function(input, next) {
|
utils.forEachSerial(tx.inputs, function(input, next) {
|
||||||
|
var prevout = input.prevout;
|
||||||
|
|
||||||
if (input.coin)
|
if (input.coin)
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
self.getCoin(input.prevout.hash, input.prevout.index, function(err, coin) {
|
self.getCoin(prevout.hash, prevout.index, function(err, coin) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -1771,7 +1813,7 @@ TXDB.prototype.toDetails = function toDetails(id, tx, callback) {
|
|||||||
|
|
||||||
if (Array.isArray(tx)) {
|
if (Array.isArray(tx)) {
|
||||||
out = [];
|
out = [];
|
||||||
utils.forEachSerial(tx, function(tx, next) {
|
return utils.forEachSerial(tx, function(tx, next) {
|
||||||
self.toDetails(tx, function(err, details) {
|
self.toDetails(tx, function(err, details) {
|
||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
@ -1812,7 +1854,7 @@ TXDB.prototype.toDetails = function toDetails(id, tx, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.hasTX = function hasTX(hash, callback) {
|
TXDB.prototype.hasTX = function hasTX(hash, callback) {
|
||||||
return this.db.has('t/' + hash, callback);
|
this.db.has('t/' + hash, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1859,7 +1901,7 @@ TXDB.prototype.hasCoin = function hasCoin(hash, index, callback) {
|
|||||||
if (this.coinCache.has(key))
|
if (this.coinCache.has(key))
|
||||||
return callback(null, true);
|
return callback(null, true);
|
||||||
|
|
||||||
return this.db.has('c/' + key, callback);
|
this.db.has('c/' + key, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1891,7 +1933,7 @@ TXDB.prototype.getBalance = function getBalance(id, callback) {
|
|||||||
confirmed += value;
|
confirmed += value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getCoinHashes(id, function(err, hashes) {
|
this.getCoinHashes(id, function(err, hashes) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -1965,23 +2007,37 @@ TXDB.prototype.zap = function zap(id, age, callback, force) {
|
|||||||
if (!utils.isNumber(age))
|
if (!utils.isNumber(age))
|
||||||
return callback(new Error('Age must be a number.'));
|
return callback(new Error('Age must be a number.'));
|
||||||
|
|
||||||
return this.getRange(id, {
|
this.getRange(id, {
|
||||||
start: 0,
|
start: 0,
|
||||||
end: bcoin.now() - age
|
end: bcoin.now() - age
|
||||||
}, function(err, txs) {
|
}, function(err, txs) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
self.fillHistory(txs, function(err) {
|
utils.forEachSerial(txs, function(tx, next) {
|
||||||
if (err)
|
if (tx.ts !== 0)
|
||||||
return callback(err);
|
return next();
|
||||||
|
self.remove(tx.hash('hex'), next, true);
|
||||||
|
}, callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
utils.forEachSerial(txs, function(tx, next) {
|
/**
|
||||||
if (tx.ts !== 0)
|
* Abandon transaction.
|
||||||
return next();
|
* @param {Hash} hash
|
||||||
self.remove(tx.hash('hex'), next, true);
|
* @param {Function} callback
|
||||||
}, callback);
|
*/
|
||||||
});
|
|
||||||
|
TXDB.prototype.abandon = function abandon(hash, callback, force) {
|
||||||
|
var self = this;
|
||||||
|
this.db.has('p/' + hash, function(err, result) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
return callback(new Error('TX not found.'));
|
||||||
|
|
||||||
|
self.remove(hash, callback, force);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user