commit
0c13927a6e
|
@ -0,0 +1,5 @@
|
||||||
|
.PHONY: test cover
|
||||||
|
test:
|
||||||
|
./node_modules/.bin/mocha
|
||||||
|
cover:
|
||||||
|
./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- --reporter spec test
|
|
@ -64,7 +64,8 @@ Verifier.checkTxProposal = function(data, txp) {
|
||||||
|
|
||||||
var hash = WalletUtils.getProposalHash(txp.toAddress, txp.amount, txp.message);
|
var hash = WalletUtils.getProposalHash(txp.toAddress, txp.amount, txp.message);
|
||||||
log.debug('Regenerating & verifying tx proposal hash -> Hash: ', hash, ' Signature: ', txp.proposalSignature);
|
log.debug('Regenerating & verifying tx proposal hash -> Hash: ', hash, ' Signature: ', txp.proposalSignature);
|
||||||
if (!WalletUtils.verifyMessage(hash, txp.proposalSignature, creatorSigningPubKey)) return false;
|
if (!WalletUtils.verifyMessage(hash, txp.proposalSignature, creatorSigningPubKey))
|
||||||
|
return false;
|
||||||
|
|
||||||
return Verifier.checkAddress(data, txp.changeAddress);
|
return Verifier.checkAddress(data, txp.changeAddress);
|
||||||
};
|
};
|
||||||
|
|
|
@ -430,6 +430,11 @@ API.prototype.import = function(str, cb) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* opts.doNotVerify
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
|
||||||
API.prototype.getTxProposals = function(opts, cb) {
|
API.prototype.getTxProposals = function(opts, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -439,10 +444,19 @@ API.prototype.getTxProposals = function(opts, cb) {
|
||||||
var url = '/v1/txproposals/';
|
var url = '/v1/txproposals/';
|
||||||
self._doGetRequest(url, data, function(err, txps) {
|
self._doGetRequest(url, data, function(err, txps) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
var fake = false;
|
||||||
|
|
||||||
_.each(txps, function(txp) {
|
_.each(txps, function(txp) {
|
||||||
txp.decryptedMessage = _decryptProposalMessage(txp.message, data.sharedEncryptingKey);
|
txp.decryptedMessage = _decryptProposalMessage(txp.message, data.sharedEncryptingKey);
|
||||||
|
|
||||||
|
if (!opts.doNotVerify
|
||||||
|
&& !Verifier.checkTxProposal(data, txp))
|
||||||
|
fake = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (fake)
|
||||||
|
return cb(new ServerCompromisedError('Server sent fake transaction proposal'));
|
||||||
|
|
||||||
return cb(null, txps);
|
return cb(null, txps);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
97
package.json
97
package.json
|
@ -1,49 +1,52 @@
|
||||||
{
|
{
|
||||||
"name": "copay-server",
|
"name": "bitcore-wallet-service",
|
||||||
"description": "Copay server",
|
"description": "A service for Mutisig HD Bitcoin Wallets",
|
||||||
"author": "isocolsky",
|
"author": "BitPay Inc",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"bitcoin",
|
"bitcoin",
|
||||||
"copay",
|
"copay",
|
||||||
"multisig",
|
"multisig",
|
||||||
"wallet"
|
"wallet"
|
||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"url": "git@github.com:isocolsky/copay-lib.git",
|
"url": "git@github.com:bitpay/bitcore-wallet-service.git",
|
||||||
"type": "git"
|
"type": "git"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/isocolsky/copay-lib/issues"
|
"url": "https://github.com/bitpay/bitcore-wallet-service/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "^0.9.0",
|
"async": "^0.9.0",
|
||||||
"bitcore": "git+https://github.com/eordano/bitcore.git#7e88167891811163071ae35dc3dbb705ab6ccff8",
|
"bitcore": "git+https://github.com/eordano/bitcore.git#7e88167891811163071ae35dc3dbb705ab6ccff8",
|
||||||
"bitcore-explorers": "^0.9.1",
|
"bitcore-explorers": "^0.9.1",
|
||||||
"body-parser": "^1.11.0",
|
"body-parser": "^1.11.0",
|
||||||
"commander": "^2.6.0",
|
"commander": "^2.6.0",
|
||||||
"express": "^4.10.0",
|
"express": "^4.10.0",
|
||||||
"inherits": "^2.0.1",
|
"inherits": "^2.0.1",
|
||||||
"leveldown": "^0.10.0",
|
"leveldown": "^0.10.0",
|
||||||
"levelup": "^0.19.0",
|
"levelup": "^0.19.0",
|
||||||
"lodash": "^3.2.0",
|
"lodash": "^3.2.0",
|
||||||
"morgan": "*",
|
"morgan": "*",
|
||||||
"npmlog": "^0.1.1",
|
"npmlog": "^0.1.1",
|
||||||
"preconditions": "^1.0.7",
|
"preconditions": "^1.0.7",
|
||||||
"qr-image": "*",
|
"qr-image": "*",
|
||||||
"request": "^2.53.0",
|
"request": "^2.53.0",
|
||||||
"sjcl": "^1.0.2",
|
"sjcl": "^1.0.2",
|
||||||
"uuid": "*"
|
"uuid": "*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "^1.9.1",
|
"chai": "^1.9.1",
|
||||||
"mocha": "^1.18.2",
|
"mocha": "^1.18.2",
|
||||||
"sinon": "^1.10.3",
|
"sinon": "^1.10.3",
|
||||||
"memdown": "^1.0.0",
|
"memdown": "^1.0.0",
|
||||||
"jsdoc": "^3.3.0",
|
"jsdoc": "^3.3.0",
|
||||||
"supertest": "*"
|
"supertest": "*",
|
||||||
},
|
"istanbul": "*"
|
||||||
"scripts": {
|
},
|
||||||
"start": "node server.js"
|
"scripts": {
|
||||||
}
|
"start": "node server.js",
|
||||||
|
"coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- --reporter spec test",
|
||||||
|
"test": "./node_modules/.bin/mocha"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,7 +202,7 @@ describe('client API ', function() {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
|
|
||||||
// Get right response
|
// Get right response
|
||||||
var data = clients[0]._load(function(err, data) {
|
clients[0]._load(function(err, data) {
|
||||||
var url = '/v1/wallets/';
|
var url = '/v1/wallets/';
|
||||||
clients[0]._doGetRequest(url, data, function(err, x) {
|
clients[0]._doGetRequest(url, data, function(err, x) {
|
||||||
|
|
||||||
|
@ -316,6 +316,58 @@ describe('client API ', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('should detect fake addresses', function(done) {
|
||||||
|
helpers.createAndJoinWallet(clients, 2, 2, function(err) {
|
||||||
|
should.not.exist(err);
|
||||||
|
|
||||||
|
// Get right response
|
||||||
|
clients[0]._load(function(err, data) {
|
||||||
|
var url = '/v1/addresses/';
|
||||||
|
clients[0]._doPostRequest(url, {}, data, function(err, address) {
|
||||||
|
|
||||||
|
// Tamper data
|
||||||
|
address.address = '2N86pNEpREGpwZyHVC5vrNUCbF9nM1Geh4K';
|
||||||
|
|
||||||
|
// Tamper response
|
||||||
|
clients[1]._doPostRequest = sinon.stub().yields(null, address);
|
||||||
|
|
||||||
|
// Grab real response
|
||||||
|
clients[1].createAddress(function(err, x0) {
|
||||||
|
err.code.should.contain('SERVERCOMPROMISED');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should detect fake public keys', function(done) {
|
||||||
|
helpers.createAndJoinWallet(clients, 2, 2, function(err) {
|
||||||
|
should.not.exist(err);
|
||||||
|
|
||||||
|
// Get right response
|
||||||
|
clients[0]._load(function(err, data) {
|
||||||
|
var url = '/v1/addresses/';
|
||||||
|
clients[0]._doPostRequest(url, {}, data, function(err, address) {
|
||||||
|
console.log('[clientApi.js.326:address:]', address); //TODO
|
||||||
|
|
||||||
|
// Tamper data
|
||||||
|
address.publicKeys = ['0322defe0c3eb9fcd8bc01878e6dbca7a6846880908d214b50a752445040cc5c54',
|
||||||
|
'02bf3aadc17131ca8144829fa1883c1ac0a8839067af4bca47a90ccae63d0d8037'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Tamper response
|
||||||
|
clients[1]._doPostRequest = sinon.stub().yields(null, address);
|
||||||
|
|
||||||
|
// Grab real response
|
||||||
|
clients[1].createAddress(function(err, x0) {
|
||||||
|
err.code.should.contain('SERVERCOMPROMISED');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -362,6 +414,184 @@ describe('client API ', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('Transaction Proposals Creation and Locked funds', function() {
|
||||||
|
it('Should lock and release funds', function(done) {
|
||||||
|
helpers.createAndJoinWallet(clients, 2, 2, function(err, w) {
|
||||||
|
clients[0].createAddress(function(err, x0) {
|
||||||
|
should.not.exist(err);
|
||||||
|
should.exist(x0.address);
|
||||||
|
blockExplorerMock.setUtxo(x0, 1, 2);
|
||||||
|
blockExplorerMock.setUtxo(x0, 1, 2);
|
||||||
|
var opts = {
|
||||||
|
amount: 120000000,
|
||||||
|
toAddress: 'n2TBMPzPECGUfcT2EByiTJ12TPZkhN2mN5',
|
||||||
|
message: 'hola 1-1',
|
||||||
|
};
|
||||||
|
clients[0].sendTxProposal(opts, function(err, x) {
|
||||||
|
should.not.exist(err);
|
||||||
|
|
||||||
|
clients[0].sendTxProposal(opts, function(err, y) {
|
||||||
|
err.code.should.contain('INSUFFICIENTFUNDS');
|
||||||
|
|
||||||
|
clients[0].rejectTxProposal(x, 'no', function(err, z) {
|
||||||
|
should.not.exist(err);
|
||||||
|
z.status.should.equal('rejected');
|
||||||
|
clients[0].sendTxProposal(opts, function(err, x) {
|
||||||
|
should.not.exist(err);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('Should keep message and refusal texts', function(done) {
|
||||||
|
var msg = 'abcdefg';
|
||||||
|
helpers.createAndJoinWallet(clients, 2, 3, function(err, w) {
|
||||||
|
clients[0].createAddress(function(err, x0) {
|
||||||
|
should.not.exist(err);
|
||||||
|
blockExplorerMock.setUtxo(x0, 10, 2);
|
||||||
|
var opts = {
|
||||||
|
amount: 10000,
|
||||||
|
toAddress: 'n2TBMPzPECGUfcT2EByiTJ12TPZkhN2mN5',
|
||||||
|
message: msg,
|
||||||
|
};
|
||||||
|
clients[0].sendTxProposal(opts, function(err, x) {
|
||||||
|
should.not.exist(err);
|
||||||
|
clients[1].rejectTxProposal(x, 'xx', function(err, tx1) {
|
||||||
|
should.not.exist(err);
|
||||||
|
clients[2].getTxProposals({}, function(err, txs) {
|
||||||
|
should.not.exist(err);
|
||||||
|
txs[0].decryptedMessage.should.equal(msg);
|
||||||
|
_.values(txs[0].actions)[0].comment.should.equal('xx');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should detect fake tx proposals (wrong signature)', function(done) {
|
||||||
|
helpers.createAndJoinWallet(clients, 2, 2, function(err) {
|
||||||
|
should.not.exist(err);
|
||||||
|
|
||||||
|
clients[0].createAddress(function(err, x0) {
|
||||||
|
should.not.exist(err);
|
||||||
|
blockExplorerMock.setUtxo(x0, 10, 2);
|
||||||
|
var opts = {
|
||||||
|
amount: 10000,
|
||||||
|
toAddress: 'n2TBMPzPECGUfcT2EByiTJ12TPZkhN2mN5',
|
||||||
|
message: 'hola',
|
||||||
|
};
|
||||||
|
clients[0].sendTxProposal(opts, function(err, x) {
|
||||||
|
should.not.exist(err);
|
||||||
|
|
||||||
|
|
||||||
|
// Get right response
|
||||||
|
clients[0]._load(function(err, data) {
|
||||||
|
var url = '/v1/txproposals/';
|
||||||
|
clients[0]._doGetRequest(url, data, function(err, txps) {
|
||||||
|
|
||||||
|
// Tamper data
|
||||||
|
txps[0].proposalSignature = '304402206e4a1db06e00068582d3be41cfc795dcf702451c132581e661e7241ef34ca19202203e17598b4764913309897d56446b51bc1dcd41a25d90fdb5f87a6b58fe3a6920';
|
||||||
|
|
||||||
|
// Tamper response
|
||||||
|
clients[0]._doGetRequest = sinon.stub().yields(null, txps);
|
||||||
|
|
||||||
|
// Grab real response
|
||||||
|
clients[0].getTxProposals({}, function(err, txps) {
|
||||||
|
should.exist(err);
|
||||||
|
err.code.should.contain('SERVERCOMPROMISED');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should detect fake tx proposals (tampered amount)', function(done) {
|
||||||
|
helpers.createAndJoinWallet(clients, 2, 2, function(err) {
|
||||||
|
should.not.exist(err);
|
||||||
|
|
||||||
|
clients[0].createAddress(function(err, x0) {
|
||||||
|
should.not.exist(err);
|
||||||
|
blockExplorerMock.setUtxo(x0, 10, 2);
|
||||||
|
var opts = {
|
||||||
|
amount: 10000,
|
||||||
|
toAddress: 'n2TBMPzPECGUfcT2EByiTJ12TPZkhN2mN5',
|
||||||
|
message: 'hola',
|
||||||
|
};
|
||||||
|
clients[0].sendTxProposal(opts, function(err, x) {
|
||||||
|
should.not.exist(err);
|
||||||
|
|
||||||
|
|
||||||
|
// Get right response
|
||||||
|
clients[0]._load(function(err, data) {
|
||||||
|
var url = '/v1/txproposals/';
|
||||||
|
clients[0]._doGetRequest(url, data, function(err, txps) {
|
||||||
|
|
||||||
|
// Tamper data
|
||||||
|
txps[0].amount = 100000;
|
||||||
|
|
||||||
|
// Tamper response
|
||||||
|
clients[0]._doGetRequest = sinon.stub().yields(null, txps);
|
||||||
|
|
||||||
|
// Grab real response
|
||||||
|
clients[0].getTxProposals({}, function(err, txps) {
|
||||||
|
should.exist(err);
|
||||||
|
err.code.should.contain('SERVERCOMPROMISED');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should detect fake tx proposals (change address not it wallet)', function(done) {
|
||||||
|
helpers.createAndJoinWallet(clients, 2, 2, function(err) {
|
||||||
|
should.not.exist(err);
|
||||||
|
|
||||||
|
clients[0].createAddress(function(err, x0) {
|
||||||
|
should.not.exist(err);
|
||||||
|
blockExplorerMock.setUtxo(x0, 10, 2);
|
||||||
|
var opts = {
|
||||||
|
amount: 10000,
|
||||||
|
toAddress: 'n2TBMPzPECGUfcT2EByiTJ12TPZkhN2mN5',
|
||||||
|
message: 'hola',
|
||||||
|
};
|
||||||
|
clients[0].sendTxProposal(opts, function(err, x) {
|
||||||
|
should.not.exist(err);
|
||||||
|
|
||||||
|
|
||||||
|
// Get right response
|
||||||
|
clients[0]._load(function(err, data) {
|
||||||
|
var url = '/v1/txproposals/';
|
||||||
|
clients[0]._doGetRequest(url, data, function(err, txps) {
|
||||||
|
// Tamper data
|
||||||
|
txps[0].changeAddress.address = 'n2TBMPzPECGUfcT2EByiTJ12TPZkhN2mN5';
|
||||||
|
|
||||||
|
// Tamper response
|
||||||
|
clients[0]._doGetRequest = sinon.stub().yields(null, txps);
|
||||||
|
|
||||||
|
// Grab real response
|
||||||
|
clients[0].getTxProposals({}, function(err, txps) {
|
||||||
|
should.exist(err);
|
||||||
|
err.code.should.contain('SERVERCOMPROMISED');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
describe('Transactions Signatures and Rejection', function() {
|
describe('Transactions Signatures and Rejection', function() {
|
||||||
it('Send and broadcast in 1-1 wallet', function(done) {
|
it('Send and broadcast in 1-1 wallet', function(done) {
|
||||||
helpers.createAndJoinWallet(clients, 1, 1, function(err, w) {
|
helpers.createAndJoinWallet(clients, 1, 1, function(err, w) {
|
||||||
|
@ -525,151 +755,4 @@ describe('client API ', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Transaction proposals and locked funds', function() {
|
|
||||||
it('Should lock and release funds', function(done) {
|
|
||||||
helpers.createAndJoinWallet(clients, 2, 2, function(err, w) {
|
|
||||||
clients[0].createAddress(function(err, x0) {
|
|
||||||
should.not.exist(err);
|
|
||||||
should.exist(x0.address);
|
|
||||||
blockExplorerMock.setUtxo(x0, 1, 2);
|
|
||||||
blockExplorerMock.setUtxo(x0, 1, 2);
|
|
||||||
var opts = {
|
|
||||||
amount: 120000000,
|
|
||||||
toAddress: 'n2TBMPzPECGUfcT2EByiTJ12TPZkhN2mN5',
|
|
||||||
message: 'hola 1-1',
|
|
||||||
};
|
|
||||||
clients[0].sendTxProposal(opts, function(err, x) {
|
|
||||||
should.not.exist(err);
|
|
||||||
|
|
||||||
clients[0].sendTxProposal(opts, function(err, y) {
|
|
||||||
err.code.should.contain('INSUFFICIENTFUNDS');
|
|
||||||
|
|
||||||
clients[0].rejectTxProposal(x, 'no', function(err, z) {
|
|
||||||
should.not.exist(err);
|
|
||||||
z.status.should.equal('rejected');
|
|
||||||
clients[0].sendTxProposal(opts, function(err, x) {
|
|
||||||
should.not.exist(err);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
describe('TODO', function(x) {
|
|
||||||
it('should detect fake addresses ', function(done) {
|
|
||||||
var response = {
|
|
||||||
createdOn: 1424105995,
|
|
||||||
address: '2N3fA6wDtnebzywPkGuNK9KkFaEzgbPRRTq',
|
|
||||||
path: 'm/2147483647/0/8',
|
|
||||||
publicKeys: ['03f6a5fe8db51bfbaf26ece22a3e3bc242891a47d3048fc70bc0e8c03a071ad76f']
|
|
||||||
};
|
|
||||||
var request = sinon.mock().yields(null, {
|
|
||||||
statusCode: 200
|
|
||||||
}, response);
|
|
||||||
client.request = request;
|
|
||||||
client.createAddress(function(err, x) {
|
|
||||||
err.code.should.equal('SERVERCOMPROMISED');
|
|
||||||
err.message.should.contain('fake address');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe('#getTxProposals', function() {
|
|
||||||
it('should return tx proposals and decrypt message', function(done) {
|
|
||||||
client.storage.fs.readFile = sinon.stub().yields(null, JSON.stringify(TestData.storage.complete11));
|
|
||||||
var request = sinon.mock().yields(null, {
|
|
||||||
statusCode: 200
|
|
||||||
}, TestData.serverResponse.pendingTxs);
|
|
||||||
client.request = request;
|
|
||||||
|
|
||||||
client.getTxProposals({}, function(err, x) {
|
|
||||||
should.not.exist(err);
|
|
||||||
x.length.should.equal(1);
|
|
||||||
x[0].id.should.equal(TestData.serverResponse.pendingTxs[0].id);
|
|
||||||
x[0].decryptedMessage.should.equal('hola');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#sendTxProposal ', function() {
|
|
||||||
it('should send tx proposal with encrypted message', function(done) {
|
|
||||||
client.storage.fs.readFile = sinon.stub().yields(null, JSON.stringify(TestData.storage.complete11));
|
|
||||||
var response = {};
|
|
||||||
var request = sinon.mock().yields(null, {
|
|
||||||
statusCode: 200
|
|
||||||
}, response);
|
|
||||||
client.request = request;
|
|
||||||
|
|
||||||
var args = {
|
|
||||||
toAddress: '2N3fA6wDtnebzywPkGuNK9KkFaEzgbPRRTq',
|
|
||||||
amount: '200bit',
|
|
||||||
message: 'some message',
|
|
||||||
};
|
|
||||||
client.sendTxProposal(args, function(err) {
|
|
||||||
var callArgs = request.getCall(0).args[0].body;
|
|
||||||
callArgs.toAddress.should.equal(args.toAddress);
|
|
||||||
callArgs.amount.should.equal(20000);
|
|
||||||
callArgs.message.should.not.equal(args.message);
|
|
||||||
var decryptedMsg = WalletUtils.decryptMessage(callArgs.message, TestData.storage.complete11.sharedEncryptingKey);
|
|
||||||
decryptedMsg.should.equal(args.message);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#signTxProposal ', function() {
|
|
||||||
it.skip('should sign tx proposal', function(done) {});
|
|
||||||
|
|
||||||
it('should detect fake tx proposal signature', function(done) {
|
|
||||||
client.storage.fs.readFile = sinon.stub().yields(null, JSON.stringify(TestData.storage.complete11));
|
|
||||||
var txp = {
|
|
||||||
creatorId: '56cb00afd85f4f37fa900ac4e367676f2eb6189a773633eb9f119eb21a22ba44',
|
|
||||||
toAddress: '2N3fA6wDtnebzywPkGuNK9KkFaEzgbPRRTq',
|
|
||||||
amount: 100000,
|
|
||||||
message: 'some message',
|
|
||||||
proposalSignature: 'dummy',
|
|
||||||
changeAddress: {
|
|
||||||
address: '2N3fA6wDtnebzywPkGuNK9KkFaEzgbPRRTq',
|
|
||||||
path: 'm/2147483647/0/7',
|
|
||||||
publicKeys: ['03f6a5fe8db51bfbaf26ece22a3e3bc242891a47d3048fc70bc0e8c03a071ad76f']
|
|
||||||
},
|
|
||||||
};
|
|
||||||
client.signTxProposal(txp, function(err) {
|
|
||||||
err.code.should.equal('SERVERCOMPROMISED');
|
|
||||||
err.message.should.contain('fake transaction proposal');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should detect fake tx proposal change address', function(done) {
|
|
||||||
var txp = {
|
|
||||||
toAddress: '2N3fA6wDtnebzywPkGuNK9KkFaEzgbPRRTq',
|
|
||||||
amount: 100000,
|
|
||||||
message: 'some message',
|
|
||||||
proposalSignature: '3045022100e2d9ef7ed592217ab2256fdcf9627075f35ecdf431dde8c9a9c9422b7b1fb00f02202bc8ce066db4401bdbafb2492c3138debbc69c4c01db50d8c22a227e744c8906',
|
|
||||||
changeAddress: {
|
|
||||||
address: '2N3fA6wDtnebzywPkGuNK9KkFaEzgbPRRTq',
|
|
||||||
path: 'm/2147483647/0/8',
|
|
||||||
publicKeys: ['03f6a5fe8db51bfbaf26ece22a3e3bc242891a47d3048fc70bc0e8c03a071ad76f']
|
|
||||||
},
|
|
||||||
};
|
|
||||||
client.signTxProposal(txp, function(err) {
|
|
||||||
err.code.should.equal('SERVERCOMPROMISED');
|
|
||||||
err.message.should.contain('fake transaction proposal');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue