diff --git a/blockNotify.js b/blockNotify.js deleted file mode 100644 index deea49e..0000000 --- a/blockNotify.js +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env node - -var net = require('net'); - -var config = process.argv[1]; -var parts = config.split(':'); -var host = parts[0]; -var port = parts[1]; -var password = process.argv[2]; -var coin = process.argv[3]; -var blockHash = process.argv[4]; - -var client = net.connect(port, host, function() { - console.log('client connected'); - client.write(JSON.stringify({ - password: password, - coin: coin, - blockHash: blockHash - }) + '\n'); -}); - -client.on('data', function(data) { - console.log(data.toString()); - //client.end(); -}); - -client.on('end', function() { - console.log('client disconnected'); - //process.exit(); -}); \ No newline at end of file diff --git a/coins/dogecoin.json b/example/coins/dogecoin.json similarity index 100% rename from coins/dogecoin.json rename to example/coins/dogecoin.json diff --git a/config.json b/example/config.json similarity index 100% rename from config.json rename to example/config.json diff --git a/init.js b/example/init.js similarity index 95% rename from init.js rename to example/init.js index 7a7f9b7..8f37aba 100644 --- a/init.js +++ b/example/init.js @@ -2,7 +2,7 @@ var net = require('net'); var fs = require('fs'); var path = require('path'); -var pool = require('./pool.js'); +var pool = require('../index.js'); var ShareManager = require('./shareManager.js').ShareManager; var logRef = console.log; diff --git a/shareManager.js b/example/shareManager.js similarity index 100% rename from shareManager.js rename to example/shareManager.js diff --git a/pool.js b/index.js similarity index 90% rename from pool.js rename to index.js index f9e0b9a..4708e0f 100644 --- a/pool.js +++ b/index.js @@ -1,14 +1,17 @@ -var net = require('net'); -var events = require('events'); -var fs = require('fs'); - -var async = require('async'); - -var daemon = require('./daemon.js'); -var stratum = require('./stratum.js'); -var jobManager = require('./jobManager.js'); -var util = require('./util.js'); +var net = require('net'); +var events = require('events'); +var fs = require('fs'); +var async = require('async'); +var daemon = require('./libs/daemon.js'); +var stratum = require('./libs/stratum.js'); +var jobManager = require('./libs/jobManager.js'); +var util = require('./libs/util.js'); +/** + * Main pool object. It emits the following events: + * - 'started'() - when the pool is effectively started. + * - 'share'(isValid, dataObj) - In case it's valid the dataObj variable will contain (TODO) and in case it's invalid (TODO) + */ var pool = module.exports = function pool(coin){ var _this = this; @@ -27,9 +30,6 @@ var pool = module.exports = function pool(coin){ } }).on('blockFound', function(blockHex, headerHex, third){ - console.log("BLOCK "+blockHex); - console.log("HEADER "+headerHex); - console.log("THIRD "+third); if (coin.options.hasSubmitMethod) { _this.daemon.cmd('submitblock', [blockHex], diff --git a/blockTemplate.js b/libs/blockTemplate.js similarity index 90% rename from blockTemplate.js rename to libs/blockTemplate.js index 8a4ffe1..396b1d2 100644 --- a/blockTemplate.js +++ b/libs/blockTemplate.js @@ -1,11 +1,13 @@ - -var binpack = require('binpack'); - -var merkleTree = require('./merkleTree.js'); +var binpack = require('binpack'); +var merkleTree = require('./merkleTree.js'); var transactions = require('./transactions.js'); -var util = require('./util.js'); +var util = require('./util.js'); +/** + * The BlockTemplate class holds a single job. + * and provides serveral methods to validate and submit it to the daemon coin +**/ var BlockTemplate = module.exports = function BlockTemplate(rpcData, publicKey, extraNoncePlaceholder){ //private members diff --git a/daemon.js b/libs/daemon.js similarity index 74% rename from daemon.js rename to libs/daemon.js index 1453da8..9f17e55 100644 --- a/daemon.js +++ b/libs/daemon.js @@ -1,10 +1,16 @@ -var http = require('http'); -var cp = require('child_process'); -var events = require('events'); - - +var http = require('http'); +var cp = require('child_process'); +var events = require('events'); var startFailedTimeout = 120; //seconds +/** + * The daemon interface interacts with the coin daemon by using the rpc interface. + * in otder to make it work it needs, as constructor, an object containing + * - 'host' : hostname where the coin lives + * - 'port' : port where the coin accepts rpc connections + * - 'user' : username of the coin for the rpc interface + * - 'password': password for the rpc interface of the coin +**/ function DaemonInterface(options){ @@ -61,11 +67,11 @@ function DaemonInterface(options){ } var options = { - hostname: 'localhost', - port: _this.options.port, - method: 'POST', - auth: _this.options.user + ':' + _this.options.password, - headers: { + hostname: (typeof(_this.options.host) === 'undefined'?'localhost':_this.options.host), + port : _this.options.port, + method : 'POST', + auth : _this.options.user + ':' + _this.options.password, + headers : { 'Content-Length': requestJson.length } }; diff --git a/jobManager.js b/libs/jobManager.js similarity index 91% rename from jobManager.js rename to libs/jobManager.js index 697c2c5..7cce92c 100644 --- a/jobManager.js +++ b/libs/jobManager.js @@ -44,7 +44,11 @@ var JobCounter = function(){ }; }; - +/** + * Emits: + * - 'newBlock'(blockTemplate) - when a new block (previously unknown to the JobManager) is being added + * - 'blockFound'(serializedBlock) - when a worker finds a block. +**/ var JobManager = module.exports = function JobManager(options){ //private members @@ -165,7 +169,7 @@ var JobManager = module.exports = function JobManager(options){ if (job.target.ge(headerBigNum)){ var blockBuf = job.serializeBlock(headerBuffer, coinbaseBuffer); - _this.emit('blockFound', blockBuf.toString('hex'), headerBigNum.toString(16), coinbaseHash.toString('hex')); + _this.emit('blockFound', blockBuf.toString('hex')); } return {result: true, headerHEX: headerBigNum.toString(16)}; diff --git a/merkleTree.js b/libs/merkleTree.js similarity index 100% rename from merkleTree.js rename to libs/merkleTree.js diff --git a/stratum.js b/libs/stratum.js similarity index 84% rename from stratum.js rename to libs/stratum.js index 2486600..076a4da 100644 --- a/stratum.js +++ b/libs/stratum.js @@ -18,6 +18,14 @@ var SubscriptionCounter = function(){ }; }; + +/** + * Defining each client that connects to the stratum server. + * Emits: + * - 'subscription'(obj, cback(error, extraNonce1, extraNonce2Size)) + * - 'authorize'() FIX THIS + * - 'submit' FIX THIS. +**/ var StratumClient = function(options){ //private members @@ -79,16 +87,11 @@ var StratumClient = function(options){ }, function(error, result){ _this.authorized = result; - /*if (_this.authorized) { - // if authorized lets store the workername - // so that when a share is found we can get it for the accounting - _this.workerName = message.params[0][0]; - }*/ sendJson({ - id: message.id, + id : message.id, result: result, - error: error + error : error }); } ); @@ -97,34 +100,34 @@ var StratumClient = function(options){ function handleSubmit(message){ if (!_this.authorized){ sendJson({ - id: message.id, + id : message.id, result: null, - error: [24, "unauthorized worker", null] + error : [24, "unauthorized worker", null] }); return; } if (!_this.extraNonce1){ sendJson({ - id: message.id, + id : message.id, result: null, - error: [25, "not subscribed", null] + error : [25, "not subscribed", null] }); return; } console.log("SUBMIT "+JSON.stringify(message)); _this.emit('submit', { - name: message.params[0], - jobId: message.params[1], + name : message.params[0], + jobId : message.params[1], extraNonce2: message.params[2], - nTime: message.params[3], - nonce: message.params[4] + nTime : message.params[3], + nonce : message.params[4] }, function(error, result){ sendJson({ - id: message.id, + id : message.id, result: result, - error: error + error : error }); } ); @@ -179,14 +182,14 @@ var StratumClient = function(options){ this.sendDifficulty = function(difficulty){ _this.difficulty = difficulty; sendJson({ - id: null, + id : null, method: "mining.set_difficulty", params: [difficulty]//[512], }); }; this.sendMiningJob = function(jobParams){ sendJson({ - id: null, + id : null, method: "mining.notify", params: jobParams }); diff --git a/transactions.js b/libs/transactions.js similarity index 100% rename from transactions.js rename to libs/transactions.js diff --git a/util.js b/libs/util.js similarity index 100% rename from util.js rename to libs/util.js diff --git a/scripts/blockNotify.js b/scripts/blockNotify.js new file mode 100644 index 0000000..37e7909 --- /dev/null +++ b/scripts/blockNotify.js @@ -0,0 +1,38 @@ +#!/usr/bin/env node +/** + * This script should be hooked to the coin daemon as follow: + * + * litecoind -blocknotify="/path/to/this/script/blockNotify.js localhost:8117 password litecoin %s" + * + * The above will send tell litecoin to launch this script with those parameters every time + * a block is found. + * This script will then send the blockhash along with other informations to a listening tcp socket +**/ + +var net = require('net'); +var config = process.argv[1]; +var parts = config.split(':'); +var host = parts[0]; +var port = parts[1]; +var password = process.argv[2]; +var coin = process.argv[3]; +var blockHash = process.argv[4]; + +var client = net.connect(port, host, function() { + console.log('client connected'); + client.write(JSON.stringify({ + password: password, + coin: coin, + blockHash: blockHash + }) + '\n'); +}); + +client.on('data', function(data) { + console.log(data.toString()); + //client.end(); +}); + +client.on('end', function() { + console.log('client disconnected'); + //process.exit(); +}); \ No newline at end of file diff --git a/test.js b/test.js deleted file mode 100644 index 3dd736a..0000000 --- a/test.js +++ /dev/null @@ -1,121 +0,0 @@ -var bignum = require('bignum'); -var scrypt = require('scrypt256-hash'); - - -var reverseBuffer = function(buff){ - var reversed = new Buffer(buff.length); - for (var i = buff.length - 1; i >= 0; i--) - reversed[buff.length - i - 1] = buff[i]; - return reversed; -}; - -/* -var hash = new Buffer("38f3e68be0b74813af175b8da506dfa3c3017ff06fed7ae85e3efee655c9f7fd", 'hex'); -var goal = "8be6f3381348b7e08d5b17afa3df06a5f07f01c3e87aed6fe6fe3e5efdf7c955"; - -var s = scrypt.digest(hash); -console.log(s.toString('hex')); -for (var i = 0; i < 20; i++) s.writeUInt32LE(s.readUInt32BE(i * 4), i * 4); - - -var nHash = new Buffer(hash.length); -for (var i = 0; i < 8; i++) nHash.writeUInt32LE(hash.readUInt32BE(i * 4), i * 4); -console.log('maybe: ' + nHash.toString('hex')); - - -var wow = bignum.fromBuffer(hash, {endian: 'little', size: 32}).toBuffer({endian: 'big', size: 32}).toString('hex'); -console.log(wow); -console.log(wow == goal ? 'good' : 'fuck'); -*/ - - -/* -var bb = new Buffer('0100000017a93c491d6e309cc53604cc32829a9610a95835e042f7c86a0b4455b8f5fbfe38f3e68be0b74813af175b8da506dfa3c3017ff06fed7ae85e3efee655c9f7fdb931ce520334011c000028cf', 'hex'); -var hash = scrypt.digest(bb); -console.log(bignum.fromBuffer(hash, {endian: 'little', size: 32}).toString()); -*? - -/* -var block = { - hash: "409fd235e2fdc7182db92e13eed1b352081d9013ddc90e0acd817e378b8c1d1a", - confirmations: 1, - size: 1913, - height: 493856, - version: 1, - merkleroot: "71669b50622da76f4d6940912e997b537006324e8a32ed06e8072c68abcd358f", - tx: [ - "0d93c30ddc4b4802ec4724b238d730b7084ba19456ca5eeda8add1e4f86afab0", - "79f0461b1b2596381eff80cc1b4929eb908d6f6f010f082d7f4762b8d8e8c573", - "91b8d68ff49310174ceeefb2bb13765552676028108119ef2f8e5b29c8ed2487", - "c02a588d2296c13d1d6aec449af916a966880b6f359d841e3f09df554ade28ac", - "d043e490e4632fa48ac6fc3cbd6544e02116db39598aadb500fa7e3594bef9e3", - "f839b2688042cb5b6338f982a7c1179f0f533d1ca219aa12537acac0c1a3f863" - ], - time: 1389202213, - nonce: 1370998784, - bits: "1d011a75", - difficulty: 0.90631872, - previousblockhash: "be11244bda34c4c08c23fa7c61a5445f6daab25049a2c75b91309b58a68d9083" -}; - -var phpResult = "0100000083908da6589b30915bc7a24950b2aa6d5f44a5617cfa238cc0c434da4b2411be8f35cdab682c07e806ed328a4e320670537b992e9140694d6fa72d62509b6671258bcd52751a011d00c8b751"; - - - -var header = new Buffer(80); -var position = 0; -header.writeUInt32BE(block.nonce, position); -header.write(block.bits, position += 4, 4, 'hex'); -header.writeUInt32BE(block.time, position += 4); -header.write(block.merkleroot, position += 4, 32, 'hex'); -header.write(block.previousblockhash, position += 32, 32, 'hex'); -header.writeUInt32BE(block.version, position += 32); -var header = reverseBuffer(header); - - - -if (phpResult === header.toString('hex')) - console.log('works!!!!!'); -else - console.log('fuck'); - */ - -nonce = "cf280000"; -bits = "1c013403"; -time = "52ce31b9"; -merkleroot = "38f3e68be0b74813af175b8da506dfa3c3017ff06fed7ae85e3efee655c9f7fd"; -pbh = "fefbf5b855440b6ac8f742e03558a910969a8232cc0436c59c306e1d493ca917"; -version = 1; - -merkleroot = reverseBuffer(new Buffer(merkleroot, 'hex')).toString('hex'); - -var serializeHeader = function(){ - var header = new Buffer(80); - var position = 0; - header.write(nonce, position, 4, 'hex'); - header.write(bits, position += 4, 4, 'hex'); - header.write(time, position += 4, 4, 'hex'); - header.write(merkleroot, position += 4, 32, 'hex'); - header.write(pbh, position += 32, 32, 'hex'); - header.writeUInt32BE(version, position + 32); - var header = reverseBuffer(header); - return header; -}; - -var headerBuff = serializeHeader(); -var headerHashed = scrypt.digest(headerBuff); -var hashInt = bignum.fromBuffer(headerHashed, {endian: 'little', size: 32}); - - -//var diffDividend = bignum.fromBuffer(new Buffer('0000ffff00000000000000000000000000000000000000000000000000000000'), 'hex'); -//var target = diffDividend.div(16) - -var dividend = 0x0000ffff00000000000000000000000000000000000000000000000000000000; -var target = dividend / 16; - -var big = bignum(target); - -console.log('dividend ' + big.toString()); - -console.log('hash ' + hashInt.toString()) -console.log('target ' + target.toString()); \ No newline at end of file