Skip to content

Commit 807de7f

Browse files
committed
refactor: track every MnNetInfo entry in the unique property map
Currently this does nothing different since both MnNetInfo and CService serialize the same (and we only store one entry) but will allow us to swap with an extended addresses capable variant down the line.
1 parent b94ad40 commit 807de7f

File tree

2 files changed

+53
-20
lines changed

2 files changed

+53
-20
lines changed

src/evo/deterministicmns.cpp

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,12 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTota
466466
throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate collateralOutpoint=%s", __func__,
467467
dmn->proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort())));
468468
}
469-
if (!dmn->pdmnState->netInfo.IsEmpty() && !AddUniqueProperty(*dmn, dmn->pdmnState->netInfo)) {
470-
mnUniquePropertyMap = mnUniquePropertyMapSaved;
471-
throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s", __func__,
472-
dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort())));
469+
for (const CService& entry : dmn->pdmnState->netInfo.GetEntries()) {
470+
if (!AddUniqueProperty(*dmn, entry)) {
471+
mnUniquePropertyMap = mnUniquePropertyMapSaved;
472+
throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s", __func__,
473+
dmn->proTxHash.ToString(), entry.ToStringAddrPort())));
474+
}
473475
}
474476
if (!AddUniqueProperty(*dmn, dmn->pdmnState->keyIDOwner)) {
475477
mnUniquePropertyMap = mnUniquePropertyMapSaved;
@@ -507,10 +509,28 @@ void CDeterministicMNList::UpdateMN(const CDeterministicMN& oldDmn, const std::s
507509
// Using this temporary map as a checkpoint to roll back to in case of any issues.
508510
decltype(mnUniquePropertyMap) mnUniquePropertyMapSaved = mnUniquePropertyMap;
509511

510-
if (!UpdateUniqueProperty(*dmn, oldState->netInfo, pdmnState->netInfo)) {
512+
const auto updateNetInfo = [&]() {
513+
if (oldState->netInfo != pdmnState->netInfo) {
514+
// We track each individual entry in netInfo as opposed to netInfo itself (preventing us from
515+
// using UpdateUniqueProperty()), so we need to successfully purge all old entries and insert
516+
// new entries to successfully update.
517+
for (const CService& old_entry : oldState->netInfo.GetEntries()) {
518+
if (old_entry != CService() && !DeleteUniqueProperty(*dmn, old_entry)) {
519+
return strprintf("internal error"); // This shouldn't be possible
520+
}
521+
}
522+
for (const CService& new_entry : pdmnState->netInfo.GetEntries()) {
523+
if (new_entry != CService() && !AddUniqueProperty(*dmn, new_entry)) {
524+
return strprintf("duplicate (%d)", new_entry.ToStringAddrPort());
525+
}
526+
}
527+
}
528+
return strprintf("");
529+
}();
530+
if (!updateNetInfo.empty()) {
511531
mnUniquePropertyMap = mnUniquePropertyMapSaved;
512-
throw(std::runtime_error(strprintf("%s: Can't update a masternode %s with a duplicate address=%s", __func__,
513-
oldDmn.proTxHash.ToString(), pdmnState->netInfo.GetPrimary().ToStringAddrPort())));
532+
throw(std::runtime_error(strprintf("%s: Can't update masternode %s with addresses, reason=%s", __func__,
533+
oldDmn.proTxHash.ToString(), updateNetInfo)));
514534
}
515535
if (!UpdateUniqueProperty(*dmn, oldState->keyIDOwner, pdmnState->keyIDOwner)) {
516536
mnUniquePropertyMap = mnUniquePropertyMapSaved;
@@ -567,10 +587,12 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash)
567587
throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a collateralOutpoint=%s", __func__,
568588
proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort())));
569589
}
570-
if (!dmn->pdmnState->netInfo.IsEmpty() && !DeleteUniqueProperty(*dmn, dmn->pdmnState->netInfo)) {
571-
mnUniquePropertyMap = mnUniquePropertyMapSaved;
572-
throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a address=%s", __func__,
573-
proTxHash.ToString(), dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort())));
590+
for (const CService& entry : dmn->pdmnState->netInfo.GetEntries()) {
591+
if (!DeleteUniqueProperty(*dmn, entry)) {
592+
mnUniquePropertyMap = mnUniquePropertyMapSaved;
593+
throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with an address=%s", __func__,
594+
proTxHash.ToString(), entry.ToStringAddrPort())));
595+
}
574596
}
575597
if (!DeleteUniqueProperty(*dmn, dmn->pdmnState->keyIDOwner)) {
576598
mnUniquePropertyMap = mnUniquePropertyMapSaved;
@@ -797,8 +819,10 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
797819
}
798820
}
799821

800-
if (newList.HasUniqueProperty(proTx.netInfo)) {
801-
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr");
822+
for (const CService& entry : proTx.netInfo.GetEntries()) {
823+
if (newList.HasUniqueProperty(entry)) {
824+
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr");
825+
}
802826
}
803827
if (newList.HasUniqueProperty(proTx.keyIDOwner) || newList.HasUniqueProperty(proTx.pubKeyOperator)) {
804828
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-key");
@@ -826,8 +850,10 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
826850
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload");
827851
}
828852

829-
if (newList.HasUniqueProperty(opt_proTx->netInfo) && newList.GetUniquePropertyMN(opt_proTx->netInfo)->proTxHash != opt_proTx->proTxHash) {
830-
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr");
853+
for (const CService& entry : opt_proTx->netInfo.GetEntries()) {
854+
if (newList.HasUniqueProperty(entry) && newList.GetUniquePropertyMN(entry)->proTxHash != opt_proTx->proTxHash) {
855+
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr");
856+
}
831857
}
832858

833859
auto dmn = newList.GetMN(opt_proTx->proTxHash);
@@ -1384,8 +1410,10 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl:
13841410
auto mnList = dmnman.GetListForBlock(pindexPrev);
13851411

13861412
// only allow reusing of addresses when it's for the same collateral (which replaces the old MN)
1387-
if (mnList.HasUniqueProperty(opt_ptx->netInfo) && mnList.GetUniquePropertyMN(opt_ptx->netInfo)->collateralOutpoint != collateralOutpoint) {
1388-
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-addr");
1413+
for (const CService& entry : opt_ptx->netInfo.GetEntries()) {
1414+
if (mnList.HasUniqueProperty(entry) && mnList.GetUniquePropertyMN(entry)->collateralOutpoint != collateralOutpoint) {
1415+
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-addr");
1416+
}
13891417
}
13901418

13911419
// never allow duplicate keys, even if this ProTx would replace an existing MN
@@ -1454,8 +1482,10 @@ bool CheckProUpServTx(CDeterministicMNManager& dmnman, const CTransaction& tx, g
14541482
}
14551483

14561484
// don't allow updating to addresses already used by other MNs
1457-
if (mnList.HasUniqueProperty(opt_ptx->netInfo) && mnList.GetUniquePropertyMN(opt_ptx->netInfo)->proTxHash != opt_ptx->proTxHash) {
1458-
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-addr");
1485+
for (const CService& entry : opt_ptx->netInfo.GetEntries()) {
1486+
if (mnList.HasUniqueProperty(entry) && mnList.GetUniquePropertyMN(entry)->proTxHash != opt_ptx->proTxHash) {
1487+
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-addr");
1488+
}
14591489
}
14601490

14611491
// don't allow updating to platformNodeIds already used by other EvoNodes

src/evo/deterministicmns.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,10 @@ class CDeterministicMNList
395395
template <typename T>
396396
[[nodiscard]] uint256 GetUniquePropertyHash(const T& v) const
397397
{
398-
static_assert(!std::is_same_v<std::decay_t<T>, CBLSPublicKey>, "GetUniquePropertyHash cannot be templated against CBLSPublicKey");
398+
#define DMNL_NO_TEMPLATE(name) static_assert(!std::is_same_v<std::decay_t<T>, name>, "GetUniquePropertyHash cannot be templated against "#name)
399+
DMNL_NO_TEMPLATE(CBLSPublicKey);
400+
DMNL_NO_TEMPLATE(MnNetInfo);
401+
#undef DMNL_NO_TEMPLATE
399402
return ::SerializeHash(v);
400403
}
401404
template <typename T>

0 commit comments

Comments
 (0)