Skip to content

Commit

Permalink
[Refactor] Fix checks order for mnw processing
Browse files Browse the repository at this point in the history
  • Loading branch information
random-zebra committed Oct 30, 2021
1 parent 729d2f9 commit e68773b
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 45 deletions.
72 changes: 43 additions & 29 deletions src/masternode-payments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,7 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, CValidationState& state, in
{
int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 100);
if (n < 1 || n > MNPAYMENTS_SIGNATURES_TOTAL) {
//It's common to have masternodes mistakenly think they are in the top 10
// We don't want to print all of these messages, or punish them unless they're way off
std::string strError = strprintf("Masternode not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL, n);
if (n > MNPAYMENTS_SIGNATURES_TOTAL * 2) {
LogPrint(BCLog::MASTERNODE,"CMasternodePaymentWinner::IsValid - %s\n", strError);
//if (masternodeSync.IsSynced()) Misbehaving(pnode->GetId(), 20);
}
return state.Error(strError);
return state.Error(strprintf("Masternode not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL, n));
}

// Must be a P2PKH
Expand Down Expand Up @@ -474,25 +467,12 @@ bool CMasternodePayments::ProcessMNWinner(CMasternodePaymentWinner& winner, CNod
return state.Error("mnw old message version");
}

if (!winner.IsValid(pfrom, state, nHeight)) {
// error cause set internally
return false;
}

if (!CanVote(winner.vinMasternode.prevout, winner.nBlockHeight)) {
return state.Error("MN already voted");
}

// See if this winner was signed with a dmn or a legacy masternode
bool is_valid_sig = false;
auto mnList = deterministicMNManager->GetListAtChainTip();
auto dmn = mnList.GetMNByCollateral(winner.vinMasternode.prevout);
if (dmn) {
// DMN: Check BLS signature
is_valid_sig = winner.CheckSignature(dmn->pdmnState->pubKeyOperator.Get());
} else {
// Legacy masternode
const CMasternode* pmn = mnodeman.Find(winner.vinMasternode.prevout);
// See if the mnw signer exists, and whether it's a legacy or DMN masternode
const CMasternode* pmn{nullptr};
auto dmn = deterministicMNManager->GetListAtChainTip().GetMNByCollateral(winner.vinMasternode.prevout);
if (dmn == nullptr) {
// legacy masternode
pmn = mnodeman.Find(winner.vinMasternode.prevout);
if (pmn == nullptr) {
// it could be a non-synced masternode. ask for the mnb
LogPrint(BCLog::MASTERNODE, "mnw - unknown masternode %s\n", winner.vinMasternode.prevout.hash.ToString());
Expand All @@ -501,18 +481,39 @@ bool CMasternodePayments::ProcessMNWinner(CMasternodePaymentWinner& winner, CNod
if (pfrom && masternodeSync.IsSynced()) mnodeman.AskForMN(pfrom, winner.vinMasternode);
return state.Error("Invalid voter or voter mnwinner signature");
}
is_valid_sig = winner.CheckSignature(pmn->pubKeyMasternode.GetID());
}
// either deterministic or legacy. not both
assert((dmn && !pmn) || (!dmn && pmn));

// See if the masternode is in the quorum (top-MNPAYMENTS_SIGNATURES_TOTAL)
if (!winner.IsValid(pfrom, state, nHeight)) {
// error cause set internally
return false;
}

// See if this masternode has already voted for this block height
if (!CanVote(winner.vinMasternode.prevout, winner.nBlockHeight)) {
return state.Error("MN already voted");
}

// Check signature
bool is_valid_sig = dmn ? winner.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())
: winner.CheckSignature(pmn->pubKeyMasternode.GetID());

if (!is_valid_sig) {
LogPrint(BCLog::MASTERNODE, "%s : mnw - invalid signature\n", __func__);
LogPrint(BCLog::MASTERNODE, "%s : mnw - invalid signature for %s masternode: %s\n",
__func__, (dmn ? "deterministic" : "legacy"), winner.vinMasternode.prevout.hash.ToString());
if (pfrom) {
LOCK(cs_main);
Misbehaving(pfrom->GetId(), 20);
}
return state.Error("invalid voter mnwinner signature");
}

// Record vote
RecordWinnerVote(winner.vinMasternode.prevout, winner.nBlockHeight);

// Add winner
if (!AddWinningMasternode(winner)) {
return state.Error("Failed to add mnwinner"); // move state inside AddWinningMasternode
}
Expand Down Expand Up @@ -827,6 +828,19 @@ std::string CMasternodePayments::ToString() const
return info.str();
}

bool CMasternodePayments::CanVote(const COutPoint& outMasternode, int nBlockHeight) const
{
LOCK(cs_mapMasternodePayeeVotes);
const auto it = mapMasternodesLastVote.find(outMasternode);
return it == mapMasternodesLastVote.end() || it->second != nBlockHeight;
}

void CMasternodePayments::RecordWinnerVote(const COutPoint& outMasternode, int nBlockHeight)
{
LOCK(cs_mapMasternodePayeeVotes);
mapMasternodesLastVote[outMasternode] = nBlockHeight;
}

bool IsCoinbaseValueValid(const CTransactionRef& tx, CAmount nBudgetAmt, CValidationState& _state)
{
assert(tx->IsCoinBase());
Expand Down
23 changes: 7 additions & 16 deletions src/masternode-payments.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ class CMasternodePayments : public CValidationInterface
public:
std::map<uint256, CMasternodePaymentWinner> mapMasternodePayeeVotes;
std::map<int, CMasternodeBlockPayees> mapMasternodeBlocks;
std::map<COutPoint, int> mapMasternodesLastVote; //prevout, nBlockHeight

CMasternodePayments()
{
Expand Down Expand Up @@ -243,28 +242,20 @@ class CMasternodePayments : public CValidationInterface
bool IsTransactionValid(const CTransaction& txNew, const CBlockIndex* pindexPrev);
bool IsScheduled(const CMasternode& mn, int nNotBlockHeight);

bool CanVote(const COutPoint& outMasternode, int nBlockHeight)
{
LOCK(cs_mapMasternodePayeeVotes);

if (mapMasternodesLastVote.count(outMasternode)) {
if (mapMasternodesLastVote[outMasternode] == nBlockHeight) {
return false;
}
}

//record this masternode voted
mapMasternodesLastVote[outMasternode] = nBlockHeight;
return true;
}

bool ProcessMNWinner(CMasternodePaymentWinner& winner, CNode* pfrom, CValidationState& state);
void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
std::string GetRequiredPaymentsString(int nBlockHeight);
void FillBlockPayee(CMutableTransaction& txCoinbase, CMutableTransaction& txCoinstake, const CBlockIndex* pindexPrev, bool fProofOfStake) const;
std::string ToString() const;

SERIALIZE_METHODS(CMasternodePayments, obj) { READWRITE(obj.mapMasternodePayeeVotes, obj.mapMasternodeBlocks); }

private:
// keep track of last voted height for mnw signers
std::map<COutPoint, int> mapMasternodesLastVote; //prevout, nBlockHeight

bool CanVote(const COutPoint& outMasternode, int nBlockHeight) const;
void RecordWinnerVote(const COutPoint& outMasternode, int nBlockHeight);
};


Expand Down

0 comments on commit e68773b

Please sign in to comment.