@@ -470,11 +470,12 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTota
470
470
throw (std::runtime_error (strprintf (" %s: Can't add a masternode %s with a duplicate collateralOutpoint=%s" , __func__,
471
471
dmn->proTxHash .ToString (), dmn->collateralOutpoint .ToStringShort ())));
472
472
}
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
+ }
478
479
}
479
480
if (!AddUniqueProperty (*dmn, dmn->pdmnState ->keyIDOwner )) {
480
481
mnUniquePropertyMap = mnUniquePropertyMapSaved;
@@ -512,11 +513,28 @@ void CDeterministicMNList::UpdateMN(const CDeterministicMN& oldDmn, const std::s
512
513
// Using this temporary map as a checkpoint to roll back to in case of any issues.
513
514
decltype (mnUniquePropertyMap) mnUniquePropertyMapSaved = mnUniquePropertyMap;
514
515
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 ()) {
516
535
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)));
520
538
}
521
539
if (!UpdateUniqueProperty (*dmn, oldState->keyIDOwner , pdmnState->keyIDOwner )) {
522
540
mnUniquePropertyMap = mnUniquePropertyMapSaved;
@@ -573,10 +591,12 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash)
573
591
throw (std::runtime_error (strprintf (" %s: Can't delete a masternode %s with a collateralOutpoint=%s" , __func__,
574
592
proTxHash.ToString (), dmn->collateralOutpoint .ToStringShort ())));
575
593
}
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
+ }
580
600
}
581
601
if (!DeleteUniqueProperty (*dmn, dmn->pdmnState ->keyIDOwner )) {
582
602
mnUniquePropertyMap = mnUniquePropertyMapSaved;
@@ -791,8 +811,10 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
791
811
}
792
812
}
793
813
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
+ }
796
818
}
797
819
if (newList.HasUniqueProperty (proTx.keyIDOwner ) || newList.HasUniqueProperty (proTx.pubKeyOperator )) {
798
820
return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-protx-dup-key" );
@@ -820,9 +842,11 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
820
842
return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-protx-payload" );
821
843
}
822
844
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
+ }
826
850
}
827
851
828
852
auto dmn = newList.GetMN (opt_proTx->proTxHash );
@@ -1349,9 +1373,11 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl:
1349
1373
auto mnList = dmnman.GetListForBlock (pindexPrev);
1350
1374
1351
1375
// 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
+ }
1355
1381
}
1356
1382
1357
1383
// 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
1420
1446
}
1421
1447
1422
1448
// 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
+ }
1426
1453
}
1427
1454
1428
1455
// don't allow updating to platformNodeIds already used by other EvoNodes
0 commit comments