WIP: ledger P2PKH

This commit is contained in:
Matias Alejo Garcia 2015-09-11 15:43:42 -03:00
parent c4964c1929
commit 78e6120e55
11 changed files with 74 additions and 32 deletions

View File

@ -106,13 +106,15 @@
<span translate>Use Ledger hardware wallet</span>
<switch id="hw-ledger" name="hwLedger" ng-model="hwLedger" ng-change="isTestnet=false" class="green right m5t m10b"></switch>
</label>
<!-- account
<div ng-show="hwLedger">
<label class="oh"><span translate>Ledger Slot</span>
<select class="m10t" ng-model="externalIndex" ng-options="externalIndex as externalIndex for externalIndex in create.externalIndexValues">
</select>
</label>
<div class="oh text-gray line-b size-12 p10b m20b"><span translate>Ledger supports up to 20 Copay wallets simultaneously. Select which slot should be used to host this wallet</div>
</div>
</div>
-->
<label for="network-name" class="oh" ng-show="!hwLedger">
<span translate>Testnet</span>
<switch id="network-name" name="isTestnet" ng-model="isTestnet" class="green right m5t m10b"></switch>

View File

@ -174,20 +174,20 @@
{{import.error|translate}}
</span>
</div>
<div class="large-12 columns">
<!-- TODO: account
<label class=" oh">
<span translate>Ledger Slot</span>
<select class="m10t" ng-model="externalIndex" ng-options="externalIndex as externalIndex for externalIndex in import.externalIndexValues">
</select>
</label>
<div class="oh text-gray line-b size-12 p10b m20b"><span translate>Ledger supports up to 20 Copay wallets simultaneously. Select which slot to import</div>
-->
<button translate type="submit" class="button round expand black"
ng-disabled="import.loading || import.ledger">
Import backup
</button>
</div>
</form>
</div>

View File

@ -91,6 +91,7 @@
<switch id="hw-ledger" name="hwLedger" ng-model="hwLedger" class="green right m5t m10b"></switch>
</label>
</div>
<!-- TODO account
<div class="large-12 columns" ng-hide="!hwLedger">
<label class="oh">
<span translate>Ledger Slot</span>
@ -98,7 +99,8 @@
</select>
</label>
<div class="oh text-gray line-b size-12 p10b m20b"><span translate>Ledger supports up to 20 Copay wallets simultaneously. Select which slot should be used to host this wallet</div>
</div>
</div>
-->
<div class="large-12 columns">
<label ng-show="!hwLedger" for="seed" class="oh">

View File

@ -44,7 +44,7 @@
<span translate>Hardware wallet</span>
<span class="right text-gray">
{{preferences.externalSource}}
(index {{preferences.externalIndex}})
<!-- (Accont {{preferences.externalAccount}}) -->
</span>
</li>
<li class="line-b p20" ng-click="$root.go('backup')" ng-hide="index.isPrivKeyExternal">

View File

@ -35,8 +35,6 @@ angular.module('copayApp.controllers').controller('createController',
$scope.requiredCopayers = Math.min(parseInt(n / 2 + 1), maxReq);
};
this.externalIndexValues = lodash.range(0, ledger.MAX_SLOT);
$scope.externalIndex = 0;
this.TCValues = lodash.range(2, defaults.limits.totalCopayers + 1);
$scope.totalCopayers = defaults.wallet.totalCopayers;
@ -80,7 +78,8 @@ angular.module('copayApp.controllers').controller('createController',
if (form.hwLedger.$modelValue) {
self.ledger = true;
ledger.getInfoForNewWallet($scope.externalIndex, function(err, lopts) {
// TODO : account
ledger.getInfoForNewWallet(0, function(err, lopts) {
self.ledger = false;
if (err) {
self.error = err;

View File

@ -7,8 +7,6 @@ angular.module('copayApp.controllers').controller('importController',
this.isSafari = isMobile.Safari();
this.isCordova = isCordova;
this.externalIndexValues = lodash.range(0, ledger.MAX_SLOT);
$scope.externalIndex = 0;
var reader = new FileReader();
window.ignoreMobilePause = true;
@ -199,7 +197,8 @@ angular.module('copayApp.controllers').controller('importController',
return;
}
self.ledger = true;
ledger.getInfoForNewWallet($scope.externalIndex, function(err, lopts) {
// TODO account
ledger.getInfoForNewWallet(0, function(err, lopts) {
self.ledger = false;
if (err) {
self.error = err;

View File

@ -4,8 +4,6 @@ angular.module('copayApp.controllers').controller('joinController',
function($scope, $rootScope, $timeout, go, isMobile, notification, profileService, isCordova, isChromeApp, $modal, gettext, lodash, ledger) {
var self = this;
this.externalIndexValues = lodash.range(0,ledger.MAX_SLOT);
$scope.externalIndex = 0;
this.isChromeApp = function() {
return isChromeApp;
@ -176,7 +174,8 @@ angular.module('copayApp.controllers').controller('joinController',
if (form.hwLedger.$modelValue) {
self.ledger = true;
ledger.getInfoForNewWallet($scope.externalIndex, function(err, lopts) {
// TODO account
ledger.getInfoForNewWallet(0, function(err, lopts) {
self.ledger = false;
if (err) {
self.error = err;

View File

@ -17,7 +17,8 @@ angular.module('copayApp.controllers').controller('preferencesController',
if (fc) {
$scope.encrypt = fc.hasPrivKeyEncrypted();
this.externalSource = fc.getPrivKeyExternalSourceName() == 'ledger' ? "Ledger" : null;
this.externalIndex = fc.getExternalIndex();
// TODO externalAccount
//this.externalIndex = fc.getExternalIndex();
}
var unwatchSpendUnconfirmed = $scope.$watch('spendUnconfirmed', function(newVal, oldVal) {

View File

@ -264,7 +264,8 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
self.setOngoingProcess(gettext('Requesting Ledger Wallet to sign'));
$scope.loading = true;
$scope.error = null;
ledger.signTx(txp, fc.getExternalIndex(), function(result) {
// TODO account
ledger.signTx(txp, 0, function(result) {
if (result.success) {
txp.signatures = [];
for (var i=0; i<result.signatures.length; i++) {
@ -836,7 +837,8 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
if (fc.getPrivKeyExternalSourceName() == 'ledger') {
$log.debug('Requesting Ledger Chrome app to sign the transaction');
self.setOngoingProcess(gettext('Requesting Ledger Wallet to sign'));
ledger.signTx(txp, fc.getExternalIndex(), function(result) {
// TODO account
ledger.signTx(txp, 0, function(result) {
if (result.success) {
txp.signatures = [];
for (var i=0; i<result.signatures.length; i++) {

View File

@ -4,7 +4,6 @@ angular.module('copayApp.services')
.factory('ledger', function($log, bwcService, gettext) {
var root = {};
var LEDGER_CHROME_ID = "kkdpmhnladdopljabkgpacgpliggeeaf";
root.MAX_SLOT = 20;
// Ledger magic number to get xPub without user confirmation
root.ENTROPY_INDEX_PATH = "0xb11e/";
@ -17,8 +16,8 @@ angular.module('copayApp.services')
});
}
root.getEntropySource = function(index, callback) {
var path = root.ENTROPY_INDEX_PATH + index + "'";
root.getEntropySource = function(account, callback) {
var path = root.ENTROPY_INDEX_PATH + account + "'";
var xpub = root.getXPubKey(path, function(data) {
if (!data.success) {
$log.warn(data.message);
@ -33,8 +32,8 @@ angular.module('copayApp.services')
});
};
root.getXPubKeyForAddresses = function(index, callback) {
return root.getXPubKey(root._getPath(index), callback);
root.getXPubKeyForAddresses = function(account, callback) {
return root.getXPubKey(root._getPath(account), callback);
};
root.getXPubKey = function(path, callback) {
@ -48,36 +47,37 @@ angular.module('copayApp.services')
};
root.getInfoForNewWallet = function(slot, callback) {
root.getInfoForNewWallet = function(account, callback) {
var opts = {};
root.getEntropySource(slot, function(data) {
root.getEntropySource(account, function(data) {
if (!data.success) {
$log.warn(data.message);
return callback(data.message);
}
opts.entropySource = data.entropySource;
root.getXPubKeyForAddresses(slot, function(data) {
root.getXPubKeyForAddresses(account, function(data) {
if (!data.success) {
$log.warn(data.message);
return callback(data);
}
opts.extendedPublicKey = data.xpubkey;
opts.externalSource = 'ledger';
opts.externalIndex = slot;
opts.externalIndex = account;
return callback(null, opts);
});
});
};
root.signTx = function(txp, index, callback) {
root._signP2PKH = function(txp, account, callback) {
root.callbacks["sign_p2sh"] = callback;
var redeemScripts = [];
var paths = [];
var tx = bwcService.getUtils().buildTx(txp);
for (var i = 0; i < tx.inputs.length; i++) {
redeemScripts.push(new ByteString(tx.inputs[i].redeemScript.toBuffer().toString('hex'), GP.HEX).toString());
paths.push(root._getPath(index) + txp.inputs[i].path.substring(1));
paths.push(root._getPath(account) + txp.inputs[i].path.substring(1));
}
var splitTransaction = root._splitTransaction(new ByteString(tx.toString(), GP.HEX));
var inputs = [];
@ -97,6 +97,44 @@ angular.module('copayApp.services')
outputs_script: splitTransaction.outputScript.toString(),
paths: paths
});
};
root._signP2SH = function(txp, account, callback) {
root.callbacks["sign_p2sh"] = callback;
var redeemScripts = [];
var paths = [];
var tx = bwcService.getUtils().buildTx(txp);
for (var i = 0; i < tx.inputs.length; i++) {
redeemScripts.push(new ByteString(tx.inputs[i].redeemScript.toBuffer().toString('hex'), GP.HEX).toString());
paths.push(root._getPath(account) + txp.inputs[i].path.substring(1));
}
var splitTransaction = root._splitTransaction(new ByteString(tx.toString(), GP.HEX));
var inputs = [];
for (var i = 0; i < splitTransaction.inputs.length; i++) {
var input = splitTransaction.inputs[i];
inputs.push([
root._reverseBytestring(input.prevout.bytes(0, 32)).toString(),
root._reverseBytestring(input.prevout.bytes(32)).toString()
]);
}
$log.debug('Ledger signing paths:', paths);
root._messageAfterSession({
command: "sign_p2sh",
inputs: inputs,
scripts: redeemScripts,
outputs_number: splitTransaction.outputs.length,
outputs_script: splitTransaction.outputScript.toString(),
paths: paths
});
};
root.signTx = function(txp, account, callback) {
console.log('[ledger.js.72:txp:]', txp, account); //TODO
if (txp.addressType == 'P2PKH') {
root._signP2PKH(txp, account, callback);
} else {
root._signP2SH(txp, account, callback);
}
}
root._message = function(data) {
@ -146,8 +184,8 @@ angular.module('copayApp.services')
}
}
root._getPath = function(index) {
return index + "'/45'";
root._getPath = function(account) {
return "44'/0'/" + account + "'";
}
root._splitTransaction = function(transaction) {

View File

@ -193,7 +193,7 @@ angular.module('copayApp.services')
}
} else if (opts.extendedPublicKey) {
try {
walletClient.seedFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.externalIndex, opts.entropySource);
walletClient.seedFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.entropySource);
} catch (ex) {
$log.warn(ex);
return cb(gettext('Could not create using the specified extended public key'));
@ -411,7 +411,7 @@ angular.module('copayApp.services')
var walletClient = bwcService.getClient();
$log.debug('Importing Wallet XPubKey');
walletClient.importFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.externalIndex, opts.entropySource, function(err) {
walletClient.importFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.entropySource, function(err) {
if (err) {
// in HW wallets, req key is always the same. They can't addAccess.