Browse Source

copayerId from pubkey

activeAddress
Matias Alejo Garcia 10 years ago
parent
commit
c6f61ae0da
  1. 2
      lib/client/api.js
  2. 0
      lib/hdpath.js
  3. 34
      lib/model/addressable.js
  4. 2
      lib/model/addressmanager.js
  5. 15
      lib/model/copayer.js
  6. 27
      lib/server.js
  7. 2
      test/hdpath.js
  8. 128
      test/integration/server.js

2
lib/client/api.js

@ -15,7 +15,7 @@ var ServerCompromisedError = require('./servercompromisederror')
var BASE_URL = 'http://localhost:3001/copay/api'; var BASE_URL = 'http://localhost:3001/copay/api';
var WALLET_CRITICAL_DATA = ['copayerId', 'xPrivKey', 'm', 'walletPrivKey', 'publicKeyRing']; var WALLET_CRITICAL_DATA = ['xPrivKey', 'm', 'publicKeyRing'];
function _createProposalOpts(opts, signingKey) { function _createProposalOpts(opts, signingKey) {
var msg = opts.toAddress + '|' + opts.amount + '|' + opts.message; var msg = opts.toAddress + '|' + opts.amount + '|' + opts.message;

0
lib/model/hdpath.js → lib/hdpath.js

34
lib/model/addressable.js

@ -1,34 +0,0 @@
var _ = require('lodash');
var HDPath = require('./hdpath');
function Addressable (opts) {
this.receiveAddressIndex = 0;
this.changeAddressIndex = 0;
this.copayerIndex = ( opts && _.isNumber(opts.copayerIndex)) ? opts.copayerIndex : HDPath.SHARED_INDEX;
};
Addressable.prototype.fromObj = function (obj) {
this.receiveAddressIndex = obj.receiveAddressIndex;
this.changeAddressIndex = obj.changeAddressIndex;
this.copayerIndex = obj.copayerIndex;
};
Addressable.prototype.addAddress = function (isChange) {
if (isChange) {
this.changeAddressIndex++;
} else {
this.receiveAddressIndex++;
}
};
Addressable.prototype.getCurrentAddressPath = function (isChange) {
return HDPath.Branch(isChange ? this.changeAddressIndex : this.receiveAddressIndex, isChange, this.copayerIndex);
};
Addressable.prototype.getNewAddressPath = function (isChange) {
this.addAddress(isChange);
return this.getCurrentAddressPath(isChange);
};
module.exports = Addressable;

2
lib/model/addressmanager.js

@ -1,5 +1,5 @@
var _ = require('lodash'); var _ = require('lodash');
var HDPath = require('./hdpath'); var HDPath = require('../hdpath');
function AddressManager(opts) { function AddressManager(opts) {
this.receiveAddressIndex = 0; this.receiveAddressIndex = 0;

15
lib/model/copayer.js

@ -1,5 +1,6 @@
'use strict'; 'use strict';
var $ = require('preconditions').singleton();
var _ = require('lodash'); var _ = require('lodash');
var util = require('util'); var util = require('util');
@ -7,20 +8,22 @@ var Bitcore = require('bitcore');
var HDPublicKey = Bitcore.HDPublicKey; var HDPublicKey = Bitcore.HDPublicKey;
var Uuid = require('uuid'); var Uuid = require('uuid');
var AddressManager = require('./addressmanager'); var AddressManager = require('./addressmanager');
var Utils = require('../bitcoinutils');
var VERSION = '1.0.0'; var VERSION = '1.0.0';
var MESSAGE_SIGNING_PATH = "m/1/0"; var MESSAGE_SIGNING_PATH = "m/1/0";
function Copayer(opts) { function Copayer(opts) {
opts = opts || {}; $.checkArgument(opts && opts.xPubKey, 'need to provide an xPubKey');
opts.copayerIndex = opts.copayerIndex || 0; opts.copayerIndex = opts.copayerIndex || 0;
this.id = Uuid.v4(); this.xPubKey = opts.xPubKey;
this.id = Utils.xpubToCopayerId(this.xPubKey);
this.version = VERSION; this.version = VERSION;
this.createdOn = Math.floor(Date.now() / 1000); this.createdOn = Math.floor(Date.now() / 1000);
this.name = opts.name; this.name = opts.name;
this.xPubKey = opts.xPubKey;
this.xPubKeySignature = opts.xPubKeySignature; // So third parties can check independently this.xPubKeySignature = opts.xPubKeySignature; // So third parties can check independently
if (this.xPubKey) if (this.xPubKey)
this.signingPubKey = this.getSigningPubKey(); this.signingPubKey = this.getSigningPubKey();
@ -40,14 +43,14 @@ Copayer.prototype.getSigningPubKey = function() {
}; };
Copayer.fromObj = function(obj) { Copayer.fromObj = function(obj) {
var x = new Copayer(); var x = new Copayer({
xPubKey: obj.xPubKey,
});
x.createdOn = obj.createdOn; x.createdOn = obj.createdOn;
x.id = obj.id; x.id = obj.id;
x.name = obj.name; x.name = obj.name;
x.xPubKey = obj.xPubKey;
x.xPubKeySignature = obj.xPubKeySignature; x.xPubKeySignature = obj.xPubKeySignature;
x.signingPubKey = obj.signingPubKey;
x.addressManager = AddressManager.fromObj(obj.addressManager); x.addressManager = AddressManager.fromObj(obj.addressManager);
return x; return x;

27
lib/server.js

@ -208,6 +208,7 @@ CopayServer.prototype.joinWallet = function(opts, cb) {
if (_.find(wallet.copayers, { if (_.find(wallet.copayers, {
xPubKey: opts.xPubKey xPubKey: opts.xPubKey
})) return cb(new ClientError('CINWALLET', 'Copayer already in wallet')); })) return cb(new ClientError('CINWALLET', 'Copayer already in wallet'));
if (wallet.copayers.length == wallet.n) if (wallet.copayers.length == wallet.n)
return cb(new ClientError('WFULL', 'Wallet full')); return cb(new ClientError('WFULL', 'Wallet full'));
@ -218,18 +219,24 @@ CopayServer.prototype.joinWallet = function(opts, cb) {
copayerIndex: wallet.copayers.length, copayerIndex: wallet.copayers.length,
}); });
wallet.addCopayer(copayer); self.storage.fetchCopayerLookup(copayer.id, function(err, res) {
self.storage.storeWalletAndUpdateCopayersLookup(wallet, function(err) {
if (err) return cb(err); if (err) return cb(err);
if (res)
return cb(new ClientError('CREGISTED', 'Copayer ID already registered on server'));
self._notify('NewCopayer', { wallet.addCopayer(copayer);
walletId: opts.walletId, self.storage.storeWalletAndUpdateCopayersLookup(wallet, function(err) {
copayerId: copayer.id, if (err) return cb(err);
copayerName: copayer.name,
}); self._notify('NewCopayer', {
return cb(null, { walletId: opts.walletId,
copayerId: copayer.id, copayerId: copayer.id,
wallet: wallet copayerName: copayer.name,
});
return cb(null, {
copayerId: copayer.id,
wallet: wallet
});
}); });
}); });
}); });

2
test/hdpath.js

@ -1,6 +1,6 @@
'use strict'; 'use strict';
var HDPath = require('../lib/model/hdpath'); var HDPath = require('../lib/hdpath');
describe('HDPath model', function() { describe('HDPath model', function() {
it('should have the correct constants', function() { it('should have the correct constants', function() {

128
test/integration/server.js

@ -39,6 +39,7 @@ helpers.getAuthServer = function(copayerId, cb) {
helpers.createAndJoinWallet = function(m, n, cb) { helpers.createAndJoinWallet = function(m, n, cb) {
var server = new CopayServer(); var server = new CopayServer();
var copayerIds = []; var copayerIds = [];
var offset = helpers.offset || 0;
var walletOpts = { var walletOpts = {
name: 'a wallet', name: 'a wallet',
@ -53,11 +54,12 @@ helpers.createAndJoinWallet = function(m, n, cb) {
var copayerOpts = { var copayerOpts = {
walletId: walletId, walletId: walletId,
name: 'copayer ' + (i + 1), name: 'copayer ' + (i + 1),
xPubKey: TestData.copayers[i].xPubKey, xPubKey: TestData.copayers[i + offset].xPubKey,
xPubKeySignature: TestData.copayers[i].xPubKeySignature, xPubKeySignature: TestData.copayers[i + offset].xPubKeySignature,
}; };
server.joinWallet(copayerOpts, function(err, result) { server.joinWallet(copayerOpts, function(err, result) {
should.not.exist(err);
copayerIds.push(result.copayerId); copayerIds.push(result.copayerId);
return cb(err); return cb(err);
}); });
@ -198,12 +200,14 @@ describe('Copay server', function() {
CopayServer.initialize({ CopayServer.initialize({
storage: storage storage: storage
}); });
helpers.offset = 0;
}); });
describe('#getInstanceWithAuth', function() { describe('#getInstanceWithAuth', function() {
beforeEach(function() {}); beforeEach(function() {});
it('should get server instance for existing copayer', function(done) { it('should get server instance for existing copayer', function(done) {
helpers.createAndJoinWallet(1, 2, function(s, wallet) { helpers.createAndJoinWallet(1, 2, function(s, wallet) {
var xpriv = TestData.copayers[0].xPrivKey; var xpriv = TestData.copayers[0].xPrivKey;
var priv = Bitcore.HDPrivateKey var priv = Bitcore.HDPrivateKey
@ -544,36 +548,6 @@ describe('Copay server', function() {
}); });
}); });
it('should fail to create address when wallet is not complete', function(done) {
var server = new CopayServer();
var walletOpts = {
name: 'my wallet',
m: 2,
n: 3,
pubKey: TestData.keyPair.pub,
};
server.createWallet(walletOpts, function(err, walletId) {
should.not.exist(err);
var copayerOpts = {
walletId: walletId,
name: 'me',
xPubKey: TestData.copayers[0].xPubKey,
xPubKeySignature: TestData.copayers[0].xPubKeySignature,
};
server.joinWallet(copayerOpts, function(err, result) {
should.not.exist(err);
helpers.getAuthServer(result.copayerId, function(server) {
server.createAddress({}, function(err, address) {
should.not.exist(address);
err.should.exist;
err.message.should.contain('not complete');
done();
});
});
});
});
});
it('should create many addresses on simultaneous requests', function(done) { it('should create many addresses on simultaneous requests', function(done) {
var N = 5; var N = 5;
async.map(_.range(N), function(i, cb) { async.map(_.range(N), function(i, cb) {
@ -611,35 +585,31 @@ describe('Copay server', function() {
}); });
}); });
describe('#createTx', function() {
var server, wallet;
beforeEach(function(done) {
helpers.createAndJoinWallet(2, 3, function(s, w) {
server = s;
wallet = w;
server.createAddress({}, function(err, address) {
done();
});
});
});
it('should create a tx', function(done) { describe('Wallet not complete tests', function() {
helpers.createUtxos(server, wallet, [100, 200], function(utxos) { it('should fail to create address when wallet is not complete', function(done) {
helpers.stubBlockExplorer(server, utxos); var server = new CopayServer();
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, 'some message', TestData.copayers[0].privKey); var walletOpts = {
server.createTx(txOpts, function(err, tx) { name: 'my wallet',
m: 2,
n: 3,
pubKey: TestData.keyPair.pub,
};
server.createWallet(walletOpts, function(err, walletId) {
should.not.exist(err);
var copayerOpts = {
walletId: walletId,
name: 'me',
xPubKey: TestData.copayers[0].xPubKey,
xPubKeySignature: TestData.copayers[0].xPubKeySignature,
};
server.joinWallet(copayerOpts, function(err, result) {
should.not.exist(err); should.not.exist(err);
tx.should.exist; helpers.getAuthServer(result.copayerId, function(server) {
tx.message.should.equal('some message'); server.createAddress({}, function(err, address) {
tx.isAccepted().should.equal.false; should.not.exist(address);
tx.isRejected().should.equal.false; err.should.exist;
server.getPendingTxs({}, function(err, txs) { err.message.should.contain('not complete');
should.not.exist(err);
txs.length.should.equal(1);
server.getBalance({}, function(err, balance) {
should.not.exist(err);
balance.totalAmount.should.equal(helpers.toSatoshi(300));
balance.lockedAmount.should.equal(helpers.toSatoshi(100));
done(); done();
}); });
}); });
@ -677,6 +647,45 @@ describe('Copay server', function() {
}); });
}); });
}); });
});
describe('#createTx', function() {
var server, wallet;
beforeEach(function(done) {
helpers.createAndJoinWallet(2, 3, function(s, w) {
server = s;
wallet = w;
server.createAddress({}, function(err, address) {
done();
});
});
});
it('should create a tx', function(done) {
helpers.createUtxos(server, wallet, [100, 200], function(utxos) {
helpers.stubBlockExplorer(server, utxos);
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, 'some message', TestData.copayers[0].privKey);
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
tx.should.exist;
tx.message.should.equal('some message');
tx.isAccepted().should.equal.false;
tx.isRejected().should.equal.false;
server.getPendingTxs({}, function(err, txs) {
should.not.exist(err);
txs.length.should.equal(1);
server.getBalance({}, function(err, balance) {
should.not.exist(err);
balance.totalAmount.should.equal(helpers.toSatoshi(300));
balance.lockedAmount.should.equal(helpers.toSatoshi(100));
done();
});
});
});
});
});
it('should fail to create tx with invalid proposal signature', function(done) { it('should fail to create tx with invalid proposal signature', function(done) {
helpers.createUtxos(server, wallet, [100, 200], function(utxos) { helpers.createUtxos(server, wallet, [100, 200], function(utxos) {
@ -1637,6 +1646,7 @@ describe('Copay server', function() {
var before = _.clone(db); var before = _.clone(db);
db.length.should.above(1); db.length.should.above(1);
helpers.offset = 1;
helpers.createAndJoinWallet(2, 3, function(s, w) { helpers.createAndJoinWallet(2, 3, function(s, w) {
server = s; server = s;
wallet = w; wallet = w;

Loading…
Cancel
Save