wallet: share batches between wallet and txdb.
This commit is contained in:
parent
a800f8c44b
commit
08c7136ef4
@ -1,3 +1,11 @@
|
||||
/*!
|
||||
* pathinfo.js - pathinfo object for bcoin
|
||||
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
|
||||
/**
|
||||
@ -53,7 +61,7 @@ function PathInfo(wallet, tx, paths) {
|
||||
|
||||
PathInfo.prototype.fromTX = function fromTX(tx, paths) {
|
||||
var uniq = {};
|
||||
var i, j, hashes, hash, paths, path;
|
||||
var i, hashes, hash, path;
|
||||
|
||||
this.tx = tx;
|
||||
|
||||
@ -72,8 +80,9 @@ PathInfo.prototype.fromTX = function fromTX(tx, paths) {
|
||||
|
||||
for (i = 0; i < hashes.length; i++) {
|
||||
hash = hashes[i];
|
||||
paths = this.pathMap[hash];
|
||||
this.paths.push(path);
|
||||
path = this.pathMap[hash];
|
||||
if (path)
|
||||
this.paths.push(path);
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -151,8 +160,6 @@ PathInfo.prototype.toJSON = function toJSON() {
|
||||
return json;
|
||||
};
|
||||
|
||||
module.exports = PathInfo;
|
||||
|
||||
/**
|
||||
* Transaction Details
|
||||
* @constructor
|
||||
@ -203,7 +210,7 @@ Details.prototype.init = function init(map) {
|
||||
*/
|
||||
|
||||
Details.prototype._insert = function _insert(vector, input, target, map) {
|
||||
var i, j, io, address, hash, paths, path, member;
|
||||
var i, io, address, hash, path, member;
|
||||
|
||||
for (i = 0; i < vector.length; i++) {
|
||||
io = vector[i];
|
||||
@ -294,3 +301,9 @@ DetailsMember.prototype.toJSON = function toJSON(network) {
|
||||
: null
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = PathInfo;
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
'use strict';
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var Locker = require('../utils/locker');
|
||||
var LRU = require('../utils/lru');
|
||||
var co = require('../utils/co');
|
||||
var assert = require('assert');
|
||||
@ -214,10 +213,7 @@ function TXDB(wallet) {
|
||||
this.options = wallet.db.options;
|
||||
this.locked = {};
|
||||
|
||||
this.locker = new Locker();
|
||||
this.coinCache = new LRU(10000);
|
||||
|
||||
this.current = null;
|
||||
this.balance = null;
|
||||
}
|
||||
|
||||
@ -267,17 +263,6 @@ TXDB.prototype.prefix = function prefix(key) {
|
||||
return layout.prefix(this.wallet.wid, key);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -285,8 +270,8 @@ TXDB.prototype.start = function start() {
|
||||
*/
|
||||
|
||||
TXDB.prototype.put = function put(key, value) {
|
||||
assert(this.current);
|
||||
this.current.put(this.prefix(key), value);
|
||||
assert(this.wallet.current);
|
||||
this.wallet.current.put(this.prefix(key), value);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -295,29 +280,8 @@ TXDB.prototype.put = function put(key, value) {
|
||||
*/
|
||||
|
||||
TXDB.prototype.del = function del(key) {
|
||||
assert(this.current);
|
||||
this.current.del(this.prefix(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;
|
||||
assert(this.wallet.current);
|
||||
this.wallet.current.del(this.prefix(key));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -380,29 +344,13 @@ TXDB.prototype.values = function values(options) {
|
||||
return this.db.values(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Commit current batch.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
TXDB.prototype.commit = co(function* commit() {
|
||||
assert(this.current);
|
||||
try {
|
||||
yield this.current.write();
|
||||
} catch (e) {
|
||||
this.current = null;
|
||||
throw e;
|
||||
}
|
||||
this.current = null;
|
||||
});
|
||||
|
||||
/**
|
||||
* Map a transactions' addresses to wallet IDs.
|
||||
* @param {TX} tx
|
||||
* @returns {Promise} - Returns {@link PathInfo}.
|
||||
*/
|
||||
|
||||
TXDB.prototype.getInfo = function getInfo(tx) {
|
||||
TXDB.prototype.getPathInfo = function getPathInfo(tx) {
|
||||
return this.wallet.getPathInfo(tx);
|
||||
};
|
||||
|
||||
@ -602,13 +550,22 @@ TXDB.prototype.resolveOrphans = co(function* resolveOrphans(tx, index) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
TXDB.prototype.add = co(function* add(tx, info) {
|
||||
var unlock = yield this.locker.lock();
|
||||
TXDB.prototype.add = co(function* add(tx) {
|
||||
var info = yield this.getPathInfo(tx);
|
||||
var result;
|
||||
|
||||
this.wallet.start();
|
||||
|
||||
try {
|
||||
return yield this._add(tx, info);
|
||||
} finally {
|
||||
unlock();
|
||||
result = yield this._add(tx, info);
|
||||
} catch (e) {
|
||||
this.wallet.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
yield this.wallet.commit();
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
/**
|
||||
@ -633,16 +590,9 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
||||
if (result)
|
||||
return true;
|
||||
|
||||
this.start();
|
||||
|
||||
// Verify and get coins.
|
||||
// This potentially removes double-spenders.
|
||||
try {
|
||||
result = yield this.verify(tx, info);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
result = yield this.verify(tx, info);
|
||||
|
||||
if (!result)
|
||||
return false;
|
||||
@ -692,12 +642,7 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
||||
|
||||
// Add orphan, if no parent transaction is yet known
|
||||
if (!input.coin) {
|
||||
try {
|
||||
yield this.addOrphan(prevout, spender);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
yield this.addOrphan(prevout, spender);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -722,12 +667,7 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
||||
if (!path)
|
||||
continue;
|
||||
|
||||
try {
|
||||
orphans = yield this.resolveOrphans(tx, i);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
orphans = yield this.resolveOrphans(tx, i);
|
||||
|
||||
if (orphans)
|
||||
continue;
|
||||
@ -744,8 +684,6 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
||||
this.coinCache.set(key, coin);
|
||||
}
|
||||
|
||||
yield this.commit();
|
||||
|
||||
// Clear any locked coins to free up memory.
|
||||
this.unlockTX(tx);
|
||||
|
||||
@ -925,8 +863,6 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
||||
// Save the original received time.
|
||||
tx.ps = existing.ps;
|
||||
|
||||
this.start();
|
||||
|
||||
this.put(layout.t(hash), tx.toExtended());
|
||||
|
||||
this.del(layout.p(hash));
|
||||
@ -947,21 +883,11 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
||||
if (!info.hasPath(address))
|
||||
continue;
|
||||
|
||||
try {
|
||||
coin = yield this.getCoin(hash, i);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
coin = yield this.getCoin(hash, i);
|
||||
|
||||
// Update spent coin.
|
||||
if (!coin) {
|
||||
try {
|
||||
yield this.updateSpentCoin(tx, i);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
yield this.updateSpentCoin(tx, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -975,8 +901,6 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
||||
this.coinCache.set(key, coin);
|
||||
}
|
||||
|
||||
yield this.commit();
|
||||
|
||||
this.emit('tx', tx, info);
|
||||
this.emit('confirmed', tx, info);
|
||||
|
||||
@ -990,12 +914,20 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
||||
*/
|
||||
|
||||
TXDB.prototype.remove = co(function* remove(hash) {
|
||||
var unlock = yield this.locker.lock();
|
||||
var result;
|
||||
|
||||
this.wallet.start();
|
||||
|
||||
try {
|
||||
return yield this._remove(hash);
|
||||
} finally {
|
||||
unlock();
|
||||
result = yield this._remove(hash);
|
||||
} catch (e) {
|
||||
this.wallet.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
yield this.wallet.commit();
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1012,16 +944,7 @@ TXDB.prototype._remove = co(function* remove(hash) {
|
||||
if (!tx)
|
||||
return;
|
||||
|
||||
this.start();
|
||||
|
||||
try {
|
||||
info = yield this.removeRecursive(tx);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
yield this.commit();
|
||||
info = yield this.removeRecursive(tx);
|
||||
|
||||
if (!info)
|
||||
return;
|
||||
@ -1038,7 +961,7 @@ TXDB.prototype._remove = co(function* remove(hash) {
|
||||
*/
|
||||
|
||||
TXDB.prototype.lazyRemove = co(function* lazyRemove(tx) {
|
||||
var info = yield this.getInfo(tx);
|
||||
var info = yield this.getPathInfo(tx);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
@ -1143,12 +1066,20 @@ TXDB.prototype.__remove = co(function* remove(tx, info) {
|
||||
*/
|
||||
|
||||
TXDB.prototype.unconfirm = co(function* unconfirm(hash) {
|
||||
var unlock = yield this.locker.lock();
|
||||
var result;
|
||||
|
||||
this.wallet.start();
|
||||
|
||||
try {
|
||||
return yield this._unconfirm(hash);
|
||||
} finally {
|
||||
unlock();
|
||||
result = yield this._unconfirm(hash);
|
||||
} catch (e) {
|
||||
this.wallet.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
yield this.wallet.commit();
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1165,21 +1096,12 @@ TXDB.prototype._unconfirm = co(function* unconfirm(hash) {
|
||||
if (!tx)
|
||||
return false;
|
||||
|
||||
info = yield this.getInfo(tx);
|
||||
info = yield this.getPathInfo(tx);
|
||||
|
||||
if (!info)
|
||||
return false;
|
||||
|
||||
this.start();
|
||||
|
||||
try {
|
||||
result = yield this.__unconfirm(tx, info);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
yield this.commit();
|
||||
result = yield this.__unconfirm(tx, info);
|
||||
|
||||
return result;
|
||||
});
|
||||
@ -1804,7 +1726,7 @@ TXDB.prototype.toDetails = co(function* toDetails(tx) {
|
||||
|
||||
yield this.fillHistory(tx);
|
||||
|
||||
info = yield this.getInfo(tx);
|
||||
info = yield this.getPathInfo(tx);
|
||||
|
||||
if (!info)
|
||||
throw new Error('Info not found.');
|
||||
@ -1996,23 +1918,6 @@ TXDB.prototype.getAccountBalance = co(function* getBalance(account) {
|
||||
*/
|
||||
|
||||
TXDB.prototype.zap = co(function* zap(account, age) {
|
||||
var unlock = yield this.locker.lock();
|
||||
try {
|
||||
return yield this._zap(account, age);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Zap pending transactions without a lock.
|
||||
* @private
|
||||
* @param {Number?} account
|
||||
* @param {Number} age
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
TXDB.prototype._zap = co(function* zap(account, age) {
|
||||
var i, txs, tx, hash;
|
||||
|
||||
if (!utils.isUInt32(age))
|
||||
@ -2030,7 +1935,16 @@ TXDB.prototype._zap = co(function* zap(account, age) {
|
||||
if (tx.ts !== 0)
|
||||
continue;
|
||||
|
||||
yield this._remove(hash);
|
||||
this.wallet.start();
|
||||
|
||||
try {
|
||||
yield this._remove(hash);
|
||||
} catch (e) {
|
||||
this.wallet.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
yield this.wallet.commit();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -535,16 +535,42 @@ Wallet.prototype.renameAccount = co(function* renameAccount(acct, name) {
|
||||
*/
|
||||
|
||||
Wallet.prototype._renameAccount = co(function* _renameAccount(acct, name) {
|
||||
var account;
|
||||
var i, account, old, paths, path;
|
||||
|
||||
assert(utils.isName(name), 'Bad account name.');
|
||||
if (!utils.isName(name))
|
||||
throw new Error('Bad account name.');
|
||||
|
||||
account = yield this.getAccount(acct);
|
||||
|
||||
if (!account)
|
||||
throw new Error('Account not found.');
|
||||
|
||||
yield this.db.renameAccount(account, name);
|
||||
if (account.accountIndex === 0)
|
||||
throw new Error('Cannot rename default account.');
|
||||
|
||||
if (yield this.hasAccount(name))
|
||||
throw new Error('Account name not available.');
|
||||
|
||||
old = account.name;
|
||||
|
||||
this.start();
|
||||
|
||||
this.db.renameAccount(account, name);
|
||||
|
||||
yield this.commit();
|
||||
|
||||
this.indexCache.remove(old);
|
||||
|
||||
paths = this.pathCache.values();
|
||||
|
||||
for (i = 0; i < paths.length; i++) {
|
||||
path = paths[i];
|
||||
|
||||
if (path.account !== account.accountIndex)
|
||||
continue;
|
||||
|
||||
path.name = name;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@ -766,7 +792,7 @@ Wallet.prototype.getAddressHashes = function getAddressHashes() {
|
||||
*/
|
||||
|
||||
Wallet.prototype.getAccount = co(function* getAccount(acct) {
|
||||
var index, unlock, account;
|
||||
var index, unlock;
|
||||
|
||||
if (this.account) {
|
||||
if (acct === 0 || acct === 'default')
|
||||
@ -805,13 +831,12 @@ Wallet.prototype._getAccount = co(function* getAccount(index) {
|
||||
return;
|
||||
|
||||
account.wallet = this;
|
||||
|
||||
yield account.open();
|
||||
|
||||
account.wid = this.wid;
|
||||
account.id = this.id;
|
||||
account.watchOnly = this.watchOnly;
|
||||
|
||||
yield account.open();
|
||||
|
||||
this.accountCache.set(index, account);
|
||||
|
||||
return account;
|
||||
@ -825,7 +850,7 @@ Wallet.prototype._getAccount = co(function* getAccount(index) {
|
||||
*/
|
||||
|
||||
Wallet.prototype.getAccountIndex = co(function* getAccountIndex(name) {
|
||||
var key, index;
|
||||
var index;
|
||||
|
||||
if (name == null)
|
||||
return -1;
|
||||
@ -1070,6 +1095,7 @@ Wallet.prototype.getPaths = co(function* getPaths(acct) {
|
||||
if (!account || path.account === account) {
|
||||
path.id = this.id;
|
||||
path.name = yield this.getAccountName(path.account);
|
||||
this.pathCache.set(path.hash, path);
|
||||
out.push(path);
|
||||
}
|
||||
}
|
||||
@ -1568,29 +1594,11 @@ Wallet.prototype.getOutputPaths = co(function* getOutputPaths(tx) {
|
||||
*/
|
||||
|
||||
Wallet.prototype.syncOutputDepth = co(function* syncOutputDepth(info) {
|
||||
var unlock = yield this.writeLock.lock();
|
||||
try {
|
||||
return yield this._syncOutputDepth(info);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Sync address depths without a lock.
|
||||
* @private
|
||||
* @param {PathInfo} info
|
||||
* @returns {Promise} - Returns Boolean
|
||||
*/
|
||||
|
||||
Wallet.prototype._syncOutputDepth = co(function* syncOutputDepth(info) {
|
||||
var derived = [];
|
||||
var accounts = {};
|
||||
var i, j, path, paths, account;
|
||||
var receive, change, nested, ring;
|
||||
|
||||
this.start();
|
||||
|
||||
for (i = 0; i < info.paths.length; i++) {
|
||||
path = info.paths[i];
|
||||
|
||||
@ -1646,8 +1654,6 @@ Wallet.prototype._syncOutputDepth = co(function* syncOutputDepth(info) {
|
||||
derived.push(ring);
|
||||
}
|
||||
|
||||
yield this.commit();
|
||||
|
||||
if (derived.length > 0) {
|
||||
this.db.emit('address', this.id, derived);
|
||||
this.emit('address', derived);
|
||||
@ -1678,19 +1684,6 @@ Wallet.prototype.updateBalances = co(function* updateBalances() {
|
||||
this.emit('balance', balance);
|
||||
});
|
||||
|
||||
/**
|
||||
* Derive new addresses and emit balance.
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @param {PathInfo} info
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.handleTX = co(function* handleTX(info) {
|
||||
yield this.syncOutputDepth(info);
|
||||
yield this.updateBalances();
|
||||
});
|
||||
|
||||
/**
|
||||
* Get a redeem script or witness script by hash.
|
||||
* @param {Hash} hash - Can be a ripemd160 or a sha256.
|
||||
@ -1820,20 +1813,123 @@ Wallet.prototype.getTX = function getTX(hash) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.addTX = function addTX(tx) {
|
||||
return this.db.addTX(tx);
|
||||
};
|
||||
|
||||
Wallet.prototype.add = co(function* add(tx) {
|
||||
var info = yield this.getPathInfo(tx);
|
||||
yield this.txdb.add(tx, info);
|
||||
yield this.handleTX(info);
|
||||
var unlock = yield this.writeLock.lock();
|
||||
try {
|
||||
return yield this._add(tx);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Add a transaction to the wallet without a lock.
|
||||
* @param {TX} tx
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype._add = co(function* add(tx) {
|
||||
var info = yield this.getPathInfo(tx);
|
||||
|
||||
this.start();
|
||||
|
||||
try {
|
||||
yield this.txdb._add(tx, info);
|
||||
yield this.syncOutputDepth(info);
|
||||
yield this.updateBalances();
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
yield this.commit();
|
||||
});
|
||||
|
||||
/**
|
||||
* Unconfirm a wallet transcation.
|
||||
* @param {Hash} hash
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.unconfirm = co(function* unconfirm(hash) {
|
||||
return yield this.txdb.unconfirm(hash);
|
||||
var unlock = yield this.writeLock.lock();
|
||||
try {
|
||||
return yield this.txdb.unconfirm(hash);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Remove a wallet transaction.
|
||||
* @param {Hash} hash
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.remove = co(function* remove(hash) {
|
||||
var unlock = yield this.writeLock.lock();
|
||||
try {
|
||||
return yield this.txdb.remove(hash);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Zap stale TXs from wallet (accesses db).
|
||||
* @param {(Number|String)?} acct
|
||||
* @param {Number} age - Age threshold (unix time, default=72 hours).
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.zap = co(function* zap(acct, age) {
|
||||
var unlock = yield this.writeLock.lock();
|
||||
try {
|
||||
return yield this._zap(acct, age);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Zap stale TXs from wallet without a lock.
|
||||
* @private
|
||||
* @param {(Number|String)?} acct
|
||||
* @param {Number} age
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype._zap = co(function* zap(acct, age) {
|
||||
var account = yield this._getIndex(acct);
|
||||
return yield this.txdb.zap(account, age);
|
||||
});
|
||||
|
||||
/**
|
||||
* Abandon transaction (accesses db).
|
||||
* @param {Hash} hash
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.abandon = co(function* abandon(hash) {
|
||||
var unlock = yield this.writeLock.lock();
|
||||
try {
|
||||
return yield this._abandon(hash);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Abandon transaction without a lock.
|
||||
* @private
|
||||
* @param {Hash} hash
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype._abandon = function abandon(hash) {
|
||||
return this.txdb.abandon(hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Map a transactions' addresses to wallet IDs.
|
||||
* @param {TX} tx
|
||||
@ -1930,28 +2026,6 @@ Wallet.prototype.getLast = co(function* getLast(acct, limit) {
|
||||
return yield this.txdb.getLast(account, limit);
|
||||
});
|
||||
|
||||
/**
|
||||
* Zap stale TXs from wallet (accesses db).
|
||||
* @param {(Number|String)?} acct
|
||||
* @param {Number} age - Age threshold (unix time, default=72 hours).
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.zap = co(function* zap(acct, age) {
|
||||
var account = yield this._getIndex(acct);
|
||||
return yield this.txdb.zap(account, age);
|
||||
});
|
||||
|
||||
/**
|
||||
* Abandon transaction (accesses db).
|
||||
* @param {Hash} hash
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.abandon = function abandon(hash) {
|
||||
return this.txdb.abandon(hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolve account index.
|
||||
* @private
|
||||
|
||||
@ -25,7 +25,6 @@ var ldb = require('../db/ldb');
|
||||
var Bloom = require('../utils/bloom');
|
||||
var Logger = require('../node/logger');
|
||||
var TX = require('../primitives/tx');
|
||||
var PathInfo = require('./pathinfo');
|
||||
|
||||
/*
|
||||
* Database Layout:
|
||||
@ -534,79 +533,44 @@ WalletDB.prototype._rename = co(function* _rename(wallet, id) {
|
||||
var old = wallet.id;
|
||||
var i, paths, path, batch;
|
||||
|
||||
assert(utils.isName(id), 'Bad wallet ID.');
|
||||
if (!utils.isName(id))
|
||||
throw new Error('Bad wallet ID.');
|
||||
|
||||
if (yield this.has(id))
|
||||
throw new Error('ID not available.');
|
||||
|
||||
batch = this.start(wallet);
|
||||
batch.del(layout.l(old));
|
||||
|
||||
wallet.id = id;
|
||||
|
||||
this.save(wallet);
|
||||
|
||||
yield this.commit(wallet);
|
||||
|
||||
this.widCache.remove(old);
|
||||
|
||||
paths = wallet.pathCache.values();
|
||||
|
||||
for (i = 0; i < paths.length; i++) {
|
||||
path = paths[i];
|
||||
|
||||
if (path.wid !== wallet.wid)
|
||||
continue;
|
||||
|
||||
path.id = id;
|
||||
}
|
||||
|
||||
wallet.id = id;
|
||||
|
||||
batch = this.start(wallet);
|
||||
batch.del(layout.l(old));
|
||||
|
||||
this.save(wallet);
|
||||
|
||||
yield this.commit(wallet);
|
||||
});
|
||||
|
||||
/**
|
||||
* Rename an account.
|
||||
* @param {Account} account
|
||||
* @param {String} name
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.renameAccount = co(function* renameAccount(account, name) {
|
||||
WalletDB.prototype.renameAccount = function renameAccount(account, name) {
|
||||
var wallet = account.wallet;
|
||||
var old = account.name;
|
||||
var i, paths, path, batch;
|
||||
|
||||
assert(utils.isName(name), 'Bad account name.');
|
||||
|
||||
if (account.accountIndex === 0)
|
||||
throw new Error('Cannot rename primary account.');
|
||||
|
||||
if (yield account.wallet.hasAccount(name))
|
||||
throw new Error('Account name not available.');
|
||||
|
||||
wallet.indexCache.remove(old);
|
||||
|
||||
paths = wallet.pathCache.values();
|
||||
|
||||
for (i = 0; i < paths.length; i++) {
|
||||
path = paths[i];
|
||||
|
||||
if (path.wid !== account.wid)
|
||||
continue;
|
||||
|
||||
if (path.account !== account.accountIndex)
|
||||
continue;
|
||||
|
||||
path.name = name;
|
||||
}
|
||||
|
||||
var batch = this.batch(wallet);
|
||||
batch.del(layout.i(account.wid, account.name));
|
||||
account.name = name;
|
||||
|
||||
batch = this.start(wallet);
|
||||
batch.del(layout.i(account.wid, old));
|
||||
|
||||
this.saveAccount(account);
|
||||
|
||||
yield this.commit(wallet);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Test an api key against a wallet's api key.
|
||||
@ -669,10 +633,10 @@ WalletDB.prototype._create = co(function* create(options) {
|
||||
wallet = Wallet.fromOptions(this, options);
|
||||
wallet.wid = this.depth++;
|
||||
|
||||
this.register(wallet);
|
||||
|
||||
yield wallet.init(options);
|
||||
|
||||
this.register(wallet);
|
||||
|
||||
this.logger.info('Created wallet %s.', wallet.id);
|
||||
|
||||
return wallet;
|
||||
@ -712,7 +676,6 @@ WalletDB.prototype.ensure = co(function* ensure(options) {
|
||||
|
||||
WalletDB.prototype.getAccount = co(function* getAccount(wid, index) {
|
||||
var data = yield this.db.get(layout.a(wid, index));
|
||||
var account;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
@ -919,6 +882,7 @@ WalletDB.prototype.getPaths = co(function* getPaths(hash) {
|
||||
|
||||
WalletDB.prototype.getPath = co(function* getPath(wid, hash) {
|
||||
var data = yield this.db.get(layout.P(wid, hash));
|
||||
var path;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
@ -1170,7 +1134,7 @@ WalletDB.prototype.resend = co(function* resend() {
|
||||
|
||||
WalletDB.prototype.getWidsByHashes = co(function* getWidsByHashes(hashes) {
|
||||
var result = [];
|
||||
var i, j, hash, wids, wid;
|
||||
var i, j, hash, wids;
|
||||
|
||||
for (i = 0; i < hashes.length; i++) {
|
||||
hash = hashes[i];
|
||||
@ -1350,7 +1314,7 @@ WalletDB.prototype._addBlock = co(function* addBlock(entry, txs) {
|
||||
for (i = 0; i < txs.length; i++) {
|
||||
tx = txs[i];
|
||||
|
||||
wallets = yield this._add(tx);
|
||||
wallets = yield this._addTX(tx);
|
||||
|
||||
if (!wallets)
|
||||
continue;
|
||||
@ -1393,7 +1357,7 @@ WalletDB.prototype.removeBlock = co(function* removeBlock(entry) {
|
||||
|
||||
WalletDB.prototype._removeBlock = co(function* removeBlock(entry) {
|
||||
var block = WalletBlock.fromEntry(entry);
|
||||
var i, j, data, hash, wallets, wid, wallet;
|
||||
var i, data, hash;
|
||||
|
||||
// If we crash during a reorg, there's not much to do.
|
||||
// Reorgs cannot be rescanned. The database will be
|
||||
@ -1416,7 +1380,7 @@ WalletDB.prototype._removeBlock = co(function* removeBlock(entry) {
|
||||
|
||||
for (i = 0; i < block.hashes.length; i++) {
|
||||
hash = block.hashes[i];
|
||||
yield this._unconfirm(hash);
|
||||
yield this._unconfirmTX(hash);
|
||||
}
|
||||
|
||||
this.tip = block.hash;
|
||||
@ -1431,11 +1395,10 @@ WalletDB.prototype._removeBlock = co(function* removeBlock(entry) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.addTX =
|
||||
WalletDB.prototype.add = co(function* add(tx) {
|
||||
WalletDB.prototype.addTX = co(function* addTX(tx) {
|
||||
var unlock = yield this.txLock.lock();
|
||||
try {
|
||||
return yield this._add(tx);
|
||||
return yield this._addTX(tx);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
@ -1448,7 +1411,7 @@ WalletDB.prototype.add = co(function* add(tx) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype._add = co(function* add(tx) {
|
||||
WalletDB.prototype._addTX = co(function* addTX(tx) {
|
||||
var i, hashes, wallets, wid, wallet;
|
||||
|
||||
assert(!tx.mutable, 'Cannot add mutable TX to wallet.');
|
||||
@ -1482,30 +1445,29 @@ WalletDB.prototype._add = co(function* add(tx) {
|
||||
});
|
||||
|
||||
/**
|
||||
* Add a transaction to the database, map addresses
|
||||
* to wallet IDs, potentially store orphans, resolve
|
||||
* orphans, or confirm a transaction.
|
||||
* @param {TX} tx
|
||||
* Unconfirm a transaction from all relevant wallets.
|
||||
* @param {Hash} hash
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.unconfirm = co(function* unconfirm(hash) {
|
||||
WalletDB.prototype.unconfirmTX = co(function* unconfirmTX(hash) {
|
||||
var unlock = yield this.txLock.lock();
|
||||
try {
|
||||
return yield this._unconfirm(tx);
|
||||
return yield this._unconfirmTX(hash);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Add a transaction to the database without a lock.
|
||||
* Unconfirm a transaction from all
|
||||
* relevant wallets without a lock.
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @param {Hash} hash
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype._unconfirm = co(function* unconfirm(hash) {
|
||||
WalletDB.prototype._unconfirmTX = co(function* unconfirmTX(hash) {
|
||||
var wallets = yield this.getWalletsByTX(hash);
|
||||
var i, wid, wallet;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user