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] === '-') {
|
||||
// e.g. -abc
|
||||
arg = arg.substring(1).split('');
|
||||
arg = arg.substring(1);
|
||||
|
||||
for (i = 0; i < arg.length; i++) {
|
||||
key = arg[i].trim();
|
||||
key = arg[i];
|
||||
alias = config.alias.arg[key];
|
||||
if (alias)
|
||||
key = alias;
|
||||
|
||||
@ -64,6 +64,7 @@ function TXDB(db, options) {
|
||||
this.busy = false;
|
||||
this.jobs = [];
|
||||
this.locker = new bcoin.locker(this);
|
||||
this.current = null;
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @private
|
||||
@ -146,7 +218,7 @@ TXDB.prototype.getInfo = function getInfo(tx, callback) {
|
||||
if (!this.testFilter(addresses))
|
||||
return callback();
|
||||
|
||||
this.mapAddresses(addresses, function(err, table) {
|
||||
this.getTable(addresses, function(err, table) {
|
||||
if (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 {Function} callback - Returns [Error, {@link AddressTable}].
|
||||
*/
|
||||
|
||||
TXDB.prototype.mapAddresses = function mapAddresses(address, callback) {
|
||||
TXDB.prototype.getTable = function getTable(address, callback) {
|
||||
var self = this;
|
||||
var table = {};
|
||||
var count = 0;
|
||||
@ -217,20 +289,21 @@ TXDB.prototype.mapAddresses = function mapAddresses(address, callback) {
|
||||
|
||||
TXDB.prototype._addOrphan = function _addOrphan(key, outpoint, callback) {
|
||||
var self = this;
|
||||
var batch = this.batch();
|
||||
var p;
|
||||
|
||||
this.db.get('o/' + key, function(err, buf) {
|
||||
this.db.get('o/' + key, function(err, data) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
p = new BufferWriter();
|
||||
|
||||
if (buf)
|
||||
p.writeBytes(buf);
|
||||
if (data)
|
||||
p.writeBytes(data);
|
||||
|
||||
p.writeBytes(outpoint);
|
||||
|
||||
self.batch().put('o/' + key, p.render());
|
||||
batch.put('o/' + key, p.render());
|
||||
|
||||
return callback();
|
||||
});
|
||||
@ -245,10 +318,10 @@ TXDB.prototype._addOrphan = function _addOrphan(key, outpoint, callback) {
|
||||
|
||||
TXDB.prototype._getOrphans = function _getOrphans(key, callback) {
|
||||
var self = this;
|
||||
var out = [];
|
||||
var items = [];
|
||||
|
||||
this.db.fetch('o/' + key, function(buf) {
|
||||
var p = new BufferReader(buf);
|
||||
this.db.fetch('o/' + key, function(data) {
|
||||
var p = new BufferReader(data);
|
||||
var orphans = [];
|
||||
|
||||
while (p.left())
|
||||
@ -267,7 +340,7 @@ TXDB.prototype._getOrphans = function _getOrphans(key, callback) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
out.push([orphan, tx]);
|
||||
items.push([orphan, tx]);
|
||||
|
||||
next();
|
||||
});
|
||||
@ -275,7 +348,7 @@ TXDB.prototype._getOrphans = function _getOrphans(key, callback) {
|
||||
if (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);
|
||||
|
||||
self.db.has('R', function(err, result) {
|
||||
this.db.has('R', function(err, result) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -304,6 +377,7 @@ TXDB.prototype.writeGenesis = function writeGenesis(callback) {
|
||||
return callback();
|
||||
|
||||
hash = new Buffer(self.network.genesis.hash, 'hex');
|
||||
|
||||
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
|
||||
* to wallet IDs, potentially store orphans, resolve
|
||||
@ -456,7 +490,7 @@ TXDB.prototype.add = function add(tx, callback, force) {
|
||||
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
return this.getInfo(tx, function(err, info) {
|
||||
this.getInfo(tx, function(err, info) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -469,12 +503,22 @@ TXDB.prototype.add = function add(tx, callback, force) {
|
||||
|
||||
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) {
|
||||
var self = this;
|
||||
|
||||
utils.forEachSerial(tx.inputs, function(input, next, i) {
|
||||
var prevout = input.prevout;
|
||||
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 batch = this.batch();
|
||||
var hash = tx.hash('hex');
|
||||
var output = tx.outputs[i];
|
||||
var key = hash + '/' + i;
|
||||
var output = tx.outputs[index];
|
||||
var key = hash + '/' + index;
|
||||
var coin;
|
||||
|
||||
this._getOrphans(key, function(err, orphans) {
|
||||
@ -572,12 +624,12 @@ TXDB.prototype._resolveOrphans = function _resolveOrphans(tx, i, callback) {
|
||||
|
||||
batch.del('o/' + key);
|
||||
|
||||
coin = bcoin.coin.fromTX(tx, i);
|
||||
coin = bcoin.coin.fromTX(tx, index);
|
||||
|
||||
// Add input to orphan
|
||||
utils.forEachSerial(orphans, function(pair, next) {
|
||||
var input = pair[0];
|
||||
var orphan = pair[1];
|
||||
utils.forEachSerial(orphans, function(item, next) {
|
||||
var input = item[0];
|
||||
var orphan = item[1];
|
||||
|
||||
// Probably removed by some other means.
|
||||
if (!orphan)
|
||||
@ -586,7 +638,7 @@ TXDB.prototype._resolveOrphans = function _resolveOrphans(tx, i, callback) {
|
||||
orphan.inputs[input.index].coin = coin;
|
||||
|
||||
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
|
||||
// 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) {
|
||||
var self = this;
|
||||
var updated = false;
|
||||
var batch, hash, i, j, unlock, path, paths, id;
|
||||
var batch, hash, i, j, path, paths, id;
|
||||
|
||||
if (tx.mutable)
|
||||
tx = tx.toTX();
|
||||
@ -692,8 +753,10 @@ TXDB.prototype._add = function add(tx, info, callback) {
|
||||
|
||||
next();
|
||||
}, function(err) {
|
||||
if (err)
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// Add unspent outputs or resolve orphans
|
||||
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) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return next(err);
|
||||
|
||||
if (orphans)
|
||||
return next();
|
||||
@ -736,8 +799,10 @@ TXDB.prototype._add = function add(tx, info, callback) {
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
self.commit(function(err) {
|
||||
if (err)
|
||||
@ -834,20 +899,19 @@ TXDB.prototype._removeRecursive = function _removeRecursive(tx, callback) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!spent)
|
||||
return next();
|
||||
|
||||
// Remove all of the spender's spenders first.
|
||||
if (spent) {
|
||||
return self.getTX(spent.hash, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.getTX(spent.hash, function(err, tx) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!tx)
|
||||
return callback(new Error('Could not find spender.'));
|
||||
if (!tx)
|
||||
return next(new Error('Could not find spender.'));
|
||||
|
||||
return self._removeRecursive(tx, next);
|
||||
});
|
||||
}
|
||||
|
||||
next();
|
||||
self._removeRecursive(tx, next);
|
||||
});
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
@ -856,14 +920,16 @@ TXDB.prototype._removeRecursive = function _removeRecursive(tx, callback) {
|
||||
self.start();
|
||||
|
||||
// Remove the spender.
|
||||
self._lazyRemove(tx, function(err, res1, res2) {
|
||||
if (err)
|
||||
self._lazyRemove(tx, function(err, result, info) {
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
self.commit(function(err) {
|
||||
if (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;
|
||||
|
||||
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)
|
||||
return next(err);
|
||||
return next(null, !spent);
|
||||
@ -901,7 +968,7 @@ TXDB.prototype.isDoubleSpend = function isDoubleSpend(tx, callback) {
|
||||
|
||||
TXDB.prototype.isSpent = function isSpent(hash, index, callback) {
|
||||
var key = 's/' + hash + '/' + index;
|
||||
return this.db.fetch(key, function(data) {
|
||||
this.db.fetch(key, function(data) {
|
||||
return bcoin.outpoint.fromRaw(data);
|
||||
}, callback);
|
||||
};
|
||||
@ -918,9 +985,8 @@ TXDB.prototype.isSpent = function isSpent(hash, index, callback) {
|
||||
|
||||
TXDB.prototype._confirm = function _confirm(tx, info, callback) {
|
||||
var self = this;
|
||||
var hash, batch, unlock, i, id;
|
||||
|
||||
hash = tx.hash('hex');
|
||||
var hash = tx.hash('hex');
|
||||
var batch, i, id;
|
||||
|
||||
this.getTX(hash, function(err, existing) {
|
||||
if (err)
|
||||
@ -982,8 +1048,10 @@ TXDB.prototype._confirm = function _confirm(tx, info, callback) {
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
self.emit('confirmed', 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) {
|
||||
var self = this;
|
||||
var unlock = this._lock(remove, [hash, callback], force);
|
||||
|
||||
if (hash.hash)
|
||||
hash = hash.hash('hex');
|
||||
if (!unlock)
|
||||
return;
|
||||
|
||||
this.getTX(hash, function(err, tx) {
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
this._removeRecursive(hash, function(err, result, info) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!tx)
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
return callback(null, !!result, info);
|
||||
});
|
||||
};
|
||||
|
||||
@ -1059,7 +1105,7 @@ TXDB.prototype._lazyRemove = function lazyRemove(tx, callback) {
|
||||
if (!info)
|
||||
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) {
|
||||
var self = this;
|
||||
var unlock, hash, batch, i, j, path, id;
|
||||
var key, paths, address, input, output, coin;
|
||||
|
||||
hash = tx.hash('hex');
|
||||
|
||||
batch = this.batch();
|
||||
var hash = tx.hash('hex');
|
||||
var batch = this.batch();
|
||||
var i, j, path, id, key, paths, address, input, output, coin;
|
||||
|
||||
batch.del('t/' + hash);
|
||||
|
||||
@ -1190,9 +1233,7 @@ TXDB.prototype.unconfirm = function unconfirm(hash, callback, force) {
|
||||
if (!tx)
|
||||
return callback(null, true);
|
||||
|
||||
assert(tx.hash('hex') === hash);
|
||||
|
||||
return self.getInfo(tx, function(err, info) {
|
||||
self.getInfo(tx, function(err, info) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -1201,7 +1242,7 @@ TXDB.prototype.unconfirm = function unconfirm(hash, callback, force) {
|
||||
|
||||
self.start();
|
||||
|
||||
return self._unconfirm(tx, info, function(err, res1, res2) {
|
||||
self._unconfirm(tx, info, function(err, res1, res2) {
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
@ -1225,11 +1266,10 @@ TXDB.prototype.unconfirm = function unconfirm(hash, callback, force) {
|
||||
|
||||
TXDB.prototype._unconfirm = function unconfirm(tx, info, callback, force) {
|
||||
var self = this;
|
||||
var batch, unlock, hash, height, i, id;
|
||||
|
||||
batch = this.batch();
|
||||
hash = tx.hash('hex');
|
||||
height = tx.height;
|
||||
var batch = this.batch();
|
||||
var hash = tx.hash('hex');
|
||||
var height = tx.height;
|
||||
var i, id;
|
||||
|
||||
if (height !== -1)
|
||||
return callback(null, false, info);
|
||||
@ -1453,7 +1493,7 @@ TXDB.prototype.getRange = function getLast(id, options, callback) {
|
||||
id = null;
|
||||
}
|
||||
|
||||
return this.getRangeHashes(id, options, function(err, hashes) {
|
||||
this.getRangeHashes(id, options, function(err, hashes) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -1492,7 +1532,7 @@ TXDB.prototype.getLast = function getLast(id, limit, callback) {
|
||||
id = null;
|
||||
}
|
||||
|
||||
return this.getRange(id, {
|
||||
this.getRange(id, {
|
||||
start: 0,
|
||||
end: 0xffffffff,
|
||||
reverse: true,
|
||||
@ -1515,7 +1555,7 @@ TXDB.prototype.getHistory = function getHistory(id, callback) {
|
||||
id = null;
|
||||
}
|
||||
|
||||
return this.getHistoryHashes(id, function(err, hashes) {
|
||||
this.getHistoryHashes(id, function(err, hashes) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -1554,7 +1594,7 @@ TXDB.prototype.getLastTime = function getLastTime(id, callback) {
|
||||
id = null;
|
||||
}
|
||||
|
||||
return this.getHistory(id, function(err, txs) {
|
||||
this.getHistory(id, function(err, txs) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -1590,7 +1630,7 @@ TXDB.prototype.getUnconfirmed = function getUnconfirmed(id, callback) {
|
||||
id = null;
|
||||
}
|
||||
|
||||
return this.getUnconfirmedHashes(id, function(err, hashes) {
|
||||
this.getUnconfirmedHashes(id, function(err, hashes) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -1630,7 +1670,7 @@ TXDB.prototype.getCoins = function getCoins(id, callback) {
|
||||
id = null;
|
||||
}
|
||||
|
||||
return this.getCoinHashes(id, function(err, hashes) {
|
||||
this.getCoinHashes(id, function(err, hashes) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -1707,10 +1747,12 @@ TXDB.prototype.fillCoins = function fillCoins(tx, callback) {
|
||||
}
|
||||
|
||||
utils.forEachSerial(tx.inputs, function(input, next) {
|
||||
var prevout = input.prevout;
|
||||
|
||||
if (input.coin)
|
||||
return next();
|
||||
|
||||
self.getCoin(input.prevout.hash, input.prevout.index, function(err, coin) {
|
||||
self.getCoin(prevout.hash, prevout.index, function(err, coin) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -1771,7 +1813,7 @@ TXDB.prototype.toDetails = function toDetails(id, tx, callback) {
|
||||
|
||||
if (Array.isArray(tx)) {
|
||||
out = [];
|
||||
utils.forEachSerial(tx, function(tx, next) {
|
||||
return utils.forEachSerial(tx, function(tx, next) {
|
||||
self.toDetails(tx, function(err, details) {
|
||||
if (err)
|
||||
return next(err);
|
||||
@ -1812,7 +1854,7 @@ TXDB.prototype.toDetails = function toDetails(id, tx, 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))
|
||||
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;
|
||||
}
|
||||
|
||||
return this.getCoinHashes(id, function(err, hashes) {
|
||||
this.getCoinHashes(id, function(err, hashes) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -1965,23 +2007,37 @@ TXDB.prototype.zap = function zap(id, age, callback, force) {
|
||||
if (!utils.isNumber(age))
|
||||
return callback(new Error('Age must be a number.'));
|
||||
|
||||
return this.getRange(id, {
|
||||
this.getRange(id, {
|
||||
start: 0,
|
||||
end: bcoin.now() - age
|
||||
}, function(err, txs) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.fillHistory(txs, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
utils.forEachSerial(txs, function(tx, next) {
|
||||
if (tx.ts !== 0)
|
||||
return next();
|
||||
self.remove(tx.hash('hex'), next, true);
|
||||
}, callback);
|
||||
});
|
||||
};
|
||||
|
||||
utils.forEachSerial(txs, function(tx, next) {
|
||||
if (tx.ts !== 0)
|
||||
return next();
|
||||
self.remove(tx.hash('hex'), next, true);
|
||||
}, callback);
|
||||
});
|
||||
/**
|
||||
* Abandon transaction.
|
||||
* @param {Hash} hash
|
||||
* @param {Function} 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