Make 0.12.1.x minable again (#963)
* Changes for getblocktemplate, CreateNewBlock, FillBlockPayee, CreateSuperblock: - Add support for superblocks in getblocktemplate (+fix miner reward - it was missing) - Refactor the way masternode payments are passed around, change getblocktemplate format for them too.
This commit is contained in:
parent
180a81eada
commit
02b86cf467
@ -396,7 +396,7 @@ bool CSuperblockManager::GetBestSuperblock(CSuperblock_sptr& pBlock, int nBlockH
|
||||
* - Create the correct payment structure for a given superblock
|
||||
*/
|
||||
|
||||
void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNew, int nBlockHeight)
|
||||
void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNewRet, int nBlockHeight, std::vector<CTxOut>& voutSuperblockRet)
|
||||
{
|
||||
DBG( cout << "CSuperblockManager::CreateSuperblock Start" << endl; );
|
||||
|
||||
@ -411,10 +411,12 @@ void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNew, int nBlock
|
||||
return;
|
||||
}
|
||||
|
||||
// CONFIGURE SUPERBLOCK OUTPUTS
|
||||
// make sure it's empty, just in case
|
||||
voutSuperblockRet.clear();
|
||||
|
||||
// CONFIGURE SUPERBLOCK OUTPUTS
|
||||
|
||||
// Superblock payments are appended to the end of the coinbase vout vector
|
||||
|
||||
DBG( cout << "CSuperblockManager::CreateSuperblock Number payments: " << pBlock->CountPayments() << endl; );
|
||||
|
||||
// TODO: How many payments can we add before things blow up?
|
||||
@ -428,7 +430,9 @@ void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNew, int nBlock
|
||||
DBG( cout << "CSuperblockManager::CreateSuperblock Payment found " << endl; );
|
||||
// SET COINBASE OUTPUT TO SUPERBLOCK SETTING
|
||||
|
||||
txNew.vout.push_back(CTxOut(payment.nAmount, payment.script));
|
||||
CTxOut txout = CTxOut(payment.nAmount, payment.script);
|
||||
txNewRet.vout.push_back(txout);
|
||||
voutSuperblockRet.push_back(txout);
|
||||
|
||||
// PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT
|
||||
|
||||
|
@ -90,7 +90,7 @@ public:
|
||||
|
||||
static bool IsSuperblockTriggered(int nBlockHeight);
|
||||
|
||||
static void CreateSuperblock(CMutableTransaction& txNew, int nBlockHeight);
|
||||
static void CreateSuperblock(CMutableTransaction& txNewRet, int nBlockHeight, std::vector<CTxOut>& voutSuperblockRet);
|
||||
|
||||
static std::string GetRequiredPaymentsString(int nBlockHeight);
|
||||
static bool IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward);
|
||||
|
@ -183,19 +183,21 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc
|
||||
return true;
|
||||
}
|
||||
|
||||
void FillBlockPayee(CMutableTransaction& txNew, CAmount blockReward, int nBlockHeight)
|
||||
void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet, std::vector<CTxOut>& voutSuperblockRet)
|
||||
{
|
||||
// only create superblocks if spork is enabled AND if superblock is actually triggered
|
||||
// (height should be validated inside)
|
||||
if(sporkManager.IsSporkActive(SPORK_9_MASTERNODE_SUPERBLOCK_ENFORCEMENT) &&
|
||||
CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
|
||||
LogPrint("gobject", "FillBlockPayee -- triggered superblock creation at height %d\n", nBlockHeight);
|
||||
CSuperblockManager::CreateSuperblock(txNew, nBlockHeight);
|
||||
LogPrint("gobject", "FillBlockPayments -- triggered superblock creation at height %d\n", nBlockHeight);
|
||||
CSuperblockManager::CreateSuperblock(txNew, nBlockHeight, voutSuperblockRet);
|
||||
return;
|
||||
}
|
||||
|
||||
// FILL BLOCK PAYEE WITH MASTERNODE PAYMENT OTHERWISE
|
||||
mnpayments.FillBlockPayee(txNew, blockReward, nBlockHeight);
|
||||
mnpayments.FillBlockPayee(txNew, nBlockHeight, blockReward, txoutMasternodeRet);
|
||||
LogPrint("mnpayments", "FillBlockPayments -- nBlockHeight %d blockReward %lld txoutMasternodeRet %s txNew %s",
|
||||
nBlockHeight, blockReward, txoutMasternodeRet.ToString(), txNew.ToString());
|
||||
}
|
||||
|
||||
std::string GetRequiredPaymentsString(int nBlockHeight)
|
||||
@ -215,40 +217,39 @@ std::string GetRequiredPaymentsString(int nBlockHeight)
|
||||
* Fill Masternode ONLY payment block
|
||||
*/
|
||||
|
||||
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, CAmount blockReward, int nBlockHeight)
|
||||
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet)
|
||||
{
|
||||
bool hasPayment = true;
|
||||
// make sure it's not filled yet
|
||||
txoutMasternodeRet = CTxOut();
|
||||
|
||||
CScript payee;
|
||||
|
||||
if(!mnpayments.GetBlockPayee(nBlockHeight, payee)) {
|
||||
//no masternode detected
|
||||
// no masternode detected...
|
||||
CMasternode* winningNode = mnodeman.GetCurrentMasterNode();
|
||||
if(winningNode) {
|
||||
payee = GetScriptForDestination(winningNode->pubkey.GetID());
|
||||
} else {
|
||||
if(!winningNode) {
|
||||
// ...and we can't calculate it on our own
|
||||
LogPrintf("CMasternodePayments::FillBlockPayee -- Failed to detect masternode to pay\n");
|
||||
hasPayment = false;
|
||||
return;
|
||||
}
|
||||
// fill payee with locally calculated winner and hope for the best
|
||||
payee = GetScriptForDestination(winningNode->pubkey.GetID());
|
||||
}
|
||||
|
||||
// GET MASTERNODE PAYMENT VARIABLES SETUP
|
||||
|
||||
CAmount masternodePayment = GetMasternodePayment(nBlockHeight, blockReward);
|
||||
|
||||
txNew.vout[0].nValue = blockReward;
|
||||
// split reward between miner ...
|
||||
txNew.vout[0].nValue -= masternodePayment;
|
||||
// ... and masternode
|
||||
txoutMasternodeRet = CTxOut(masternodePayment, payee);
|
||||
txNew.vout.push_back(txoutMasternodeRet);
|
||||
|
||||
if(hasPayment) {
|
||||
// split reward between miner ...
|
||||
txNew.vout[0].nValue -= masternodePayment;
|
||||
// ... and masternode
|
||||
txNew.vout.push_back(CTxOut(masternodePayment, payee));
|
||||
CTxDestination address1;
|
||||
ExtractDestination(payee, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
CTxDestination address1;
|
||||
ExtractDestination(payee, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
LogPrintf("Masternode payment %d to %s\n", masternodePayment, address2.ToString());
|
||||
}
|
||||
LogPrintf("CMasternodePayments::FillBlockPayee -- Masternode payment %lld to %s\n", masternodePayment, address2.ToString());
|
||||
}
|
||||
|
||||
int CMasternodePayments::GetMinMasternodePaymentsProto() {
|
||||
|
@ -35,7 +35,7 @@ bool IsReferenceNode(CTxIn& vin);
|
||||
/// TODO: all 4 functions do not belong here really, they should be refactored/moved somewhere (main.cpp ?)
|
||||
bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockReward);
|
||||
bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward);
|
||||
void FillBlockPayee(CMutableTransaction& txNew, CAmount blockReward, int nBlockHeight);
|
||||
void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet, std::vector<CTxOut>& voutSuperblockRet);
|
||||
std::string GetRequiredPaymentsString(int nBlockHeight);
|
||||
|
||||
class CMasternodePayee
|
||||
@ -249,7 +249,7 @@ public:
|
||||
int GetMinMasternodePaymentsProto();
|
||||
void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
||||
std::string GetRequiredPaymentsString(int nBlockHeight);
|
||||
void FillBlockPayee(CMutableTransaction& txNew, CAmount blockReward, int nBlockHeight);
|
||||
void FillBlockPayee(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet);
|
||||
std::string ToString() const;
|
||||
|
||||
int GetOldestBlock();
|
||||
|
@ -274,24 +274,25 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
|
||||
}
|
||||
}
|
||||
}
|
||||
CAmount blockReward = nFees + GetBlockSubsidy(pindexPrev->nBits, pindexPrev->nHeight, Params().GetConsensus());
|
||||
// Masternode and governace payments
|
||||
FillBlockPayee(txNew, blockReward, nHeight);
|
||||
|
||||
// Make payee
|
||||
// TODO: does not make sense for superblocks and it is not enough anymore
|
||||
if(txNew.vout.size() > 1){
|
||||
pblock->payee = txNew.vout[1].scriptPubKey;
|
||||
}
|
||||
// NOTE: unlike in bitcoin, we need to pass PREVIOUS block height here
|
||||
CAmount blockReward = nFees + GetBlockSubsidy(pindexPrev->nBits, pindexPrev->nHeight, Params().GetConsensus());
|
||||
|
||||
// Compute regular coinbase transaction.
|
||||
txNew.vout[0].nValue = blockReward;
|
||||
txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
|
||||
|
||||
// Update coinbase transaction with additional info about masternode and governace payments,
|
||||
// get some info back to pass to getblocktemplate
|
||||
FillBlockPayments(txNew, nHeight, blockReward, pblock->txoutMasternode, pblock->voutSuperblock);
|
||||
// LogPrintf("CreateNewBlock -- nBlockHeight %d blockReward %lld txoutMasternode %s txNew %s",
|
||||
// nHeight, blockReward, pblock->txoutMasternode.ToString(), txNew.ToString());
|
||||
|
||||
nLastBlockTx = nBlockTx;
|
||||
nLastBlockSize = nBlockSize;
|
||||
LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOps);
|
||||
|
||||
// Compute final coinbase transaction.
|
||||
// Should already be calculated in FillBlockPayee
|
||||
// txNew.vout[0].nValue = nFees + GetBlockSubsidy(pindexPrev->nBits, nHeight, chainparams.GetConsensus());
|
||||
txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
|
||||
// Update block coinbase
|
||||
pblock->vtx[0] = txNew;
|
||||
pblocktemplate->vTxFees[0] = -nFees;
|
||||
|
||||
|
@ -77,7 +77,8 @@ public:
|
||||
std::vector<CTransaction> vtx;
|
||||
|
||||
// memory only
|
||||
mutable CScript payee;
|
||||
mutable CTxOut txoutMasternode; // masternode payment
|
||||
mutable std::vector<CTxOut> voutSuperblock; // superblock payment
|
||||
mutable bool fChecked;
|
||||
|
||||
CBlock()
|
||||
@ -103,7 +104,8 @@ public:
|
||||
{
|
||||
CBlockHeader::SetNull();
|
||||
vtx.clear();
|
||||
payee = CScript();
|
||||
txoutMasternode = CTxOut();
|
||||
voutSuperblock.clear();
|
||||
fChecked = false;
|
||||
}
|
||||
|
||||
|
@ -381,10 +381,23 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
" \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
|
||||
" \"bits\" : \"xxx\", (string) compressed target of next block\n"
|
||||
" \"height\" : n (numeric) The height of the next block\n"
|
||||
" \"payee\" : \"xxx\", (string) required payee for the next block\n"
|
||||
" \"payee_amount\" : n, (numeric) required amount to pay\n"
|
||||
" \"masternode_payments\" : true|false, (boolean) true, if masternode payments are enabled\n"
|
||||
" \"enforce_masternode_payments\" : true|false (boolean) true, if masternode payments are enforced\n"
|
||||
" \"masternode\" : { (json object) required masternode payee that must be included in the next block\n"
|
||||
" \"payee\" : \"xxxx\", (string) payee address\n"
|
||||
" \"script\" : \"xxxx\", (string) payee scriptPubKey\n"
|
||||
" \"amount\": n (numeric) required amount to pay\n"
|
||||
" },\n"
|
||||
" \"masternode_payments_started\" : true|false, (boolean) true, if masternode payments started\n"
|
||||
" \"masternode_payments_enforced\" : true|false, (boolean) true, if masternode payments are enforced\n"
|
||||
" \"superblock\" : [ (array) required superblock payees that must be included in the next block\n"
|
||||
" {\n"
|
||||
" \"payee\" : \"xxxx\", (string) payee address\n"
|
||||
" \"script\" : \"xxxx\", (string) payee scriptPubKey\n"
|
||||
" \"amount\": n (numeric) required amount to pay\n"
|
||||
" }\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
" \"superblocks_started\" : true|false, (boolean) true, if superblock payments started\n"
|
||||
" \"superblocks_enabled\" : true|false (boolean) true, if superblock payments are enabled\n"
|
||||
"}\n"
|
||||
|
||||
"\nExamples:\n"
|
||||
@ -597,20 +610,35 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
|
||||
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
|
||||
|
||||
|
||||
if(pblock->payee != CScript()){
|
||||
UniValue masternodeObj(UniValue::VOBJ);
|
||||
if(pblock->txoutMasternode != CTxOut()) {
|
||||
CTxDestination address1;
|
||||
ExtractDestination(pblock->payee, address1);
|
||||
ExtractDestination(pblock->txoutMasternode.scriptPubKey, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
result.push_back(Pair("payee", address2.ToString().c_str()));
|
||||
result.push_back(Pair("payee_amount", (int64_t)pblock->vtx[0].vout[1].nValue));
|
||||
} else {
|
||||
result.push_back(Pair("payee", ""));
|
||||
result.push_back(Pair("payee_amount", ""));
|
||||
masternodeObj.push_back(Pair("payee", address2.ToString().c_str()));
|
||||
masternodeObj.push_back(Pair("script", HexStr(pblock->txoutMasternode.scriptPubKey.begin(), pblock->txoutMasternode.scriptPubKey.end())));
|
||||
masternodeObj.push_back(Pair("amount", pblock->txoutMasternode.nValue));
|
||||
}
|
||||
result.push_back(Pair("masternode", masternodeObj));
|
||||
result.push_back(Pair("masternode_payments_started", pindexPrev->nHeight + 1 > Params().GetConsensus().nMasternodePaymentsStartBlock));
|
||||
result.push_back(Pair("masternode_payments_enforced", sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)));
|
||||
|
||||
result.push_back(Pair("masternode_payments", (int64_t)(pindexPrev->nHeight+1) > Params().GetConsensus().nMasternodePaymentsStartBlock));
|
||||
result.push_back(Pair("enforce_masternode_payments", sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)));
|
||||
UniValue superblockObjArray(UniValue::VARR);
|
||||
if(pblock->voutSuperblock.size()) {
|
||||
BOOST_FOREACH (const CTxOut& txout, pblock->voutSuperblock) {
|
||||
UniValue entry(UniValue::VOBJ);
|
||||
CTxDestination address1;
|
||||
ExtractDestination(txout.scriptPubKey, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
entry.push_back(Pair("payee", address2.ToString().c_str()));
|
||||
entry.push_back(Pair("script", HexStr(txout.scriptPubKey.begin(), txout.scriptPubKey.end())));
|
||||
entry.push_back(Pair("amount", txout.nValue));
|
||||
superblockObjArray.push_back(entry);
|
||||
}
|
||||
}
|
||||
result.push_back(Pair("superblock", superblockObjArray));
|
||||
result.push_back(Pair("superblocks_started", pindexPrev->nHeight + 1 > Params().GetConsensus().nSuperblockStartBlock));
|
||||
result.push_back(Pair("superblocks_enabled", sporkManager.IsSporkActive(SPORK_9_MASTERNODE_SUPERBLOCK_ENFORCEMENT)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user