Skip to content

Instantly share code, notes, and snippets.

@brandon-lockaby
Created May 12, 2013 08:41
Show Gist options
  • Save brandon-lockaby/5562870 to your computer and use it in GitHub Desktop.
Save brandon-lockaby/5562870 to your computer and use it in GitHub Desktop.
educational node bitcoin getwork pool cpu mining
// educational node bitcoin getwork pool cpu mining
var request = require('request');
var crypto = require('crypto');
var json_rpc_id = 1;
function sha256(buf) {
var sha = crypto.createHash('sha256');
sha.update(buf);
return sha.digest();
}
function reverse_hex(str) {
var out = "";
for(var i = 0; i < str.length; i += 2) {
out = str.substr(i, 2) + out;
}
return out;
}
function swap32(buf) {
if(buf.length % 4) throw "what";
for(var i = 0; i < buf.length; i += 4) {
buf.writeUInt32BE(buf.readUInt32LE(i), i);
}
return buf;
}
var BlockHeader = function() {};
BlockHeader.deserialize = function(buf) {
var blockheader = new BlockHeader();
blockheader.ver = buf.readUInt32LE(0);
blockheader.prev_block = reverse_hex(buf.slice(4, 4+32).toString('hex'));
blockheader.mrkl_root = reverse_hex(buf.slice(36, 36+32).toString('hex'));
blockheader.time = buf.readUInt32LE(68);
blockheader.bits = buf.readUInt32LE(72);
blockheader.nonce = buf.readUInt32LE(76);
return blockheader;
}
BlockHeader.prototype.serialize = function() {
var buf = new Buffer(80);
buf.writeUInt32LE(this.ver, 0);
buf.write(reverse_hex(this.prev_block), 4, 32, 'hex');
buf.write(reverse_hex(this.mrkl_root), 36, 32, 'hex');
buf.writeUInt32LE(this.time, 68);
buf.writeUInt32LE(this.bits, 72);
buf.writeUInt32LE(this.nonce, 76);
return buf;
};
BlockHeader.prototype.hash = function() {
return reverse_hex(sha256(sha256(this.serialize())).toString('hex'));
};
var Work = function() {};
Work.get = function(url, cb) {
var work = new Work();
work.url = url;
request({
url: url,
method: 'POST',
body: JSON.stringify({
"method": "getwork",
"params": [],
"id": (json_rpc_id++)
})
}, function(e, r, body) {
console.log("RESPONSE1:", body);
var result = JSON.parse(body);
work.data = result.result.data;
work.target = result.result.target;
work.current_nonce = work.getBlockHeader().nonce; // usually 0
setImmediate(cb.bind(this, work));
});
};
Work.prototype.getBlockHeader = function() {
var buf = new Buffer(this.data, 'hex');
buf = swap32(buf);
return BlockHeader.deserialize(buf);
};
Work.prototype.submit = function(blockheader) {
var url = this.url;
var data = swap32(blockheader.serialize()).toString('hex');
data += this.data.substr(160);
var body = JSON.stringify({
"method": "getwork",
"params": [data],
"id": (json_rpc_id++)
});
console.log("SUBMIT:", body);
request({
url: url,
method: 'POST',
body: body
}, function(e, r, body) {
console.log("RESPONSE2:", body);
});
};
Work.prototype.do = function(hashes, cb) {
var blockheader = this.getBlockHeader();
for(var i = 0; i < hashes; i++) {
blockheader.nonce = ++this.current_nonce;
var hash = blockheader.hash();
if(hash.indexOf("00000000") == 0) {
// todo: real target comparison
this.submit(blockheader);
}
}
};
var url = 'http://user.worker:password@api.bitcoin.cz:8332';
var get_new_work = false;
var do_work = function(work) {
work.do(10000);
setImmediate(function() {
if(get_new_work) {
get_new_work = false;
Work.get(url, do_work);
} else {
do_work(work);
}
});
};
Work.get(url, do_work);
setInterval(function() {
get_new_work = true;
}, 1000 * 60 * 5); // 5 minutes...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment