forked from z-classic/node-stratum-pool
-
Notifications
You must be signed in to change notification settings - Fork 29
/
blockTemplate.js
144 lines (121 loc) · 5.26 KB
/
blockTemplate.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
var bignum = require('bignum');
var merkle = require('./merkleTree.js');
var transactions = require('./transactions.js');
var util = require('./util.js');
/**
* The BlockTemplate class holds a single job.
* and provides several methods to validate and submit it to the daemon coin
**/
var BlockTemplate = module.exports = function BlockTemplate(jobId, rpcData, extraNoncePlaceholder, reward, recipients, poolAddress){
//private members
var submits = [];
//public members
this.rpcData = rpcData;
this.jobId = jobId;
// get target info
this.target = bignum(rpcData.target, 16);
this.difficulty = parseFloat((diff1 / this.target.toNumber()).toFixed(9));
// generate the fees and coinbase tx
var blockReward = this.rpcData.coinbasevalue;
var fees = [];
rpcData.transactions.forEach(function(value) {
fees.push(value);
});
this.rewardFees = transactions.getFees(fees);
rpcData.rewardFees = this.rewardFees;
if (typeof this.genTx === 'undefined') {
this.genTx = transactions.createGeneration(rpcData.height, blockReward, this.rewardFees, recipients, poolAddress).toString('hex');
this.genTxHash = transactions.txHash();
/*
console.log('this.genTxHash: ' + transactions.txHash());
console.log('this.merkleRoot: ' + merkle.getRoot(rpcData, this.genTxHash));
*/
}
// generate the merkle root
this.prevHashReversed = util.reverseBuffer(new Buffer(rpcData.previousblockhash, 'hex')).toString('hex');
this.merkleRoot = merkle.getRoot(rpcData, this.genTxHash);
this.txCount = this.rpcData.transactions.length + 1; // add total txs and new coinbase
this.merkleRootReversed = util.reverseBuffer(new Buffer(this.merkleRoot, 'hex')).toString('hex');
// we can't do anything else until we have a submission
//block header per https://github.com/zcash/zips/blob/master/protocol/protocol.pdf
this.serializeHeader = function(nTime, nonce){
var header = new Buffer(140);
var position = 0;
/*
console.log('nonce:' + nonce);
console.log('this.rpcData.bits: ' + this.rpcData.bits);
console.log('nTime: ' + nTime);
console.log('this.merkleRootReversed: ' + this.merkleRoot);
console.log('this.prevHashReversed: ' + this.prevHashReversed);
console.log('this.rpcData.version: ' + this.rpcData.version);
*/
header.writeUInt32LE(this.rpcData.version, position += 0, 4, 'hex');
header.write(this.prevHashReversed, position += 4, 32, 'hex');
header.write(this.merkleRootReversed, position += 32, 32, 'hex');
header.write(util.packUInt32LE(this.rpcData.height).toString('hex'), position += 32, 4, 'hex'); //hashReserved
header.write('00000000000000000000000000000000000000000000000000000000', position += 4, 28, 'hex');
header.write(nTime, position += 28, 4, 'hex');
header.write(util.reverseBuffer(new Buffer(rpcData.bits, 'hex')).toString('hex'), position += 4, 4, 'hex');
header.write(nonce, position += 4, 32, 'hex');
return header;
};
// join the header and txs together
this.serializeBlock = function(header, soln){
var txCount = this.txCount.toString(16);
if (Math.abs(txCount.length % 2) == 1) {
txCount = "0" + txCount;
}
if (this.txCount <= 0x7f){
var varInt = new Buffer(txCount, 'hex');
}
else if (this.txCount <= 0x7fff){
var varInt = new Buffer.concat([Buffer('FD', 'hex'), new Buffer(txCount, 'hex')]);
}
buf = new Buffer.concat([
header,
soln,
varInt,
new Buffer(this.genTx, 'hex')
]);
if (this.rpcData.transactions.length > 0) {
this.rpcData.transactions.forEach(function (value) {
tmpBuf = new Buffer.concat([buf, new Buffer(value.data, 'hex')]);
buf = tmpBuf;
});
}
/*
console.log('header: ' + header.toString('hex'));
console.log('soln: ' + soln.toString('hex'));
console.log('varInt: ' + varInt.toString('hex'));
console.log('this.genTx: ' + this.genTx);
console.log('data: ' + value.data);
console.log('buf_block: ' + buf.toString('hex'));
*/
return buf;
};
// submit the block header
this.registerSubmit = function(header, soln){
var submission = header + soln;
if (submits.indexOf(submission) === -1){
submits.push(submission);
return true;
}
return false;
};
// used for mining.notify
this.getJobParams = function(){
if (!this.jobParams){
this.jobParams = [
this.jobId,
util.packUInt32LE(this.rpcData.version).toString('hex'),
this.prevHashReversed,
this.merkleRootReversed,
util.packUInt32LE(this.rpcData.height).toString('hex') + '00000000000000000000000000000000000000000000000000000000', //hashReserved
util.packUInt32LE(rpcData.curtime).toString('hex'),
util.reverseBuffer(new Buffer(this.rpcData.bits, 'hex')).toString('hex'),
true
];
}
return this.jobParams;
};
};