@@ -470,11 +470,12 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTota
470470 throw (std::runtime_error (strprintf (" %s: Can't add a masternode %s with a duplicate collateralOutpoint=%s" , __func__,
471471 dmn->proTxHash .ToString (), dmn->collateralOutpoint .ToStringShort ())));
472472 }
473- if (!dmn->pdmnState ->netInfo .IsEmpty () && !AddUniqueProperty (*dmn, dmn->pdmnState ->netInfo )) {
474- mnUniquePropertyMap = mnUniquePropertyMapSaved;
475- throw (std::runtime_error (strprintf (" %s: Can't add a masternode %s with a duplicate address=%s" , __func__,
476- dmn->proTxHash .ToString (),
477- dmn->pdmnState ->netInfo .GetPrimary ().ToStringAddrPort ())));
473+ for (const CService& entry : dmn->pdmnState ->netInfo .GetEntries ()) {
474+ if (!AddUniqueProperty (*dmn, entry)) {
475+ mnUniquePropertyMap = mnUniquePropertyMapSaved;
476+ throw (std::runtime_error (strprintf (" %s: Can't add a masternode %s with a duplicate address=%s" , __func__,
477+ dmn->proTxHash .ToString (), entry.ToStringAddrPort ())));
478+ }
478479 }
479480 if (!AddUniqueProperty (*dmn, dmn->pdmnState ->keyIDOwner )) {
480481 mnUniquePropertyMap = mnUniquePropertyMapSaved;
@@ -512,11 +513,28 @@ void CDeterministicMNList::UpdateMN(const CDeterministicMN& oldDmn, const std::s
512513 // Using this temporary map as a checkpoint to roll back to in case of any issues.
513514 decltype (mnUniquePropertyMap) mnUniquePropertyMapSaved = mnUniquePropertyMap;
514515
515- if (!UpdateUniqueProperty (*dmn, oldState->netInfo , pdmnState->netInfo )) {
516+ const auto updateNetInfo = [&]() {
517+ if (oldState->netInfo != pdmnState->netInfo ) {
518+ // We track each individual entry in netInfo as opposed to netInfo itself (preventing us from
519+ // using UpdateUniqueProperty()), so we need to successfully purge all old entries and insert
520+ // new entries to successfully update.
521+ for (const CService& old_entry : oldState->netInfo .GetEntries ()) {
522+ if (!DeleteUniqueProperty (*dmn, old_entry)) {
523+ return strprintf (" internal error" ); // This shouldn't be possible
524+ }
525+ }
526+ for (const CService& new_entry : pdmnState->netInfo .GetEntries ()) {
527+ if (!AddUniqueProperty (*dmn, new_entry)) {
528+ return strprintf (" duplicate (%s)" , new_entry.ToStringAddrPort ());
529+ }
530+ }
531+ }
532+ return strprintf (" " );
533+ }();
534+ if (!updateNetInfo.empty ()) {
516535 mnUniquePropertyMap = mnUniquePropertyMapSaved;
517- throw (std::runtime_error (strprintf (" %s: Can't update a masternode %s with a duplicate address=%s" , __func__,
518- oldDmn.proTxHash .ToString (),
519- pdmnState->netInfo .GetPrimary ().ToStringAddrPort ())));
536+ throw (std::runtime_error (strprintf (" %s: Can't update masternode %s with addresses, reason=%s" , __func__,
537+ oldDmn.proTxHash .ToString (), updateNetInfo)));
520538 }
521539 if (!UpdateUniqueProperty (*dmn, oldState->keyIDOwner , pdmnState->keyIDOwner )) {
522540 mnUniquePropertyMap = mnUniquePropertyMapSaved;
@@ -573,10 +591,12 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash)
573591 throw (std::runtime_error (strprintf (" %s: Can't delete a masternode %s with a collateralOutpoint=%s" , __func__,
574592 proTxHash.ToString (), dmn->collateralOutpoint .ToStringShort ())));
575593 }
576- if (!dmn->pdmnState ->netInfo .IsEmpty () && !DeleteUniqueProperty (*dmn, dmn->pdmnState ->netInfo )) {
577- mnUniquePropertyMap = mnUniquePropertyMapSaved;
578- throw (std::runtime_error (strprintf (" %s: Can't delete a masternode %s with a address=%s" , __func__,
579- proTxHash.ToString (), dmn->pdmnState ->netInfo .GetPrimary ().ToStringAddrPort ())));
594+ for (const CService& entry : dmn->pdmnState ->netInfo .GetEntries ()) {
595+ if (!DeleteUniqueProperty (*dmn, entry)) {
596+ mnUniquePropertyMap = mnUniquePropertyMapSaved;
597+ throw (std::runtime_error (strprintf (" %s: Can't delete a masternode %s with an address=%s" , __func__,
598+ proTxHash.ToString (), entry.ToStringAddrPort ())));
599+ }
580600 }
581601 if (!DeleteUniqueProperty (*dmn, dmn->pdmnState ->keyIDOwner )) {
582602 mnUniquePropertyMap = mnUniquePropertyMapSaved;
@@ -791,8 +811,10 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
791811 }
792812 }
793813
794- if (newList.HasUniqueProperty (proTx.netInfo )) {
795- return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-protx-dup-addr" );
814+ for (const CService& entry : proTx.netInfo .GetEntries ()) {
815+ if (newList.HasUniqueProperty (entry)) {
816+ return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-protx-dup-netinfo-entry" );
817+ }
796818 }
797819 if (newList.HasUniqueProperty (proTx.keyIDOwner ) || newList.HasUniqueProperty (proTx.pubKeyOperator )) {
798820 return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-protx-dup-key" );
@@ -820,9 +842,11 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
820842 return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-protx-payload" );
821843 }
822844
823- if (newList.HasUniqueProperty (opt_proTx->netInfo ) &&
824- newList.GetUniquePropertyMN (opt_proTx->netInfo )->proTxHash != opt_proTx->proTxHash ) {
825- return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-protx-dup-addr" );
845+ for (const CService& entry : opt_proTx->netInfo .GetEntries ()) {
846+ if (newList.HasUniqueProperty (entry) &&
847+ newList.GetUniquePropertyMN (entry)->proTxHash != opt_proTx->proTxHash ) {
848+ return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-protx-dup-netinfo-entry" );
849+ }
826850 }
827851
828852 auto dmn = newList.GetMN (opt_proTx->proTxHash );
@@ -1349,9 +1373,11 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl:
13491373 auto mnList = dmnman.GetListForBlock (pindexPrev);
13501374
13511375 // only allow reusing of addresses when it's for the same collateral (which replaces the old MN)
1352- if (mnList.HasUniqueProperty (opt_ptx->netInfo ) &&
1353- mnList.GetUniquePropertyMN (opt_ptx->netInfo )->collateralOutpoint != collateralOutpoint) {
1354- return state.Invalid (TxValidationResult::TX_BAD_SPECIAL, " bad-protx-dup-addr" );
1376+ for (const CService& entry : opt_ptx->netInfo .GetEntries ()) {
1377+ if (mnList.HasUniqueProperty (entry) &&
1378+ mnList.GetUniquePropertyMN (entry)->collateralOutpoint != collateralOutpoint) {
1379+ return state.Invalid (TxValidationResult::TX_BAD_SPECIAL, " bad-protx-dup-netinfo-entry" );
1380+ }
13551381 }
13561382
13571383 // never allow duplicate keys, even if this ProTx would replace an existing MN
@@ -1420,9 +1446,10 @@ bool CheckProUpServTx(CDeterministicMNManager& dmnman, const CTransaction& tx, g
14201446 }
14211447
14221448 // don't allow updating to addresses already used by other MNs
1423- if (mnList.HasUniqueProperty (opt_ptx->netInfo ) &&
1424- mnList.GetUniquePropertyMN (opt_ptx->netInfo )->proTxHash != opt_ptx->proTxHash ) {
1425- return state.Invalid (TxValidationResult::TX_BAD_SPECIAL, " bad-protx-dup-addr" );
1449+ for (const CService& entry : opt_ptx->netInfo .GetEntries ()) {
1450+ if (mnList.HasUniqueProperty (entry) && mnList.GetUniquePropertyMN (entry)->proTxHash != opt_ptx->proTxHash ) {
1451+ return state.Invalid (TxValidationResult::TX_BAD_SPECIAL, " bad-protx-dup-netinfo-entry" );
1452+ }
14261453 }
14271454
14281455 // don't allow updating to platformNodeIds already used by other EvoNodes
0 commit comments