mirror of https://github.com/BTCPrivate/z-nomp.git
Fixes & Zen Updates (#149)
* Create zen.json * Update api.js Remove unnecessary address.startWith() check in api for improved support of future Zcash forks. * Update zen.json * Update paymentProcessor.js Improved operation id handling during RPC call errors. Improved error handling and reporting during payment RPC call errors. Force final rounding of addressAmounts array. Limit tries when reducing rewards due to insufficient funds. Do not processPayments at start of z-nomp. * Update paymentProcessor.js Improved error handling in cacheNetworkStats() Updates to error messages * Update paymentProcessor.js Remove false positive * Update paymentProcessor.js Remove another false positive
This commit is contained in:
parent
6e638e7bf6
commit
8fd1d7eceb
|
@ -0,0 +1,62 @@
|
||||||
|
{
|
||||||
|
"name": "zen",
|
||||||
|
"symbol": "zen",
|
||||||
|
"algorithm": "equihash",
|
||||||
|
"requireShielding": true,
|
||||||
|
"payFoundersReward": true,
|
||||||
|
"percentFoundersReward": 8.5,
|
||||||
|
"maxFoundersRewardBlockHeight": 839999,
|
||||||
|
"foundersRewardAddressChangeInterval": 17500,
|
||||||
|
"vFoundersRewardAddress": [
|
||||||
|
"zssEdGnZCQ9G86LZFtbynMn1hYTVhn6eYCL",
|
||||||
|
"zsrCsXXmUf8k59NLasEKfxA7us3iNvaPATz",
|
||||||
|
"zsnLPsWMXW2s4w9EmFSwtSLRxL2LhPcfdby",
|
||||||
|
"zshdovbcPfUAfkPeEE2qLbKnoue9RsbVokU",
|
||||||
|
"zsqmq97JAKCCBFRGvxgv6FiJgQLCZBDp62S",
|
||||||
|
"zskyFVFA7VRYX8EGdXmYN75WaBB25FmiL3g",
|
||||||
|
"zsmncLmwEUdVmAGPUrUnNKmPGXyej7mbmdM",
|
||||||
|
"zsfa9VVJCEdjfPbku4XrFcRR8kTDm2T64rz",
|
||||||
|
"zsjdMnfWuFi46VeN2HSXVQWEGsnGHgVxayY",
|
||||||
|
"zseb8wRQ8rZ722oLX5B8rx7qwZiBRb9mdig",
|
||||||
|
"zsjxkovhqiMVggoW7jvSRi3NTSD3a6b6qfd",
|
||||||
|
"zsokCCSU3wvZrS2G6mEDpJ5cH49E7sDyNr1",
|
||||||
|
"zt12EsFgkABHLMRXA7JNnpMqLrxsgCLnVEV",
|
||||||
|
"zt39mvuG9gDTHX8A8Qk45rbk3dSdQoJ8ZAv",
|
||||||
|
"zssTQZs5YxDGijKC86dvcDxzWogWcK7n5AK",
|
||||||
|
"zsywuMoQK7Bved2nrXs56AEtWBhpb88rMzS",
|
||||||
|
"zsxVS2w7h1fHFX2nQtGm4372pd4DSHzq9ee",
|
||||||
|
"zsupGi7ro3uC8CEVwm9r7vrdVUZaXQnHF6T",
|
||||||
|
"zshVZvW47dA5AB3Sqk1h7ytwWJeUJUJxxaE",
|
||||||
|
"zsubBCjvDx252MKFsL4Dcf5rJU9Z9Upqr1N",
|
||||||
|
"zsweaST3NcU4hfgkVULfCsfEq41pjgMDgcW",
|
||||||
|
"zswz6Rxb1S33fUpftETZwtGiVSeYxNKq2xc",
|
||||||
|
"zswnpHtiBbrvYDzbhPQshkgvLSfYhDMRJ4S",
|
||||||
|
"zsjSYAWaEYj35Ht7aXrRJUGY6Dc8qCmgYqu",
|
||||||
|
"zsvMv8fGroWR8epbSiGDCJHmfe6ec2uFQrt",
|
||||||
|
"zsujxCT56BExQDAwKwktBjtnopYnw8BiKbg",
|
||||||
|
"zsxeXc2FTAzmUmeZmqVsKVdwTMSvzyns4rT",
|
||||||
|
"zsuLqgABNudD8bVPbVGeUjGqapuoXp68i7F",
|
||||||
|
"zsoc39J1dCFK1U8kckZznvQkv8As7sajYLz",
|
||||||
|
"zt21NFdu1KRPJ7VRKtrWugM2Jqe5ePNmU4T",
|
||||||
|
"zsp15qbVcbx9ifcjKe6XZEJTvzsFUZ2BHLT",
|
||||||
|
"zso2KvqH6yxLQEYggHdmfL3Tcd5V6E9tqhp",
|
||||||
|
"zsnFG2W5ZHRYh3QucNze4mp31tBkemtfxdj",
|
||||||
|
"zsex2CGJtxHyHbpLXm7kESBmp3vWRqUkJMy",
|
||||||
|
"zsvtFv96nrgrXKUbtNe2BpCt8aQEp5oJ7F8",
|
||||||
|
"zsk5KitThmhK9KBa1KDybPgEmGSFTHzhMVA",
|
||||||
|
"zsuy4n48c4NsJyaCZEzwdAKULM1FqbB6Y4z",
|
||||||
|
"zsgtQVMpX2zNMLvHHG2NDwfqKoaebvVectJ",
|
||||||
|
"zszQqXRSPGdqsWw4iaMTNN6aJz4JjEzSdCF",
|
||||||
|
"zst6dBLrTtaMQBX7BLMNjKLTGcP11PBmgTV",
|
||||||
|
"zshD9r6Eb6dZGdzYW2HCb9CzkMokCT1NGJR",
|
||||||
|
"zswUaj1TboEGmvSfF7fdoxWyH3RMx7MBHHo",
|
||||||
|
"zsv8s4Poi5GxCsbBrRJ97Vsvazp84nrz5AN",
|
||||||
|
"zsmmxrKU6dqWFwUKow1iyovg3gxrgXpEivr",
|
||||||
|
"zskh1221aRC9WEfb5a59WxffeW34McmZZsw",
|
||||||
|
"zssAhuj57NnVm4yNFT6o8muRctABkUaBu3L",
|
||||||
|
"zsi5Yr4Z8HwBvdBqQE8gk7ahExDu95J4oqZ",
|
||||||
|
"zsy6ryEaxfk8emJ8bGVB7tmwRwBL8cfSqBW"
|
||||||
|
],
|
||||||
|
"peerMagic": "63617368",
|
||||||
|
"txfee": 0.0004
|
||||||
|
}
|
|
@ -35,7 +35,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
|
||||||
var workers = {};
|
var workers = {};
|
||||||
var address = url_parms[1] || null;
|
var address = url_parms[1] || null;
|
||||||
//res.end(portalStats.getWorkerStats(address));
|
//res.end(portalStats.getWorkerStats(address));
|
||||||
if (address != null && address.length > 0 && address.startsWith('t'),('R')) {
|
if (address != null && address.length > 0) {
|
||||||
// make sure it is just the miners address
|
// make sure it is just the miners address
|
||||||
address = address.split(".")[0];
|
address = address.split(".")[0];
|
||||||
// get miners balance along with worker balances
|
// get miners balance along with worker balances
|
||||||
|
|
|
@ -167,14 +167,8 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
if (paymentInterval) {
|
if (paymentInterval) {
|
||||||
clearInterval(paymentInterval);
|
clearInterval(paymentInterval);
|
||||||
}
|
}
|
||||||
paymentInterval = setInterval(function(){
|
paymentInterval = setInterval(processPayments, paymentIntervalSecs * 1000);
|
||||||
try {
|
//setTimeout(processPayments, 100);
|
||||||
processPayments();
|
|
||||||
} catch(e){
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}, paymentIntervalSecs * 1000);
|
|
||||||
setTimeout(processPayments, 100);
|
|
||||||
setupFinished(true);
|
setupFinished(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,9 +187,8 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
var args = [minConf, 99999999];
|
var args = [minConf, 99999999];
|
||||||
}
|
}
|
||||||
daemon.cmd('listunspent', args, function (result) {
|
daemon.cmd('listunspent', args, function (result) {
|
||||||
if (!result || result.error || result[0].error || !result[0].response) {
|
if (!result || result.error || result[0].error) {
|
||||||
logger.error(logSystem, logComponent, 'Error trying to get balance for address '+addr+' with RPC call listunspent.'
|
logger.error(logSystem, logComponent, 'Error with RPC call listunspent '+addr+' '+JSON.stringify(result[0].error));
|
||||||
+ JSON.stringify(result.error));
|
|
||||||
callback = function (){};
|
callback = function (){};
|
||||||
callback(true);
|
callback(true);
|
||||||
}
|
}
|
||||||
|
@ -221,7 +214,7 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
function listUnspentZ (addr, minConf, displayBool, callback) {
|
function listUnspentZ (addr, minConf, displayBool, callback) {
|
||||||
daemon.cmd('z_getbalance', [addr, minConf], function (result) {
|
daemon.cmd('z_getbalance', [addr, minConf], function (result) {
|
||||||
if (!result || result.error || result[0].error) {
|
if (!result || result.error || result[0].error) {
|
||||||
logger.error(logSystem, logComponent, 'Error trying to get z-addr balance with RPC call z_getbalance.');
|
logger.error(logSystem, logComponent, 'Error with RPC call z_getbalance '+addr+' '+JSON.stringify(result[0].error));
|
||||||
callback = function (){};
|
callback = function (){};
|
||||||
callback(true);
|
callback(true);
|
||||||
}
|
}
|
||||||
|
@ -260,14 +253,14 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
daemon.cmd('z_sendmany', params,
|
daemon.cmd('z_sendmany', params,
|
||||||
function (result) {
|
function (result) {
|
||||||
//Check if payments failed because wallet doesn't have enough coins to pay for tx fees
|
//Check if payments failed because wallet doesn't have enough coins to pay for tx fees
|
||||||
if (result.error) {
|
if (!result || result.error || result[0].error || !result[0].response) {
|
||||||
logger.error(logSystem, logComponent, 'Error trying to shield mined balance ' + JSON.stringify(result.error));
|
logger.error(logSystem, logComponent, 'Error trying to shield balance '+amount+' '+JSON.stringify(result[0].error));
|
||||||
callback = function (){};
|
callback = function (){};
|
||||||
callback(true);
|
callback(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
opidCount++;
|
opidCount++;
|
||||||
logger.special(logSystem, logComponent, 'Shield mined balance ' + amount);
|
logger.special(logSystem, logComponent, 'Shield balance ' + amount);
|
||||||
callback = function (){};
|
callback = function (){};
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
|
@ -301,9 +294,8 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
daemon.cmd('z_sendmany', params,
|
daemon.cmd('z_sendmany', params,
|
||||||
function (result) {
|
function (result) {
|
||||||
//Check if payments failed because wallet doesn't have enough coins to pay for tx fees
|
//Check if payments failed because wallet doesn't have enough coins to pay for tx fees
|
||||||
if (result.error) {
|
if (!result || result.error || result[0].error || !result[0].response) {
|
||||||
logger.error(logSystem, logComponent, 'Error trying to send z_address coin balance to payout t_address.'
|
logger.error(logSystem, logComponent, 'Error trying to send z_address coin balance to payout t_address.'+JSON.stringify(result[0].error));
|
||||||
+ JSON.stringify(result.error));
|
|
||||||
callback = function (){};
|
callback = function (){};
|
||||||
callback(true);
|
callback(true);
|
||||||
}
|
}
|
||||||
|
@ -317,13 +309,12 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO, this needs to be moved out of payments processor
|
|
||||||
function cacheMarketStats() {
|
function cacheMarketStats() {
|
||||||
var marketStatsUpdate = [];
|
var marketStatsUpdate = [];
|
||||||
var coin = logComponent.replace('_testnet', '');
|
var coin = logComponent.replace('_testnet', '');
|
||||||
request('https://api.coinmarketcap.com/v1/ticker/'+coin+'/', function (error, response, body) {
|
request('https://api.coinmarketcap.com/v1/ticker/'+coin+'/', function (error, response, body) {
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error(logSystem, logComponent, 'Error getting coin market stats from CoinMarketCap ' + JSON.stringify(err));
|
logger.error(logSystem, logComponent, 'Error with http request to https://api.coinmarketcap.com/ ' + JSON.stringify(error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (response && response.statusCode) {
|
if (response && response.statusCode) {
|
||||||
|
@ -334,60 +325,67 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
marketStatsUpdate.push(['hset', coin + ':stats', 'coinmarketcap', JSON.stringify(data)]);
|
marketStatsUpdate.push(['hset', coin + ':stats', 'coinmarketcap', JSON.stringify(data)]);
|
||||||
redisClient.multi(marketStatsUpdate).exec(function(err, results){
|
redisClient.multi(marketStatsUpdate).exec(function(err, results){
|
||||||
if (err){
|
if (err){
|
||||||
logger.error(logSystem, logComponent, 'Error update coin market stats to redis ' + JSON.stringify(err));
|
logger.error(logSystem, logComponent, 'Error with redis during call to cacheMarketStats() ' + JSON.stringify(error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.error(logSystem, logComponent, 'Error returned from coinmarketcap ' + JSON.stringify(response));
|
logger.error(logSystem, logComponent, 'Error, unexpected http status code during call to cacheMarketStats() ' + JSON.stringify(response.statusCode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO, this needs to be moved out of payments processor
|
|
||||||
function cacheNetworkStats () {
|
function cacheNetworkStats () {
|
||||||
var params = null;
|
var params = null;
|
||||||
daemon.cmd('getmininginfo', params,
|
daemon.cmd('getmininginfo', params,
|
||||||
function (result) {
|
function (result) {
|
||||||
var finalRedisCommands = [];
|
if (!result || result.error || result[0].error || !result[0].response) {
|
||||||
var coin = logComponent;
|
logger.error(logSystem, logComponent, 'Error with RPC call getmininginfo '+JSON.stringify(result[0].error));
|
||||||
|
|
||||||
if (result.error) {
|
|
||||||
logger.error(logSystem, logComponent, 'Error with RPC call `getmininginfo`'
|
|
||||||
+ JSON.stringify(result.error));
|
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
if (result[0].response.blocks !== null) {
|
|
||||||
finalRedisCommands.push(['hset', coin + ':stats', 'networkBlocks', result[0].response.blocks]);
|
var coin = logComponent;
|
||||||
finalRedisCommands.push(['hset', coin + ':stats', 'networkDiff', result[0].response.difficulty]);
|
var finalRedisCommands = [];
|
||||||
finalRedisCommands.push(['hset', coin + ':stats', 'networkSols', result[0].response.networkhashps]);
|
|
||||||
} else {
|
if (result[0].response.blocks !== null) {
|
||||||
logger.error(logSystem, logComponent, "Error parse RPC call reponse.blocks tp `getmininginfo`." + JSON.stringify(result[0].response));
|
finalRedisCommands.push(['hset', coin + ':stats', 'networkBlocks', result[0].response.blocks]);
|
||||||
}
|
}
|
||||||
|
if (result[0].response.difficulty !== null) {
|
||||||
|
finalRedisCommands.push(['hset', coin + ':stats', 'networkDiff', result[0].response.difficulty]);
|
||||||
|
}
|
||||||
|
if (result[0].response.networkhashps !== null) {
|
||||||
|
finalRedisCommands.push(['hset', coin + ':stats', 'networkSols', result[0].response.networkhashps]);
|
||||||
}
|
}
|
||||||
|
|
||||||
daemon.cmd('getnetworkinfo', params,
|
daemon.cmd('getnetworkinfo', params,
|
||||||
function (result) {
|
function (result) {
|
||||||
if (result.error) {
|
if (!result || result.error || result[0].error || !result[0].response) {
|
||||||
logger.error(logSystem, logComponent, 'Error with RPC call `getnetworkinfo`'
|
logger.error(logSystem, logComponent, 'Error with RPC call getnetworkinfo '+JSON.stringify(result[0].error));
|
||||||
+ JSON.stringify(result.error));
|
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
if (result[0].response !== null) {
|
|
||||||
finalRedisCommands.push(['hset', coin + ':stats', 'networkConnections', result[0].response.connections]);
|
|
||||||
finalRedisCommands.push(['hset', coin + ':stats', 'networkVersion', result[0].response.version]);
|
|
||||||
finalRedisCommands.push(['hset', coin + ':stats', 'networkSubVersion', result[0].response.subversion]);
|
|
||||||
finalRedisCommands.push(['hset', coin + ':stats', 'networkProtocolVersion', result[0].response.protocolversion]);
|
|
||||||
} else {
|
|
||||||
logger.error(logSystem, logComponent, "Error parse RPC call response to `getnetworkinfo`." + JSON.stringify(result[0].response));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result[0].response.connections !== null) {
|
||||||
|
finalRedisCommands.push(['hset', coin + ':stats', 'networkConnections', result[0].response.connections]);
|
||||||
|
}
|
||||||
|
if (result[0].response.version !== null) {
|
||||||
|
finalRedisCommands.push(['hset', coin + ':stats', 'networkVersion', result[0].response.version]);
|
||||||
|
}
|
||||||
|
if (result[0].response.subversion !== null) {
|
||||||
|
finalRedisCommands.push(['hset', coin + ':stats', 'networkSubVersion', result[0].response.subversion]);
|
||||||
|
}
|
||||||
|
if (result[0].response.protocolversion !== null) {
|
||||||
|
finalRedisCommands.push(['hset', coin + ':stats', 'networkProtocolVersion', result[0].response.protocolversion]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finalRedisCommands.length <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
redisClient.multi(finalRedisCommands).exec(function(error, results){
|
redisClient.multi(finalRedisCommands).exec(function(error, results){
|
||||||
if (error){
|
if (error){
|
||||||
logger.error(logSystem, logComponent, 'Error update coin stats to redis ' + JSON.stringify(error));
|
logger.error(logSystem, logComponent, 'Error with redis during call to cacheNetworkStats() ' + JSON.stringify(error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -432,14 +430,19 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
// shielding not required for some equihash coins
|
// shielding not required for some equihash coins
|
||||||
if (requireShielding === true) {
|
if (requireShielding === true) {
|
||||||
var checkOpids = function() {
|
var checkOpids = function() {
|
||||||
|
clearTimeout(opidTimeout);
|
||||||
var checkOpIdSuccessAndGetResult = function(ops) {
|
var checkOpIdSuccessAndGetResult = function(ops) {
|
||||||
var batchRPC = [];
|
var batchRPC = [];
|
||||||
ops.forEach(function(op, i){
|
ops.forEach(function(op, i){
|
||||||
|
// check operation id status
|
||||||
if (op.status == "success" || op.status == "failed") {
|
if (op.status == "success" || op.status == "failed") {
|
||||||
|
// clear operation id result
|
||||||
batchRPC.push(['z_getoperationresult', [[op.id]]]);
|
batchRPC.push(['z_getoperationresult', [[op.id]]]);
|
||||||
|
// clear operation id count
|
||||||
if (opidCount > 0) {
|
if (opidCount > 0) {
|
||||||
opidCount = 0;
|
opidCount = 0;
|
||||||
}
|
}
|
||||||
|
// log status to console
|
||||||
if (op.status == "failed") {
|
if (op.status == "failed") {
|
||||||
if (op.error) {
|
if (op.error) {
|
||||||
logger.error(logSystem, logComponent, "Shielding operation failed " + op.id + " " + op.error.code +", " + op.error.message);
|
logger.error(logSystem, logComponent, "Shielding operation failed " + op.id + " " + op.error.code +", " + op.error.message);
|
||||||
|
@ -456,45 +459,50 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if there are no pending operations
|
// if there are no completed operations
|
||||||
if (batchRPC.length <= 0) {
|
if (batchRPC.length <= 0) {
|
||||||
opidInterval = setInterval(checkOpids, opid_interval);
|
opidTimeout = setTimeout(checkOpids, opid_interval);
|
||||||
if (opidCount > 0) {
|
|
||||||
opidCount = 0;
|
|
||||||
logger.warning(logSystem, logComponent, 'Cleared opidCount, batchRPC.length <= 0 for z_getoperationresult RPC call.');
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// clear results for completed operations
|
||||||
daemon.batchCmd(batchRPC, function(error, results){
|
daemon.batchCmd(batchRPC, function(error, results){
|
||||||
if (error || !results) {
|
if (error || !results) {
|
||||||
logger.error(logSystem, logComponent, 'Error with z_getoperationresult ' + JSON.stringify(error));
|
opidTimeout = setTimeout(checkOpids, opid_interval);
|
||||||
|
logger.error(logSystem, logComponent, 'Error with RPC call z_getoperationresult ' + JSON.stringify(error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// check result execution_secs vs pool_config
|
||||||
results.forEach(function(result, i) {
|
results.forEach(function(result, i) {
|
||||||
if (parseFloat(result.result[i].execution_secs || 0) > shielding_interval)
|
if (parseFloat(result.result[i].execution_secs || 0) > shielding_interval) {
|
||||||
logger.warning(logSystem, logComponent, 'Increase walletInterval in pool_config. opid execution took '+result.result[i].execution_secs+' secs.');
|
logger.warning(logSystem, logComponent, 'Warning, walletInverval shorter than opid execution time of '+result.result[i].execution_secs+' secs.');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
opidInterval = setInterval(checkOpids, opid_interval);
|
// keep checking operation ids
|
||||||
|
opidTimeout = setTimeout(checkOpids, opid_interval);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
clearInterval(opidInterval);
|
// check for completed operation ids
|
||||||
daemon.cmd('z_getoperationstatus', null, function (result) {
|
daemon.cmd('z_getoperationstatus', null, function (result) {
|
||||||
if (result.error) {
|
var err = false;
|
||||||
logger.warning(logSystem, logComponent, 'Unable to get operation ids for clearing.');
|
if (result.error) {
|
||||||
opidInterval = setInterval(checkOpids, opid_interval);
|
err = true;
|
||||||
} else if (result.response) {
|
logger.error(logSystem, logComponent, 'Error with RPC call z_getoperationstatus ' + JSON.stringify(result.error));
|
||||||
checkOpIdSuccessAndGetResult(result.response);
|
} else if (result.response) {
|
||||||
} else {
|
checkOpIdSuccessAndGetResult(result.response);
|
||||||
opidInterval = setInterval(checkOpids, opid_interval);
|
} else {
|
||||||
if (opidCount > 0) {
|
err = true;
|
||||||
opidCount = 0;
|
logger.error(logSystem, logComponent, 'No response from z_getoperationstatus RPC call.');
|
||||||
logger.warning(logSystem, logComponent, 'Cleared opidCount, no response from z_getoperationstatus RPC call.');
|
}
|
||||||
|
if (err === true) {
|
||||||
|
opidTimeout = setTimeout(checkOpids, opid_interval);
|
||||||
|
if (opidCount > 0) {
|
||||||
|
opidCount = 0;
|
||||||
|
logger.warning(logSystem, logComponent, 'Clearing operation ids due to RPC call errors.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}, true, true);
|
}, true, true);
|
||||||
}
|
}
|
||||||
|
var opidTimeout = setTimeout(checkOpids, opid_interval);
|
||||||
var opidInterval = setInterval(checkOpids, opid_interval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function roundTo(n, digits) {
|
function roundTo(n, digits) {
|
||||||
|
@ -953,6 +961,7 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
*/
|
*/
|
||||||
function(workers, rounds, addressAccount, callback) {
|
function(workers, rounds, addressAccount, callback) {
|
||||||
|
|
||||||
|
var tries = 0;
|
||||||
var trySend = function (withholdPercent) {
|
var trySend = function (withholdPercent) {
|
||||||
var addressAmounts = {};
|
var addressAmounts = {};
|
||||||
var balanceAmounts = {};
|
var balanceAmounts = {};
|
||||||
|
@ -961,6 +970,10 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
var minerTotals = {};
|
var minerTotals = {};
|
||||||
var totalSent = 0;
|
var totalSent = 0;
|
||||||
var totalShares = 0;
|
var totalShares = 0;
|
||||||
|
|
||||||
|
// track attempts made, calls to trySend...
|
||||||
|
tries++;
|
||||||
|
|
||||||
// total up miner's balances
|
// total up miner's balances
|
||||||
for (var w in workers) {
|
for (var w in workers) {
|
||||||
var worker = workers[w];
|
var worker = workers[w];
|
||||||
|
@ -1024,31 +1037,55 @@ function SetupForPool(logger, poolOptions, setupFinished){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do final rounding of payments per address
|
||||||
|
// this forces amounts to be valid (0.12345678)
|
||||||
|
for (var a in addressAmounts) {
|
||||||
|
addressAmounts[a] = coinsRound(addressAmounts[a]);
|
||||||
|
}
|
||||||
|
|
||||||
// POINT OF NO RETURN! GOOD LUCK!
|
// POINT OF NO RETURN! GOOD LUCK!
|
||||||
// WE ARE SENDING PAYMENT CMD TO DAEMON
|
// WE ARE SENDING PAYMENT CMD TO DAEMON
|
||||||
|
|
||||||
// perform the sendmany operation .. addressAccount
|
// perform the sendmany operation .. addressAccount
|
||||||
|
var rpccallTracking = 'sendmany "" '+JSON.stringify(addressAmounts);
|
||||||
daemon.cmd('sendmany', ["", addressAmounts], function (result) {
|
daemon.cmd('sendmany', ["", addressAmounts], function (result) {
|
||||||
// check for failed payments, there are many reasons
|
// check for failed payments, there are many reasons
|
||||||
if (result.error && result.error.code === -6) {
|
if (result.error && result.error.code === -6) {
|
||||||
// we thought we had enough funds to send payments, but apparently not...
|
// check if it is because we don't have enough funds
|
||||||
// try decreasing payments by a small percent to cover unexpected tx fees?
|
if (result.error.message && result.error.message.includes("insufficient funds")) {
|
||||||
var higherPercent = withholdPercent + 0.001;
|
// only try up to XX times (Max, 0.5%)
|
||||||
logger.warning(logSystem, logComponent, 'Not enough funds to cover the tx fees for sending out payments, decreasing rewards by ' + (higherPercent * 100) + '% and retrying');
|
if (tries < 5) {
|
||||||
trySend(higherPercent);
|
// we thought we had enough funds to send payments, but apparently not...
|
||||||
//callback(true); not a complete failure...
|
// try decreasing payments by a small percent to cover unexpected tx fees?
|
||||||
|
var higherPercent = withholdPercent + 0.001; // 0.1%
|
||||||
|
logger.warning(logSystem, logComponent, 'Insufficient funds (??) for payments ('+satoshisToCoins(totalSent)+'), decreasing rewards by ' + (higherPercent * 100).toFixed(1) + '% and retrying');
|
||||||
|
trySend(higherPercent);
|
||||||
|
} else {
|
||||||
|
logger.warning(logSystem, logComponent, rpccallTracking);
|
||||||
|
logger.error(logSystem, logComponent, "Error sending payments, decreased rewards by too much!!!");
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// there was some fatal payment error?
|
||||||
|
logger.warning(logSystem, logComponent, rpccallTracking);
|
||||||
|
logger.error(logSystem, logComponent, 'Error sending payments ' + JSON.stringify(result.error));
|
||||||
|
// payment failed, prevent updates to redis
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (result.error && result.error.code === -5) {
|
else if (result.error && result.error.code === -5) {
|
||||||
// invalid address specified in addressAmounts array
|
// invalid address specified in addressAmounts array
|
||||||
logger.error(logSystem, logComponent, 'Error sending payments ' + result.error.message);
|
logger.warning(logSystem, logComponent, rpccallTracking);
|
||||||
|
logger.error(logSystem, logComponent, 'Error sending payments ' + JSON.stringify(result.error));
|
||||||
// payment failed, prevent updates to redis
|
// payment failed, prevent updates to redis
|
||||||
callback(true);
|
callback(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (result.error && result.error.message != null) {
|
else if (result.error && result.error.message != null) {
|
||||||
// error from daemon
|
// invalid amount, others?
|
||||||
logger.error(logSystem, logComponent, 'Error sending payments ' + result.error.message);
|
logger.warning(logSystem, logComponent, rpccallTracking);
|
||||||
|
logger.error(logSystem, logComponent, 'Error sending payments ' + JSON.stringify(result.error));
|
||||||
// payment failed, prevent updates to redis
|
// payment failed, prevent updates to redis
|
||||||
callback(true);
|
callback(true);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue