41 if (!
GetTransaction(nTxCollateralHash, txCollateral, nBlockHash,
true)) {
47 if (txCollateral.
vout.size() < 1)
return false;
48 if (txCollateral.
nLockTime != 0)
return false;
53 bool foundOpReturn =
false;
75 if (!nBlockHash.
IsNull()) {
81 nTime = pindex->
nTime;
89 if (conf >=
Params().Budget_Fee_Confirmations()) {
92 strError =
strprintf(
"Collateral requires at least %d confirmations - %d confirmations",
Params().Budget_Fee_Confirmations(), conf);
93 LogPrint(
BCLog::MNBUDGET,
"CBudgetProposalBroadcast::IsBudgetCollateralValid - %s - %d confirmations\n", strError, conf);
103 std::string strError =
"";
107 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::CheckOrphanVotes - Proposal/Budget is known, activating and removing orphan vote\n");
116 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::CheckOrphanVotes - Proposal/Budget is known, activating and removing orphan vote\n");
127 static int nSubmittedHeight = 0;
138 if (nSubmittedHeight >= nBlockStart){
139 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::SubmitFinalBudget - nSubmittedHeight(=%ld) < nBlockStart(=%ld) condition not fulfilled.\n", nSubmittedHeight, nBlockStart);
144 int nOffsetToStart = nFinalizationStart - nCurrentHeight;
147 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::SubmitFinalBudget - Too early for finalization. Current block is %ld, next Superblock is %ld.\n", nCurrentHeight, nBlockStart);
148 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::SubmitFinalBudget - First possible block for finalization: %ld. Last possible block for finalization: %ld. You have to wait for %ld block(s) until Budget finalization will be possible\n", nFinalizationStart, nBlockStart, nOffsetToStart);
154 std::string strBudgetName =
"main";
155 std::vector<CTxBudgetPayment> vecTxBudgetPayments;
157 for (
unsigned int i = 0; i < vBudgetProposals.size(); i++) {
160 txBudgetPayment.
payee = vBudgetProposals[i]->GetPayee();
161 txBudgetPayment.
nAmount = vBudgetProposals[i]->GetAllotted();
162 vecTxBudgetPayments.push_back(txBudgetPayment);
165 if (vecTxBudgetPayments.size() < 1) {
173 nSubmittedHeight = nCurrentHeight;
203 if (!
GetTransaction(txidCollateral, txCollateral, nBlockHash,
true)) {
208 if (!nBlockHash.
IsNull()) {
222 if (conf <
Params().Budget_Fee_Confirmations() + 1) {
223 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::SubmitFinalBudget - Collateral requires at least %d confirmations - %s - %d confirmations\n",
Params().Budget_Fee_Confirmations() + 1, txidCollateral.
ToString(), conf);
230 std::string strError =
"";
231 if (!finalizedBudgetBroadcast.
IsValid(strError)) {
238 finalizedBudgetBroadcast.
Relay();
240 nSubmittedHeight = nCurrentHeight;
272 return error(
"%s : Failed to open file %s", __func__,
pathDB.string());
277 }
catch (
const std::exception& e) {
278 return error(
"%s : Serialize or I/O error - %s", __func__, e.what());
296 error(
"%s : Failed to open file %s", __func__,
pathDB.string());
301 int fileSize = fs::file_size(
pathDB);
302 int dataSize = fileSize -
sizeof(
uint256);
306 std::vector<unsigned char> vchData;
307 vchData.resize(dataSize);
312 filein.
read((
char*)&vchData[0], dataSize);
314 }
catch (
const std::exception& e) {
315 error(
"%s : Deserialize or I/O error - %s", __func__, e.what());
324 if (hashIn != hashTmp) {
325 error(
"%s : Checksum mismatch, data corrupted", __func__);
330 unsigned char pchMsgTmp[4];
331 std::string strMagicMessageTmp;
334 ssObj >> strMagicMessageTmp;
338 error(
"%s : Invalid masternode cache magic message", __func__);
347 if (memcmp(pchMsgTmp,
Params().MessageStart(),
sizeof(pchMsgTmp))) {
348 error(
"%s : Invalid network magic number", __func__);
354 }
catch (
const std::exception& e) {
356 error(
"%s : Deserialize or I/O error - %s", __func__, e.what());
401 std::string strError =
"";
402 if (!finalizedBudget.
IsValid(strError))
return false;
415 std::string strError =
"";
416 if (!budgetProposal.
IsValid(strError)) {
437 std::string strError =
"";
444 pfinalizedBudget->
fValid = pfinalizedBudget->
IsValid(strError);
445 if (!strError.empty ()) {
453 if (pfinalizedBudget->
fValid) {
462 std::map<uint256, CBudgetProposal>::iterator it2 =
mapProposals.begin();
465 pbudgetProposal->
fValid = pbudgetProposal->
IsValid(strError);
466 if (!strError.empty ()) {
474 if (pbudgetProposal->
fValid) {
493 LogPrintf(
"%s: budget manager filling block payee\n", __func__);
495 if (!pindexPrev)
return false;
497 int nHighestCount = 0;
519 if (nHighestCount > 0) {
520 unsigned int i = txNew.
vout.size();
521 txNew.
vout.resize(i + 1);
522 txNew.
vout[i].scriptPubKey = payee;
523 txNew.
vout[i].nValue = nAmount;
528 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::FillBlockPayee - Budget payment to %s for %lld, nHighestCount = %d\n", address2.
ToString(), nAmount, nHighestCount);
531 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::FillBlockPayee - No Budget payment, nHighestCount = %d\n", nHighestCount);
535 txNew.
vout[0].nValue = blockValue;
537 if (nHighestCount > 0) {
538 txNew.
vout.resize(2);
541 txNew.
vout[1].scriptPubKey = payee;
542 txNew.
vout[1].nValue = nAmount;
566 int nYesCount = -99999;
569 std::map<uint256, CBudgetProposal>::iterator it =
mapProposals.begin();
571 if ((*it).second.strProposalName == strProposalName && (*it).second.GetYeas() > nYesCount) {
572 pbudgetProposal = &((*it).second);
573 nYesCount = pbudgetProposal->
GetYeas();
578 if (nYesCount == -99999)
return NULL;
580 return pbudgetProposal;
595 int nHighestCount = -1;
610 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::IsBudgetPaymentBlock() - nHighestCount: %lli, 5%% of Masternodes: %lli. Number of budgets: %lli\n",
614 if (nHighestCount > nFivePercent)
return true;
623 int nHighestCount = 0;
625 std::vector<CFinalizedBudget*> ret;
641 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::IsTransactionValid() - nHighestCount: %lli, 5%% of Masternodes: %lli mapFinalizedBudgets.size(): %ld\n",
646 if (nHighestCount < nFivePercent)
return false;
673 std::vector<CBudgetProposal*> vBudgetProposalRet;
675 std::map<uint256, CBudgetProposal>::iterator it =
mapProposals.begin();
677 (*it).second.CleanAndRemove(
false);
680 vBudgetProposalRet.push_back(pbudgetProposal);
685 return vBudgetProposalRet;
692 bool operator()(
const std::pair<CBudgetProposal*, int>& left,
const std::pair<CBudgetProposal*, int>& right)
694 if (left.second != right.second)
695 return (left.second > right.second);
696 return (left.first->nFeeTXHash > right.first->nFeeTXHash);
707 std::vector<std::pair<CBudgetProposal*, int> > vBudgetPorposalsSort;
709 std::map<uint256, CBudgetProposal>::iterator it =
mapProposals.begin();
711 (*it).second.CleanAndRemove(
false);
712 vBudgetPorposalsSort.push_back(std::make_pair(&((*it).second), (*it).second.GetYeas() - (*it).second.GetNays()));
720 std::vector<CBudgetProposal*> vBudgetProposalsRet;
724 if (pindexPrev == NULL)
return vBudgetProposalsRet;
731 std::vector<std::pair<CBudgetProposal*, int> >::iterator it2 = vBudgetPorposalsSort.begin();
732 while (it2 != vBudgetPorposalsSort.end()) {
738 pbudgetProposal->
nBlockEnd >= nBlockEnd &&
742 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::GetBudget() - Check 1 passed: valid=%d | %ld <= %ld | %ld >= %ld | Yeas=%d Nays=%d Count=%d | established=%d\n",
747 if (pbudgetProposal->
GetAmount() + nBudgetAllocated <= nTotalBudget) {
749 nBudgetAllocated += pbudgetProposal->
GetAmount();
750 vBudgetProposalsRet.push_back(pbudgetProposal);
758 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::GetBudget() - Check 1 failed: valid=%d | %ld <= %ld | %ld >= %ld | Yeas=%d Nays=%d Count=%d | established=%d\n",
767 return vBudgetProposalsRet;
772 bool operator()(
const std::pair<CFinalizedBudget*, int>& left,
const std::pair<CFinalizedBudget*, int>& right)
774 if (left.second != right.second)
775 return left.second > right.second;
776 return (left.first->nFeeTXHash > right.first->nFeeTXHash);
784 std::vector<CFinalizedBudget*> vFinalizedBudgetsRet;
785 std::vector<std::pair<CFinalizedBudget*, int> > vFinalizedBudgetsSort;
793 vFinalizedBudgetsSort.push_back(std::make_pair(pfinalizedBudget, pfinalizedBudget->
GetVoteCount()));
798 std::vector<std::pair<CFinalizedBudget*, int> >::iterator it2 = vFinalizedBudgetsSort.begin();
799 while (it2 != vFinalizedBudgetsSort.end()) {
800 vFinalizedBudgetsRet.push_back((*it2).first);
804 return vFinalizedBudgetsRet;
811 std::string ret =
"unknown-budget";
819 if (ret ==
"unknown-budget") {
826 LogPrint(
BCLog::MNBUDGET,
"CBudgetManager::GetRequiredPaymentsString - Couldn't find budget payment for block %d\n", nBlockHeight);
842 if (nHeight <=
Params().LAST_POW_BLOCK() && nHeight >= 151200) {
843 nSubsidy = 50 * COIN;
844 }
else if (nHeight <= 302399 && nHeight >
Params().LAST_POW_BLOCK()) {
845 nSubsidy = 50 * COIN;
846 }
else if (nHeight <= 345599 && nHeight >= 302400) {
847 nSubsidy = 45 * COIN;
848 }
else if (nHeight <= 388799 && nHeight >= 345600) {
849 nSubsidy = 40 * COIN;
850 }
else if (nHeight <= 431999 && nHeight >= 388800) {
851 nSubsidy = 35 * COIN;
852 }
else if (nHeight <= 475199 && nHeight >= 432000) {
853 nSubsidy = 30 * COIN;
854 }
else if (nHeight <= 518399 && nHeight >= 475200) {
855 nSubsidy = 25 * COIN;
856 }
else if (nHeight <= 561599 && nHeight >= 518400) {
857 nSubsidy = 20 * COIN;
858 }
else if (nHeight <= 604799 && nHeight >= 561600) {
859 nSubsidy = 15 * COIN;
860 }
else if (nHeight <= 647999 && nHeight >= 604800) {
861 nSubsidy = 10 * COIN;
862 }
else if (nHeight >= 648000) {
869 if (nHeight <= 172800) {
870 return 648000 * COIN;
872 return ((nSubsidy / 100) * 10) * 1440 * 30;
879 if (!fBudgetNewBlock)
return;
914 if ((*it).second >
GetTime() - (60 * 60 * 24)) {
922 std::map<uint256, CBudgetProposal>::iterator it2 =
mapProposals.begin();
924 (*it2).second.CleanAndRemove(
false);
931 (*it3).second.CleanAndRemove(
false);
938 std::string strError =
"";
945 if (!(*it4).IsValid(strError)) {
963 std::string strError =
"";
970 if (!(*it5).IsValid(strError)) {
1001 if (nProp.IsNull()) {
1018 vRecv >> budgetProposalBroadcast;
1025 std::string strError =
"";
1027 if (!
IsBudgetCollateralValid(budgetProposalBroadcast.nFeeTXHash, budgetProposalBroadcast.GetHash(), strError, budgetProposalBroadcast.nTime, nConf)) {
1028 LogPrint(
BCLog::MNBUDGET,
"Proposal FeeTX is not valid - %s - %s\n", budgetProposalBroadcast.nFeeTXHash.ToString(), strError);
1035 if (!budgetProposalBroadcast.IsValid(strError)) {
1042 budgetProposalBroadcast.Relay();
1071 if (!vote.SignatureValid(
true)) {
1073 LogPrintf(
"CBudgetManager::ProcessMessage() : mvote - signature invalid\n");
1082 std::string strError =
"";
1088 LogPrint(
BCLog::MNBUDGET,
"mvote - new budget vote for budget %s - %s\n", vote.nProposalHash.ToString(), vote.GetHash().ToString());
1093 vRecv >> finalizedBudgetBroadcast;
1100 std::string strError =
"";
1102 if (!
IsBudgetCollateralValid(finalizedBudgetBroadcast.nFeeTXHash, finalizedBudgetBroadcast.GetHash(), strError, finalizedBudgetBroadcast.nTime, nConf)) {
1103 LogPrint(
BCLog::MNBUDGET,
"Finalized Budget FeeTX is not valid - %s - %s\n", finalizedBudgetBroadcast.nFeeTXHash.ToString(), strError);
1111 if (!finalizedBudgetBroadcast.IsValid(strError)) {
1120 finalizedBudgetBroadcast.Relay();
1146 if (!vote.SignatureValid(
true)) {
1148 LogPrintf(
"CBudgetManager::ProcessMessage() : fbvote - signature invalid\n");
1157 std::string strError =
"";
1164 LogPrint(
BCLog::MNBUDGET,
"fbvote - rejected finalized budget vote - %s - %s\n", vote.GetHash().ToString(), strError);
1184 if (pbudgetProposal && pbudgetProposal->
fValid) {
1186 std::map<uint256, CBudgetVote>::iterator it2 = pbudgetProposal->
mapVotes.begin();
1187 while (it2 != pbudgetProposal->
mapVotes.end()) {
1188 (*it2).second.fSynced =
false;
1198 if (pfinalizedBudget && pfinalizedBudget->
fValid) {
1200 std::map<uint256, CFinalizedBudgetVote>::iterator it4 = pfinalizedBudget->
mapVotes.begin();
1201 while (it4 != pfinalizedBudget->
mapVotes.end()) {
1202 (*it4).second.fSynced =
false;
1221 if (pbudgetProposal && pbudgetProposal->
fValid) {
1223 std::map<uint256, CBudgetVote>::iterator it2 = pbudgetProposal->
mapVotes.begin();
1224 while (it2 != pbudgetProposal->
mapVotes.end()) {
1225 if ((*it2).second.fValid)
1226 (*it2).second.fSynced =
true;
1236 if (pfinalizedBudget && pfinalizedBudget->
fValid) {
1238 std::map<uint256, CFinalizedBudgetVote>::iterator it4 = pfinalizedBudget->
mapVotes.begin();
1239 while (it4 != pfinalizedBudget->
mapVotes.end()) {
1240 if ((*it4).second.fValid)
1241 (*it4).second.fSynced =
true;
1269 if (pbudgetProposal && pbudgetProposal->
fValid && (nProp.
IsNull() || (*it1).first == nProp)) {
1274 std::map<uint256, CBudgetVote>::iterator it2 = pbudgetProposal->
mapVotes.begin();
1275 while (it2 != pbudgetProposal->
mapVotes.end()) {
1276 if ((*it2).second.fValid) {
1277 if ((fPartial && !(*it2).second.fSynced) || !fPartial) {
1297 if (pfinalizedBudget && pfinalizedBudget->
fValid && (nProp.
IsNull() || (*it3).first == nProp)) {
1302 std::map<uint256, CFinalizedBudgetVote>::iterator it4 = pfinalizedBudget->
mapVotes.begin();
1303 while (it4 != pfinalizedBudget->
mapVotes.end()) {
1304 if ((*it4).second.fValid) {
1305 if ((fPartial && !(*it4).second.fSynced) || !fPartial) {
1339 strError =
"Proposal not found!";
1417 strError =
"Invalid Proposal";
1422 strError =
"Proposal " +
strProposalName +
": Invalid nBlockEnd (end before start)";
1432 strError =
"Proposal " +
strProposalName +
": Invalid Payment Address";
1436 if (fCheckCollateral) {
1448 strError =
"Proposal " +
strProposalName +
": Multisig is not currently supported.";
1469 if (pindexPrev == NULL) {
1478 if(nProposalEnd < pindexPrev->nHeight){
1479 strError =
"Proposal " +
strProposalName +
": Invalid nBlockEnd (" + std::to_string(nProposalEnd) +
") < current height (" + std::to_string(pindexPrev->
nHeight) +
")";
1488 std::string strAction =
"New vote inserted:";
1499 if (vote.
nTime -
mapVotes[hash].nTime < BUDGET_VOTE_UPDATE_MIN) {
1504 strAction =
"Existing vote updated:";
1522 std::map<uint256, CBudgetVote>::iterator it =
mapVotes.begin();
1525 (*it).second.fValid = (*it).second.SignatureValid(fSignatureCheck);
1535 std::map<uint256, CBudgetVote>::iterator it =
mapVotes.begin();
1538 if ((*it).second.nVote ==
VOTE_YES) yeas++;
1539 if ((*it).second.nVote ==
VOTE_NO) nays++;
1543 if (yeas + nays == 0)
return 0.0f;
1545 return ((
double)(yeas) / (
double)(yeas + nays));
1552 std::map<uint256, CBudgetVote>::iterator it =
mapVotes.begin();
1554 if ((*it).second.nVote ==
VOTE_YES && (*it).second.fValid) ret++;
1565 std::map<uint256, CBudgetVote>::iterator it =
mapVotes.begin();
1567 if ((*it).second.nVote ==
VOTE_NO && (*it).second.fValid) ret++;
1578 std::map<uint256, CBudgetVote>::iterator it =
mapVotes.begin();
1580 if ((*it).second.nVote ==
VOTE_ABSTAIN && (*it).second.fValid) ret++;
1597 if (pindexPrev == NULL)
return -1;
1686 std::string strError =
"";
1689 CPubKey pubKeyCollateralAddress;
1690 CKey keyCollateralAddress;
1693 std::string strMessage =
HEX_STR(ser);
1710 std::string strError =
"";
1712 std::string strMessage =
HEX_STR(ser);
1721 if (!fSignatureCheck)
return true;
1760 std::string strAction =
"New vote inserted:";
1768 if (vote.
nTime -
mapVotes[hash].nTime < BUDGET_VOTE_UPDATE_MIN) {
1773 strAction =
"Existing vote updated:";
1793 if (!pindexPrev)
return;
1820 for (
unsigned int i = 0; i < vBudgetProposals.size(); i++) {
1822 LogPrint(
BCLog::MNBUDGET,
"CFinalizedBudget::AutoCheck - Payee %d %s\n", i, vBudgetProposals[i]->GetPayee().ToString());
1823 LogPrint(
BCLog::MNBUDGET,
"CFinalizedBudget::AutoCheck - nAmount %d %lli\n", i, vBudgetProposals[i]->GetAmount());
1826 if (vBudgetProposals.size() == 0) {
1832 LogPrint(
BCLog::MNBUDGET,
"CFinalizedBudget::AutoCheck - Budget length doesn't match. vBudgetProposals.size()=%ld != vecBudgetPayments.size()=%ld\n",
1839 if (i > vBudgetProposals.size() - 1) {
1840 LogPrint(
BCLog::MNBUDGET,
"CFinalizedBudget::AutoCheck - Proposal size mismatch, i=%d > (vBudgetProposals.size() - 1)=%d\n", i, vBudgetProposals.size() - 1);
1850 if (
vecBudgetPayments[i].payee.ToString() != vBudgetProposals[i]->GetPayee().ToString()) {
1868 std::map<uint256, CFinalizedBudgetVote>::iterator it =
mapVotes.begin();
1871 (*it).second.fValid = (*it).second.SignatureValid(fSignatureCheck);
1891 std::string ret =
"";
1896 std::string token = budgetPayment.nProposalHash.ToString();
1898 if (pbudgetProposal) token = pbudgetProposal->
GetName();
1910 std::string retBadHashes =
"";
1911 std::string retBadPayeeOrAmount =
"";
1916 LogPrint(
BCLog::MNBUDGET,
"CFinalizedBudget::GetStatus - Couldn't find budget payment for block %lld\n", nBlockHeight);
1921 if (!pbudgetProposal) {
1922 if (retBadHashes ==
"") {
1923 retBadHashes =
"Unknown proposal hash! Check this proposal before voting" + budgetPayment.
nProposalHash.
ToString();
1929 if (retBadPayeeOrAmount ==
"") {
1930 retBadPayeeOrAmount =
"Budget payee/nAmount doesn't match our proposal! " + budgetPayment.
nProposalHash.
ToString();
1938 if (retBadHashes ==
"" && retBadPayeeOrAmount ==
"")
return "OK";
1940 return retBadHashes + retBadPayeeOrAmount;
1947 strError =
"Invalid BlockStart";
1953 strError =
"Invalid BlockEnd";
1957 strError =
"Invalid budget payments count (too many)";
1961 strError =
"Invalid Budget Name";
1965 strError =
"Budget " +
strBudgetName +
" Invalid BlockStart == 0";
1969 strError =
"Budget " +
strBudgetName +
" Invalid FeeTx == 0";
1975 strError =
"Budget " +
strBudgetName +
" Invalid Payout (more than max)";
1979 std::string strError2 =
"";
1980 if (fCheckCollateral) {
1984 strError =
"Budget " +
strBudgetName +
" Invalid Collateral : " + strError2;
1991 if (pindexPrev == NULL)
return true;
1999 if (nCurrentBudgetPayment < 0) {
2032 std::string strError =
"";
2042 if (!vote.
Sign(keyMasternode, pubKeyMasternode)) {
2121 std::string strError =
"";
2124 CPubKey pubKeyCollateralAddress;
2125 CKey keyCollateralAddress;
2128 std::string strMessage =
HEX_STR(ser);
2145 std::string strError;
2147 std::string strMessage =
HEX_STR(ser);
2156 if (!fSignatureCheck)
return true;
2159 LogPrint(
BCLog::MNBUDGET,
"CFinalizedBudgetVote::SignatureValid() - Verify message failed %s: %s\n", strMessage, strError);
2168 std::ostringstream info;