walletdb: fixes.

This commit is contained in:
Christopher Jeffrey 2016-08-15 05:53:02 -07:00
parent 17b176141e
commit cfad740b09
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 73 additions and 66 deletions

View File

@ -956,7 +956,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
if (this.depth >= 0xff)
throw new Error('Depth too high.');
id = this.xprivkey + '/' + index;
id = this.getID(index);
child = HD.cache.get(id);
if (child)
@ -1002,6 +1002,19 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
return child;
};
/**
* Unique HD key ID.
* @private
* @param {Number} index
* @returns {String}
*/
HDPrivateKey.prototype.getID = function getID(index) {
return this.network.keyPrefix.xprivkey58
+ this.publicKey.toString('hex')
+ '/' + index;
};
/**
* Derive a BIP44 account key.
* @param {Number} accountIndex
@ -1603,7 +1616,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
if (this.depth >= 0xff)
throw new Error('Depth too high.');
id = this.xpubkey + '/' + index;
id = this.getID(index);
child = HD.cache.get(id);
if (child)
@ -1640,6 +1653,19 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
return child;
};
/**
* Unique HD key ID.
* @private
* @param {Number} index
* @returns {String}
*/
HDPublicKey.prototype.getID = function getID(index) {
return this.network.keyPrefix.xpubkey58
+ this.publicKey.toString('hex')
+ '/' + index;
};
/**
* Derive a BIP44 account key (does not derive, only ensures account key).
* @method

View File

@ -1493,7 +1493,7 @@ Wallet.prototype.addTX = function addTX(tx, callback) {
*/
Wallet.prototype.getHistory = function getHistory(account, callback) {
this._getKey(account, callback, function(account, callback) {
this._getIndex(account, callback, function(account, callback) {
this.tx.getHistory(account, callback);
});
};
@ -1505,7 +1505,7 @@ Wallet.prototype.getHistory = function getHistory(account, callback) {
*/
Wallet.prototype.getCoins = function getCoins(account, callback) {
this._getKey(account, callback, function(account, callback) {
this._getIndex(account, callback, function(account, callback) {
this.tx.getCoins(account, callback);
});
};
@ -1517,7 +1517,7 @@ Wallet.prototype.getCoins = function getCoins(account, callback) {
*/
Wallet.prototype.getUnconfirmed = function getUnconfirmed(account, callback) {
this._getKey(account, callback, function(account, callback) {
this._getIndex(account, callback, function(account, callback) {
this.tx.getUnconfirmed(account, callback);
});
};
@ -1529,7 +1529,7 @@ Wallet.prototype.getUnconfirmed = function getUnconfirmed(account, callback) {
*/
Wallet.prototype.getBalance = function getBalance(account, callback) {
this._getKey(account, callback, function(account, callback) {
this._getIndex(account, callback, function(account, callback) {
this.tx.getBalance(account, callback);
});
};
@ -1543,7 +1543,7 @@ Wallet.prototype.getBalance = function getBalance(account, callback) {
*/
Wallet.prototype.getLastTime = function getLastTime(account, callback) {
this._getKey(account, callback, function(account, callback) {
this._getIndex(account, callback, function(account, callback) {
this.tx.getLastTime(account, callback);
});
};
@ -1561,7 +1561,7 @@ Wallet.prototype.getLast = function getLast(account, limit, callback) {
limit = account;
account = null;
}
this._getKey(account, callback, function(account, callback) {
this._getIndex(account, callback, function(account, callback) {
this.tx.getLast(account, limit, callback);
});
};
@ -1581,7 +1581,7 @@ Wallet.prototype.getTimeRange = function getTimeRange(account, options, callback
options = account;
account = null;
}
this._getKey(account, callback, function(account, callback) {
this._getIndex(account, callback, function(account, callback) {
this.tx.getTimeRange(account, options, callback);
});
};
@ -1599,7 +1599,7 @@ Wallet.prototype.zap = function zap(account, age, callback) {
age = account;
account = null;
}
this._getKey(account, callback, function(account, callback) {
this._getIndex(account, callback, function(account, callback) {
this.tx.zap(account, age, callback);
});
};
@ -1610,15 +1610,8 @@ Wallet.prototype.zap = function zap(account, age, callback) {
* @param {Function} callback - Returns [Error].
*/
Wallet.prototype.abandon = function abandon(account, hash, callback) {
if (typeof hash === 'function') {
callback = hash;
hash = account;
account = null;
}
this._getKey(account, callback, function(account, callback) {
this.tx.abandon(account, hash, callback);
});
Wallet.prototype.abandon = function abandon(hash, callback) {
this.tx.abandon(hash, callback);
};
/**
@ -1629,7 +1622,7 @@ Wallet.prototype.abandon = function abandon(account, hash, callback) {
* @param {Function} callback
*/
Wallet.prototype._getKey = function _getKey(account, errback, callback) {
Wallet.prototype._getIndex = function _getIndex(account, errback, callback) {
var self = this;
if (typeof account === 'function') {
@ -2715,9 +2708,6 @@ Account.prototype.toRaw = function toRaw(writer) {
var i;
p.writeU32(this.network.magic);
// NOTE: Passed in by caller.
// p.writeU32(this.wid);
// p.writeVarString(this.id, 'utf8');
p.writeVarString(this.name, 'utf8');
p.writeU8(this.initialized ? 1 : 0);
p.writeU8(this.type === 'pubkeyhash' ? 0 : 1);
@ -2751,9 +2741,6 @@ Account.prototype.fromRaw = function fromRaw(data) {
var i, count;
this.network = bcoin.network.fromMagic(p.readU32());
// NOTE: Passed in by caller.
// this.wid = p.readU32();
// this.id = p.readVarString('utf8');
this.name = p.readVarString('utf8');
this.initialized = p.readU8() === 1;
this.type = p.readU8() === 0 ? 'pubkeyhash' : 'multisig';
@ -3039,8 +3026,9 @@ MasterKey.prototype.encrypt = function encrypt(passphrase, callback) {
if (!passphrase)
return callback();
iv = bcoin.ec.random(16);
data = this.key.toExtended();
iv = bcoin.ec.random(16);
this.stop();
utils.encrypt(data, passphrase, iv, function(err, data) {

View File

@ -9,15 +9,15 @@
/*
* Database Layout:
* (inherits all from txdb)
* p/[address] -> wid & path data
* p/[address] -> path data
* w/[wid] -> wallet
* l/[label] -> wallet wid
* l/[id] -> wid
* a/[wid]/[index] -> account
* i/[wid]/[name] -> account index
* t/[wid]/* -> txdb
* R -> tip
* b/[hash] -> wallet block
* t/[hash] -> tx->wallet-wid map
* t/[hash] -> tx->wid map
*/
var bcoin = require('./env');
@ -186,7 +186,7 @@ WalletDB.prototype.getDepth = function getDepth(callback) {
// This may seem like a strange way to do
// this, but updating a global state when
// creating a new wallet is actually pretty
// damn tricky. They would be major atomicity
// damn tricky. There would be major atomicity
// issues if updating a global state inside
// a "scoped" state. So, we avoid all the
// nonsense of adding a global lock to
@ -290,8 +290,8 @@ WalletDB.prototype.loadFilter = function loadFilter(callback) {
return callback();
this.db.iterate({
gte: 'W',
lte: 'W~',
gte: 'p/' + constants.NULL_HASH,
lte: 'p/' + constants.HIGH_HASH,
transform: function(key) {
key = key.split('/')[1];
self.filter.add(key, 'hex');
@ -563,12 +563,12 @@ WalletDB.prototype.create = function create(options, callback) {
/**
* Test for the existence of a wallet.
* @param {WalletID?} wid
* @param {WalletID} id
* @param {Function} callback
*/
WalletDB.prototype.has = function has(wid, callback) {
this.getWalletID(wid, function(err, wid) {
WalletDB.prototype.has = function has(id, callback) {
this.getWalletID(id, function(err, wid) {
if (err)
return callback(err);
return callback(null, wid != null);
@ -577,7 +577,6 @@ WalletDB.prototype.has = function has(wid, callback) {
/**
* Attempt to create wallet, return wallet if already exists.
* @param {WalletID?} wid
* @param {Object} options - See {@link Wallet}.
* @param {Function} callback
*/
@ -663,9 +662,6 @@ WalletDB.prototype.getAccounts = function getAccounts(wid, callback) {
var map = [];
var i, accounts;
if (!utils.isNumber(wid))
return callback(new Error('Wallet IDs must be alphanumeric.'));
this.db.iterate({
gte: 'i/' + pad32(wid) + '/',
lte: 'i/' + pad32(wid) + '/~',
@ -944,8 +940,8 @@ WalletDB.prototype.getAddresses = function getAddresses(wid, callback) {
}
this.db.iterate({
gte: 'W',
lte: 'W~',
gte: 'p/' + constants.NULL_HASH,
lte: 'p/' + constants.HIGH_HASH,
values: true,
parse: function(value, key) {
var paths = parsePaths(value);
@ -965,8 +961,8 @@ WalletDB.prototype.getAddresses = function getAddresses(wid, callback) {
WalletDB.prototype.getWallets = function getWallets(callback) {
this.db.iterate({
gte: 'w',
lte: 'w~',
gte: 'l/',
lte: 'l/~',
transform: function(key) {
return key.split('/')[1];
}
@ -1194,15 +1190,7 @@ WalletDB.prototype.writeBlock = function writeBlock(block, matches, callback) {
}
}
batch.write(function(err) {
if (err)
return callback(err);
self.tip = block.hash;
self.height = block.height;
return callback();
});
batch.write(callback);
};
/**
@ -1219,15 +1207,7 @@ WalletDB.prototype.unwriteBlock = function unwriteBlock(block, callback) {
batch.put('R', prev.toTip());
batch.del('b/' + block.hash);
batch.write(function(err) {
if (err)
return callback(err);
self.tip = prev.hash;
self.height = prev.height;
return callback();
});
batch.write(callback);
};
/**
@ -1277,6 +1257,11 @@ WalletDB.prototype.addBlock = function addBlock(entry, txs, callback, force) {
block = WalletBlock.fromEntry(entry);
matches = [];
// Update these early so transactions
// get correct confirmation calculations.
this.tip = block.hash;
this.height = block.height;
// NOTE: Atomicity doesn't matter here. If we crash
// during this loop, the automatic rescan will get
// the database back into the correct state.
@ -1359,7 +1344,15 @@ WalletDB.prototype.removeBlock = function removeBlock(entry, callback, force) {
wallet.tx.unconfirm(hash, next);
});
}, callback);
}, function(err) {
if (err)
return callback(err);
self.tip = block.hash;
self.height = block.height;
return callback();
});
});
});
});

View File

@ -222,8 +222,8 @@ describe('Chain', function() {
var txs = [];
walletdb.getAddresses(function(err, hashes) {
assert.ifError(err);
chain.db.scan(null, hashes, function(tx, block, next) {
txs.push(tx);
chain.db.scan(null, hashes, function(block, tx, next) {
txs = txs.concat(tx);
next();
}, function(err) {
assert.ifError(err);