From cf58b69bbfdf01edd109acd7fcdd143fc6ad17a3 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 17 Sep 2015 16:19:36 -0400 Subject: [PATCH] Added message verification endpoint. --- .travis.yml | 5 ++- README.md | 12 ++++++ lib/index.js | 12 +++--- lib/messages.js | 34 +++++++++++++++++ package.json | 9 ++++- test/messages.js | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 161 insertions(+), 10 deletions(-) create mode 100644 lib/messages.js create mode 100644 test/messages.js diff --git a/.travis.yml b/.travis.yml index f070f6e..cb81fca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: node_js node_js: -- '0.10' -install: npm install + - 'v0.12.7' +install: + - npm install diff --git a/README.md b/README.md index 2f9db63..2ba09bb 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,18 @@ A Bitcoin blockchain REST and web socket API service for [Bitcore Node](https:// This is a backend-only service. If you're looking for the web frontend application, take a look at https://github.com/bitpay/insight. +## Getting Started + +```bash +npm install -g bitcore-node@latest +bitcore-node create mynode +cd mynode +bitcore-node add insight-api +bitcore-node start +``` + +The API endpoints will be available by default at: 'http://localhost:3001/insight-api/` + ## Prerequisites - [Bitcore Node 0.2.x](https://github.com/bitpay/bitcore-node) diff --git a/lib/index.js b/lib/index.js index b284ffd..d990cd1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -6,6 +6,7 @@ var BlockController = require('./blocks'); var TxController = require('./transactions'); var AddressController = require('./addresses'); var StatusController = require('./status'); +var MessagesController = require('./messages'); var bitcore = require('bitcore'); var $ = bitcore.util.preconditions; var Transaction = bitcore.Transaction; @@ -77,6 +78,10 @@ InsightAPI.prototype.setupRoutes = function(app) { app.get('/peer', status.peer.bind(status)); app.get('/version', status.version.bind(status)); + // Address routes + var messages = new MessagesController(this.node); + app.get('/messages/verify', messages.verify.bind(messages)); + app.post('/messages/verify', messages.verify.bind(messages)); // Utils route /*var utils = require('../app/controllers/utils'); @@ -98,11 +103,6 @@ InsightAPI.prototype.setupRoutes = function(app) { app.get(apiPrefix + '/rates/:code', currencyRatesPlugin.getRate); } - // Address routes - var messages = require('../app/controllers/messages'); - app.get(apiPrefix + '/messages/verify', messages.verify); - app.post(apiPrefix + '/messages/verify', messages.verify); - //Home route var index = require('../app/controllers/index'); app.get('*', index.render);*/ @@ -162,4 +162,4 @@ InsightAPI.prototype.unsubscribe = function(emitter) { } }; -module.exports = InsightAPI; \ No newline at end of file +module.exports = InsightAPI; diff --git a/lib/messages.js b/lib/messages.js new file mode 100644 index 0000000..d495a23 --- /dev/null +++ b/lib/messages.js @@ -0,0 +1,34 @@ +'use strict'; + +var bitcore = require('bitcore'); +var _ = bitcore.deps._; +var Message = require('bitcore-message'); +var common = require('./common'); + +function MessagesController(node) { + this.node = node; +} + +MessagesController.prototype.verify = function(req, res) { + var address = req.body.address || req.query.address; + var signature = req.body.signature || req.query.signature; + var message = req.body.message || req.query.message; + if(_.isUndefined(address) || _.isUndefined(signature) || _.isUndefined(message)) { + return common.handleErrors({ + message: 'Missing parameters (expected "address", "signature" and "message")', + code: 1 + }, res); + } + var valid; + try { + valid = new Message(message).verify(address, signature); + } catch(err) { + return common.handleErrors({ + message: 'Unexpected error: ' + err.message, + code: 1 + }, res); + } + res.json({'result': valid}); +}; + +module.exports = MessagesController; diff --git a/package.json b/package.json index 33831b1..8dd9212 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,10 @@ { "name": "Patrick Nagurny", "email": "patrick@bitpay.com" + }, + { + "name": "Braydon Fuller", + "email": "braydon@bitpay.com" } ], "bugs": { @@ -48,7 +52,7 @@ "bitcore" ], "engines": { - "node": "*" + "node": ">=0.12.0" }, "scripts": { "test": "NODE_ENV=test mocha -R spec --recursive" @@ -57,8 +61,9 @@ "bitcoreNode": "lib", "dependencies": { "async": "*", + "lodash": "^2.4.1", "bitcore": "^0.13.3", - "lodash": "^2.4.1" + "bitcore-message": "^0.12.0" }, "devDependencies": { "mocha": "~1.16.2", diff --git a/test/messages.js b/test/messages.js new file mode 100644 index 0000000..04b321d --- /dev/null +++ b/test/messages.js @@ -0,0 +1,99 @@ +'use strict'; + +var should = require('should'); +var sinon = require('sinon'); +var MessagesController = require('../lib/messages'); +var bitcore = require('bitcore'); +var _ = require('lodash'); + +describe('Messages', function() { + + var privateKey = bitcore.PrivateKey.fromWIF('cQwApHAg8hw9AZuxiU4a7g9kFWdaemhPxVZXWiAKgJTx6dPP32fN'); + var address = 'mswTKCE2tYSFvUNnNPBKZfeNmugYL1rZMx'; + var badAddress = 'mswTKCE2tYSFvUNnNPBKZfeNmuhYL1rZMm'; + var signature = 'IA4sIwhcLMPPsYtB8tN0PI+aQuwDyl+/4Ksa89llNSAeVaRdMyyIxpo1H5N3GHbPl9LQqZ7CvaokeQgsOkK9fn4='; + var message = 'cellar door'; + + it('will verify a message (true)', function(done) { + + var controller = new MessagesController({node: {}}); + + var req = { + body: { + 'address': address, + 'signature': signature, + 'message': message + }, + query: {} + }; + var res = { + json: function(data) { + data.result.should.equal(true); + done(); + } + }; + + controller.verify(req, res); + }); + + it('will verify a message (false)', function(done) { + + var controller = new MessagesController({node: {}}); + + var req = { + body: { + 'address': address, + 'signature': signature, + 'message': 'wrong message' + }, + query: {} + }; + var res = { + json: function(data) { + data.result.should.equal(false); + done(); + } + }; + + controller.verify(req, res); + }); + + it('handle an error from message verification', function(done) { + var controller = new MessagesController({node: {}}); + var req = { + body: { + 'address': badAddress, + 'signature': signature, + 'message': message + }, + query: {} + }; + var send = sinon.stub(); + var status = sinon.stub().returns({send: send}); + var res = { + status: status, + }; + controller.verify(req, res); + status.args[0][0].should.equal(400); + send.args[0][0].should.equal('Unexpected error: Checksum mismatch. Code:1'); + done(); + }); + + it('handle error with missing parameters', function(done) { + var controller = new MessagesController({node: {}}); + var req = { + body: {}, + query: {} + }; + var send = sinon.stub(); + var status = sinon.stub().returns({send: send}); + var res = { + status: status + }; + controller.verify(req, res); + status.args[0][0].should.equal(400); + send.args[0][0].should.match(/^Missing parameters/); + done(); + }); + +});