add test
This commit is contained in:
parent
d56dcd41de
commit
196ae2a448
|
@ -62,35 +62,49 @@ function API(opts) {
|
|||
};
|
||||
|
||||
|
||||
API.prototype._tryToComplete = function(data, cb) {
|
||||
var self = this;
|
||||
var isCorrupted;
|
||||
|
||||
var url = '/v1/wallets/';
|
||||
self._doGetRequest(url, data, function(err, wallet) {
|
||||
if (err) return cb(err);
|
||||
if (wallet.n > 0 && wallet.status === 'complete' && !data.verified) {
|
||||
API.prototype._isWalletCorrupt = function(wallet, data) {
|
||||
var pubKey = Bitcore.PrivateKey.fromString(data.walletPrivKey).toPublicKey().toString();
|
||||
var fake = [];
|
||||
|
||||
if (data.n != wallet.copayers.length)
|
||||
return true;
|
||||
|
||||
var uniq = [];
|
||||
_.each(wallet.copayers, function(copayer) {
|
||||
if (uniq[copayer.xPubKey]++)
|
||||
return true;
|
||||
|
||||
if (!SignUtils.verify(copayer.xPubKey, copayer.xPubKeySignature, pubKey)) {
|
||||
fake.push(copayer);
|
||||
}
|
||||
});
|
||||
if (fake.length > 0) {
|
||||
isCorrupted = true;
|
||||
return fake.length > 0;
|
||||
};
|
||||
|
||||
|
||||
API.prototype._tryToComplete = function(data, cb) {
|
||||
var self = this;
|
||||
|
||||
var url = '/v1/wallets/';
|
||||
self._doGetRequest(url, data, function(err, wallet) {
|
||||
if (err) return cb(err);
|
||||
|
||||
if (wallet.status === 'complete' && !data.verified) {
|
||||
|
||||
if (self._isWalletCorrupt(wallet, data)) {
|
||||
data.verified = 'corrupt';
|
||||
} else {
|
||||
data.verified = 'ok';
|
||||
}
|
||||
self.storage.save(data, function(err) {
|
||||
if (isCorrupted) {
|
||||
if (data.verified == 'corrupt') {
|
||||
return cb('Some copayers in the wallet could not be verified to have known the wallet secret');
|
||||
}
|
||||
return cb(err, data);
|
||||
});
|
||||
} else {
|
||||
return cb('Wallet Incomplete');
|
||||
}
|
||||
return cb(null, data);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -99,11 +113,11 @@ API.prototype._tryToComplete = function(data, cb) {
|
|||
|
||||
API.prototype._loadAndCheck = function(cb) {
|
||||
var self = this;
|
||||
|
||||
this.storage.load(function(err, data) {
|
||||
if (err || !data) {
|
||||
return cb(err || 'Wallet file not found.');
|
||||
}
|
||||
|
||||
if (data.verified == 'corrupt') {
|
||||
return cb('The wallet is tagged as corrupt. Some of the copayers cannot be verified to have known the wallet secret.');
|
||||
}
|
||||
|
@ -131,10 +145,13 @@ API.prototype._doRequest = function(method, url, args, data, cb) {
|
|||
body: args,
|
||||
json: true,
|
||||
};
|
||||
log.verbose('Request Args', util.inspect(args));
|
||||
log.verbose('Request Args', util.inspect(args, {
|
||||
depth: 10
|
||||
}));
|
||||
this.request(args, function(err, res, body) {
|
||||
log.verbose('Response:', err, body);
|
||||
|
||||
log.verbose(util.inspect(body, {
|
||||
depth: 10
|
||||
}));
|
||||
if (err) return cb(err);
|
||||
if (res.statusCode != 200) {
|
||||
_parseError(body);
|
||||
|
@ -279,8 +296,7 @@ API.prototype.getStatus = function(cb) {
|
|||
API.prototype.sendTxProposal = function(inArgs, cb) {
|
||||
var self = this;
|
||||
|
||||
this._loadAndCheck(
|
||||
function(err, data) {
|
||||
this._loadAndCheck(function(err, data) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var args = _createProposalOpts(inArgs, data.signingPrivKey);
|
||||
|
@ -293,8 +309,7 @@ API.prototype.sendTxProposal = function(inArgs, cb) {
|
|||
API.prototype.createAddress = function(cb) {
|
||||
var self = this;
|
||||
|
||||
this._loadAndCheck(
|
||||
function(err, data) {
|
||||
this._loadAndCheck(function(err, data) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var url = '/v1/addresses/';
|
||||
|
|
|
@ -7,30 +7,7 @@ var should = chai.should();
|
|||
var Client = require('../../lib/client');
|
||||
var API = Client.API;
|
||||
var Bitcore = require('bitcore');
|
||||
|
||||
var wallet11 = {
|
||||
"m": 1,
|
||||
"n": 1,
|
||||
"walletPrivKey": "{\"bn\":\"6b862ffbfc90a37a2fedbbcfea91c6a4e49f49b6aaa322b6e16c46bfdbe71a38\",\"compressed\":true,\"network\":\"livenet\"}",
|
||||
"network": "testnet",
|
||||
"xPrivKey": "tprv8ZgxMBicQKsPeisyNJteQXZnb7CnhYc4TVAyxxicXuxMjK1rmaqVq1xnXtbSTPxUKKL9h5xJhUvw1AKfDD3i98A82eJWSYRWYjmPksewFKR",
|
||||
"copayerId": "a84daa08-17b5-45ad-84cd-e275f3b07123",
|
||||
"signingPrivKey": "42798f82c4ed9ace4d66335165071edf180e70bc0fc08dacb3e35185a2141d5b",
|
||||
"publicKeyRing": ["tpubD6NzVbkrYhZ4YBumFxZEowDuA8iirsny2nmmFUkuxBkkZoGdPyf61Waei3tDYvVa1yqW82Xhmmd6oiibeDyM1MS3zTiky7Yg75UEV9oQhFJ"]
|
||||
};
|
||||
|
||||
var incompleteWallet22 = {
|
||||
"m": 2,
|
||||
"n": 2,
|
||||
"walletPrivKey": "L3XSE3KNjQM1XRP1h5yMCSKsN4hs3D6eK7Vwn5M88Bs6jpCnXR3R",
|
||||
"network": "testnet",
|
||||
"secret": "d9cf45a1-6793-4df4-94df-c99d2c2e1fe9:bc2488c1b83e455a4b908a0d0aeaf70351efc48fbcaa454bffefdef419a5ee6a:T",
|
||||
"xPrivKey": "tprv8ZgxMBicQKsPdoC5DGtnXx7fp7YnUtGv8b7fU2oDQfDpHFQh1QCgpKc8GHpdsBN5THaHYMV5LgD5cP5NYaacGVr786p3mVLSZff9berTV8h",
|
||||
"copayerId": "c3a33ca0-37cf-4e80-b745-71272683835c",
|
||||
"signingPrivKey": "6e129c4996666e5ecdf78aed626c01977fa19eacce6659738ebe065f86523e9b",
|
||||
"publicKeyRing": []
|
||||
};
|
||||
|
||||
var TestData = require('./clienttestdata');
|
||||
|
||||
describe(' client API ', function() {
|
||||
|
||||
|
@ -39,17 +16,84 @@ describe('client API', function() {
|
|||
beforeEach(function() {
|
||||
|
||||
var fsmock = {};;
|
||||
fsmock.readFile = sinon.mock().yields(null, JSON.stringify(wallet11));
|
||||
fsmock.readFile = sinon.mock().yields(null, JSON.stringify(TestData.storage.wallet11));
|
||||
fsmock.writeFile = sinon.mock().yields();
|
||||
var storage = new Client.FileStorage({
|
||||
filename: 'dummy',
|
||||
fs: fsmock,
|
||||
});
|
||||
client = new Client({
|
||||
storage: storage,
|
||||
storage: storage
|
||||
});
|
||||
});
|
||||
|
||||
describe(' _tryToComplete ', function() {
|
||||
it('should complete a wallet ', function(done) {
|
||||
var request = sinon.stub();
|
||||
|
||||
// Wallet request
|
||||
request.onCall(0).yields(null, {
|
||||
statusCode: 200,
|
||||
}, TestData.serverResponse.completeWallet);
|
||||
request.onCall(1).yields(null, {
|
||||
statusCode: 200,
|
||||
}, "pepe");
|
||||
|
||||
client.request = request;
|
||||
client.storage.fs.readFile = sinon.stub().yields(null, JSON.stringify(TestData.storage.incompleteWallet22));
|
||||
client.getBalance(function(err, x) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
it('should complain wallet is not complete ', function(done) {
|
||||
var request = sinon.stub();
|
||||
|
||||
// Wallet request
|
||||
request.onCall(0).yields(null, {
|
||||
statusCode: 200,
|
||||
}, TestData.serverResponse.incompleteWallet);
|
||||
|
||||
client.request = request;
|
||||
client.storage.fs.readFile = sinon.stub().yields(null, JSON.stringify(TestData.storage.incompleteWallet22));
|
||||
client.createAddress(function(err, x) {
|
||||
err.should.contain('Incomplete');
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
it(' should reject wallets with bad signatures', function(done) {
|
||||
var request = sinon.stub();
|
||||
// Wallet request
|
||||
request.onCall(0).yields(null, {
|
||||
statusCode: 200,
|
||||
}, TestData.serverResponse.corruptWallet22);
|
||||
|
||||
client.request = request;
|
||||
client.storage.fs.readFile = sinon.stub().yields(null, JSON.stringify(TestData.storage.incompleteWallet22));
|
||||
client.createAddress(function(err, x) {
|
||||
err.should.contain('verified');
|
||||
done();
|
||||
});
|
||||
})
|
||||
it(' should reject wallets with missing signatures ', function(done) {
|
||||
var request = sinon.stub();
|
||||
// Wallet request
|
||||
request.onCall(0).yields(null, {
|
||||
statusCode: 200,
|
||||
}, TestData.serverResponse.corruptWallet222);
|
||||
|
||||
client.request = request;
|
||||
client.storage.fs.readFile = sinon.stub().yields(null, JSON.stringify(TestData.storage.incompleteWallet22));
|
||||
client.createAddress(function(err, x) {
|
||||
err.should.contain('verified');
|
||||
done();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe(' createAddress ', function() {
|
||||
it(' should check address ', function(done) {
|
||||
|
||||
|
@ -88,20 +132,5 @@ describe('client API', function() {
|
|||
done();
|
||||
});
|
||||
})
|
||||
|
||||
it('should complain wallet is not complete', function(done) {
|
||||
var request = sinon.mock().yields(null, {
|
||||
statusCode: 200
|
||||
}, {
|
||||
dummy: true
|
||||
});
|
||||
client.request = request;
|
||||
client.storage.fs.readFile = sinon.mock().yields(null, JSON.stringify(incompleteWallet22));
|
||||
client.createAddress(function(err, x) {
|
||||
err.should.contain('Incomplete');
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
var storage = {
|
||||
wallet11: {
|
||||
"m": 1,
|
||||
"n": 1,
|
||||
"walletPrivKey": "{\"bn\":\"6b862ffbfc90a37a2fedbbcfea91c6a4e49f49b6aaa322b6e16c46bfdbe71a38\",\"compressed\":true,\"network\":\"livenet\"}",
|
||||
"network": "testnet",
|
||||
"xPrivKey": "tprv8ZgxMBicQKsPeisyNJteQXZnb7CnhYc4TVAyxxicXuxMjK1rmaqVq1xnXtbSTPxUKKL9h5xJhUvw1AKfDD3i98A82eJWSYRWYjmPksewFKR",
|
||||
"copayerId": "a84daa08-17b5-45ad-84cd-e275f3b07123",
|
||||
"signingPrivKey": "42798f82c4ed9ace4d66335165071edf180e70bc0fc08dacb3e35185a2141d5b",
|
||||
"publicKeyRing": ["tpubD6NzVbkrYhZ4YBumFxZEowDuA8iirsny2nmmFUkuxBkkZoGdPyf61Waei3tDYvVa1yqW82Xhmmd6oiibeDyM1MS3zTiky7Yg75UEV9oQhFJ"]
|
||||
},
|
||||
|
||||
incompleteWallet22: {
|
||||
"m": 2,
|
||||
"n": 2,
|
||||
"walletPrivKey":"L2Fu6TM1AqSNBaQcjgjvYjGf3EzS3MVSTwEeTw3bvy52x7ZkffWj",
|
||||
"network": "testnet",
|
||||
"secret": "b6f57154-0df8-4845-a61d-47ecd648c2d4:eab5a55d9214845ee8d13ea1033e42ec8d7f780ae6e521d830252a80433e91a5:T",
|
||||
"xPrivKey": "tprv8ZgxMBicQKsPfFVXegcKyJjy2Y5DSrHNrtGBHG1f9pPX75QQdHwHGjWUtR7cCUXV7QcCCDon4cieHWTYscy8M7oXwF3qd3ssfBiV9M68bPB",
|
||||
"copayerId": "3fc03e7a-6ebc-409b-a4b7-45b14d5a8199",
|
||||
"signingPrivKey": "0d3c796fb12e387c4b5a5c566312b2b22fa0553ca041d859e3f0987215ca3a4f",
|
||||
"publicKeyRing": []
|
||||
}
|
||||
};
|
||||
|
||||
var serverResponse = {
|
||||
completeWallet: {
|
||||
m: 2,
|
||||
n: 2,
|
||||
status: 'complete',
|
||||
publicKeyRing: ['tpubD6NzVbkrYhZ4Y1CGuCZ88eZvhDSTjAqjotZWGXC7e4GEoyXq3SQgZK9iRz4qC2h8MrzqrYBndCMQDiaaLdqpY8ihYmJC9Msvns83jGopb3E',
|
||||
'tpubD6NzVbkrYhZ4WSuBBLyubi8DHMipbFQcZoLJHjb21gEtznCEJMJhwkvaSshHVLtq8C1uNMKD4GtADVYY6WZt1cyT218JUm3PiNKYVkMATWV'
|
||||
],
|
||||
addressIndex: 0,
|
||||
copayers: [{
|
||||
xPubKey: 'tpubD6NzVbkrYhZ4Y1CGuCZ88eZvhDSTjAqjotZWGXC7e4GEoyXq3SQgZK9iRz4qC2h8MrzqrYBndCMQDiaaLdqpY8ihYmJC9Msvns83jGopb3E',
|
||||
xPubKeySignature: '3045022100ef86122060bbb7681db05486f8b1ee1579c5800e8da78182a87384f05542a4cc0220215ce7ef8c484b64178779414efdf2b7033d25ed752eebf4eb3241f9fa8e6b67',
|
||||
}, {
|
||||
xPubKey: 'tpubD6NzVbkrYhZ4WSuBBLyubi8DHMipbFQcZoLJHjb21gEtznCEJMJhwkvaSshHVLtq8C1uNMKD4GtADVYY6WZt1cyT218JUm3PiNKYVkMATWV',
|
||||
xPubKeySignature: '3044022025c93b418ebdbb66a0f2b21af709420e8ae769bf054f29aaa252cb5417c46a2302205e0c8b931324736b7eea4971a48039614e19abe26e13ab0ef1547aef92b55aab',
|
||||
}],
|
||||
pubKey: ' { "x": "b2903ab878ed1316f82b859e9807e23bab3d579175563e1068d2ed9c9e37873c", "y": "5f30165915557394223a58329c1527dfa0f34f483d8aed02e0638f9124dbddef", "compressed": true }',
|
||||
network: 'testnet',
|
||||
},
|
||||
|
||||
|
||||
incompleteWallet: {
|
||||
m: 2,
|
||||
n: 2,
|
||||
status: 'pending',
|
||||
publicKeyRing: ['tpubD6NzVbkrYhZ4Y1CGuCZ88eZvhDSTjAqjotZWGXC7e4GEoyXq3SQgZK9iRz4qC2h8MrzqrYBndCMQDiaaLdqpY8ihYmJC9Msvns83jGopb3E',
|
||||
'tpubD6NzVbkrYhZ4WSuBBLyubi8DHMipbFQcZoLJHjb21gEtznCEJMJhwkvaSshHVLtq8C1uNMKD4GtADVYY6WZt1cyT218JUm3PiNKYVkMATWV'
|
||||
],
|
||||
addressIndex: 0,
|
||||
copayers: [{
|
||||
xPubKey: 'tpubD6NzVbkrYhZ4Y1CGuCZ88eZvhDSTjAqjotZWGXC7e4GEoyXq3SQgZK9iRz4qC2h8MrzqrYBndCMQDiaaLdqpY8ihYmJC9Msvns83jGopb3E',
|
||||
xPubKeySignature: '3045022100ef86122060bbb7681db05486f8b1ee1579c5800e8da78182a87384f05542a4cc0220215ce7ef8c484b64178779414efdf2b7033d25ed752eebf4eb3241f9fa8e6b67',
|
||||
}],
|
||||
pubKey: ' { "x": "b2903ab878ed1316f82b859e9807e23bab3d579175563e1068d2ed9c9e37873c", "y": "5f30165915557394223a58329c1527dfa0f34f483d8aed02e0638f9124dbddef", "compressed": true }',
|
||||
network: 'testnet',
|
||||
},
|
||||
|
||||
corruptWallet22: {
|
||||
m: 2,
|
||||
n: 2,
|
||||
status: 'complete',
|
||||
publicKeyRing: ['tpubD6NzVbkrYhZ4Y1CGuCZ88eZvhDSTjAqjotZWGXC7e4GEoyXq3SQgZK9iRz4qC2h8MrzqrYBndCMQDiaaLdqpY8ihYmJC9Msvns83jGopb3E',
|
||||
'tpubD6NzVbkrYhZ4WSuBBLyubi8DHMipbFQcZoLJHjb21gEtznCEJMJhwkvaSshHVLtq8C1uNMKD4GtADVYY6WZt1cyT218JUm3PiNKYVkMATWV'
|
||||
],
|
||||
copayers: [{
|
||||
xPubKey: 'tpubD6NzVbkrYhZ4Y1CGuCZ88eZvhDSTjAqjotZWGXC7e4GEoyXq3SQgZK9iRz4qC2h8MrzqrYBndCMQDiaaLdqpY8ihYmJC9Msvns83jGopb3E',
|
||||
xPubKeySignature: '3045022100ef86122060bbb7681db05486f8b1ee1579c5800e8da78182a87384f05542a4cc0220215ce7ef8c484b64178779414efdf2b7033d25ed752eebf4eb3241f9fa8e6b67',
|
||||
}, {
|
||||
xPubKey: 'tpubD6NzVbkrYhZ4Y1CGuCZ88eZvhDSTjAqjotZWGXC7e4GEoyXq3SQgZK9iRz4qC2h8MrzqrYBndCMQDiaaLdqpY8ihYmJC9Msvns83jGopb3E',
|
||||
xPubKeySignature: 'bababa',
|
||||
}],
|
||||
},
|
||||
corruptWallet222: {
|
||||
m: 2,
|
||||
n: 2,
|
||||
status: 'complete',
|
||||
publicKeyRing: ['tpubD6NzVbkrYhZ4Y1CGuCZ88eZvhDSTjAqjotZWGXC7e4GEoyXq3SQgZK9iRz4qC2h8MrzqrYBndCMQDiaaLdqpY8ihYmJC9Msvns83jGopb3E',
|
||||
'tpubD6NzVbkrYhZ4WSuBBLyubi8DHMipbFQcZoLJHjb21gEtznCEJMJhwkvaSshHVLtq8C1uNMKD4GtADVYY6WZt1cyT218JUm3PiNKYVkMATWV'
|
||||
],
|
||||
copayers: [{
|
||||
xPubKey: 'tpubD6NzVbkrYhZ4Y1CGuCZ88eZvhDSTjAqjotZWGXC7e4GEoyXq3SQgZK9iRz4qC2h8MrzqrYBndCMQDiaaLdqpY8ihYmJC9Msvns83jGopb3E',
|
||||
}, ],
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.serverResponse = serverResponse;
|
||||
module.exports.storage = storage;
|
Loading…
Reference in New Issue