this.processShare = function(jobId, previousDifficulty, difficulty, extraNonce1, extraNonce2, nTime, nonce, ipAddress, port, workerName){
        var shareError = function(error){
            _this.emit('share', {
                job: jobId,
                ip: ipAddress,
                worker: workerName,
                difficulty: difficulty,
                error: error[1]
            });
            return {error: error, result: null};
        };

        var submitTime = Date.now() / 1000 | 0;

        if (extraNonce2.length / 2 !== _this.extraNonce2Size)
            return shareError([20, 'incorrect size of extranonce2']);

        var job = this.validJobs[jobId];

        if (typeof job === 'undefined' || job.jobId != jobId ) {
            return shareError([21, 'job not found']);
        }

        if (nTime.length !== 8) {
            return shareError([20, 'incorrect size of ntime']);
        }

        var nTimeInt = parseInt(nTime, 16);
        if (nTimeInt < job.rpcData.curtime || nTimeInt > submitTime + 7200) {
            return shareError([20, 'ntime out of range']);
        }

        if (nonce.length !== 8) {
            return shareError([20, 'incorrect size of nonce']);
        }

        if (!job.registerSubmit(extraNonce1, extraNonce2, nTime, nonce)) {
            return shareError([22, 'duplicate share']);
        }


        var extraNonce1Buffer = new Buffer(extraNonce1, 'hex');
        var extraNonce2Buffer = new Buffer(extraNonce2, 'hex');

        var coinbaseBuffer = job.serializeCoinbase(extraNonce1Buffer, extraNonce2Buffer);
        var coinbaseHash = coinbaseHasher(coinbaseBuffer);

        var merkleRoot = util.reverseBuffer(job.merkleTree.withFirst(coinbaseHash)).toString('hex');

        var headerBuffer = job.serializeHeader(merkleRoot, nTime, nonce);
        var headerHash = hashDigest(headerBuffer, nTimeInt);
        var headerBigNum = bignum.fromBuffer(headerHash, {endian: 'little', size: 32});

        var blockHashInvalid;
        var blockHash;
        var blockHex;

        var shareDiff = diff1 / headerBigNum.toNumber() * shareMultiplier;

        var blockDiffAdjusted = job.difficulty * shareMultiplier;

        //Check if share is a block candidate (matched network difficulty)
        if (job.target.ge(headerBigNum)){
            blockHex = job.serializeBlock(headerBuffer, coinbaseBuffer).toString('hex');
            if (options.coin.algorithm === 'neoscrypt') {
                blockHash = util.reverseBuffer(util.sha256d(headerBuffer, nTime)).toString('hex');
            }
            else {
                blockHash = blockHasher(headerBuffer, nTime).toString('hex');
            }
        }
        else {
            if (options.emitInvalidBlockHashes)
                blockHashInvalid = util.reverseBuffer(util.sha256d(headerBuffer)).toString('hex');

            //Check if share didn't reached the miner's difficulty)
            if (shareDiff / difficulty < 0.99){

                //Check if share matched a previous difficulty from before a vardiff retarget
                if (previousDifficulty && shareDiff >= previousDifficulty){
                    difficulty = previousDifficulty;
                }
                else{
                    return shareError([23, 'low difficulty share of ' + shareDiff]);
                }

            }
        }


        _this.emit('share', {
            job: jobId,
            ip: ipAddress,
            port: port,
            worker: workerName,
            height: job.rpcData.height,
            blockReward: job.rpcData.coinbasevalue,
            difficulty: difficulty,
            shareDiff: shareDiff.toFixed(8),
            blockDiff : blockDiffAdjusted,
            blockDiffActual: job.difficulty,
            blockHash: blockHash,
            blockHashInvalid: blockHashInvalid
        }, blockHex);

        return {result: true, error: null, blockHash: blockHash};
    };
Example #2
0
 BigInteger.fromBase64 = function(b64_string) {
   var bi = bigint.fromBuffer(new Buffer(b64_string, 'base64'));
   return BigInteger._from_bigint(bi);
 };
    this.processShare = function(jobId, previousDifficulty, difficulty, extraNonce1, extraNonce2, nTime, nonce, ipAddress, workerName){
        var shareError = function(error){
            _this.emit('share', {
                job: jobId,
                ip: ipAddress,
                worker: workerName,
                difficulty: difficulty,
                error: error[1]
            });
            return {error: error, result: null};
        };

        var submitTime = Date.now() / 1000 | 0;

        if (extraNonce2.length / 2 !== _this.extraNonce2Size)
            return shareError([20, 'incorrect size of extranonce2']);

        var job = this.validJobs[jobId];

        if (typeof job === 'undefined' || job.jobId != jobId ) {
            return shareError([21, 'job not found']);
        }

        if (nTime.length !== 8) {
            return shareError([20, 'incorrect size of ntime']);
        }

        var nTimeInt = parseInt(nTime, 16);
        if (nTimeInt < job.rpcData.curtime || nTimeInt > submitTime + 7200) {
            return shareError([20, 'ntime out of range']);
        }

        if (nonce.length !== 8) {
            return shareError([20, 'incorrect size of nonce']);
        }

        if (!job.registerSubmit(extraNonce1, extraNonce2, nTime, nonce)) {
            return shareError([22, 'duplicate share']);
        }


        var extraNonce1Buffer = new Buffer(extraNonce1, 'hex');
        var extraNonce2Buffer = new Buffer(extraNonce2, 'hex');

        var coinbaseBuffer = job.serializeCoinbase(extraNonce1Buffer, extraNonce2Buffer);
        var coinbaseHash = coinbaseHasher(coinbaseBuffer);

        var merkleRoot = util.reverseBuffer(job.merkleTree.withFirst(coinbaseHash)).toString('hex');

        var headerBuffer = job.serializeHeader(merkleRoot, nTime, nonce);
        var headerHash = hashDigest(headerBuffer, nTimeInt);
        var headerBigNum = bignum.fromBuffer(headerHash, {endian: 'little', size: 32});

        var blockHashInvalid;
        var blockHash;
        var blockHex;

        var shareDiff = maxDifficulty.div(headerBigNum);

        //Check if share is a block candidate (matched network difficulty)
        if (job.target.ge(headerBigNum)){
            blockHex = job.serializeBlock(headerBuffer, coinbaseBuffer).toString('hex');
            blockHash = util.reverseBuffer(util.sha256d(headerBuffer)).toString('hex');
        }
        else {
            if (options.emitInvalidBlockHashes)
                blockHashInvalid = util.reverseBuffer(util.sha256d(headerBuffer)).toString('hex');

            //Difficulty the miner is set to
            var targetUser = maxDifficulty.div(difficulty);

            //Check if share didn't reached the miner's difficulty)
            if (headerBigNum.gt(targetUser)){

                //Check if share matched a previous difficulty from before a vardiff retarget
                if (previousDifficulty && !headerBigNum.gt(maxDifficulty.div(previousDifficulty))){
                    difficulty = previousDifficulty;
                }
                else{
                    var offPercent = 100 - (shareDiff.toNumber() / difficulty) * 100;

                    //Check to see if low diff share is within acceptable configured range
                    if (offPercent > (options.shareVariancePercent || 0)){
                        return shareError([23, 'low difficulty share of ' + shareDiff.toString()]);
                    }
                    else{
                        _this.emit('log', 'warning', 'Share accepted a low diff ' + shareDiff + ' off by ' + offPercent.toFixed(2) + '%');
                    }
                }

            }
        }


        _this.emit('share', {
            job: jobId,
            ip: ipAddress,
            worker: workerName,
            difficulty: difficulty,
            shareDiff: shareDiff,
            height: job.rpcData.height,
            reward: job.rpcData.coinbasevalue,
            networkDifficulty : job.difficulty.toString(),
            blockHash: blockHash,
            blockHashInvalid: blockHashInvalid

        }, blockHex);

        return {result: true, error: null, blockHash: blockHash};
    };
Example #4
0
exports.encryptTweet = function(user, tweet) {
    var message = new Buffer(tweet.tweet);
    tweet.tweet = exports.encryptWithUser(user, bignum.fromBuffer(message));
    return tweet;
}
function processShare(miner, job, blockTemplate, nonce, resultHash){
    var template = new Buffer(blockTemplate.buffer.length);
    blockTemplate.buffer.copy(template);
    template.writeUInt32BE(job.extraNonce, blockTemplate.reserveOffset);
    var shareBuffer = cnUtil.construct_block_blob(template, new Buffer(nonce, 'hex'));

    var convertedBlob;
    var hash;
    var shareType;

    if (shareTrustEnabled && miner.trust.threshold <= 0 && miner.trust.penalty <= 0 && Math.random() > miner.trust.probability){
        hash = new Buffer(resultHash, 'hex');
        shareType = 'trusted';
    }
    else {
        convertedBlob = cnUtil.convert_blob(shareBuffer);
        hash = cryptoNight(convertedBlob);
        shareType = 'valid';
    }


    if (hash.toString('hex') !== resultHash) {
        log('warn', logSystem, 'Bad hash from miner %s@%s', [miner.login, miner.ip]);
        return false;
    }

    var hashArray = hash.toJSON();
    hashArray.reverse();
    var hashNum = bignum.fromBuffer(new Buffer(hashArray));
    var hashDiff = diff1.div(hashNum);



    if (hashDiff.ge(blockTemplate.difficulty)){

        apiInterfaces.rpcDaemon('submitblock', [shareBuffer.toString('hex')], function(error, result){
            if (error){
                log('error', logSystem, 'Error submitting block at height %d from %s@%s, share type: "%s" - %j', [job.height, miner.login, miner.ip, shareType, error]);
                recordShareData(miner, job, hashDiff.toString(), false, null, shareType);
            }
            else{
                var blockFastHash = cnUtil.get_block_id(shareBuffer).toString('hex');
                log('info', logSystem,
                    'Block %s found at height %d by miner %s@%s - submit result: %j',
                    [blockFastHash.substr(0, 6), job.height, miner.login, miner.ip, result]
                );
                recordShareData(miner, job, hashDiff.toString(), true, blockFastHash, shareType, blockTemplate);
                jobRefresh();
            }
        });
    }

    else if (hashDiff.lt(job.difficulty)){
        log('warn', logSystem, 'Rejected low difficulty share of %s from %s@%s', [hashDiff.toString(), miner.login, miner.ip]);
        return false;
    }
    else{
        recordShareData(miner, job, hashDiff.toString(), false, null, shareType);
    }

    return true;
}
 state.get(address, function(err, data) {
   var account = new Account(data);
   account.balance = bignum.fromBuffer(account.balance).sub(minerReward).toBuffer();
   state.put(address, account.serialize(), done);
 });
Example #7
0
exports.str_to_num = function (str) {
    return bignum.fromBuffer(new Buffer(str));
};
Example #8
0
var xor = function(buf, buf2){
  return bignum.fromBuffer(buf).xor(bignum.fromBuffer(buf2)).toBuffer()
}
Example #9
0
HierarchicalKey.prototype.deriveChild = function(i) {
  var ib = [];
  ib.push((i >> 24) & 0xff);
  ib.push((i >> 16) & 0xff);
  ib.push((i >> 8) & 0xff);
  ib.push(i & 0xff);
  ib = new Buffer(ib);

  var usePrivate = (i & 0x80000000) != 0;

  var isPrivate =
    (this.version == networks['livenet'].hkeyPrivateVersion ||
      this.version == networks['testnet'].hkeyPrivateVersion);

  if (usePrivate && (!this.hasPrivateKey || !isPrivate))
    throw new Error('Cannot do private key derivation without private key');

  var ret = null;
  if (this.hasPrivateKey) {
    var data = null;

    if (usePrivate) {
      data = Buffer.concat([new Buffer([0]), this.eckey.private, ib]);
    } else {
      data = Buffer.concat([this.eckey.public, ib]);
    }

    var hash = coinUtil.sha512hmac(data, this.chainCode);
    var il = bignum.fromBuffer(hash.slice(0, 32), {
      size: 32
    });
    var ir = hash.slice(32, 64);

    // ki = IL + kpar (mod n).
    var priv = bignum.fromBuffer(this.eckey.private, {
      size: 32
    });
    var k = il.add(priv).mod(secp256k1_n);

    ret = new HierarchicalKey(null);
    ret.chainCode = ir;

    ret.eckey = new Key();
    ret.eckey.private = k.toBuffer({
      size: 32
    });
    ret.eckey.regenerateSync();
    ret.hasPrivateKey = true;

  } else {
    var data = Buffer.concat([this.eckey.public, ib]);
    var hash = coinUtil.sha512hmac(data, this.chainCode);
    var il = hash.slice(0, 32);
    var ir = hash.slice(32, 64);

    // Ki = (IL + kpar)*G = IL*G + Kpar
    var ilGkey = new Key();
    ilGkey.private = il;
    ilGkey.regenerateSync();
    ilGkey.compressed = false;
    var ilG = Point.fromUncompressedPubKey(ilGkey.public);
    var oldkey = new Key();
    oldkey.public = this.eckey.public;
    oldkey.compressed = false;
    var Kpar = Point.fromUncompressedPubKey(oldkey.public);
    var newpub = Point.add(ilG, Kpar).toUncompressedPubKey();

    ret = new HierarchicalKey(null);
    ret.chainCode = new Buffer(ir);

    var eckey = new Key();
    eckey.public = newpub;
    eckey.compressed = true;
    ret.eckey = eckey;
    ret.hasPrivateKey = false;
  }

  ret.childIndex = i;
  ret.parentFingerprint = this.pubKeyHash.slice(0, 4);
  ret.version = this.version;
  ret.depth = this.depth + 1;

  ret.eckey.compressed = true;
  ret.pubKeyHash = coinUtil.sha256ripe160(ret.eckey.public);

  ret.buildExtendedPublicKey();
  ret.buildExtendedPrivateKey();

  return ret;
}
Example #10
0
/*
 * calculate the SRP-6 multiplier
 *
 * params:
 *         N (bignum)       group parameter N
 *         g (bignum)       generator
 *         alg (string)     default = ALG
 *
 * returns: bignum
 */
function getk(N, g, alg) {
  return bignum.fromBuffer(getkBuffer(N.toBuffer(), g.toBuffer(), alg));
};
Example #11
0
/*
 * Random scrambling parameter u
 *
 * params:
 *         A (bignum)       client ephemeral public key
 *         B (bignum)       server ephemeral public key
 *         N (bignum)       group parameter N
 */
function getu(A, B, N, alg) {
  return bignum.fromBuffer(getuBuffer(A.toBuffer(), B.toBuffer(), N.toBuffer(), alg));
};
Example #12
0
/**
 * Process miner share data
 **/
function processShare(miner, job, blockTemplate, params){
    var nonce = params.nonce;
    var resultHash = params.result;
    var template = new Buffer(blockTemplate.buffer.length);
    if (!miner.proxy) {
        blockTemplate.buffer.copy(template);
        template.writeUInt32BE(job.extraNonce, blockTemplate.reserveOffset);
    } else {
        blockTemplate.buffer.copy(template);
        template.writeUInt32BE(job.extraNonce, blockTemplate.reserveOffset);
        template.writeUInt32BE(params.poolNonce, job.clientPoolLocation);
        template.writeUInt32BE(params.workerNonce, job.clientNonceLocation);
    }

    var shareBuffer = utils.cnUtil.construct_block_blob(template, new Buffer(nonce, 'hex'), 0);

    var hash;
    var shareType;

    if (shareTrustEnabled && miner.trust.threshold <= 0 && miner.trust.penalty <= 0 && Math.random() > miner.trust.probability){
        hash = new Buffer(resultHash, 'hex');
        shareType = 'trusted';
    } else {

		let convertedBlob = utils.cnUtil.convert_blob(shareBuffer, 0);
        let hard_fork_version = convertedBlob[0];
        let variant = 0;
        if(hard_fork_version == 3){
            variant = 1;
        } else if(hard_fork_version > 3){
            variant = 2;
        }
        hash = cryptonight(convertedBlob,variant);
        shareType = 'valid';
//         log('info', logSystem, 'Mining pool algorithm: %s variant %d, Hard fork version: %d', [cnAlgorithm, cnVariant, hard_fork_version]);
    }

    if (hash.toString('hex') !== resultHash) {
        log('warn', logSystem, 'Bad hash from miner %s@%s', [miner.login, miner.ip]);
        return false;
    }

    var hashArray = hash.toByteArray().reverse();
    var hashNum = bignum.fromBuffer(new Buffer(hashArray));
    var hashDiff = diff1.div(hashNum);

    if (hashDiff.ge(blockTemplate.difficulty)){

        rpcDaemon.submitBlock([shareBuffer.toString('hex')], function(error, result){
            if (error){
                log('error', logSystem, 'Error submitting block at height %d from %s@%s, share type: "%s" - %j', [job.height, miner.login, miner.ip, shareType, error]);
                recordShareData(miner, job, hashDiff.toString(), false, null, shareType);

            }else{
                var blockFastHash = utils.cnUtil.get_block_id(shareBuffer, 0).toString('hex');
                log('info', logSystem,
                    'Block %s found at height %d by miner %s@%s - submit result: %j',
                    [blockFastHash.substr(0, 6), job.height, miner.login, miner.ip, result]
                );
                recordShareData(miner, job, hashDiff.toString(), true, blockFastHash, shareType, blockTemplate);
                
            }
            jobRefresh();
        });
    } else if (hashDiff.lt(job.difficulty)){
        log('warn', logSystem, 'Rejected low difficulty share of %s from %s@%s', [hashDiff.toString(), miner.login, miner.ip]);
        return false;
    }
    else{
        recordShareData(miner, job, hashDiff.toString(), false, null, shareType);
    }

    return true;
}
var BlockTemplate = module.exports = function BlockTemplate(jobId, rpcData, publicKey, extraNoncePlaceholder, reward, txMessages){

    //private members

    var submits = [];

    function getMerkleHashes(steps){
        return steps.map(function(step){
            return step.toString('hex');
        });
    }

    function getTransactionBuffers(txs){
        var txHashes = txs.map(function(tx){
            return util.uint256BufferFromHash(tx.hash);
        });
        return [null].concat(txHashes);
    }


    //public members

    this.rpcData = rpcData;
    this.jobId = jobId;

    /*
    Use the 'target' field if available, but some daemons only return the 'bits' field
     */
    this.target = rpcData.target ?
        bignum.fromBuffer(new Buffer(rpcData.target, 'hex')) :
        util.bignumFromBits(rpcData.bits);

    this.prevHashReversed = util.reverseByteOrder(new Buffer(rpcData.previousblockhash, 'hex')).toString('hex');
    this.transactionData = Buffer.concat(rpcData.transactions.map(function(tx){
        return new Buffer(tx.data, 'hex');
    }));
    this.merkleTree = new merkleTree(getTransactionBuffers(rpcData.transactions));
    this.merkleBranch = getMerkleHashes(this.merkleTree.steps);
    this.generationTransaction = transactions.CreateGeneration(//new transactions.Generation(
        rpcData,
        publicKey,
        extraNoncePlaceholder,
        reward,
        txMessages
    );

    this.serializeCoinbase = function(extraNonce1, extraNonce2){
        return Buffer.concat([
            this.generationTransaction[0],
            extraNonce1,
            extraNonce2,
            this.generationTransaction[1]
        ]);
    };


    //https://en.bitcoin.it/wiki/Protocol_specification#Block_Headers
    this.serializeHeader = function(merkleRoot, nTime, nonce){

        var header =  new Buffer(80);
        var position = 0;
        header.write(nonce, position, 4, 'hex');
        header.write(rpcData.bits, position += 4, 4, 'hex');
        header.write(nTime, position += 4, 4, 'hex');
        header.write(merkleRoot, position += 4, 32, 'hex');
        header.write(rpcData.previousblockhash, position += 32, 32, 'hex');
        header.writeUInt32BE(rpcData.version, position + 32);
        var header = util.reverseBuffer(header);
        return header;
    };

    this.serializeBlock = function(header, coinbase){
        return Buffer.concat([
            header,
            util.varIntBuffer(this.rpcData.transactions.length + 1),
            coinbase,
            this.transactionData,
            new Buffer(reward === 'POS' ? [0] : []) //POS coins require a zero byte appended to block which the daemon replaces with the signature
        ]);
    };

    this.registerSubmit = function(extraNonce1, extraNonce2, nTime, nonce){
        var submission = extraNonce1 + extraNonce2 + nTime + nonce;
        if (submits.indexOf(submission) === -1){
            submits.push(submission);
            return true;
        }
        return false;
    };

    this.getJobParams = function(){
        if (!this.jobParams){
            this.jobParams = [
                this.jobId,
                this.prevHashReversed,
                this.generationTransaction[0].toString('hex'),
                this.generationTransaction[1].toString('hex'),
                this.merkleBranch,
                util.packInt32BE(this.rpcData.version).toString('hex'),
                this.rpcData.bits,
                util.packUInt32BE(this.rpcData.curtime).toString('hex'),
                true
            ];
        }
        return this.jobParams;
    };
};
function processShare(miner, job, blockTemplate, nonce, resultHash){
    var shareBuffer = new Buffer(blockTemplate.buffer.length);
    blockTemplate.buffer.copy(shareBuffer);
    shareBuffer.writeUInt32BE(job.extraNonce, blockTemplate.reserveOffset);
    if (typeof(nonce) === 'number' && nonce % 1 === 0) {
        var nonceBuf = bignum(nonce, 10).toBuffer();
        var bufReversed = new Buffer(nonceBuf.toJSON().reverse());
        bufReversed.copy(shareBuffer, 1);
    } else {
        new Buffer(nonce, 'hex').copy(shareBuffer, 1);
    }
    //XMR FIXME:
    //new Buffer(nonce, 'hex').copy(shareBuffer, 39);

    var convertedBlob;
    var hash;
    var shareType;

    if (shareTrustEnabled && miner.trust.threshold <= 0 && miner.trust.penalty <= 0 && Math.random() > miner.trust.probability){
        hash = new Buffer(resultHash, 'hex');
        shareType = 'trusted';
        //Fixme do i need this?
		log('debug', logSystem, 'Share Validator', 'Trusted share from miner ' + miner.login + '@' + miner.ip);
    } else {
		convertedBlob = convertBlockBlob(shareBuffer);
		//XMR FIXME:
		//hash = cryptoNight(convertedBlob);
		hash = multiHashing.boolberry(convertedBlob, scratchpad, job.height);
        shareType = 'valid';
    }
    //BBR FIXME:


    if (hash.toString('hex') !== resultHash) {
        //log('warn', logSystem, 'Bad hash from miner %s@%s', [miner.login, miner.ip]);
        log('warn', logSystem, 'Bad hash from miner ' +  miner.login + '@' + miner.ip +
            '\n scratchpadHeight.height=' + scratchpadHeight.height + ', job.height=' + job.height +
            '\n calculated hash: ' + hash.toString('hex') + ', transfered hash: ' + resultHash);
        return false;
    }

    var hashArray = hash.toJSON();
    hashArray.reverse();
    var hashNum = bignum.fromBuffer(new Buffer(hashArray));
    var hashDiff = diff1.div(hashNum);



    if (hashDiff.ge(blockTemplate.difficulty)){

        apiInterfaces.rpcDaemon('submitblock', [shareBuffer.toString('hex')], function(error, result){
            if (error){
                log('error', logSystem, 'Error submitting block at height %d from %s@%s, share type: "%s" - %j', [job.height, miner.login, miner.ip, shareType, error]);
                recordShareData(miner, job, hashDiff.toString(), false, null, shareType);
            }
            else{
                var blockFastHash = cryptoNightFast(convertedBlob || convertBlockBlob(shareBuffer)).toString('hex');                
                log('info', logSystem,
                    'Block %s found at height %d by miner %s@%s - submit result: %j',
                    [blockFastHash.substr(0, 6), job.height, miner.login, miner.ip, result]
                );

				recordShareData(miner, job, hashDiff.toString(), true, blockFastHash, shareType, blockTemplate);
                //XMR FIXME:
                //jobRefresh();
                if(aliases_config && aliases_config.aliases_que && aliases_config.aliases_que.length > 0)
                {
                    aliases_config.aliases_que.shift();
                    storeAliasesQue();
                    log('debug', logSystem, 'Alias que updated.');
                }             
            }
        });
    }

    else if (hashDiff.lt(job.difficulty)){
        log('warn', logSystem, 'Rejected low difficulty share of %s from %s@%s', [hashDiff.toString(), miner.login, miner.ip]);
        return false;
    }
    else{
        recordShareData(miner, job, hashDiff.toString(), false, null, shareType);
    }

    return true;
}