void CMasternode::UpdateLastPaid(const CBlockIndex *pindex, int nMaxBlocksToScanBack) { if(!pindex) return; const CBlockIndex *BlockReading = pindex; CScript mnpayee = GetScriptForDestination(pubKeyCollateralAddress.GetID()); // LogPrint("masternode", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s\n", vin.prevout.ToStringShort()); LOCK(cs_mapMasternodeBlocks); for (int i = 0; BlockReading && BlockReading->nHeight > nBlockLastPaid && i < nMaxBlocksToScanBack; i++) { if(mnpayments.mapMasternodeBlocks.count(BlockReading->nHeight) && mnpayments.mapMasternodeBlocks[BlockReading->nHeight].HasPayeeWithVotes(mnpayee, 2)) { CBlock block; if(!ReadBlockFromDisk(block, BlockReading, Params().GetConsensus())) // shouldn't really happen continue; CAmount nMasternodePayment = GetMasternodePayment(BlockReading->nHeight, block.vtx[0].GetValueOut()); BOOST_FOREACH(CTxOut txout, block.vtx[0].vout) if(mnpayee == txout.scriptPubKey && nMasternodePayment == txout.nValue) { nBlockLastPaid = BlockReading->nHeight; nTimeLastPaid = BlockReading->nTime; LogPrint("masternode", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- found new %d\n", vin.prevout.ToStringShort(), nBlockLastPaid); return; } } if (BlockReading->pprev == NULL) { assert(BlockReading); break; } BlockReading = BlockReading->pprev; }
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet) { // make sure it's not filled yet txoutMasternodeRet = CTxOut(); CScript payee; if(!mnpayments.GetBlockPayee(nBlockHeight, payee)) { // no masternode detected... int nCount = 0; masternode_info_t mnInfo; if(!mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount, mnInfo)) { // ...and we can't calculate it on our own LogPrintf("CMasternodePayments::FillBlockPayee -- Failed to detect masternode to pay\n"); return; } // fill payee with locally calculated winner and hope for the best payee = GetScriptForDestination(mnInfo.pubKeyCollateralAddress.GetID()); } // GET MASTERNODE PAYMENT VARIABLES SETUP CAmount masternodePayment = GetMasternodePayment(nBlockHeight, blockReward); // split reward between miner ... txNew.vout[0].nValue -= masternodePayment; // ... and masternode txoutMasternodeRet = CTxOut(masternodePayment, payee); txNew.vout.push_back(txoutMasternodeRet); CTxDestination address1; ExtractDestination(payee, address1); CBitcoinAddress address2(address1); LogPrintf("CMasternodePayments::FillBlockPayee -- Masternode payment %lld to %s\n", masternodePayment, address2.ToString()); }
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFees, bool fProofOfStake, bool fZXAPStake) { CBlockIndex* pindexPrev = chainActive.Tip(); if (!pindexPrev) return; bool hasPayment = true; CScript payee; //spork if (!masternodePayments.GetBlockPayee(pindexPrev->nHeight + 1, payee)) { //no masternode detected CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1); if (winningNode) { payee = GetScriptForDestination(winningNode->pubKeyCollateralAddress.GetID()); } else { LogPrint("masternode","CreateNewBlock: Failed to detect masternode to pay\n"); hasPayment = false; } } CAmount blockValue = GetBlockValue(pindexPrev->nHeight); CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight, blockValue, 0, fZXAPStake); if (hasPayment) { if (fProofOfStake) { /**For Proof Of Stake vout[0] must be null * Stake reward can be split into many different outputs, so we must * use vout.size() to align with several different cases. * An additional output is appended as the masternode payment */ unsigned int i = txNew.vout.size(); txNew.vout.resize(i + 1); txNew.vout[i].scriptPubKey = payee; txNew.vout[i].nValue = masternodePayment; //subtract mn payment from the stake reward if (!txNew.vout[1].IsZerocoinMint()) txNew.vout[i - 1].nValue -= masternodePayment; } else { txNew.vout.resize(2); txNew.vout[1].scriptPubKey = payee; txNew.vout[1].nValue = masternodePayment; txNew.vout[0].nValue = blockValue - masternodePayment; } CTxDestination address1; ExtractDestination(payee, address1); CBitcoinAddress address2(address1); LogPrint("masternode","Masternode payment of %s to %s\n", FormatMoney(masternodePayment).c_str(), address2.ToString().c_str()); } else { if (!fProofOfStake) txNew.vout[0].nValue = blockValue; } }
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFees, bool fProofOfStake) { CBlockIndex* pindexPrev = chainActive.Tip(); if(!pindexPrev) return; bool hasPayment = true; CScript payee; //spork if(!masternodePayments.GetBlockPayee(pindexPrev->nHeight+1, payee)){ //no masternode detected CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1); if(winningNode){ payee = GetScriptForDestination(winningNode->pubKeyCollateralAddress.GetID()); } else { LogPrintf("CreateNewBlock: Failed to detect masternode to pay\n"); hasPayment = false; } } CAmount blockValue = GetBlockValue(pindexPrev->nHeight); CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight, blockValue); if(hasPayment) { if(fProofOfStake) { unsigned int i = txNew.vout.size(); txNew.vout.resize(i + 1); txNew.vout[i].scriptPubKey = payee; txNew.vout[i].nValue = masternodePayment; txNew.vout[i - 1].nValue -= masternodePayment; } else { txNew.vout.resize(2); txNew.vout[1].scriptPubKey = payee; txNew.vout[1].nValue = masternodePayment; txNew.vout[0].nValue = blockValue - masternodePayment; } CTxDestination address1; ExtractDestination(payee, address1); CBitcoinAddress address2(address1); LogPrintf("Masternode payment to %s\n", address2.ToString().c_str()); } }
void CMasternode::UpdateLastPaid(const CBlockIndex* pindex, int nMaxBlocksToScanBack) { if (!pindex) return; const CBlockIndex* pindexActive = chainActive.Tip(); assert(pindexActive); CDiskBlockPos blockPos = pindexActive->GetBlockPos(); CScript mnpayee = GetScriptForDestination(CScriptID(GetScriptForDestination(WitnessV0KeyHash(pubKeyCollateralAddress.GetID())))); //LogPrint(MCLog::MN, "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s\n", outpoint.ToStringShort()); LOCK(cs_mapMasternodeBlocks); for (int i = 0; pindexActive->nHeight > nBlockLastPaid && i < nMaxBlocksToScanBack; i++) { if (mnpayments.mapMasternodeBlocks.count(pindexActive->nHeight) && mnpayments.mapMasternodeBlocks[pindexActive->nHeight].HasPayeeWithVotes(mnpayee, 2)) { if (blockPos.IsNull() == true) { return; } CBlock block; if (!ReadBlockFromDisk(block, blockPos, Params().GetConsensus())) continue; CAmount nMasternodePayment = GetMasternodePayment(pindexActive->nHeight, block.vtx[0]->GetValueOut()); for (const auto& txout : block.vtx[0]->vout) if (mnpayee == txout.scriptPubKey && nMasternodePayment == txout.nValue) { nBlockLastPaid = pindexActive->nHeight; nTimeLastPaid = pindexActive->nTime; LogPrint(MCLog::MN, "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- found new %d\n", outpoint.ToStringShort(), nBlockLastPaid); return; } } if (pindexActive->pprev == nullptr) { assert(pindexActive); break; } pindexActive = pindexActive->pprev; } // Last payment for this masternode wasn't found in latest mnpayments blocks // or it was found in mnpayments blocks but wasn't found in the blockchain. LogPrint(MCLog::MN, "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- keeping old %d\n", outpoint.ToStringShort(), nBlockLastPaid); }