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 WALLET_CRITICAL_DATA = ['copayerId', 'xPrivKey', 'm', 'walletPrivKey', 'publicKeyRing'];
var WALLET_CRITICAL_DATA = ['xPrivKey', 'm', 'publicKeyRing'];
function _createProposalOpts(opts, signingKey) {
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 HDPath = require('./hdpath');
var HDPath = require('../hdpath');
function AddressManager(opts) {
this.receiveAddressIndex = 0;

15
lib/model/copayer.js

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

27
lib/server.js

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

2
test/hdpath.js

@ -1,6 +1,6 @@
'use strict';
var HDPath = require('../lib/model/hdpath');
var HDPath = require('../lib/hdpath');
describe('HDPath model', 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) {
var server = new CopayServer();
var copayerIds = [];
var offset = helpers.offset || 0;
var walletOpts = {
name: 'a wallet',
@ -53,11 +54,12 @@ helpers.createAndJoinWallet = function(m, n, cb) {
var copayerOpts = {
walletId: walletId,
name: 'copayer ' + (i + 1),
xPubKey: TestData.copayers[i].xPubKey,
xPubKeySignature: TestData.copayers[i].xPubKeySignature,
xPubKey: TestData.copayers[i + offset].xPubKey,
xPubKeySignature: TestData.copayers[i + offset].xPubKeySignature,
};
server.joinWallet(copayerOpts, function(err, result) {
should.not.exist(err);
copayerIds.push(result.copayerId);
return cb(err);
});
@ -198,12 +200,14 @@ describe('Copay server', function() {
CopayServer.initialize({
storage: storage
});
helpers.offset = 0;
});
describe('#getInstanceWithAuth', function() {
beforeEach(function() {});
it('should get server instance for existing copayer', function(done) {
helpers.createAndJoinWallet(1, 2, function(s, wallet) {
var xpriv = TestData.copayers[0].xPrivKey;
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) {
var N = 5;
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) {
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) {
describe('Wallet not complete tests', 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);
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));
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();
});
});
@ -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) {
helpers.createUtxos(server, wallet, [100, 200], function(utxos) {
@ -1637,6 +1646,7 @@ describe('Copay server', function() {
var before = _.clone(db);
db.length.should.above(1);
helpers.offset = 1;
helpers.createAndJoinWallet(2, 3, function(s, w) {
server = s;
wallet = w;

Loading…
Cancel
Save