refactor: trim and document assumptions for Get*MN* and friends

This commit is contained in:
Kittywhiskers Van Gogh 2024-11-14 10:08:05 +00:00
parent 8c9f57dac4
commit a014cf3703
No known key found for this signature in database
GPG Key ID: 30CD0C065E5C4AAD
7 changed files with 39 additions and 11 deletions

View File

@ -428,7 +428,7 @@ CDeterministicMNList CDeterministicMNList::ApplyDiff(gsl::not_null<const CBlockI
for (const auto& id : diff.removedMns) { for (const auto& id : diff.removedMns) {
auto dmn = result.GetMNByInternalId(id); auto dmn = result.GetMNByInternalId(id);
if (!dmn) { 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); result.RemoveMN(dmn->proTxHash);
} }
@ -437,6 +437,9 @@ CDeterministicMNList CDeterministicMNList::ApplyDiff(gsl::not_null<const CBlockI
} }
for (const auto& p : diff.updatedMNs) { for (const auto& p : diff.updatedMNs) {
auto dmn = result.GetMNByInternalId(p.first); 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); result.UpdateMN(*dmn, p.second);
} }
@ -818,7 +821,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr"); 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) { if (!dmn) {
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash"); return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
} }
@ -859,7 +862,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload"); 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) { if (!dmn) {
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash"); return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
} }
@ -887,7 +890,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload"); 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) { if (!dmn) {
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash"); return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
} }
@ -947,6 +950,8 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
// current block. We still pay that MN one last time, however. // current block. We still pay that MN one last time, however.
if (payee && newList.HasMN(payee->proTxHash)) { if (payee && newList.HasMN(payee->proTxHash)) {
auto dmn = newList.GetMN(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); auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
newState->nLastPaidHeight = nHeight; newState->nLastPaidHeight = nHeight;
// Starting from v19 and until MNRewardReallocation, EvoNodes will be paid 4 blocks in a row // Starting from v19 and until MNRewardReallocation, EvoNodes will be paid 4 blocks in a row
@ -962,6 +967,9 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
newList.UpdateMN(payee->proTxHash, newState); newList.UpdateMN(payee->proTxHash, newState);
if (debugLogs) { if (debugLogs) {
dmn = newList.GetMN(payee->proTxHash); 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", LogPrint(BCLog::MNPAYMENTS, "CDeterministicMNManager::%s -- MN %s, nConsecutivePayments=%d\n",
__func__, dmn->proTxHash.ToString(), dmn->pdmnState->nConsecutivePayments); __func__, dmn->proTxHash.ToString(), dmn->pdmnState->nConsecutivePayments);
} }

View File

@ -1601,6 +1601,9 @@ void CGovernanceManager::RemoveInvalidVotes()
std::vector<COutPoint> changedKeyMNs; std::vector<COutPoint> changedKeyMNs;
for (const auto& p : diff.updatedMNs) { for (const auto& p : diff.updatedMNs) {
auto oldDmn = lastMNListForVotingKeys->GetMNByInternalId(p.first); 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) { if ((p.second.fields & CDeterministicMNStateDiff::Field_keyIDVoting) && p.second.state.keyIDVoting != oldDmn->pdmnState->keyIDVoting) {
changedKeyMNs.emplace_back(oldDmn->collateralOutpoint); changedKeyMNs.emplace_back(oldDmn->collateralOutpoint);
} else if ((p.second.fields & CDeterministicMNStateDiff::Field_pubKeyOperator) && p.second.state.pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) { } else if ((p.second.fields & CDeterministicMNStateDiff::Field_pubKeyOperator) && p.second.state.pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) {
@ -1609,6 +1612,9 @@ void CGovernanceManager::RemoveInvalidVotes()
} }
for (const auto& id : diff.removedMns) { for (const auto& id : diff.removedMns) {
auto oldDmn = lastMNListForVotingKeys->GetMNByInternalId(id); 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); changedKeyMNs.emplace_back(oldDmn->collateralOutpoint);
} }

View File

@ -129,7 +129,7 @@ void CActiveMasternodeManager::InitInternal(const CBlockIndex* pindex)
CDeterministicMNList mnList = Assert(m_dmnman)->GetListForBlock(pindex); CDeterministicMNList mnList = Assert(m_dmnman)->GetListForBlock(pindex);
CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(m_info.blsPubKeyOperator); auto dmn = mnList.GetMNByOperatorKey(m_info.blsPubKeyOperator);
if (!dmn) { if (!dmn) {
// MN not appeared on the chain yet // MN not appeared on the chain yet
return; return;
@ -202,6 +202,9 @@ void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, con
auto oldDmn = oldMNList.GetMN(cur_protx_hash); auto oldDmn = oldMNList.GetMN(cur_protx_hash);
auto newDmn = newMNList.GetMN(cur_protx_hash); auto newDmn = newMNList.GetMN(cur_protx_hash);
if (!oldDmn || !newDmn) {
return reset(MasternodeState::SOME_ERROR);
}
if (newDmn->pdmnState->pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) { if (newDmn->pdmnState->pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) {
// MN operator key changed or revoked // MN operator key changed or revoked
return reset(MasternodeState::OPERATOR_KEY_CHANGED); return reset(MasternodeState::OPERATOR_KEY_CHANGED);

View File

@ -354,7 +354,8 @@ CDeterministicMNCPtr MasternodeList::GetSelectedDIP3MN()
uint256 proTxHash; uint256 proTxHash;
proTxHash.SetHex(strProTxHash); proTxHash.SetHex(strProTxHash);
return clientModel->getMasternodeList().first.GetMN(proTxHash);; // Caller is responsible for nullptr checking return value
return clientModel->getMasternodeList().first.GetMN(proTxHash);
} }
void MasternodeList::extraInfoDIP3_clicked() void MasternodeList::extraInfoDIP3_clicked()

View File

@ -1635,6 +1635,9 @@ static RPCHelpMan protx_listdiff()
UniValue jremovedMNs(UniValue::VARR); UniValue jremovedMNs(UniValue::VARR);
for(const auto& internal_id : mnDiff.removedMns) { for(const auto& internal_id : mnDiff.removedMns) {
auto dmn = baseBlockMNList.GetMNByInternalId(internal_id); 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);
jremovedMNs.push_back(dmn->proTxHash.ToString()); jremovedMNs.push_back(dmn->proTxHash.ToString());
} }
ret.pushKV("removedMNs", jremovedMNs); ret.pushKV("removedMNs", jremovedMNs);
@ -1642,6 +1645,9 @@ static RPCHelpMan protx_listdiff()
UniValue jupdatedMNs(UniValue::VARR); UniValue jupdatedMNs(UniValue::VARR);
for(const auto& [internal_id, stateDiff] : mnDiff.updatedMNs) { for(const auto& [internal_id, stateDiff] : mnDiff.updatedMNs) {
auto dmn = baseBlockMNList.GetMNByInternalId(internal_id); 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);
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.pushKV(dmn->proTxHash.ToString(), stateDiff.ToJson(dmn->nType)); obj.pushKV(dmn->proTxHash.ToString(), stateDiff.ToJson(dmn->nType));
jupdatedMNs.push_back(obj); jupdatedMNs.push_back(obj);

View File

@ -229,7 +229,7 @@ static RPCHelpMan masternode_status()
// keep compatibility with legacy status for now (might get deprecated/removed later) // keep compatibility with legacy status for now (might get deprecated/removed later)
mnObj.pushKV("outpoint", node.mn_activeman->GetOutPoint().ToStringShort()); mnObj.pushKV("outpoint", node.mn_activeman->GetOutPoint().ToStringShort());
mnObj.pushKV("service", node.mn_activeman->GetService().ToStringAddrPort()); mnObj.pushKV("service", node.mn_activeman->GetService().ToStringAddrPort());
CDeterministicMNCPtr dmn = CHECK_NONFATAL(node.dmnman)->GetListAtChainTip().GetMN(node.mn_activeman->GetProTxHash()); auto dmn = CHECK_NONFATAL(node.dmnman)->GetListAtChainTip().GetMN(node.mn_activeman->GetProTxHash());
if (dmn) { if (dmn) {
mnObj.pushKV("proTxHash", dmn->proTxHash.ToString()); mnObj.pushKV("proTxHash", dmn->proTxHash.ToString());
mnObj.pushKV("type", std::string(GetMnType(dmn->nType).description)); mnObj.pushKV("type", std::string(GetMnType(dmn->nType).description));
@ -322,9 +322,11 @@ static RPCHelpMan masternode_winners()
for (int h = nStartHeight; h <= nChainTipHeight; h++) { for (int h = nStartHeight; h <= nChainTipHeight; h++) {
const CBlockIndex* pIndex = pindexTip->GetAncestor(h - 1); const CBlockIndex* pIndex = pindexTip->GetAncestor(h - 1);
auto payee = node.dmnman->GetListForBlock(pIndex).GetMNPayee(pIndex); auto payee = node.dmnman->GetListForBlock(pIndex).GetMNPayee(pIndex);
std::string strPayments = GetRequiredPaymentsString(*CHECK_NONFATAL(node.govman), tip_mn_list, h, payee); if (payee) {
if (strFilter != "" && strPayments.find(strFilter) == std::string::npos) continue; std::string strPayments = GetRequiredPaymentsString(*CHECK_NONFATAL(node.govman), tip_mn_list, h, payee);
obj.pushKV(strprintf("%d", h), strPayments); if (strFilter != "" && strPayments.find(strFilter) == std::string::npos) continue;
obj.pushKV(strprintf("%d", h), strPayments);
}
} }
auto projection = node.dmnman->GetListForBlock(pindexTip).GetProjectedMNPayees(pindexTip, 20); auto projection = node.dmnman->GetListForBlock(pindexTip).GetProjectedMNPayees(pindexTip, 20);

View File

@ -467,6 +467,7 @@ void FuncDIP3Protx(TestChainSetup& setup)
// check MN reward payments // check MN reward payments
for (size_t i = 0; i < 20; i++) { for (size_t i = 0; i < 20; i++) {
auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip()); auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip());
BOOST_ASSERT(dmnExpectedPayee);
CBlock block = setup.CreateAndProcessBlock({}, setup.coinbaseKey); CBlock block = setup.CreateAndProcessBlock({}, setup.coinbaseKey);
dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip()); dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip());
@ -525,7 +526,7 @@ void FuncDIP3Protx(TestChainSetup& setup)
// test that the revoked MN does not get paid anymore // test that the revoked MN does not get paid anymore
for (size_t i = 0; i < 20; i++) { for (size_t i = 0; i < 20; i++) {
auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip()); auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip());
BOOST_REQUIRE(dmnExpectedPayee->proTxHash != dmnHashes[0]); BOOST_REQUIRE(dmnExpectedPayee && dmnExpectedPayee->proTxHash != dmnHashes[0]);
CBlock block = setup.CreateAndProcessBlock({}, setup.coinbaseKey); CBlock block = setup.CreateAndProcessBlock({}, setup.coinbaseKey);
dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip()); dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip());
@ -575,6 +576,7 @@ void FuncDIP3Protx(TestChainSetup& setup)
bool foundRevived = false; bool foundRevived = false;
for (size_t i = 0; i < 20; i++) { for (size_t i = 0; i < 20; i++) {
auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip()); auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip());
BOOST_ASSERT(dmnExpectedPayee);
if (dmnExpectedPayee->proTxHash == dmnHashes[0]) { if (dmnExpectedPayee->proTxHash == dmnHashes[0]) {
foundRevived = true; foundRevived = true;
} }