node-stratum-pool/README.md

7.9 KiB

node-stratum

Under development

High performance Stratum poolserver in Node.js. One instance of this software can startup and manage multiple coin pools, each with their own daemon and stratum port :)

This project does not handle share rewards (payment processing). An MPOS compatibility layer is in the works here. Otherwise, to setup a pool site, you will have to use this code as module for another project that handles share rewards. A portal (alternative to MPOS) that uses this module is under development here.

Build Status

NPM

Why

This server was built to be more efficient and easier to setup, maintain and scale than existing stratum poolservers which are written in python. Compared to the spaghetti state of the latest stratum-mining python server, this software should also have a lower barrier to entry for other developers to fork and add features or fix bugs.

Features

  • Daemon RPC interface
  • Stratum TCP socket server
  • Block template / job manager
  • Optimized generation transaction building
  • Connecting to multiple daemons for redundancy
  • Process share submissions
  • POW (proof-of-work) & POS (proof-of-stake) support
  • Transaction messages support
  • Vardiff (variable difficulty / share limiter)
  • Supports the hashing algorithms:
    • SHA256 (Bitcoin, Freicoin, Peercoin/PPCoin, Terracoin, etc..)
    • Scrypt (Litecoin, Dogecoin, Feathercoin, etc..)
    • Scrypt-Jane (YaCoin, CopperBars, Pennies, Tickets, etc..)
    • Quark (Quarkcoin [QRK])
    • X11 (Darkcoin [DRK])

Under development

  • Skein (Skeincoin) algorithm
  • Keccak (Maxcoin) algorithm
  • P2P functionality for highly efficient block updates from daemon as a peer node

To do

  • Statistics module
  • Auto-banning flooders

Requirements

  • node v0.10+
  • coin daemon (preferably one with a relatively updated API and not some crapcoin :p)

Example Usage

Install as a node module by cloning repository

git clone https://github.com/zone117x/node-stratum node_modules/stratum-pool
npm update

Module usage

Create and start new pool with configuration options and authentication function


var Stratum = require('stratum-pool');

var pool = Stratum.createPool({

    coin: {
        name: "Dogecoin",
        symbol: "doge",
        algorithm: "scrypt", //or "sha256", "scrypt-jane", "quark", "x11"
        reward: "POW", //or "POS"
        txMessages: false //or true
    },

    pool: {
        address: "nhfNedMmQ1Rjb62znwaiJgFhL3f4NQztSp",
        stratumPort: 3334,
        //instanceId: 37, //I recommend not to use this option as a crypto-random one will be generated
        difficulty: 32,
        blockRefreshInterval: 2000 //milliseconds
    },

    /* Recommended to have at least two daemon instances running in case one drops out-of-sync
       or offline. For redundancy, all instances will be polled for block/transaction updates
       and be used for submitting blocks */
    daemons: [
        {   //main daemon instance
            host: "localhost",
            port: 19334,
            user: "testnet",
            password: "testnet"
        },
        {   //backup daemon instance
            host: "localhost",
            port: 19335,
            user: "testnet",
            password: "testnet"
        }
    ],

    varDiff: {
        enabled: true, //set to false to disable vardiff functionality
        minDifficulty: 16, //minimum difficulty. below 16 will cause problems
        maxDifficulty: 1000, //network difficulty will be used if it is lower than this
        targetTime: 30, //target time per share (i.e. try to get 1 share per this many seconds)
        retargetTime: 120, //check to see if we should retarget every this many seconds
        variancePercent: 20 //allow average time to very this % from target without retarget

        /* By default new difficulties will be sent when a new job is available as stratum
           protocol (http://mining.bitcoin.cz/stratum-mining) states that new difficulties
           "will be applied to every next job received from the server." Some miner software
           will almost immediately apply new difficulties. Set mode to fast for difficulty
           to be sent immediately. */
        //mode: 'fast'
    },

    p2p: {
        enabled: false,
        host: "localhost",
        port: 19333,

        /* Magic value is different for main/testnet and for each coin. It is found in the daemon
          source code as the pchMessageStart variable. For example, litecoin mainnet:
            http://github.com/litecoin-project/litecoin/blob/85f303d883ffff35238eaea5174b780c950c0ae4/src/main.cpp#L3059
          And for litecoin testnet:
            http://github.com/litecoin-project/litecoin/blob/85f303d883ffff35238eaea5174b780c950c0ae4/src/main.cpp#L2722-L2725
         */
        magic: "fcc1b7dc",

        /* Found in src as the PROTOCOL_VERSION variable, for example:
             https://github.com/litecoin-project/litecoin/blob/85f303d883ffff35238eaea5174b780c950c0ae4/src/version.h#L28
         */
        protocolVersion: 70002
    }

}, function(ip, workerName, password, callback){ //stratum authorization function
    console.log("Authorize " + workerName + ":" + password + "@" + ip);
    callback({
        error: null,
        authorized: true,
        disconnect: false
    });
});

Listen to pool events

/*
'data' object contains:
    job: 4, //stratum work job ID
    ip: '71.33.19.37', //ip address of client
    worker: 'matt.worker1', //stratum worker name
    difficulty: 64, //stratum client difficulty
    height: 443795, //block height
    networkDifficulty: 3349 //network difficulty for this block
    //solution is set if block was found
    solution: '110c0447171ad819dd181216d5d80f41e9218e25d833a2789cb8ba289a52eee4',
    error: 'low share difficulty' //set if share is rejected for some reason
*/
pool.on('share', function(isValidShare, isValidBlock, data){

    if (isValidBlock)
        console.log('Block found');
    else if (isValidShare)
        console.log('Valid share submitted');
    else if (data.solution)
        console.log('We thought a block solution was found but it was rejected by the daemon');
    else
        console.log('Invalid share submitted')

    console.log('share data: ' + JSON.stringify(data));
});



/*
'severity': can be 'debug', 'warning', 'error'
'logKey':   can be 'system' or 'client' indicating if the error
            was caused by our system or a stratum client
*/
pool.on('log', function(severity, logKey, logText){
    console.log(severity + ': ' + '[' + logKey + '] ' + logText);
});

Start pool

pool.start();

Credits

  • vekexasia - co-developer & great tester
  • TheSeven - answering an absurd amount of my questions, found the block 1-16 problem, provided example code for peer node functionality
  • pronooob - knowledgeable & helpful
  • Slush0 - stratum protocol, documentation and original python code
  • viperaus - scrypt adaptions to python code
  • ahmedbodi - more algo adaptions to python code
  • steveshit - ported X11 hashing algo from python to node module

Donations

BTC: 1KRotMnQpxu3sePQnsVLRy3EraRFYfJQFR

License

Released under the GNU General Public License v2

http://www.gnu.org/licenses/gpl-2.0.html