walletdb: fixes.
This commit is contained in:
parent
17b176141e
commit
cfad740b09
@ -956,7 +956,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
|||||||
if (this.depth >= 0xff)
|
if (this.depth >= 0xff)
|
||||||
throw new Error('Depth too high.');
|
throw new Error('Depth too high.');
|
||||||
|
|
||||||
id = this.xprivkey + '/' + index;
|
id = this.getID(index);
|
||||||
child = HD.cache.get(id);
|
child = HD.cache.get(id);
|
||||||
|
|
||||||
if (child)
|
if (child)
|
||||||
@ -1002,6 +1002,19 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
|||||||
return child;
|
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.
|
* Derive a BIP44 account key.
|
||||||
* @param {Number} accountIndex
|
* @param {Number} accountIndex
|
||||||
@ -1603,7 +1616,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
|
|||||||
if (this.depth >= 0xff)
|
if (this.depth >= 0xff)
|
||||||
throw new Error('Depth too high.');
|
throw new Error('Depth too high.');
|
||||||
|
|
||||||
id = this.xpubkey + '/' + index;
|
id = this.getID(index);
|
||||||
child = HD.cache.get(id);
|
child = HD.cache.get(id);
|
||||||
|
|
||||||
if (child)
|
if (child)
|
||||||
@ -1640,6 +1653,19 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
|
|||||||
return child;
|
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).
|
* Derive a BIP44 account key (does not derive, only ensures account key).
|
||||||
* @method
|
* @method
|
||||||
|
|||||||
@ -1493,7 +1493,7 @@ Wallet.prototype.addTX = function addTX(tx, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.getHistory = function getHistory(account, 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);
|
this.tx.getHistory(account, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1505,7 +1505,7 @@ Wallet.prototype.getHistory = function getHistory(account, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.getCoins = function getCoins(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);
|
this.tx.getCoins(account, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1517,7 +1517,7 @@ Wallet.prototype.getCoins = function getCoins(account, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.getUnconfirmed = function getUnconfirmed(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);
|
this.tx.getUnconfirmed(account, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1529,7 +1529,7 @@ Wallet.prototype.getUnconfirmed = function getUnconfirmed(account, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.getBalance = function getBalance(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);
|
this.tx.getBalance(account, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1543,7 +1543,7 @@ Wallet.prototype.getBalance = function getBalance(account, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.getLastTime = function getLastTime(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);
|
this.tx.getLastTime(account, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1561,7 +1561,7 @@ Wallet.prototype.getLast = function getLast(account, limit, callback) {
|
|||||||
limit = account;
|
limit = account;
|
||||||
account = null;
|
account = null;
|
||||||
}
|
}
|
||||||
this._getKey(account, callback, function(account, callback) {
|
this._getIndex(account, callback, function(account, callback) {
|
||||||
this.tx.getLast(account, limit, callback);
|
this.tx.getLast(account, limit, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1581,7 +1581,7 @@ Wallet.prototype.getTimeRange = function getTimeRange(account, options, callback
|
|||||||
options = account;
|
options = account;
|
||||||
account = null;
|
account = null;
|
||||||
}
|
}
|
||||||
this._getKey(account, callback, function(account, callback) {
|
this._getIndex(account, callback, function(account, callback) {
|
||||||
this.tx.getTimeRange(account, options, callback);
|
this.tx.getTimeRange(account, options, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1599,7 +1599,7 @@ Wallet.prototype.zap = function zap(account, age, callback) {
|
|||||||
age = account;
|
age = account;
|
||||||
account = null;
|
account = null;
|
||||||
}
|
}
|
||||||
this._getKey(account, callback, function(account, callback) {
|
this._getIndex(account, callback, function(account, callback) {
|
||||||
this.tx.zap(account, age, callback);
|
this.tx.zap(account, age, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1610,15 +1610,8 @@ Wallet.prototype.zap = function zap(account, age, callback) {
|
|||||||
* @param {Function} callback - Returns [Error].
|
* @param {Function} callback - Returns [Error].
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.abandon = function abandon(account, hash, callback) {
|
Wallet.prototype.abandon = function abandon(hash, callback) {
|
||||||
if (typeof hash === 'function') {
|
this.tx.abandon(hash, callback);
|
||||||
callback = hash;
|
|
||||||
hash = account;
|
|
||||||
account = null;
|
|
||||||
}
|
|
||||||
this._getKey(account, callback, function(account, callback) {
|
|
||||||
this.tx.abandon(account, hash, callback);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1629,7 +1622,7 @@ Wallet.prototype.abandon = function abandon(account, hash, callback) {
|
|||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype._getKey = function _getKey(account, errback, callback) {
|
Wallet.prototype._getIndex = function _getIndex(account, errback, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (typeof account === 'function') {
|
if (typeof account === 'function') {
|
||||||
@ -2715,9 +2708,6 @@ Account.prototype.toRaw = function toRaw(writer) {
|
|||||||
var i;
|
var i;
|
||||||
|
|
||||||
p.writeU32(this.network.magic);
|
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.writeVarString(this.name, 'utf8');
|
||||||
p.writeU8(this.initialized ? 1 : 0);
|
p.writeU8(this.initialized ? 1 : 0);
|
||||||
p.writeU8(this.type === 'pubkeyhash' ? 0 : 1);
|
p.writeU8(this.type === 'pubkeyhash' ? 0 : 1);
|
||||||
@ -2751,9 +2741,6 @@ Account.prototype.fromRaw = function fromRaw(data) {
|
|||||||
var i, count;
|
var i, count;
|
||||||
|
|
||||||
this.network = bcoin.network.fromMagic(p.readU32());
|
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.name = p.readVarString('utf8');
|
||||||
this.initialized = p.readU8() === 1;
|
this.initialized = p.readU8() === 1;
|
||||||
this.type = p.readU8() === 0 ? 'pubkeyhash' : 'multisig';
|
this.type = p.readU8() === 0 ? 'pubkeyhash' : 'multisig';
|
||||||
@ -3039,8 +3026,9 @@ MasterKey.prototype.encrypt = function encrypt(passphrase, callback) {
|
|||||||
if (!passphrase)
|
if (!passphrase)
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
iv = bcoin.ec.random(16);
|
|
||||||
data = this.key.toExtended();
|
data = this.key.toExtended();
|
||||||
|
iv = bcoin.ec.random(16);
|
||||||
|
|
||||||
this.stop();
|
this.stop();
|
||||||
|
|
||||||
utils.encrypt(data, passphrase, iv, function(err, data) {
|
utils.encrypt(data, passphrase, iv, function(err, data) {
|
||||||
|
|||||||
@ -9,15 +9,15 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Database Layout:
|
* Database Layout:
|
||||||
* (inherits all from txdb)
|
* p/[address] -> path data
|
||||||
* p/[address] -> wid & path data
|
|
||||||
* w/[wid] -> wallet
|
* w/[wid] -> wallet
|
||||||
* l/[label] -> wallet wid
|
* l/[id] -> wid
|
||||||
* a/[wid]/[index] -> account
|
* a/[wid]/[index] -> account
|
||||||
* i/[wid]/[name] -> account index
|
* i/[wid]/[name] -> account index
|
||||||
|
* t/[wid]/* -> txdb
|
||||||
* R -> tip
|
* R -> tip
|
||||||
* b/[hash] -> wallet block
|
* b/[hash] -> wallet block
|
||||||
* t/[hash] -> tx->wallet-wid map
|
* t/[hash] -> tx->wid map
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var bcoin = require('./env');
|
var bcoin = require('./env');
|
||||||
@ -186,7 +186,7 @@ WalletDB.prototype.getDepth = function getDepth(callback) {
|
|||||||
// This may seem like a strange way to do
|
// This may seem like a strange way to do
|
||||||
// this, but updating a global state when
|
// this, but updating a global state when
|
||||||
// creating a new wallet is actually pretty
|
// 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
|
// issues if updating a global state inside
|
||||||
// a "scoped" state. So, we avoid all the
|
// a "scoped" state. So, we avoid all the
|
||||||
// nonsense of adding a global lock to
|
// nonsense of adding a global lock to
|
||||||
@ -290,8 +290,8 @@ WalletDB.prototype.loadFilter = function loadFilter(callback) {
|
|||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
this.db.iterate({
|
this.db.iterate({
|
||||||
gte: 'W',
|
gte: 'p/' + constants.NULL_HASH,
|
||||||
lte: 'W~',
|
lte: 'p/' + constants.HIGH_HASH,
|
||||||
transform: function(key) {
|
transform: function(key) {
|
||||||
key = key.split('/')[1];
|
key = key.split('/')[1];
|
||||||
self.filter.add(key, 'hex');
|
self.filter.add(key, 'hex');
|
||||||
@ -563,12 +563,12 @@ WalletDB.prototype.create = function create(options, callback) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for the existence of a wallet.
|
* Test for the existence of a wallet.
|
||||||
* @param {WalletID?} wid
|
* @param {WalletID} id
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.has = function has(wid, callback) {
|
WalletDB.prototype.has = function has(id, callback) {
|
||||||
this.getWalletID(wid, function(err, wid) {
|
this.getWalletID(id, function(err, wid) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
return callback(null, wid != null);
|
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.
|
* Attempt to create wallet, return wallet if already exists.
|
||||||
* @param {WalletID?} wid
|
|
||||||
* @param {Object} options - See {@link Wallet}.
|
* @param {Object} options - See {@link Wallet}.
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
@ -663,9 +662,6 @@ WalletDB.prototype.getAccounts = function getAccounts(wid, callback) {
|
|||||||
var map = [];
|
var map = [];
|
||||||
var i, accounts;
|
var i, accounts;
|
||||||
|
|
||||||
if (!utils.isNumber(wid))
|
|
||||||
return callback(new Error('Wallet IDs must be alphanumeric.'));
|
|
||||||
|
|
||||||
this.db.iterate({
|
this.db.iterate({
|
||||||
gte: 'i/' + pad32(wid) + '/',
|
gte: 'i/' + pad32(wid) + '/',
|
||||||
lte: 'i/' + pad32(wid) + '/~',
|
lte: 'i/' + pad32(wid) + '/~',
|
||||||
@ -944,8 +940,8 @@ WalletDB.prototype.getAddresses = function getAddresses(wid, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.db.iterate({
|
this.db.iterate({
|
||||||
gte: 'W',
|
gte: 'p/' + constants.NULL_HASH,
|
||||||
lte: 'W~',
|
lte: 'p/' + constants.HIGH_HASH,
|
||||||
values: true,
|
values: true,
|
||||||
parse: function(value, key) {
|
parse: function(value, key) {
|
||||||
var paths = parsePaths(value);
|
var paths = parsePaths(value);
|
||||||
@ -965,8 +961,8 @@ WalletDB.prototype.getAddresses = function getAddresses(wid, callback) {
|
|||||||
|
|
||||||
WalletDB.prototype.getWallets = function getWallets(callback) {
|
WalletDB.prototype.getWallets = function getWallets(callback) {
|
||||||
this.db.iterate({
|
this.db.iterate({
|
||||||
gte: 'w',
|
gte: 'l/',
|
||||||
lte: 'w~',
|
lte: 'l/~',
|
||||||
transform: function(key) {
|
transform: function(key) {
|
||||||
return key.split('/')[1];
|
return key.split('/')[1];
|
||||||
}
|
}
|
||||||
@ -1194,15 +1190,7 @@ WalletDB.prototype.writeBlock = function writeBlock(block, matches, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.write(function(err) {
|
batch.write(callback);
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
self.tip = block.hash;
|
|
||||||
self.height = block.height;
|
|
||||||
|
|
||||||
return callback();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1219,15 +1207,7 @@ WalletDB.prototype.unwriteBlock = function unwriteBlock(block, callback) {
|
|||||||
batch.put('R', prev.toTip());
|
batch.put('R', prev.toTip());
|
||||||
batch.del('b/' + block.hash);
|
batch.del('b/' + block.hash);
|
||||||
|
|
||||||
batch.write(function(err) {
|
batch.write(callback);
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
self.tip = prev.hash;
|
|
||||||
self.height = prev.height;
|
|
||||||
|
|
||||||
return callback();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1277,6 +1257,11 @@ WalletDB.prototype.addBlock = function addBlock(entry, txs, callback, force) {
|
|||||||
block = WalletBlock.fromEntry(entry);
|
block = WalletBlock.fromEntry(entry);
|
||||||
matches = [];
|
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
|
// NOTE: Atomicity doesn't matter here. If we crash
|
||||||
// during this loop, the automatic rescan will get
|
// during this loop, the automatic rescan will get
|
||||||
// the database back into the correct state.
|
// the database back into the correct state.
|
||||||
@ -1359,7 +1344,15 @@ WalletDB.prototype.removeBlock = function removeBlock(entry, callback, force) {
|
|||||||
|
|
||||||
wallet.tx.unconfirm(hash, next);
|
wallet.tx.unconfirm(hash, next);
|
||||||
});
|
});
|
||||||
}, callback);
|
}, function(err) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
self.tip = block.hash;
|
||||||
|
self.height = block.height;
|
||||||
|
|
||||||
|
return callback();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -222,8 +222,8 @@ describe('Chain', function() {
|
|||||||
var txs = [];
|
var txs = [];
|
||||||
walletdb.getAddresses(function(err, hashes) {
|
walletdb.getAddresses(function(err, hashes) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
chain.db.scan(null, hashes, function(tx, block, next) {
|
chain.db.scan(null, hashes, function(block, tx, next) {
|
||||||
txs.push(tx);
|
txs = txs.concat(tx);
|
||||||
next();
|
next();
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user