Run pool through MM proxy with Salvium backend
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 37s
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 37s
This commit is contained in:
@@ -125,32 +125,60 @@
|
||||
"solo": {
|
||||
"enabled": true,
|
||||
"type": "solo",
|
||||
"coin": "Peya",
|
||||
"symbol": "PEY",
|
||||
"host": "127.0.0.1",
|
||||
"port": 37777
|
||||
"port": 37777,
|
||||
"cnAlgorithm": "randomx",
|
||||
"cnVariant": 0,
|
||||
"cnBlobType": 15,
|
||||
"includeHeight": true,
|
||||
"isRandomX": true
|
||||
},
|
||||
"salvium": {
|
||||
"enabled": false,
|
||||
"type": "merge-mining",
|
||||
"parentCoin": "salvium",
|
||||
"coin": "Salvium",
|
||||
"symbol": "SAL",
|
||||
"host": "127.0.0.1",
|
||||
"port": 37777,
|
||||
"walletAddress": "SC1T_PARENT_POOL_ADDRESS_HERE"
|
||||
"walletAddress": "SC1T_PARENT_POOL_ADDRESS_HERE",
|
||||
"cnAlgorithm": "randomx",
|
||||
"cnVariant": 0,
|
||||
"cnBlobType": 0,
|
||||
"includeHeight": true,
|
||||
"isRandomX": true
|
||||
},
|
||||
"monero": {
|
||||
"enabled": false,
|
||||
"type": "merge-mining",
|
||||
"parentCoin": "monero",
|
||||
"coin": "Monero",
|
||||
"symbol": "XMR",
|
||||
"host": "127.0.0.1",
|
||||
"port": 37777,
|
||||
"walletAddress": "42_PARENT_POOL_ADDRESS_HERE"
|
||||
"walletAddress": "42_PARENT_POOL_ADDRESS_HERE",
|
||||
"cnAlgorithm": "randomx",
|
||||
"cnVariant": 0,
|
||||
"cnBlobType": 0,
|
||||
"includeHeight": true,
|
||||
"isRandomX": true
|
||||
},
|
||||
"zephyr": {
|
||||
"enabled": false,
|
||||
"type": "merge-mining",
|
||||
"parentCoin": "zephyr",
|
||||
"coin": "Zephyr",
|
||||
"symbol": "ZEPH",
|
||||
"host": "127.0.0.1",
|
||||
"port": 37777,
|
||||
"walletAddress": "ZEPH_PARENT_POOL_ADDRESS_HERE"
|
||||
"walletAddress": "ZEPH_PARENT_POOL_ADDRESS_HERE",
|
||||
"cnAlgorithm": "randomx",
|
||||
"cnVariant": 0,
|
||||
"cnBlobType": 13,
|
||||
"includeHeight": true,
|
||||
"isRandomX": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2,10 +2,17 @@ function getLegacySoloBackend() {
|
||||
return {
|
||||
name: 'solo',
|
||||
type: 'solo',
|
||||
coin: config.coin,
|
||||
symbol: config.symbol,
|
||||
host: (config.miningSource && config.miningSource.host) || config.daemon.host,
|
||||
port: (config.miningSource && config.miningSource.port) || config.daemon.port,
|
||||
alwaysPoll: (config.miningSource && config.miningSource.alwaysPoll) || config.daemon.alwaysPoll || false,
|
||||
walletAddress: null
|
||||
walletAddress: null,
|
||||
cnAlgorithm: config.cnAlgorithm || 'cryptonight',
|
||||
cnVariant: config.cnVariant || 0,
|
||||
cnBlobType: config.cnBlobType || 0,
|
||||
includeHeight: typeof config.includeHeight !== 'undefined' ? config.includeHeight : false,
|
||||
isRandomX: config.isRandomX || false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -37,10 +44,17 @@ function normalizeBackend(name, backend) {
|
||||
name: name,
|
||||
type: backend.type || (name === 'solo' ? 'solo' : 'merge-mining'),
|
||||
parentCoin: backend.parentCoin || null,
|
||||
coin: backend.coin || config.coin,
|
||||
symbol: backend.symbol || config.symbol,
|
||||
host: backend.host,
|
||||
port: backend.port,
|
||||
alwaysPoll: backend.alwaysPoll || false,
|
||||
walletAddress: backend.walletAddress || null
|
||||
walletAddress: backend.walletAddress || null,
|
||||
cnAlgorithm: backend.cnAlgorithm || config.cnAlgorithm || 'cryptonight',
|
||||
cnVariant: typeof backend.cnVariant !== 'undefined' ? backend.cnVariant : (config.cnVariant || 0),
|
||||
cnBlobType: typeof backend.cnBlobType !== 'undefined' ? backend.cnBlobType : (config.cnBlobType || 0),
|
||||
includeHeight: typeof backend.includeHeight !== 'undefined' ? backend.includeHeight : (typeof config.includeHeight !== 'undefined' ? config.includeHeight : false),
|
||||
isRandomX: typeof backend.isRandomX !== 'undefined' ? backend.isRandomX : (config.isRandomX || false)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -85,3 +99,17 @@ function isSoloMiningBackend() {
|
||||
return getActiveMiningBackend().type === 'solo';
|
||||
}
|
||||
exports.isSoloMiningBackend = isSoloMiningBackend;
|
||||
|
||||
function getActiveMiningParams() {
|
||||
let backend = getActiveMiningBackend();
|
||||
return {
|
||||
coin: backend.coin,
|
||||
symbol: backend.symbol,
|
||||
cnAlgorithm: backend.cnAlgorithm,
|
||||
cnVariant: backend.cnVariant,
|
||||
cnBlobType: backend.cnBlobType,
|
||||
includeHeight: backend.includeHeight,
|
||||
isRandomX: backend.isRandomX
|
||||
};
|
||||
}
|
||||
exports.getActiveMiningParams = getActiveMiningParams;
|
||||
|
||||
@@ -16,6 +16,40 @@ let blockData = JSON.stringify({
|
||||
|
||||
require('./exceptionWriter.js')(logSystem);
|
||||
|
||||
function pollMiningTip(miningConfig, callback) {
|
||||
apiInterfaces.jsonHttpRequest(miningConfig.host, miningConfig.port, blockData, function (err, res) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res && res.result && res.result.status === "OK" && res.result.hasOwnProperty('block_header')) {
|
||||
callback(null, {
|
||||
hash: res.result.block_header.hash,
|
||||
height: res.result.block_header.height
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
apiInterfaces.jsonHttpRequest(miningConfig.host, miningConfig.port, '', function (heightErr, heightRes) {
|
||||
if (heightErr) {
|
||||
callback(heightErr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (heightRes && heightRes.status === 'OK' && heightRes.hash) {
|
||||
callback(null, {
|
||||
hash: heightRes.hash,
|
||||
height: heightRes.height
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
callback(new Error('bad response from mining source'));
|
||||
}, '/get_height');
|
||||
});
|
||||
}
|
||||
|
||||
function runInterval () {
|
||||
let miningConfig;
|
||||
try {
|
||||
@@ -28,29 +62,23 @@ function runInterval () {
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
apiInterfaces.jsonHttpRequest(miningConfig.host, miningConfig.port, blockData, function (err, res) {
|
||||
pollMiningTip(miningConfig, function (err, tip) {
|
||||
if (err) {
|
||||
log('error', logSystem, '%s error from mining source', [config.coin]);
|
||||
setTimeout(runInterval, 3000);
|
||||
return;
|
||||
}
|
||||
if (res && res.result && res.result.status === "OK" && res.result.hasOwnProperty('block_header')) {
|
||||
let hash = res.result.block_header.hash.toString('hex');
|
||||
if (!lastHash || lastHash !== hash) {
|
||||
lastHash = hash;
|
||||
log('info', logSystem, '%s found new hash %s via %s', [config.coin, hash, miningConfig.name]);
|
||||
callback(null, true);
|
||||
return;
|
||||
} else if (miningConfig.alwaysPoll || config.daemon.alwaysPoll || false) {
|
||||
callback(null, true);
|
||||
return;
|
||||
} else {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
let hash = tip.hash.toString('hex');
|
||||
if (!lastHash || lastHash !== hash) {
|
||||
lastHash = hash;
|
||||
log('info', logSystem, '%s found new hash %s via %s at height %s', [miningConfig.coin || config.coin, hash, miningConfig.name, tip.height]);
|
||||
callback(null, true);
|
||||
return;
|
||||
} else if (miningConfig.alwaysPoll || config.daemon.alwaysPoll || false) {
|
||||
callback(null, true);
|
||||
return;
|
||||
} else {
|
||||
log('error', logSystem, 'bad response from mining source');
|
||||
setTimeout(runInterval, 3000);
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
37
lib/pool.js
37
lib/pool.js
@@ -36,10 +36,14 @@ let log = function (severity, system, text, data) {
|
||||
global.log(severity, system, threadId + text, data);
|
||||
};
|
||||
|
||||
function getMiningParams() {
|
||||
return miningBackends.getActiveMiningParams();
|
||||
}
|
||||
|
||||
// Set cryptonight algorithm
|
||||
let cnAlgorithm = config.cnAlgorithm || "cryptonight";
|
||||
let cnVariant = config.cnVariant || 0;
|
||||
let cnBlobType = config.cnBlobType || 0;
|
||||
let cnAlgorithm = getMiningParams().cnAlgorithm || "cryptonight";
|
||||
let cnVariant = getMiningParams().cnVariant || 0;
|
||||
let cnBlobType = getMiningParams().cnBlobType || 0;
|
||||
|
||||
let cryptoNight;
|
||||
if (!cnHashing || !cnHashing[cnAlgorithm]) {
|
||||
@@ -90,8 +94,6 @@ if (config.poolServer.paymentId.validations == null) {
|
||||
config.poolServer.paymentId.validation = false;
|
||||
}
|
||||
|
||||
config.isRandomX = config.isRandomX || false;
|
||||
|
||||
let previousOffset = config.previousOffset || 7;
|
||||
let offset = config.offset || 2;
|
||||
config.daemonType = config.daemonType || 'default';
|
||||
@@ -197,7 +199,7 @@ process.on('message', function (message) {
|
||||
buffer.copy(new_hash, 0, previousOffset, 39);
|
||||
try {
|
||||
if (!currentBlockTemplate[0] || new_hash.toString('hex') !== currentBlockTemplate[0].prev_hash.toString('hex') || (currentBlockTemplate[0].num_transactions == 0 && message.block.num_transactions > 0)) {
|
||||
log('info', logSystem, 'New %s block to mine at height %d w/ difficulty of %d (%d transactions)', [config.coin, message.block.height, message.block.difficulty, (message.block.num_transactions || 0)]);
|
||||
log('info', logSystem, 'New %s block to mine at height %d w/ difficulty of %d (%d transactions)', [miningBackends.getActiveMiningBackend().coin, message.block.height, message.block.difficulty, (message.block.num_transactions || 0)]);
|
||||
processBlockTemplate(message.block);
|
||||
return;
|
||||
} else {
|
||||
@@ -225,7 +227,7 @@ function BlockTemplate (template) {
|
||||
this.blocktemplate_blob = template.blocktemplate_blob;
|
||||
let blob = this.blocktemplate_blob;
|
||||
this.buffer = Buffer.from(blob, 'hex');
|
||||
this.isRandomX = config.isRandomX
|
||||
this.isRandomX = getMiningParams().isRandomX;
|
||||
if (this.isRandomX) {
|
||||
this.seed_hash = template.seed_hash;
|
||||
this.next_seed_hash = template.next_seed_hash;
|
||||
@@ -255,7 +257,7 @@ function BlockTemplate (template) {
|
||||
BlockTemplate.prototype = {
|
||||
nextBlob: function () {
|
||||
this.buffer.writeUInt32BE(++this.extraNonce, this.reserveOffset);
|
||||
return utils.cnUtil.convert_blob(this.buffer, cnBlobType).toString('hex');
|
||||
return utils.cnUtil.convert_blob(this.buffer, getMiningParams().cnBlobType).toString('hex');
|
||||
},
|
||||
nextBlobWithChildNonce: function () {
|
||||
// Write a 32 bit integer, big-endian style to the 0 byte of the reserve offset.
|
||||
@@ -468,7 +470,7 @@ Miner.prototype = {
|
||||
if (typeof config.includeAlgo !== "undefined" && config.includeAlgo) {
|
||||
this.cachedJob.algo = config.includeAlgo
|
||||
}
|
||||
if (typeof config.includeHeight !== "undefined" && config.includeHeight) {
|
||||
if (getMiningParams().includeHeight) {
|
||||
this.cachedJob.height = blockTemplate.height
|
||||
}
|
||||
|
||||
@@ -987,7 +989,7 @@ function getShareBuffer (miner, job, blockTemplate, params) {
|
||||
}
|
||||
|
||||
try {
|
||||
let shareBuffer = utils.cnUtil.construct_block_blob(template, Buffer.from(nonce, 'hex'), cnBlobType);
|
||||
let shareBuffer = utils.cnUtil.construct_block_blob(template, Buffer.from(nonce, 'hex'), getMiningParams().cnBlobType);
|
||||
return shareBuffer;
|
||||
} catch (e) {
|
||||
log('error', logSystem, "Can't get share buffer with nonce %s from %s@%s: %s", [nonce, miner.login, miner.ip, e]);
|
||||
@@ -1011,18 +1013,19 @@ function processShare (miner, job, blockTemplate, params) {
|
||||
hash = Buffer.from(resultHash, 'hex');
|
||||
shareType = 'trusted';
|
||||
} else {
|
||||
let convertedBlob = utils.cnUtil.convert_blob(shareBuffer, cnBlobType);
|
||||
let miningParams = getMiningParams();
|
||||
let convertedBlob = utils.cnUtil.convert_blob(shareBuffer, miningParams.cnBlobType);
|
||||
let hard_fork_version = convertedBlob[0];
|
||||
|
||||
if (blockTemplate.isRandomX) {
|
||||
hash = cryptoNight(convertedBlob, Buffer.from(blockTemplate.seed_hash, 'hex'), cnVariant);
|
||||
hash = cryptoNight(convertedBlob, Buffer.from(blockTemplate.seed_hash, 'hex'), miningParams.cnVariant);
|
||||
} else {
|
||||
if (typeof config.includeHeight !== "undefined" && config.includeHeight)
|
||||
hash = cryptoNight(convertedBlob, cnVariant, job.height);
|
||||
if (miningParams.includeHeight)
|
||||
hash = cryptoNight(convertedBlob, miningParams.cnVariant, job.height);
|
||||
else
|
||||
hash = cryptoNight(convertedBlob, cnVariant);
|
||||
hash = cryptoNight(convertedBlob, miningParams.cnVariant);
|
||||
}
|
||||
log('info', logSystem, 'Mining pool algorithm: %s variant %d, Hard fork version: %d', [cnAlgorithm, cnVariant, hard_fork_version]);
|
||||
log('info', logSystem, 'Mining pool algorithm: %s variant %d, Hard fork version: %d', [miningParams.cnAlgorithm, miningParams.cnVariant, hard_fork_version]);
|
||||
shareType = 'valid'
|
||||
}
|
||||
|
||||
@@ -1042,7 +1045,7 @@ function processShare (miner, job, blockTemplate, params) {
|
||||
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, cnBlobType).toString('hex');
|
||||
let blockFastHash = utils.cnUtil.get_block_id(shareBuffer, getMiningParams().cnBlobType).toString('hex');
|
||||
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]
|
||||
|
||||
Reference in New Issue
Block a user