@@ -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
0 commit comments