Skip to content

Commit

Permalink
refactor: trim and document assumptions for Get*MN* and friends
Browse files Browse the repository at this point in the history
  • Loading branch information
kwvg committed Jul 19, 2024
1 parent 8b6f83d commit 378f219
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 11 deletions.
16 changes: 12 additions & 4 deletions src/evo/deterministicmns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ CDeterministicMNList CDeterministicMNList::ApplyDiff(gsl::not_null<const CBlockI
for (const auto& id : diff.removedMns) {
auto dmn = result.GetMNByInternalId(id);
if (!dmn) {
throw(std::runtime_error(strprintf("%s: can't find a removed masternode, id=%d", __func__, id)));
throw std::runtime_error(strprintf("%s: can't find a removed masternode, id=%d", __func__, id));
}
result.RemoveMN(dmn->proTxHash);
}
Expand All @@ -435,6 +435,9 @@ CDeterministicMNList CDeterministicMNList::ApplyDiff(gsl::not_null<const CBlockI
}
for (const auto& p : diff.updatedMNs) {
auto dmn = result.GetMNByInternalId(p.first);
if (!dmn) {
throw std::runtime_error(strprintf("%s: can't find an updated masternode, id=%d", __func__, p.first));
}
result.UpdateMN(*dmn, p.second);
}

Expand Down Expand Up @@ -816,7 +819,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr");
}

CDeterministicMNCPtr dmn = newList.GetMN(opt_proTx->proTxHash);
auto dmn = newList.GetMN(opt_proTx->proTxHash);
if (!dmn) {
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
}
Expand Down Expand Up @@ -857,7 +860,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload");
}

CDeterministicMNCPtr dmn = newList.GetMN(opt_proTx->proTxHash);
auto dmn = newList.GetMN(opt_proTx->proTxHash);
if (!dmn) {
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
}
Expand Down Expand Up @@ -885,7 +888,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload");
}

CDeterministicMNCPtr dmn = newList.GetMN(opt_proTx->proTxHash);
auto dmn = newList.GetMN(opt_proTx->proTxHash);
if (!dmn) {
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
}
Expand Down Expand Up @@ -945,6 +948,8 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
// current block. We still pay that MN one last time, however.
if (payee && newList.HasMN(payee->proTxHash)) {
auto dmn = newList.GetMN(payee->proTxHash);
// HasMN has reported that GetMN should succeed, enforce that.
assert(dmn);
auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
newState->nLastPaidHeight = nHeight;
// Starting from v19 and until MNRewardReallocation, EvoNodes will be paid 4 blocks in a row
Expand All @@ -960,6 +965,9 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
newList.UpdateMN(payee->proTxHash, newState);
if (debugLogs) {
dmn = newList.GetMN(payee->proTxHash);
// Since the previous GetMN query returned a value, after an update, querying the same
// hash *must* give us a result. If it doesn't, that would be a potential logic bug.
assert(dmn);
LogPrint(BCLog::MNPAYMENTS, "CDeterministicMNManager::%s -- MN %s, nConsecutivePayments=%d\n",
__func__, dmn->proTxHash.ToString(), dmn->pdmnState->nConsecutivePayments);
}
Expand Down
6 changes: 6 additions & 0 deletions src/governance/governance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,9 @@ void CGovernanceManager::RemoveInvalidVotes()
std::vector<COutPoint> changedKeyMNs;
for (const auto& p : diff.updatedMNs) {
auto oldDmn = lastMNListForVotingKeys->GetMNByInternalId(p.first);
// BuildDiff will construct itself with MNs that we already have knowledge
// of, meaning that fetch operations should never fail.
assert(oldDmn);
if ((p.second.fields & CDeterministicMNStateDiff::Field_keyIDVoting) && p.second.state.keyIDVoting != oldDmn->pdmnState->keyIDVoting) {
changedKeyMNs.emplace_back(oldDmn->collateralOutpoint);
} else if ((p.second.fields & CDeterministicMNStateDiff::Field_pubKeyOperator) && p.second.state.pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) {
Expand All @@ -1567,6 +1570,9 @@ void CGovernanceManager::RemoveInvalidVotes()
}
for (const auto& id : diff.removedMns) {
auto oldDmn = lastMNListForVotingKeys->GetMNByInternalId(id);
// BuildDiff will construct itself with MNs that we already have knowledge
// of, meaning that fetch operations should never fail.
assert(oldDmn);
changedKeyMNs.emplace_back(oldDmn->collateralOutpoint);
}

Expand Down
5 changes: 4 additions & 1 deletion src/masternode/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ void CActiveMasternodeManager::InitInternal(const CBlockIndex* pindex)

CDeterministicMNList mnList = Assert(m_dmnman)->GetListForBlock(pindex);

CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(m_info.blsPubKeyOperator);
auto dmn = mnList.GetMNByOperatorKey(m_info.blsPubKeyOperator);
if (!dmn) {
// MN not appeared on the chain yet
return;
Expand Down Expand Up @@ -166,6 +166,9 @@ void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, con

auto oldDmn = oldMNList.GetMN(cur_protx_hash);
auto newDmn = newMNList.GetMN(cur_protx_hash);
if (oldDmn == nullptr || newDmn == nullptr) {
return reset(MASTERNODE_ERROR);
}
if (newDmn->pdmnState->pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) {
// MN operator key changed or revoked
return reset(MASTERNODE_OPERATOR_KEY_CHANGED);
Expand Down
3 changes: 2 additions & 1 deletion src/qt/masternodelist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ CDeterministicMNCPtr MasternodeList::GetSelectedDIP3MN()
uint256 proTxHash;
proTxHash.SetHex(strProTxHash);

return clientModel->getMasternodeList().first.GetMN(proTxHash);;
auto ret = clientModel->getMasternodeList().first.GetMN(proTxHash);
return ret != nullptr ? ret : CDeterministicMNCPtr{};
}

void MasternodeList::extraInfoDIP3_clicked()
Expand Down
6 changes: 6 additions & 0 deletions src/rpc/evo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1709,13 +1709,19 @@ static RPCHelpMan protx_listdiff()
UniValue jremovedMNs(UniValue::VARR);
for(const auto& internal_id : mnDiff.removedMns) {
auto dmn = baseBlockMNList.GetMNByInternalId(internal_id);
// BuildDiff will construct itself with MNs that we already have knowledge
// of, meaning that fetch operations should never fail.
CHECK_NONFATAL(dmn != nullptr);
jremovedMNs.push_back(dmn->proTxHash.ToString());
}
ret.pushKV("removedMNs", jremovedMNs);

UniValue jupdatedMNs(UniValue::VARR);
for(const auto& [internal_id, stateDiff] : mnDiff.updatedMNs) {
auto dmn = baseBlockMNList.GetMNByInternalId(internal_id);
// BuildDiff will construct itself with MNs that we already have knowledge
// of, meaning that fetch operations should never fail.
CHECK_NONFATAL(dmn != nullptr);
UniValue obj(UniValue::VOBJ);
obj.pushKV(dmn->proTxHash.ToString(), stateDiff.ToJson(dmn->nType));
jupdatedMNs.push_back(obj);
Expand Down
10 changes: 6 additions & 4 deletions src/rpc/masternode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ static RPCHelpMan masternode_status()
// keep compatibility with legacy status for now (might get deprecated/removed later)
mnObj.pushKV("outpoint", node.mn_activeman->GetOutPoint().ToStringShort());
mnObj.pushKV("service", node.mn_activeman->GetService().ToString());
CDeterministicMNCPtr dmn = node.dmnman->GetListAtChainTip().GetMN(node.mn_activeman->GetProTxHash());
auto dmn = node.dmnman->GetListAtChainTip().GetMN(node.mn_activeman->GetProTxHash());
if (dmn) {
mnObj.pushKV("proTxHash", dmn->proTxHash.ToString());
mnObj.pushKV("type", std::string(GetMnType(dmn->nType).description));
Expand Down Expand Up @@ -316,9 +316,11 @@ static RPCHelpMan masternode_winners()
for (int h = nStartHeight; h <= nChainTipHeight; h++) {
const CBlockIndex* pIndex = pindexTip->GetAncestor(h - 1);
auto payee = node.dmnman->GetListForBlock(pIndex).GetMNPayee(pIndex);
std::string strPayments = GetRequiredPaymentsString(*node.govman, tip_mn_list, h, payee);
if (strFilter != "" && strPayments.find(strFilter) == std::string::npos) continue;
obj.pushKV(strprintf("%d", h), strPayments);
if (payee != nullptr) {
std::string strPayments = GetRequiredPaymentsString(*node.govman, tip_mn_list, h, payee);
if (strFilter != "" && strPayments.find(strFilter) == std::string::npos) continue;
obj.pushKV(strprintf("%d", h), strPayments);
}
}

auto projection = node.dmnman->GetListForBlock(pindexTip).GetProjectedMNPayees(pindexTip, 20);
Expand Down
4 changes: 3 additions & 1 deletion src/test/evo_deterministicmns_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ void FuncDIP3Protx(TestChainSetup& setup)
// check MN reward payments
for (size_t i = 0; i < 20; i++) {
auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip());
BOOST_ASSERT(dmnExpectedPayee);

CBlock block = setup.CreateAndProcessBlock({}, setup.coinbaseKey);
dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip());
Expand Down Expand Up @@ -522,7 +523,7 @@ void FuncDIP3Protx(TestChainSetup& setup)
// test that the revoked MN does not get paid anymore
for (size_t i = 0; i < 20; i++) {
auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip());
BOOST_ASSERT(dmnExpectedPayee->proTxHash != dmnHashes[0]);
BOOST_ASSERT(dmnExpectedPayee && dmnExpectedPayee->proTxHash != dmnHashes[0]);

CBlock block = setup.CreateAndProcessBlock({}, setup.coinbaseKey);
dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip());
Expand Down Expand Up @@ -570,6 +571,7 @@ void FuncDIP3Protx(TestChainSetup& setup)
bool foundRevived = false;
for (size_t i = 0; i < 20; i++) {
auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip());
BOOST_ASSERT(dmnExpectedPayee);
if (dmnExpectedPayee->proTxHash == dmnHashes[0]) {
foundRevived = true;
}
Expand Down

0 comments on commit 378f219

Please sign in to comment.