Skip to content

Commit 1d52678

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 bcb8a7d commit 1d52678

File tree

2 files changed

+56
-26
lines changed

2 files changed

+56
-26
lines changed

src/evo/deterministicmns.cpp

+51-24
Original file line numberDiff line numberDiff line change
@@ -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

src/evo/deterministicmns.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -394,8 +394,11 @@ class CDeterministicMNList
394394
template <typename T>
395395
[[nodiscard]] uint256 GetUniquePropertyHash(const T& v) const
396396
{
397-
static_assert(!std::is_same_v<std::decay_t<T>, CBLSPublicKey>,
398-
"GetUniquePropertyHash cannot be templated against CBLSPublicKey");
397+
#define DMNL_NO_TEMPLATE(name) \
398+
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)