checking arguments
This commit is contained in:
parent
0885b26983
commit
07012633a9
|
@ -10,17 +10,17 @@ var MESSAGE_SIGNING_PATH = "m/1/0";
|
|||
function Copayer(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
this.version = VERSION;
|
||||
this.createdOn = Math.floor(Date.now() / 1000);
|
||||
this.id = opts.id;
|
||||
this.name = opts.name;
|
||||
this.xPubKey = opts.xPubKey;
|
||||
this.xPubKeySignature = opts.xPubKeySignature; // So third parties can check independently
|
||||
this.version = VERSION;
|
||||
this.signingPubKey = opts.signingPubKey || this.getSigningPubKey();
|
||||
|
||||
this.xPubKeySignature = opts.xPubKeySignature; // So third parties can check independently
|
||||
if (opts.xPubKey) {
|
||||
this.signingPubKey = this.getSigningPubKey();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Copayer.prototype.getSigningPubKey = function () {
|
||||
if (!this.xPubKey) return null;
|
||||
return HDPublicKey.fromString(this.xPubKey).derive(MESSAGE_SIGNING_PATH).publicKey.toString();
|
||||
|
@ -29,13 +29,13 @@ Copayer.prototype.getSigningPubKey = function () {
|
|||
Copayer.fromObj = function (obj) {
|
||||
var x = new Copayer();
|
||||
|
||||
|
||||
x.version = obj.version;
|
||||
x.createdOn = obj.createdOn;
|
||||
x.id = obj.id;
|
||||
x.name = obj.name;
|
||||
x.xPubKey = obj.xPubKey;
|
||||
x.xPubKeySignature = obj.xPubKeySignature;
|
||||
x.signingPubKey = obj.signingPubKey || this.getSigningPubKey();
|
||||
x.signingPubKey = obj.signingPubKey;
|
||||
|
||||
return x;
|
||||
};
|
||||
|
|
|
@ -4,9 +4,12 @@ var _ = require('lodash');
|
|||
|
||||
var TxProposalAction = require('./txproposalaction');
|
||||
|
||||
var VERSION = '1.0.0';
|
||||
|
||||
function TxProposal(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
this.version = VERSION;
|
||||
this.createdOn = Math.floor(Date.now() / 1000);
|
||||
this.id = opts.id;
|
||||
this.creatorId = opts.creatorId;
|
||||
|
@ -24,6 +27,7 @@ function TxProposal(opts) {
|
|||
TxProposal.fromObj = function (obj) {
|
||||
var x = new TxProposal();
|
||||
|
||||
x.version = obj.version;
|
||||
x.createdOn = obj.createdOn;
|
||||
x.id = obj.id;
|
||||
x.creatorId = obj.creatorId;
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
var _ = require('lodash');
|
||||
|
||||
var Copayer = require('./copayer');
|
||||
var WALLET_VERSION = '1.0.0';
|
||||
var VERSION = '1.0.0';
|
||||
|
||||
function Wallet(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
this.version = VERSION;
|
||||
this.createdOn = Math.floor(Date.now() / 1000);
|
||||
this.id = opts.id;
|
||||
this.name = opts.name;
|
||||
|
@ -17,23 +18,43 @@ function Wallet(opts) {
|
|||
this.publicKeyRing = [];
|
||||
this.addressIndex = 0;
|
||||
this.copayers = [];
|
||||
this.version = WALLET_VERSION;
|
||||
this.pubKey = opts.pubKey;
|
||||
};
|
||||
|
||||
/* For compressed keys, m*73 + n*34 <= 496 */
|
||||
Wallet.COPAYER_PAIR_LIMITS = {
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 3,
|
||||
4: 4,
|
||||
5: 4,
|
||||
6: 4,
|
||||
7: 3,
|
||||
8: 3,
|
||||
9: 2,
|
||||
10: 2,
|
||||
11: 1,
|
||||
12: 1,
|
||||
};
|
||||
|
||||
Wallet.fromUntrustedObj = function (obj) {
|
||||
/**
|
||||
* Get the maximum allowed number of required copayers.
|
||||
* This is a limit imposed by the maximum allowed size of the scriptSig.
|
||||
* @param {number} totalCopayers - the total number of copayers
|
||||
* @return {number}
|
||||
*/
|
||||
Wallet.getMaxRequiredCopayers = function(totalCopayers) {
|
||||
return Wallet.COPAYER_PAIR_LIMITS[totalCopayers];
|
||||
};
|
||||
|
||||
// TODO add sanity checks OR migration steps?
|
||||
if (!obj.pubKey || !obj.m || !obj.n)
|
||||
return cb('Wallet corrupted');
|
||||
|
||||
return Wallet.fromObj(obj);
|
||||
Wallet.verifyCopayerLimits = function (m, n) {
|
||||
return (n >= 1 && n <= 12) && (m >= 1 && m <= Wallet.COPAYER_PAIR_LIMITS[n]);
|
||||
};
|
||||
|
||||
Wallet.fromObj = function (obj) {
|
||||
var x = new Wallet();
|
||||
|
||||
x.version = obj.version;
|
||||
x.createdOn = obj.createdOn;
|
||||
x.id = obj.id;
|
||||
x.name = obj.name;
|
||||
|
|
|
@ -5,11 +5,13 @@ var $ = require('preconditions').singleton();
|
|||
var async = require('async');
|
||||
var log = require('npmlog');
|
||||
log.debug = log.verbose;
|
||||
|
||||
var Bitcore = require('bitcore');
|
||||
var PublicKey = Bitcore.PublicKey;
|
||||
var HDPublicKey = Bitcore.HDPublicKey;
|
||||
var Explorers = require('bitcore-explorers');
|
||||
|
||||
var utils = require('./utils');
|
||||
var Lock = require('./lock');
|
||||
var Storage = require('./storage');
|
||||
var SignUtils = require('./signutils');
|
||||
|
@ -45,6 +47,11 @@ function CopayServer(opts) {
|
|||
CopayServer.prototype.createWallet = function (opts, cb) {
|
||||
var self = this, pubKey;
|
||||
|
||||
utils.checkRequired(opts, ['id', 'name', 'm', 'n', 'pubKey']);
|
||||
if (!Wallet.verifyCopayerLimits(opts.m, opts.n)) return cb('Incorrect m or n value');
|
||||
var network = opts.network || 'livenet';
|
||||
if (network != 'livenet' && network != 'testnet') return cb('Invalid network');
|
||||
|
||||
try {
|
||||
pubKey = new PublicKey.fromString(opts.pubKey);
|
||||
} catch (e) {
|
||||
|
@ -60,7 +67,7 @@ CopayServer.prototype.createWallet = function (opts, cb) {
|
|||
name: opts.name,
|
||||
m: opts.m,
|
||||
n: opts.n,
|
||||
network: opts.network || 'livenet',
|
||||
network: network,
|
||||
pubKey: pubKey,
|
||||
});
|
||||
|
||||
|
@ -119,6 +126,8 @@ CopayServer.prototype._verifySignature = function (text, signature, pubKey) {
|
|||
CopayServer.prototype.joinWallet = function (opts, cb) {
|
||||
var self = this;
|
||||
|
||||
utils.checkRequired(opts, ['walletId', 'id', 'name', 'xPubKey', 'xPubKeySignature']);
|
||||
|
||||
self._runLocked(opts.walletId, cb, function (cb) {
|
||||
self.getWallet({ id: opts.walletId }, function (err, wallet) {
|
||||
if (err) return cb(err);
|
||||
|
@ -164,6 +173,8 @@ CopayServer.prototype._doCreateAddress = function (pkr, index, isChange) {
|
|||
CopayServer.prototype.createAddress = function (opts, cb) {
|
||||
var self = this;
|
||||
|
||||
utils.checkRequired(opts, ['walletId', 'isChange']);
|
||||
|
||||
self._runLocked(opts.walletId, cb, function (cb) {
|
||||
self.getWallet({ id: opts.walletId }, function (err, wallet) {
|
||||
if (err) return cb(err);
|
||||
|
@ -195,6 +206,8 @@ CopayServer.prototype._doCreateAddress = function (pkr, index, isChange) {
|
|||
CopayServer.prototype.verifyMessageSignature = function (opts, cb) {
|
||||
var self = this;
|
||||
|
||||
utils.checkRequired(opts, ['walletId', 'copayerId', 'message', 'signature']);
|
||||
|
||||
self.getWallet({ id: opts.walletId }, function (err, wallet) {
|
||||
if (err) return cb(err);
|
||||
|
||||
|
@ -275,6 +288,8 @@ CopayServer.prototype._getUtxos = function (opts, cb) {
|
|||
CopayServer.prototype.getBalance = function (opts, cb) {
|
||||
var self = this;
|
||||
|
||||
utils.checkRequired(opts, 'walletId');
|
||||
|
||||
self._getUtxos({ walletId: opts.walletId }, function (err, utxos) {
|
||||
if (err) return cb(err);
|
||||
|
||||
|
@ -326,6 +341,8 @@ CopayServer.prototype._selectUtxos = function (txp, utxos) {
|
|||
CopayServer.prototype.createTx = function (opts, cb) {
|
||||
var self = this;
|
||||
|
||||
utils.checkRequired(opts, ['walletId', 'copayerId', 'toAddress', 'amount', 'message']);
|
||||
|
||||
self.getWallet({ id: opts.walletId }, function (err, wallet) {
|
||||
if (err) return cb(err);
|
||||
|
||||
|
@ -373,6 +390,8 @@ CopayServer.prototype._broadcastTx = function (rawTx, cb) {
|
|||
CopayServer.prototype.signTx = function (opts, cb) {
|
||||
var self = this;
|
||||
|
||||
utils.checkRequired(opts, ['walletId', 'copayerId', 'txProposalId', 'signature']);
|
||||
|
||||
self.fetchTx(opts.walletId, opts.txProposalId, function (err, txp) {
|
||||
if (err) return cb(err);
|
||||
if (!txp) return cb('Transaction proposal not found');
|
||||
|
@ -406,10 +425,13 @@ CopayServer.prototype.signTx = function (opts, cb) {
|
|||
* @param {string} opts.walletId - The wallet id.
|
||||
* @param {string} opts.copayerId - The wallet id.
|
||||
* @param {string} opts.txProposalId - The identifier of the transaction.
|
||||
* @param {string} [opts.reason] - A message to other copayers explaining the rejection.
|
||||
*/
|
||||
CopayServer.prototype.rejectTx = function (opts, cb) {
|
||||
var self = this;
|
||||
|
||||
utils.checkRequired(opts, ['walletId', 'copayerId', 'txProposalId']);
|
||||
|
||||
self.fetchTx(opts.walletId, opts.txProposalId, function (err, txp) {
|
||||
if (err) return cb(err);
|
||||
if (!txp) return cb('Transaction proposal not found');
|
||||
|
@ -436,6 +458,8 @@ CopayServer.prototype.rejectTx = function (opts, cb) {
|
|||
CopayServer.prototype.getPendingTxs = function (opts, cb) {
|
||||
var self = this;
|
||||
|
||||
utils.checkRequired(opts, 'walletId');
|
||||
|
||||
self.storage.fetchTxs(opts.walletId, function (err, txps) {
|
||||
if (err) return cb(err);
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
var $ = require('preconditions').singleton();
|
||||
var _ = require('lodash');
|
||||
|
||||
var utils = {};
|
||||
|
||||
utils.checkRequired = function (obj, args) {
|
||||
args = [].concat(args);
|
||||
if (!_.isObject(obj)) throw 'Required arguments missing';
|
||||
_.each(args, function (arg) {
|
||||
if (!obj.hasOwnProperty(arg)) throw "Missing required argument '" + arg + "'";
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = utils;
|
|
@ -428,10 +428,12 @@ describe('Copay server', function() {
|
|||
name: 'me',
|
||||
xPubKey: someXPubKeys[0],
|
||||
};
|
||||
server.joinWallet(copayerOpts, function(err) {
|
||||
err.should.contain('Bad request');
|
||||
try {
|
||||
server.joinWallet(copayerOpts, function(err) {});
|
||||
} catch (e) {
|
||||
e.should.contain('xPubKeySignature');
|
||||
done();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -526,11 +528,12 @@ describe('Copay server', function() {
|
|||
it('should create address', function(done) {
|
||||
server._doCreateAddress = sinon.stub().returns(new Address({
|
||||
address: 'addr1',
|
||||
path: 'path1'
|
||||
path: 'path1',
|
||||
}));
|
||||
helpers.createAndJoinWallet('123', 2, 2, function(err, wallet) {
|
||||
server.createAddress({
|
||||
walletId: '123'
|
||||
walletId: '123',
|
||||
isChange: false,
|
||||
}, function(err, address) {
|
||||
should.not.exist(err);
|
||||
address.should.exist;
|
||||
|
|
Loading…
Reference in New Issue