updated
This commit is contained in:
parent
b37f4f974b
commit
7a21abacc4
@ -12,9 +12,9 @@ Features (mostly untested)
|
||||
* Stratum TCP socket server
|
||||
* Block template / job manager
|
||||
* Optimized generation transaction building
|
||||
* Process share submissions
|
||||
|
||||
#### To do
|
||||
* Handle share submissions
|
||||
* Payment processing module
|
||||
* Support more algos (scrypt, scrypt-jane, quark)
|
||||
* Port [scrypt hash](https://github.com/Tydus/litecoin_scrypt) to node module
|
||||
|
||||
@ -10,6 +10,8 @@ var BlockTemplate = module.exports = function BlockTemplate(jobId, rpcData, publ
|
||||
|
||||
//private members
|
||||
|
||||
var submits = [];
|
||||
|
||||
function getMerkleHashes(steps){
|
||||
return steps.map(function(step){
|
||||
return util.reverseBuffer(step).toString('hex');
|
||||
@ -28,6 +30,11 @@ var BlockTemplate = module.exports = function BlockTemplate(jobId, rpcData, publ
|
||||
|
||||
this.rpcData = rpcData;
|
||||
this.jobId = jobId;
|
||||
this.target = util.bignumFromBits(rpcData.bits);
|
||||
this.previousHashBuffer = util.reverseHex(rpcData.previousblockhash);
|
||||
this.transactionData = Buffer.concat(rpcData.transactions.map(function(tx){
|
||||
return new Buffer(tx.data, 'hex');
|
||||
}));
|
||||
this.merkleTree = new merkleTree(getTransactionBuffers(rpcData.transactions));
|
||||
this.merkleBranch = getMerkleHashes(this.merkleTree.steps);
|
||||
this.generationTransaction = new transactions.Generation(
|
||||
@ -37,11 +44,49 @@ var BlockTemplate = module.exports = function BlockTemplate(jobId, rpcData, publ
|
||||
extraNoncePlaceholder
|
||||
);
|
||||
|
||||
this.serializeCoinbase = function(extraNonce1, extraNonce2){
|
||||
return Buffer.concat([
|
||||
this.generationTransaction.coinbase[0],
|
||||
extraNonce1,
|
||||
extraNonce2,
|
||||
this.generationTransaction.coinbase[1]
|
||||
]);
|
||||
};
|
||||
|
||||
this.serializeHeader = function(merkleRootBuffer, nTimeBuffer, nonceBuffer){
|
||||
return Buffer.concat([
|
||||
binpack.packInt32(rpcData.version, 'big'),
|
||||
this.previousHashBuffer,
|
||||
merkleRootBuffer,
|
||||
nTimeBuffer,
|
||||
new Buffer(this.rpcData.bits, 'hex'),
|
||||
nonceBuffer
|
||||
]);
|
||||
};
|
||||
|
||||
this.serializeBlock = function(header, coinbase){
|
||||
return Buffer.concat([
|
||||
header,
|
||||
util.varIntBuffer(this.rpcData.transaction.length + 1),
|
||||
coinbase,
|
||||
this.transactionData
|
||||
]);
|
||||
};
|
||||
|
||||
this.registerSubmit = function(extraNonce1Buffer, extraNonce2, nTime, nonce){
|
||||
var submission = extraNonce1Buffer.toString('hex') + extraNonce2 + nTime + nonce;
|
||||
if (submits.indexOf(submission) === -1){
|
||||
submits.push(submission);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.getJobParams = function(){
|
||||
if (!this.jobParams){
|
||||
this.jobParams = [
|
||||
this.jobId,
|
||||
util.reverseHex(this.rpcData.previousblockhash),
|
||||
this.previousHashBuffer,
|
||||
this.generationTransaction.coinbase[0].toString('hex'),
|
||||
this.generationTransaction.coinbase[1].toString('hex'),
|
||||
this.merkleBranch,
|
||||
|
||||
@ -67,10 +67,67 @@ var JobManager = module.exports = function JobManager(options){
|
||||
jobs[this.currentJob.jobId] = this.currentJob;
|
||||
CheckNewIfNewBlock(this.currentJob);
|
||||
};
|
||||
this.processShare = function(jobId, difficulty, extraNonce1, extraNonce2, nTime, nonce){
|
||||
this.processShare = function(jobId, difficulty, extraNonce1Buffer, extraNonce2, nTime, nonce){
|
||||
|
||||
var submitTime = Date.now() / 1000 | 0;
|
||||
|
||||
if (extraNonce2.length / 2 !== _this.extraNonce2Size)
|
||||
return {error: [20, 'incorrect size of extranonce2', null]};
|
||||
|
||||
|
||||
var job = jobs[jobId];
|
||||
if (!job)
|
||||
return {error: [21, 'job not found', null]};
|
||||
|
||||
|
||||
if (nTime.length !== 8)
|
||||
return {error: [20, 'incorrect size of ntime']};
|
||||
|
||||
|
||||
var nTimeInt = parseInt(nTime, 16);
|
||||
if (nTimeInt < job.rpcData.curtime || nTime > submitTime + 7200)
|
||||
return {error: [20, 'ntime out of range', null]};
|
||||
|
||||
|
||||
if (nonce.length !== 8)
|
||||
return {error: [20, 'incorrect size of nonce']};
|
||||
|
||||
|
||||
if (!job.registerSubmit(extraNonce1Buffer, extraNonce2, nTime, nonce))
|
||||
return {error: [22, 'duplicate share', null]};
|
||||
|
||||
|
||||
var extraNonce2Buffer = new Buffer(extraNonce2, 'hex');
|
||||
var nTimeBuffer = new Buffer(nTime, 'hex');
|
||||
var nonceBuffer = new Buffer(nonce, 'hex');
|
||||
|
||||
|
||||
var coinbaseBuffer = job.serializeCoinbase(extraNonce1Buffer, extraNonce2Buffer);
|
||||
var coinbaseHash = util.doublesha(coinbaseBuffer);
|
||||
|
||||
|
||||
var merkleRootBuffer = job.merkleTree.withFirst(coinbaseHash);
|
||||
for (var i = 0; i < 8; i++)
|
||||
merkleRootBuffer.writeUInt32LE(merkleRootBuffer.readUInt32BE(i * 4), i * 4);
|
||||
|
||||
|
||||
var headerBuffer = job.serializeHeader(merkleRootBuffer, nTimeBuffer, nonceBuffer);
|
||||
for (var i = 0; i < 20; i++) headerBuffer.writeUInt32LE(headerBuffer.readUInt32BE(i * 4), i * 4);
|
||||
var headerHash = util.doublesha(headerBuffer);
|
||||
var headerBigNum = bignum.fromBuffer(headerHash);
|
||||
|
||||
|
||||
var targetUser = bignum.fromBuffer(
|
||||
new Buffer('00000000ffff0000000000000000000000000000000000000000000000000000', 'hex')
|
||||
).div(difficulty);
|
||||
if (headerBigNum.gt(targetUser))
|
||||
return {error: [23, 'low difficulty share', null]};
|
||||
|
||||
|
||||
if (headerBigNum.gt(job.target)){
|
||||
_this.emit('blockFound', job.serializeBlock(headerBuffer, coinbaseBuffer));
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
9
main.js
9
main.js
@ -1,7 +1,16 @@
|
||||
var net = require('net');
|
||||
|
||||
var bignum = require('bignum');
|
||||
|
||||
var pool = require('./pool.js');
|
||||
|
||||
var fff = "03be78733329d27a63d6ca058a1e3e1048d90e945c2ee985f4bc9042da280a4b";
|
||||
var ff = new Buffer(fff, 'hex');
|
||||
var nn = bignum.fromBuffer(ff);
|
||||
var aa = nn.toBuffer();
|
||||
console.log(aa.toString('hex'));
|
||||
|
||||
|
||||
function Coin(options){
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
3
pool.js
3
pool.js
@ -60,7 +60,7 @@ var pool = module.exports = function pool(coin){
|
||||
}, function(err, results){
|
||||
if (err) return;
|
||||
|
||||
//console.log(results);
|
||||
|
||||
|
||||
publicKeyBuffer = coin.options.reward === 'POW' ?
|
||||
util.script_to_address(results.addressInfo.address) :
|
||||
@ -68,6 +68,7 @@ var pool = module.exports = function pool(coin){
|
||||
|
||||
_this.jobManager.newTemplate(results.rpcTemplate, publicKeyBuffer);
|
||||
|
||||
console.log(results.rpcTemplate);
|
||||
console.log(_this.jobManager.currentJob.getJobParams());
|
||||
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user