ensure full atomicity in wallet.
This commit is contained in:
parent
850b16fa7d
commit
196f3ca861
@ -96,7 +96,7 @@ TXDB.prototype._lock = function _lock(func, args, force) {
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
TXDB.prototype._loadFilter = function loadFilter(callback) {
|
||||
TXDB.prototype.loadFilter = function loadFilter(callback) {
|
||||
var self = this;
|
||||
|
||||
if (!this.filter)
|
||||
@ -119,7 +119,7 @@ TXDB.prototype._loadFilter = function loadFilter(callback) {
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
TXDB.prototype._testFilter = function _testFilter(addresses) {
|
||||
TXDB.prototype.testFilter = function testFilter(addresses) {
|
||||
var i;
|
||||
|
||||
if (!this.filter)
|
||||
@ -143,7 +143,7 @@ TXDB.prototype.getMap = function getMap(tx, callback) {
|
||||
var addresses = tx.getHashes('hex');
|
||||
var map;
|
||||
|
||||
if (!this._testFilter(addresses))
|
||||
if (!this.testFilter(addresses))
|
||||
return callback();
|
||||
|
||||
this.mapAddresses(addresses, function(err, table) {
|
||||
@ -281,6 +281,34 @@ TXDB.prototype._getOrphans = function _getOrphans(key, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Write the genesis block as the best hash.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
TXDB.prototype.writeGenesis = function writeGenesis(callback) {
|
||||
var self = this;
|
||||
var unlock, hash;
|
||||
|
||||
unlock = this._lock(writeGenesis, [callback]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
self.db.has('R', function(err, result) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (result)
|
||||
return callback();
|
||||
|
||||
hash = new Buffer(self.network.genesis.hash, 'hex');
|
||||
self.db.put('R', hash, callback);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a block's transactions and write the new best hash.
|
||||
* @param {Block} block
|
||||
|
||||
@ -50,7 +50,8 @@ function Wallet(db, options) {
|
||||
|
||||
this.db = db;
|
||||
this.network = db.network;
|
||||
this.locker = new bcoin.locker(this);
|
||||
this.writeLock = new bcoin.locker(this);
|
||||
this.fillLock = new bcoin.locker(this);
|
||||
|
||||
this.id = null;
|
||||
this.master = null;
|
||||
@ -220,6 +221,7 @@ Wallet.prototype.destroy = function destroy(callback) {
|
||||
*/
|
||||
|
||||
Wallet.prototype.addKey = function addKey(account, key, callback) {
|
||||
var self = this;
|
||||
var unlock;
|
||||
|
||||
if (typeof key === 'function') {
|
||||
@ -228,7 +230,7 @@ Wallet.prototype.addKey = function addKey(account, key, callback) {
|
||||
account = 0;
|
||||
}
|
||||
|
||||
unlock = this.locker.lock(addKey, [account, key, callback]);
|
||||
unlock = this.writeLock.lock(addKey, [account, key, callback]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
@ -242,7 +244,19 @@ Wallet.prototype.addKey = function addKey(account, key, callback) {
|
||||
if (!account)
|
||||
return callback(new Error('Account not found.'));
|
||||
|
||||
account.addKey(key, callback);
|
||||
self.start();
|
||||
|
||||
account.addKey(key, function(err, result) {
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
}
|
||||
self.commit(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, result);
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
};
|
||||
|
||||
@ -254,6 +268,7 @@ Wallet.prototype.addKey = function addKey(account, key, callback) {
|
||||
*/
|
||||
|
||||
Wallet.prototype.removeKey = function removeKey(account, key, callback) {
|
||||
var self = this;
|
||||
var unlock;
|
||||
|
||||
if (typeof key === 'function') {
|
||||
@ -262,7 +277,7 @@ Wallet.prototype.removeKey = function removeKey(account, key, callback) {
|
||||
account = 0;
|
||||
}
|
||||
|
||||
unlock = this.locker.lock(removeKey, [account, key, callback]);
|
||||
unlock = this.writeLock.lock(removeKey, [account, key, callback]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
@ -276,7 +291,19 @@ Wallet.prototype.removeKey = function removeKey(account, key, callback) {
|
||||
if (!account)
|
||||
return callback(new Error('Account not found.'));
|
||||
|
||||
account.removeKey(key, callback);
|
||||
self.start();
|
||||
|
||||
account.removeKey(key, function(err, result) {
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
}
|
||||
self.commit(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, result);
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
};
|
||||
|
||||
@ -297,7 +324,7 @@ Wallet.prototype.setPassphrase = function setPassphrase(old, new_, callback) {
|
||||
old = null;
|
||||
}
|
||||
|
||||
unlock = this.locker.lock(setPassphrase, [old, new_, callback]);
|
||||
unlock = this.writeLock.lock(setPassphrase, [old, new_, callback]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
@ -312,7 +339,9 @@ Wallet.prototype.setPassphrase = function setPassphrase(old, new_, callback) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return self.save(callback);
|
||||
self.start();
|
||||
self.save();
|
||||
self.commit(callback);
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -332,7 +361,7 @@ Wallet.prototype.retoken = function retoken(passphrase, callback) {
|
||||
passphrase = null;
|
||||
}
|
||||
|
||||
unlock = this.locker.lock(retoken, [passphrase, callback]);
|
||||
unlock = this.writeLock.lock(retoken, [passphrase, callback]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
@ -346,7 +375,9 @@ Wallet.prototype.retoken = function retoken(passphrase, callback) {
|
||||
self.tokenDepth++;
|
||||
self.token = self.getToken(master, self.tokenDepth);
|
||||
|
||||
self.save(function(err) {
|
||||
self.start();
|
||||
self.save();
|
||||
self.commit(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, self.token);
|
||||
@ -431,7 +462,7 @@ Wallet.prototype.createAccount = function createAccount(options, callback, force
|
||||
var self = this;
|
||||
var key, unlock;
|
||||
|
||||
unlock = this.locker.lock(createAccount, [options, callback], force);
|
||||
unlock = this.writeLock.lock(createAccount, [options, callback], force);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
@ -457,13 +488,17 @@ Wallet.prototype.createAccount = function createAccount(options, callback, force
|
||||
n: options.n
|
||||
};
|
||||
|
||||
self.start();
|
||||
|
||||
self.db.createAccount(options, function(err, account) {
|
||||
if (err)
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
self.accountDepth++;
|
||||
|
||||
self.save(function(err) {
|
||||
self.save();
|
||||
self.commit(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, account);
|
||||
@ -487,14 +522,7 @@ Wallet.prototype.getAccounts = function getAccounts(callback) {
|
||||
* @param {Function} callback - Returns [Error, {@link Account}].
|
||||
*/
|
||||
|
||||
Wallet.prototype.getAccount = function getAccount(account, callback, force) {
|
||||
var unlock = this.locker.lock(getAccount, [account, callback], force);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
Wallet.prototype.getAccount = function getAccount(account, callback) {
|
||||
if (this.account) {
|
||||
if (account === 0 || account === 'default')
|
||||
return callback(null, this.account);
|
||||
@ -547,7 +575,7 @@ Wallet.prototype.createAddress = function createAddress(account, change, callbac
|
||||
account = 0;
|
||||
}
|
||||
|
||||
unlock = this.locker.lock(createAddress, [account, change, callback]);
|
||||
unlock = this.writeLock.lock(createAddress, [account, change, callback]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
@ -561,7 +589,19 @@ Wallet.prototype.createAddress = function createAddress(account, change, callbac
|
||||
if (!account)
|
||||
return callback(new Error('Account not found.'));
|
||||
|
||||
account.createAddress(change, callback);
|
||||
self.start();
|
||||
|
||||
account.createAddress(change, function(err, result) {
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
}
|
||||
self.commit(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, result);
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
};
|
||||
|
||||
@ -571,8 +611,35 @@ Wallet.prototype.createAddress = function createAddress(account, change, callbac
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Wallet.prototype.save = function save(callback) {
|
||||
return this.db.save(this, callback);
|
||||
Wallet.prototype.save = function save() {
|
||||
return this.db.save(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Start batch.
|
||||
* @private
|
||||
*/
|
||||
|
||||
Wallet.prototype.start = function start() {
|
||||
return this.db.start(this.id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Drop batch.
|
||||
* @private
|
||||
*/
|
||||
|
||||
Wallet.prototype.drop = function drop() {
|
||||
return this.db.drop(this.id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Save batch.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Wallet.prototype.commit = function commit(callback) {
|
||||
return this.db.commit(this.id, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -620,7 +687,7 @@ Wallet.prototype.getPath = function getPath(address, callback) {
|
||||
|
||||
Wallet.prototype.fill = function fill(tx, options, callback) {
|
||||
var self = this;
|
||||
var rate;
|
||||
var unlock, rate;
|
||||
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
@ -630,6 +697,15 @@ Wallet.prototype.fill = function fill(tx, options, callback) {
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
// We use a lock here to ensure we
|
||||
// don't end up double spending coins.
|
||||
unlock = this.fillLock.lock(fill, [tx, options, callback]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
|
||||
callback = utils.wrap(callback, unlock);
|
||||
|
||||
if (!this.initialized)
|
||||
return callback(new Error('Wallet is not initialized.'));
|
||||
|
||||
@ -920,7 +996,7 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(tx, callback) {
|
||||
var receive = [];
|
||||
var i, path, unlock;
|
||||
|
||||
unlock = this.locker.lock(syncOutputDepth, [tx, callback]);
|
||||
unlock = this.writeLock.lock(syncOutputDepth, [tx, callback]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
@ -940,6 +1016,8 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(tx, callback) {
|
||||
accounts[path.account].push(path);
|
||||
}
|
||||
|
||||
self.start();
|
||||
|
||||
utils.forEachSerial(Object.keys(accounts), function(index, next) {
|
||||
var paths = accounts[index];
|
||||
var receiveDepth = -1;
|
||||
@ -979,12 +1057,18 @@ Wallet.prototype.syncOutputDepth = function syncOutputDepth(tx, callback) {
|
||||
|
||||
next();
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
return callback(null, receive, change);
|
||||
self.commit(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, receive, change);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -1049,7 +1133,7 @@ Wallet.prototype.scan = function scan(maxGap, scanner, callback) {
|
||||
maxGap = null;
|
||||
}
|
||||
|
||||
unlock = this.locker.lock(scan, [maxGap, scanner, callback]);
|
||||
unlock = this.writeLock.lock(scan, [maxGap, scanner, callback]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
@ -1059,17 +1143,31 @@ Wallet.prototype.scan = function scan(maxGap, scanner, callback) {
|
||||
if (!this.initialized)
|
||||
return callback(new Error('Wallet is not initialized.'));
|
||||
|
||||
self.start();
|
||||
|
||||
function done(err, total) {
|
||||
if (err) {
|
||||
self.drop();
|
||||
return callback(err);
|
||||
}
|
||||
self.commit(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, total);
|
||||
});
|
||||
}
|
||||
|
||||
(function next() {
|
||||
self.getAccount(index++, function(err, account) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return done(err);
|
||||
|
||||
if (!account)
|
||||
return callback(null, total);
|
||||
return done(null, total);
|
||||
|
||||
account.scan(maxGap, scanner, function(err, result) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return done(err);
|
||||
|
||||
total += result;
|
||||
|
||||
@ -1829,7 +1927,8 @@ Account.prototype.init = function init(callback) {
|
||||
// Waiting for more keys.
|
||||
if (this.keys.length !== this.n) {
|
||||
assert(!this.initialized);
|
||||
return this.save(callback);
|
||||
this.save();
|
||||
return callback();
|
||||
}
|
||||
|
||||
assert(this.receiveDepth === 0);
|
||||
@ -1870,14 +1969,6 @@ Account.prototype.pushKey = function pushKey(key) {
|
||||
|
||||
assert(key, 'Key required.');
|
||||
|
||||
if (Array.isArray(key)) {
|
||||
for (i = 0; i < key.length; i++) {
|
||||
if (this.pushKey(key[i]))
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (key.accountKey)
|
||||
key = key.accountKey;
|
||||
|
||||
@ -1924,14 +2015,6 @@ Account.prototype.spliceKey = function spliceKey(key) {
|
||||
var index = -1;
|
||||
var i;
|
||||
|
||||
if (Array.isArray(key)) {
|
||||
for (i = 0; i < key.length; i++) {
|
||||
if (this.spliceKey(key[i]))
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
assert(key, 'Key required.');
|
||||
|
||||
if (key.accountKey)
|
||||
@ -1976,12 +2059,11 @@ Account.prototype.spliceKey = function spliceKey(key) {
|
||||
|
||||
Account.prototype.addKey = function addKey(key, callback) {
|
||||
var result = false;
|
||||
var error;
|
||||
|
||||
try {
|
||||
result = this.pushKey(key);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
// Try to initialize again.
|
||||
@ -1989,9 +2071,6 @@ Account.prototype.addKey = function addKey(key, callback) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (error)
|
||||
return callback(error);
|
||||
|
||||
return callback(null, result);
|
||||
});
|
||||
};
|
||||
@ -2005,23 +2084,16 @@ Account.prototype.addKey = function addKey(key, callback) {
|
||||
|
||||
Account.prototype.removeKey = function removeKey(key, callback) {
|
||||
var result = false;
|
||||
var error;
|
||||
|
||||
try {
|
||||
result = this.spliceKey(key);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
this.save(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
this.save();
|
||||
|
||||
if (error)
|
||||
return callback(error);
|
||||
|
||||
return callback(null, result);
|
||||
});
|
||||
return callback(null, result);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2076,11 +2148,9 @@ Account.prototype.createAddress = function createAddress(change, callback) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.save(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, address);
|
||||
});
|
||||
self.save();
|
||||
|
||||
return callback(null, address);
|
||||
});
|
||||
};
|
||||
|
||||
@ -2149,8 +2219,8 @@ Account.prototype.deriveAddress = function deriveAddress(change, index) {
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Account.prototype.save = function save(callback) {
|
||||
return this.db.saveAccount(this, callback);
|
||||
Account.prototype.save = function save() {
|
||||
return this.db.saveAccount(this);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2209,12 +2279,9 @@ Account.prototype.setDepth = function setDepth(receiveDepth, changeDepth, callba
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.save(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.save();
|
||||
|
||||
return callback(null, receive, change);
|
||||
});
|
||||
return callback(null, receive, change);
|
||||
});
|
||||
};
|
||||
|
||||
@ -2284,6 +2351,7 @@ Account.prototype.scan = function scan(maxGap, scanner, callback) {
|
||||
if (maxGap === 0 && index === depth) {
|
||||
if (!change)
|
||||
return chainCheck(true);
|
||||
self.save();
|
||||
return callback(null, total);
|
||||
}
|
||||
|
||||
@ -2305,11 +2373,7 @@ Account.prototype.scan = function scan(maxGap, scanner, callback) {
|
||||
self.changeDepth = Math.max(depth, self.changeDepth - gap);
|
||||
self.changeAddress = self.deriveChange(self.changeDepth - 1);
|
||||
|
||||
self.save(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, total);
|
||||
});
|
||||
return callback(null, total);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -50,13 +50,14 @@ function WalletDB(options) {
|
||||
this.network = bcoin.network.get(options.network);
|
||||
this.fees = options.fees;
|
||||
this.logger = options.logger || bcoin.defaultLogger;
|
||||
this.batches = {};
|
||||
|
||||
// We need one read lock for `get` and `create`.
|
||||
// It will hold locks specific to wallet ids.
|
||||
this.readLock = new ReadLock(this);
|
||||
|
||||
this.accountCache = new bcoin.lru(10000, 1);
|
||||
this.walletCache = new bcoin.lru(10000, 1);
|
||||
this.accountCache = new bcoin.lru(10000, 1);
|
||||
this.pathCache = new bcoin.lru(100000, 1);
|
||||
|
||||
this.db = bcoin.ldb({
|
||||
@ -139,7 +140,12 @@ WalletDB.prototype._open = function open(callback) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.tx._loadFilter(callback);
|
||||
self.tx.writeGenesis(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.tx.loadFilter(callback);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -176,6 +182,58 @@ WalletDB.prototype._lock = function lock(id, func, args, force) {
|
||||
return this.readLock.lock(id, func, args, force);
|
||||
};
|
||||
|
||||
/**
|
||||
* Start batch.
|
||||
* @private
|
||||
* @param {WalletID} id
|
||||
*/
|
||||
|
||||
WalletDB.prototype.start = function start(id) {
|
||||
assert(utils.isAlpha(id), 'Bad ID for batch.');
|
||||
assert(!this.batches[id], 'Batch already started.');
|
||||
this.batches[id] = this.db.batch();
|
||||
};
|
||||
|
||||
/**
|
||||
* Drop batch.
|
||||
* @private
|
||||
* @param {WalletID} id
|
||||
*/
|
||||
|
||||
WalletDB.prototype.drop = function drop(id) {
|
||||
var batch = this.batch(id);
|
||||
batch.clear();
|
||||
delete this.batches[id];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get batch.
|
||||
* @private
|
||||
* @param {WalletID} id
|
||||
* @returns {Leveldown.Batch}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.batch = function batch(id) {
|
||||
var batch;
|
||||
assert(utils.isAlpha(id), 'Bad ID for batch.');
|
||||
batch = this.batches[id];
|
||||
assert(batch, 'Batch does not exist.');
|
||||
return batch;
|
||||
};
|
||||
|
||||
/**
|
||||
* Save batch.
|
||||
* @private
|
||||
* @param {WalletID} id
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
WalletDB.prototype.commit = function commit(id, callback) {
|
||||
var batch = this.batch(id);
|
||||
delete this.batches[id];
|
||||
batch.write(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Emit balance events after a tx is saved.
|
||||
* @private
|
||||
@ -495,13 +553,10 @@ WalletDB.prototype._get = function get(id, callback) {
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
WalletDB.prototype.save = function save(wallet, callback) {
|
||||
if (!utils.isAlpha(wallet.id))
|
||||
return callback(new Error('Wallet IDs must be alphanumeric.'));
|
||||
|
||||
WalletDB.prototype.save = function save(wallet) {
|
||||
var batch = this.batch(wallet.id);
|
||||
this.walletCache.set(wallet.id, wallet);
|
||||
|
||||
this.db.put('w/' + wallet.id, wallet.toRaw(), callback);
|
||||
batch.put('w/' + wallet.id, wallet.toRaw());
|
||||
};
|
||||
|
||||
/**
|
||||
@ -770,25 +825,17 @@ WalletDB.prototype.getAccountIndex = function getAccountIndex(id, name, callback
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
WalletDB.prototype.saveAccount = function saveAccount(account, callback) {
|
||||
var index, key, batch;
|
||||
WalletDB.prototype.saveAccount = function saveAccount(account) {
|
||||
var batch = this.batch(account.id);
|
||||
var index = new Buffer(4);
|
||||
var key = account.id + '/' + account.accountIndex;
|
||||
|
||||
if (!utils.isAlpha(account.name))
|
||||
return callback(new Error('Account names must be alphanumeric.'));
|
||||
|
||||
batch = this.db.batch();
|
||||
|
||||
index = new Buffer(4);
|
||||
index.writeUInt32LE(account.accountIndex, 0, true);
|
||||
|
||||
key = account.id + '/' + account.accountIndex;
|
||||
|
||||
batch.put('a/' + key, account.toRaw());
|
||||
batch.put('i/' + account.id + '/' + account.name, index);
|
||||
|
||||
this.accountCache.set(key, account);
|
||||
|
||||
batch.write(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -863,7 +910,7 @@ WalletDB.prototype.hasAccount = function hasAccount(id, account, callback) {
|
||||
WalletDB.prototype.saveAddress = function saveAddress(id, addresses, callback) {
|
||||
var self = this;
|
||||
var items = [];
|
||||
var batch = this.db.batch();
|
||||
var batch = this.batch(id);
|
||||
var i, address, path;
|
||||
|
||||
if (!Array.isArray(addresses))
|
||||
@ -910,12 +957,7 @@ WalletDB.prototype.saveAddress = function saveAddress(id, addresses, callback) {
|
||||
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
batch.write(callback);
|
||||
});
|
||||
}, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user