diff --git a/index.js b/index.js index 334ff98..7e62b14 100644 --- a/index.js +++ b/index.js @@ -20,7 +20,7 @@ function scriptCompile(addrHash) { } function reverseBuffer(buff) { - let reversed = new Buffer(buff.length); + let reversed = Buffer.alloc(buff.length); for (var i = buff.length - 1; i >= 0; i--) reversed[buff.length - i - 1] = buff[i]; return reversed; } @@ -47,7 +47,7 @@ function hash256(buffer) { }; function getMerkleRoot(transactions) { - if (transactions.length === 0) return new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex') + if (transactions.length === 0) return Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex') const forWitness = txesHaveWitnessCommit(transactions); const hashes = transactions.map(transaction => transaction.getHash(forWitness)); const rootHash = fastMerkleRoot(hashes, hash256); @@ -77,27 +77,27 @@ module.exports.RavenBlockTemplate = function(rpcData, poolAddress) { bytesHeight = Math.ceil((rpcData.height << 1).toString(2).length / 8); const lengthDiff = blockHeightSerial.length/2 - bytesHeight; for (let i = 0; i < lengthDiff; i++) blockHeightSerial = blockHeightSerial + '00'; - const serializedBlockHeight = new Buffer.concat([ - new Buffer('0' + bytesHeight, 'hex'), - reverseBuffer(new Buffer(blockHeightSerial, 'hex')), - new Buffer('00', 'hex') // OP_0 + const serializedBlockHeight = Buffer.concat([ + Buffer.from('0' + bytesHeight, 'hex'), + reverseBuffer(Buffer.from(blockHeightSerial, 'hex')), + Buffer.from('00', 'hex') // OP_0 ]); txCoinbase.addInput( // will be used for our reserved_offset extra_nonce - new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex'), + Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex'), 0xFFFFFFFF, 0xFFFFFFFF, - new Buffer.concat([serializedBlockHeight, Buffer('CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC', 'hex')]) // 17 bytes + Buffer.concat([serializedBlockHeight, Buffer('CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC', 'hex')]) // 17 bytes ); txCoinbase.addOutput(scriptCompile(poolAddrHash), Math.floor(rpcData.coinbasevalue)); if (rpcData.default_witness_commitment) { - txCoinbase.addOutput(new Buffer(rpcData.default_witness_commitment, 'hex'), 0); + txCoinbase.addOutput(Buffer.from(rpcData.default_witness_commitment, 'hex'), 0); } } - let header = new Buffer(80); + let header = Buffer.alloc(80); { let position = 0; header.writeUInt32BE(rpcData.height, position, 4); // height 42-46 header.write(rpcData.bits, position += 4, 4, 'hex'); // bits 47-50 @@ -108,17 +108,17 @@ module.exports.RavenBlockTemplate = function(rpcData, poolAddress) { header = reverseBuffer(header); } - let blob = new Buffer.concat([ + let blob = Buffer.concat([ header, // 80 bytes - new Buffer('AAAAAAAAAAAAAAAA', 'hex'), // 8 bytes - new Buffer('BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB', 'hex'), // 32 bytes - varuint.encode(rpcData.transactions.length + 1, new Buffer(varuint.encodingLength(rpcData.transactions.length + 1)), 0) + Buffer.from('AAAAAAAAAAAAAAAA', 'hex'), // 8 bytes + Buffer.from('BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB', 'hex'), // 32 bytes + varuint.encode(rpcData.transactions.length + 1, Buffer.alloc(varuint.encodingLength(rpcData.transactions.length + 1)), 0) ]); const offset1 = blob.length; - blob = new Buffer.concat([ blob, new Buffer(txCoinbase.toHex(), 'hex') ]); + blob = Buffer.concat([ blob, Buffer.from(txCoinbase.toHex(), 'hex') ]); rpcData.transactions.forEach(function (value) { - blob = new Buffer.concat([ blob, new Buffer(value.data, 'hex') ]); + blob = Buffer.concat([ blob, Buffer.from(value.data, 'hex') ]); }); const EPOCH_LENGTH = 7500; @@ -128,7 +128,7 @@ module.exports.RavenBlockTemplate = function(rpcData, poolAddress) { if (last_epoch_number && last_epoch_number + 1 === epoch_number) { last_seed_hash = sha3.update(last_seed_hash).digest(); } else { - last_seed_hash = new Buffer(32, 0); + last_seed_hash = Buffer.alloc(32, 0); for (let i = 0; i < epoch_number; i++) { last_seed_hash = sha3.update(last_seed_hash).digest(); sha3.reset(); @@ -207,6 +207,10 @@ module.exports.RtmBlockTemplate = function(rpcData, poolAddress) { return rtm.RtmBlockTemplate(rpcData, poolAddress); }; -module.exports.RtmPreHashingBlob = function(bt, nonce1) { - return rtm.RtmPreHashingBlob(bt, nonce1); +module.exports.convertRtmBlob = function(buffer) { + return rtm.convertRtmBlob(buffer); +}; + +module.exports.constructNewRtmBlob = function(blockTemplate, nonceBuff) { + return rtm.constructNewRtmBlob(blockTemplate, nonceBuff); }; diff --git a/package.json b/package.json index e2d6903..f23edf8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cryptoforknote-util", - "version": "10.1.0", + "version": "11.0.0", "main": "cryptoforknote-util", "author": { "name": "LucasJones", diff --git a/rtm.js b/rtm.js index aaf2960..3758f42 100644 --- a/rtm.js +++ b/rtm.js @@ -2,7 +2,7 @@ const crypto = require('crypto'); const bignum = require('bignum'); const base58 = require('base58-native'); -const diff1 = 0x00000000ffff0000000000000000000000000000000000000000000000000000; +const diff1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; function reverseBuffer(buff) { let reversed = Buffer.alloc(buff.length); @@ -15,6 +15,12 @@ function reverseByteOrder(buff) { return reverseBuffer(buff); } +function packInt32LE(num) { + let buff = Buffer.alloc(4); + buff.writeInt32LE(num, 0); + return buff; +} + function packInt32BE(num) { let buff = Buffer.alloc(4); buff.writeInt32BE(num, 0); @@ -146,7 +152,7 @@ function merkleTreeBranches(data) { if (Ll > 1) { while (true) { if (Ll === 1) break; - steps.push(L[1].toString('hex')); + steps.push(L[1]); if (Ll % 2) L.push(L[L.length - 1]); let Ld = []; let r = range(StartL, Ll, 2); @@ -245,14 +251,11 @@ function generateOutputTransactions(rpcData, poolAddress) { ])); } - return { - reward: rewardToPool, - buff: Buffer.concat([ varIntBuffer(txOutputBuffers.length), Buffer.concat(txOutputBuffers)]) - }; + return Buffer.concat([ varIntBuffer(txOutputBuffers.length), Buffer.concat(txOutputBuffers)]); } module.exports.RtmBlockTemplate = function(rpcData, poolAddress) { - const extraNoncePlaceholderLength = 8; + const extraNoncePlaceholderLength = 16; const coinbaseVersion = Buffer.concat([packUInt16LE(3), packUInt16LE(5)]); const scriptSigPart1 = Buffer.concat([ @@ -264,8 +267,6 @@ module.exports.RtmBlockTemplate = function(rpcData, poolAddress) { const scriptSigPart2 = serializeString('/nodeStratum/'); - const out = generateOutputTransactions(rpcData, poolAddress); - const blob1 = Buffer.concat([ coinbaseVersion, // transaction input @@ -281,28 +282,41 @@ module.exports.RtmBlockTemplate = function(rpcData, poolAddress) { packUInt32LE(0), // txInSequence // end transaction input // transaction output - out.buff, + generateOutputTransactions(rpcData, poolAddress), // end transaction ouput packUInt32LE(0), // txLockTime varIntBuffer(rpcData.coinbase_payload.length / 2), Buffer.from(rpcData.coinbase_payload, 'hex') ]); + const version = packInt32LE(rpcData.version).toString('hex'); + const curtime = packUInt32LE(rpcData.curtime).toString('hex'); + let bits = Buffer.from(rpcData.bits, 'hex'); + bits.writeUInt32LE(bits.readUInt32BE()); + return { - reward: out.reward, difficulty: parseFloat((diff1 / bignum(rpcData.target, 16).toNumber()).toFixed(9)), - prev_hash: reverseByteOrder(Buffer.from(rpcData.previousblockhash, 'hex')).toString('hex'), - blob1: blob1.toString('hex'), - blob2: blob2.toString('hex'), - merkle_branches: merkleTreeBranches(getTransactionBuffers(rpcData.transactions)), - version: packInt32BE(rpcData.version).toString('hex'), - nbits: rpcData.bits, - ntime: packUInt32BE(rpcData.curtime).toString('hex'), + height: rpcData.height, + prev_hash: rpcData.previousblockhash, + blocktemplate_blob: version + rpcData.previousblockhash + Buffer.alloc(32, 0).toString('hex') + curtime + bits.toString('hex') + Buffer.alloc(4, 0).toString('hex') + + packUInt32LE(blob1.length + extraNoncePlaceholderLength + blob2.length).toString('hex') + + blob1.toString('hex') + Buffer.alloc(extraNoncePlaceholderLength, 0).toString('hex') + blob2.toString('hex') + + Buffer.concat(merkleTreeBranches(getTransactionBuffers(rpcData.transactions))).toString('hex'), + reserved_offset: 80 + 4 + blob1.length } } -module.exports.RtmPreHashingBlob = function(bt, nonce1) { - let merkle_root = sha256d(Buffer.from(bt.blob1 + nonce1.toString('hex') + "00000000" + bt.blob2)); - bt.merkle_branches.forEach(function(branch) { merkle_root = merkleJoin(merkle_root, Buffer.from(branch, 'hex')); }); - return Buffer.from(bt.version + bt.prev_hash + merkle_root.toString('hex') + bt.ntime + bt.ntime, 'hex'); -} \ No newline at end of file +module.exports.convertRtmBlob = function(buffer) { + let header = buffer.slice(0, 80); + const blobSize = buffer.slice(80, 80 + 4).readUInt32LE(); + let merkle_root = sha256d(buffer.slice(84, 84 + blobSize)); + for (let i = 84 + blobSize; i < buffer.length; i += 32) + merkle_root = merkleJoin(merkle_root, buffer.slice(i, i + 32)); + merkle_root.copy(header, 4 + 32, 0, 32); + return header; +} + +module.exports.constructNewRtmBlob = function(blockTemplate, nonceBuff) { + nonceBuff.copy(blockTemplate, 76, 0, 4); + return blockTemplate; +}