wallet: make more state local to wallets.
This commit is contained in:
parent
3cef641780
commit
9a3e3fba3a
@ -48,6 +48,7 @@ function Account(db, options) {
|
|||||||
|
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.network = db.network;
|
this.network = db.network;
|
||||||
|
this.wallet = null;
|
||||||
this.lookahead = Account.MAX_LOOKAHEAD;
|
this.lookahead = Account.MAX_LOOKAHEAD;
|
||||||
|
|
||||||
this.receive = null;
|
this.receive = null;
|
||||||
@ -368,7 +369,7 @@ Account.prototype._checkKeys = co(function* _checkKeys() {
|
|||||||
ring = this.deriveReceive(0);
|
ring = this.deriveReceive(0);
|
||||||
hash = ring.getScriptHash('hex');
|
hash = ring.getScriptHash('hex');
|
||||||
|
|
||||||
return yield this.db.hasAddress(this.wid, hash);
|
return yield this.wallet.hasAddress(hash);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -587,7 +588,7 @@ Account.prototype.save = function save() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.saveKey = function saveKey(ring) {
|
Account.prototype.saveKey = function saveKey(ring) {
|
||||||
return this.db.saveKey(this.wid, ring);
|
return this.db.saveKey(this.wallet, ring);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -597,7 +598,7 @@ Account.prototype.saveKey = function saveKey(ring) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.savePath = function savePath(path) {
|
Account.prototype.savePath = function savePath(path) {
|
||||||
return this.db.savePath(this.wid, path);
|
return this.db.savePath(this.wallet, path);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -27,6 +27,7 @@ var Account = require('./account');
|
|||||||
var MasterKey = require('./masterkey');
|
var MasterKey = require('./masterkey');
|
||||||
var Input = require('../primitives/input');
|
var Input = require('../primitives/input');
|
||||||
var Output = require('../primitives/output');
|
var Output = require('../primitives/output');
|
||||||
|
var LRU = require('../utils/lru');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BIP44 Wallet
|
* BIP44 Wallet
|
||||||
@ -67,6 +68,10 @@ function Wallet(db, options) {
|
|||||||
this.readLock = new Locker.Mapped();
|
this.readLock = new Locker.Mapped();
|
||||||
this.writeLock = new Locker();
|
this.writeLock = new Locker();
|
||||||
this.fundLock = new Locker();
|
this.fundLock = new Locker();
|
||||||
|
this.indexCache = new LRU(10000);
|
||||||
|
this.accountCache = new LRU(10000);
|
||||||
|
this.pathCache = new LRU(100000);
|
||||||
|
this.batch = null;
|
||||||
|
|
||||||
this.wid = 0;
|
this.wid = 0;
|
||||||
this.id = null;
|
this.id = null;
|
||||||
@ -184,7 +189,7 @@ Wallet.prototype.init = co(function* init(options) {
|
|||||||
if (options.passphrase)
|
if (options.passphrase)
|
||||||
yield this.master.encrypt(options.passphrase);
|
yield this.master.encrypt(options.passphrase);
|
||||||
|
|
||||||
account = yield this.createAccount(options);
|
account = yield this._createAccount(options);
|
||||||
assert(account);
|
assert(account);
|
||||||
|
|
||||||
this.account = account;
|
this.account = account;
|
||||||
@ -394,7 +399,7 @@ Wallet.prototype._encrypt = co(function* encrypt(passphrase) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
key = yield this.master.encrypt(passphrase);
|
key = yield this.master.encrypt(passphrase);
|
||||||
yield this.db.encryptKeys(this.wid, key);
|
yield this.db.encryptKeys(this, key);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.drop();
|
this.drop();
|
||||||
throw e;
|
throw e;
|
||||||
@ -440,7 +445,7 @@ Wallet.prototype._decrypt = co(function* decrypt(passphrase) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
key = yield this.master.decrypt(passphrase);
|
key = yield this.master.decrypt(passphrase);
|
||||||
yield this.db.decryptKeys(this.wid, key);
|
yield this.db.decryptKeys(this, key);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.drop();
|
this.drop();
|
||||||
throw e;
|
throw e;
|
||||||
@ -646,7 +651,7 @@ Wallet.prototype._createAccount = co(function* createAccount(options) {
|
|||||||
var passphrase = options.passphrase;
|
var passphrase = options.passphrase;
|
||||||
var timeout = options.timeout;
|
var timeout = options.timeout;
|
||||||
var name = options.name;
|
var name = options.name;
|
||||||
var key, master, account;
|
var key, master, account, exists;
|
||||||
|
|
||||||
if (typeof options.account === 'string')
|
if (typeof options.account === 'string')
|
||||||
name = options.account;
|
name = options.account;
|
||||||
@ -654,6 +659,11 @@ Wallet.prototype._createAccount = co(function* createAccount(options) {
|
|||||||
if (!name)
|
if (!name)
|
||||||
name = this.accountDepth + '';
|
name = this.accountDepth + '';
|
||||||
|
|
||||||
|
exists = yield this.hasAccount(name);
|
||||||
|
|
||||||
|
if (exists)
|
||||||
|
throw new Error('Account already exists.');
|
||||||
|
|
||||||
master = yield this.unlock(passphrase, timeout);
|
master = yield this.unlock(passphrase, timeout);
|
||||||
|
|
||||||
if (this.watchOnly && options.accountKey) {
|
if (this.watchOnly && options.accountKey) {
|
||||||
@ -686,12 +696,21 @@ Wallet.prototype._createAccount = co(function* createAccount(options) {
|
|||||||
this.start();
|
this.start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
account = yield this.db.createAccount(options);
|
account = Account.fromOptions(this.db, options);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.drop();
|
this.drop();
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
account.wallet = this;
|
||||||
|
|
||||||
|
yield account.init();
|
||||||
|
|
||||||
|
this.logger.info('Created account %s/%s/%d.',
|
||||||
|
account.id,
|
||||||
|
account.name,
|
||||||
|
account.accountIndex);
|
||||||
|
|
||||||
this.accountDepth++;
|
this.accountDepth++;
|
||||||
this.save();
|
this.save();
|
||||||
|
|
||||||
@ -746,14 +765,14 @@ Wallet.prototype.getAddressHashes = function getAddressHashes() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.getAccount = co(function* getAccount(acct) {
|
Wallet.prototype.getAccount = co(function* getAccount(acct) {
|
||||||
var index, unlock;
|
var index, unlock, account;
|
||||||
|
|
||||||
if (this.account) {
|
if (this.account) {
|
||||||
if (acct === 0 || acct === 'default')
|
if (acct === 0 || acct === 'default')
|
||||||
return this.account;
|
return this.account;
|
||||||
}
|
}
|
||||||
|
|
||||||
index = yield this.db.getAccountIndex(this.wid, acct);
|
index = yield this.getAccountIndex(acct);
|
||||||
|
|
||||||
if (index === -1)
|
if (index === -1)
|
||||||
return;
|
return;
|
||||||
@ -773,28 +792,94 @@ Wallet.prototype.getAccount = co(function* getAccount(acct) {
|
|||||||
* @returns {Promise} - Returns {@link Account}.
|
* @returns {Promise} - Returns {@link Account}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype._getAccount = co(function* _getAccount(index) {
|
Wallet.prototype._getAccount = co(function* getAccount(index) {
|
||||||
var account = yield this.db.getAccount(this.wid, index);
|
var account = this.accountCache.get(index);
|
||||||
|
|
||||||
|
if (account)
|
||||||
|
return account;
|
||||||
|
|
||||||
|
account = yield this.db.getAccount(this.wid, index);
|
||||||
|
|
||||||
if (!account)
|
if (!account)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
account.wallet = this;
|
||||||
|
|
||||||
|
yield account.open();
|
||||||
|
|
||||||
account.wid = this.wid;
|
account.wid = this.wid;
|
||||||
account.id = this.id;
|
account.id = this.id;
|
||||||
account.watchOnly = this.watchOnly;
|
account.watchOnly = this.watchOnly;
|
||||||
|
|
||||||
|
this.accountCache.set(index, account);
|
||||||
|
|
||||||
return account;
|
return account;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup the corresponding account name's index.
|
||||||
|
* @param {WalletID} wid
|
||||||
|
* @param {String|Number} name - Account name/index.
|
||||||
|
* @returns {Promise} - Returns Number.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Wallet.prototype.getAccountIndex = co(function* getAccountIndex(name) {
|
||||||
|
var key, index;
|
||||||
|
|
||||||
|
if (name == null)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (typeof name === 'number')
|
||||||
|
return name;
|
||||||
|
|
||||||
|
index = this.indexCache.get(name);
|
||||||
|
|
||||||
|
if (index != null)
|
||||||
|
return index;
|
||||||
|
|
||||||
|
index = yield this.db.getAccountIndex(this.wid, name);
|
||||||
|
|
||||||
|
if (index === -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
this.indexCache.set(name, index);
|
||||||
|
|
||||||
|
return index;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup the corresponding account index's name.
|
||||||
|
* @param {WalletID} wid
|
||||||
|
* @param {Number} index - Account index.
|
||||||
|
* @returns {Promise} - Returns String.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Wallet.prototype.getAccountName = co(function* getAccountName(index) {
|
||||||
|
var account = yield this.getAccount(index);
|
||||||
|
|
||||||
|
if (!account)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return account.name;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an account exists.
|
* Test whether an account exists.
|
||||||
* @param {Number|String} acct
|
* @param {Number|String} acct
|
||||||
* @returns {Promise} - Returns {@link Boolean}.
|
* @returns {Promise} - Returns {@link Boolean}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.hasAccount = function hasAccount(acct) {
|
Wallet.prototype.hasAccount = co(function* hasAccount(acct) {
|
||||||
return this.db.hasAccount(this.wid, acct);
|
var index = yield this.getAccountIndex(acct);
|
||||||
};
|
|
||||||
|
if (index === -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (this.accountCache.has(index))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return yield this.db.hasAccount(this.wid, index);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new receiving address (increments receiveDepth).
|
* Create a new receiving address (increments receiveDepth).
|
||||||
@ -896,7 +981,7 @@ Wallet.prototype.save = function save() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.start = function start() {
|
Wallet.prototype.start = function start() {
|
||||||
return this.db.start(this.wid);
|
return this.db.start(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -905,7 +990,7 @@ Wallet.prototype.start = function start() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.drop = function drop() {
|
Wallet.prototype.drop = function drop() {
|
||||||
return this.db.drop(this.wid);
|
return this.db.drop(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -914,7 +999,7 @@ Wallet.prototype.drop = function drop() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.commit = function commit() {
|
Wallet.prototype.commit = function commit() {
|
||||||
return this.db.commit(this.wid);
|
return this.db.commit(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -923,12 +1008,17 @@ Wallet.prototype.commit = function commit() {
|
|||||||
* @returns {Promise} - Returns Boolean.
|
* @returns {Promise} - Returns Boolean.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.hasAddress = function hasAddress(address) {
|
Wallet.prototype.hasAddress = co(function* hasAddress(address) {
|
||||||
var hash = Address.getHash(address, 'hex');
|
var hash = Address.getHash(address, 'hex');
|
||||||
|
var path;
|
||||||
|
|
||||||
if (!hash)
|
if (!hash)
|
||||||
return Promise.resolve(false);
|
return false;
|
||||||
return this.db.hasAddress(this.wid, hash);
|
|
||||||
};
|
path = yield this.getPath(hash);
|
||||||
|
|
||||||
|
return path != null;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get path by address hash.
|
* Get path by address hash.
|
||||||
@ -943,12 +1033,20 @@ Wallet.prototype.getPath = co(function* getPath(address) {
|
|||||||
if (!hash)
|
if (!hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
path = this.pathCache.get(hash);
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
return path;
|
||||||
|
|
||||||
path = yield this.db.getPath(this.wid, hash);
|
path = yield this.db.getPath(this.wid, hash);
|
||||||
|
|
||||||
if (!path)
|
if (!path)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
path.id = this.id;
|
path.id = this.id;
|
||||||
|
path.name = yield this.getAccountName(path.account);
|
||||||
|
|
||||||
|
this.pathCache.set(hash, path);
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
});
|
});
|
||||||
@ -970,6 +1068,7 @@ Wallet.prototype.getPaths = co(function* getPaths(acct) {
|
|||||||
path = paths[i];
|
path = paths[i];
|
||||||
if (!account || path.account === account) {
|
if (!account || path.account === account) {
|
||||||
path.id = this.id;
|
path.id = this.id;
|
||||||
|
path.name = yield this.getAccountName(path.account);
|
||||||
out.push(path);
|
out.push(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1835,7 +1934,7 @@ Wallet.prototype._getIndex = co(function* _getIndex(acct) {
|
|||||||
if (acct == null)
|
if (acct == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
index = yield this.db.getAccountIndex(this.wid, acct);
|
index = yield this.getAccountIndex(acct);
|
||||||
|
|
||||||
if (index === -1)
|
if (index === -1)
|
||||||
throw new Error('Account not found.');
|
throw new Error('Account not found.');
|
||||||
|
|||||||
@ -157,9 +157,6 @@ function WalletDB(options) {
|
|||||||
this.txLock = new Locker();
|
this.txLock = new Locker();
|
||||||
|
|
||||||
this.widCache = new LRU(10000);
|
this.widCache = new LRU(10000);
|
||||||
this.indexCache = new LRU(10000);
|
|
||||||
this.accountCache = new LRU(10000);
|
|
||||||
this.pathCache = new LRU(100000);
|
|
||||||
this.pathMapCache = new LRU(100000);
|
this.pathMapCache = new LRU(100000);
|
||||||
|
|
||||||
// Try to optimize for up to 1m addresses.
|
// Try to optimize for up to 1m addresses.
|
||||||
@ -293,13 +290,10 @@ WalletDB.prototype.getDepth = co(function* getDepth() {
|
|||||||
* @param {WalletID} wid
|
* @param {WalletID} wid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.start = function start(wid) {
|
WalletDB.prototype.start = function start(wallet) {
|
||||||
var batch;
|
assert(!wallet.batch, 'Batch already started.');
|
||||||
assert(utils.isNumber(wid), 'Bad ID for batch.');
|
wallet.batch = this.db.batch();
|
||||||
assert(!this.batches[wid], 'Batch already started.');
|
return wallet.batch;
|
||||||
batch = this.db.batch();
|
|
||||||
this.batches[wid] = batch;
|
|
||||||
return batch;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -308,10 +302,10 @@ WalletDB.prototype.start = function start(wid) {
|
|||||||
* @param {WalletID} wid
|
* @param {WalletID} wid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.drop = function drop(wid) {
|
WalletDB.prototype.drop = function drop(wallet) {
|
||||||
var batch = this.batch(wid);
|
var batch = this.batch(wallet);
|
||||||
|
wallet.batch = null;
|
||||||
batch.clear();
|
batch.clear();
|
||||||
delete this.batches[wid];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -321,12 +315,9 @@ WalletDB.prototype.drop = function drop(wid) {
|
|||||||
* @returns {Leveldown.Batch}
|
* @returns {Leveldown.Batch}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.batch = function batch(wid) {
|
WalletDB.prototype.batch = function batch(wallet) {
|
||||||
var batch;
|
assert(wallet.batch, 'Batch does not exist.');
|
||||||
assert(utils.isNumber(wid), 'Bad ID for batch.');
|
return wallet.batch;
|
||||||
batch = this.batches[wid];
|
|
||||||
assert(batch, 'Batch does not exist.');
|
|
||||||
return batch;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,9 +327,9 @@ WalletDB.prototype.batch = function batch(wid) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.commit = function commit(wid) {
|
WalletDB.prototype.commit = function commit(wallet) {
|
||||||
var batch = this.batch(wid);
|
var batch = wallet.batch;
|
||||||
delete this.batches[wid];
|
wallet.batch = null;
|
||||||
return batch.write();
|
return batch.write();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -377,18 +368,11 @@ WalletDB.prototype.loadFilter = co(function* loadFilter() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.testFilter = function testFilter(hashes) {
|
WalletDB.prototype.testFilter = function testFilter(hash) {
|
||||||
var i;
|
|
||||||
|
|
||||||
if (!this.filter)
|
if (!this.filter)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (i = 0; i < hashes.length; i++) {
|
return this.filter.test(hash, 'hex');
|
||||||
if (this.filter.test(hashes[i], 'hex'))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -511,7 +495,7 @@ WalletDB.prototype._get = co(function* get(wid) {
|
|||||||
WalletDB.prototype.save = function save(wallet) {
|
WalletDB.prototype.save = function save(wallet) {
|
||||||
var wid = wallet.wid;
|
var wid = wallet.wid;
|
||||||
var id = wallet.id;
|
var id = wallet.id;
|
||||||
var batch = this.batch(wid);
|
var batch = this.batch(wallet);
|
||||||
var buf = new Buffer(4);
|
var buf = new Buffer(4);
|
||||||
|
|
||||||
this.widCache.set(id, wid);
|
this.widCache.set(id, wid);
|
||||||
@ -557,7 +541,7 @@ WalletDB.prototype._rename = co(function* _rename(wallet, id) {
|
|||||||
|
|
||||||
this.widCache.remove(old);
|
this.widCache.remove(old);
|
||||||
|
|
||||||
paths = this.pathCache.values();
|
paths = wallet.pathCache.values();
|
||||||
|
|
||||||
for (i = 0; i < paths.length; i++) {
|
for (i = 0; i < paths.length; i++) {
|
||||||
path = paths[i];
|
path = paths[i];
|
||||||
@ -570,12 +554,12 @@ WalletDB.prototype._rename = co(function* _rename(wallet, id) {
|
|||||||
|
|
||||||
wallet.id = id;
|
wallet.id = id;
|
||||||
|
|
||||||
batch = this.start(wallet.wid);
|
batch = this.start(wallet);
|
||||||
batch.del(layout.l(old));
|
batch.del(layout.l(old));
|
||||||
|
|
||||||
this.save(wallet);
|
this.save(wallet);
|
||||||
|
|
||||||
yield this.commit(wallet.wid);
|
yield this.commit(wallet);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -586,8 +570,8 @@ WalletDB.prototype._rename = co(function* _rename(wallet, id) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.renameAccount = co(function* renameAccount(account, name) {
|
WalletDB.prototype.renameAccount = co(function* renameAccount(account, name) {
|
||||||
|
var wallet = account.wallet;
|
||||||
var old = account.name;
|
var old = account.name;
|
||||||
var key = account.wid + '/' + old;
|
|
||||||
var i, paths, path, batch;
|
var i, paths, path, batch;
|
||||||
|
|
||||||
assert(utils.isName(name), 'Bad account name.');
|
assert(utils.isName(name), 'Bad account name.');
|
||||||
@ -595,12 +579,12 @@ WalletDB.prototype.renameAccount = co(function* renameAccount(account, name) {
|
|||||||
if (account.accountIndex === 0)
|
if (account.accountIndex === 0)
|
||||||
throw new Error('Cannot rename primary account.');
|
throw new Error('Cannot rename primary account.');
|
||||||
|
|
||||||
if (yield this.hasAccount(account.wid, name))
|
if (yield account.wallet.hasAccount(name))
|
||||||
throw new Error('Account name not available.');
|
throw new Error('Account name not available.');
|
||||||
|
|
||||||
this.indexCache.remove(key);
|
wallet.indexCache.remove(old);
|
||||||
|
|
||||||
paths = this.pathCache.values();
|
paths = wallet.pathCache.values();
|
||||||
|
|
||||||
for (i = 0; i < paths.length; i++) {
|
for (i = 0; i < paths.length; i++) {
|
||||||
path = paths[i];
|
path = paths[i];
|
||||||
@ -616,12 +600,12 @@ WalletDB.prototype.renameAccount = co(function* renameAccount(account, name) {
|
|||||||
|
|
||||||
account.name = name;
|
account.name = name;
|
||||||
|
|
||||||
batch = this.start(account.wid);
|
batch = this.start(wallet);
|
||||||
batch.del(layout.i(account.wid, old));
|
batch.del(layout.i(account.wid, old));
|
||||||
|
|
||||||
this.saveAccount(account);
|
this.saveAccount(account);
|
||||||
|
|
||||||
yield this.commit(account.wid);
|
yield this.commit(wallet);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -718,30 +702,6 @@ WalletDB.prototype.ensure = co(function* ensure(options) {
|
|||||||
return yield this.create(options);
|
return yield this.create(options);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an account from the database.
|
|
||||||
* @param {WalletID} wid
|
|
||||||
* @param {String|Number} acct - Account name/index.
|
|
||||||
* @returns {Promise} - Returns {@link Wallet}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getAccount = co(function* getAccount(wid, acct) {
|
|
||||||
var index = yield this.getAccountIndex(wid, acct);
|
|
||||||
var account;
|
|
||||||
|
|
||||||
if (index === -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
account = yield this._getAccount(wid, index);
|
|
||||||
|
|
||||||
if (!account)
|
|
||||||
return;
|
|
||||||
|
|
||||||
yield account.open();
|
|
||||||
|
|
||||||
return account;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an account from the database by wid.
|
* Get an account from the database by wid.
|
||||||
* @private
|
* @private
|
||||||
@ -750,24 +710,14 @@ WalletDB.prototype.getAccount = co(function* getAccount(wid, acct) {
|
|||||||
* @returns {Promise} - Returns {@link Wallet}.
|
* @returns {Promise} - Returns {@link Wallet}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype._getAccount = co(function* getAccount(wid, index) {
|
WalletDB.prototype.getAccount = co(function* getAccount(wid, index) {
|
||||||
var key = wid + '/' + index;
|
var data = yield this.db.get(layout.a(wid, index));
|
||||||
var account = this.accountCache.get(key);
|
var account;
|
||||||
var data;
|
|
||||||
|
|
||||||
if (account)
|
|
||||||
return account;
|
|
||||||
|
|
||||||
data = yield this.db.get(layout.a(wid, index));
|
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
account = Account.fromRaw(this, data);
|
return Account.fromRaw(this, data);
|
||||||
|
|
||||||
this.accountCache.set(key, account);
|
|
||||||
|
|
||||||
return account;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -811,49 +761,12 @@ WalletDB.prototype.getAccounts = co(function* getAccounts(wid) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.getAccountIndex = co(function* getAccountIndex(wid, name) {
|
WalletDB.prototype.getAccountIndex = co(function* getAccountIndex(wid, name) {
|
||||||
var key, index;
|
var index = yield this.db.get(layout.i(wid, name));
|
||||||
|
|
||||||
if (!wid)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (name == null)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (typeof name === 'number')
|
|
||||||
return name;
|
|
||||||
|
|
||||||
key = wid + '/' + name;
|
|
||||||
index = this.indexCache.get(key);
|
|
||||||
|
|
||||||
if (index != null)
|
|
||||||
return index;
|
|
||||||
|
|
||||||
index = yield this.db.get(layout.i(wid, name));
|
|
||||||
|
|
||||||
if (!index)
|
if (!index)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
index = index.readUInt32LE(0, true);
|
return index.readUInt32LE(0, true);
|
||||||
|
|
||||||
this.indexCache.set(key, index);
|
|
||||||
|
|
||||||
return index;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lookup the corresponding account index's name.
|
|
||||||
* @param {WalletID} wid
|
|
||||||
* @param {Number} index - Account index.
|
|
||||||
* @returns {Promise} - Returns String.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getAccountName = co(function* getAccountName(wid, index) {
|
|
||||||
var account = yield this._getAccount(wid, index);
|
|
||||||
|
|
||||||
if (!account)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return account.name;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -864,10 +777,10 @@ WalletDB.prototype.getAccountName = co(function* getAccountName(wid, index) {
|
|||||||
|
|
||||||
WalletDB.prototype.saveAccount = function saveAccount(account) {
|
WalletDB.prototype.saveAccount = function saveAccount(account) {
|
||||||
var wid = account.wid;
|
var wid = account.wid;
|
||||||
|
var wallet = account.wallet;
|
||||||
var index = account.accountIndex;
|
var index = account.accountIndex;
|
||||||
var name = account.name;
|
var name = account.name;
|
||||||
var batch = this.batch(wid);
|
var batch = this.batch(account.wallet);
|
||||||
var key = wid + '/' + index;
|
|
||||||
var buf = new Buffer(4);
|
var buf = new Buffer(4);
|
||||||
|
|
||||||
buf.writeUInt32LE(index, 0, true);
|
buf.writeUInt32LE(index, 0, true);
|
||||||
@ -875,34 +788,9 @@ WalletDB.prototype.saveAccount = function saveAccount(account) {
|
|||||||
batch.put(layout.a(wid, index), account.toRaw());
|
batch.put(layout.a(wid, index), account.toRaw());
|
||||||
batch.put(layout.i(wid, name), buf);
|
batch.put(layout.i(wid, name), buf);
|
||||||
|
|
||||||
this.accountCache.set(key, account);
|
wallet.accountCache.set(index, account);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an account.
|
|
||||||
* @param {Object} options - See {@link Account} options.
|
|
||||||
* @returns {Promise} - Returns {@link Account}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.createAccount = co(function* createAccount(options) {
|
|
||||||
var exists = yield this.hasAccount(options.wid, options.name);
|
|
||||||
var account;
|
|
||||||
|
|
||||||
if (exists)
|
|
||||||
throw new Error('Account already exists.');
|
|
||||||
|
|
||||||
account = Account.fromOptions(this, options);
|
|
||||||
|
|
||||||
yield account.init();
|
|
||||||
|
|
||||||
this.logger.info('Created account %s/%s/%d.',
|
|
||||||
account.id,
|
|
||||||
account.name,
|
|
||||||
account.accountIndex);
|
|
||||||
|
|
||||||
return account;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for the existence of an account.
|
* Test for the existence of an account.
|
||||||
* @param {WalletID} wid
|
* @param {WalletID} wid
|
||||||
@ -910,22 +798,7 @@ WalletDB.prototype.createAccount = co(function* createAccount(options) {
|
|||||||
* @returns {Promise} - Returns Boolean.
|
* @returns {Promise} - Returns Boolean.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.hasAccount = co(function* hasAccount(wid, acct) {
|
WalletDB.prototype.hasAccount = co(function* hasAccount(wid, index) {
|
||||||
var index, key;
|
|
||||||
|
|
||||||
if (!wid)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
index = yield this.getAccountIndex(wid, acct);
|
|
||||||
|
|
||||||
if (index === -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
key = wid + '/' + index;
|
|
||||||
|
|
||||||
if (this.accountCache.has(key))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return yield this.db.has(layout.a(wid, index));
|
return yield this.db.has(layout.a(wid, index));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -962,8 +835,8 @@ WalletDB.prototype.getWalletsByHash = co(function* getWalletsByHash(hash) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.saveKey = function saveKey(wid, ring) {
|
WalletDB.prototype.saveKey = function saveKey(wallet, ring) {
|
||||||
return this.savePath(wid, ring.toPath());
|
return this.savePath(wallet, ring.toPath());
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -978,10 +851,10 @@ WalletDB.prototype.saveKey = function saveKey(wid, ring) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.savePath = co(function* savePath(wid, path) {
|
WalletDB.prototype.savePath = co(function* savePath(wallet, path) {
|
||||||
|
var wid = wallet.wid;
|
||||||
var hash = path.hash;
|
var hash = path.hash;
|
||||||
var batch = this.batch(wid);
|
var batch = this.batch(wallet);
|
||||||
var key = wid + hash;
|
|
||||||
var wallets;
|
var wallets;
|
||||||
|
|
||||||
if (this.filter)
|
if (this.filter)
|
||||||
@ -1000,7 +873,7 @@ WalletDB.prototype.savePath = co(function* savePath(wid, path) {
|
|||||||
wallets.push(wid);
|
wallets.push(wid);
|
||||||
|
|
||||||
this.pathMapCache.set(hash, wallets);
|
this.pathMapCache.set(hash, wallets);
|
||||||
this.pathCache.set(key, path);
|
wallet.pathCache.set(hash, path);
|
||||||
|
|
||||||
batch.put(layout.p(hash), serializeWallets(wallets));
|
batch.put(layout.p(hash), serializeWallets(wallets));
|
||||||
batch.put(layout.P(wid, hash), path.toRaw());
|
batch.put(layout.P(wid, hash), path.toRaw());
|
||||||
@ -1014,7 +887,7 @@ WalletDB.prototype.savePath = co(function* savePath(wid, path) {
|
|||||||
|
|
||||||
WalletDB.prototype.getPaths = co(function* getPaths(hash) {
|
WalletDB.prototype.getPaths = co(function* getPaths(hash) {
|
||||||
var wallets = yield this.getWalletsByHash(hash);
|
var wallets = yield this.getWalletsByHash(hash);
|
||||||
var i, wid, path, paths;
|
var i, wid, path, paths, wallet;
|
||||||
|
|
||||||
if (!wallets)
|
if (!wallets)
|
||||||
return;
|
return;
|
||||||
@ -1023,7 +896,13 @@ WalletDB.prototype.getPaths = co(function* getPaths(hash) {
|
|||||||
|
|
||||||
for (i = 0; i < wallets.length; i++) {
|
for (i = 0; i < wallets.length; i++) {
|
||||||
wid = wallets[i];
|
wid = wallets[i];
|
||||||
path = yield this.getPath(wid, hash);
|
wallet = yield this.get(wid);
|
||||||
|
|
||||||
|
if (!wallet)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
path = yield wallet.getPath(hash);
|
||||||
|
|
||||||
if (path)
|
if (path)
|
||||||
paths.push(path);
|
paths.push(path);
|
||||||
}
|
}
|
||||||
@ -1039,18 +918,7 @@ WalletDB.prototype.getPaths = co(function* getPaths(hash) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.getPath = co(function* getPath(wid, hash) {
|
WalletDB.prototype.getPath = co(function* getPath(wid, hash) {
|
||||||
var key, path, data;
|
var data = yield this.db.get(layout.P(wid, hash));
|
||||||
|
|
||||||
if (!hash)
|
|
||||||
return;
|
|
||||||
|
|
||||||
key = wid + hash;
|
|
||||||
path = this.pathCache.get(key);
|
|
||||||
|
|
||||||
if (path)
|
|
||||||
return path;
|
|
||||||
|
|
||||||
data = yield this.db.get(layout.P(wid, hash));
|
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return;
|
return;
|
||||||
@ -1058,26 +926,10 @@ WalletDB.prototype.getPath = co(function* getPath(wid, hash) {
|
|||||||
path = Path.fromRaw(data);
|
path = Path.fromRaw(data);
|
||||||
path.wid = wid;
|
path.wid = wid;
|
||||||
path.hash = hash;
|
path.hash = hash;
|
||||||
path.name = yield this.getAccountName(wid, path.account);
|
|
||||||
|
|
||||||
this.pathCache.set(key, path);
|
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether an address hash exists in the
|
|
||||||
* path map and is relevant to the wallet id.
|
|
||||||
* @param {WalletID} wid
|
|
||||||
* @param {Hash} hash
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.hasAddress = co(function* hasAddress(wid, hash) {
|
|
||||||
var path = yield this.getPath(wid, hash);
|
|
||||||
return path != null;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all address hashes.
|
* Get all address hashes.
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
@ -1126,7 +978,6 @@ WalletDB.prototype.getWalletPaths = co(function* getWalletPaths(wid) {
|
|||||||
|
|
||||||
path.hash = hash;
|
path.hash = hash;
|
||||||
path.wid = wid;
|
path.wid = wid;
|
||||||
path.name = yield this.getAccountName(wid, path.account);
|
|
||||||
|
|
||||||
items[i] = path;
|
items[i] = path;
|
||||||
}
|
}
|
||||||
@ -1153,9 +1004,10 @@ WalletDB.prototype.getWallets = function getWallets() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.encryptKeys = co(function* encryptKeys(wid, key) {
|
WalletDB.prototype.encryptKeys = co(function* encryptKeys(wallet, key) {
|
||||||
var paths = yield this.getWalletPaths(wid);
|
var wid = wallet.wid;
|
||||||
var batch = this.batch(wid);
|
var paths = yield wallet.getPaths();
|
||||||
|
var batch = this.batch(wallet);
|
||||||
var i, path, iv;
|
var i, path, iv;
|
||||||
|
|
||||||
for (i = 0; i < paths.length; i++) {
|
for (i = 0; i < paths.length; i++) {
|
||||||
@ -1166,7 +1018,7 @@ WalletDB.prototype.encryptKeys = co(function* encryptKeys(wid, key) {
|
|||||||
iv = iv.slice(0, 16);
|
iv = iv.slice(0, 16);
|
||||||
path.data = crypto.encipher(path.data, key, iv);
|
path.data = crypto.encipher(path.data, key, iv);
|
||||||
path.encrypted = true;
|
path.encrypted = true;
|
||||||
this.pathCache.set(wid + path.hash, path);
|
wallet.pathCache.set(path.hash, path);
|
||||||
batch.put(layout.P(wid, path.hash), path.toRaw());
|
batch.put(layout.P(wid, path.hash), path.toRaw());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1178,9 +1030,10 @@ WalletDB.prototype.encryptKeys = co(function* encryptKeys(wid, key) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.decryptKeys = co(function* decryptKeys(wid, key) {
|
WalletDB.prototype.decryptKeys = co(function* decryptKeys(wallet, key) {
|
||||||
var paths = yield this.getWalletPaths(wid);
|
var wid = wallet.wid;
|
||||||
var batch = this.batch(wid);
|
var paths = yield wallet.getPaths();
|
||||||
|
var batch = this.batch(wallet);
|
||||||
var i, path, iv;
|
var i, path, iv;
|
||||||
|
|
||||||
for (i = 0; i < paths.length; i++) {
|
for (i = 0; i < paths.length; i++) {
|
||||||
@ -1191,7 +1044,7 @@ WalletDB.prototype.decryptKeys = co(function* decryptKeys(wid, key) {
|
|||||||
iv = iv.slice(0, 16);
|
iv = iv.slice(0, 16);
|
||||||
path.data = crypto.decipher(path.data, key, iv);
|
path.data = crypto.decipher(path.data, key, iv);
|
||||||
path.encrypted = false;
|
path.encrypted = false;
|
||||||
this.pathCache.set(wid + path.hash, path);
|
wallet.pathCache.set(path.hash, path);
|
||||||
batch.put(layout.P(wid, path.hash), path.toRaw());
|
batch.put(layout.P(wid, path.hash), path.toRaw());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1317,17 +1170,67 @@ WalletDB.prototype.resend = co(function* resend() {
|
|||||||
|
|
||||||
WalletDB.prototype.mapWallets = co(function* mapWallets(tx) {
|
WalletDB.prototype.mapWallets = co(function* mapWallets(tx) {
|
||||||
var hashes = tx.getHashes('hex');
|
var hashes = tx.getHashes('hex');
|
||||||
var table;
|
var wallets = yield this.getWalletsByHashes(hashes);
|
||||||
|
var info = [];
|
||||||
|
var i, wallets, item;
|
||||||
|
|
||||||
if (!this.testFilter(hashes))
|
if (wallets.length === 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
table = yield this.getTable(hashes);
|
for (i = 0; i < wallets.length; i++) {
|
||||||
|
item = wallets[i];
|
||||||
|
info.push(new PathInfo(item.wallet, tx, item.matches));
|
||||||
|
}
|
||||||
|
|
||||||
if (!table)
|
return info;
|
||||||
return;
|
});
|
||||||
|
|
||||||
return PathInfo.map(this, tx, table);
|
/**
|
||||||
|
* Get all wallets by multiple address hashes.
|
||||||
|
* @param {Hash[]} hashes
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
WalletDB.prototype.getWalletsByHashes = co(function* getWalletsByHashes(hashes) {
|
||||||
|
var map = {};
|
||||||
|
var result = [];
|
||||||
|
var i, j, hash, wids, wid, wallet, item, path;
|
||||||
|
|
||||||
|
for (i = 0; i < hashes.length; i++) {
|
||||||
|
hash = hashes[i];
|
||||||
|
|
||||||
|
if (!this.testFilter(hash))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wids = yield this.getWalletsByHash(hash);
|
||||||
|
|
||||||
|
for (j = 0; j < wids.length; j++) {
|
||||||
|
wid = wids[j];
|
||||||
|
item = map[wid];
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
wallet = item.wallet;
|
||||||
|
path = yield wallet.getPath(hash);
|
||||||
|
assert(path);
|
||||||
|
item.matches.push(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wallet = yield this.get(wid);
|
||||||
|
assert(wallet);
|
||||||
|
|
||||||
|
path = yield wallet.getPath(hash);
|
||||||
|
assert(path);
|
||||||
|
|
||||||
|
item = new WalletMatch(wallet);
|
||||||
|
item.matches.push(path);
|
||||||
|
|
||||||
|
map[wid] = item;
|
||||||
|
result.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1338,46 +1241,22 @@ WalletDB.prototype.mapWallets = co(function* mapWallets(tx) {
|
|||||||
|
|
||||||
WalletDB.prototype.getPathInfo = co(function* getPathInfo(wallet, tx) {
|
WalletDB.prototype.getPathInfo = co(function* getPathInfo(wallet, tx) {
|
||||||
var hashes = tx.getHashes('hex');
|
var hashes = tx.getHashes('hex');
|
||||||
var table = yield this.getTable(hashes);
|
var paths = [];
|
||||||
var info;
|
var i, hash, path;
|
||||||
|
|
||||||
if (!table)
|
|
||||||
return;
|
|
||||||
|
|
||||||
info = new PathInfo(this, wallet.wid, tx, table);
|
|
||||||
info.id = wallet.id;
|
|
||||||
|
|
||||||
return info;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map address hashes to paths.
|
|
||||||
* @param {Hash[]} hashes - Address hashes.
|
|
||||||
* @returns {Promise} - Returns {@link AddressTable}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getTable = co(function* getTable(hashes) {
|
|
||||||
var table = {};
|
|
||||||
var match = false;
|
|
||||||
var i, hash, paths;
|
|
||||||
|
|
||||||
for (i = 0; i < hashes.length; i++) {
|
for (i = 0; i < hashes.length; i++) {
|
||||||
hash = hashes[i];
|
hash = hashes[i];
|
||||||
paths = yield this.getPaths(hash);
|
|
||||||
|
|
||||||
if (!paths) {
|
if (!this.testFilter(hash))
|
||||||
table[hash] = [];
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
table[hash] = paths;
|
path = yield wallet.getPath(hash);
|
||||||
match = true;
|
|
||||||
|
if (path)
|
||||||
|
paths.push(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!match)
|
return new PathInfo(wallet, tx, paths);
|
||||||
return;
|
|
||||||
|
|
||||||
return table;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1672,14 +1551,12 @@ WalletDB.prototype._addTX = co(function* addTX(tx, force) {
|
|||||||
|
|
||||||
for (i = 0; i < wallets.length; i++) {
|
for (i = 0; i < wallets.length; i++) {
|
||||||
info = wallets[i];
|
info = wallets[i];
|
||||||
wallet = yield this.get(info.wid);
|
wallet = info.wallet;
|
||||||
|
|
||||||
if (!wallet)
|
if (!wallet)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
this.logger.debug('Adding tx to wallet: %s', wallet.id);
|
this.logger.debug('Adding tx to wallet: %s', info.id);
|
||||||
|
|
||||||
info.id = wallet.id;
|
|
||||||
|
|
||||||
yield wallet.txdb.add(tx, info);
|
yield wallet.txdb.add(tx, info);
|
||||||
yield wallet.handleTX(info);
|
yield wallet.handleTX(info);
|
||||||
@ -1697,12 +1574,9 @@ WalletDB.prototype._addTX = co(function* addTX(tx, force) {
|
|||||||
* @param {Object} table
|
* @param {Object} table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function PathInfo(db, wid, tx, table) {
|
function PathInfo(wallet, tx, paths) {
|
||||||
if (!(this instanceof PathInfo))
|
if (!(this instanceof PathInfo))
|
||||||
return new PathInfo(db, wid, tx, table);
|
return new PathInfo(wallet, tx, paths);
|
||||||
|
|
||||||
// Reference to the walletdb.
|
|
||||||
this.db = db;
|
|
||||||
|
|
||||||
// All relevant Accounts for
|
// All relevant Accounts for
|
||||||
// inputs and outputs (for database indexing).
|
// inputs and outputs (for database indexing).
|
||||||
@ -1711,16 +1585,16 @@ function PathInfo(db, wid, tx, table) {
|
|||||||
// All output paths (for deriving during sync).
|
// All output paths (for deriving during sync).
|
||||||
this.paths = [];
|
this.paths = [];
|
||||||
|
|
||||||
|
// Wallet
|
||||||
|
this.wallet = wallet;
|
||||||
|
|
||||||
// Wallet ID
|
// Wallet ID
|
||||||
this.wid = wid;
|
this.wid = wallet.wid;
|
||||||
|
|
||||||
// Wallet Label (passed in by caller).
|
// Wallet Label
|
||||||
this.id = null;
|
this.id = wallet.id;
|
||||||
|
|
||||||
// Map of address hashes->paths (for everything).
|
// Map of address hashes->paths.
|
||||||
this.table = null;
|
|
||||||
|
|
||||||
// Map of address hashes->paths (specific to wallet).
|
|
||||||
this.pathMap = {};
|
this.pathMap = {};
|
||||||
|
|
||||||
// Current transaction.
|
// Current transaction.
|
||||||
@ -1731,47 +1605,9 @@ function PathInfo(db, wid, tx, table) {
|
|||||||
this._json = null;
|
this._json = null;
|
||||||
|
|
||||||
if (tx)
|
if (tx)
|
||||||
this.fromTX(tx, table);
|
this.fromTX(tx, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Map a transaction to multiple wallets.
|
|
||||||
* @param {WalletDB} db
|
|
||||||
* @param {TX} tx
|
|
||||||
* @param {Object} table
|
|
||||||
* @returns {PathInfo[]}
|
|
||||||
*/
|
|
||||||
|
|
||||||
PathInfo.map = function map(db, tx, table) {
|
|
||||||
var hashes = Object.keys(table);
|
|
||||||
var wallets = [];
|
|
||||||
var info = [];
|
|
||||||
var uniq = {};
|
|
||||||
var i, j, hash, paths, path, wid;
|
|
||||||
|
|
||||||
for (i = 0; i < hashes.length; i++) {
|
|
||||||
hash = hashes[i];
|
|
||||||
paths = table[hash];
|
|
||||||
for (j = 0; j < paths.length; j++) {
|
|
||||||
path = paths[j];
|
|
||||||
if (!uniq[path.wid]) {
|
|
||||||
uniq[path.wid] = true;
|
|
||||||
wallets.push(path.wid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wallets.length === 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < wallets.length; i++) {
|
|
||||||
wid = wallets[i];
|
|
||||||
info.push(new PathInfo(db, wid, tx, table));
|
|
||||||
}
|
|
||||||
|
|
||||||
return info;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate path info from a transaction.
|
* Instantiate path info from a transaction.
|
||||||
* @private
|
* @private
|
||||||
@ -1780,31 +1616,20 @@ PathInfo.map = function map(db, tx, table) {
|
|||||||
* @returns {PathInfo}
|
* @returns {PathInfo}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PathInfo.prototype.fromTX = function fromTX(tx, table) {
|
PathInfo.prototype.fromTX = function fromTX(tx, paths) {
|
||||||
var uniq = {};
|
var uniq = {};
|
||||||
var i, j, hashes, hash, paths, path;
|
var i, j, hashes, hash, paths, path;
|
||||||
|
|
||||||
this.tx = tx;
|
this.tx = tx;
|
||||||
this.table = table;
|
|
||||||
|
|
||||||
hashes = Object.keys(table);
|
for (i = 0; i < paths.length; i++) {
|
||||||
|
path = paths[i];
|
||||||
|
|
||||||
for (i = 0; i < hashes.length; i++) {
|
this.pathMap[path.hash] = path;
|
||||||
hash = hashes[i];
|
|
||||||
paths = table[hash];
|
|
||||||
|
|
||||||
for (j = 0; j < paths.length; j++) {
|
if (!uniq[path.account]) {
|
||||||
path = paths[j];
|
uniq[path.account] = true;
|
||||||
|
this.accounts.push(path.account);
|
||||||
if (path.wid !== this.wid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
this.pathMap[hash] = path;
|
|
||||||
|
|
||||||
if (!uniq[path.account]) {
|
|
||||||
uniq[path.account] = true;
|
|
||||||
this.accounts.push(path.account);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1812,16 +1637,8 @@ PathInfo.prototype.fromTX = function fromTX(tx, table) {
|
|||||||
|
|
||||||
for (i = 0; i < hashes.length; i++) {
|
for (i = 0; i < hashes.length; i++) {
|
||||||
hash = hashes[i];
|
hash = hashes[i];
|
||||||
paths = table[hash];
|
paths = this.pathMap[hash];
|
||||||
|
this.paths.push(path);
|
||||||
for (j = 0; j < paths.length; j++) {
|
|
||||||
path = paths[j];
|
|
||||||
|
|
||||||
if (path.wid !== this.wid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
this.paths.push(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@ -1836,8 +1653,8 @@ PathInfo.prototype.fromTX = function fromTX(tx, table) {
|
|||||||
* @returns {PathInfo}
|
* @returns {PathInfo}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PathInfo.fromTX = function fromTX(db, wid, tx, table) {
|
PathInfo.fromTX = function fromTX(wallet, tx, paths) {
|
||||||
return new PathInfo(db, wid).fromTX(tx, table);
|
return new PathInfo(wallet).fromTX(tx, paths);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1909,8 +1726,8 @@ function Details(info) {
|
|||||||
if (!(this instanceof Details))
|
if (!(this instanceof Details))
|
||||||
return new Details(info);
|
return new Details(info);
|
||||||
|
|
||||||
this.db = info.db;
|
this.db = info.wallet.db;
|
||||||
this.network = info.db.network;
|
this.network = this.db.network;
|
||||||
this.wid = info.wid;
|
this.wid = info.wid;
|
||||||
this.id = info.id;
|
this.id = info.id;
|
||||||
this.hash = info.tx.hash('hex');
|
this.hash = info.tx.hash('hex');
|
||||||
@ -1925,7 +1742,7 @@ function Details(info) {
|
|||||||
this.inputs = [];
|
this.inputs = [];
|
||||||
this.outputs = [];
|
this.outputs = [];
|
||||||
|
|
||||||
this.init(info.table);
|
this.init(info.pathMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1935,9 +1752,9 @@ function Details(info) {
|
|||||||
* @param {Object} table
|
* @param {Object} table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Details.prototype.init = function init(table) {
|
Details.prototype.init = function init(map) {
|
||||||
this._insert(this.tx.inputs, this.inputs, table);
|
this._insert(this.tx.inputs, true, this.inputs, map);
|
||||||
this._insert(this.tx.outputs, this.outputs, table);
|
this._insert(this.tx.outputs, false, this.outputs, map);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1948,17 +1765,19 @@ Details.prototype.init = function init(table) {
|
|||||||
* @param {Object} table
|
* @param {Object} table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Details.prototype._insert = function _insert(vector, target, table) {
|
Details.prototype._insert = function _insert(vector, input, target, map) {
|
||||||
var i, j, io, address, hash, paths, path, member;
|
var i, j, io, address, hash, paths, path, member;
|
||||||
|
|
||||||
for (i = 0; i < vector.length; i++) {
|
for (i = 0; i < vector.length; i++) {
|
||||||
io = vector[i];
|
io = vector[i];
|
||||||
member = new DetailsMember();
|
member = new DetailsMember();
|
||||||
|
|
||||||
if (io.prevout)
|
if (input) {
|
||||||
member.value = io.coin ? io.coin.value : 0;
|
if (io.coin)
|
||||||
else
|
member.value = io.coin.value;
|
||||||
|
} else {
|
||||||
member.value = io.value;
|
member.value = io.value;
|
||||||
|
}
|
||||||
|
|
||||||
address = io.getAddress();
|
address = io.getAddress();
|
||||||
|
|
||||||
@ -1966,16 +1785,10 @@ Details.prototype._insert = function _insert(vector, target, table) {
|
|||||||
member.address = address;
|
member.address = address;
|
||||||
|
|
||||||
hash = address.getHash('hex');
|
hash = address.getHash('hex');
|
||||||
paths = table[hash];
|
path = map[hash];
|
||||||
|
|
||||||
for (j = 0; j < paths.length; j++) {
|
if (path)
|
||||||
path = paths[j];
|
member.path = path;
|
||||||
if (path.wid === this.wid) {
|
|
||||||
path.id = this.id;
|
|
||||||
member.path = path;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
target.push(member);
|
target.push(member);
|
||||||
@ -2237,6 +2050,11 @@ function serializeInfo(wallets) {
|
|||||||
return p.render();
|
return p.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function WalletMatch(wallet) {
|
||||||
|
this.wallet = wallet;
|
||||||
|
this.matches = [];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user