Converted init coin info detection from RPC waterfall to batch RPC call. Added getblocktemplate after submitting block
This commit is contained in:
parent
a9270f3782
commit
9a42211c38
@ -132,7 +132,7 @@ function DaemonInterface(options){
|
|||||||
|
|
||||||
performHttpRequest(instances[0], serializedRequest, function(error, result){
|
performHttpRequest(instances[0], serializedRequest, function(error, result){
|
||||||
callback(error, result);
|
callback(error, result);
|
||||||
}, 'fuck');
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
272
lib/pool.js
272
lib/pool.js
@ -297,6 +297,12 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
isValidBlock = isAccepted;
|
isValidBlock = isAccepted;
|
||||||
shareData.txHash = tx;
|
shareData.txHash = tx;
|
||||||
emitShare();
|
emitShare();
|
||||||
|
|
||||||
|
GetBlockTemplate(function(error, result, foundNewBlock){
|
||||||
|
if (foundNewBlock)
|
||||||
|
emitLog('Block notification via RPC after block submission');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -332,199 +338,83 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
|
|
||||||
function DetectCoinData(finishedCallback){
|
function DetectCoinData(finishedCallback){
|
||||||
|
|
||||||
|
var batchRpcCalls = [
|
||||||
|
['validateaddress', [options.address]],
|
||||||
|
['getdifficulty', []],
|
||||||
|
['getinfo', []],
|
||||||
|
['getmininginfo', []],
|
||||||
|
['submitblock', []]
|
||||||
|
];
|
||||||
|
|
||||||
//TODO: Convert this all into a batch RPC call for better performance
|
_this.daemon.batchCmd(batchRpcCalls, function(error, results){
|
||||||
|
if (error || !results){
|
||||||
async.waterfall([
|
emitErrorLog('Could not start pool, error with init batch RPC call: ' + JSON.stringify(error));
|
||||||
|
|
||||||
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 + ' - ' + 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('not all addresses are valid');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//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;
|
|
||||||
});
|
|
||||||
|
|
||||||
options.coin.addressByte = util.getVersionByte(options.address);
|
|
||||||
|
|
||||||
callback(null, ownedInfo.length > 0 ? ownedInfo[0].response : results[0].response);
|
|
||||||
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
function(addressInfo, callback){
|
|
||||||
var examplePubKey = new Buffer([options.coin.addressByte, new Buffer('010966776006953D5567439E5E39F86A0D273BEE', 'hex')]);
|
|
||||||
var dHashed = util.sha256d(examplePubKey);
|
|
||||||
var binaryAddress =
|
|
||||||
|
|
||||||
callback(null, addressInfo);
|
|
||||||
},
|
|
||||||
|
|
||||||
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.protocolVersion = infoResult.protocolversion;
|
|
||||||
|
|
||||||
options.initStats = { connections: infoResult.connections, difficulty: infoResult.difficulty };
|
|
||||||
|
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rpcResults = {};
|
||||||
|
|
||||||
|
for (var i = 0; i < results.length; i++){
|
||||||
|
var rpcCall = batchRpcCalls[i][0];
|
||||||
|
var r = results[i];
|
||||||
|
rpcResults[rpcCall] = r.result || r.error;
|
||||||
|
|
||||||
|
if (rpcCall !== 'submitblock' && (r.error || !r.result)){
|
||||||
|
emitErrorLog('Could not start pool, error with init RPC ' + rpcCall + ' - ' + JSON.stringify(r.error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rpcResults.validateaddress.isvalid){
|
||||||
|
emitErrorLog('Daemon reports address is not valid');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(rpcResults.getdifficulty) && 'proof-of-stake' in rpcResults.getdifficulty)
|
||||||
|
options.coin.reward = 'POS';
|
||||||
|
else
|
||||||
|
options.coin.reward = '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(rpcResults.validateaddress.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(rpcResults.validateaddress.pubkey);
|
||||||
|
case 'POW':
|
||||||
|
return util.addressToScript(rpcResults.validateaddress.address);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
options.testnet = rpcResults.getinfo.testnet;
|
||||||
|
options.protocolVersion = rpcResults.getinfo.protocolversion;
|
||||||
|
|
||||||
|
options.initStats = {
|
||||||
|
connections: rpcResults.getinfo.connections,
|
||||||
|
difficulty: rpcResults.getinfo.difficulty,
|
||||||
|
networkHashRate: rpcResults.getmininginfo.networkhashps
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (rpcResults.submitblock.message === 'Method not found'){
|
||||||
|
options.hasSubmitMethod = false;
|
||||||
|
}
|
||||||
|
else if (rpcResults.submitblock.code === -1){
|
||||||
|
options.hasSubmitMethod = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
emitErrorLog('Could not detect block submission RPC method, ' + JSON.stringify(results));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
finishedCallback();
|
finishedCallback();
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,7 +559,7 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
|
|
||||||
|
|
||||||
function CheckBlockAccepted(blockHash, callback){
|
function CheckBlockAccepted(blockHash, callback){
|
||||||
setTimeout(function(){
|
//setTimeout(function(){
|
||||||
_this.daemon.cmd('getblock',
|
_this.daemon.cmd('getblock',
|
||||||
[blockHash],
|
[blockHash],
|
||||||
function(results){
|
function(results){
|
||||||
@ -685,7 +575,7 @@ var pool = module.exports = function pool(options, authorizeFn){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}, 500);
|
//}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user