Skip to content

Commit 474e035

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 196ee4f commit 474e035

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);
@@ -1383,8 +1409,10 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl:
13831409
auto mnList = dmnman.GetListForBlock(pindexPrev);
13841410

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

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

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

14601490
// 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)