txdb: less confusing tx details.
This commit is contained in:
parent
9ed439b60c
commit
11b2f1a7bc
@ -1259,32 +1259,27 @@ HTTPServer.prototype._initIO = function _initIO() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.walletdb.on('tx', function(id, tx, info) {
|
this.walletdb.on('tx', function(id, tx, details) {
|
||||||
var details = info.toJSON();
|
|
||||||
self.server.io.to(id).emit('wallet tx', details);
|
self.server.io.to(id).emit('wallet tx', details);
|
||||||
self.server.io.to('!all').emit('wallet tx', id, details);
|
self.server.io.to('!all').emit('wallet tx', id, details);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.walletdb.on('confirmed', function(id, tx, info) {
|
this.walletdb.on('confirmed', function(id, tx, details) {
|
||||||
var details = info.toJSON();
|
|
||||||
self.server.io.to(id).emit('wallet confirmed', details);
|
self.server.io.to(id).emit('wallet confirmed', details);
|
||||||
self.server.io.to('!all').emit('wallet confirmed', id, details);
|
self.server.io.to('!all').emit('wallet confirmed', id, details);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.walletdb.on('unconfirmed', function(id, tx, info) {
|
this.walletdb.on('unconfirmed', function(id, tx, details) {
|
||||||
var details = info.toJSON();
|
|
||||||
self.server.io.to(id).emit('wallet unconfirmed', details);
|
self.server.io.to(id).emit('wallet unconfirmed', details);
|
||||||
self.server.io.to('!all').emit('wallet unconfirmed', id, details);
|
self.server.io.to('!all').emit('wallet unconfirmed', id, details);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.walletdb.on('conflict', function(id, tx, info) {
|
this.walletdb.on('conflict', function(id, tx, details) {
|
||||||
var details = info.toJSON();
|
|
||||||
self.server.io.to(id).emit('wallet conflict', details);
|
self.server.io.to(id).emit('wallet conflict', details);
|
||||||
self.server.io.to('!all').emit('wallet conflict', id, details);
|
self.server.io.to('!all').emit('wallet conflict', id, details);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.walletdb.on('balance', function(id, balance) {
|
this.walletdb.on('balance', function(id, balance) {
|
||||||
var json = balance.toJSON();
|
|
||||||
self.server.io.to(id).emit('wallet balance', json);
|
self.server.io.to(id).emit('wallet balance', json);
|
||||||
self.server.io.to('!all').emit('wallet balance', id, json);
|
self.server.io.to('!all').emit('wallet balance', id, json);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -331,11 +331,11 @@ TXDB.prototype.commit = co(function* commit() {
|
|||||||
* @private
|
* @private
|
||||||
* @param {String} event
|
* @param {String} event
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {PathInfo} info
|
* @param {PathInfo} details
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.emit = function emit(event, data, info) {
|
TXDB.prototype.emit = function emit(event, data, details) {
|
||||||
this.events.push([event, data, info]);
|
this.events.push([event, data, details]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -436,8 +436,22 @@ TXDB.prototype.values = function values(options) {
|
|||||||
* @returns {Promise} - Returns {@link PathInfo}.
|
* @returns {Promise} - Returns {@link PathInfo}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.getPathInfo = function getPathInfo(tx) {
|
TXDB.prototype.getPath = function getPath(output) {
|
||||||
return this.wallet.getPathInfo(tx);
|
if (!output)
|
||||||
|
return Promise.resolve();
|
||||||
|
return this.wallet.getPath(output.getAddress());
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map a transactions' addresses to wallet IDs.
|
||||||
|
* @param {TX} tx
|
||||||
|
* @returns {Promise} - Returns {@link PathInfo}.
|
||||||
|
*/
|
||||||
|
|
||||||
|
TXDB.prototype.hasPath = function hasPath(output) {
|
||||||
|
if (!output)
|
||||||
|
return Promise.resolve();
|
||||||
|
return this.wallet.hasPath(output.getAddress());
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -478,7 +492,7 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx) {
|
|||||||
var hasOrphans = false;
|
var hasOrphans = false;
|
||||||
var orphans = [];
|
var orphans = [];
|
||||||
var i, input, prevout;
|
var i, input, prevout;
|
||||||
var path, key, coin, spent;
|
var key, coin, spent;
|
||||||
|
|
||||||
if (tx.isCoinbase())
|
if (tx.isCoinbase())
|
||||||
return true;
|
return true;
|
||||||
@ -519,12 +533,8 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = yield this.wallet.hasPath(input.getAddress());
|
if (yield this.hasPath(input))
|
||||||
|
orphans[i] = true;
|
||||||
if (!path)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
orphans[i] = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < tx.inputs.length; i++) {
|
for (i = 0; i < tx.inputs.length; i++) {
|
||||||
@ -627,11 +637,10 @@ TXDB.prototype.resolveOutputs = co(function* resolveOutputs(tx, resolved) {
|
|||||||
* double spenders, and verify inputs.
|
* double spenders, and verify inputs.
|
||||||
* @private
|
* @private
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
* @param {PathInfo} info
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.removeConflicts = co(function* removeConflicts(tx, info) {
|
TXDB.prototype.removeConflicts = co(function* removeConflicts(tx) {
|
||||||
var hash = tx.hash('hex');
|
var hash = tx.hash('hex');
|
||||||
var i, input, prevout, spent;
|
var i, input, prevout, spent;
|
||||||
|
|
||||||
@ -660,18 +669,16 @@ TXDB.prototype.removeConflicts = co(function* removeConflicts(tx, info) {
|
|||||||
/**
|
/**
|
||||||
* Add transaction, runs `confirm()` and `verify()`.
|
* Add transaction, runs `confirm()` and `verify()`.
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
* @param {PathInfo} info
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.add = co(function* add(tx) {
|
TXDB.prototype.add = co(function* add(tx) {
|
||||||
var info = yield this.getPathInfo(tx);
|
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
this.start();
|
this.start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = yield this._add(tx, info);
|
result = yield this._add(tx);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.drop();
|
this.drop();
|
||||||
throw e;
|
throw e;
|
||||||
@ -686,43 +693,53 @@ TXDB.prototype.add = co(function* add(tx) {
|
|||||||
* Add transaction without a lock.
|
* Add transaction without a lock.
|
||||||
* @private
|
* @private
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
* @param {PathInfo} info
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype._add = co(function* add(tx, info) {
|
TXDB.prototype._add = co(function* add(tx) {
|
||||||
var hash = tx.hash('hex');
|
var hash = tx.hash('hex');
|
||||||
var path, account;
|
var path, account, existing;
|
||||||
var i, result, input, output, coin;
|
var i, input, output, coin;
|
||||||
var prevout, key, spender, raw;
|
var prevout, key, spender, raw, details;
|
||||||
|
|
||||||
assert(!tx.mutable, 'Cannot add mutable TX to wallet.');
|
assert(!tx.mutable, 'Cannot add mutable TX to wallet.');
|
||||||
|
|
||||||
|
existing = yield this.getTX(hash);
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
// Existing tx is already confirmed. Ignore.
|
||||||
|
if (existing.height !== -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// The incoming tx won't confirm the
|
||||||
|
// existing one anyway. Ignore.
|
||||||
|
if (tx.height === -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Attempt to confirm tx before adding it.
|
||||||
|
return yield this.confirm(tx, existing);
|
||||||
|
}
|
||||||
|
|
||||||
if (tx.height === -1) {
|
if (tx.height === -1) {
|
||||||
// We ignore double spends from the mempool.
|
// We ignore double spends from the mempool.
|
||||||
if (yield this.isDoubleSpend(tx))
|
if (yield this.isDoubleSpend(tx))
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
// We ignore any unconfirmed txs
|
// We ignore any unconfirmed txs
|
||||||
// that are replace-by-fee.
|
// that are replace-by-fee.
|
||||||
if (yield this.isRBF(tx)) {
|
if (yield this.isRBF(tx)) {
|
||||||
this.put(layout.r(hash), DUMMY);
|
this.put(layout.r(hash), DUMMY);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This potentially removes double-spenders.
|
// This potentially removes double-spenders.
|
||||||
yield this.removeConflicts(tx, info);
|
yield this.removeConflicts(tx);
|
||||||
|
|
||||||
// Delete the replace-by-fee record.
|
// Delete the replace-by-fee record.
|
||||||
this.del(layout.r(hash));
|
this.del(layout.r(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to confirm tx before adding it.
|
details = new Details(this, tx);
|
||||||
result = yield this.confirm(tx, info);
|
|
||||||
|
|
||||||
// Ignore if we already have this tx.
|
|
||||||
if (result)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
this.put(layout.t(hash), tx.toExtended());
|
this.put(layout.t(hash), tx.toExtended());
|
||||||
|
|
||||||
@ -733,19 +750,6 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
|||||||
|
|
||||||
this.put(layout.m(tx.ps, hash), DUMMY);
|
this.put(layout.m(tx.ps, hash), DUMMY);
|
||||||
|
|
||||||
for (i = 0; i < info.accounts.length; i++) {
|
|
||||||
account = info.accounts[i];
|
|
||||||
|
|
||||||
this.put(layout.T(account, hash), DUMMY);
|
|
||||||
|
|
||||||
if (tx.height === -1)
|
|
||||||
this.put(layout.P(account, hash), DUMMY);
|
|
||||||
else
|
|
||||||
this.put(layout.H(account, tx.height, hash), DUMMY);
|
|
||||||
|
|
||||||
this.put(layout.M(account, tx.ps, hash), DUMMY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume unspent money or add orphans
|
// Consume unspent money or add orphans
|
||||||
if (!tx.isCoinbase()) {
|
if (!tx.isCoinbase()) {
|
||||||
for (i = 0; i < tx.inputs.length; i++) {
|
for (i = 0; i < tx.inputs.length; i++) {
|
||||||
@ -757,9 +761,11 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
|||||||
if (!coin)
|
if (!coin)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
path = info.getPath(coin);
|
path = yield this.getPath(coin);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
|
details.addInput(i, path, coin);
|
||||||
|
|
||||||
key = prevout.hash + prevout.index;
|
key = prevout.hash + prevout.index;
|
||||||
|
|
||||||
spender = Outpoint.fromTX(tx, i).toRaw();
|
spender = Outpoint.fromTX(tx, i).toRaw();
|
||||||
@ -786,7 +792,7 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
|||||||
// Add unspent outputs or resolve orphans.
|
// Add unspent outputs or resolve orphans.
|
||||||
for (i = 0; i < tx.outputs.length; i++) {
|
for (i = 0; i < tx.outputs.length; i++) {
|
||||||
output = tx.outputs[i];
|
output = tx.outputs[i];
|
||||||
path = info.getPath(output);
|
path = yield this.getPath(output);
|
||||||
key = hash + i;
|
key = hash + i;
|
||||||
|
|
||||||
// Do not add unspents for
|
// Do not add unspents for
|
||||||
@ -794,6 +800,8 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
|||||||
if (!path)
|
if (!path)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
details.addOutput(i, path);
|
||||||
|
|
||||||
coin = Coin.fromTX(tx, i);
|
coin = Coin.fromTX(tx, i);
|
||||||
raw = coin.toRaw();
|
raw = coin.toRaw();
|
||||||
|
|
||||||
@ -809,20 +817,33 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
|||||||
this.coinCache.set(key, raw);
|
this.coinCache.set(key, raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < details.accounts.length; i++) {
|
||||||
|
account = details.accounts[i];
|
||||||
|
|
||||||
|
this.put(layout.T(account, hash), DUMMY);
|
||||||
|
|
||||||
|
if (tx.height === -1)
|
||||||
|
this.put(layout.P(account, hash), DUMMY);
|
||||||
|
else
|
||||||
|
this.put(layout.H(account, tx.height, hash), DUMMY);
|
||||||
|
|
||||||
|
this.put(layout.M(account, tx.ps, hash), DUMMY);
|
||||||
|
}
|
||||||
|
|
||||||
this.pending.tx++;
|
this.pending.tx++;
|
||||||
this.put(layout.R, this.pending.commit());
|
this.put(layout.R, this.pending.commit());
|
||||||
|
|
||||||
// Clear any locked coins to free up memory.
|
// Clear any locked coins to free up memory.
|
||||||
this.unlockTX(tx);
|
this.unlockTX(tx);
|
||||||
|
|
||||||
this.emit('tx', tx, info);
|
this.emit('tx', tx, details);
|
||||||
|
|
||||||
if (tx.height !== -1)
|
if (tx.height !== -1)
|
||||||
this.emit('confirmed', tx, info);
|
this.emit('confirmed', tx, details);
|
||||||
|
|
||||||
this.emit('balance', this.pending.toBalance(), info);
|
this.emit('balance', this.pending.toBalance(), details);
|
||||||
|
|
||||||
return true;
|
return details;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -839,7 +860,7 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
|||||||
|
|
||||||
TXDB.prototype.removeConflict = co(function* removeConflict(hash, ref) {
|
TXDB.prototype.removeConflict = co(function* removeConflict(hash, ref) {
|
||||||
var tx = yield this.getTX(hash);
|
var tx = yield this.getTX(hash);
|
||||||
var info;
|
var details;
|
||||||
|
|
||||||
assert(tx);
|
assert(tx);
|
||||||
|
|
||||||
@ -847,14 +868,16 @@ TXDB.prototype.removeConflict = co(function* removeConflict(hash, ref) {
|
|||||||
|
|
||||||
this.drop();
|
this.drop();
|
||||||
|
|
||||||
info = yield this.removeRecursive(tx);
|
details = yield this.removeRecursive(tx);
|
||||||
|
|
||||||
this.start();
|
this.start();
|
||||||
|
|
||||||
this.logger.warning('Removed conflict: %s.', tx.rhash);
|
this.logger.warning('Removed conflict: %s.', tx.rhash);
|
||||||
|
|
||||||
// Emit the _removed_ transaction.
|
// Emit the _removed_ transaction.
|
||||||
this.emit('conflict', tx, info);
|
this.emit('conflict', tx, details);
|
||||||
|
|
||||||
|
return details;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -867,7 +890,7 @@ TXDB.prototype.removeConflict = co(function* removeConflict(hash, ref) {
|
|||||||
|
|
||||||
TXDB.prototype.removeRecursive = co(function* removeRecursive(tx) {
|
TXDB.prototype.removeRecursive = co(function* removeRecursive(tx) {
|
||||||
var hash = tx.hash('hex');
|
var hash = tx.hash('hex');
|
||||||
var i, spent, stx, info;
|
var i, spent, stx, details;
|
||||||
|
|
||||||
for (i = 0; i < tx.outputs.length; i++) {
|
for (i = 0; i < tx.outputs.length; i++) {
|
||||||
spent = yield this.getSpent(hash, i);
|
spent = yield this.getSpent(hash, i);
|
||||||
@ -886,13 +909,13 @@ TXDB.prototype.removeRecursive = co(function* removeRecursive(tx) {
|
|||||||
this.start();
|
this.start();
|
||||||
|
|
||||||
// Remove the spender.
|
// Remove the spender.
|
||||||
info = yield this.lazyRemove(tx);
|
details = yield this.lazyRemove(tx);
|
||||||
|
|
||||||
assert(info);
|
assert(details);
|
||||||
|
|
||||||
yield this.commit();
|
yield this.commit();
|
||||||
|
|
||||||
return info;
|
return details;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1012,32 +1035,16 @@ TXDB.prototype.isSpending = co(function* isSpending(hash, index) {
|
|||||||
* Attempt to confirm a transaction.
|
* Attempt to confirm a transaction.
|
||||||
* @private
|
* @private
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
* @param {AddressMap} info
|
|
||||||
* @returns {Promise} - Returns Boolean. `false` if
|
* @returns {Promise} - Returns Boolean. `false` if
|
||||||
* the transaction should be added to the database, `true` if the
|
* the transaction should be added to the database, `true` if the
|
||||||
* transaction was confirmed, or should be ignored.
|
* transaction was confirmed, or should be ignored.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
TXDB.prototype.confirm = co(function* confirm(tx, existing) {
|
||||||
var hash = tx.hash('hex');
|
var hash = tx.hash('hex');
|
||||||
var i, account, existing, output, coin;
|
var i, account, output, coin;
|
||||||
var input, prevout, path, spender, coins;
|
var input, prevout, path, spender, coins;
|
||||||
var key, raw;
|
var key, raw, details;
|
||||||
|
|
||||||
existing = yield this.getTX(hash);
|
|
||||||
|
|
||||||
// Haven't seen this tx before, add it.
|
|
||||||
if (!existing)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Existing tx is already confirmed. Ignore.
|
|
||||||
if (existing.height !== -1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// The incoming tx won't confirm the
|
|
||||||
// existing one anyway. Ignore.
|
|
||||||
if (tx.height === -1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Inject block properties.
|
// Inject block properties.
|
||||||
existing.ts = tx.ts;
|
existing.ts = tx.ts;
|
||||||
@ -1046,17 +1053,13 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
|||||||
existing.block = tx.block;
|
existing.block = tx.block;
|
||||||
tx = existing;
|
tx = existing;
|
||||||
|
|
||||||
|
details = new Details(this, tx);
|
||||||
|
|
||||||
this.put(layout.t(hash), tx.toExtended());
|
this.put(layout.t(hash), tx.toExtended());
|
||||||
|
|
||||||
this.del(layout.p(hash));
|
this.del(layout.p(hash));
|
||||||
this.put(layout.h(tx.height, hash), DUMMY);
|
this.put(layout.h(tx.height, hash), DUMMY);
|
||||||
|
|
||||||
for (i = 0; i < info.accounts.length; i++) {
|
|
||||||
account = info.accounts[i];
|
|
||||||
this.del(layout.P(account, hash));
|
|
||||||
this.put(layout.H(account, tx.height, hash), DUMMY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume unspent money or add orphans
|
// Consume unspent money or add orphans
|
||||||
if (!tx.isCoinbase()) {
|
if (!tx.isCoinbase()) {
|
||||||
coins = yield this.fillHistory(tx);
|
coins = yield this.fillHistory(tx);
|
||||||
@ -1082,10 +1085,14 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
|||||||
|
|
||||||
assert(coin.height !== -1);
|
assert(coin.height !== -1);
|
||||||
|
|
||||||
|
input.coin = coin;
|
||||||
|
|
||||||
// Only bother if this input is ours.
|
// Only bother if this input is ours.
|
||||||
path = info.getPath(coin);
|
path = yield this.getPath(coin);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
|
details.addInput(i, path, coin);
|
||||||
|
|
||||||
key = prevout.hash + prevout.index;
|
key = prevout.hash + prevout.index;
|
||||||
|
|
||||||
this.del(layout.S(prevout.hash, prevout.index));
|
this.del(layout.S(prevout.hash, prevout.index));
|
||||||
@ -1102,12 +1109,15 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
|||||||
|
|
||||||
for (i = 0; i < tx.outputs.length; i++) {
|
for (i = 0; i < tx.outputs.length; i++) {
|
||||||
output = tx.outputs[i];
|
output = tx.outputs[i];
|
||||||
|
path = yield this.getPath(output);
|
||||||
key = hash + i;
|
key = hash + i;
|
||||||
|
|
||||||
// Only update coins if this output is ours.
|
// Only update coins if this output is ours.
|
||||||
if (!info.hasPath(output))
|
if (!path)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
details.addOutput(i, path);
|
||||||
|
|
||||||
// Update spent coin.
|
// Update spent coin.
|
||||||
yield this.updateSpentCoin(tx, i);
|
yield this.updateSpentCoin(tx, i);
|
||||||
|
|
||||||
@ -1127,16 +1137,22 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
|||||||
this.coinCache.set(key, raw);
|
this.coinCache.set(key, raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < details.accounts.length; i++) {
|
||||||
|
account = details.accounts[i];
|
||||||
|
this.del(layout.P(account, hash));
|
||||||
|
this.put(layout.H(account, tx.height, hash), DUMMY);
|
||||||
|
}
|
||||||
|
|
||||||
this.put(layout.R, this.pending.commit());
|
this.put(layout.R, this.pending.commit());
|
||||||
|
|
||||||
// Clear any locked coins to free up memory.
|
// Clear any locked coins to free up memory.
|
||||||
this.unlockTX(tx);
|
this.unlockTX(tx);
|
||||||
|
|
||||||
this.emit('tx', tx, info);
|
this.emit('tx', tx, details);
|
||||||
this.emit('confirmed', tx, info);
|
this.emit('confirmed', tx, details);
|
||||||
this.emit('balance', this.pending.toBalance(), info);
|
this.emit('balance', this.pending.toBalance(), details);
|
||||||
|
|
||||||
return true;
|
return details;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1146,12 +1162,12 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.remove = co(function* remove(hash) {
|
TXDB.prototype.remove = co(function* remove(hash) {
|
||||||
var result;
|
var details;
|
||||||
|
|
||||||
this.start();
|
this.start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = yield this._remove(hash);
|
details = yield this._remove(hash);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.drop();
|
this.drop();
|
||||||
throw e;
|
throw e;
|
||||||
@ -1159,7 +1175,7 @@ TXDB.prototype.remove = co(function* remove(hash) {
|
|||||||
|
|
||||||
yield this.commit();
|
yield this.commit();
|
||||||
|
|
||||||
return result;
|
return details;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1171,21 +1187,21 @@ TXDB.prototype.remove = co(function* remove(hash) {
|
|||||||
|
|
||||||
TXDB.prototype._remove = co(function* remove(hash) {
|
TXDB.prototype._remove = co(function* remove(hash) {
|
||||||
var tx = yield this.getTX(hash);
|
var tx = yield this.getTX(hash);
|
||||||
var info;
|
var details;
|
||||||
|
|
||||||
if (!tx)
|
if (!tx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.drop();
|
this.drop();
|
||||||
|
|
||||||
info = yield this.removeRecursive(tx);
|
details = yield this.removeRecursive(tx);
|
||||||
|
|
||||||
this.start();
|
this.start();
|
||||||
|
|
||||||
if (!info)
|
if (!details)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
return info;
|
return details;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1197,25 +1213,22 @@ TXDB.prototype._remove = co(function* remove(hash) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.lazyRemove = co(function* lazyRemove(tx) {
|
TXDB.prototype.lazyRemove = co(function* lazyRemove(tx) {
|
||||||
var info = yield this.getPathInfo(tx);
|
return yield this.__remove(tx);
|
||||||
if (!info)
|
|
||||||
return;
|
|
||||||
|
|
||||||
return yield this.__remove(tx, info);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a transaction from the database. Disconnect inputs.
|
* Remove a transaction from the database. Disconnect inputs.
|
||||||
* @private
|
* @private
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
* @param {AddressMap} info
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.__remove = co(function* remove(tx, info) {
|
TXDB.prototype.__remove = co(function* remove(tx) {
|
||||||
var hash = tx.hash('hex');
|
var hash = tx.hash('hex');
|
||||||
var i, path, account, key, prevout;
|
var i, path, account, key, prevout;
|
||||||
var input, output, coin, coins, raw;
|
var input, output, coin, coins, raw, details;
|
||||||
|
|
||||||
|
details = new Details(this, tx);
|
||||||
|
|
||||||
this.del(layout.t(hash));
|
this.del(layout.t(hash));
|
||||||
|
|
||||||
@ -1226,19 +1239,6 @@ TXDB.prototype.__remove = co(function* remove(tx, info) {
|
|||||||
|
|
||||||
this.del(layout.m(tx.ps, hash));
|
this.del(layout.m(tx.ps, hash));
|
||||||
|
|
||||||
for (i = 0; i < info.accounts.length; i++) {
|
|
||||||
account = info.accounts[i];
|
|
||||||
|
|
||||||
this.del(layout.T(account, hash));
|
|
||||||
|
|
||||||
if (tx.height === -1)
|
|
||||||
this.del(layout.P(account, hash));
|
|
||||||
else
|
|
||||||
this.del(layout.H(account, tx.height, hash));
|
|
||||||
|
|
||||||
this.del(layout.M(account, tx.ps, hash));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tx.isCoinbase()) {
|
if (!tx.isCoinbase()) {
|
||||||
coins = yield this.fillHistory(tx);
|
coins = yield this.fillHistory(tx);
|
||||||
|
|
||||||
@ -1251,9 +1251,11 @@ TXDB.prototype.__remove = co(function* remove(tx, info) {
|
|||||||
if (!coin)
|
if (!coin)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
path = info.getPath(coin);
|
path = yield this.getPath(coin);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
|
details.addInput(i, path, coin);
|
||||||
|
|
||||||
this.pending.unconfirmed += coin.value;
|
this.pending.unconfirmed += coin.value;
|
||||||
|
|
||||||
this.del(layout.s(prevout.hash, prevout.index));
|
this.del(layout.s(prevout.hash, prevout.index));
|
||||||
@ -1277,11 +1279,13 @@ TXDB.prototype.__remove = co(function* remove(tx, info) {
|
|||||||
for (i = 0; i < tx.outputs.length; i++) {
|
for (i = 0; i < tx.outputs.length; i++) {
|
||||||
output = tx.outputs[i];
|
output = tx.outputs[i];
|
||||||
key = hash + i;
|
key = hash + i;
|
||||||
path = info.getPath(output);
|
path = yield this.getPath(output);
|
||||||
|
|
||||||
if (!path)
|
if (!path)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
details.addOutput(i, path);
|
||||||
|
|
||||||
this.pending.coin--;
|
this.pending.coin--;
|
||||||
this.pending.unconfirmed -= output.value;
|
this.pending.unconfirmed -= output.value;
|
||||||
|
|
||||||
@ -1294,13 +1298,26 @@ TXDB.prototype.__remove = co(function* remove(tx, info) {
|
|||||||
this.coinCache.remove(key);
|
this.coinCache.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < details.accounts.length; i++) {
|
||||||
|
account = details.accounts[i];
|
||||||
|
|
||||||
|
this.del(layout.T(account, hash));
|
||||||
|
|
||||||
|
if (tx.height === -1)
|
||||||
|
this.del(layout.P(account, hash));
|
||||||
|
else
|
||||||
|
this.del(layout.H(account, tx.height, hash));
|
||||||
|
|
||||||
|
this.del(layout.M(account, tx.ps, hash));
|
||||||
|
}
|
||||||
|
|
||||||
this.pending.tx--;
|
this.pending.tx--;
|
||||||
this.put(layout.R, this.pending.commit());
|
this.put(layout.R, this.pending.commit());
|
||||||
|
|
||||||
this.emit('remove tx', tx, info);
|
this.emit('remove tx', tx, details);
|
||||||
this.emit('balance', this.pending.toBalance(), info);
|
this.emit('balance', this.pending.toBalance(), details);
|
||||||
|
|
||||||
return info;
|
return details;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1310,12 +1327,12 @@ TXDB.prototype.__remove = co(function* remove(tx, info) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.unconfirm = co(function* unconfirm(hash) {
|
TXDB.prototype.unconfirm = co(function* unconfirm(hash) {
|
||||||
var result;
|
var details;
|
||||||
|
|
||||||
this.start();
|
this.start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = yield this._unconfirm(hash);
|
details = yield this._unconfirm(hash);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.drop();
|
this.drop();
|
||||||
throw e;
|
throw e;
|
||||||
@ -1323,7 +1340,7 @@ TXDB.prototype.unconfirm = co(function* unconfirm(hash) {
|
|||||||
|
|
||||||
yield this.commit();
|
yield this.commit();
|
||||||
|
|
||||||
return result;
|
return details;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1335,29 +1352,23 @@ TXDB.prototype.unconfirm = co(function* unconfirm(hash) {
|
|||||||
|
|
||||||
TXDB.prototype._unconfirm = co(function* unconfirm(hash) {
|
TXDB.prototype._unconfirm = co(function* unconfirm(hash) {
|
||||||
var tx = yield this.getTX(hash);
|
var tx = yield this.getTX(hash);
|
||||||
var info, result;
|
var details;
|
||||||
|
|
||||||
if (!tx)
|
if (!tx)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
info = yield this.getPathInfo(tx);
|
details = yield this.__unconfirm(tx);
|
||||||
|
|
||||||
if (!info)
|
return details;
|
||||||
return false;
|
|
||||||
|
|
||||||
result = yield this.__unconfirm(tx, info);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unconfirm a transaction. This is usually necessary after a reorg.
|
* Unconfirm a transaction. This is usually necessary after a reorg.
|
||||||
* @param {Hash} hash
|
* @param {Hash} hash
|
||||||
* @param {AddressMap} info
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.__unconfirm = co(function* unconfirm(tx, info) {
|
TXDB.prototype.__unconfirm = co(function* unconfirm(tx) {
|
||||||
var hash = tx.hash('hex');
|
var hash = tx.hash('hex');
|
||||||
var height = tx.height;
|
var height = tx.height;
|
||||||
var i, account, output, key, coin, coins;
|
var i, account, output, key, coin, coins;
|
||||||
@ -1368,17 +1379,13 @@ TXDB.prototype.__unconfirm = co(function* unconfirm(tx, info) {
|
|||||||
|
|
||||||
tx.unsetBlock();
|
tx.unsetBlock();
|
||||||
|
|
||||||
|
details = new Details(this, tx);
|
||||||
|
|
||||||
this.put(layout.t(hash), tx.toExtended());
|
this.put(layout.t(hash), tx.toExtended());
|
||||||
|
|
||||||
this.put(layout.p(hash), DUMMY);
|
this.put(layout.p(hash), DUMMY);
|
||||||
this.del(layout.h(height, hash));
|
this.del(layout.h(height, hash));
|
||||||
|
|
||||||
for (i = 0; i < info.accounts.length; i++) {
|
|
||||||
account = info.accounts[i];
|
|
||||||
this.put(layout.P(account, hash), DUMMY);
|
|
||||||
this.del(layout.H(account, height, hash));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume unspent money or add orphans
|
// Consume unspent money or add orphans
|
||||||
if (!tx.isCoinbase()) {
|
if (!tx.isCoinbase()) {
|
||||||
coins = yield this.fillHistory(tx);
|
coins = yield this.fillHistory(tx);
|
||||||
@ -1396,9 +1403,11 @@ TXDB.prototype.__unconfirm = co(function* unconfirm(tx, info) {
|
|||||||
|
|
||||||
raw = coin.toRaw();
|
raw = coin.toRaw();
|
||||||
|
|
||||||
path = info.getPath(coin);
|
path = yield this.getPath(coin);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
|
details.addInput(i, path, coin);
|
||||||
|
|
||||||
key = prevout.hash + prevout.index;
|
key = prevout.hash + prevout.index;
|
||||||
|
|
||||||
spender = Outpoint.fromTX(tx, i).toRaw();
|
spender = Outpoint.fromTX(tx, i).toRaw();
|
||||||
@ -1417,6 +1426,7 @@ TXDB.prototype.__unconfirm = co(function* unconfirm(tx, info) {
|
|||||||
|
|
||||||
for (i = 0; i < tx.outputs.length; i++) {
|
for (i = 0; i < tx.outputs.length; i++) {
|
||||||
output = tx.outputs[i];
|
output = tx.outputs[i];
|
||||||
|
path = yield this.getPath(output);
|
||||||
key = hash + i;
|
key = hash + i;
|
||||||
|
|
||||||
// Update spent coin.
|
// Update spent coin.
|
||||||
@ -1427,6 +1437,8 @@ TXDB.prototype.__unconfirm = co(function* unconfirm(tx, info) {
|
|||||||
if (!coin)
|
if (!coin)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
details.addOutput(i, path);
|
||||||
|
|
||||||
coin.height = -1;
|
coin.height = -1;
|
||||||
raw = coin.toRaw();
|
raw = coin.toRaw();
|
||||||
|
|
||||||
@ -1438,12 +1450,18 @@ TXDB.prototype.__unconfirm = co(function* unconfirm(tx, info) {
|
|||||||
this.coinCache.set(key, raw);
|
this.coinCache.set(key, raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < details.accounts.length; i++) {
|
||||||
|
account = details.accounts[i];
|
||||||
|
this.put(layout.P(account, hash), DUMMY);
|
||||||
|
this.del(layout.H(account, height, hash));
|
||||||
|
}
|
||||||
|
|
||||||
this.put(layout.R, this.pending.commit());
|
this.put(layout.R, this.pending.commit());
|
||||||
|
|
||||||
this.emit('unconfirmed', tx, info);
|
this.emit('unconfirmed', tx, details);
|
||||||
this.emit('balance', this.pending.toBalance(), info);
|
this.emit('balance', this.pending.toBalance(), details);
|
||||||
|
|
||||||
return info;
|
return details;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2105,7 +2123,8 @@ TXDB.prototype.getDetails = co(function* getDetails(hash) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.toDetails = co(function* toDetails(tx) {
|
TXDB.prototype.toDetails = co(function* toDetails(tx) {
|
||||||
var i, out, txs, details, info;
|
var i, out, txs, details;
|
||||||
|
var coins, coin, path, input, output;
|
||||||
|
|
||||||
if (Array.isArray(tx)) {
|
if (Array.isArray(tx)) {
|
||||||
out = [];
|
out = [];
|
||||||
@ -2124,14 +2143,23 @@ TXDB.prototype.toDetails = co(function* toDetails(tx) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield this.fillHistory(tx);
|
details = new Details(this, tx);
|
||||||
|
|
||||||
info = yield this.getPathInfo(tx);
|
coins = yield this.fillHistory(tx);
|
||||||
|
|
||||||
if (!info)
|
for (i = 0; i < tx.inputs.length; i++) {
|
||||||
throw new Error('Info not found.');
|
coin = coins[i];
|
||||||
|
path = yield this.getPath(coin);
|
||||||
|
details.addInput(i, path, coin);
|
||||||
|
}
|
||||||
|
|
||||||
return info.toDetails();
|
for (i = 0; i < tx.outputs.length; i++) {
|
||||||
|
output = tx.outputs[i];
|
||||||
|
path = yield this.getPath(output);
|
||||||
|
details.addOutput(i, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return details;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2483,6 +2511,147 @@ function Orphan(tx, i) {
|
|||||||
this.index = i;
|
this.index = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cmp(a, b) {
|
||||||
|
return a - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction Details
|
||||||
|
* @constructor
|
||||||
|
* @param {PathInfo} info
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Details(txdb, tx) {
|
||||||
|
if (!(this instanceof Details))
|
||||||
|
return new Details(txdb, tx);
|
||||||
|
|
||||||
|
this.db = txdb.walletdb;
|
||||||
|
this.network = this.db.network;
|
||||||
|
this.wid = txdb.wallet.wid;
|
||||||
|
this.id = txdb.wallet.id;
|
||||||
|
this.hash = tx.hash('hex');
|
||||||
|
this.height = tx.height;
|
||||||
|
this.block = tx.block;
|
||||||
|
this.index = tx.index;
|
||||||
|
this.confirmations = tx.getConfirmations(this.db.height);
|
||||||
|
this.fee = tx.getFee();
|
||||||
|
this.ts = tx.ts;
|
||||||
|
this.ps = tx.ps;
|
||||||
|
this.tx = tx;
|
||||||
|
|
||||||
|
this.inputs = [];
|
||||||
|
this.outputs = [];
|
||||||
|
this.accounts = [];
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
Details.prototype.init = function init() {
|
||||||
|
var i, input, output, member;
|
||||||
|
|
||||||
|
for (i = 0; i < this.tx.inputs.length; i++) {
|
||||||
|
input = this.tx.inputs[i];
|
||||||
|
member = new DetailsMember();
|
||||||
|
member.address = input.getAddress();
|
||||||
|
this.inputs.push(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < this.tx.outputs.length; i++) {
|
||||||
|
output = this.tx.outputs[i];
|
||||||
|
member = new DetailsMember();
|
||||||
|
member.value = output.value;
|
||||||
|
member.address = output.getAddress();
|
||||||
|
this.outputs.push(member);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Details.prototype.addInput = function addInput(i, path, coin) {
|
||||||
|
var member = this.inputs[i];
|
||||||
|
|
||||||
|
if (coin) {
|
||||||
|
member.value = coin.value;
|
||||||
|
member.address = coin.getAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path) {
|
||||||
|
member.path = path;
|
||||||
|
utils.binaryInsert(this.accounts, path.account, cmp, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Details.prototype.addOutput = function addOutput(i, path) {
|
||||||
|
var member = this.outputs[i];
|
||||||
|
|
||||||
|
if (path) {
|
||||||
|
member.path = path;
|
||||||
|
utils.binaryInsert(this.accounts, path.account, cmp, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert details to a more json-friendly object.
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Details.prototype.toJSON = function toJSON() {
|
||||||
|
var self = this;
|
||||||
|
return {
|
||||||
|
wid: this.wid,
|
||||||
|
id: this.id,
|
||||||
|
hash: utils.revHex(this.hash),
|
||||||
|
height: this.height,
|
||||||
|
block: this.block ? utils.revHex(this.block) : null,
|
||||||
|
ts: this.ts,
|
||||||
|
ps: this.ps,
|
||||||
|
index: this.index,
|
||||||
|
fee: utils.btc(this.fee),
|
||||||
|
confirmations: this.confirmations,
|
||||||
|
inputs: this.inputs.map(function(input) {
|
||||||
|
return input.toJSON(self.network);
|
||||||
|
}),
|
||||||
|
outputs: this.outputs.map(function(output) {
|
||||||
|
return output.toJSON(self.network);
|
||||||
|
}),
|
||||||
|
tx: this.tx.toRaw().toString('hex')
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction Details Member
|
||||||
|
* @constructor
|
||||||
|
* @property {Number} value
|
||||||
|
* @property {Address} address
|
||||||
|
* @property {Path} path
|
||||||
|
*/
|
||||||
|
|
||||||
|
function DetailsMember() {
|
||||||
|
if (!(this instanceof DetailsMember))
|
||||||
|
return new DetailsMember();
|
||||||
|
|
||||||
|
this.value = 0;
|
||||||
|
this.address = null;
|
||||||
|
this.path = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the member to a more json-friendly object.
|
||||||
|
* @param {Network} network
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
|
||||||
|
DetailsMember.prototype.toJSON = function toJSON(network) {
|
||||||
|
return {
|
||||||
|
value: utils.btc(this.value),
|
||||||
|
address: this.address
|
||||||
|
? this.address.toBase58(network)
|
||||||
|
: null,
|
||||||
|
path: this.path
|
||||||
|
? this.path.toJSON()
|
||||||
|
: null
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1622,14 +1622,20 @@ Wallet.prototype.getOutputPaths = co(function* getOutputPaths(tx) {
|
|||||||
* (true if new addresses were allocated).
|
* (true if new addresses were allocated).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.syncOutputDepth = co(function* syncOutputDepth(info) {
|
Wallet.prototype.syncOutputDepth = co(function* syncOutputDepth(details) {
|
||||||
var derived = [];
|
var derived = [];
|
||||||
var accounts = {};
|
var accounts = {};
|
||||||
var i, j, path, paths, account;
|
var i, j, path, paths, account;
|
||||||
var receive, change, nested, ring;
|
var receive, change, nested, ring;
|
||||||
|
|
||||||
for (i = 0; i < info.paths.length; i++) {
|
if (!details)
|
||||||
path = info.paths[i];
|
return derived;
|
||||||
|
|
||||||
|
for (i = 0; i < details.outputs.length; i++) {
|
||||||
|
path = details.outputs[i].path;
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (path.index === -1)
|
if (path.index === -1)
|
||||||
continue;
|
continue;
|
||||||
@ -1842,14 +1848,13 @@ Wallet.prototype._add = co(function* add(tx) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype._insert = co(function* insert(tx) {
|
Wallet.prototype._insert = co(function* insert(tx) {
|
||||||
var info = yield this.getPathInfo(tx);
|
var details, derived;
|
||||||
var result, derived;
|
|
||||||
|
|
||||||
this.txdb.start();
|
this.txdb.start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = yield this.txdb._add(tx, info);
|
details = yield this.txdb._add(tx);
|
||||||
derived = yield this.syncOutputDepth(info);
|
derived = yield this.syncOutputDepth(details);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.txdb.drop();
|
this.txdb.drop();
|
||||||
throw e;
|
throw e;
|
||||||
@ -1862,7 +1867,7 @@ Wallet.prototype._insert = co(function* insert(tx) {
|
|||||||
this.emit('address', derived);
|
this.emit('address', derived);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return details;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1986,27 +1991,6 @@ Wallet.prototype.getLocked = function getLocked() {
|
|||||||
return this.txdb.getLocked();
|
return this.txdb.getLocked();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Map a transactions' addresses to wallet IDs.
|
|
||||||
* @param {TX} tx
|
|
||||||
* @returns {Promise} - Returns {@link PathInfo}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Wallet.prototype.getPathInfo = co(function* getPathInfo(tx) {
|
|
||||||
var hashes = tx.getHashes('hex');
|
|
||||||
var paths = [];
|
|
||||||
var i, hash, path;
|
|
||||||
|
|
||||||
for (i = 0; i < hashes.length; i++) {
|
|
||||||
hash = hashes[i];
|
|
||||||
path = yield this.getPath(hash);
|
|
||||||
if (path)
|
|
||||||
paths.push(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PathInfo(this, tx, paths);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all transactions in transaction history (accesses db).
|
* Get all transactions in transaction history (accesses db).
|
||||||
* @param {(String|Number)?} acct
|
* @param {(String|Number)?} acct
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user