Refactored locking for masternode winners and budgets

This commit is contained in:
Evan Duffield 2015-07-29 08:28:49 -07:00
parent fc33c3b963
commit dfad32272c
4 changed files with 86 additions and 29 deletions

View File

@ -85,6 +85,8 @@ bool IsBudgetCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, s
void CBudgetManager::CheckOrphanVotes() void CBudgetManager::CheckOrphanVotes()
{ {
LOCK(cs);
std::string strError = ""; std::string strError = "";
std::map<uint256, CBudgetVote>::iterator it1 = mapOrphanMasternodeBudgetVotes.begin(); std::map<uint256, CBudgetVote>::iterator it1 = mapOrphanMasternodeBudgetVotes.begin();
while(it1 != mapOrphanMasternodeBudgetVotes.end()){ while(it1 != mapOrphanMasternodeBudgetVotes.end()){
@ -181,6 +183,7 @@ void CBudgetManager::SubmitFinalBudget()
return; return;
} }
LOCK(cs);
mapSeenFinalizedBudgets.insert(make_pair(finalizedBudgetBroadcast.GetHash(), finalizedBudgetBroadcast)); mapSeenFinalizedBudgets.insert(make_pair(finalizedBudgetBroadcast.GetHash(), finalizedBudgetBroadcast));
finalizedBudgetBroadcast.Relay(); finalizedBudgetBroadcast.Relay();
budget.AddFinalizedBudget(finalizedBudgetBroadcast); budget.AddFinalizedBudget(finalizedBudgetBroadcast);
@ -198,6 +201,8 @@ CBudgetDB::CBudgetDB()
bool CBudgetDB::Write(const CBudgetManager& objToSave) bool CBudgetDB::Write(const CBudgetManager& objToSave)
{ {
LOCK(objToSave.cs);
int64_t nStart = GetTimeMillis(); int64_t nStart = GetTimeMillis();
// serialize, checksum data up to that point, then append checksum // serialize, checksum data up to that point, then append checksum
@ -230,6 +235,7 @@ bool CBudgetDB::Write(const CBudgetManager& objToSave)
CBudgetDB::ReadResult CBudgetDB::Read(CBudgetManager& objToLoad, bool fDryRun) CBudgetDB::ReadResult CBudgetDB::Read(CBudgetManager& objToLoad, bool fDryRun)
{ {
LOCK(objToLoad.cs);
int64_t nStart = GetTimeMillis(); int64_t nStart = GetTimeMillis();
// open input file, and associate with CAutoFile // open input file, and associate with CAutoFile
@ -349,7 +355,6 @@ void DumpBudgets()
bool CBudgetManager::AddFinalizedBudget(CFinalizedBudget& finalizedBudget) bool CBudgetManager::AddFinalizedBudget(CFinalizedBudget& finalizedBudget)
{ {
LOCK(cs);
std::string strError = ""; std::string strError = "";
if(!finalizedBudget.IsValid(strError)) return false; if(!finalizedBudget.IsValid(strError)) return false;
@ -405,6 +410,8 @@ void CBudgetManager::CheckAndRemove()
void CBudgetManager::FillBlockPayee(CMutableTransaction& txNew, CAmount nFees) void CBudgetManager::FillBlockPayee(CMutableTransaction& txNew, CAmount nFees)
{ {
LOCK(cs);
CBlockIndex* pindexPrev = chainActive.Tip(); CBlockIndex* pindexPrev = chainActive.Tip();
if(!pindexPrev) return; if(!pindexPrev) return;
@ -480,13 +487,18 @@ CBudgetProposal *CBudgetManager::FindProposal(const std::string &strProposalName
CBudgetProposal *CBudgetManager::FindProposal(uint256 nHash) CBudgetProposal *CBudgetManager::FindProposal(uint256 nHash)
{ {
LOCK(cs);
if(mapProposals.count(nHash)) if(mapProposals.count(nHash))
return &mapProposals[nHash]; return &mapProposals[nHash];
return NULL; return NULL;
} }
bool CBudgetManager::IsBudgetPaymentBlock(int nBlockHeight){ bool CBudgetManager::IsBudgetPaymentBlock(int nBlockHeight)
{
LOCK(cs);
int nHighestCount = -1; int nHighestCount = -1;
std::map<uint256, CFinalizedBudget>::iterator it = mapFinalizedBudgets.begin(); std::map<uint256, CFinalizedBudget>::iterator it = mapFinalizedBudgets.begin();
@ -529,6 +541,8 @@ bool CBudgetManager::HasNextFinalizedBudget()
bool CBudgetManager::IsTransactionValid(const CTransaction& txNew, int nBlockHeight) bool CBudgetManager::IsTransactionValid(const CTransaction& txNew, int nBlockHeight)
{ {
LOCK(cs);
int nHighestCount = 0; int nHighestCount = 0;
std::vector<CFinalizedBudget*> ret; std::vector<CFinalizedBudget*> ret;
@ -576,6 +590,8 @@ bool CBudgetManager::IsTransactionValid(const CTransaction& txNew, int nBlockHei
std::vector<CBudgetProposal*> CBudgetManager::GetAllProposals() std::vector<CBudgetProposal*> CBudgetManager::GetAllProposals()
{ {
LOCK(cs);
std::vector<CBudgetProposal*> vBudgetProposalRet; std::vector<CBudgetProposal*> vBudgetProposalRet;
std::map<uint256, CBudgetProposal>::iterator it = mapProposals.begin(); std::map<uint256, CBudgetProposal>::iterator it = mapProposals.begin();
@ -606,6 +622,8 @@ struct sortProposalsByVotes {
//Need to review this function //Need to review this function
std::vector<CBudgetProposal*> CBudgetManager::GetBudget() std::vector<CBudgetProposal*> CBudgetManager::GetBudget()
{ {
LOCK(cs);
// ------- Sort budgets by Yes Count // ------- Sort budgets by Yes Count
std::vector<std::pair<CBudgetProposal*, int> > vBudgetPorposalsSort; std::vector<std::pair<CBudgetProposal*, int> > vBudgetPorposalsSort;
@ -667,6 +685,8 @@ struct sortFinalizedBudgetsByVotes {
std::vector<CFinalizedBudget*> CBudgetManager::GetFinalizedBudgets() std::vector<CFinalizedBudget*> CBudgetManager::GetFinalizedBudgets()
{ {
LOCK(cs);
std::vector<CFinalizedBudget*> vFinalizedBudgetsRet; std::vector<CFinalizedBudget*> vFinalizedBudgetsRet;
std::vector<std::pair<CFinalizedBudget*, int> > vFinalizedBudgetsSort; std::vector<std::pair<CFinalizedBudget*, int> > vFinalizedBudgetsSort;
@ -694,6 +714,8 @@ std::vector<CFinalizedBudget*> CBudgetManager::GetFinalizedBudgets()
std::string CBudgetManager::GetRequiredPaymentsString(int nBlockHeight) std::string CBudgetManager::GetRequiredPaymentsString(int nBlockHeight)
{ {
LOCK(cs);
std::string ret = "unknown-budget"; std::string ret = "unknown-budget";
std::map<uint256, CFinalizedBudget>::iterator it = mapFinalizedBudgets.begin(); std::map<uint256, CFinalizedBudget>::iterator it = mapFinalizedBudgets.begin();
@ -743,6 +765,8 @@ CAmount CBudgetManager::GetTotalBudget(int nHeight)
void CBudgetManager::NewBlock() void CBudgetManager::NewBlock()
{ {
LOCK(cs);
if (masternodeSync.RequestedMasternodeAssets <= MASTERNODE_SYNC_BUDGET) return; if (masternodeSync.RequestedMasternodeAssets <= MASTERNODE_SYNC_BUDGET) return;
if (strBudgetMode == "suggest") { //suggest the budget we see if (strBudgetMode == "suggest") { //suggest the budget we see
@ -935,6 +959,8 @@ bool CBudgetManager::PropExists(uint256 nHash)
void CBudgetManager::Sync(CNode* pfrom, uint256 nProp) void CBudgetManager::Sync(CNode* pfrom, uint256 nProp)
{ {
LOCK(cs);
/* /*
Sync with a client on the network Sync with a client on the network
@ -1472,6 +1498,8 @@ bool CFinalizedBudget::AddOrUpdateVote(CFinalizedBudgetVote& vote, std::string&
//evaluate if we should vote for this. Masternode only //evaluate if we should vote for this. Masternode only
void CFinalizedBudget::AutoCheck() void CFinalizedBudget::AutoCheck()
{ {
LOCK(cs);
if(!fMasterNode || fAutoChecked) return; if(!fMasterNode || fAutoChecked) return;
//do this 1 in 20 blocks -- spread out the voting activity on mainnet //do this 1 in 20 blocks -- spread out the voting activity on mainnet
@ -1538,7 +1566,9 @@ CAmount CFinalizedBudget::GetTotalPayout()
return ret; return ret;
} }
std::string CFinalizedBudget::GetProposals() { std::string CFinalizedBudget::GetProposals()
{
LOCK(cs);
std::string ret = ""; std::string ret = "";
BOOST_FOREACH(CTxBudgetPayment& budgetPayment, vecBudgetPayments){ BOOST_FOREACH(CTxBudgetPayment& budgetPayment, vecBudgetPayments){

View File

@ -17,6 +17,8 @@
using namespace std; using namespace std;
extern CCriticalSection cs_budget;
class CBudgetManager; class CBudgetManager;
class CFinalizedBudgetBroadcast; class CFinalizedBudgetBroadcast;
class CFinalizedBudget; class CFinalizedBudget;
@ -73,13 +75,14 @@ public:
class CBudgetManager class CBudgetManager
{ {
private: private:
// critical section to protect the inner data structures
mutable CCriticalSection cs;
//hold txes until they mature enough to use //hold txes until they mature enough to use
map<uint256, CTransaction> mapCollateral; map<uint256, CTransaction> mapCollateral;
public: public:
// critical section to protect the inner data structures
mutable CCriticalSection cs;
// keep track of the scanning errors I've seen // keep track of the scanning errors I've seen
map<uint256, CBudgetProposal> mapProposals; map<uint256, CBudgetProposal> mapProposals;
map<uint256, CFinalizedBudget> mapFinalizedBudgets; map<uint256, CFinalizedBudget> mapFinalizedBudgets;
@ -128,6 +131,8 @@ public:
void CheckOrphanVotes(); void CheckOrphanVotes();
void Clear(){ void Clear(){
LOCK(cs);
LogPrintf("Budget object cleared\n"); LogPrintf("Budget object cleared\n");
mapProposals.clear(); mapProposals.clear();
mapFinalizedBudgets.clear(); mapFinalizedBudgets.clear();
@ -221,6 +226,8 @@ public:
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight); bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
bool GetBudgetPaymentByBlock(int64_t nBlockHeight, CTxBudgetPayment& payment) bool GetBudgetPaymentByBlock(int64_t nBlockHeight, CTxBudgetPayment& payment)
{ {
LOCK(cs);
int i = nBlockHeight - GetBlockStart(); int i = nBlockHeight - GetBlockStart();
if(i < 0) return false; if(i < 0) return false;
if(i > (int)vecBudgetPayments.size() - 1) return false; if(i > (int)vecBudgetPayments.size() - 1) return false;
@ -229,6 +236,8 @@ public:
} }
bool GetPayeeAndAmount(int64_t nBlockHeight, CScript& payee, CAmount& nAmount) bool GetPayeeAndAmount(int64_t nBlockHeight, CScript& payee, CAmount& nAmount)
{ {
LOCK(cs);
int i = nBlockHeight - GetBlockStart(); int i = nBlockHeight - GetBlockStart();
if(i < 0) return false; if(i < 0) return false;
if(i > (int)vecBudgetPayments.size() - 1) return false; if(i > (int)vecBudgetPayments.size() - 1) return false;

View File

@ -14,11 +14,13 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
CCriticalSection cs_masternodepayments;
/** Object for who's going to get paid on which blocks */ /** Object for who's going to get paid on which blocks */
CMasternodePayments masternodePayments; CMasternodePayments masternodePayments;
CCriticalSection cs_vecPayments;
CCriticalSection cs_mapMasternodeBlocks;
CCriticalSection cs_mapMasternodePayeeVotes;
// //
// CMasternodePaymentDB // CMasternodePaymentDB
// //
@ -353,9 +355,6 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
LogPrintf("mnget - Sent Masternode winners to %s\n", pfrom->addr.ToString().c_str()); LogPrintf("mnget - Sent Masternode winners to %s\n", pfrom->addr.ToString().c_str());
} }
else if (strCommand == "mnw") { //Masternode Payments Declare Winner else if (strCommand == "mnw") { //Masternode Payments Declare Winner
// disabled due to locking issues
LOCK(cs_masternodepayments);
//this is required in litemodef //this is required in litemodef
CMasternodePaymentWinner winner; CMasternodePaymentWinner winner;
vRecv >> winner; vRecv >> winner;
@ -439,6 +438,8 @@ bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee)
// -- Only look ahead up to 8 blocks to allow for propagation of the latest 2 winners // -- Only look ahead up to 8 blocks to allow for propagation of the latest 2 winners
bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight) bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
{ {
LOCK(cs_mapMasternodeBlocks);
CBlockIndex* pindexPrev = chainActive.Tip(); CBlockIndex* pindexPrev = chainActive.Tip();
if(pindexPrev == NULL) return false; if(pindexPrev == NULL) return false;
@ -467,15 +468,19 @@ bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerI
return false; return false;
} }
if(mapMasternodePayeeVotes.count(winnerIn.GetHash())){ {
return false; LOCK2(cs_mapMasternodePayeeVotes, cs_mapMasternodeBlocks);
}
if(mapMasternodePayeeVotes.count(winnerIn.GetHash())){
return false;
}
mapMasternodePayeeVotes[winnerIn.GetHash()] = winnerIn; mapMasternodePayeeVotes[winnerIn.GetHash()] = winnerIn;
if(!mapMasternodeBlocks.count(winnerIn.nBlockHeight)){ if(!mapMasternodeBlocks.count(winnerIn.nBlockHeight)){
CMasternodeBlockPayees blockPayees(winnerIn.nBlockHeight); CMasternodeBlockPayees blockPayees(winnerIn.nBlockHeight);
mapMasternodeBlocks[winnerIn.nBlockHeight] = blockPayees; mapMasternodeBlocks[winnerIn.nBlockHeight] = blockPayees;
}
} }
int n = 1; int n = 1;
@ -487,6 +492,8 @@ bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerI
bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew) bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew)
{ {
LOCK(cs_vecPayments);
int nMaxSignatures = 0; int nMaxSignatures = 0;
std::string strPayeesPossible = ""; std::string strPayeesPossible = "";
@ -532,6 +539,8 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew)
std::string CMasternodeBlockPayees::GetRequiredPaymentsString() std::string CMasternodeBlockPayees::GetRequiredPaymentsString()
{ {
LOCK(cs_vecPayments);
std::string ret = "Unknown"; std::string ret = "Unknown";
BOOST_FOREACH(CMasternodePayee& payee, vecPayments) BOOST_FOREACH(CMasternodePayee& payee, vecPayments)
@ -552,6 +561,8 @@ std::string CMasternodeBlockPayees::GetRequiredPaymentsString()
std::string CMasternodePayments::GetRequiredPaymentsString(int nBlockHeight) std::string CMasternodePayments::GetRequiredPaymentsString(int nBlockHeight)
{ {
LOCK(cs_mapMasternodeBlocks);
if(mapMasternodeBlocks.count(nBlockHeight)){ if(mapMasternodeBlocks.count(nBlockHeight)){
return mapMasternodeBlocks[nBlockHeight].GetRequiredPaymentsString(); return mapMasternodeBlocks[nBlockHeight].GetRequiredPaymentsString();
} }
@ -561,6 +572,8 @@ std::string CMasternodePayments::GetRequiredPaymentsString(int nBlockHeight)
bool CMasternodePayments::IsTransactionValid(const CTransaction& txNew, int nBlockHeight) bool CMasternodePayments::IsTransactionValid(const CTransaction& txNew, int nBlockHeight)
{ {
LOCK(cs_mapMasternodeBlocks);
if(mapMasternodeBlocks.count(nBlockHeight)){ if(mapMasternodeBlocks.count(nBlockHeight)){
return mapMasternodeBlocks[nBlockHeight].IsTransactionValid(txNew); return mapMasternodeBlocks[nBlockHeight].IsTransactionValid(txNew);
} }
@ -570,7 +583,7 @@ bool CMasternodePayments::IsTransactionValid(const CTransaction& txNew, int nBlo
void CMasternodePayments::CleanPaymentList() void CMasternodePayments::CleanPaymentList()
{ {
LOCK(cs_masternodepayments); LOCK(cs_mapMasternodePayeeVotes);
if(chainActive.Tip() == NULL) return; if(chainActive.Tip() == NULL) return;
@ -634,8 +647,6 @@ bool CMasternodePaymentWinner::IsValid(std::string& strError)
bool CMasternodePayments::ProcessBlock(int nBlockHeight) bool CMasternodePayments::ProcessBlock(int nBlockHeight)
{ {
LOCK(cs_masternodepayments);
if(!fMasterNode) return false; if(!fMasterNode) return false;
//reference node - hybrid mode //reference node - hybrid mode
@ -663,12 +674,6 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
if(budget.IsBudgetPaymentBlock(nBlockHeight)){ if(budget.IsBudgetPaymentBlock(nBlockHeight)){
//is budget payment block -- handled by the budgeting software //is budget payment block -- handled by the budgeting software
} else { } else {
uint256 hash;
if(!GetBlockHash(hash, nBlockHeight-100)) return false;
unsigned int nHash;
memcpy(&nHash, &hash, 2);
LogPrintf("CMasternodePayments::ProcessBlock() Start nHeight %d - vin %s. \n", nBlockHeight, activeMasternode.vin.ToString().c_str()); LogPrintf("CMasternodePayments::ProcessBlock() Start nHeight %d - vin %s. \n", nBlockHeight, activeMasternode.vin.ToString().c_str());
// pay to the oldest MN that still had no payment but its input is old enough and it was active long enough // pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
@ -751,7 +756,7 @@ bool CMasternodePaymentWinner::SignatureValid()
void CMasternodePayments::Sync(CNode* node, int nCountNeeded) void CMasternodePayments::Sync(CNode* node, int nCountNeeded)
{ {
LOCK(cs_masternodepayments); LOCK(cs_mapMasternodePayeeVotes);
if(chainActive.Tip() == NULL) return; if(chainActive.Tip() == NULL) return;
@ -786,7 +791,7 @@ std::string CMasternodePayments::ToString() const
int CMasternodePayments::GetOldestBlock() int CMasternodePayments::GetOldestBlock()
{ {
LOCK(cs_masternodepayments); LOCK(cs_mapMasternodeBlocks);
int nOldestBlock = std::numeric_limits<int>::max(); int nOldestBlock = std::numeric_limits<int>::max();
@ -805,7 +810,7 @@ int CMasternodePayments::GetOldestBlock()
int CMasternodePayments::GetNewestBlock() int CMasternodePayments::GetNewestBlock()
{ {
LOCK(cs_masternodepayments); LOCK(cs_mapMasternodeBlocks);
int nNewestBlock = 0; int nNewestBlock = 0;

View File

@ -13,6 +13,10 @@
using namespace std; using namespace std;
extern CCriticalSection cs_vecPayments;
extern CCriticalSection cs_mapMasternodeBlocks;
extern CCriticalSection cs_mapMasternodePayeeVotes;
class CMasternodePayments; class CMasternodePayments;
class CMasternodePaymentWinner; class CMasternodePaymentWinner;
class CMasternodeBlockPayees; class CMasternodeBlockPayees;
@ -96,6 +100,8 @@ public:
} }
void AddPayee(CScript payeeIn, int nIncrement){ void AddPayee(CScript payeeIn, int nIncrement){
LOCK(cs_vecPayments);
BOOST_FOREACH(CMasternodePayee& payee, vecPayments){ BOOST_FOREACH(CMasternodePayee& payee, vecPayments){
if(payee.scriptPubKey == payeeIn) { if(payee.scriptPubKey == payeeIn) {
payee.nVotes += nIncrement; payee.nVotes += nIncrement;
@ -109,6 +115,8 @@ public:
bool GetPayee(CScript& payee) bool GetPayee(CScript& payee)
{ {
LOCK(cs_vecPayments);
int nVotes = -1; int nVotes = -1;
BOOST_FOREACH(CMasternodePayee& p, vecPayments){ BOOST_FOREACH(CMasternodePayee& p, vecPayments){
if(p.nVotes > nVotes){ if(p.nVotes > nVotes){
@ -122,6 +130,8 @@ public:
bool HasPayeeWithVotes(CScript payee, int nVotesReq) bool HasPayeeWithVotes(CScript payee, int nVotesReq)
{ {
LOCK(cs_vecPayments);
BOOST_FOREACH(CMasternodePayee& p, vecPayments){ BOOST_FOREACH(CMasternodePayee& p, vecPayments){
if(p.nVotes >= nVotesReq && p.scriptPubKey == payee) return true; if(p.nVotes >= nVotesReq && p.scriptPubKey == payee) return true;
} }
@ -225,6 +235,7 @@ public:
} }
void Clear() { void Clear() {
LOCK2(cs_mapMasternodeBlocks, cs_mapMasternodePayeeVotes);
mapMasternodeBlocks.clear(); mapMasternodeBlocks.clear();
mapMasternodePayeeVotes.clear(); mapMasternodePayeeVotes.clear();
} }
@ -241,6 +252,8 @@ public:
bool IsScheduled(CMasternode& mn, int nNotBlockHeight); bool IsScheduled(CMasternode& mn, int nNotBlockHeight);
bool CanVote(COutPoint outMasternode, int nBlockHeight) { bool CanVote(COutPoint outMasternode, int nBlockHeight) {
LOCK(cs_mapMasternodePayeeVotes);
if(mapMasternodesLastVote.count(outMasternode.hash + outMasternode.n)) { if(mapMasternodesLastVote.count(outMasternode.hash + outMasternode.n)) {
if(mapMasternodesLastVote[outMasternode.hash + outMasternode.n] == nBlockHeight) { if(mapMasternodesLastVote[outMasternode.hash + outMasternode.n] == nBlockHeight) {
return false; return false;