Harden MM pool flow and frontend guards
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 1m3s

This commit is contained in:
Codex Bot
2026-03-22 17:23:38 +01:00
parent 38a8187c07
commit 4207f95790
5 changed files with 62 additions and 27 deletions

View File

@@ -3,8 +3,8 @@
"coin": "Peya",
"symbol": "PEY",
"coinUnits": 1000000000000,
"coinDecimalPlaces": 12,
"coinUnits": 100000000,
"coinDecimalPlaces": 8,
"coinDifficultyTarget": 120,
"daemonType": "default",

View File

@@ -9,19 +9,20 @@
var http = require('http');
var https = require('https');
function jsonHttpRequest (host, port, data, callback, path) {
function jsonHttpRequest (host, port, data, callback, path, extraHeaders) {
path = path || '/json_rpc';
callback = callback || function () {};
extraHeaders = extraHeaders || {};
var options = {
hostname: host,
port: port,
path: path,
method: data ? 'POST' : 'GET',
headers: {
headers: Object.assign({
'Content-Length': data.length,
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}, extraHeaders)
};
var req = (port === 443 ? https : http)
.request(options, function (res) {
@@ -51,7 +52,7 @@ function jsonHttpRequest (host, port, data, callback, path) {
/**
* Send RPC request
**/
function rpc (host, port, method, params, callback) {
function rpc (host, port, method, params, callback, extraHeaders) {
var data = JSON.stringify({
id: "0",
jsonrpc: "2.0",
@@ -64,7 +65,7 @@ function rpc (host, port, method, params, callback) {
return;
}
callback(replyJson.error, replyJson.result);
});
}, '/json_rpc', extraHeaders);
}
/**
@@ -99,11 +100,11 @@ module.exports = function (daemonConfig, walletConfig, poolApiConfig) {
batchRpcDaemon: function (batchArray, callback) {
batchRpc(daemonConfig.host, daemonConfig.port, batchArray, callback);
},
rpcDaemon: function (method, params, callback, serverConfig) {
rpcDaemon: function (method, params, callback, serverConfig, extraHeaders) {
if (serverConfig) {
rpc(serverConfig.host, serverConfig.port, method, params, callback);
rpc(serverConfig.host, serverConfig.port, method, params, callback, extraHeaders);
} else {
rpc(daemonConfig.host, daemonConfig.port, method, params, callback);
rpc(daemonConfig.host, daemonConfig.port, method, params, callback, extraHeaders);
}
},
rpcWallet: function (method, params, callback) {

View File

@@ -366,6 +366,7 @@ function getPoolChartsData (callback) {
**/
function getUserChartsData (address, paymentsData, callback) {
let stats = {};
let userChartsConfig = config.charts && config.charts.user ? config.charts.user : {};
let chartsFuncs = {
hashrate: function (callback) {
getUserHashrateChartData(address, function (data) {
@@ -378,7 +379,8 @@ function getUserChartsData (address, paymentsData, callback) {
}
};
for (let chartName in chartsFuncs) {
if (!config.charts.user[chartName].enabled) {
let chartConfig = userChartsConfig[chartName];
if (chartConfig && chartConfig.enabled === false) {
delete chartsFuncs[chartName];
}
}

View File

@@ -864,12 +864,13 @@ function IsBannedIp (ip) {
}
}
function recordShareData (miner, job, shareDiff, blockCandidate, hashHex, shareType, blockTemplate) {
function recordShareData (miner, job, shareDiff, blockCandidate, hashHex, shareType, blockTemplate, blockMeta) {
let dateNow = Date.now();
let dateNowSeconds = dateNow / 1000 | 0;
let coin = config.coin;
let login = miner.login;
let job_height = job.height;
let job_height = blockMeta && blockMeta.height ? blockMeta.height : job.height;
let candidateHash = blockMeta && blockMeta.hash ? blockMeta.hash : hashHex;
let workerName = miner.workerName;
let rewardType = miner.rewardType;
let updateScore;
@@ -960,23 +961,39 @@ function recordShareData (miner, job, shareDiff, blockCandidate, hashHex, shareT
return p + parseInt(workerShares[c])
}, 0);
}
redisClient.zrangebyscore(coin + ':blocks:candidates', job_height, job_height, function (err, existingCandidates) {
if (err) {
log('error', logSystem, 'Failed loading existing block candidates for height %d before inserting %s \n %j', [job_height, candidateHash, err]);
return;
}
let duplicateCandidate = existingCandidates.some(function (candidate) {
let parts = candidate.split(':');
return parts.length >= 3 && parts[2] === candidateHash;
});
if (duplicateCandidate) {
return;
}
redisClient.zadd(coin + ':blocks:candidates', job_height, [
rewardType,
login,
hashHex,
candidateHash,
Date.now() / 1000 | 0,
blockTemplate.difficulty,
totalShares,
totalScore
].join(':'), function (err, result) {
if (err) {
log('error', logSystem, 'Failed inserting block candidate %s \n %j', [hashHex, err]);
log('error', logSystem, 'Failed inserting block candidate %s \n %j', [candidateHash, err]);
}
});
});
notifications.sendToAll('blockFound', {
'HEIGHT': job_height,
'HASH': hashHex,
'HASH': candidateHash,
'DIFFICULTY': blockTemplate.difficulty,
'SHARES': totalShares,
'MINER': login.substring(0, 7) + '...' + login.substring(login.length - 7)
@@ -1054,19 +1071,33 @@ function processShare (miner, job, blockTemplate, params) {
let jobDifficulty = BigInt(job.difficulty);
if (hashDiff >= blockDifficulty) {
let submitHeaders = {
'X-Hash-Difficulty': hashDiff.toString()
};
apiInterfaces.rpcDaemon('submitblock', [shareBuffer.toString('hex')], function (error, result) {
if (error) {
log('error', logSystem, 'Error submitting block at height %d from %s@%s, share type: "%s" - %j', [job.height, miner.login, miner.ip, shareType, error]);
} else {
let blockFastHash = utils.cnUtil.get_block_id(shareBuffer, getMiningParams().cnBlobType).toString('hex');
let acceptedBlockMeta = null;
if (result && result.aux_accepted && result.aux_height && result.aux_block_id) {
acceptedBlockMeta = {
height: result.aux_height,
hash: result.aux_block_id
};
} else if (result && result.block_id) {
acceptedBlockMeta = {
height: job.height,
hash: result.block_id
};
}
log('info', logSystem,
'Block %s found at height %d by miner %s@%s - submit result: %j',
[blockFastHash.substr(0, 6), job.height, miner.login, miner.ip, result]
);
recordShareData(miner, job, hashDiff.toString(), true, blockFastHash, shareType, blockTemplate);
recordShareData(miner, job, hashDiff.toString(), true, blockFastHash, shareType, blockTemplate, acceptedBlockMeta);
}
}, miningBackends.getMiningRpcConfig());
}, miningBackends.getMiningRpcConfig(), submitHeaders);
} else if (hashDiff < jobDifficulty) {
log('warn', logSystem, 'Rejected low difficulty share of %s from %s@%s', [hashDiff.toString(), miner.login, miner.ip]);
return false;

View File

@@ -219,6 +219,7 @@ function fetchLiveStats(endPoint, key) {
// Fetch Block and Transaction Explorer Urls
let xhrBlockExplorers;
let xhrMergedApis;
function fetchBlockExplorers() {
let apiURL = api + '/block_explorers';