Lex Pool (A rewritten pool based on uray source)



  • hi all,

    recommended mandatory update has been pushed.

    this update limits the use of post requests over port 80. before this update any post requests made to a uray pool for any api call was forwarded straight to the wallet. and the result relayed back to whoever was sending the request.

    this plugs that huge hole. its never a good idea to fully open up an API like this. i beleive the code was originally written by uray. and cant believe i missed it up untill now. but lates better than never i suppose

    0_1484819187795_upload-a9d7d129-343a-44a8-98b7-9fcb71586302



  • Hi @Lexicon, can I do this:

    module.exports = {
        wallets : [
            {
            /*Wallet Server 1*/
                walletIP : '10.0.0.10',
                walletPort : 8125,
                walletUrl : 'http://10.0.0.10:8125'
            },
            {
            /*Wallet Server 2*/
                walletIP : '10.0.0.11',
                walletPort : 8125,
                walletUrl : 'http://10.0.0.15:8125'
            },
            {
            /*Wallet Server 3*/
                walletIP : '10.0.0.12',
                walletPort : 8125,
                walletUrl : 'http://10.0.0.12:8125'
            },
            {
            /*Wallet Server 4*/
                walletIP : '10.0.0.15',
                walletPort : 8125,
                walletUrl : 'http://10.0.0.15:8125'
            }   
        ],
        redirection : {
            enabled : false,
            target : 'http://lhc.ddns.net:8124'
        },
        walletIndex: 0,
        blockMature : 1,
        txFeePercent : 0.0005,
        devFee : true,
        devFeePercent : 0.01,
        poolFee : 0.01,
        poolDiff : 1000000,
        poolDiffCurve : 0.75,
        poolPort : 8124,
        poolPvtKey : '<pool private key>',
         poolPublicRS : 'BURST-F3XD-Y4M5-SN8C-G9FFJ',
           poolPublic : '16732464642587527083',
           poolFeePaymentAddr : '17572168194578653714',
        defaultPaymentDeadline : 1440,
        poolFeePaymentTxFeeNQT : 100000000,
        httpPort : 80,
        websocketPort : 4443,
        enablePayment : true,
        minimumPayout : 250.0,
        clearingMinPayout : 2.0,
        lastSessionFile : 'last-session.json',
        cumulativeFundReduction : 0.5,
        logWebsocketToConsole : false,
        maxRoundCount : 97,
        sharePenalty : 0.001,
        maxRecentPaymentHistory : 50
    };
    
    /*
    SubmitNonce = {
          secretPhrase, (private-key) ---> secretAccount (public-key)   <----------+
      +-- nonce,                                                                   |
      |   accountId ---> getRewardRecipient() ---> rewardId (public-pool-address) -+
      |            |                                  ^
    } |            |                                  |
      V            V                                  |
    nonce + genAccount                                |
      |            |                                  |
      +____________+                                  |
             |                                        |
             V                                        |
         Deadline                                     |
             |    (if smallest)                       |
             V                                        |
         Forge() ------> getRewardRecipient() --------+
     */
    

    Add multiple wallet servers to reduce the load on one server.



  • yes its possible. also use the function in burst-pool-session

    function switchNextWallet(){
        if(config.wallets.length > 1){
            if(config.walletIndex+1 < config.wallets.length){
                sessionState.walletIndex = sessionState.walletIndex + 1;
                console.log('switch wallet to '+config.wallets[config.walletIndex].walletUrl+' ['+config.walletIndex+']');
            }
            else{
                sessionState.walletIndex = 0;
                console.log('switch wallet to '+config.wallets[config.walletIndex].walletUrl+' ['+config.walletIndex+']');
            }
        }
    }
    


  • @Lexicon I download the newest pool code and I get this:

    genesis block id = 3444294670862540038
    current timestamp 1486932898895
    genesis-block blocktime 79210499
    genesis-block timestamp 1407722399895
    genesis base target = 18325193796
    burst pool running on port 8124
    websocket running on port 4443
    http server running on port 8020
    new block #327471 BT:839318 ND:21833.433568683144
    new best deadline 16364423585
    TypeError: Object burstcoin-jminer-0.4.5-RELEASE has no method 'startsWith'
        at /var/www/burstcoin_ml/pool/burst-pool.js:199:32
        at process._tickCallback (node.js:415:13)
    clean
    
    


  • @Tate-A First make sure another instance isn't running



  • @Burstde Second make sure you have folder node_modules0_1486933947827_upload-60f51190-4c37-44b6-bf6f-a22c7951f799



  • @Burstde said in Lex Pool (A rewritten pool based on uray source):

    First make sure another instance isn't running

    No noting is running on this server.



  • it could be the versoin of node your running. try converting that line to a string at line 199

    req.minerData.xMiner.toString().startsWith(
    


  • @Burstde said in Lex Pool (A rewritten pool based on uray source):

    Second make sure you have folder node_modules

    node_modules >
    	async
    	body-parser
    	compression
    	express
    	fs
    	http
    	http-proxy
    	json-markup
    	lodash
    	moment
    	path
    	prettyjson
    	request
    	socket.io
    	url
    	.bin
    


  • @Lexicon I get the same error, nodejs v0.10.25



  • @Lexicon 199: if(req.minerData.xMiner.toString().startsWith('Blago'))



  • @Tate-A yeah change the rest of them to suit



  • @Lexicon

    Here from my miner:

    dl '1359691053' confirmed!  [ 15737d 3h 57m 33s ]
    2017-02-12 16:34:21.686  WARN 19156 --- [  networkPool-1] b.j.c.n.task.NetworkSubmitPoolNonceTask  : Error: Failed to submit nonce to pool: java.io.EOFException: HttpConnectionOverHTTP@28674d86(l:/10.0.0.10:51644 <-> r:/10.0.0.10:8124,closed=false)[HttpChannelOverHTTP@3d9e7d37(exchange=HttpExchange@2284caa8 req=TERMINATED/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@7691b8b7(req=QUEUED,snd=COMPLETED,failure=null)[HttpGenerator@6488d09e{s=START}],recv=HttpReceiverOverHTTP@2a317efd(rsp=IDLE,failure=null)[HttpParser{s=CLOSED,0 of 0}]]]
    2017-02-12 16:34:21.689  WARN 19156 --- [  networkPool-1] b.j.c.n.task.NetworkSubmitPoolNonceTask  : Error: Failed to submit nonce to pool: java.net.ConnectException: Connection refused
    
    

    burst-pool.js

    #!/usr/bin/env node
    var fs              = require('fs');
    var url             = require('url');
    var moment          = require('moment');
    var config          = require('./burst-pool-config');
    var poolSession     = require('./burst-pool-session');
    var poolShare       = require('./burst-pool-share');
    var poolPayment     = require('./burst-pool-payment');
    var poolProtocol    = require('./burst-pool-protocol');
    var async       = require('async');
    
    function onNewBlock(miningInfo){
        poolProtocol.clientLog("new block :");
        poolProtocol.clientLogJson(miningInfo);
    
        try{
            poolSession.updateByNewBlock(miningInfo.height,miningInfo.baseTarget, function(){
                poolShare.deleteRoundShareByDistance(config.maxRoundCount);
                poolShare.deleteAccountShareBelowThresshold(1.0,config.maxRoundCount);
                poolShare.saveSession();
                poolShare.updateByNewBlock(miningInfo.height, miningInfo.baseTarget);
                poolPayment.updateByNewBlock(miningInfo.height);
                poolPayment.saveSession();
                poolSession.saveSession();
                logMiningRound();
    
                console.log('new block #'+miningInfo.height+' BT:'+miningInfo.baseTarget+' ND:'+poolSession.getNetDiff());
                poolProtocol.getWebsocket().emit('shareList',JSON.stringify(poolShare.getCumulativeShares()));
                poolProtocol.getWebsocket().emit('blockHistory',JSON.stringify(poolSession.getState().prevBlocks));
            });
        }
        catch(e){
            console.log(e);
            console.trace();
        }
    }
    function getDateTime() {
        var date = new Date();
        var hour = date.getHours();
        hour = (hour < 10 ? "0" : "") + hour;
        var min  = date.getMinutes();
        min = (min < 10 ? "0" : "") + min;
        var sec  = date.getSeconds();
        sec = (sec < 10 ? "0" : "") + sec;
        var year = date.getFullYear();
        var month = date.getMonth() + 1;
        month = (month < 10 ? "0" : "") + month;
        var day  = date.getDate();
        day = (day < 10 ? "0" : "") + day;
        return hour + ":" + min + ":" + sec;
    }
    function logMiningRound(socket){
        var blockHeight = poolSession.getCurrentBlockHeight();
        var roundStart = poolSession.getCurrentRoundStartTime();
        var currentTime = new Date().getTime();
        var elapsed = currentTime - roundStart;
        var duration = moment.duration(elapsed).humanize(true);
        var roundShare = poolShare.getCurrentRoundShares();
        var submitters = roundShare.submitters;
        var netDiff = poolSession.getNetDiff();
        var sessionState = poolSession.getState();
        var miningInfo = {
            height      : blockHeight,
            currentTime : currentTime,
            totalShare  : roundShare.totalShare,
            submitters  : roundShare.submitters,
            roundStart  : roundStart,
            netDiff     : netDiff,
            bestDeadline: sessionState.current.bestDeadline
        };
        sessionState.current.submitters = roundShare.submitters;
        sessionState.current.totalShare = roundShare.totalShare;
    
        if(typeof socket === 'undefined'){
            poolProtocol.getWebsocket().emit('miningInfo',JSON.stringify(miningInfo));
            poolProtocol.clientLog("round #" + blockHeight + " diff "+netDiff.toFixed(1)+", elapsed " + duration + ", " + submitters + " Miners, total shares " + roundShare.totalShare.toFixed(2)+', best deadline '+roundShare.bestDeadline+' from '+roundShare.bestDeadlineAccount);
        }
        else{
            socket.emit('miningInfo',JSON.stringify(miningInfo));
            poolProtocol.clientUnicastLog(socket,"round #" + blockHeight + " diff "+netDiff.toFixed(1)+", elapsed " + duration + ", " + submitters + " Miners, total shares " + roundShare.totalShare.toFixed(2)+', best deadline '+roundShare.bestDeadline+' from '+roundShare.bestDeadlineAccount);
        }
    }
    
    function onNonceSubmitReq(req){
    
        var minerReq = null;
        try {
            minerReq = url.parse(req.url ,true);
        }
        catch (e){
            minerReq = null;
        }
    
        if( minerReq != null &&
            minerReq.hasOwnProperty('query') &&
            minerReq.query.hasOwnProperty('requestType')){
            if(minerReq.query.requestType.toLowerCase() == 'submitnonce'){
                var remoteAddr = req.connection.remoteAddress+':'+req.connection.remotePort;
                var minerData = {
                    nonce : 0,
                    from : remoteAddr,
    				xMiner : ''
    
                };
                req.url = '/burst?requestType=submitNonce';
    
                if(minerReq.query.hasOwnProperty('nonce')){
                    req.url+= '&nonce='+minerReq.query.nonce;
                    minerData.nonce = parseInt(minerReq.query.nonce);
                }
    			        if(req.headers.hasOwnProperty('x-miner')){
                       minerData.xMiner = req.headers['x-miner'];
                          }
                if(minerReq.query.hasOwnProperty('accountId')){ //<------ POOL MINING
                    req.url+= '&accountId='+minerReq.query.accountId;
                    minerData.accountId = minerReq.query.accountId;
    
                    minerReq.query.secretPhrase = config.poolPvtKey;
                    req.url+= '&secretPhrase='+config.poolPvtKey;
                }
                else {
                    if(minerReq.query.hasOwnProperty('secretPhrase')){ //<----- SOLO MINING
                        var urlPhrase = minerReq.query.secretPhrase.replace(/%2B|%2b/g,'+');
                        req.url+= '&secretPhrase='+urlPhrase;
                    }
                }
    
                req.isSubmitNonce = true;
                req.headers['content-length'] = "0";
                req.minerData = minerData;
            }
            else if(minerReq.query.requestType.toLowerCase() == 'getmininginfo'){
                req.isMiningInfo = true;
            }
        }
    
    }
    
    function onNonceSubmitedRes(req,res){
        if(req.hasOwnProperty('minerData')) {
            if (res.hasOwnProperty('deadline') &&
                req.minerData.hasOwnProperty('accountId')) {
    
                var deadline = parseInt(res.deadline);
                var accountId = req.minerData.accountId;
                process.nextTick(function(){
                    req.minerData.deadline = deadline;
                    req.minerData.submission = res.result;
    
                    poolShare.updateByNewDeadline(accountId,deadline);
    
                    var accountShare = poolShare.getAccountShare(accountId);
                    if(accountShare != null){
                        poolProtocol.getWebsocket().emit('roundShares',JSON.stringify(accountShare));
                    }
    
                    var sessionState = poolSession.getState();
    
                    var currentTime = new Date().getTime();
                    var miningInfo = {
                        height      : sessionState.current.blockHeight,
                        currentTime : currentTime,
                        totalShare  : sessionState.current.totalShare,
                        submitters  : sessionState.current.submitters,
                        roundStart  : sessionState.current.startTime,
                        netDiff     : poolSession.getNetDiff(),
                        bestDeadline: sessionState.current.bestDeadline
                    };
    
                    if(sessionState.current.bestDeadline > deadline){
                        sessionState.current.bestDeadline = deadline;
                        console.log('new best deadline '+sessionState.current.bestDeadline);
                        poolProtocol.getWebsocket().emit('miningInfo',JSON.stringify(miningInfo));
    				  var minerPic ='<img src="Hopstarter-Button-Button-Help.ico" alt="'+req.minerData.xMiner+'" style="width:20px;height:20px;">';
    					if(req.minerData.xMiner.toString().startsWith('Blago'))
    					{
    				   minerPic = '<img src="Untitled-1.png" alt="'+req.minerData.xMiner+'" style="width:20px;height:20px;">'
    					} else if(req.minerData.xMiner.toString().startsWith('IBAndroid'))
    					 {
    					minerPic = '<img src="http://storage.googleapis.com/ix_choosemuse/uploads/2016/02/android-logo.png" alt="'+req.minerData.xMiner+' " style="width:20px;height:20px;">'
    					 }
    					 else if(req.minerData.xMiner.toString().startsWith('burstcoin-jminer'))
    					  {
    					 minerPic = '<img src="Jminer.png" alt="'+req.minerData.xMiner+' " style="width:20px;height:20px;">'
    					  }
    					  else if(req.minerData.xMiner.toString().startsWith('creepsky'))
    					  {
    					 minerPic = '<img src="cat_tied.png" alt="'+req.minerData.xMiner+' " style="width:20px;height:20px;">'
    					  }
                     //   poolProtocol.clientLog("new best deadline : #"+poolSession.getCurrentBlockHeight());
                           poolProtocol.clientLogFormatted('<span class="logLine time">'+getDateTime()+'</span>'+minerPic+'<span class="logLine"> Best deadline = </span><span class="logLine deadline">'+moment.duration(req.minerData.deadline*1000).humanize(false)+'</span><span class="logLine"> by Burst ID: </span><span class="logLine accountName"><a href="https://block.burstcoin.info/acc.php?acc='+req.minerData.accountId+'" target=_blank>'+req.minerData.accountId+'</a></span>');
               
                    }
                    if(sessionState.current.bestDeadline == -1){
                        sessionState.current.bestDeadline = deadline;
                        console.log('new best deadline '+sessionState.current.bestDeadline);
                        poolProtocol.getWebsocket().emit('miningInfo',JSON.stringify(miningInfo));
    					var minerPic ='<img src="Hopstarter-Button-Button-Help.ico" alt="'+req.minerData.xMiner+'" style="width:20px;height:20px;">';
    							if(req.minerData.xMiner.toString().startsWith('Blago'))
    							{
    						   minerPic = '<img src="Untitled-1.png" alt="'+req.minerData.xMiner+'" style="width:20px;height:20px;">'
    							} else if(req.minerData.xMiner.toString().startsWith('IBAndroid'))
    							 {
    							minerPic = '<img src="http://storage.googleapis.com/ix_choosemuse/uploads/2016/02/android-logo.png" alt="'+req.minerData.xMiner+' " style="width:20px;height:20px;">'
    							 }
    							 else if(req.minerData.xMiner.toString().startsWith('burstcoin-jminer'))
    							  {
    							 minerPic = '<img src="Jminer.png" alt="'+req.minerData.xMiner+' " style="width:20px;height:20px;">'
    							  }
                        //poolProtocol.clientLog("new best deadline : #"+poolSession.getCurrentBlockHeight());
                       poolProtocol.clientLogFormatted('<span class="logLine time">'+getDateTime()+'</span>'+minerPic+'<span class="logLine"> Best deadline = </span><span class="logLine deadline">'+moment.duration(req.minerData.deadline*1000).humanize(false)+'</span><span class="logLine"> by Burst ID: </span><span class="logLine accountName"><a href="https://block.burstcoin.info/acc.php?acc='+req.minerData.accountId+'" target=_blank>'+req.minerData.accountId+'</a></span>');
               
                    }
                });
            }
        }
    }
    
    
    function onMiningInfoUpdate(res){
    
        var miningInfo = res;
    
        if(poolSession.getCurrentBlockHeight() < miningInfo.height){
            onNewBlock(miningInfo);
        }
    }
    
    function onNewClientConnected(socket){
        var clientIp   = socket.request.connection.remoteAddress;
        var clientPort = socket.request.connection.remotePort;
    
        socket.on('chat', function(msg){
            onWebsocketClientChat(clientIp,msg);
        });
    
        socket.on('disconnect', function() {
            //console.log('viewer disconnected from '+clientIp+":"+clientPort);
        });
    
        //socket.emit('log','<div class=".json-text>">Welcome to BurstPool, may the hash be with you!</div>');
        //poolProtocol.clientLog('viewer connected from '+clientIp+":"+clientPort);
        //console.log('viewer connected from '+clientIp+":"+clientPort);
        var cumulativeShare = poolShare.getCumulativeShares();
        socket.emit('shareList',JSON.stringify(cumulativeShare));
        socket.emit('sentList',JSON.stringify(poolPayment.getPaidList()));
        socket.emit('blockHistory',JSON.stringify(poolSession.getState().prevBlocks));
        logMiningRound(socket);
    }
    
    function onWebsocketClientChat(clientIp, msg){
        var textMsg = msg;
        if(textMsg.length > 256){
            textMsg = textMsg.substring(0, 255);
        }
        poolProtocol.clientLog(clientIp+' : '+'<span class="chatMsg">'+textMsg+'</span>');
    }
    
    function saveSession(){
        poolShare.saveSession();
        poolPayment.saveSession();
        poolSession.saveSession();
        logMiningRound();
    }
    
    function initPool(walletNdx){
        poolSession.setWalletNdx(walletNdx);
        poolSession.init(function(){
            async.parallel(
                [
                    function(callback){
                        poolPayment.loadSession(function(){
                            callback();
                        })
                    },
                    function(callback){
                        poolShare.loadSession(function(){
                            callback();
                        });
                    }
                ],
                function(err, results){
                    poolProtocol.start(onNonceSubmitReq,onNonceSubmitedRes,onNewClientConnected);
                    setInterval(saveSession,60000);
                    setInterval(function(){
                        poolSession.getMiningInfo(function(result){
                            if(result.status === true){
                                onMiningInfoUpdate(result.msg);
                            }
                        });
                    },1000);
                }
            );
        });
    }
    
    initPool(config.walletIndex);
    
    process.stdin.resume();
    
    function exitHandler(options, err) {
        poolShare.saveSession();
        if (options.cleanup) console.log('clean');
        if (err) console.log(err.stack);
        if (options.exit) process.exit();
    }
    
    process.on('exit', exitHandler.bind(null,{cleanup:true}));
    process.on('SIGINT', exitHandler.bind(null, {exit:true}));
    process.on('uncaughtException', exitHandler.bind(null, {exit:true}));
    

    Pool's console

    genesis base target = 18325193796
    current timestamp 1486935219600
    genesis-block blocktime 79212820
    genesis-block timestamp 1407722399600
    burst pool running on port 8124
    websocket running on port 4443
    http server running on port 8020
    new best deadline 1359691053
    TypeError: Object burstcoin-jminer-0.4.5-RELEASE has no method 'startsWith'
        at /var/www/burstcoin_ml/pool/burst-pool.js:199:43
        at process._tickCallback (node.js:415:13)
    clean
    
    


  • @Lexicon Now running v6.9.5 LTS

    genesis base target = 18325193796
    current timestamp 1486936771374
    genesis-block blocktime 79214371
    genesis-block timestamp 1407722400374
    burst pool running on port 8124
    websocket running on port 4443
    http server running on port 8020
    TypeError: minerReq.query.hasOwnProperty is not a function
        at onNonceSubmitReq (/var/www/burstcoin_ml/pool/burst-pool.js:96:24)
        at transformRequest (/var/www/burstcoin_ml/pool/burst-pool-protocol.js:84:5)
        at Server.<anonymous> (/var/www/burstcoin_ml/pool/burst-pool-protocol.js:136:9)
        at emitTwo (events.js:106:13)
        at Server.emit (events.js:191:7)
        at HTTPParser.parserOnIncoming [as onIncoming] (_http_server.js:546:12)
        at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)
    clean
    


  • @Tate-A said in Lex Pool (A rewritten pool based on uray source):

    query.hasOwnProperty is not a function

    changing everywhere where it uses minerReq.query.hasOwnProperty to

    Object.prototype.hasOwnProperty.call(minerReq.query, 'whatever') 
    

    fix's those errors

    you will find another error around the done() callback probably when a block is won. lmk what like it is and ill get you my fix.

    i think a few of them i used a try catch statement. they remove some callback support in one of the updates from 5.12 up to v6



  • @Lexicon Okay, it looks like it's a go. Thanks @Lexicon and @Burstde for your help! :-)



  • @Lexicon Sorry for bugging you again man, I must be dumb, it seems to be running fine. except for it is not updating the site, I have no errors. I'm currently run node js v4.7.3.



  • @Tate-A I got it, like I said i'm dumb. All I had to do was rename: Chart.js to chart.js Sending you some burst for you help, BURST-ZPPL-BV2U-VVZN-8DJX7.



  • @Tate-A haha this is a common one XD

    apparently windows doesnt care about the case of charts.js but linux does.

    linux only likes it lowercase. and i think windows doesn't care and will run with either.



  • @Lexicon Hey, any chance u could assist me step by step on how can I create my own pool in my VPS linux based server?

    The START POOL.cmd file is not present in the download file neither.


Log in to reply
 

Looks like your connection to Burst - Efficient HDD Mining was lost, please wait while we try to reconnect.