Restructured pool object - much cleaner and easier to follow flow.
This commit is contained in:
parent
5b849dce59
commit
b05f7689f3
@ -84,15 +84,16 @@ var JobManager = module.exports = function JobManager(maxDifficulty, hashDigest,
|
|||||||
(_this.currentJob.rpcData.transactions.length != rpcData.transactions.length)
|
(_this.currentJob.rpcData.transactions.length != rpcData.transactions.length)
|
||||||
|
|
||||||
|
|
||||||
if (updatedTransactions && (Date.now() - lastTransactionUpdateCheck >= options.txRefreshInterval)){
|
if (updatedTransactions && (Date.now() - lastTransactionUpdateCheck <= options.txRefreshInterval)){
|
||||||
lastTransactionUpdateCheck = Date.now();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
updatedTransactions = false;
|
updatedTransactions = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//Update current job if new block or new transactions
|
//Update current job if new block or new transactions
|
||||||
if (isNewBlock || updatedTransactions){
|
if (isNewBlock || updatedTransactions){
|
||||||
|
|
||||||
|
lastTransactionUpdateCheck = Date.now();
|
||||||
|
|
||||||
var tmpBlockTemplate = new blockTemplate(
|
var tmpBlockTemplate = new blockTemplate(
|
||||||
maxDifficulty,
|
maxDifficulty,
|
||||||
jobCounter.next(),
|
jobCounter.next(),
|
||||||
|
|||||||
522
lib/pool.js
522
lib/pool.js
@ -37,7 +37,6 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
this.options = options;
|
this.options = options;
|
||||||
|
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var publicKeyBuffer;
|
|
||||||
var blockPollingIntervalId;
|
var blockPollingIntervalId;
|
||||||
|
|
||||||
|
|
||||||
@ -53,12 +52,13 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
case 'sha256':
|
case 'sha256':
|
||||||
case 'skein':
|
case 'skein':
|
||||||
case 'hefty1':
|
case 'hefty1':
|
||||||
|
case 'keccak':
|
||||||
return '00000000ffff0000000000000000000000000000000000000000000000000000';
|
return '00000000ffff0000000000000000000000000000000000000000000000000000';
|
||||||
case 'scrypt':
|
case 'scrypt':
|
||||||
case 'scrypt-jane':
|
case 'scrypt-jane':
|
||||||
case 'x11':
|
case 'x11':
|
||||||
case 'quark':
|
case 'quark':
|
||||||
case 'keccak':
|
case 'max':
|
||||||
return '0000ffff00000000000000000000000000000000000000000000000000000000';
|
return '0000ffff00000000000000000000000000000000000000000000000000000000';
|
||||||
default:
|
default:
|
||||||
emitErrorLog('The ' + options.coin.algorithm + ' hashing algorithm is not supported.');
|
emitErrorLog('The ' + options.coin.algorithm + ' hashing algorithm is not supported.');
|
||||||
@ -114,10 +114,112 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
emitLog('Starting pool for ' + options.coin.name + ' [' + options.coin.symbol.toUpperCase() + ']');
|
emitLog('Starting pool for ' + options.coin.name + ' [' + options.coin.symbol.toUpperCase() + ']');
|
||||||
SetupJobManager();
|
SetupJobManager();
|
||||||
SetupVarDiff();
|
SetupVarDiff();
|
||||||
SetupDaemonInterface();
|
|
||||||
SetupApi();
|
SetupApi();
|
||||||
|
SetupDaemonInterface(function(){
|
||||||
|
DetectCoinData(function(){
|
||||||
|
OnBlockchainSynced(function(){
|
||||||
|
GetFirstJob(function(){
|
||||||
|
OutputPoolInfo();
|
||||||
|
SetupBlockPolling();
|
||||||
|
StartStratumServer();
|
||||||
|
SetupPeer();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function GetFirstJob(finishedCallback){
|
||||||
|
|
||||||
|
GetBlockTemplate(function(error, result){
|
||||||
|
if (error) {
|
||||||
|
emitErrorLog('Error with getblocktemplate on creating first job, server cannot start');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(options.ports).forEach(function(port){
|
||||||
|
var portDiff = options.ports[port].diff;
|
||||||
|
if (portDiff > _this.jobManager.currentJob.difficulty)
|
||||||
|
emitWarningLog('Pool difficulty of ' + portDiff + ' on port ' + port +
|
||||||
|
' was set higher than network difficulty of ' + _this.jobManager.currentJob.difficulty);
|
||||||
|
});
|
||||||
|
|
||||||
|
finishedCallback();
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function OutputPoolInfo(){
|
||||||
|
|
||||||
|
|
||||||
|
if (!process.env.forkId || process.env.forkId === '0')
|
||||||
|
emitLog(['Pool Server Started...',
|
||||||
|
'Running Coin Pool:\t' + options.coin.name + ' [' + options.coin.symbol.toUpperCase() + ']',
|
||||||
|
'Network Connected:\t' + (options.testnet ? 'Testnet' : 'Live Blockchain'),
|
||||||
|
'Detected Reward Type:\t' + options.coin.reward,
|
||||||
|
'Current Block Height:\t' + _this.jobManager.currentJob.rpcData.height,
|
||||||
|
'Current Connect Peers:\t' + options.initStats.connections,
|
||||||
|
'Network Hash Rate:\t' + (options.initStats.networkHashRate / 1e3).toFixed(6) + ' KH/s',
|
||||||
|
'Network Difficulty:\t' + _this.jobManager.currentJob.difficulty
|
||||||
|
].join('\n\t\t\t\t\t\t')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function OnBlockchainSynced(syncedCallback){
|
||||||
|
|
||||||
|
var checkSynced = function(displayNotSynced){
|
||||||
|
_this.daemon.cmd('getblocktemplate', [], function(results){
|
||||||
|
var synced = results.every(function(r){
|
||||||
|
return !r.error || r.error.code !== -10;
|
||||||
|
});
|
||||||
|
if (synced){
|
||||||
|
syncedCallback();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (displayNotSynced) displayNotSynced();
|
||||||
|
setTimeout(checkSynced, 5000);
|
||||||
|
generateProgress(smallestHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
checkSynced(function(){
|
||||||
|
emitErrorLog('Daemon is still syncing with network (download blockchain) - server will be started once synced');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var generateProgress = function(){
|
||||||
|
|
||||||
|
_this.daemon.cmd('getinfo', [], function(results) {
|
||||||
|
var blockCount = results.sort(function (a, b) {
|
||||||
|
return b.response.blocks - a.response.blocks;
|
||||||
|
})[0].response.blocks;
|
||||||
|
|
||||||
|
//get list of peers and their highest block height to compare to ours
|
||||||
|
_this.daemon.cmd('getpeerinfo', [], function(results){
|
||||||
|
|
||||||
|
var peers = results[0].response;
|
||||||
|
var totalBlocks = peers.sort(function(a, b){
|
||||||
|
return b.startingheight - a.startingheight;
|
||||||
|
})[0].startingheight;
|
||||||
|
|
||||||
|
var percent = (blockCount / totalBlocks * 100).toFixed(2);
|
||||||
|
|
||||||
|
//Only let the first fork show synced status or the log wil look flooded with it
|
||||||
|
if (!process.env.forkId || process.env.forkId === '0')
|
||||||
|
emitWarningLog('Downloaded ' + percent + '% of blockchain from network');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function SetupApi() {
|
function SetupApi() {
|
||||||
if (typeof(options.api) !== 'object' || typeof(options.api.start) !== 'function') {
|
if (typeof(options.api) !== 'object' || typeof(options.api.start) !== 'function') {
|
||||||
return;
|
return;
|
||||||
@ -126,6 +228,7 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function SetupPeer(){
|
function SetupPeer(){
|
||||||
if (!options.p2p || !options.p2p.enabled)
|
if (!options.p2p || !options.p2p.enabled)
|
||||||
return;
|
return;
|
||||||
@ -139,10 +242,11 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
}).on('error', function(msg){
|
}).on('error', function(msg){
|
||||||
emitWarningLog(msg);
|
emitWarningLog(msg);
|
||||||
}).on('blockFound', function(hash){
|
}).on('blockFound', function(hash){
|
||||||
this.processBlockNotify(hash);
|
_this.processBlockNotify(hash);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function SetupVarDiff(){
|
function SetupVarDiff(){
|
||||||
_this.varDiff = {};
|
_this.varDiff = {};
|
||||||
Object.keys(options.ports).forEach(function(port) {
|
Object.keys(options.ports).forEach(function(port) {
|
||||||
@ -151,6 +255,7 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Coin daemons either use submitblock or getblocktemplate for submitting new blocks
|
Coin daemons either use submitblock or getblocktemplate for submitting new blocks
|
||||||
*/
|
*/
|
||||||
@ -195,13 +300,13 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
_this.jobManager.on('newBlock', function(blockTemplate){
|
_this.jobManager.on('newBlock', function(blockTemplate){
|
||||||
//Check if stratumServer has been initialized yet
|
//Check if stratumServer has been initialized yet
|
||||||
if ( typeof(_this.stratumServer ) !== 'undefined') {
|
if ( typeof(_this.stratumServer ) !== 'undefined') {
|
||||||
emitLog('Detected new block');
|
//emitLog('Detected new block');
|
||||||
_this.stratumServer.broadcastMiningJobs(blockTemplate.getJobParams());
|
_this.stratumServer.broadcastMiningJobs(blockTemplate.getJobParams());
|
||||||
}
|
}
|
||||||
}).on('updatedBlock', function(blockTemplate){
|
}).on('updatedBlock', function(blockTemplate){
|
||||||
//Check if stratumServer has been initialized yet
|
//Check if stratumServer has been initialized yet
|
||||||
if ( typeof(_this.stratumServer ) !== 'undefined') {
|
if ( typeof(_this.stratumServer ) !== 'undefined') {
|
||||||
emitLog('Detected updated block transactions');
|
//emitLog('Detected updated block transactions');
|
||||||
var job = blockTemplate.getJobParams();
|
var job = blockTemplate.getJobParams();
|
||||||
job[8] = false;
|
job[8] = false;
|
||||||
_this.stratumServer.broadcastMiningJobs(job);
|
_this.stratumServer.broadcastMiningJobs(job);
|
||||||
@ -235,181 +340,12 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function SetupDaemonInterface(){
|
function SetupDaemonInterface(finishedCallback){
|
||||||
|
|
||||||
if (!_this.daemon) _this.daemon = new daemon.interface(options.daemons);
|
_this.daemon = new daemon.interface(options.daemons);
|
||||||
|
|
||||||
_this.daemon.once('online', function(){
|
_this.daemon.once('online', function(){
|
||||||
async.parallel({
|
finishedCallback();
|
||||||
|
|
||||||
addressInfo: function(callback){
|
|
||||||
_this.daemon.cmd('validateaddress', [options.address], function(results){
|
|
||||||
|
|
||||||
//Make sure address is valid with each daemon
|
|
||||||
var allValid = results.every(function(result){
|
|
||||||
if (result.error || !result.response){
|
|
||||||
emitErrorLog('validateaddress rpc error on daemon instance ' +
|
|
||||||
result.instance.index + ', error +' + JSON.stringify(result.error));
|
|
||||||
}
|
|
||||||
else if (!result.response.isvalid)
|
|
||||||
emitErrorLog('Daemon instance ' + result.instance.index +
|
|
||||||
' reports address is not valid');
|
|
||||||
return result.response && result.response.isvalid;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (allValid)
|
|
||||||
callback(null, results[0].response);
|
|
||||||
else{
|
|
||||||
callback('not all addresses are valid')
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
info: function(callback){
|
|
||||||
_this.daemon.cmd('getinfo', [], function(results){
|
|
||||||
|
|
||||||
// Print which network each daemon is running on
|
|
||||||
|
|
||||||
var isTestnet;
|
|
||||||
var allValid = results.every(function(result){
|
|
||||||
|
|
||||||
if (result.error){
|
|
||||||
emitErrorLog('getmininginfo on init failed with daemon instance ' +
|
|
||||||
result.instance.index + ', error ' + JSON.stringify(result.error)
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof isTestnet === 'undefined'){
|
|
||||||
isTestnet = result.response.testnet;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (isTestnet !== result.response.testnet){
|
|
||||||
emitErrorLog('not all daemons are on same network');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
if (!allValid){
|
|
||||||
callback('could not getmininginfo correctly on each daemon');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Find and return the response with the largest block height (most in-sync)
|
|
||||||
var largestHeight = results.sort(function(a, b){
|
|
||||||
return b.response.blocks - a.response.blocks;
|
|
||||||
})[0].response;
|
|
||||||
|
|
||||||
callback(null, largestHeight);
|
|
||||||
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
rewardType: function(callback){
|
|
||||||
_this.daemon.cmd('getdifficulty', [], function(results){
|
|
||||||
|
|
||||||
var isPos = results.every(function(result){
|
|
||||||
|
|
||||||
if (result.error){
|
|
||||||
emitErrorLog('getinfo on init failed with daemon instance ' +
|
|
||||||
result.instance.index + ', error ' + JSON.stringify(result.error)
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isNaN(result.response) && 'proof-of-stake' in result.response;
|
|
||||||
});
|
|
||||||
|
|
||||||
options.coin.reward = isPos ? 'POS' : 'POW'
|
|
||||||
callback(null);
|
|
||||||
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
submitMethod: function(callback){
|
|
||||||
/* This checks to see whether the daemon uses submitblock
|
|
||||||
or getblocktemplate for submitting new blocks */
|
|
||||||
_this.daemon.cmd('submitblock', [], function(results){
|
|
||||||
var couldNotDetectMethod = results.every(function(result){
|
|
||||||
if (result.error && result.error.message === 'Method not found'){
|
|
||||||
options.hasSubmitMethod = false;
|
|
||||||
callback(null);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (result.error && result.error.code === -1){
|
|
||||||
options.hasSubmitMethod = true;
|
|
||||||
callback(null);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
if (couldNotDetectMethod){
|
|
||||||
emitErrorLog('Could not detect block submission RPC method, ' + JSON.stringify(results));
|
|
||||||
callback('block submission detection failed');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, function(err, results){
|
|
||||||
if (err){
|
|
||||||
emitErrorLog('Could not start pool, ' + JSON.stringify(err));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.coin.reward === 'POS' && typeof(results.addressInfo.pubkey) == 'undefined') {
|
|
||||||
// address provided is not of the wallet.
|
|
||||||
emitErrorLog('The address provided is not from the daemon wallet.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
publicKeyBuffer = (function(){
|
|
||||||
switch(options.coin.reward){
|
|
||||||
case 'POS':
|
|
||||||
return util.pubkeyToScript(results.addressInfo.pubkey);
|
|
||||||
case 'POW':
|
|
||||||
if (options.coin.algorithm)
|
|
||||||
return util.addressToScript(results.addressInfo.address);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
var networkType = results.info.testnet ? 'testnet' : 'live blockchain';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GetBlockTemplate(function(error, result){
|
|
||||||
if (error) {
|
|
||||||
if (error.code === -10){
|
|
||||||
emitErrorLog('Daemon is still syncing with network (download blocks)');
|
|
||||||
WaitForSync(results.info.blocks);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
emitErrorLog('Error with getblocktemplate on initializing');
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Object.keys(options.ports).forEach(function(port){
|
|
||||||
var portDiff = options.ports[port].diff;
|
|
||||||
if (portDiff > _this.jobManager.currentJob.difficulty)
|
|
||||||
emitWarningLog('Pool difficulty of ' + portDiff + ' on port ' + port +
|
|
||||||
' was set higher than network difficulty of ' + _this.jobManager.currentJob.difficulty);
|
|
||||||
});
|
|
||||||
|
|
||||||
emitLog('Connected to ' + networkType +
|
|
||||||
'; detected ' + options.coin.reward +
|
|
||||||
' reward type; block height of ' + results.info.blocks +
|
|
||||||
'; difficulty of ' + _this.jobManager.currentJob.difficulty);
|
|
||||||
|
|
||||||
SetupBlockPolling();
|
|
||||||
StartStratumServer();
|
|
||||||
SetupPeer();
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}).on('connectionFailed', function(error){
|
}).on('connectionFailed', function(error){
|
||||||
emitErrorLog('Failed to connect daemon(s): ' + JSON.stringify(error));
|
emitErrorLog('Failed to connect daemon(s): ' + JSON.stringify(error));
|
||||||
@ -423,54 +359,197 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function DetectCoinData(finishedCallback){
|
||||||
|
|
||||||
function WaitForSync(currentBlocks){
|
async.waterfall([
|
||||||
|
|
||||||
var generateProgress = function(currentBlocks){
|
|
||||||
|
|
||||||
//get list of peers and their highest block height to compare to ours
|
function(callback){
|
||||||
|
_this.daemon.cmd('validateaddress', [options.address], function(results){
|
||||||
|
|
||||||
_this.daemon.cmd('getpeerinfo', [], function(results){
|
//Make sure address is valid with each daemon
|
||||||
|
var allValid = results.every(function(result){
|
||||||
var peers = results[0].response;
|
if (result.error || !result.response){
|
||||||
var totalBlocks = peers.sort(function(a, b){
|
emitErrorLog('validateaddress rpc error on daemon instance ' +
|
||||||
return b.startingheight - a.startingheight;
|
result.instance.index + ', error +' + JSON.stringify(result.error));
|
||||||
})[0].startingheight;
|
}
|
||||||
|
else if (!result.response.isvalid)
|
||||||
var percent = (currentBlocks / totalBlocks * 100).toFixed(2);
|
emitErrorLog('Daemon instance ' + result.instance.index +
|
||||||
|
' reports address is not valid');
|
||||||
//Only let the first fork show synced status or the log wil look flooded with it
|
return result.response && result.response.isvalid;
|
||||||
if (!process.env.forkId || process.env.forkId === '0')
|
|
||||||
emitWarningLog('Downloaded ' + percent + '% of blockchain from network');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
generateProgress(currentBlocks);
|
|
||||||
|
|
||||||
setInterval(function(){
|
|
||||||
|
|
||||||
_this.daemon.cmd('getblocktemplate', [], function(results){
|
|
||||||
var synced = results.every(function(r){
|
|
||||||
return !r.error || r.error.code !== -10;
|
|
||||||
});
|
|
||||||
if (synced){
|
|
||||||
SetupDaemonInterface();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
_this.daemon.cmd('getinfo', [], function(results){
|
|
||||||
var smallestHeight = results.sort(function(a, b){
|
|
||||||
return b.response.blocks - a.response.blocks;
|
|
||||||
})[0].response.blocks;
|
|
||||||
generateProgress(smallestHeight);
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
});
|
if (!allValid){
|
||||||
|
callback('not all addresses are valid');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}, 5000);
|
//Try to find result that owns address in case of POS coin with multi daemons
|
||||||
|
var ownedInfo = results.filter(function(r){
|
||||||
|
return r.response.ismine;
|
||||||
|
});
|
||||||
|
|
||||||
|
callback(null, !!ownedInfo.length ? ownedInfo[0].response : results[0].response);
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function(addressInfo, callback){
|
||||||
|
_this.daemon.cmd('getdifficulty', [], function(results){
|
||||||
|
|
||||||
|
//This detects if a coin is POS because getdiff returns an object instead of a number
|
||||||
|
|
||||||
|
var isPos = results.every(function(result){
|
||||||
|
|
||||||
|
if (result.error){
|
||||||
|
emitErrorLog('getinfo on init failed with daemon instance ' +
|
||||||
|
result.instance.index + ', error ' + JSON.stringify(result.error)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isNaN(result.response) && 'proof-of-stake' in result.response;
|
||||||
|
});
|
||||||
|
|
||||||
|
options.coin.reward = isPos ? 'POS' : 'POW';
|
||||||
|
|
||||||
|
/* POS coins must use the pubkey in coinbase transaction, and pubkey is
|
||||||
|
only given if address is owned by wallet.*/
|
||||||
|
if (options.coin.reward === 'POS' && typeof(addressInfo.pubkey) == 'undefined') {
|
||||||
|
emitErrorLog('The address provided is not from the daemon wallet - this is required for POS coins.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
options.publicKeyBuffer = (function(){
|
||||||
|
switch(options.coin.reward){
|
||||||
|
case 'POS':
|
||||||
|
return util.pubkeyToScript(addressInfo.pubkey);
|
||||||
|
case 'POW':
|
||||||
|
return util.addressToScript(addressInfo.address);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
callback(null);
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function(callback){
|
||||||
|
_this.daemon.cmd('getinfo', [], function(results){
|
||||||
|
|
||||||
|
// Print which network each daemon is running on
|
||||||
|
|
||||||
|
var isTestnet;
|
||||||
|
var allValid = results.every(function(result){
|
||||||
|
|
||||||
|
if (result.error){
|
||||||
|
emitErrorLog('getinfo on init failed with daemon instance ' +
|
||||||
|
result.instance.index + ', error ' + JSON.stringify(result.error)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Make sure every daemon is on the correct network or the config is wrong
|
||||||
|
if (typeof isTestnet === 'undefined'){
|
||||||
|
isTestnet = result.response.testnet;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (isTestnet !== result.response.testnet){
|
||||||
|
emitErrorLog('not all daemons are on same network');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (!allValid){
|
||||||
|
callback('could not getinfo correctly on each daemon');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Find and return the response with the largest block height (most in-sync)
|
||||||
|
var infoResult = results.sort(function(a, b){
|
||||||
|
return b.response.blocks - a.response.blocks;
|
||||||
|
})[0].response;
|
||||||
|
|
||||||
|
options.testnet = infoResult.testnet;
|
||||||
|
|
||||||
|
options.initStats = { connections: infoResult.connections};
|
||||||
|
|
||||||
|
callback(null);
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function(callback){
|
||||||
|
_this.daemon.cmd('getmininginfo', [], function(results){
|
||||||
|
var allValid = results.every(function(result){
|
||||||
|
if (result.error){
|
||||||
|
emitErrorLog('getmininginfo on init failed with daemon instance ' +
|
||||||
|
result.instance.index + ', error ' + JSON.stringify(result.error)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!allValid){
|
||||||
|
callback('could not getmininginfo correctly on each daemon');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Find and return the response with the largest block height (most in-sync)
|
||||||
|
var miningInfoResult = results.sort(function(a, b){
|
||||||
|
return b.response.blocks - a.response.blocks;
|
||||||
|
})[0].response;
|
||||||
|
|
||||||
|
options.initStats.networkHashRate = miningInfoResult.networkhashps;
|
||||||
|
|
||||||
|
callback(null);
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function(callback){
|
||||||
|
/* This checks to see whether the daemon uses submitblock
|
||||||
|
or getblocktemplate for submitting new blocks */
|
||||||
|
_this.daemon.cmd('submitblock', [], function(results){
|
||||||
|
var couldNotDetectMethod = results.every(function(result){
|
||||||
|
if (result.error && result.error.message === 'Method not found'){
|
||||||
|
options.hasSubmitMethod = false;
|
||||||
|
callback(null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (result.error && result.error.code === -1){
|
||||||
|
options.hasSubmitMethod = true;
|
||||||
|
callback(null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (couldNotDetectMethod){
|
||||||
|
emitErrorLog('Could not detect block submission RPC method, ' + JSON.stringify(results));
|
||||||
|
callback('block submission detection failed');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], function(err, results){
|
||||||
|
if (err){
|
||||||
|
emitErrorLog('Could not start pool, ' + JSON.stringify(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
finishedCallback();
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function StartStratumServer(){
|
function StartStratumServer(){
|
||||||
_this.stratumServer = new stratum.Server(options.ports, options.connectionTimeout, options.banning, authorizeFn);
|
_this.stratumServer = new stratum.Server(options.ports, options.connectionTimeout, options.banning, authorizeFn);
|
||||||
|
|
||||||
@ -540,6 +619,8 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function SetupBlockPolling(){
|
function SetupBlockPolling(){
|
||||||
|
|
||||||
if (typeof options.blockRefreshInterval !== "number" || options.blockRefreshInterval <= 0){
|
if (typeof options.blockRefreshInterval !== "number" || options.blockRefreshInterval <= 0){
|
||||||
@ -555,6 +636,8 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
emitLog('Block polling every ' + pollingInterval + ' milliseconds');
|
emitLog('Block polling every ' + pollingInterval + ' milliseconds');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function GetBlockTemplate(callback){
|
function GetBlockTemplate(callback){
|
||||||
_this.daemon.cmd('getblocktemplate',
|
_this.daemon.cmd('getblocktemplate',
|
||||||
[{"capabilities": [ "coinbasetxn", "workid", "coinbase/append" ]}],
|
[{"capabilities": [ "coinbasetxn", "workid", "coinbase/append" ]}],
|
||||||
@ -564,7 +647,7 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
result.instance.index + ' with error ' + JSON.stringify(result.error));
|
result.instance.index + ' with error ' + JSON.stringify(result.error));
|
||||||
callback(result.error);
|
callback(result.error);
|
||||||
} else {
|
} else {
|
||||||
var processedNewBlock = _this.jobManager.processTemplate(result.response, publicKeyBuffer);
|
var processedNewBlock = _this.jobManager.processTemplate(result.response, options.publicKeyBuffer);
|
||||||
|
|
||||||
if (processedNewBlock) {
|
if (processedNewBlock) {
|
||||||
|
|
||||||
@ -581,6 +664,8 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function CheckBlockAccepted(blockHash, callback){
|
function CheckBlockAccepted(blockHash, callback){
|
||||||
_this.daemon.cmd('getblock',
|
_this.daemon.cmd('getblock',
|
||||||
[blockHash],
|
[blockHash],
|
||||||
@ -600,6 +685,8 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is being called from the blockNotify so that when a new block is discovered by the daemon
|
* This method is being called from the blockNotify so that when a new block is discovered by the daemon
|
||||||
* We can inform our miners about the newly found block
|
* We can inform our miners about the newly found block
|
||||||
@ -646,6 +733,7 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.attachMiners = function(miners) {
|
this.attachMiners = function(miners) {
|
||||||
miners.forEach(function (clientObj) {
|
miners.forEach(function (clientObj) {
|
||||||
_this.stratumServer.manuallyAddStratumClient(clientObj);
|
_this.stratumServer.manuallyAddStratumClient(clientObj);
|
||||||
@ -654,10 +742,12 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.getStratumServer = function() {
|
this.getStratumServer = function() {
|
||||||
return _this.stratumServer;
|
return _this.stratumServer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.setVarDiff = function(port, varDiffInstance) {
|
this.setVarDiff = function(port, varDiffInstance) {
|
||||||
if (typeof(_this.varDiff[port]) != 'undefined' ) {
|
if (typeof(_this.varDiff[port]) != 'undefined' ) {
|
||||||
_this.varDiff[port].removeAllListeners();
|
_this.varDiff[port].removeAllListeners();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user