diff --git a/js/models/core/PrivateKey.js b/js/models/core/PrivateKey.js
index 7c220dadd..8df3325c7 100644
--- a/js/models/core/PrivateKey.js
+++ b/js/models/core/PrivateKey.js
@@ -1,23 +1,45 @@
'use strict';
+// 62.9% typed (by google's closure-compiler account)
var bitcore = require('bitcore');
var HK = bitcore.HierarchicalKey;
var WalletKey = bitcore.WalletKey;
var networks = bitcore.networks;
var util = bitcore.util;
+var _ = require('underscore');
+var preconditions = require('preconditions').instance();
var HDPath = require('./HDPath');
+/**
+ * @desc
+ * Wrapper for bitcore.HierarchicalKey to be used inside of Copay.
+ *
+ * @param {Object} opts
+ * @param {string} opts.networkName if set to 'testnet', use the test3 bitcoin
+ * network constants (livenet otherwise)
+ * @param {string} opts.extendedPrivateKeyString if set, use this private key
+ * string, othewise create a new
+ * private key
+ */
function PrivateKey(opts) {
opts = opts || {};
- this.network = opts.networkName === 'testnet' ?
- networks.testnet : networks.livenet;
+ this.network = opts.networkName === 'testnet' ? networks.testnet : networks.livenet;
var init = opts.extendedPrivateKeyString || this.network.name;
this.bip = new HK(init);
this.privateKeyCache = {};
this.publicHex = this.deriveBIP45Branch().eckey.public.toString('hex');
};
+/**
+ * @desc Retrieve this derivated private key's public key in hexa format
+ *
+ * The value returned is calculated using the path from PrivateKey's
+ * HDParams.IdFullBranch. This key is used to identify the copayer
+ * (signing messages mostly).
+ *
+ * @returns {string} the public key in a hexadecimal string
+ */
PrivateKey.prototype.getId = function() {
if (!this.id) {
this.cacheId();
@@ -25,6 +47,15 @@ PrivateKey.prototype.getId = function() {
return this.id;
};
+/**
+ * @desc Retrieve this private key's private key in hex format
+ *
+ * The value returned is calculated using the path from PrivateKey's
+ * HDParams.IdFullBranch. This key is used to identify the copayer
+ * (signing messages mostly).
+ *
+ * @returns {string} the private key in a hexadecimal string
+ */
PrivateKey.prototype.getIdPriv = function() {
if (!this.idpriv) {
this.cacheId();
@@ -32,6 +63,15 @@ PrivateKey.prototype.getIdPriv = function() {
return this.idpriv;
};
+/**
+ * @desc Retrieve this private key's private key
+ *
+ * The value returned is calculated using the path from PrivateKey's
+ * HDParams.IdFullBranch. This key is used to identify the copayer
+ * (signing messages mostly).
+ *
+ * @returns {bitcore.PrivateKey} the private key
+ */
PrivateKey.prototype.getIdKey = function() {
if (!this.idkey) {
this.cacheId();
@@ -39,6 +79,11 @@ PrivateKey.prototype.getIdKey = function() {
return this.idkey;
};
+/**
+ * @desc Caches the result of deriving IdFullBranch
+ *
+ * @private
+ */
PrivateKey.prototype.cacheId = function() {
var path = HDPath.IdFullBranch;
var idhk = this.bip.derive(path);
@@ -47,54 +92,116 @@ PrivateKey.prototype.cacheId = function() {
this.idpriv = idhk.eckey.private.toString('hex');
};
+/**
+ * @desc Derive the master branch for Copay.
+ */
PrivateKey.prototype.deriveBIP45Branch = function() {
if (!this.bip45Branch) {
this.bip45Branch = this.bip.derive(HDPath.BIP45_PUBLIC_PREFIX);
}
return this.bip45Branch;
-}
-
-
-PrivateKey.trim = function(data) {
- var opts = {};
- ['networkName', 'extendedPrivateKeyString'].forEach(function(k){
- opts[k] = data[k];
- });
-
- return opts;
};
+/**
+ * @desc Returns an object with information needed to rebuild a PrivateKey
+ * (as most of its properties are derived from the extended private key).
+ *
+ * @TODO: Figure out if this is the correct pattern
+ * This is a static method and is probably used for serialization.
+ *
+ * @static
+ * @param {Object} data
+ * @param {*} data.networkName - a name for a bitcoin network
+ * @param {*} data.extendedPrivateKeyString - a bip32 extended private key
+ * @returns {Object} an object with two properties: networkName and
+ * extendedPrivateKeyString, taken from the data
+ * parameter.
+ */
+PrivateKey.trim = function(data) {
+ var opts = {};
+ ['networkName', 'extendedPrivateKeyString'].forEach(function(k){
+ opts[k] = data[k];
+ });
+ return opts
+};
+
+/**
+ * @desc Generate a private Key from a serialized object
+ *
+ * @TODO: This method uses PrivateKey.trim but it's actually not needed...
+ *
+ * @param {Object} data
+ * @param {*} data.networkName - a name for a bitcoin network
+ * @param {*} data.extendedPrivateKeyString - a bip32 extended private key
+ * @returns {PrivateKey}
+ */
PrivateKey.fromObj = function(obj) {
return new PrivateKey(PrivateKey.trim(obj));
};
+/**
+ * @desc Serialize a private key, keeping only the data necessary to rebuild it
+ *
+ * @returns {Object}
+ */
PrivateKey.prototype.toObj = function() {
return {
extendedPrivateKeyString: this.getExtendedPrivateKeyString(),
- networkName: this.network.name,
+ networkName: this.network.name
};
};
+/**
+ * @desc Retrieve a BIP32 extended public key as generated by bitcore
+ *
+ * @returns {string}
+ */
PrivateKey.prototype.getExtendedPublicKeyString = function() {
return this.bip.extendedPublicKeyString();
};
+/**
+ * @desc Retrieve a BIP32 extended private key as generated by bitcore
+ *
+ * @returns {string}
+ */
PrivateKey.prototype.getExtendedPrivateKeyString = function() {
return this.bip.extendedPrivateKeyString();
};
+/**
+ * @desc
+ * Retrieve a HierarchicalKey derived from the given path as generated by
+ * bitcore
+ * @param {string} path - a string for derivation (something like "m/234'/1/2")
+ * @returns {bitcore.HierarchicalKey}
+ */
PrivateKey.prototype._getHK = function(path) {
- if (typeof path === 'undefined') {
+ if (_.isUndefined(path)) {
return this.bip;
}
var ret = this.bip.derive(path);
return ret;
};
+/**
+ * @desc
+ * Retrieve an array of WalletKey derived from given paths. {@see PrivateKey#getForPath}
+ *
+ * @param {string[]} paths - the paths to derive
+ * @returns {bitcore.WalletKey[]} - the derived keys
+ */
PrivateKey.prototype.getForPaths = function(paths) {
return paths.map(this.getForPath.bind(this));
};
+/**
+ * @desc
+ * Retrieve a WalletKey derived from a path.
+ *
+ * @param {string} paths - the path to derive
+ * @returns {bitcore.WalletKey} - the derived key
+ */
PrivateKey.prototype.getForPath = function(path) {
var pk = this.privateKeyCache[path];
if (!pk) {
@@ -110,14 +217,38 @@ PrivateKey.prototype.getForPath = function(path) {
return wk;
};
+/**
+ * @desc
+ * Retrieve a Branch for Copay using the given path
+ *
+ * @TODO: Investigate when is this called and if this is really needed
+ *
+ * @param {number} index - the index of the key to generate
+ * @param {boolean} isChange - whether this is a change adderess or a receive
+ * @param {number} cosigner - the cosigner index
+ * @return {bitcore.HierarchicalKey}
+ */
PrivateKey.prototype.get = function(index, isChange, cosigner) {
+
+ // TODO: Add parameter validation?
+
var path = HDPath.FullBranch(index, isChange, cosigner);
return this.getForPath(path);
};
+/**
+ * @desc
+ * Retrieve multiple branches for Copay up to the received indexes
+ *
+ * @TODO: Investigate when is this called and if this is really needed
+ *
+ * @param {number} receiveIndex - the number of receive addresses to generate
+ * @param {number} changeIndex - the number of change addresses to generate
+ * @param {number} cosigner - the cosigner index
+ * @return {bitcore.HierarchicalKey}
+ */
PrivateKey.prototype.getAll = function(receiveIndex, changeIndex, cosigner) {
- if (typeof receiveIndex === 'undefined' || typeof changeIndex === 'undefined')
- throw new Error('Invalid parameters');
+ preconditions.checkArgument(!_.isUndefined(receiveIndex) && !_.isUndefined(changeIndex));
var ret = [];
for (var i = 0; i < receiveIndex; i++) {
@@ -129,6 +260,4 @@ PrivateKey.prototype.getAll = function(receiveIndex, changeIndex, cosigner) {
return ret;
};
-
-
module.exports = PrivateKey;