|
|
|
@ -11,9 +11,6 @@ const bodyParser = require('body-parser');
|
|
|
|
|
const jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
|
|
|
|
|
const crypto = require('crypto');
|
|
|
|
|
const cors = require('cors');
|
|
|
|
|
const zmq = require('zmq');
|
|
|
|
|
const sock = zmq.socket('sub');
|
|
|
|
|
const io = require('socket.io')(server);
|
|
|
|
|
|
|
|
|
|
let addressBase58Prefix = cnUtil.address_decode(new Buffer(global.config.pool.address));
|
|
|
|
|
let threadName = "";
|
|
|
|
@ -39,127 +36,6 @@ app.use(cors({origin: true}));
|
|
|
|
|
app.use(bodyParser.urlencoded({extended: false}));
|
|
|
|
|
app.use(bodyParser.json());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!cluster.isMaster) {
|
|
|
|
|
// Init the ZMQ listeners here.
|
|
|
|
|
sock.connect('tcp://127.0.0.1:3000');
|
|
|
|
|
sock.connect('tcp://127.0.0.1:3001');
|
|
|
|
|
// miner_hash_graph - Hash graphs updated
|
|
|
|
|
// miner_hash_stats - Miner hashes updated
|
|
|
|
|
// network_block_info - New block information
|
|
|
|
|
// pool_stats - Pool statistics update
|
|
|
|
|
sock.subscribe('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require('sticky-cluster')(
|
|
|
|
|
// server initialization function
|
|
|
|
|
function (callback) {
|
|
|
|
|
// don't do server.listen(), just pass the server instance into the callback
|
|
|
|
|
callback(server);
|
|
|
|
|
},
|
|
|
|
|
// options
|
|
|
|
|
{
|
|
|
|
|
concurrency: require('os').cpus().length,
|
|
|
|
|
port: 8001,
|
|
|
|
|
debug: false,
|
|
|
|
|
env: function (index) { return { stickycluster_worker_index: index }; }
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// SocketIO Routes
|
|
|
|
|
// ===============
|
|
|
|
|
io.on('connection', (socket) => {
|
|
|
|
|
socket.on('room', function(room) {
|
|
|
|
|
socket.join(room);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// As the majority of updates come in upstream from the main SocketIO server, we use ZMQ to manage this.
|
|
|
|
|
// The following is the ZMQ logic. Pray to whatever deity you like.
|
|
|
|
|
|
|
|
|
|
sock.on('message', function(topic, message) {
|
|
|
|
|
topic = topic.toString();
|
|
|
|
|
message = message.toString();
|
|
|
|
|
/*
|
|
|
|
|
Registered ZMQ Messages:
|
|
|
|
|
miner_hash_graph - Hash graphs updated
|
|
|
|
|
miner_hash_stats - Miner hashes updated
|
|
|
|
|
network_block_info - New block information
|
|
|
|
|
pool_stats - Pool statistics update
|
|
|
|
|
payments - Payments complete - Trip the frontend to hit the frontend for new payment information
|
|
|
|
|
|
|
|
|
|
Registered Rooms:
|
|
|
|
|
payments
|
|
|
|
|
hash_chart_<address> - equiv to https://api.xmrpool.net/miner/<address>/chart/hashrate/allWorkers
|
|
|
|
|
worker_stats_<address> - equiv to https://api.xmrpool.net/miner/<address>/stats/allWorkers
|
|
|
|
|
worker_ids_<address> - equiv to https://api.xmrpool.net/miner/<address>/identifiers
|
|
|
|
|
address_stats_<address> - equiv to https://api.xmrpool.net/miner/<address>/stats
|
|
|
|
|
network_block_info - equiv to https://api.xmrpool.net/network/stats
|
|
|
|
|
pool_stats_<type> - equiv to https://api.xmrpool.net/pool/stats/<type>
|
|
|
|
|
pool_stats - equiv to https://api.xmrpool.net/pool/stats/
|
|
|
|
|
*/
|
|
|
|
|
switch(topic){
|
|
|
|
|
case 'payments':
|
|
|
|
|
io.sockets.in('payments').emit('message', 'newPaymentsAvailable');
|
|
|
|
|
break;
|
|
|
|
|
case 'miner_hash_graph':
|
|
|
|
|
message = JSON.parse(message);
|
|
|
|
|
message.forEach(function(address){
|
|
|
|
|
getAllWorkerHashCharts(address, function(err, data){
|
|
|
|
|
return io.sockets.in('hash_chart_'+address).emit('message', JSON.stringify(data));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
break;
|
|
|
|
|
case 'miner_hash_stats':
|
|
|
|
|
message = JSON.parse(message);
|
|
|
|
|
message.forEach(function(address){
|
|
|
|
|
getAddressStats(address, function(err,data){
|
|
|
|
|
io.sockets.in('address_stats_'+address).emit('message', JSON.stringify(data));
|
|
|
|
|
});
|
|
|
|
|
getAllWorkerStats(address, function(err, data){
|
|
|
|
|
io.sockets.in('worker_stats_'+address).emit('message', JSON.stringify(data));
|
|
|
|
|
});
|
|
|
|
|
io.sockets.in('worker_ids_'+address).emit('message', JSON.stringify(global.database.getCache(address + '_identifiers')));
|
|
|
|
|
});
|
|
|
|
|
break;
|
|
|
|
|
case 'network_block_info':
|
|
|
|
|
io.sockets.in('block_update').emit('message', message);
|
|
|
|
|
break;
|
|
|
|
|
case 'pool_stats':
|
|
|
|
|
if (message === 'global'){
|
|
|
|
|
let localCache = global.database.getCache('pool_stats_global');
|
|
|
|
|
delete(localCache.minerHistory);
|
|
|
|
|
delete(localCache.hashHistory);
|
|
|
|
|
let lastPayment = global.database.getCache('lastPaymentCycle');
|
|
|
|
|
io.sockets.in('pool_stats').emit('message', JSON.stringify({pool_list: pool_list, pool_statistics: localCache, last_payment: !lastPayment ? 0 : lastPayment}));
|
|
|
|
|
} else {
|
|
|
|
|
let pool_type = message;
|
|
|
|
|
let localCache;
|
|
|
|
|
switch (pool_type) {
|
|
|
|
|
case 'pplns':
|
|
|
|
|
localCache = global.database.getCache('pool_stats_pplns');
|
|
|
|
|
localCache.fee = global.config.payout.pplnsFee;
|
|
|
|
|
break;
|
|
|
|
|
case 'pps':
|
|
|
|
|
localCache = global.database.getCache('pool_stats_pps');
|
|
|
|
|
localCache.fee = global.config.payout.ppsFee;
|
|
|
|
|
break;
|
|
|
|
|
case 'solo':
|
|
|
|
|
localCache = global.database.getCache('pool_stats_solo');
|
|
|
|
|
localCache.fee = global.config.payout.soloFee;
|
|
|
|
|
break;
|
|
|
|
|
case 'default':
|
|
|
|
|
io.sockets.in('pool_stats_' + message).emit('message', JSON.stringify({'error': 'Invalid pool type'}));
|
|
|
|
|
}
|
|
|
|
|
localCache.poolType = pool_type;
|
|
|
|
|
delete(localCache.minerHistory);
|
|
|
|
|
delete(localCache.hashHistory);
|
|
|
|
|
io.sockets.in('pool_stats_' + message).emit('message', JSON.stringify({pool_statistics: localCache}));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Support Functions that are reused now
|
|
|
|
|
function getAllWorkerHashCharts(address, callback){
|
|
|
|
|
let identifiers = global.database.getCache(address + '_identifiers');
|
|
|
|
@ -944,4 +820,31 @@ adminRoutes.get('/userList', function (req, res) {
|
|
|
|
|
app.use('/authed', secureRoutes);
|
|
|
|
|
app.use('/admin', adminRoutes);
|
|
|
|
|
|
|
|
|
|
// Authenticated routes
|
|
|
|
|
// Authenticated routes
|
|
|
|
|
|
|
|
|
|
let workerList = [];
|
|
|
|
|
|
|
|
|
|
if (cluster.isMaster) {
|
|
|
|
|
let numWorkers = require('os').cpus().length;
|
|
|
|
|
console.log('Master cluster setting up ' + numWorkers + ' workers...');
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < numWorkers; i++) {
|
|
|
|
|
let worker = cluster.fork();
|
|
|
|
|
workerList.push(worker);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cluster.on('online', function (worker) {
|
|
|
|
|
console.log('Worker ' + worker.process.pid + ' is online');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
cluster.on('exit', function (worker, code, signal) {
|
|
|
|
|
console.log('Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
|
|
|
|
|
console.log('Starting a new worker');
|
|
|
|
|
worker = cluster.fork();
|
|
|
|
|
workerList.push(worker);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
app.listen(8001, function () {
|
|
|
|
|
console.log('Process ' + process.pid + ' is listening to all incoming requests');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|