From 99e27d6ff7a04aa81dd634c22a5cabf31e4e6845 Mon Sep 17 00:00:00 2001 From: alex v Date: Sat, 23 May 2020 18:49:03 +0200 Subject: [PATCH] Optimize memory use for blockindex (#682) * optimize memory use for blockindex * use function reference --- src/chain.h | 40 +- src/consensus/dao.cpp | 140 +++--- src/main.cpp | 228 ++++++---- src/main.h | 13 + src/rpc/blockchain.cpp | 998 +++++++++++++++++++++-------------------- src/txdb.cpp | 57 ++- src/txdb.h | 6 +- 7 files changed, 812 insertions(+), 670 deletions(-) diff --git a/src/chain.h b/src/chain.h index 7095bb947..96a160364 100644 --- a/src/chain.h +++ b/src/chain.h @@ -222,21 +222,12 @@ class CBlockIndex int64_t nCFSupply; int64_t nCFLocked; - std::vector> vProposalVotes; - std::vector> vPaymentRequestVotes; - std::map mapSupport; - std::map mapConsultationVotes; - std::string strDZeel; unsigned int nFlags; // ppcoin: block index flags uint64_t nStakeModifier; // hash modifier for proof-of-stake - // proof-of-stake specific fields - COutPoint prevoutStake; - unsigned int nStakeTime; - arith_uint256 hashProof; //! (memory only) Sequential id assigned to distinguish order in which blocks are received. @@ -262,17 +253,11 @@ class CBlockIndex nFlags = 0; nStakeModifier = 0; hashProof = arith_uint256(); - prevoutStake.SetNull(); - nStakeTime = 0; nVersion = 0; hashMerkleRoot = uint256(); nTime = 0; nBits = 0; nNonce = 0; - vProposalVotes.clear(); - vPaymentRequestVotes.clear(); - mapSupport.clear(); - mapConsultationVotes.clear(); } CBlockIndex() @@ -298,13 +283,6 @@ class CBlockIndex if (block.IsProofOfStake()) { SetProofOfStake(); - prevoutStake = block.vtx[1].vin[0].prevout; - nStakeTime = block.vtx[1].nTime; - } - else - { - prevoutStake.SetNull(); - nStakeTime = 0; } nVersion = block.nVersion; @@ -389,13 +367,12 @@ class CBlockIndex std::string ToString() const { - return strprintf("CBlockIndex(nprev=%p, nFile=%u, nHeight=%d, nMint=%s, nCFSupply=%s, nCFLocked=%s, nFlags=(%s)(%d)(%s), nStakeModifier=%016x, hashProof=%s, prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)", + return strprintf("CBlockIndex(nprev=%p, nFile=%u, nHeight=%d, nMint=%s, nCFSupply=%s, nCFLocked=%s, nFlags=(%s)(%d)(%s), nStakeModifier=%016x, hashProof=%s, merkle=%s, hashBlock=%s)", pprev, nFile, nHeight, FormatMoney(nMint), FormatMoney(nCFSupply), FormatMoney(nCFLocked), GeneratedStakeModifier() ? "MOD" : "-", GetStakeEntropyBit(), IsProofOfStake()? "PoS" : "PoW", nStakeModifier, hashProof.ToString(), - prevoutStake.ToString(), nStakeTime, hashMerkleRoot.ToString(), GetBlockHash().ToString()); } @@ -484,10 +461,25 @@ class CDiskBlockIndex : public CBlockIndex uint256 hashPrev; uint256 hashNext; + std::vector> vProposalVotes; + std::vector> vPaymentRequestVotes; + std::map mapSupport; + std::map mapConsultationVotes; + + // proof-of-stake specific fields + COutPoint prevoutStake; + unsigned int nStakeTime; + CDiskBlockIndex() { hashPrev = uint256(); hashNext = uint256(); blockHash = uint256(); + prevoutStake.SetNull(); + nStakeTime = 0; + vProposalVotes.clear(); + vPaymentRequestVotes.clear(); + mapSupport.clear(); + mapConsultationVotes.clear(); } explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex) { diff --git a/src/consensus/dao.cpp b/src/consensus/dao.cpp index ee9d0c39f..806317c36 100644 --- a/src/consensus/dao.cpp +++ b/src/consensus/dao.cpp @@ -377,103 +377,121 @@ bool VoteStep(const CValidationState& state, CBlockIndex *pindexNew, const bool if (fCFund) { - for(unsigned int i = 0; i < pindexblock->vProposalVotes.size(); i++) + auto pVotes = GetProposalVotes(pindexblock->GetBlockHash()); + if (pVotes != nullptr) { - if(mapSeen.count(pindexblock->vProposalVotes[i].first) == 0) + for(unsigned int i = 0; i < pVotes->size(); i++) { - LogPrint("daoextra", "%s: Found vote %d for proposal %s at block height %d\n", __func__, - pindexblock->vProposalVotes[i].second, pindexblock->vProposalVotes[i].first.ToString(), - pindexblock->nHeight); + if(mapSeen.count((*pVotes)[i].first) == 0) + { + LogPrint("daoextra", "%s: Found vote %d for proposal %s at block height %d\n", __func__, + (*pVotes)[i].second, (*pVotes)[i].first.ToString(), + pindexblock->nHeight); - if(mapCacheProposalsToUpdate.count(pindexblock->vProposalVotes[i].first) == 0) - mapCacheProposalsToUpdate[pindexblock->vProposalVotes[i].first] = make_pair(make_pair(0, 0), 0); + if(mapCacheProposalsToUpdate.count((*pVotes)[i].first) == 0) + mapCacheProposalsToUpdate[(*pVotes)[i].first] = make_pair(make_pair(0, 0), 0); - if(pindexblock->vProposalVotes[i].second == VoteFlags::VOTE_YES) - mapCacheProposalsToUpdate[pindexblock->vProposalVotes[i].first].first.first += 1; - else if(pindexblock->vProposalVotes[i].second == VoteFlags::VOTE_ABSTAIN) - mapCacheProposalsToUpdate[pindexblock->vProposalVotes[i].first].second += 1; - else if(pindexblock->vProposalVotes[i].second == VoteFlags::VOTE_NO) - mapCacheProposalsToUpdate[pindexblock->vProposalVotes[i].first].first.second += 1; + if((*pVotes)[i].second == VoteFlags::VOTE_YES) + mapCacheProposalsToUpdate[(*pVotes)[i].first].first.first += 1; + else if((*pVotes)[i].second == VoteFlags::VOTE_ABSTAIN) + mapCacheProposalsToUpdate[(*pVotes)[i].first].second += 1; + else if((*pVotes)[i].second == VoteFlags::VOTE_NO) + mapCacheProposalsToUpdate[(*pVotes)[i].first].first.second += 1; - mapSeen[pindexblock->vProposalVotes[i].first]=true; + mapSeen[(*pVotes)[i].first]=true; + } } } - for(unsigned int i = 0; i < pindexblock->vPaymentRequestVotes.size(); i++) + auto prVotes = GetPaymentRequestVotes(pindexblock->GetBlockHash()); + if (prVotes != nullptr) { - if(mapSeen.count(pindexblock->vPaymentRequestVotes[i].first) == 0) + for(unsigned int i = 0; i < prVotes->size(); i++) { - LogPrint("daoextra", "%s: Found vote %d for payment request %s at block height %d\n", __func__, - pindexblock->vPaymentRequestVotes[i].second, pindexblock->vPaymentRequestVotes[i].first.ToString(), - pindexblock->nHeight); + if(mapSeen.count((*prVotes)[i].first) == 0) + { + LogPrint("daoextra", "%s: Found vote %d for payment request %s at block height %d\n", __func__, + (*prVotes)[i].second, (*prVotes)[i].first.ToString(), + pindexblock->nHeight); - if(mapCachePaymentRequestToUpdate.count(pindexblock->vPaymentRequestVotes[i].first) == 0) - mapCachePaymentRequestToUpdate[pindexblock->vPaymentRequestVotes[i].first] = make_pair(make_pair(0, 0), 0); + if(mapCachePaymentRequestToUpdate.count((*prVotes)[i].first) == 0) + mapCachePaymentRequestToUpdate[(*prVotes)[i].first] = make_pair(make_pair(0, 0), 0); - if(pindexblock->vPaymentRequestVotes[i].second == VoteFlags::VOTE_YES) - mapCachePaymentRequestToUpdate[pindexblock->vPaymentRequestVotes[i].first].first.first += 1; - else if(pindexblock->vPaymentRequestVotes[i].second == VoteFlags::VOTE_ABSTAIN) - mapCachePaymentRequestToUpdate[pindexblock->vPaymentRequestVotes[i].first].second += 1; - else if(pindexblock->vPaymentRequestVotes[i].second == VoteFlags::VOTE_NO) - mapCachePaymentRequestToUpdate[pindexblock->vPaymentRequestVotes[i].first].first.second += 1; + if((*prVotes)[i].second == VoteFlags::VOTE_YES) + mapCachePaymentRequestToUpdate[(*prVotes)[i].first].first.first += 1; + else if((*prVotes)[i].second == VoteFlags::VOTE_ABSTAIN) + mapCachePaymentRequestToUpdate[(*prVotes)[i].first].second += 1; + else if((*prVotes)[i].second == VoteFlags::VOTE_NO) + mapCachePaymentRequestToUpdate[(*prVotes)[i].first].first.second += 1; - mapSeen[pindexblock->vPaymentRequestVotes[i].first]=true; + mapSeen[(*prVotes)[i].first]=true; + } } } } if (fDAOConsultations) { - for (auto& it: pindexblock->mapSupport) - { - if (!it.second) - continue; + auto supp = GetSupport(pindexblock->GetBlockHash()); - if (!mapSeenSupport.count(it.first)) + if (supp != nullptr) + { + for (auto& it: *supp) { - LogPrint("daoextra", "%s: Found support vote for %s at block height %d\n", __func__, - it.first.ToString(), - pindexblock->nHeight); + if (!it.second) + continue; - if(mapCacheSupportToUpdate.count(it.first) == 0) - mapCacheSupportToUpdate[it.first] = 0; + if (!mapSeenSupport.count(it.first)) + { + LogPrint("daoextra", "%s: Found support vote for %s at block height %d\n", __func__, + it.first.ToString(), + pindexblock->nHeight); - mapCacheSupportToUpdate[it.first] += 1; - mapSeenSupport[it.first]=true; + if(mapCacheSupportToUpdate.count(it.first) == 0) + mapCacheSupportToUpdate[it.first] = 0; + + mapCacheSupportToUpdate[it.first] += 1; + mapSeenSupport[it.first]=true; + } } } - for (auto&it: pindexblock->mapConsultationVotes) - { - if (mapSeen.count(it.first)) - continue; + auto cVotes = GetConsultationVotes(pindexblock->GetBlockHash()); - if (view.HaveConsultation(it.first) || view.HaveConsultationAnswer(it.first)) + if (cVotes != nullptr) + { + for (auto&it: *cVotes) { + if (mapSeen.count(it.first)) + continue; - if (it.second == VoteFlags::VOTE_ABSTAIN && view.GetConsultationAnswer(it.first, answer)) + if (view.HaveConsultation(it.first) || view.HaveConsultationAnswer(it.first)) { - if(mapCacheConsultationToUpdate.count(std::make_pair(answer.parent,it.second)) == 0) - mapCacheConsultationToUpdate[std::make_pair(answer.parent,it.second)] = 0; - mapCacheConsultationToUpdate[std::make_pair(answer.parent,it.second)] += 1; + if (it.second == VoteFlags::VOTE_ABSTAIN && view.GetConsultationAnswer(it.first, answer)) + { + if(mapCacheConsultationToUpdate.count(std::make_pair(answer.parent,it.second)) == 0) + mapCacheConsultationToUpdate[std::make_pair(answer.parent,it.second)] = 0; - mapSeen[it.first]=true; + mapCacheConsultationToUpdate[std::make_pair(answer.parent,it.second)] += 1; - LogPrint("daoextra", "%s: Found consultation answer vote %d for %s at block height %d (total %d)\n", __func__, - it.second, answer.parent.ToString(), pindexblock->nHeight, mapCacheConsultationToUpdate[std::make_pair(answer.parent,it.second)]); - } - else - { - if(mapCacheConsultationToUpdate.count(std::make_pair(it.first,it.second)) == 0) - mapCacheConsultationToUpdate[std::make_pair(it.first,it.second)] = 0; + mapSeen[it.first]=true; - mapCacheConsultationToUpdate[std::make_pair(it.first,it.second)] += 1; + LogPrint("daoextra", "%s: Found consultation answer vote %d for %s at block height %d (total %d)\n", __func__, + it.second, answer.parent.ToString(), pindexblock->nHeight, mapCacheConsultationToUpdate[std::make_pair(answer.parent,it.second)]); + } + else + { + if(mapCacheConsultationToUpdate.count(std::make_pair(it.first,it.second)) == 0) + mapCacheConsultationToUpdate[std::make_pair(it.first,it.second)] = 0; - mapSeen[it.first]=true; + mapCacheConsultationToUpdate[std::make_pair(it.first,it.second)] += 1; - LogPrint("daoextra", "%s: Found consultation vote %d for %s at block height %d (total %d)\n", __func__, - it.second, it.first.ToString(), pindexblock->nHeight, mapCacheConsultationToUpdate[std::make_pair(it.first,it.second)]); + mapSeen[it.first]=true; + + LogPrint("daoextra", "%s: Found consultation vote %d for %s at block height %d (total %d)\n", __func__, + it.second, it.first.ToString(), pindexblock->nHeight, mapCacheConsultationToUpdate[std::make_pair(it.first,it.second)]); + } } } } diff --git a/src/main.cpp b/src/main.cpp index 22bd80b19..75dbcf090 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -67,6 +67,10 @@ using namespace std; CCriticalSection cs_main; BlockMap mapBlockIndex; +std::map>> vProposalVotes; +std::map>> vPaymentRequestVotes; +std::map> mapSupport; +std::map> mapConsultationVotes; CChain chainActive; CBlockIndex *pindexBestHeader = nullptr; int64_t nTimeBestReceived = 0; @@ -99,8 +103,6 @@ uint256 hashBestChain = uint256(); CBlockIndex* pindexBest = nullptr; CBlockIndex* pindexVerifyChainTip = nullptr; -set > setStakeSeen; - CTxMemPool mempool(::minRelayTxFee); FeeFilterRounder filterRounder(::minRelayTxFee); CTxMemPool stempool(::minRelayTxFee); @@ -131,9 +133,6 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned static void CheckBlockIndex(const Consensus::Params& consensusParams); /* Proof of Stake constants */ - -extern std::set > setStakeSeen; - arith_uint256 bnProofOfStakeLimit(~arith_uint256() >> 20); arith_uint256 bnProofOfStakeLimitV2(~arith_uint256() >> 20); @@ -2699,90 +2698,107 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI std::map vSeen; - for(unsigned int i = 0; i < pindex->vProposalVotes.size(); i++) + auto pVotes = GetProposalVotes(block.GetHash()); + auto prVotes = GetPaymentRequestVotes(block.GetHash()); + auto supp = GetSupport(block.GetHash()); + auto cVotes = GetConsultationVotes(block.GetHash()); + + if (pVotes != nullptr) { - if(!view.HaveProposal(pindex->vProposalVotes[i].first)) - continue; + for(unsigned int i = 0; i < pVotes->size(); i++) + { + if(!view.HaveProposal((*pVotes)[i].first)) + continue; - CProposalModifier proposal = view.ModifyProposal(pindex->vProposalVotes[i].first, pindex->nHeight); + CProposalModifier proposal = view.ModifyProposal((*pVotes)[i].first, pindex->nHeight); - if(vSeen.count(proposal->hash) == 0) - { - if(pindex->vProposalVotes[i].second == VoteFlags::VOTE_YES) - proposal->nVotesYes = max(proposal->nVotesYes - 1, 0); - else if(pindex->vProposalVotes[i].second == VoteFlags::VOTE_ABSTAIN) - proposal->nVotesAbs = max(proposal->nVotesAbs - 1, 0); - else if(pindex->vProposalVotes[i].second == VoteFlags::VOTE_NO) - proposal->nVotesNo = max(proposal->nVotesNo - 1, 0); + if(vSeen.count(proposal->hash) == 0) + { + if((*pVotes)[i].second == VoteFlags::VOTE_YES) + proposal->nVotesYes = max(proposal->nVotesYes - 1, 0); + else if((*pVotes)[i].second == VoteFlags::VOTE_ABSTAIN) + proposal->nVotesAbs = max(proposal->nVotesAbs - 1, 0); + else if((*pVotes)[i].second == VoteFlags::VOTE_NO) + proposal->nVotesNo = max(proposal->nVotesNo - 1, 0); - proposal->fDirty = true; + proposal->fDirty = true; - vSeen[pindex->vProposalVotes[i].first]=true; + vSeen[(*pVotes)[i].first]=true; + } } } - for(unsigned int i = 0; i < pindex->vPaymentRequestVotes.size(); i++) + if (prVotes != nullptr) { - if(!view.HavePaymentRequest(pindex->vPaymentRequestVotes[i].first)) - continue; + for(unsigned int i = 0; i < prVotes->size(); i++) + { + if(!view.HavePaymentRequest((*prVotes)[i].first)) + continue; - CPaymentRequestModifier prequest = view.ModifyPaymentRequest(pindex->vPaymentRequestVotes[i].first, pindex->nHeight); + CPaymentRequestModifier prequest = view.ModifyPaymentRequest((*prVotes)[i].first, pindex->nHeight); - if(vSeen.count(prequest->hash) == 0) - { - if(pindex->vPaymentRequestVotes[i].second == VoteFlags::VOTE_YES) - prequest->nVotesYes = max(prequest->nVotesYes - 1, 0); - else if(pindex->vPaymentRequestVotes[i].second == VoteFlags::VOTE_ABSTAIN) - prequest->nVotesAbs = max(prequest->nVotesAbs - 1, 0); - else if(pindex->vPaymentRequestVotes[i].second == VoteFlags::VOTE_NO) - prequest->nVotesNo = max(prequest->nVotesNo - 1, 0); + if(vSeen.count(prequest->hash) == 0) + { + if((*prVotes)[i].second == VoteFlags::VOTE_YES) + prequest->nVotesYes = max(prequest->nVotesYes - 1, 0); + else if((*prVotes)[i].second == VoteFlags::VOTE_ABSTAIN) + prequest->nVotesAbs = max(prequest->nVotesAbs - 1, 0); + else if((*prVotes)[i].second == VoteFlags::VOTE_NO) + prequest->nVotesNo = max(prequest->nVotesNo - 1, 0); - prequest->fDirty = true; + prequest->fDirty = true; - vSeen[pindex->vPaymentRequestVotes[i].first]=true; + vSeen[(*prVotes)[i].first]=true; + } } } - for (auto &it: pindex->mapSupport) + if (supp != nullptr) { - if (view.HaveConsultation(it.first)) + for (auto &it: *supp) { - if(vSeen.count(it.first) == 0) + if (view.HaveConsultation(it.first)) { - CConsultationModifier consultation = view.ModifyConsultation(it.first, pindex->nHeight); - consultation->nSupport = max(consultation->nSupport - 1, 0); - consultation->fDirty = true; - vSeen[it.first] = true; + if(vSeen.count(it.first) == 0) + { + CConsultationModifier consultation = view.ModifyConsultation(it.first, pindex->nHeight); + consultation->nSupport = max(consultation->nSupport - 1, 0); + consultation->fDirty = true; + vSeen[it.first] = true; + } } - } - else if (view.HaveConsultationAnswer(it.first)) - { - if(vSeen.count(it.first) == 0) + else if (view.HaveConsultationAnswer(it.first)) { - CConsultationAnswerModifier answer = view.ModifyConsultationAnswer(it.first, pindex->nHeight); - answer->nSupport = max(answer->nSupport - 1, 0); - answer->fDirty = true; - vSeen[it.first] = true; + if(vSeen.count(it.first) == 0) + { + CConsultationAnswerModifier answer = view.ModifyConsultationAnswer(it.first, pindex->nHeight); + answer->nSupport = max(answer->nSupport - 1, 0); + answer->fDirty = true; + vSeen[it.first] = true; + } } } } - for (auto &it: pindex->mapConsultationVotes) + if (cVotes != nullptr) { - if (view.HaveConsultation(it.first)) + for (auto &it: *cVotes) { - CConsultationModifier mConsultation = view.ModifyConsultation(it.first, pindex->nHeight); - if (mConsultation->mapVotes[it.second] == 1) - mConsultation->mapVotes.erase(it.second); - else - mConsultation->mapVotes[it.second] = max(mConsultation->mapVotes[it.second] - (uint64_t)1, (uint64_t)0); - mConsultation->fDirty = true; - } - else if (view.HaveConsultationAnswer(it.first)) - { - CConsultationAnswerModifier mConsultationAnswer = view.ModifyConsultationAnswer(it.first, pindex->nHeight); - mConsultationAnswer->nVotes = max(mConsultationAnswer->nVotes - (uint64_t)1, (uint64_t)0); - mConsultationAnswer->fDirty = true; + if (view.HaveConsultation(it.first)) + { + CConsultationModifier mConsultation = view.ModifyConsultation(it.first, pindex->nHeight); + if (mConsultation->mapVotes[it.second] == 1) + mConsultation->mapVotes.erase(it.second); + else + mConsultation->mapVotes[it.second] = max(mConsultation->mapVotes[it.second] - (uint64_t)1, (uint64_t)0); + mConsultation->fDirty = true; + } + else if (view.HaveConsultationAnswer(it.first)) + { + CConsultationAnswerModifier mConsultationAnswer = view.ModifyConsultationAnswer(it.first, pindex->nHeight); + mConsultationAnswer->nVotes = max(mConsultationAnswer->nVotes - (uint64_t)1, (uint64_t)0); + mConsultationAnswer->fDirty = true; + } } } @@ -3194,20 +3210,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin pindex->nCFSupply = pindex->pprev != NULL ? pindex->pprev->nCFSupply : 0; pindex->nCFLocked = pindex->pprev != NULL ? pindex->pprev->nCFLocked : 0; - pindex->vProposalVotes.clear(); - pindex->vPaymentRequestVotes.clear(); - pindex->mapConsultationVotes.clear(); - if (block.IsProofOfStake()) { pindex->SetProofOfStake(); - pindex->prevoutStake = block.vtx[1].vin[0].prevout; - pindex->nStakeTime = block.vtx[1].nTime; - } - else - { - pindex->prevoutStake.SetNull(); - pindex->nStakeTime = 0; } int64_t nTimeStart = GetTimeMicros(); @@ -3231,9 +3236,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return true; } - if (pindex->IsProofOfStake()) - setStakeSeen.insert(make_pair(pindex->prevoutStake, pindex->nStakeTime)); - // Check proof of stake if (block.nBits != GetNextTargetRequired(pindex->pprev, block.IsProofOfStake())){ return state.DoS(1,error("ContextualCheckBlock() : incorrect %s at height %d (%d)", !block.IsProofOfStake() ? "proof-of-work" : "proof-of-stake",pindex->pprev->nHeight, block.nBits), REJECT_INVALID, "bad-diffbits"); @@ -3532,26 +3534,26 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (fCFund && (fProposal && view.GetProposal(hash, proposal) && proposal.CanVote(view))) { LogPrint("daoextra", "%s: Adding vote at height %d - hash: %s vote: %d\n", __func__, pindex->nHeight, hash.ToString(), vote); - pindex->vProposalVotes.push_back(make_pair(hash, vote)); + InsertProposalVotes(block.GetHash())->push_back(make_pair(hash, vote)); } else if (fCFund && (fPaymentRequest && view.GetPaymentRequest(hash, prequest) && prequest.CanVote(view))) { LogPrint("daoextra", "%s: Adding vote at height %d - hash: %s vote: %d\n", __func__, pindex->nHeight, hash.ToString(), vote); - pindex->vPaymentRequestVotes.push_back(make_pair(hash, vote)); + InsertPaymentRequestVotes(block.GetHash())->push_back(make_pair(hash, vote)); } else if(fDAOConsultations && fSupport && ((view.GetConsultation(hash, consultation) && consultation.CanBeSupported()) || (view.GetConsultationAnswer(hash, answer) && answer.CanBeSupported(view)))) { LogPrint("daoextra", "%s: Adding support vote at height %d - hash: %s\n", __func__, pindex->nHeight, hash.ToString()); - pindex->mapSupport.insert(make_pair(hash, true)); + InsertSupport(block.GetHash())->insert(make_pair(hash, true)); } else if (fDAOConsultations && fConsultation && !fSupport && vote != VoteFlags::VOTE_REMOVE) { if ((view.GetConsultation(hash, consultation) && (consultation.CanBeVoted(vote) && consultation.IsValidVote(vote)))) { LogPrint("daoextra", "%s: Adding consultation vote at height %d - hash: %s vote: %d\n", __func__, pindex->nHeight, hash.ToString(), vote); - pindex->mapConsultationVotes.insert(make_pair(hash, vote)); + InsertConsultationVotes(block.GetHash())->insert(make_pair(hash, vote)); } else { @@ -3564,7 +3566,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (mapCountAnswers[answer.parent] > mapCacheMaxAnswers[answer.parent]) continue; LogPrint("daoextra", "%s: Adding consultation answer vote at height %d - hash: %s vote: %d\n", __func__, pindex->nHeight, hash.ToString(), vote); - pindex->mapConsultationVotes.insert(make_pair(hash, vote)); + InsertConsultationVotes(block.GetHash())->insert(make_pair(hash, vote)); } else { @@ -3942,12 +3944,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (fCFund && view.GetProposal(it.first, proposal) && proposal.CanVote(view)) { - pindex->vProposalVotes.push_back(make_pair(it.first, val)); + InsertProposalVotes(block.GetHash())->push_back(make_pair(it.first, val)); LogPrint("daoextra", "%s: Inserting vote for staker %s in block index %d - proposal hash: %s vote: %d\n", __func__, HexStr(stakerScript), pindex->nHeight, it.first.ToString(), val); } else if (fCFund && view.GetPaymentRequest(it.first, prequest) && prequest.CanVote(view)) { - pindex->vPaymentRequestVotes.push_back(make_pair(it.first, val)); + InsertPaymentRequestVotes(block.GetHash())->push_back(make_pair(it.first, val)); LogPrint("daoextra", "%s: Inserting vote for staker %s in block index %d - payment request hash: %s vote: %d\n", __func__, HexStr(stakerScript), pindex->nHeight, it.first.ToString(), val); } else if (val == VoteFlags::SUPPORT) @@ -3956,7 +3958,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin ((view.GetConsultation(it.first, consultation) && consultation.CanBeSupported()) || (view.GetConsultationAnswer(it.first, answer) && answer.CanBeSupported(view)))) { - pindex->mapSupport.insert(make_pair(it.first, true)); + InsertSupport(block.GetHash())->insert(make_pair(it.first, true)); LogPrint("daoextra", "%s: Inserting vote for staker %s in block index %d - hash: %s vote: support\n", __func__, HexStr(stakerScript), pindex->nHeight, it.first.ToString()); } } @@ -3965,7 +3967,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if ((view.GetConsultation(it.first, consultation) && (consultation.CanBeVoted(val) && consultation.IsValidVote(val)))) { LogPrint("daoextra", "%s: Inserting consultation vote for staker %s in block index %d - hash: %s vote: %d\n", __func__, HexStr(stakerScript), pindex->nHeight, it.first.ToString(), val); - pindex->mapConsultationVotes.insert(make_pair(it.first, val)); + InsertConsultationVotes(block.GetHash())->insert(make_pair(it.first, val)); } else { @@ -3981,7 +3983,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin continue; } LogPrint("daoextra", "%s: Inserting consultation answer vote for staker %s in block index %d - hash: %s vote: %d\n", __func__, HexStr(stakerScript), pindex->nHeight, it.first.ToString(), val); - pindex->mapConsultationVotes.insert(make_pair(it.first, val)); + InsertConsultationVotes(block.GetHash())->insert(make_pair(it.first, val)); } else { @@ -5881,7 +5883,7 @@ CBlockIndex * InsertBlockIndex(uint256 hash) bool static LoadBlockIndexDB() { const CChainParams& chainparams = Params(); - if (!pblocktree->LoadBlockIndexGuts(InsertBlockIndex)) + if (!pblocktree->LoadBlockIndexGuts(InsertBlockIndex, InsertProposalVotes, InsertPaymentRequestVotes, InsertSupport, InsertConsultationVotes)) return false; boost::this_thread::interruption_point(); @@ -9791,3 +9793,55 @@ static void CheckDandelionEmbargoes() } } } + +std::vector>* GetProposalVotes(const uint256& hash) +{ + if (vProposalVotes.count(hash) == 0) + return nullptr; + + return InsertProposalVotes(hash); +} + +std::vector>* GetPaymentRequestVotes(const uint256& hash) +{ + if (vPaymentRequestVotes.count(hash) == 0) + return nullptr; + + return InsertPaymentRequestVotes(hash); +} + +std::map* GetSupport(const uint256& hash) +{ + if (mapSupport.count(hash) == 0) + return nullptr; + + return InsertSupport(hash); +} + +std::map* GetConsultationVotes(const uint256& hash) +{ + if (mapConsultationVotes.count(hash) == 0) + return nullptr; + + return InsertConsultationVotes(hash); +} + +std::vector>* InsertProposalVotes(const uint256& hash) +{ + return &vProposalVotes[hash]; +} + +std::vector>* InsertPaymentRequestVotes(const uint256& hash) +{ + return &vPaymentRequestVotes[hash]; +} + +std::map* InsertSupport(const uint256& hash) +{ + return &mapSupport[hash]; +} + +std::map* InsertConsultationVotes(const uint256& hash) +{ + return &mapConsultationVotes[hash]; +} diff --git a/src/main.h b/src/main.h index ca87c76a3..c7f3fb237 100644 --- a/src/main.h +++ b/src/main.h @@ -186,6 +186,10 @@ extern CTxMemPool mempool; extern CTxMemPool stempool; typedef boost::unordered_map BlockMap; extern BlockMap mapBlockIndex; +extern std::map>> vProposalVotes; +extern std::map>> vPaymentRequestVotes; +extern std::map> mapSupport; +extern std::map> mapConsultationVotes; extern uint64_t nLastBlockTx; extern uint64_t nLastBlockSize; extern uint64_t nLastBlockWeight; @@ -673,4 +677,13 @@ uint64_t GetStakingRewardPerBlock(const CStateViewCache& view); static void RelayDandelionTransaction(const CTransaction& tx, CNode* pfrom); static void CheckDandelionEmbargoes(); +std::vector>* GetProposalVotes(const uint256& hash); +std::vector>* GetPaymentRequestVotes(const uint256& hash); +std::map* GetSupport(const uint256& hash); +std::map* GetConsultationVotes(const uint256& hash); +std::vector>* InsertProposalVotes(const uint256& hash); +std::vector>* InsertPaymentRequestVotes(const uint256& hash); +std::map* InsertSupport(const uint256& hash); +std::map* InsertConsultationVotes(const uint256& hash); + #endif // NAVCOIN_MAIN_H diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 2296b3299..67bf9da66 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -66,39 +66,55 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) result.pushKV("modifier", strprintf("%016x", blockindex->nStakeModifier)); UniValue votes(UniValue::VARR); - for (auto& it: blockindex->vProposalVotes) + auto pVotes = GetProposalVotes(blockindex->GetBlockHash()); + if (pVotes != nullptr) { - UniValue entry(UniValue::VOBJ); - entry.pushKV("hash", it.first.ToString()); - entry.pushKV("vote", it.second); - votes.push_back(entry); + for (auto& it: *pVotes) + { + UniValue entry(UniValue::VOBJ); + entry.pushKV("hash", it.first.ToString()); + entry.pushKV("vote", it.second); + votes.push_back(entry); + } } result.pushKV("cfund_votes", votes); UniValue votes_pr(UniValue::VARR); - for (auto& it: blockindex->vPaymentRequestVotes) + auto prVotes = GetPaymentRequestVotes(blockindex->GetBlockHash()); + if (prVotes != nullptr) { - UniValue entry(UniValue::VOBJ); - entry.pushKV("hash", it.first.ToString()); - entry.pushKV("vote", it.second); - votes_pr.push_back(entry); + for (auto& it: *prVotes) + { + UniValue entry(UniValue::VOBJ); + entry.pushKV("hash", it.first.ToString()); + entry.pushKV("vote", it.second); + votes_pr.push_back(entry); + } } result.pushKV("cfund_request_votes", votes_pr); UniValue daosupport(UniValue::VARR); - for (auto& it: blockindex->mapSupport) + auto supp = GetSupport(blockindex->GetBlockHash()); + if (supp != nullptr) { - daosupport.push_back(it.first.ToString()); + for (auto& it: *supp) + { + daosupport.push_back(it.first.ToString()); + } } result.pushKV("dao_support", daosupport); UniValue daovotes(UniValue::VARR); - for (auto& it: blockindex->mapConsultationVotes) + auto cVotes = GetConsultationVotes(blockindex->GetBlockHash()); + if (cVotes != nullptr) { - UniValue entry(UniValue::VOBJ); - entry.pushKV("hash", it.first.ToString()); - entry.pushKV("vote", it.second); - daovotes.push_back(entry); + for (auto& it: *cVotes) + { + UniValue entry(UniValue::VOBJ); + entry.pushKV("hash", it.first.ToString()); + entry.pushKV("vote", it.second); + daovotes.push_back(entry); + } } result.pushKV("dao_votes", daovotes); @@ -316,14 +332,14 @@ UniValue getblockcount(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( - "getblockcount\n" - "\nReturns the number of blocks in the longest block chain.\n" - "\nResult:\n" - "n (numeric) The current block count\n" - "\nExamples:\n" - + HelpExampleCli("getblockcount", "") - + HelpExampleRpc("getblockcount", "") - ); + "getblockcount\n" + "\nReturns the number of blocks in the longest block chain.\n" + "\nResult:\n" + "n (numeric) The current block count\n" + "\nExamples:\n" + + HelpExampleCli("getblockcount", "") + + HelpExampleRpc("getblockcount", "") + ); LOCK(cs_main); return chainActive.Height(); @@ -333,14 +349,14 @@ UniValue getbestblockhash(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( - "getbestblockhash\n" - "\nReturns the hash of the best (tip) block in the longest block chain.\n" - "\nResult\n" - "\"hex\" (string) the block hash hex encoded\n" - "\nExamples\n" - + HelpExampleCli("getbestblockhash", "") - + HelpExampleRpc("getbestblockhash", "") - ); + "getbestblockhash\n" + "\nReturns the hash of the best (tip) block in the longest block chain.\n" + "\nResult\n" + "\"hex\" (string) the block hash hex encoded\n" + "\nExamples\n" + + HelpExampleCli("getbestblockhash", "") + + HelpExampleRpc("getbestblockhash", "") + ); LOCK(cs_main); return chainActive.Tip()->GetBlockHash().GetHex(); @@ -350,14 +366,14 @@ UniValue getdifficulty(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( - "getdifficulty\n" - "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n" - "\nResult:\n" - "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n" - "\nExamples:\n" - + HelpExampleCli("getdifficulty", "") - + HelpExampleRpc("getdifficulty", "") - ); + "getdifficulty\n" + "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n" + "\nResult:\n" + "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n" + "\nExamples:\n" + + HelpExampleCli("getdifficulty", "") + + HelpExampleRpc("getdifficulty", "") + ); LOCK(cs_main); return GetDifficulty(); @@ -367,20 +383,20 @@ std::string EntryDescriptionString() { return " \"size\" : n, (numeric) transaction size in bytes\n" " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" - " \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority\n" - " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" - " \"height\" : n, (numeric) block height when transaction entered pool\n" - " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n" - " \"currentpriority\" : n, (numeric) transaction priority now\n" - " \"descendantcount\" : n, (numeric) number of in-mempool descendant transactions (including this one)\n" - " \"descendantsize\" : n, (numeric) size of in-mempool descendants (including this one)\n" - " \"descendantfees\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one)\n" - " \"ancestorcount\" : n, (numeric) number of in-mempool ancestor transactions (including this one)\n" - " \"ancestorsize\" : n, (numeric) size of in-mempool ancestors (including this one)\n" - " \"ancestorfees\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one)\n" - " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" - " \"transactionid\", (string) parent transaction id\n" - " ... ]\n"; + " \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority\n" + " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" + " \"height\" : n, (numeric) block height when transaction entered pool\n" + " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n" + " \"currentpriority\" : n, (numeric) transaction priority now\n" + " \"descendantcount\" : n, (numeric) number of in-mempool descendant transactions (including this one)\n" + " \"descendantsize\" : n, (numeric) size of in-mempool descendants (including this one)\n" + " \"descendantfees\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one)\n" + " \"ancestorcount\" : n, (numeric) number of in-mempool ancestor transactions (including this one)\n" + " \"ancestorsize\" : n, (numeric) size of in-mempool ancestors (including this one)\n" + " \"ancestorfees\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one)\n" + " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" + " \"transactionid\", (string) parent transaction id\n" + " ... ]\n"; } void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) @@ -449,25 +465,25 @@ UniValue getrawmempool(const UniValue& params, bool fHelp) { if (fHelp || params.size() > 1) throw runtime_error( - "getrawmempool ( verbose )\n" - "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" - "\nArguments:\n" - "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" - "\nResult: (for verbose = false):\n" - "[ (json array of string)\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - "]\n" - "\nResult: (for verbose = true):\n" - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - + EntryDescriptionString() - + " }, ...\n" - "}\n" - "\nExamples\n" - + HelpExampleCli("getrawmempool", "true") - + HelpExampleRpc("getrawmempool", "true") - ); + "getrawmempool ( verbose )\n" + "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" + "\nArguments:\n" + "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" + "\nResult: (for verbose = false):\n" + "[ (json array of string)\n" + " \"transactionid\" (string) The transaction id\n" + " ,...\n" + "]\n" + "\nResult: (for verbose = true):\n" + "{ (json object)\n" + " \"transactionid\" : { (json object)\n" + + EntryDescriptionString() + + " }, ...\n" + "}\n" + "\nExamples\n" + + HelpExampleCli("getrawmempool", "true") + + HelpExampleRpc("getrawmempool", "true") + ); bool fVerbose = false; if (params.size() > 0) @@ -480,26 +496,26 @@ UniValue getmempoolancestors(const UniValue& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) { throw runtime_error( - "getmempoolancestors txid (verbose)\n" - "\nIf txid is in the mempool, returns all in-mempool ancestors.\n" - "\nArguments:\n" - "1. \"txid\" (string, required) The transaction id (must be in mempool)\n" - "2. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" - "\nResult (for verbose=false):\n" - "[ (json array of strings)\n" - " \"transactionid\" (string) The transaction id of an in-mempool ancestor transaction\n" - " ,...\n" - "]\n" - "\nResult (for verbose=true):\n" - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - + EntryDescriptionString() - + " }, ...\n" - "}\n" - "\nExamples\n" - + HelpExampleCli("getmempoolancestors", "\"mytxid\"") - + HelpExampleRpc("getmempoolancestors", "\"mytxid\"") - ); + "getmempoolancestors txid (verbose)\n" + "\nIf txid is in the mempool, returns all in-mempool ancestors.\n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id (must be in mempool)\n" + "2. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" + "\nResult (for verbose=false):\n" + "[ (json array of strings)\n" + " \"transactionid\" (string) The transaction id of an in-mempool ancestor transaction\n" + " ,...\n" + "]\n" + "\nResult (for verbose=true):\n" + "{ (json object)\n" + " \"transactionid\" : { (json object)\n" + + EntryDescriptionString() + + " }, ...\n" + "}\n" + "\nExamples\n" + + HelpExampleCli("getmempoolancestors", "\"mytxid\"") + + HelpExampleRpc("getmempoolancestors", "\"mytxid\"") + ); } bool fVerbose = false; @@ -544,26 +560,26 @@ UniValue getmempooldescendants(const UniValue& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) { throw runtime_error( - "getmempooldescendants txid (verbose)\n" - "\nIf txid is in the mempool, returns all in-mempool descendants.\n" - "\nArguments:\n" - "1. \"txid\" (string, required) The transaction id (must be in mempool)\n" - "2. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" - "\nResult (for verbose=false):\n" - "[ (json array of strings)\n" - " \"transactionid\" (string) The transaction id of an in-mempool descendant transaction\n" - " ,...\n" - "]\n" - "\nResult (for verbose=true):\n" - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - + EntryDescriptionString() - + " }, ...\n" - "}\n" - "\nExamples\n" - + HelpExampleCli("getmempooldescendants", "\"mytxid\"") - + HelpExampleRpc("getmempooldescendants", "\"mytxid\"") - ); + "getmempooldescendants txid (verbose)\n" + "\nIf txid is in the mempool, returns all in-mempool descendants.\n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id (must be in mempool)\n" + "2. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" + "\nResult (for verbose=false):\n" + "[ (json array of strings)\n" + " \"transactionid\" (string) The transaction id of an in-mempool descendant transaction\n" + " ,...\n" + "]\n" + "\nResult (for verbose=true):\n" + "{ (json object)\n" + " \"transactionid\" : { (json object)\n" + + EntryDescriptionString() + + " }, ...\n" + "}\n" + "\nExamples\n" + + HelpExampleCli("getmempooldescendants", "\"mytxid\"") + + HelpExampleRpc("getmempooldescendants", "\"mytxid\"") + ); } bool fVerbose = false; @@ -608,18 +624,18 @@ UniValue getmempoolentry(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) { throw runtime_error( - "getmempoolentry txid\n" - "\nReturns mempool data for given transaction\n" - "\nArguments:\n" - "1. \"txid\" (string, required) The transaction id (must be in mempool)\n" - "\nResult:\n" - "{ (json object)\n" - + EntryDescriptionString() - + "}\n" - "\nExamples\n" - + HelpExampleCli("getmempoolentry", "\"mytxid\"") - + HelpExampleRpc("getmempoolentry", "\"mytxid\"") - ); + "getmempoolentry txid\n" + "\nReturns mempool data for given transaction\n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id (must be in mempool)\n" + "\nResult:\n" + "{ (json object)\n" + + EntryDescriptionString() + + "}\n" + "\nExamples\n" + + HelpExampleCli("getmempoolentry", "\"mytxid\"") + + HelpExampleRpc("getmempoolentry", "\"mytxid\"") + ); } uint256 hash = ParseHashV(params[0], "parameter 1"); @@ -664,31 +680,31 @@ UniValue getblockhashes(const UniValue& params, bool fHelp) { if (fHelp || params.size() < 2) throw runtime_error( - "getblockhashes timestamp\n" - "\nReturns array of hashes of blocks within the timestamp range provided.\n" - "\nArguments:\n" - "1. high (numeric, required) The newer block timestamp\n" - "2. low (numeric, required) The older block timestamp\n" - "3. options (string, required) A json object\n" - " {\n" - " \"noOrphans\":true (boolean) will only include blocks on the main chain\n" - " \"logicalTimes\":true (boolean) will include logical timestamps with hashes\n" - " }\n" - "\nResult:\n" - "[\n" - " \"hash\" (string) The block hash\n" - "]\n" - "[\n" - " {\n" - " \"blockhash\": (string) The block hash\n" - " \"logicalts\": (numeric) The logical timestamp\n" - " }\n" - "]\n" - "\nExamples:\n" - + HelpExampleCli("getblockhashes", "1231614698 1231024505") - + HelpExampleRpc("getblockhashes", "1231614698, 1231024505") - + HelpExampleCli("getblockhashes", "1231614698 1231024505 '{\"noOrphans\":false, \"logicalTimes\":true}'") - ); + "getblockhashes timestamp\n" + "\nReturns array of hashes of blocks within the timestamp range provided.\n" + "\nArguments:\n" + "1. high (numeric, required) The newer block timestamp\n" + "2. low (numeric, required) The older block timestamp\n" + "3. options (string, required) A json object\n" + " {\n" + " \"noOrphans\":true (boolean) will only include blocks on the main chain\n" + " \"logicalTimes\":true (boolean) will include logical timestamps with hashes\n" + " }\n" + "\nResult:\n" + "[\n" + " \"hash\" (string) The block hash\n" + "]\n" + "[\n" + " {\n" + " \"blockhash\": (string) The block hash\n" + " \"logicalts\": (numeric) The logical timestamp\n" + " }\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("getblockhashes", "1231614698 1231024505") + + HelpExampleRpc("getblockhashes", "1231614698, 1231024505") + + HelpExampleCli("getblockhashes", "1231614698 1231024505 '{\"noOrphans\":false, \"logicalTimes\":true}'") + ); unsigned int high = params[0].get_int(); unsigned int low = params[1].get_int(); @@ -737,16 +753,16 @@ UniValue getblockhash(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( - "getblockhash index\n" - "\nReturns hash of block in best-block-chain at index provided.\n" - "\nArguments:\n" - "1. index (numeric, required) The block index\n" - "\nResult:\n" - "\"hash\" (string) The block hash\n" - "\nExamples:\n" - + HelpExampleCli("getblockhash", "1000") - + HelpExampleRpc("getblockhash", "1000") - ); + "getblockhash index\n" + "\nReturns hash of block in best-block-chain at index provided.\n" + "\nArguments:\n" + "1. index (numeric, required) The block index\n" + "\nResult:\n" + "\"hash\" (string) The block hash\n" + "\nExamples:\n" + + HelpExampleCli("getblockhash", "1000") + + HelpExampleRpc("getblockhash", "1000") + ); LOCK(cs_main); @@ -762,35 +778,35 @@ UniValue getblockheader(const UniValue& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "getblockheader \"hash\" ( verbose )\n" - "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" - "If verbose is true, returns an Object with information about blockheader .\n" - "\nArguments:\n" - "1. \"hash\" (string, required) The block hash\n" - "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" - "\nResult (for verbose = true):\n" - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"version\" : n, (numeric) The block version\n" - " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\", (string) The hash of the next block\n" - " \"chainwork\" : \"0000...1f3\" (string) Expected number of hashes required to produce the current chain (in hex)\n" - "}\n" - "\nResult (for verbose=false):\n" - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - "\nExamples:\n" - + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - ); + "getblockheader \"hash\" ( verbose )\n" + "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" + "If verbose is true, returns an Object with information about blockheader .\n" + "\nArguments:\n" + "1. \"hash\" (string, required) The block hash\n" + "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" + "\nResult (for verbose = true):\n" + "{\n" + " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" + " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" + " \"height\" : n, (numeric) The block height or index\n" + " \"version\" : n, (numeric) The block version\n" + " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" + " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" + " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"nonce\" : n, (numeric) The nonce\n" + " \"bits\" : \"1d00ffff\", (string) The bits\n" + " \"difficulty\" : x.xxx, (numeric) The difficulty\n" + " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" + " \"nextblockhash\" : \"hash\", (string) The hash of the next block\n" + " \"chainwork\" : \"0000...1f3\" (string) Expected number of hashes required to produce the current chain (in hex)\n" + "}\n" + "\nResult (for verbose=false):\n" + "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" + "\nExamples:\n" + + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + ); LOCK(cs_main); @@ -821,42 +837,42 @@ UniValue getblock(const UniValue& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "getblock \"hash\" ( verbose )\n" - "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.\n" - "If verbose is true, returns an Object with information about block .\n" - "\nArguments:\n" - "1. \"hash\" (string, required) The block hash\n" - "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" - "\nResult (for verbose = true):\n" - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"size\" : n, (numeric) The block size\n" - " \"strippedsize\" : n, (numeric) The block size excluding witness data\n" - " \"weight\" : n (numeric) The block weight (BIP 141)\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"version\" : n, (numeric) The block version\n" - " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"tx\" : [ (array of string) The transaction ids\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - " ],\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"chainwork\" : \"xxxx\", (string) Expected number of hashes required to produce the chain up to this block (in hex)\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" - "}\n" - "\nResult (for verbose=false):\n" - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - "\nExamples:\n" - + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - ); + "getblock \"hash\" ( verbose )\n" + "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.\n" + "If verbose is true, returns an Object with information about block .\n" + "\nArguments:\n" + "1. \"hash\" (string, required) The block hash\n" + "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" + "\nResult (for verbose = true):\n" + "{\n" + " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" + " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" + " \"size\" : n, (numeric) The block size\n" + " \"strippedsize\" : n, (numeric) The block size excluding witness data\n" + " \"weight\" : n (numeric) The block weight (BIP 141)\n" + " \"height\" : n, (numeric) The block height or index\n" + " \"version\" : n, (numeric) The block version\n" + " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" + " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" + " \"tx\" : [ (array of string) The transaction ids\n" + " \"transactionid\" (string) The transaction id\n" + " ,...\n" + " ],\n" + " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"nonce\" : n, (numeric) The nonce\n" + " \"bits\" : \"1d00ffff\", (string) The bits\n" + " \"difficulty\" : x.xxx, (numeric) The difficulty\n" + " \"chainwork\" : \"xxxx\", (string) Expected number of hashes required to produce the chain up to this block (in hex)\n" + " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" + " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" + "}\n" + "\nResult (for verbose=false):\n" + "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" + "\nExamples:\n" + + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + ); LOCK(cs_main); @@ -948,23 +964,23 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( - "gettxoutsetinfo\n" - "\nReturns statistics about the unspent transaction output set.\n" - "Note this call may take some time.\n" - "\nResult:\n" - "{\n" - " \"height\":n, (numeric) The current block height (index)\n" - " \"bestblock\": \"hex\", (string) the best block hash hex\n" - " \"transactions\": n, (numeric) The number of transactions\n" - " \"txouts\": n, (numeric) The number of output transactions\n" - " \"bytes_serialized\": n, (numeric) The serialized size\n" - " \"hash_serialized\": \"hash\", (string) The serialized hash\n" - " \"total_amount\": x.xxx (numeric) The total amount\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("gettxoutsetinfo", "") - + HelpExampleRpc("gettxoutsetinfo", "") - ); + "gettxoutsetinfo\n" + "\nReturns statistics about the unspent transaction output set.\n" + "Note this call may take some time.\n" + "\nResult:\n" + "{\n" + " \"height\":n, (numeric) The current block height (index)\n" + " \"bestblock\": \"hex\", (string) the best block hash hex\n" + " \"transactions\": n, (numeric) The number of transactions\n" + " \"txouts\": n, (numeric) The number of output transactions\n" + " \"bytes_serialized\": n, (numeric) The serialized size\n" + " \"hash_serialized\": \"hash\", (string) The serialized hash\n" + " \"total_amount\": x.xxx (numeric) The total amount\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("gettxoutsetinfo", "") + + HelpExampleRpc("gettxoutsetinfo", "") + ); UniValue ret(UniValue::VOBJ); @@ -1091,11 +1107,11 @@ UniValue listconsultations(const UniValue& params, bool fHelp) flags fState = consultation.GetLastState(); if((showNotEnoughAnswers && fState == DAOFlags::NIL && vAnswers.size() < 2) || - (showLookingForSupport && fState == DAOFlags::NIL) || - (showReflection && fState == DAOFlags::REFLECTION) || - (showReflection && fState == DAOFlags::ACCEPTED) || - (showFinished && fState == DAOFlags::EXPIRED) || - showAll) { + (showLookingForSupport && fState == DAOFlags::NIL) || + (showReflection && fState == DAOFlags::REFLECTION) || + (showReflection && fState == DAOFlags::ACCEPTED) || + (showFinished && fState == DAOFlags::EXPIRED) || + showAll) { UniValue o(UniValue::VOBJ); consultation.ToJson(o, view); ret.push_back(o); @@ -1110,11 +1126,11 @@ UniValue cfundstats(const UniValue& params, bool fHelp) if (fHelp || params.size() != 0) throw runtime_error( - "cfundstats\n" - "\nReturns statistics about the community fund.\n" - + HelpExampleCli("cfundstats", "") - + HelpExampleRpc("cfundstats", "") - ); + "cfundstats\n" + "\nReturns statistics about the community fund.\n" + + HelpExampleCli("cfundstats", "") + + HelpExampleRpc("cfundstats", "") + ); LOCK(cs_main); @@ -1135,46 +1151,54 @@ UniValue cfundstats(const UniValue& params, bool fHelp) while(nBlocks > 0 && pindexblock != nullptr) { vSeen.clear(); - for(unsigned int i = 0; i < pindexblock->vProposalVotes.size(); i++) + auto pVotes = GetProposalVotes(pindexblock->GetBlockHash()); + if (pVotes != nullptr) { - if(!view.GetProposal(pindexblock->vProposalVotes[i].first, proposal)) - continue; - - if(vSeen.count(pindexblock->vProposalVotes[i].first) == 0) + for (unsigned int i = 0; i < pVotes->size(); i++) { - if(vCacheProposalsRPC.count(pindexblock->vProposalVotes[i].first) == 0) - vCacheProposalsRPC[pindexblock->vProposalVotes[i].first] = make_pair(make_pair(0,0), 0); + if(!view.GetProposal((*pVotes)[i].first, proposal)) + continue; - if(pindexblock->vProposalVotes[i].second == 1) - vCacheProposalsRPC[pindexblock->vProposalVotes[i].first].first.first += 1; - else if(pindexblock->vProposalVotes[i].second == -1) - vCacheProposalsRPC[pindexblock->vProposalVotes[i].first].second += 1; - else if (pindexblock->vProposalVotes[i].second == 0) - vCacheProposalsRPC[pindexblock->vProposalVotes[i].first].first.second += 1; + if(vSeen.count((*pVotes)[i].first) == 0) + { + if(vCacheProposalsRPC.count((*pVotes)[i].first) == 0) + vCacheProposalsRPC[(*pVotes)[i].first] = make_pair(make_pair(0,0), 0); - vSeen[pindexblock->vProposalVotes[i].first]=true; + if((*pVotes)[i].second == 1) + vCacheProposalsRPC[(*pVotes)[i].first].first.first += 1; + else if((*pVotes)[i].second == -1) + vCacheProposalsRPC[(*pVotes)[i].first].second += 1; + else if ((*pVotes)[i].second == 0) + vCacheProposalsRPC[(*pVotes)[i].first].first.second += 1; + + vSeen[(*pVotes)[i].first]=true; + } } } - for(unsigned int i = 0; i < pindexblock->vPaymentRequestVotes.size(); i++) + auto prVotes = GetPaymentRequestVotes(pindexblock->GetBlockHash()); + if (prVotes != nullptr) { - if(!view.GetPaymentRequest(pindexblock->vPaymentRequestVotes[i].first, prequest)) - continue; + for(unsigned int i = 0; i < prVotes->size(); i++) + { + if(!view.GetPaymentRequest((*prVotes)[i].first, prequest)) + continue; - if(!view.GetProposal(prequest.proposalhash, proposal)) - continue; - if(vSeen.count(pindexblock->vPaymentRequestVotes[i].first) == 0) { - if(vCachePaymentRequestRPC.count(pindexblock->vPaymentRequestVotes[i].first) == 0) - vCachePaymentRequestRPC[pindexblock->vPaymentRequestVotes[i].first] = make_pair(make_pair(0,0), 0); - - if(pindexblock->vPaymentRequestVotes[i].second == 1) - vCachePaymentRequestRPC[pindexblock->vPaymentRequestVotes[i].first].first.first += 1; - else if(pindexblock->vPaymentRequestVotes[i].second == -1) - vCachePaymentRequestRPC[pindexblock->vPaymentRequestVotes[i].first].second += 1; - else if (pindexblock->vPaymentRequestVotes[i].second == 0) - vCachePaymentRequestRPC[pindexblock->vPaymentRequestVotes[i].first].first.second += 1; - - vSeen[pindexblock->vPaymentRequestVotes[i].first]=true; + if(!view.GetProposal(prequest.proposalhash, proposal)) + continue; + if(vSeen.count((*prVotes)[i].first) == 0) { + if(vCachePaymentRequestRPC.count((*prVotes)[i].first) == 0) + vCachePaymentRequestRPC[(*prVotes)[i].first] = make_pair(make_pair(0,0), 0); + + if((*prVotes)[i].second == 1) + vCachePaymentRequestRPC[(*prVotes)[i].first].first.first += 1; + else if((*prVotes)[i].second == -1) + vCachePaymentRequestRPC[(*prVotes)[i].first].second += 1; + else if ((*prVotes)[i].second == 0) + vCachePaymentRequestRPC[(*prVotes)[i].first].first.second += 1; + + vSeen[(*prVotes)[i].first]=true; + } } } @@ -1274,39 +1298,39 @@ UniValue gettxout(const UniValue& params, bool fHelp) { if (fHelp || params.size() < 2 || params.size() > 3) throw runtime_error( - "gettxout \"txid\" n ( includemempool )\n" - "\nReturns details about an unspent transaction output.\n" - "\nArguments:\n" - "1. \"txid\" (string, required) The transaction id\n" - "2. n (numeric, required) vout number\n" - "3. includemempool (boolean, optional) Whether to include the mem pool\n" - "\nResult:\n" - "{\n" - " \"bestblock\" : \"hash\", (string) the block hash\n" - " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"code\", (string) \n" - " \"hex\" : \"hex\", (string) \n" - " \"reqSigs\" : n, (numeric) Number of required signatures\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" - " \"addresses\" : [ (array of string) array of navcoin addresses\n" - " \"navcoinaddress\" (string) navcoin address\n" - " ,...\n" - " ]\n" - " },\n" - " \"version\" : n, (numeric) The version\n" - " \"coinbase\" : true|false (boolean) Coinbase or not\n" - "}\n" - - "\nExamples:\n" - "\nGet unspent transactions\n" - + HelpExampleCli("listunspent", "") + - "\nView the details\n" - + HelpExampleCli("gettxout", "\"txid\" 1") + - "\nAs a json rpc call\n" - + HelpExampleRpc("gettxout", "\"txid\", 1") - ); + "gettxout \"txid\" n ( includemempool )\n" + "\nReturns details about an unspent transaction output.\n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id\n" + "2. n (numeric, required) vout number\n" + "3. includemempool (boolean, optional) Whether to include the mem pool\n" + "\nResult:\n" + "{\n" + " \"bestblock\" : \"hash\", (string) the block hash\n" + " \"confirmations\" : n, (numeric) The number of confirmations\n" + " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" + " \"scriptPubKey\" : { (json object)\n" + " \"asm\" : \"code\", (string) \n" + " \"hex\" : \"hex\", (string) \n" + " \"reqSigs\" : n, (numeric) Number of required signatures\n" + " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" + " \"addresses\" : [ (array of string) array of navcoin addresses\n" + " \"navcoinaddress\" (string) navcoin address\n" + " ,...\n" + " ]\n" + " },\n" + " \"version\" : n, (numeric) The version\n" + " \"coinbase\" : true|false (boolean) Coinbase or not\n" + "}\n" + + "\nExamples:\n" + "\nGet unspent transactions\n" + + HelpExampleCli("listunspent", "") + + "\nView the details\n" + + HelpExampleCli("gettxout", "\"txid\" 1") + + "\nAs a json rpc call\n" + + HelpExampleRpc("gettxout", "\"txid\", 1") + ); LOCK(cs_main); @@ -1356,17 +1380,17 @@ UniValue verifychain(const UniValue& params, bool fHelp) int nCheckDepth = GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); if (fHelp || params.size() > 2) throw runtime_error( - "verifychain ( checklevel numblocks )\n" - "\nVerifies blockchain database.\n" - "\nArguments:\n" - "1. checklevel (numeric, optional, 0-4, default=" + strprintf("%d", nCheckLevel) + ") How thorough the block verification is.\n" - "2. numblocks (numeric, optional, default=" + strprintf("%d", nCheckDepth) + ", 0=all) The number of blocks to check.\n" - "\nResult:\n" - "true|false (boolean) Verified or not\n" - "\nExamples:\n" - + HelpExampleCli("verifychain", "") - + HelpExampleRpc("verifychain", "") - ); + "verifychain ( checklevel numblocks )\n" + "\nVerifies blockchain database.\n" + "\nArguments:\n" + "1. checklevel (numeric, optional, 0-4, default=" + strprintf("%d", nCheckLevel) + ") How thorough the block verification is.\n" + "2. numblocks (numeric, optional, default=" + strprintf("%d", nCheckDepth) + ", 0=all) The number of blocks to check.\n" + "\nResult:\n" + "true|false (boolean) Verified or not\n" + "\nExamples:\n" + + HelpExampleCli("verifychain", "") + + HelpExampleRpc("verifychain", "") + ); LOCK(cs_main); @@ -1445,46 +1469,46 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( - "getblockchaininfo\n" - "Returns an object containing various state info regarding block chain processing.\n" - "\nResult:\n" - "{\n" - " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" - " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" - " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" - " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" - " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" - " \"mediantime\": xxxxxx, (numeric) median time for the current best block\n" - " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" - " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" - " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" - " \"pruneheight\": xxxxxx, (numeric) heighest block available\n" - " \"softforks\": [ (array) status of softforks in progress\n" - " {\n" - " \"id\": \"xxxx\", (string) name of softfork\n" - " \"version\": xx, (numeric) block version\n" - " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n" - " \"status\": xx, (boolean) true if threshold reached\n" - " \"found\": xx, (numeric) number of blocks with the new version found\n" - " \"required\": xx, (numeric) number of blocks required to trigger\n" - " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n" - " },\n" - " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" - " }, ...\n" - " ],\n" - " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" - " \"xxxx\" : { (string) name of the softfork\n" - " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" - " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" - " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" - " \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" - " }\n" - " }\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getblockchaininfo", "") - + HelpExampleRpc("getblockchaininfo", "") - ); + "getblockchaininfo\n" + "Returns an object containing various state info regarding block chain processing.\n" + "\nResult:\n" + "{\n" + " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" + " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" + " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" + " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" + " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" + " \"mediantime\": xxxxxx, (numeric) median time for the current best block\n" + " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" + " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" + " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" + " \"pruneheight\": xxxxxx, (numeric) heighest block available\n" + " \"softforks\": [ (array) status of softforks in progress\n" + " {\n" + " \"id\": \"xxxx\", (string) name of softfork\n" + " \"version\": xx, (numeric) block version\n" + " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n" + " \"status\": xx, (boolean) true if threshold reached\n" + " \"found\": xx, (numeric) number of blocks with the new version found\n" + " \"required\": xx, (numeric) number of blocks required to trigger\n" + " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n" + " },\n" + " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" + " }, ...\n" + " ],\n" + " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" + " \"xxxx\" : { (string) name of the softfork\n" + " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" + " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" + " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" + " \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" + " }\n" + " }\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getblockchaininfo", "") + + HelpExampleRpc("getblockchaininfo", "") + ); LOCK(cs_main); @@ -1543,7 +1567,7 @@ struct CompareBlocksByHeight equal. Use the pointers themselves to make a distinction. */ if (a->nHeight != b->nHeight) - return (a->nHeight > b->nHeight); + return (a->nHeight > b->nHeight); return a < b; } @@ -1553,34 +1577,34 @@ UniValue getchaintips(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( - "getchaintips\n" - "Return information about all known tips in the block tree," - " including the main chain as well as orphaned branches.\n" - "\nResult:\n" - "[\n" - " {\n" - " \"height\": xxxx, (numeric) height of the chain tip\n" - " \"hash\": \"xxxx\", (string) block hash of the tip\n" - " \"branchlen\": 0 (numeric) zero for main chain\n" - " \"status\": \"active\" (string) \"active\" for the main chain\n" - " },\n" - " {\n" - " \"height\": xxxx,\n" - " \"hash\": \"xxxx\",\n" - " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n" - " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" - " }\n" - "]\n" - "Possible values for status:\n" - "1. \"invalid\" This branch contains at least one invalid block\n" - "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" - "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" - "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" - "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" - "\nExamples:\n" - + HelpExampleCli("getchaintips", "") - + HelpExampleRpc("getchaintips", "") - ); + "getchaintips\n" + "Return information about all known tips in the block tree," + " including the main chain as well as orphaned branches.\n" + "\nResult:\n" + "[\n" + " {\n" + " \"height\": xxxx, (numeric) height of the chain tip\n" + " \"hash\": \"xxxx\", (string) block hash of the tip\n" + " \"branchlen\": 0 (numeric) zero for main chain\n" + " \"status\": \"active\" (string) \"active\" for the main chain\n" + " },\n" + " {\n" + " \"height\": xxxx,\n" + " \"hash\": \"xxxx\",\n" + " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n" + " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" + " }\n" + "]\n" + "Possible values for status:\n" + "1. \"invalid\" This branch contains at least one invalid block\n" + "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" + "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" + "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" + "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" + "\nExamples:\n" + + HelpExampleCli("getchaintips", "") + + HelpExampleRpc("getchaintips", "") + ); LOCK(cs_main); @@ -1680,20 +1704,20 @@ UniValue getmempoolinfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( - "getmempoolinfo\n" - "\nReturns details on the active state of the TX memory pool.\n" - "\nResult:\n" - "{\n" - " \"size\": xxxxx, (numeric) Current tx count\n" - " \"bytes\": xxxxx, (numeric) Sum of all tx sizes\n" - " \"usage\": xxxxx, (numeric) Total memory usage for the mempool\n" - " \"maxmempool\": xxxxx, (numeric) Maximum memory usage for the mempool\n" - " \"mempoolminfee\": xxxxx (numeric) Minimum fee for tx to be accepted\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getmempoolinfo", "") - + HelpExampleRpc("getmempoolinfo", "") - ); + "getmempoolinfo\n" + "\nReturns details on the active state of the TX memory pool.\n" + "\nResult:\n" + "{\n" + " \"size\": xxxxx, (numeric) Current tx count\n" + " \"bytes\": xxxxx, (numeric) Sum of all tx sizes\n" + " \"usage\": xxxxx, (numeric) Total memory usage for the mempool\n" + " \"maxmempool\": xxxxx, (numeric) Maximum memory usage for the mempool\n" + " \"mempoolminfee\": xxxxx (numeric) Minimum fee for tx to be accepted\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getmempoolinfo", "") + + HelpExampleRpc("getmempoolinfo", "") + ); return mempoolInfoToJSON(); } @@ -1703,17 +1727,17 @@ UniValue getstempoolinfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( - "getstempoolinfo\n" - "\nReturns details on the active state of the dandelion stem pool.\n" - "\nResult:\n" - "{\n" - " \"size\": xxxxx, (numeric) Current tx count\n" - " \"bytes\": xxxxx, (numeric) Sum of all tx sizes\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getstempoolinfo", "") - + HelpExampleRpc("getstempoolinfo", "") - ); + "getstempoolinfo\n" + "\nReturns details on the active state of the dandelion stem pool.\n" + "\nResult:\n" + "{\n" + " \"size\": xxxxx, (numeric) Current tx count\n" + " \"bytes\": xxxxx, (numeric) Sum of all tx sizes\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getstempoolinfo", "") + + HelpExampleRpc("getstempoolinfo", "") + ); return stempoolInfoToJSON(); } @@ -1722,11 +1746,11 @@ UniValue getproposal(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( - "getproposal \"hash\"\n" - "\nShows information about the given proposal.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the proposal\n" - ); + "getproposal \"hash\"\n" + "\nShows information about the given proposal.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the proposal\n" + ); LOCK(cs_main); @@ -1746,11 +1770,11 @@ UniValue getconsultation(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( - "getconsultation \"hash\"\n" - "\nShows information about the given consultation.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the consultation\n" - ); + "getconsultation \"hash\"\n" + "\nShows information about the given consultation.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the consultation\n" + ); LOCK(cs_main); @@ -1770,11 +1794,11 @@ UniValue getconsultationanswer(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( - "getconsultationanswer \"hash\"\n" - "\nShows information about the given consultation answer.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the consultation answer\n" - ); + "getconsultationanswer \"hash\"\n" + "\nShows information about the given consultation answer.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the consultation answer\n" + ); LOCK(cs_main); @@ -1799,7 +1823,7 @@ UniValue getpaymentrequest(const UniValue& params, bool fHelp) "\nShows information about the given payment request.\n" "\nArguments:\n" "1. hash (string, required) the hash of the payment request\n" - ); + ); LOCK(cs_main); @@ -1820,15 +1844,15 @@ UniValue invalidateblock(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( - "invalidateblock \"hash\"\n" - "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the block to mark as invalid\n" - "\nResult:\n" - "\nExamples:\n" - + HelpExampleCli("invalidateblock", "\"blockhash\"") - + HelpExampleRpc("invalidateblock", "\"blockhash\"") - ); + "invalidateblock \"hash\"\n" + "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the block to mark as invalid\n" + "\nResult:\n" + "\nExamples:\n" + + HelpExampleCli("invalidateblock", "\"blockhash\"") + + HelpExampleRpc("invalidateblock", "\"blockhash\"") + ); std::string strHash = params[0].get_str(); uint256 hash(uint256S(strHash)); @@ -1858,16 +1882,16 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( - "reconsiderblock \"hash\"\n" - "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n" - "This can be used to undo the effects of invalidateblock.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the block to reconsider\n" - "\nResult:\n" - "\nExamples:\n" - + HelpExampleCli("reconsiderblock", "\"blockhash\"") - + HelpExampleRpc("reconsiderblock", "\"blockhash\"") - ); + "reconsiderblock \"hash\"\n" + "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n" + "This can be used to undo the effects of invalidateblock.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the block to reconsider\n" + "\nResult:\n" + "\nExamples:\n" + + HelpExampleCli("reconsiderblock", "\"blockhash\"") + + HelpExampleRpc("reconsiderblock", "\"blockhash\"") + ); std::string strHash = params[0].get_str(); uint256 hash(uint256S(strHash)); @@ -1894,36 +1918,36 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- - { "communityfund", "cfundstats", &cfundstats, true }, - { "blockchain", "getblockchaininfo", &getblockchaininfo, true }, - { "blockchain", "getbestblockhash", &getbestblockhash, true }, - { "blockchain", "getblockcount", &getblockcount, true }, - { "blockchain", "getblock", &getblock, true }, - { "blockchain", "getblockdeltas", &getblockdeltas, false }, - { "blockchain", "getblockhashes", &getblockhashes, true }, - { "blockchain", "getblockhash", &getblockhash, true }, - { "blockchain", "getblockheader", &getblockheader, true }, - { "blockchain", "getchaintips", &getchaintips, true }, - { "blockchain", "getdifficulty", &getdifficulty, true }, - { "blockchain", "getmempoolancestors", &getmempoolancestors, true }, - { "blockchain", "getmempooldescendants", &getmempooldescendants, true }, - { "blockchain", "getmempoolentry", &getmempoolentry, true }, - { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, - { "blockchain", "getstempoolinfo", &getstempoolinfo, true }, - { "communityfund", "getproposal", &getproposal, true }, - { "communityfund", "getpaymentrequest", &getpaymentrequest, true }, - { "blockchain", "getrawmempool", &getrawmempool, true }, - { "blockchain", "gettxout", &gettxout, true }, - { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, - { "blockchain", "verifychain", &verifychain, true }, - { "dao", "listconsultations", &listconsultations, true }, - { "dao", "getconsultation", &getconsultation, true }, - { "dao", "getconsultationanswer", &getconsultationanswer, true }, - { "dao", "getcfunddbstatehash", &getcfunddbstatehash, true }, - - /* Not shown in help */ - { "hidden", "invalidateblock", &invalidateblock, true }, - { "hidden", "reconsiderblock", &reconsiderblock, true }, + { "communityfund", "cfundstats", &cfundstats, true }, + { "blockchain", "getblockchaininfo", &getblockchaininfo, true }, + { "blockchain", "getbestblockhash", &getbestblockhash, true }, + { "blockchain", "getblockcount", &getblockcount, true }, + { "blockchain", "getblock", &getblock, true }, + { "blockchain", "getblockdeltas", &getblockdeltas, false }, + { "blockchain", "getblockhashes", &getblockhashes, true }, + { "blockchain", "getblockhash", &getblockhash, true }, + { "blockchain", "getblockheader", &getblockheader, true }, + { "blockchain", "getchaintips", &getchaintips, true }, + { "blockchain", "getdifficulty", &getdifficulty, true }, + { "blockchain", "getmempoolancestors", &getmempoolancestors, true }, + { "blockchain", "getmempooldescendants", &getmempooldescendants, true }, + { "blockchain", "getmempoolentry", &getmempoolentry, true }, + { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, + { "blockchain", "getstempoolinfo", &getstempoolinfo, true }, + { "communityfund", "getproposal", &getproposal, true }, + { "communityfund", "getpaymentrequest", &getpaymentrequest, true }, + { "blockchain", "getrawmempool", &getrawmempool, true }, + { "blockchain", "gettxout", &gettxout, true }, + { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, + { "blockchain", "verifychain", &verifychain, true }, + { "dao", "listconsultations", &listconsultations, true }, + { "dao", "getconsultation", &getconsultation, true }, + { "dao", "getconsultationanswer", &getconsultationanswer, true }, + { "dao", "getcfunddbstatehash", &getcfunddbstatehash, true }, + + /* Not shown in help */ + { "hidden", "invalidateblock", &invalidateblock, true }, + { "hidden", "reconsiderblock", &reconsiderblock, true }, }; void RegisterBlockchainRPCCommands(CRPCTable &tableRPC) diff --git a/src/txdb.cpp b/src/txdb.cpp index 82dcc7c09..3e593a4b0 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -410,7 +410,28 @@ bool CBlockTreeDB::WriteBatchSync(const std::vector::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) { - batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it)); + CDiskBlockIndex dbi(*it); + auto pVotes = GetProposalVotes(dbi.GetBlockHash()); + if (pVotes != nullptr) + { + dbi.vProposalVotes = *pVotes; + } + auto prVotes = GetPaymentRequestVotes(dbi.GetBlockHash()); + if (prVotes != nullptr) + { + dbi.vPaymentRequestVotes = *prVotes; + } + auto supp = GetSupport(dbi.GetBlockHash()); + if (supp != nullptr) + { + dbi.mapSupport = *supp; + } + auto cVotes = GetConsultationVotes(dbi.GetBlockHash()); + if (cVotes != nullptr) + { + dbi.mapConsultationVotes = *cVotes; + } + batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), dbi); } return WriteBatch(batch, true); } @@ -713,7 +734,11 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { return true; } -bool CBlockTreeDB::LoadBlockIndexGuts(boost::function insertBlockIndex) +bool CBlockTreeDB::LoadBlockIndexGuts(boost::function insertBlockIndex, + boost::function>*(const uint256&)> insertProposalVotes, + boost::function>*(const uint256&)> insertPaymentRequestVotes, + boost::function*(const uint256&)> insertSupport, + boost::function*(const uint256&)> insertConsultationVotes) { boost::scoped_ptr pcursor(NewIterator()); @@ -742,19 +767,31 @@ bool CBlockTreeDB::LoadBlockIndexGuts(boost::functionnTx = diskindex.nTx; pindexNew->nMint = diskindex.nMint; pindexNew->nCFSupply = diskindex.nCFSupply; - pindexNew->vPaymentRequestVotes - = diskindex.vPaymentRequestVotes; - pindexNew->vProposalVotes = diskindex.vProposalVotes; pindexNew->nCFLocked = diskindex.nCFLocked; pindexNew->strDZeel = diskindex.strDZeel; pindexNew->nFlags = diskindex.nFlags; pindexNew->nStakeModifier = diskindex.nStakeModifier; - pindexNew->prevoutStake = diskindex.prevoutStake; - pindexNew->nStakeTime = diskindex.nStakeTime; pindexNew->hashProof = diskindex.hashProof; - pindexNew->mapSupport = diskindex.mapSupport; - pindexNew->mapConsultationVotes - = diskindex.mapConsultationVotes; + if (diskindex.vProposalVotes.size() > 0) + { + auto pVotes = insertProposalVotes(diskindex.GetBlockHash()); + *pVotes = diskindex.vProposalVotes; + } + if (diskindex.vPaymentRequestVotes.size() > 0) + { + auto prVotes = insertPaymentRequestVotes(diskindex.GetBlockHash()); + *prVotes = diskindex.vPaymentRequestVotes; + } + if (diskindex.mapSupport.size() > 0) + { + auto supp = insertSupport(diskindex.GetBlockHash()); + *supp = diskindex.mapSupport; + } + if (diskindex.mapConsultationVotes.size() > 0) + { + auto cVotes = insertConsultationVotes(diskindex.GetBlockHash()); + *cVotes = diskindex.mapConsultationVotes; + } pcursor->Next(); } else { diff --git a/src/txdb.h b/src/txdb.h index 85b3e5b13..8ce0e60b5 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -182,7 +182,11 @@ class CBlockTreeDB : public CDBWrapper bool ReadTimestampBlockIndex(const uint256 &hash, unsigned int &logicalTS); bool WriteFlag(const std::string &name, bool fValue); bool ReadFlag(const std::string &name, bool &fValue); - bool LoadBlockIndexGuts(boost::function insertBlockIndex); + bool LoadBlockIndexGuts(boost::function insertBlockIndex, + boost::function>*(const uint256&)> insertProposalVotes, + boost::function>*(const uint256&)> insertPaymentRequestVotes, + boost::function*(const uint256&)> insertSupport, + boost::function*(const uint256&)> insertConsultationVotes); bool ReadProposalIndex(const uint256 &proposalid, CProposal &proposal); bool WriteProposalIndex(const std::vector >&vect); bool GetProposalIndex(std::vector&vect);