@@ -79,11 +79,12 @@ bool CFund::FindPaymentRequest(string preqstr, CFund::CPaymentRequest &prequest)
7979
8080bool CFund::VoteProposal (string strProp, bool vote, bool &duplicate)
8181{
82+ AssertLockHeld (cs_main);
8283
8384 CFund::CProposal proposal;
8485 bool found = CFund::FindProposal (uint256S (" 0x" +strProp), proposal);
8586
86- if (!found || proposal.IsNull ())
87+ if (!found || proposal.IsNull () || !proposal. CanVote () )
8788 return false ;
8889
8990 vector<std::pair<std::string, bool >>::iterator it = vAddedProposalVotes.begin ();
@@ -133,11 +134,12 @@ bool CFund::RemoveVoteProposal(uint256 proposalHash)
133134
134135bool CFund::VotePaymentRequest (string strProp, bool vote, bool &duplicate)
135136{
137+ AssertLockHeld (cs_main);
136138
137139 CFund::CPaymentRequest prequest;
138140 bool found = CFund::FindPaymentRequest (uint256S (" 0x" +strProp), prequest);
139141
140- if (!found || prequest.IsNull ())
142+ if (!found || prequest.IsNull () || !prequest. CanVote (*pcoinsTip) )
141143 return false ;
142144
143145 vector<std::pair<std::string, bool >>::iterator it = vAddedPaymentRequestVotes.begin ();
@@ -188,7 +190,7 @@ bool CFund::RemoveVotePaymentRequest(uint256 proposalHash)
188190 return RemoveVotePaymentRequest (proposalHash.ToString ());
189191}
190192
191- bool CFund::IsValidPaymentRequest (CTransaction tx, int nMaxVersion)
193+ bool CFund::IsValidPaymentRequest (CTransaction tx, CCoinsViewCache& coins, int nMaxVersion)
192194{
193195 if (tx.strDZeel .length () > 1024 )
194196 return error (" %s: Too long strdzeel for payment request %s" , __func__, tx.GetHash ().ToString ());
@@ -258,9 +260,9 @@ bool CFund::IsValidPaymentRequest(CTransaction tx, int nMaxVersion)
258260 if (!pubkey.RecoverCompact (ss.GetHash (), vchSig) || pubkey.GetID () != keyID)
259261 return error (" %s: Invalid signature for payment request %s" , __func__, tx.GetHash ().ToString ());
260262
261- if (nAmount > proposal.GetAvailable (true ))
263+ if (nAmount > proposal.GetAvailable (coins, true ))
262264 return error (" %s: Invalid requested amount for payment request %s (%d vs %d available)" ,
263- __func__, tx.GetHash ().ToString (), nAmount, proposal.GetAvailable ());
265+ __func__, tx.GetHash ().ToString (), nAmount, proposal.GetAvailable (coins, true ));
264266
265267 bool ret = (nVersion <= nMaxVersion);
266268
@@ -271,11 +273,23 @@ bool CFund::IsValidPaymentRequest(CTransaction tx, int nMaxVersion)
271273
272274}
273275
274- bool CFund::CPaymentRequest::CanVote () const {
276+ bool CFund::CPaymentRequest::CanVote (CCoinsViewCache& coins) const
277+ {
278+ AssertLockHeld (cs_main);
279+
280+ CBlockIndex* pindex;
281+ if (txblockhash == uint256 () || !mapBlockIndex.count (txblockhash))
282+ return false ;
283+
284+ pindex = mapBlockIndex[txblockhash];
285+ if (!chainActive.Contains (pindex))
286+ return false ;
287+
275288 CFund::CProposal proposal;
276289 if (!CFund::FindProposal (proposalhash, proposal))
277290 return false ;
278- return nAmount <= proposal.GetAvailable () && fState != ACCEPTED && fState != REJECTED && fState != EXPIRED && !ExceededMaxVotingCycles ();
291+
292+ return nAmount <= proposal.GetAvailable (coins) && fState != ACCEPTED && fState != REJECTED && fState != EXPIRED && !ExceededMaxVotingCycles ();
279293}
280294
281295bool CFund::CPaymentRequest::IsExpired () const {
@@ -388,6 +402,16 @@ bool CFund::CProposal::IsRejected() const {
388402}
389403
390404bool CFund::CProposal::CanVote () const {
405+ AssertLockHeld (cs_main);
406+
407+ CBlockIndex* pindex;
408+ if (txblockhash == uint256 () || !mapBlockIndex.count (txblockhash))
409+ return false ;
410+
411+ pindex = mapBlockIndex[txblockhash];
412+ if (!chainActive.Contains (pindex))
413+ return false ;
414+
391415 return (fState == NIL) && (!ExceededMaxVotingCycles ());
392416}
393417
@@ -418,6 +442,59 @@ bool CFund::CProposal::ExceededMaxVotingCycles() const {
418442 return nVotingCycle > Params ().GetConsensus ().nCyclesProposalVoting ;
419443}
420444
445+ CAmount CFund::CProposal::GetAvailable (CCoinsViewCache& coins, bool fIncludeRequests ) const
446+ {
447+ AssertLockHeld (cs_main);
448+
449+ CAmount initial = nAmount;
450+ for (unsigned int i = 0 ; i < vPayments.size (); i++)
451+ {
452+ CFund::CPaymentRequest prequest;
453+ if (FindPaymentRequest (vPayments[i], prequest))
454+ {
455+ if (!coins.HaveCoins (prequest.hash ))
456+ {
457+ CBlockIndex* pindex;
458+ if (prequest.txblockhash == uint256 () || !mapBlockIndex.count (prequest.txblockhash ))
459+ continue ;
460+ pindex = mapBlockIndex[prequest.txblockhash ];
461+ if (!chainActive.Contains (pindex))
462+ continue ;
463+ }
464+ if ((fIncludeRequests && prequest.fState != REJECTED && prequest.fState != EXPIRED) || (!fIncludeRequests && prequest.fState == ACCEPTED))
465+ initial -= prequest.nAmount ;
466+ }
467+ }
468+ return initial;
469+ }
470+
471+ std::string CFund::CProposal::ToString (CCoinsViewCache& coins, uint32_t currentTime) const {
472+ std::string str;
473+ str += strprintf (" CProposal(hash=%s, nVersion=%i, nAmount=%f, available=%f, nFee=%f, address=%s, nDeadline=%u, nVotesYes=%u, "
474+ " nVotesNo=%u, nVotingCycle=%u, fState=%s, strDZeel=%s, blockhash=%s)" ,
475+ hash.ToString (), nVersion, (float )nAmount/COIN, (float )GetAvailable (coins)/COIN, (float )nFee/COIN, Address, nDeadline,
476+ nVotesYes, nVotesNo, nVotingCycle, GetState (currentTime), strDZeel, blockhash.ToString ().substr (0 ,10 ));
477+ for (unsigned int i = 0 ; i < vPayments.size (); i++) {
478+ CFund::CPaymentRequest prequest;
479+ if (FindPaymentRequest (vPayments[i], prequest))
480+ str += " \n " + prequest.ToString ();
481+ }
482+ return str + " \n " ;
483+ }
484+
485+ bool CFund::CProposal::HasPendingPaymentRequests (CCoinsViewCache& coins) const {
486+ AssertLockHeld (cs_main);
487+
488+ for (unsigned int i = 0 ; i < vPayments.size (); i++)
489+ {
490+ CFund::CPaymentRequest prequest;
491+ if (FindPaymentRequest (vPayments[i], prequest))
492+ if (prequest.CanVote (coins))
493+ return true ;
494+ }
495+ return false ;
496+ }
497+
421498std::string CFund::CProposal::GetState (uint32_t currentTime) const {
422499 std::string sFlags = " pending" ;
423500 if (IsAccepted ()) {
@@ -444,13 +521,15 @@ std::string CFund::CProposal::GetState(uint32_t currentTime) const {
444521 return sFlags ;
445522}
446523
447- void CFund::CProposal::ToJson (UniValue& ret) const {
524+ void CFund::CProposal::ToJson (UniValue& ret, CCoinsViewCache& coins) const {
525+ AssertLockHeld (cs_main);
526+
448527 ret.push_back (Pair (" version" , nVersion));
449528 ret.push_back (Pair (" hash" , hash.ToString ()));
450529 ret.push_back (Pair (" blockHash" , txblockhash.ToString ()));
451530 ret.push_back (Pair (" description" , strDZeel));
452531 ret.push_back (Pair (" requestedAmount" , FormatMoney (nAmount)));
453- ret.push_back (Pair (" notPaidYet" , FormatMoney (GetAvailable ())));
532+ ret.push_back (Pair (" notPaidYet" , FormatMoney (GetAvailable (coins ))));
454533 ret.push_back (Pair (" userPaidFee" , FormatMoney (nFee)));
455534 ret.push_back (Pair (" paymentAddress" , Address));
456535 if (nVersion >= 2 ) {
0 commit comments