Skip to content

Instantly share code, notes, and snippets.

@JCThePants
Created December 27, 2017 04:01
Show Gist options
  • Save JCThePants/c3c96ca97cd673dace69fe389588af66 to your computer and use it in GitHub Desktop.
Save JCThePants/c3c96ca97cd673dace69fe389588af66 to your computer and use it in GitHub Desktop.
Modified for use with znodes
var util = require('./util.js');
exports.CreateGeneration = function (args) {
var rpcData = args.rpcData;
var publicKey = args.publicKey;
var extraNoncePlaceholder = args.extraNoncePlaceholder;
var rewardType = args.rewardType;
var txMessages = args.txMessages;
var fixedRewards = args.fixedRewards;
var auxMerkleTree = args.auxMerkleTree;
var txInputsCount = 1;
var txOutputsCount = 1;
var txVersion = txMessages === true ? 2 : 1;
var txLockTime = 0;
var txInPrevOutHash = 0;
var txInPrevOutIndex = Math.pow(2, 32) - 1;
var txInSequence = 0;
//Only required for POS coins
var txTimestamp = rewardType === 'POS' ?
util.packUInt32LE(rpcData.curtime) : new Buffer([]);
//For coins that support/require transaction comments
var txComment = txMessages === true ?
util.serializeString('https://github.com/UNOMP/node-merged-pool') :
new Buffer([]);
var scriptSigPart1 = Buffer.concat([
util.serializeNumber(rpcData.height),
new Buffer(rpcData.coinbaseaux.flags, 'hex'),
util.serializeNumber(Date.now() / 1000 | 0),
new Buffer([extraNoncePlaceholder.length]),
new Buffer('fabe6d6d', 'hex'),
util.reverseBuffer(auxMerkleTree.root),
util.packUInt32LE(auxMerkleTree.data.length),
util.packUInt32LE(0)
]);
var scriptSigPart2 = util.serializeString('/nodeStratum/');
var p1 = Buffer.concat([
util.packUInt32LE(txVersion),
txTimestamp,
//transaction input
util.varIntBuffer(txInputsCount),
util.uint256BufferFromHash(txInPrevOutHash),
util.packUInt32LE(txInPrevOutIndex),
util.varIntBuffer(scriptSigPart1.length + extraNoncePlaceholder.length + scriptSigPart2.length),
scriptSigPart1
]);
/*
The generation transaction must be split at the extranonce (which located in the transaction input
scriptSig). Miners send us unique extranonces that we use to join the two parts in attempt to create
a valid share and/or block.
*/
var outputTransactions = generateOutputTransactions(publicKey, fixedRewards, rpcData);
var p2 = Buffer.concat([
scriptSigPart2,
util.packUInt32LE(txInSequence),
//end transaction input
//transaction output
outputTransactions,
//end transaction ouput
util.packUInt32LE(txLockTime),
txComment
]);
return [p1, p2];
};
/*
This function creates the generation transaction that accepts the reward for
successfully mining a new block.
For some (probably outdated and incorrect) documentation about whats kinda going on here,
see: https://en.bitcoin.it/wiki/Protocol_specification#tx
*/
function generateOutputTransactions(poolRecipient, fixedRewards, blockTemplate) {
var rewardAmount = blockTemplate.coinbasevalue;
var rewardToPool = rewardAmount;
var txOutputBuffers = [];
/* Dash 12.1 */
var masternode = blockTemplate.masternode;
var superblock = blockTemplate.superblock;
if (masternode && superblock) {
if (masternode.payee) {
var payeeReward = masternode.amount;
rewardAmount -= payeeReward;
rewardToPool -= payeeReward;
var payeeScript = util.addressToScript(masternode.payee);
txOutputBuffers.push(Buffer.concat([
util.packInt64LE(payeeReward),
util.varIntBuffer(payeeScript.length),
payeeScript
]));
}
else if (superblock.length > 0) {
for (var i in superblock) {
var payeeReward = 0;
payeeReward = superblock[i].amount;
rewardAmount -= payeeReward;
rewardToPool -= payeeReward;
var payeeScript = util.addressToScript(superblock[i].payee);
txOutputBuffers.push(Buffer.concat([
util.packInt64LE(payeeReward),
util.varIntBuffer(payeeScript.length),
payeeScript
]));
}
}
}
// Zcoin znodes
if (blockTemplate.znode) {
var znode = blockTemplate.znode;
if (znode.payee) {
var payeeReward = znode.amount;
var payeeScript = util.addressToScript(znode.payee);
txOutputBuffers.push(Buffer.concat([
util.packInt64LE(payeeReward),
util.varIntBuffer(payeeScript.length),
payeeScript
]));
}
}
// Payee
if (blockTemplate.payee) {
var payeeReward = 0;
if (blockTemplate.payee_amount) {
payeeReward = blockTemplate.payee_amount;
}
else {
payeeReward = Math.ceil(rewardAmount / 5);
}
rewardAmount -= payeeReward;
rewardToPool -= payeeReward;
var payeeScript = util.addressToScript(blockTemplate.payee);
txOutputBuffers.push(Buffer.concat([
util.packInt64LE(payeeReward),
util.varIntBuffer(payeeScript.length),
payeeScript
]));
}
// Fixed rewards
fixedRewards.forEachReward(rewardAmount, function(recipientReward, recipientInfo) {
// subtract from pool reward
if (recipientInfo.subtractFromPool)
rewardToPool -= recipientReward;
txOutputBuffers.push(Buffer.concat([
util.packInt64LE(recipientReward),
util.varIntBuffer(recipientInfo.script.length),
recipientInfo.script
]));
});
// Payment to pool
txOutputBuffers.unshift(Buffer.concat([
util.packInt64LE(rewardToPool),
util.varIntBuffer(poolRecipient.length),
poolRecipient
]));
if (blockTemplate.default_witness_commitment !== undefined) {
var witness_commitment = new Buffer(blockTemplate.default_witness_commitment, 'hex');
txOutputBuffers.unshift(Buffer.concat([
util.packInt64LE(0),
util.varIntBuffer(witness_commitment.length),
witness_commitment
]));
}
return Buffer.concat([
util.varIntBuffer(txOutputBuffers.length),
Buffer.concat(txOutputBuffers)
]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment