restrict BIP44 usage to 1-of-1 wallets

This commit is contained in:
Ivan Socolsky 2015-09-04 21:05:39 -03:00
parent 884a68a628
commit 765ccf33a0
2 changed files with 8 additions and 22 deletions

View File

@ -203,7 +203,7 @@ WalletService.prototype._runLocked = function(cb, task) {
* @param {number} opts.n - Total copayers. * @param {number} opts.n - Total copayers.
* @param {string} opts.pubKey - Public key to verify copayers joining have access to the wallet secret. * @param {string} opts.pubKey - Public key to verify copayers joining have access to the wallet secret.
* @param {string} [opts.network = 'livenet'] - The Bitcoin network for this wallet. * @param {string} [opts.network = 'livenet'] - The Bitcoin network for this wallet.
* @param {string} [opts.derivationStrategy = 'BIP45'] - Strategy used for address derivation (BIP44, BIP45). * @param {string} [opts.supportBIP44 = false] - Client supports BIP44 paths for 1-of-1 wallets.
*/ */
WalletService.prototype.createWallet = function(opts, cb) { WalletService.prototype.createWallet = function(opts, cb) {
var self = this, var self = this,
@ -220,9 +220,8 @@ WalletService.prototype.createWallet = function(opts, cb) {
if (!_.contains(['livenet', 'testnet'], opts.network)) if (!_.contains(['livenet', 'testnet'], opts.network))
return cb(new ClientError('Invalid network')); return cb(new ClientError('Invalid network'));
opts.derivationStrategy = opts.derivationStrategy || WalletUtils.DERIVATION_STRATEGIES.BIP45; var derivationStrategy = (opts.n == 1 && opts.supportBIP44) ?
if (!_.contains(_.values(WalletUtils.DERIVATION_STRATEGIES), opts.derivationStrategy)) WalletUtils.DERIVATION_STRATEGIES.BIP44 : WalletUtils.DERIVATION_STRATEGIES.BIP45;
return cb(new ClientError('Invalid address derivation strategy'));
try { try {
pubKey = new PublicKey.fromString(opts.pubKey); pubKey = new PublicKey.fromString(opts.pubKey);
@ -250,7 +249,7 @@ WalletService.prototype.createWallet = function(opts, cb) {
n: opts.n, n: opts.n,
network: opts.network, network: opts.network,
pubKey: pubKey.toString(), pubKey: pubKey.toString(),
derivationStrategy: opts.derivationStrategy, derivationStrategy: derivationStrategy,
}); });
self.storage.storeWallet(wallet, function(err) { self.storage.storeWallet(wallet, function(err) {
log.debug('Wallet created', wallet.id, opts.network); log.debug('Wallet created', wallet.id, opts.network);
@ -417,7 +416,7 @@ WalletService.prototype._addCopayerToWallet = function(wallet, opts, cb) {
requestPubKey: opts.requestPubKey, requestPubKey: opts.requestPubKey,
signature: opts.copayerSignature, signature: opts.copayerSignature,
customData: opts.customData, customData: opts.customData,
derivationStrategy: opts.derivationStrategy, derivationStrategy: wallet.derivationStrategy,
}); });
self.storage.fetchCopayerLookup(copayer.id, function(err, res) { self.storage.fetchCopayerLookup(copayer.id, function(err, res) {
if (err) return cb(err); if (err) return cb(err);
@ -563,7 +562,6 @@ WalletService.prototype._clientSupportsTXPv2 = function() {
* @param {string} opts.requestPubKey - Public Key used to check requests from this copayer. * @param {string} opts.requestPubKey - Public Key used to check requests from this copayer.
* @param {string} opts.copayerSignature - S(name|xPubKey|requestPubKey). Used by other copayers to verify that the copayer joining knows the wallet secret. * @param {string} opts.copayerSignature - S(name|xPubKey|requestPubKey). Used by other copayers to verify that the copayer joining knows the wallet secret.
* @param {string} opts.customData - (optional) Custom data for this copayer. * @param {string} opts.customData - (optional) Custom data for this copayer.
* @param {string} [opts.derivationStrategy = 'BIP45'] - Strategy used for address derivation (BIP44, BIP45).
*/ */
WalletService.prototype.joinWallet = function(opts, cb) { WalletService.prototype.joinWallet = function(opts, cb) {
var self = this; var self = this;
@ -574,21 +572,11 @@ WalletService.prototype.joinWallet = function(opts, cb) {
if (_.isEmpty(opts.name)) if (_.isEmpty(opts.name))
return cb(new ClientError('Invalid copayer name')); return cb(new ClientError('Invalid copayer name'));
opts.derivationStrategy = opts.derivationStrategy || WalletUtils.DERIVATION_STRATEGIES.BIP45;
if (!_.contains(_.values(WalletUtils.DERIVATION_STRATEGIES), opts.derivationStrategy))
return cb(new ClientError('Invalid address derivation strategy'));
self.walletId = opts.walletId; self.walletId = opts.walletId;
self._runLocked(cb, function(cb) { self._runLocked(cb, function(cb) {
self.storage.fetchWallet(opts.walletId, function(err, wallet) { self.storage.fetchWallet(opts.walletId, function(err, wallet) {
if (err) return cb(err); if (err) return cb(err);
if (!wallet) return cb(Errors.WALLET_NOT_FOUND); if (!wallet) return cb(Errors.WALLET_NOT_FOUND);
if (wallet.addressManager.derivationStrategy != opts.derivationStrategy) {
if (!self._clientSupportsBIP44()) {
return cb(new ClientError(Errors.codes.UPGRADE_NEEDED, 'To join this wallet, you need to upgrade your client app.'));
}
return cb(new ClientError('Incompatible address derivation strategy'));
}
var hash = WalletUtils.getCopayerHash(opts.name, opts.xPubKey, opts.requestPubKey); var hash = WalletUtils.getCopayerHash(opts.name, opts.xPubKey, opts.requestPubKey);
if (!self._verifySignature(hash, opts.copayerSignature, wallet.pubKey)) { if (!self._verifySignature(hash, opts.copayerSignature, wallet.pubKey)) {
@ -1222,7 +1210,7 @@ WalletService.prototype.createTx = function(opts, cb) {
requiredRejections: Math.min(wallet.m, wallet.n - wallet.m + 1), requiredRejections: Math.min(wallet.m, wallet.n - wallet.m + 1),
walletN: wallet.n, walletN: wallet.n,
excludeUnconfirmedUtxos: !!opts.excludeUnconfirmedUtxos, excludeUnconfirmedUtxos: !!opts.excludeUnconfirmedUtxos,
derivationStrategy: wallet.addressManager.derivationStrategy, derivationStrategy: wallet.derivationStrategy,
customData: opts.customData customData: opts.customData
}; };

View File

@ -101,21 +101,19 @@ helpers.createAndJoinWallet = function(m, n, opts, cb) {
m: m, m: m,
n: n, n: n,
pubKey: TestData.keyPair.pub, pubKey: TestData.keyPair.pub,
derivationStrategy: opts.derivationStrategy || 'BIP44', supportBIP44: !!opts.supportBIP44,
}; };
server.createWallet(walletOpts, function(err, walletId) { server.createWallet(walletOpts, function(err, walletId) {
if (err) return cb(err); if (err) return cb(err);
async.each(_.range(n), function(i, cb) { async.each(_.range(n), function(i, cb) {
var copayerData = TestData.copayers[i + offset]; var copayerData = TestData.copayers[i + offset];
var bip = opts.derivationStrategy || 'BIP44';
var copayerOpts = helpers.getSignedCopayerOpts({ var copayerOpts = helpers.getSignedCopayerOpts({
walletId: walletId, walletId: walletId,
name: 'copayer ' + (i + 1), name: 'copayer ' + (i + 1),
xPubKey: bip == 'BIP44' ? copayerData.xPubKey_44H_0H_0H : copayerData.xPubKey_45H, xPubKey: (n == 1 && !!opts.supportBIP44) ? copayerData.xPubKey_44H_0H_0H : copayerData.xPubKey_45H,
requestPubKey: copayerData.pubKey_1H_0, requestPubKey: copayerData.pubKey_1H_0,
customData: 'custom data ' + (i + 1), customData: 'custom data ' + (i + 1),
derivationStrategy: bip,
}); });
server.joinWallet(copayerOpts, function(err, result) { server.joinWallet(copayerOpts, function(err, result) {
should.not.exist(err); should.not.exist(err);