diff --git a/docker/my-dojo/.env b/docker/my-dojo/.env index 03b2972..966583e 100644 --- a/docker/my-dojo/.env +++ b/docker/my-dojo/.env @@ -13,8 +13,8 @@ COMPOSE_CONVERT_WINDOWS_PATHS=1 DOJO_VERSION_TAG=1.3.0 DOJO_DB_VERSION_TAG=1.1.0 DOJO_BITCOIND_VERSION_TAG=1.2.0 -DOJO_NODEJS_VERSION_TAG=1.2.0 -DOJO_NGINX_VERSION_TAG=1.2.0 +DOJO_NODEJS_VERSION_TAG=1.3.0 +DOJO_NGINX_VERSION_TAG=1.3.0 DOJO_TOR_VERSION_TAG=1.1.0 diff --git a/docker/my-dojo/docker-compose.yaml b/docker/my-dojo/docker-compose.yaml index e59c762..8b37db2 100644 --- a/docker/my-dojo/docker-compose.yaml +++ b/docker/my-dojo/docker-compose.yaml @@ -36,6 +36,7 @@ services: expose: - "8080" - "8081" + - "8082" volumes: - data-nodejs:/data depends_on: diff --git a/docker/my-dojo/nginx/mainnet.conf b/docker/my-dojo/nginx/mainnet.conf index c7517d3..d729066 100644 --- a/docker/my-dojo/nginx/mainnet.conf +++ b/docker/my-dojo/nginx/mainnet.conf @@ -34,6 +34,11 @@ server { proxy_pass http://node:8081/; } + # Tracker server is separate, so proxy first + location /v2/tracker/ { + proxy_pass http://node:8082/; + } + # Proxy requests to maintenance tool location /admin/ { proxy_pass http://node:8080/static/admin/; diff --git a/docker/my-dojo/nginx/testnet.conf b/docker/my-dojo/nginx/testnet.conf index 4b9b71f..8c75fc6 100644 --- a/docker/my-dojo/nginx/testnet.conf +++ b/docker/my-dojo/nginx/testnet.conf @@ -34,6 +34,11 @@ server { proxy_pass http://node:8081/; } + # Tracker server is separate, so proxy first + location /test/v2/tracker/ { + proxy_pass http://node:8082/; + } + # Proxy requests to maintenance tool location /admin/ { proxy_pass http://node:8080/static/admin/; diff --git a/docker/my-dojo/node/keys.index.js b/docker/my-dojo/node/keys.index.js index 936a5bc..9ba3887 100644 --- a/docker/my-dojo/node/keys.index.js +++ b/docker/my-dojo/node/keys.index.js @@ -70,8 +70,10 @@ module.exports = { ports: { // Port used by the API account: 8080, - // Port used by pushtx + // Port used by the pushtx API pushtx: 8081, + // Port used by the tracker API + trackerApi: 8082, // Port used by the tracker for its notifications tracker: 5555, // Port used by pushtx for its notifications diff --git a/keys/index-example.js b/keys/index-example.js index 68e485a..d73cc48 100644 --- a/keys/index-example.js +++ b/keys/index-example.js @@ -67,8 +67,10 @@ module.exports = { ports: { // Port used by the API account: 8080, - // Port used by pushtx + // Port used by pushtx API pushtx: 8081, + // Port used by the tracker API + trackerApi: 8082, // Port used by the tracker for its notifications tracker: 5555, // Port used by pushtx for its notifications @@ -270,6 +272,7 @@ module.exports = { ports: { account: 18080, pushtx: 18081, + trackerApi: 18082, tracker: 15555, notifpushtx: 15556, orchestrator: 15557 diff --git a/tracker/index.js b/tracker/index.js index 3cf5420..47d091c 100644 --- a/tracker/index.js +++ b/tracker/index.js @@ -11,7 +11,9 @@ const keys = require('../keys')[network.key] const db = require('../lib/db/mysql-db-wrapper') const Logger = require('../lib/logger') + const HttpServer = require('../lib/http-server/http-server') const Tracker = require('./tracker') + const TrackerRestApi = require('./tracker-rest-api') Logger.info('Process ID: ' + process.pid) @@ -33,8 +35,20 @@ db.connect(dbConfig) - // Start the tracker + // Initialize the tracker const tracker = new Tracker() + + // Initialize the http server + const port = keys.ports.trackerApi + const httpServer = new HttpServer(port) + + // Initialize the rest api endpoints + const trackerRestApi = new TrackerRestApi(httpServer, tracker) + + // Start the http server + httpServer.start() + + // Start the tracker tracker.start() })().catch(err => { diff --git a/tracker/tracker-rest-api.js b/tracker/tracker-rest-api.js new file mode 100644 index 0000000..85d7c5f --- /dev/null +++ b/tracker/tracker-rest-api.js @@ -0,0 +1,79 @@ +/*! + * tracker/tracker-rest-api.js + * Copyright (c) 2016-2019, Samourai Wallet (CC BY-NC-ND 4.0 License). + */ +'use strict' + +const qs = require('querystring') +const validator = require('validator') +const bodyParser = require('body-parser') +const Logger = require('../lib/logger') +const errors = require('../lib/errors') +const authMgr = require('../lib/auth/authorizations-manager') +const HttpServer = require('../lib/http-server/http-server') +const network = require('../lib/bitcoin/network') +const keys = require('../keys')[network.key] + + +/** + * Tracker API endpoints + */ +class TrackerRestApi { + + /** + * Constructor + * @param {pushtx.HttpServer} httpServer - HTTP server + * @param {tracker.Tracker} tracker - tracker + */ + constructor(httpServer, tracker) { + this.httpServer = httpServer + this.tracker = tracker + + const urlencodedParser = bodyParser.urlencoded({ extended: true }) + + // Establish routes. Proxy server strips /pushtx + this.httpServer.app.get( + `/${keys.prefixes.support}/rescan`, + authMgr.checkHasAdminProfile.bind(authMgr), + this.getBlocksRescan.bind(this), + HttpServer.sendAuthError + ) + } + + /** + * Rescan a range of blocks + */ + async getBlocksRescan(req, res) { + // Check request arguments + if (!req.query) + return HttpServer.sendError(res, errors.body.INVDATA) + + if (!req.query.fromHeight || !validator.isInt(req.query.fromHeight)) + return HttpServer.sendError(res, errors.body.INVDATA) + + if (req.query.toHeight && !validator.isInt(req.query.toHeight)) + return HttpServer.sendError(res, errors.body.INVDATA) + + // Retrieve the request arguments + const fromHeight = parseInt(req.query.fromHeight) + const toHeight = req.query.toHeight ? parseInt(req.query.toHeight) : fromHeight + + if (req.query.toHeight && (toHeight < fromHeight)) + return HttpServer.sendError(res, errors.body.INVDATA) + + try { + await this.tracker.blockchainProcessor.rescanBlocks(fromHeight, toHeight) + const ret = { + status: 'Rescan complete', + fromHeight: fromHeight, + toHeight: toHeight + } + HttpServer.sendRawData(res, JSON.stringify(ret, null, 2)) + } catch(e) { + return HttpServer.sendError(res, e) + } + } + +} + +module.exports = TrackerRestApi