Fixed duplicate shares on vardiff difficulty update. Added more comments.

This commit is contained in:
Matt 2014-02-19 13:46:17 -07:00
parent 87bab0dfd1
commit 897dadbf11
3 changed files with 54 additions and 12 deletions

View File

@ -16,10 +16,10 @@ var blockTemplate = require('./blockTemplate.js');
var ExtraNonceCounter = function(){
var instanceId = 31;
var counter = instanceId << 27;
var size = util.packUInt32BE(counter).length; //binpack.packUInt32(counter, 'big').length;
var size = util.packUInt32BE(counter).length;
this.next = function(){
var extraNonce = util.packUInt32BE(counter++);//binpack.packUInt32(counter++, 'big');
var extraNonce = util.packUInt32BE(counter++);
return extraNonce.toString('hex');
};
this.size = function(){
@ -54,6 +54,7 @@ var JobManager = module.exports = function JobManager(options){
var _this = this;
var jobCounter = new JobCounter();
//var jobs = {};
/**
* It only checks if the blockTemplate is already in our jobs list.
@ -68,8 +69,19 @@ var JobManager = module.exports = function JobManager(options){
} else {
return false;
}
/*var newBlock = true;
for(var job in jobs){
if (jobs[job].rpcData.previousblockhash === prevBlockHash) {
newBlock = false;
}
}
return newBlock;*/
}
//Which number to use as dividend when converting difficulty to target
var diffDividend = (function(){
switch(options.algorithm){
case 'sha256':
@ -82,6 +94,8 @@ var JobManager = module.exports = function JobManager(options){
}
})();
//On initialization lets figure out which hashing algorithm to use
var hashDigest = (function(){
switch(options.algorithm){
case 'sha256':
@ -103,7 +117,6 @@ var JobManager = module.exports = function JobManager(options){
}
})();
//public members
@ -125,6 +138,8 @@ var JobManager = module.exports = function JobManager(options){
options.txMessages
);
//jobs[tmpBlockTemplate.jobId] = tmpBlockTemplate;
this.currentJob = tmpBlockTemplate;
_this.emit('newBlock', tmpBlockTemplate);
}
@ -132,7 +147,6 @@ var JobManager = module.exports = function JobManager(options){
this.processShare = function(jobId, difficulty, extraNonce1, extraNonce2, nTime, nonce, ipAddress, workerName){
var shareError = function(error){
_this.emit('share', {
job: jobId,
@ -150,7 +164,9 @@ var JobManager = module.exports = function JobManager(options){
return shareError([20, 'incorrect size of extranonce2']);
var job = this.currentJob;
if ( job.jobId != jobId ) {
//var job = jobs[jobId];
if (typeof job === 'undefined' || job.jobId != jobId ) {
return shareError([21, 'job not found']);
}

View File

@ -52,7 +52,25 @@ var pool = module.exports = function pool(options, authorizeFn){
RequestDifficulty(function(){});
}).on('newDifficulty', function(client, newDiff){
client.sendDifficulty(newDiff);
client.sendMiningJob(_this.jobManager.currentJob.getJobParams());
/*
Disabled this line of code as it will because it will force the miner
to restart and submit duplicate shares. The stratum-python sends out a
mining.notify but rolls the jobID and sets "clean jobs" to false.
Meaning that the worker will only start on the new work once it
exhausts its current nonce range. But if the miner were to start the
new job, the shares would be invalidated since stratum-python doesn't
insert the new jobID that the share-limiter generated into the jobs
array. Also, since the new work is only sent with a new jobID but with
the same extranonce as the last job, the shares will be duplicate
anyway. Perhaps this bug has gone unnoticed because of how likely it
is for a miner to exhaust the nonce range before new work is sent.
So lets only send a new difficulty, and the worker will use it when
it receives a new job when the block template updates.
*/
//client.sendMiningJob(_this.jobManager.currentJob.getJobParams());
});
emitLog("system", "VarDiff enabled and setup");
}

View File

@ -118,10 +118,7 @@ var Generation = exports.Generation = function Generation(rpcData, publicKey, ex
/*
This function creates the generation transaction that accepts the reward for
successfully mining a new block. Creating this function required tons of trial
and error and reversing existing pool server code. I went to write a good comment
describing how it works in detail but at this point I don't even know..
successfully mining a new block.
For some (probably outdated and incorrect) documentation about whats kinda going on here,
see: https://en.bitcoin.it/wiki/Protocol_specification#tx
*/
@ -139,6 +136,11 @@ exports.CreateGeneration = function(rpcData, publicKey, extraNoncePlaceholder, r
var txInPrevOutIndex = Math.pow(2, 32) - 1;
var txInSequence = 0;
//Only required for POS coins
var txTimestamp = reward === 'POS' ?
util.packUInt32LE(rpcData.curtime) : new Buffer([]);
//For coins that support/require transaction comments
var txComment = txMessages === true ?
util.serializeString('https://github.com/zone117x/node-stratum') :
new Buffer([]);
@ -153,10 +155,9 @@ exports.CreateGeneration = function(rpcData, publicKey, extraNoncePlaceholder, r
var scriptSigPart2 = util.serializeString('/nodeStratum/');
var p1 = Buffer.concat([
util.packUInt32LE(txVersion),
reward === 'POS' ? util.packUInt32LE(rpcData.curtime) : new Buffer([]),
txTimestamp,
util.varIntBuffer(txInputsCount),
//transaction input
@ -166,6 +167,13 @@ exports.CreateGeneration = function(rpcData, publicKey, extraNoncePlaceholder, r
scriptSigPart1
]);
/*
The generation transaction must be split at the extranonce (which located in the transaction input
scriptSig). Miners send us unique extranonces that we use to join the two parts in attempt to create
a valid share and/or block.
*/
var p2 = Buffer.concat([
scriptSigPart2,
util.packUInt32LE(txInSequence),