From 2c6dd056379a1a2633c4b63352652cb55714aa28 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Sat, 3 May 2025 08:15:14 +0000 Subject: [PATCH 01/10] fix: avoid potential "no user-provided default constructor" error --- src/evo/deterministicmns.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 76375e2d0695..b7dadf6aca68 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -394,13 +394,14 @@ class CDeterministicMNList template [[nodiscard]] uint256 GetUniquePropertyHash(const T& v) const { - static_assert(!std::is_same(), "GetUniquePropertyHash cannot be templated against CBLSPublicKey"); + static_assert(!std::is_same_v, CBLSPublicKey>, + "GetUniquePropertyHash cannot be templated against CBLSPublicKey"); return ::SerializeHash(v); } template [[nodiscard]] bool AddUniqueProperty(const CDeterministicMN& dmn, const T& v) { - static const T nullValue; + static const T nullValue{}; if (v == nullValue) { return false; } @@ -420,7 +421,7 @@ class CDeterministicMNList template [[nodiscard]] bool DeleteUniqueProperty(const CDeterministicMN& dmn, const T& oldValue) { - static const T nullValue; + static const T nullValue{}; if (oldValue == nullValue) { return false; } @@ -443,7 +444,7 @@ class CDeterministicMNList if (oldValue == newValue) { return true; } - static const T nullValue; + static const T nullValue{}; if (oldValue != nullValue && !DeleteUniqueProperty(dmn, oldValue)) { return false; From aaabc35a8547942ca0ac7df5017dc55207556e99 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Sat, 3 May 2025 09:20:42 +0000 Subject: [PATCH 02/10] refactor: section off masternode service to `MnNetInfo` --- src/Makefile.am | 1 + src/coinjoin/client.cpp | 12 +++--- src/evo/core_write.cpp | 5 ++- src/evo/deterministicmns.cpp | 45 +++++++++++--------- src/evo/dmnstate.cpp | 8 ++-- src/evo/dmnstate.h | 12 +++--- src/evo/netinfo.h | 31 ++++++++++++++ src/evo/providertx.cpp | 4 +- src/evo/providertx.h | 9 ++-- src/evo/simplifiedmns.cpp | 8 ++-- src/evo/simplifiedmns.h | 7 +-- src/llmq/utils.cpp | 4 +- src/masternode/node.cpp | 4 +- src/masternode/utils.cpp | 3 +- src/net.cpp | 16 +++---- src/qt/masternodelist.cpp | 4 +- src/rpc/evo.cpp | 4 +- src/rpc/masternode.cpp | 10 ++--- src/rpc/quorums.cpp | 2 +- src/test/block_reward_reallocation_tests.cpp | 2 +- src/test/evo_deterministicmns_tests.cpp | 14 +++--- src/test/evo_simplifiedmns_tests.cpp | 2 +- src/txmempool.cpp | 20 ++++----- 23 files changed, 133 insertions(+), 94 deletions(-) create mode 100644 src/evo/netinfo.h diff --git a/src/Makefile.am b/src/Makefile.am index 0a91b742a016..9e8aa5ca464d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -192,6 +192,7 @@ BITCOIN_CORE_H = \ evo/evodb.h \ evo/mnauth.h \ evo/mnhftx.h \ + evo/netinfo.h \ evo/providertx.h \ evo/simplifiedmns.h \ evo/specialtx.h \ diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index 8ae8a666c30a..ccecd4dea41b 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -186,7 +186,7 @@ void CCoinJoinClientSession::ProcessMessage(CNode& peer, CChainState& active_cha if (!m_mn_sync.IsBlockchainSynced()) return; if (!mixingMasternode) return; - if (mixingMasternode->pdmnState->addr != peer.addr) return; + if (mixingMasternode->pdmnState->netInfo.m_addr != peer.addr) return; if (msg_type == NetMsgType::DSSTATUSUPDATE) { CCoinJoinStatusUpdate psssup; @@ -1106,7 +1106,7 @@ bool CCoinJoinClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized, m_clientman.AddUsedMasternode(dsq.masternodeOutpoint); - if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) { + if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->netInfo.m_addr)) { WalletCJLogPrint(m_wallet, /* Continued */ "CCoinJoinClientSession::JoinExistingQueue -- skipping connection, masternode=%s\n", dmn->proTxHash.ToString()); continue; @@ -1178,7 +1178,7 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon continue; } - if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) { + if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->netInfo.m_addr)) { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- skipping connection, masternode=%s\n", dmn->proTxHash.ToString()); nTries++; @@ -1218,7 +1218,7 @@ bool CCoinJoinClientSession::ProcessPendingDsaRequest(CConnman& connman) CService mn_addr; if (auto dmn = m_dmnman.GetListAtChainTip().GetMN(pendingDsaRequest.GetProTxHash())) { - mn_addr = Assert(dmn->pdmnState)->addr; + mn_addr = Assert(dmn->pdmnState)->netInfo.m_addr; } else { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- cannot find address to connect, masternode=%s\n", __func__, pendingDsaRequest.GetProTxHash().ToString()); @@ -1820,7 +1820,7 @@ void CCoinJoinClientSession::RelayIn(const CCoinJoinEntry& entry, CConnman& conn { if (!mixingMasternode) return; - connman.ForNode(mixingMasternode->pdmnState->addr, [&entry, &connman, this](CNode* pnode) { + connman.ForNode(mixingMasternode->pdmnState->netInfo.m_addr, [&entry, &connman, this](CNode* pnode) { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::RelayIn -- found master, relaying message to %s\n", pnode->addr.ToStringAddrPort()); CNetMsgMaker msgMaker(pnode->GetCommonVersion()); @@ -1876,7 +1876,7 @@ void CCoinJoinClientSession::GetJsonInfo(UniValue& obj) const assert(mixingMasternode->pdmnState); obj.pushKV("protxhash", mixingMasternode->proTxHash.ToString()); obj.pushKV("outpoint", mixingMasternode->collateralOutpoint.ToStringShort()); - obj.pushKV("service", mixingMasternode->pdmnState->addr.ToStringAddrPort()); + obj.pushKV("service", mixingMasternode->pdmnState->netInfo.m_addr.ToStringAddrPort()); } obj.pushKV("denomination", ValueFromAmount(CoinJoin::DenominationToAmount(nSessionDenom))); obj.pushKV("state", GetStateString()); diff --git a/src/evo/core_write.cpp b/src/evo/core_write.cpp index b2a2cdbd7f0a..24e59d8a093c 100644 --- a/src/evo/core_write.cpp +++ b/src/evo/core_write.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -66,7 +67,7 @@ ret.pushKV("type", ToUnderlying(nType)); ret.pushKV("collateralHash", collateralOutpoint.hash.ToString()); ret.pushKV("collateralIndex", (int)collateralOutpoint.n); - ret.pushKV("service", addr.ToStringAddrPort()); + ret.pushKV("service", netInfo.m_addr.ToStringAddrPort()); ret.pushKV("ownerAddress", EncodeDestination(PKHash(keyIDOwner))); ret.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting))); if (CTxDestination dest; ExtractDestination(scriptPayout, dest)) { @@ -113,7 +114,7 @@ ret.pushKV("version", nVersion); ret.pushKV("type", ToUnderlying(nType)); ret.pushKV("proTxHash", proTxHash.ToString()); - ret.pushKV("service", addr.ToStringAddrPort()); + ret.pushKV("service", netInfo.m_addr.ToStringAddrPort()); if (CTxDestination dest; ExtractDestination(scriptOperatorPayout, dest)) { ret.pushKV("operatorPayoutAddress", EncodeDestination(dest)); } diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 546f4ad292c8..7c2d76f7946e 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -470,10 +470,10 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTota throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate collateralOutpoint=%s", __func__, dmn->proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort()))); } - if (dmn->pdmnState->addr != CService() && !AddUniqueProperty(*dmn, dmn->pdmnState->addr)) { + if (dmn->pdmnState->netInfo.m_addr != CService() && !AddUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s", __func__, - dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringAddrPort()))); + dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()))); } if (!AddUniqueProperty(*dmn, dmn->pdmnState->keyIDOwner)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; @@ -511,10 +511,10 @@ void CDeterministicMNList::UpdateMN(const CDeterministicMN& oldDmn, const std::s // Using this temporary map as a checkpoint to roll back to in case of any issues. decltype(mnUniquePropertyMap) mnUniquePropertyMapSaved = mnUniquePropertyMap; - if (!UpdateUniqueProperty(*dmn, oldState->addr, pdmnState->addr)) { + if (!UpdateUniqueProperty(*dmn, oldState->netInfo, pdmnState->netInfo)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; throw(std::runtime_error(strprintf("%s: Can't update a masternode %s with a duplicate address=%s", __func__, - oldDmn.proTxHash.ToString(), pdmnState->addr.ToStringAddrPort()))); + oldDmn.proTxHash.ToString(), pdmnState->netInfo.m_addr.ToStringAddrPort()))); } if (!UpdateUniqueProperty(*dmn, oldState->keyIDOwner, pdmnState->keyIDOwner)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; @@ -571,10 +571,10 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash) throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a collateralOutpoint=%s", __func__, proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort()))); } - if (dmn->pdmnState->addr != CService() && !DeleteUniqueProperty(*dmn, dmn->pdmnState->addr)) { + if (dmn->pdmnState->netInfo.m_addr != CService() && !DeleteUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a address=%s", __func__, - proTxHash.ToString(), dmn->pdmnState->addr.ToStringAddrPort()))); + proTxHash.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()))); } if (!DeleteUniqueProperty(*dmn, dmn->pdmnState->keyIDOwner)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; @@ -789,7 +789,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no } } - if (newList.HasUniqueProperty(proTx.addr)) { + if (newList.HasUniqueProperty(proTx.netInfo)) { return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr"); } if (newList.HasUniqueProperty(proTx.keyIDOwner) || newList.HasUniqueProperty(proTx.pubKeyOperator)) { @@ -800,7 +800,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no auto dmnState = std::make_shared(proTx); dmnState->nRegisteredHeight = nHeight; - if (proTx.addr == CService()) { + if (proTx.netInfo.m_addr == CService()) { // start in banned pdmnState as we need to wait for a ProUpServTx dmnState->BanIfNotBanned(nHeight); } @@ -818,7 +818,8 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload"); } - if (newList.HasUniqueProperty(opt_proTx->addr) && newList.GetUniquePropertyMN(opt_proTx->addr)->proTxHash != opt_proTx->proTxHash) { + if (newList.HasUniqueProperty(opt_proTx->netInfo) && + newList.GetUniquePropertyMN(opt_proTx->netInfo)->proTxHash != opt_proTx->proTxHash) { return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr"); } @@ -834,7 +835,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no } auto newState = std::make_shared(*dmn->pdmnState); - newState->addr = opt_proTx->addr; + newState->netInfo = opt_proTx->netInfo; newState->scriptOperatorPayout = opt_proTx->scriptOperatorPayout; if (opt_proTx->nType == MnType::Evo) { newState->platformNodeID = opt_proTx->platformNodeID; @@ -1177,24 +1178,25 @@ void CDeterministicMNManager::CleanupCache(int nHeight) template static bool CheckService(const ProTx& proTx, TxValidationState& state) { - if (!proTx.addr.IsValid()) { + const auto& addr{proTx.netInfo.m_addr}; + if (!addr.IsValid()) { return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr"); } - if (Params().RequireRoutableExternalIP() && !proTx.addr.IsRoutable()) { + if (Params().RequireRoutableExternalIP() && !addr.IsRoutable()) { return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr"); } // TODO: use real args here static int mainnetDefaultPort = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN)->GetDefaultPort(); if (Params().NetworkIDString() == CBaseChainParams::MAIN) { - if (proTx.addr.GetPort() != mainnetDefaultPort) { + if (addr.GetPort() != mainnetDefaultPort) { return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr-port"); } - } else if (proTx.addr.GetPort() == mainnetDefaultPort) { + } else if (addr.GetPort() == mainnetDefaultPort) { return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr-port"); } - if (!proTx.addr.IsIPv4()) { + if (!addr.IsIPv4()) { return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr"); } @@ -1233,9 +1235,8 @@ static bool CheckPlatformFields(const ProTx& proTx, TxValidationState& state) return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-http-port"); } - if (proTx.platformP2PPort == proTx.platformHTTPPort || - proTx.platformP2PPort == proTx.addr.GetPort() || - proTx.platformHTTPPort == proTx.addr.GetPort()) { + if (proTx.platformP2PPort == proTx.platformHTTPPort || proTx.platformP2PPort == proTx.netInfo.m_addr.GetPort() || + proTx.platformHTTPPort == proTx.netInfo.m_addr.GetPort()) { return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-dup-ports"); } @@ -1300,7 +1301,7 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl: // It's allowed to set addr to 0, which will put the MN into PoSe-banned state and require a ProUpServTx to be issues later // If any of both is set, it must be valid however - if (opt_ptx->addr != CService() && !CheckService(*opt_ptx, state)) { + if (opt_ptx->netInfo.m_addr != CService() && !CheckService(*opt_ptx, state)) { // pass the state returned by the function above return false; } @@ -1360,7 +1361,8 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl: auto mnList = dmnman.GetListForBlock(pindexPrev); // only allow reusing of addresses when it's for the same collateral (which replaces the old MN) - if (mnList.HasUniqueProperty(opt_ptx->addr) && mnList.GetUniquePropertyMN(opt_ptx->addr)->collateralOutpoint != collateralOutpoint) { + if (mnList.HasUniqueProperty(opt_ptx->netInfo) && + mnList.GetUniquePropertyMN(opt_ptx->netInfo)->collateralOutpoint != collateralOutpoint) { return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-addr"); } @@ -1430,7 +1432,8 @@ bool CheckProUpServTx(CDeterministicMNManager& dmnman, const CTransaction& tx, g } // don't allow updating to addresses already used by other MNs - if (mnList.HasUniqueProperty(opt_ptx->addr) && mnList.GetUniquePropertyMN(opt_ptx->addr)->proTxHash != opt_ptx->proTxHash) { + if (mnList.HasUniqueProperty(opt_ptx->netInfo) && + mnList.GetUniquePropertyMN(opt_ptx->netInfo)->proTxHash != opt_ptx->proTxHash) { return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-addr"); } diff --git a/src/evo/dmnstate.cpp b/src/evo/dmnstate.cpp index 8943640b8db3..8fd3de6ae441 100644 --- a/src/evo/dmnstate.cpp +++ b/src/evo/dmnstate.cpp @@ -31,7 +31,7 @@ std::string CDeterministicMNState::ToString() const "operatorPayoutAddress=%s)", nVersion, nRegisteredHeight, nLastPaidHeight, nPoSePenalty, nPoSeRevivedHeight, nPoSeBanHeight, nRevocationReason, EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), - EncodeDestination(PKHash(keyIDVoting)), addr.ToStringAddrPort(), payoutAddress, + EncodeDestination(PKHash(keyIDVoting)), netInfo.m_addr.ToStringAddrPort(), payoutAddress, operatorPayoutAddress); } @@ -39,7 +39,7 @@ UniValue CDeterministicMNState::ToJson(MnType nType) const { UniValue obj(UniValue::VOBJ); obj.pushKV("version", nVersion); - obj.pushKV("service", addr.ToStringAddrPort()); + obj.pushKV("service", netInfo.m_addr.ToStringAddrPort()); obj.pushKV("registeredHeight", nRegisteredHeight); obj.pushKV("lastPaidHeight", nLastPaidHeight); obj.pushKV("consecutivePayments", nConsecutivePayments); @@ -72,8 +72,8 @@ UniValue CDeterministicMNStateDiff::ToJson(MnType nType) const if (fields & Field_nVersion) { obj.pushKV("version", state.nVersion); } - if (fields & Field_addr) { - obj.pushKV("service", state.addr.ToStringAddrPort()); + if (fields & Field_netInfo) { + obj.pushKV("service", state.netInfo.m_addr.ToStringAddrPort()); } if (fields & Field_nRegisteredHeight) { obj.pushKV("registeredHeight", state.nRegisteredHeight); diff --git a/src/evo/dmnstate.h b/src/evo/dmnstate.h index ec8a767ed76b..85e7fb9434f9 100644 --- a/src/evo/dmnstate.h +++ b/src/evo/dmnstate.h @@ -54,7 +54,7 @@ class CDeterministicMNState CKeyID keyIDOwner; CBLSLazyPublicKey pubKeyOperator; CKeyID keyIDVoting; - CService addr; + MnNetInfo netInfo; CScript scriptPayout; CScript scriptOperatorPayout; @@ -69,7 +69,7 @@ class CDeterministicMNState keyIDOwner(proTx.keyIDOwner), pubKeyOperator(proTx.pubKeyOperator), keyIDVoting(proTx.keyIDVoting), - addr(proTx.addr), + netInfo(proTx.netInfo), scriptPayout(proTx.scriptPayout), platformNodeID(proTx.platformNodeID), platformP2PPort(proTx.platformP2PPort), @@ -100,7 +100,7 @@ class CDeterministicMNState READWRITE(CBLSLazyPublicKeyVersionWrapper(const_cast(obj.pubKeyOperator), obj.nVersion == ProTxVersion::LegacyBLS)); READWRITE( obj.keyIDVoting, - obj.addr, + obj.netInfo, obj.scriptPayout, obj.scriptOperatorPayout, obj.platformNodeID, @@ -112,7 +112,7 @@ class CDeterministicMNState { nVersion = ProTxVersion::LegacyBLS; pubKeyOperator = CBLSLazyPublicKey(); - addr = CService(); + netInfo.m_addr = CService(); scriptOperatorPayout = CScript(); nRevocationReason = CProUpRevTx::REASON_NOT_SPECIFIED; platformNodeID = uint160(); @@ -166,7 +166,7 @@ class CDeterministicMNStateDiff Field_keyIDOwner = 0x0100, Field_pubKeyOperator = 0x0200, Field_keyIDVoting = 0x0400, - Field_addr = 0x0800, + Field_netInfo = 0x0800, Field_scriptPayout = 0x1000, Field_scriptOperatorPayout = 0x2000, Field_nConsecutivePayments = 0x4000, @@ -198,7 +198,7 @@ class CDeterministicMNStateDiff DMN_STATE_MEMBER(keyIDOwner), DMN_STATE_MEMBER(pubKeyOperator), DMN_STATE_MEMBER(keyIDVoting), - DMN_STATE_MEMBER(addr), + DMN_STATE_MEMBER(netInfo), DMN_STATE_MEMBER(scriptPayout), DMN_STATE_MEMBER(scriptOperatorPayout), DMN_STATE_MEMBER(nConsecutivePayments), diff --git a/src/evo/netinfo.h b/src/evo/netinfo.h new file mode 100644 index 000000000000..87aedacba42e --- /dev/null +++ b/src/evo/netinfo.h @@ -0,0 +1,31 @@ +// Copyright (c) 2025 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_EVO_NETINFO_H +#define BITCOIN_EVO_NETINFO_H + +#include +#include + +class CService; + +class MnNetInfo +{ +public: + CService m_addr{}; + +public: + MnNetInfo() = default; + ~MnNetInfo() = default; + + bool operator==(const MnNetInfo& rhs) const { return m_addr == rhs.m_addr; } + bool operator!=(const MnNetInfo& rhs) const { return !(*this == rhs); } + + SERIALIZE_METHODS(MnNetInfo, obj) + { + READWRITE(obj.m_addr); + } +}; + +#endif // BITCOIN_EVO_NETINFO_H diff --git a/src/evo/providertx.cpp b/src/evo/providertx.cpp index 4763bf04dd7a..e06205cca760 100644 --- a/src/evo/providertx.cpp +++ b/src/evo/providertx.cpp @@ -90,7 +90,7 @@ std::string CProRegTx::ToString() const return strprintf("CProRegTx(nVersion=%d, nType=%d, collateralOutpoint=%s, addr=%s, nOperatorReward=%f, " "ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, scriptPayout=%s, platformNodeID=%s, " "platformP2PPort=%d, platformHTTPPort=%d)", - nVersion, ToUnderlying(nType), collateralOutpoint.ToStringShort(), addr.ToStringAddrPort(), + nVersion, ToUnderlying(nType), collateralOutpoint.ToStringShort(), netInfo.m_addr.ToStringAddrPort(), (double)nOperatorReward / 100, EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), payee, platformNodeID.ToString(), platformP2PPort, platformHTTPPort); @@ -118,7 +118,7 @@ std::string CProUpServTx::ToString() const return strprintf("CProUpServTx(nVersion=%d, nType=%d, proTxHash=%s, addr=%s, operatorPayoutAddress=%s, " "platformNodeID=%s, platformP2PPort=%d, platformHTTPPort=%d)", - nVersion, ToUnderlying(nType), proTxHash.ToString(), addr.ToStringAddrPort(), payee, + nVersion, ToUnderlying(nType), proTxHash.ToString(), netInfo.m_addr.ToStringAddrPort(), payee, platformNodeID.ToString(), platformP2PPort, platformHTTPPort); } diff --git a/src/evo/providertx.h b/src/evo/providertx.h index 50f777293221..48017579c14c 100644 --- a/src/evo/providertx.h +++ b/src/evo/providertx.h @@ -6,6 +6,7 @@ #define BITCOIN_EVO_PROVIDERTX_H #include +#include #include #include @@ -40,7 +41,7 @@ class CProRegTx MnType nType{MnType::Regular}; uint16_t nMode{0}; // only 0 supported for now COutPoint collateralOutpoint{uint256(), (uint32_t)-1}; // if hash is null, we refer to a ProRegTx output - CService addr; + MnNetInfo netInfo; uint160 platformNodeID{}; uint16_t platformP2PPort{0}; uint16_t platformHTTPPort{0}; @@ -66,7 +67,7 @@ class CProRegTx obj.nType, obj.nMode, obj.collateralOutpoint, - obj.addr, + obj.netInfo, obj.keyIDOwner, CBLSLazyPublicKeyVersionWrapper(const_cast(obj.pubKeyOperator), (obj.nVersion == ProTxVersion::LegacyBLS)), obj.keyIDVoting, @@ -109,7 +110,7 @@ class CProUpServTx uint16_t nVersion{ProTxVersion::LegacyBLS}; // message version MnType nType{MnType::Regular}; uint256 proTxHash; - CService addr; + MnNetInfo netInfo; uint160 platformNodeID{}; uint16_t platformP2PPort{0}; uint16_t platformHTTPPort{0}; @@ -132,7 +133,7 @@ class CProUpServTx } READWRITE( obj.proTxHash, - obj.addr, + obj.netInfo, obj.scriptOperatorPayout, obj.inputsHash ); diff --git a/src/evo/simplifiedmns.cpp b/src/evo/simplifiedmns.cpp index f99dbe08166a..7297373ff37d 100644 --- a/src/evo/simplifiedmns.cpp +++ b/src/evo/simplifiedmns.cpp @@ -30,7 +30,7 @@ CSimplifiedMNListEntry::CSimplifiedMNListEntry(const CDeterministicMN& dmn) : proRegTxHash(dmn.proTxHash), confirmedHash(dmn.pdmnState->confirmedHash), - service(dmn.pdmnState->addr), + netInfo(dmn.pdmnState->netInfo), pubKeyOperator(dmn.pdmnState->pubKeyOperator), keyIDVoting(dmn.pdmnState->keyIDVoting), isValid(!dmn.pdmnState->IsBanned()), @@ -62,11 +62,11 @@ std::string CSimplifiedMNListEntry::ToString() const operatorPayoutAddress = EncodeDestination(dest); } - return strprintf("CSimplifiedMNListEntry(nVersion=%d, nType=%d, proRegTxHash=%s, confirmedHash=%s, service=%s, " + return strprintf("CSimplifiedMNListEntry(nVersion=%d, nType=%d, proRegTxHash=%s, confirmedHash=%s, addr=%s, " "pubKeyOperator=%s, votingAddress=%s, isValid=%d, payoutAddress=%s, operatorPayoutAddress=%s, " "platformHTTPPort=%d, platformNodeID=%s)", nVersion, ToUnderlying(nType), proRegTxHash.ToString(), confirmedHash.ToString(), - service.ToStringAddrPort(), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), + netInfo.m_addr.ToStringAddrPort(), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), isValid, payoutAddress, operatorPayoutAddress, platformHTTPPort, platformNodeID.ToString()); } @@ -77,7 +77,7 @@ UniValue CSimplifiedMNListEntry::ToJson(bool extended) const obj.pushKV("nType", ToUnderlying(nType)); obj.pushKV("proRegTxHash", proRegTxHash.ToString()); obj.pushKV("confirmedHash", confirmedHash.ToString()); - obj.pushKV("service", service.ToStringAddrPort()); + obj.pushKV("service", netInfo.m_addr.ToStringAddrPort()); obj.pushKV("pubKeyOperator", pubKeyOperator.ToString()); obj.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting))); obj.pushKV("isValid", isValid); diff --git a/src/evo/simplifiedmns.h b/src/evo/simplifiedmns.h index 0a1fa4c4633e..5e5bf7efeb81 100644 --- a/src/evo/simplifiedmns.h +++ b/src/evo/simplifiedmns.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -34,7 +35,7 @@ class CSimplifiedMNListEntry public: uint256 proRegTxHash; uint256 confirmedHash; - CService service; + MnNetInfo netInfo; CBLSLazyPublicKey pubKeyOperator; CKeyID keyIDVoting; bool isValid{false}; @@ -52,7 +53,7 @@ class CSimplifiedMNListEntry { return proRegTxHash == rhs.proRegTxHash && confirmedHash == rhs.confirmedHash && - service == rhs.service && + netInfo == rhs.netInfo && pubKeyOperator == rhs.pubKeyOperator && keyIDVoting == rhs.keyIDVoting && isValid == rhs.isValid && @@ -75,7 +76,7 @@ class CSimplifiedMNListEntry READWRITE( obj.proRegTxHash, obj.confirmedHash, - obj.service, + obj.netInfo, CBLSLazyPublicKeyVersionWrapper(const_cast(obj.pubKeyOperator), (obj.nVersion == ProTxVersion::LegacyBLS)), obj.keyIDVoting, obj.isValid diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index 2379e6eeef02..4ae040e26bc8 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -823,7 +823,7 @@ bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& if (!dmn) { debugMsg += strprintf(" %s (not in valid MN set anymore)\n", c.ToString()); } else { - debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToStringAddrPort()); + debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); } } LogPrint(BCLog::NET_NETCONN, debugMsg.c_str()); /* Continued */ @@ -871,7 +871,7 @@ void AddQuorumProbeConnections(const Consensus::LLMQParams& llmqParams, CConnman if (!dmn) { debugMsg += strprintf(" %s (not in valid MN set anymore)\n", c.ToString()); } else { - debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToStringAddrPort()); + debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); } } LogPrint(BCLog::NET_NETCONN, debugMsg.c_str()); /* Continued */ diff --git a/src/masternode/node.cpp b/src/masternode/node.cpp index 3a51c1597278..76a1bd4e107b 100644 --- a/src/masternode/node.cpp +++ b/src/masternode/node.cpp @@ -146,7 +146,7 @@ void CActiveMasternodeManager::InitInternal(const CBlockIndex* pindex) LogPrintf("CActiveMasternodeManager::Init -- proTxHash=%s, proTx=%s\n", dmn->proTxHash.ToString(), dmn->ToString()); - if (m_info.service != dmn->pdmnState->addr) { + if (m_info.service != dmn->pdmnState->netInfo.m_addr) { m_state = MasternodeState::SOME_ERROR; m_error = "Local address does not match the address from ProTx"; LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error); @@ -201,7 +201,7 @@ void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, con // MN operator key changed or revoked return reset(MasternodeState::OPERATOR_KEY_CHANGED); } - if (newDmn->pdmnState->addr != oldDmn->pdmnState->addr) { + if (newDmn->pdmnState->netInfo.m_addr != oldDmn->pdmnState->netInfo.m_addr) { // MN IP changed return reset(MasternodeState::PROTX_IP_CHANGED); } diff --git a/src/masternode/utils.cpp b/src/masternode/utils.cpp index 5dc707f4bf2a..abcf6b628432 100644 --- a/src/masternode/utils.cpp +++ b/src/masternode/utils.cpp @@ -77,7 +77,8 @@ void CMasternodeUtils::DoMaintenance(CConnman& connman, CDeterministicMNManager& } #ifdef ENABLE_WALLET - bool fFound = ranges::any_of(vecDmns, [&pnode](const auto& dmn){ return pnode->addr == dmn->pdmnState->addr; }); + bool fFound = ranges::any_of(vecDmns, + [&pnode](const auto& dmn) { return pnode->addr == dmn->pdmnState->netInfo.m_addr; }); if (fFound) return; // do NOT disconnect mixing masternodes #endif // ENABLE_WALLET if (fLogIPs) { diff --git a/src/net.cpp b/src/net.cpp index 4b759ecd3469..3c82865311a2 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3674,7 +3674,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, if (!dmn) { continue; } - const auto& addr2 = dmn->pdmnState->addr; + const auto& addr2 = dmn->pdmnState->netInfo.m_addr; if (connectedNodes.count(addr2) && !connectedProRegTxHashes.count(proRegTxHash)) { // we probably connected to it before it became a masternode // or maybe we are still waiting for mnauth @@ -3740,8 +3740,8 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, if (!vPendingMasternodes.empty()) { auto dmn = mnList.GetValidMN(vPendingMasternodes.front()); vPendingMasternodes.erase(vPendingMasternodes.begin()); - if (dmn && !connectedNodes.count(dmn->pdmnState->addr) && !IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) { - LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- opening pending masternode connection to %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringAddrPort()); + if (dmn && !connectedNodes.count(dmn->pdmnState->netInfo.m_addr) && !IsMasternodeOrDisconnectRequested(dmn->pdmnState->netInfo.m_addr)) { + LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- opening pending masternode connection to %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); return dmn; } } @@ -3750,7 +3750,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, // not-null auto dmn = pending[GetRand(pending.size())]; LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- opening quorum connection to %s, service=%s\n", - _func_, dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringAddrPort()); + _func_, dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); return dmn; } @@ -3760,7 +3760,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, masternodePendingProbes.erase(dmn->proTxHash); isProbe = MasternodeProbeConn::IsConnection; - LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- probing masternode %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringAddrPort()); + LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- probing masternode %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); return dmn; } return nullptr; @@ -3776,16 +3776,16 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, mn_metaman.GetMetaInfo(connectToDmn->proTxHash)->SetLastOutboundAttempt(nANow); - OpenMasternodeConnection(CAddress(connectToDmn->pdmnState->addr, NODE_NETWORK), /*use_v2transport=*/GetLocalServices() & NODE_P2P_V2, isProbe); + OpenMasternodeConnection(CAddress(connectToDmn->pdmnState->netInfo.m_addr, NODE_NETWORK), /*use_v2transport=*/GetLocalServices() & NODE_P2P_V2, isProbe); // should be in the list now if connection was opened - bool connected = ForNode(connectToDmn->pdmnState->addr, CConnman::AllNodes, [&](CNode* pnode) { + bool connected = ForNode(connectToDmn->pdmnState->netInfo.m_addr, CConnman::AllNodes, [&](CNode* pnode) { if (pnode->fDisconnect) { return false; } return true; }); if (!connected) { - LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- connection failed for masternode %s, service=%s\n", __func__, connectToDmn->proTxHash.ToString(), connectToDmn->pdmnState->addr.ToStringAddrPort()); + LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- connection failed for masternode %s, service=%s\n", __func__, connectToDmn->proTxHash.ToString(), connectToDmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); // Will take a few consequent failed attempts to PoSe-punish a MN. if (mn_metaman.GetMetaInfo(connectToDmn->proTxHash)->OutboundFailedTooManyTimes()) { LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- failed to connect to masternode %s too many times\n", __func__, connectToDmn->proTxHash.ToString()); diff --git a/src/qt/masternodelist.cpp b/src/qt/masternodelist.cpp index 44a799559a67..69f151f33209 100644 --- a/src/qt/masternodelist.cpp +++ b/src/qt/masternodelist.cpp @@ -221,10 +221,10 @@ void MasternodeList::updateDIP3List() } // populate list // Address, Protocol, Status, Active Seconds, Last Seen, Pub Key - auto addr_key = dmn.pdmnState->addr.GetKey(); + auto addr_key = dmn.pdmnState->netInfo.m_addr.GetKey(); QByteArray addr_ba(reinterpret_cast(addr_key.data()), addr_key.size()); QTableWidgetItem* addressItem = new CMasternodeListWidgetItem( - QString::fromStdString(dmn.pdmnState->addr.ToStringAddrPort()), addr_ba); + QString::fromStdString(dmn.pdmnState->netInfo.m_addr.ToStringAddrPort()), addr_ba); QTableWidgetItem* typeItem = new QTableWidgetItem(QString::fromStdString(std::string(GetMnType(dmn.nType).description))); QTableWidgetItem* statusItem = new QTableWidgetItem(dmn.pdmnState->IsBanned() ? tr("POSE_BANNED") : tr("ENABLED")); QTableWidgetItem* PoSeScoreItem = new CMasternodeListWidgetItem(QString::number(dmn.pdmnState->nPoSePenalty), dmn.pdmnState->nPoSePenalty); diff --git a/src/rpc/evo.cpp b/src/rpc/evo.cpp index 78bd077c4678..a9b558cdeeb5 100644 --- a/src/rpc/evo.cpp +++ b/src/rpc/evo.cpp @@ -684,7 +684,7 @@ static UniValue protx_register_common_wrapper(const JSONRPCRequest& request, if (!request.params[paramIdx].get_str().empty()) { if (auto addr = Lookup(request.params[paramIdx].get_str(), Params().GetDefaultPort(), false); addr.has_value()) { - ptx.addr = addr.value(); + ptx.netInfo.m_addr = addr.value(); } else { throw std::runtime_error(strprintf("invalid network address %s", request.params[paramIdx].get_str())); } @@ -979,7 +979,7 @@ static UniValue protx_update_service_common_wrapper(const JSONRPCRequest& reques ptx.nVersion = dmn->pdmnState->nVersion; if (auto addr = Lookup(request.params[1].get_str().c_str(), Params().GetDefaultPort(), false); addr.has_value()) { - ptx.addr = addr.value(); + ptx.netInfo.m_addr = addr.value(); } else { throw std::runtime_error(strprintf("invalid network address %s", request.params[1].get_str())); } diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 02699c42c082..ed1e5ed48f8e 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -566,7 +566,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite) } if (strMode == "addr") { - std::string strAddress = dmn.pdmnState->addr.ToStringAddrPort(); + std::string strAddress = dmn.pdmnState->netInfo.m_addr.ToStringAddrPort(); if (!strFilter.empty() && strAddress.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; obj.pushKV(strOutpoint, strAddress); @@ -577,7 +577,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite) payeeStr, PadString(ToString(dmnToLastPaidTime(dmn)), 10), PadString(ToString(dmn.pdmnState->nLastPaidHeight), 6), - dmn.pdmnState->addr.ToStringAddrPort()); + dmn.pdmnState->netInfo.m_addr.ToStringAddrPort()); if (!strFilter.empty() && strFull.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; obj.pushKV(strOutpoint, strFull); @@ -586,14 +586,14 @@ static RPCHelpMan masternodelist_helper(bool is_composite) PadString(dmnToStatus(dmn), 18), dmn.pdmnState->nPoSePenalty, payeeStr, - dmn.pdmnState->addr.ToStringAddrPort()); + dmn.pdmnState->netInfo.m_addr.ToStringAddrPort()); if (!strFilter.empty() && strInfo.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; obj.pushKV(strOutpoint, strInfo); } else if (strMode == "json" || strMode == "recent" || strMode == "evo") { std::string strInfo = strprintf("%s %s %s %s %d %d %d %s %s %s %s", dmn.proTxHash.ToString(), - dmn.pdmnState->addr.ToStringAddrPort(), + dmn.pdmnState->netInfo.m_addr.ToStringAddrPort(), payeeStr, dmnToStatus(dmn), dmn.pdmnState->nPoSePenalty, @@ -607,7 +607,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite) strOutpoint.find(strFilter) == std::string::npos) return; UniValue objMN(UniValue::VOBJ); objMN.pushKV("proTxHash", dmn.proTxHash.ToString()); - objMN.pushKV("address", dmn.pdmnState->addr.ToStringAddrPort()); + objMN.pushKV("address", dmn.pdmnState->netInfo.m_addr.ToStringAddrPort()); objMN.pushKV("payee", payeeStr); objMN.pushKV("status", dmnToStatus(dmn)); objMN.pushKV("type", std::string(GetMnType(dmn.nType).description)); diff --git a/src/rpc/quorums.cpp b/src/rpc/quorums.cpp index c7463d0e7557..5b850b359758 100644 --- a/src/rpc/quorums.cpp +++ b/src/rpc/quorums.cpp @@ -203,7 +203,7 @@ static UniValue BuildQuorumInfo(const llmq::CQuorumBlockProcessor& quorum_block_ const auto& dmn = quorum->members[i]; UniValue mo(UniValue::VOBJ); mo.pushKV("proTxHash", dmn->proTxHash.ToString()); - mo.pushKV("service", dmn->pdmnState->addr.ToStringAddrPort()); + mo.pushKV("service", dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); mo.pushKV("pubKeyOperator", dmn->pdmnState->pubKeyOperator.ToString()); mo.pushKV("valid", quorum->qc->validMembers[i]); if (quorum->qc->validMembers[i]) { diff --git a/src/test/block_reward_reallocation_tests.cpp b/src/test/block_reward_reallocation_tests.cpp index adb1f09ba415..0bf20a703e08 100644 --- a/src/test/block_reward_reallocation_tests.cpp +++ b/src/test/block_reward_reallocation_tests.cpp @@ -117,7 +117,7 @@ static CMutableTransaction CreateProRegTx(const CChain& active_chain, const CTxM CProRegTx proTx; proTx.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); proTx.collateralOutpoint.n = 0; - proTx.addr = LookupNumeric("1.1.1.1", port); + proTx.netInfo.m_addr = LookupNumeric("1.1.1.1", port); proTx.keyIDOwner = ownerKeyRet.GetPubKey().GetID(); proTx.pubKeyOperator.Set(operatorKeyRet.GetPublicKey(), bls::bls_legacy_scheme.load()); proTx.keyIDVoting = ownerKeyRet.GetPubKey().GetID(); diff --git a/src/test/evo_deterministicmns_tests.cpp b/src/test/evo_deterministicmns_tests.cpp index 26eae84c15a7..694b74cdb0ce 100644 --- a/src/test/evo_deterministicmns_tests.cpp +++ b/src/test/evo_deterministicmns_tests.cpp @@ -106,7 +106,7 @@ static CMutableTransaction CreateProRegTx(const CChain& active_chain, const CTxM CProRegTx proTx; proTx.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); proTx.collateralOutpoint.n = 0; - proTx.addr = LookupNumeric("1.1.1.1", port); + proTx.netInfo.m_addr = LookupNumeric("1.1.1.1", port); proTx.keyIDOwner = ownerKeyRet.GetPubKey().GetID(); proTx.pubKeyOperator.Set(operatorKeyRet.GetPublicKey(), bls::bls_legacy_scheme.load()); proTx.keyIDVoting = ownerKeyRet.GetPubKey().GetID(); @@ -128,7 +128,7 @@ static CMutableTransaction CreateProUpServTx(const CChain& active_chain, const C CProUpServTx proTx; proTx.nVersion = CProUpServTx::GetMaxVersion(!bls::bls_legacy_scheme); proTx.proTxHash = proTxHash; - proTx.addr = LookupNumeric("1.1.1.1", port); + proTx.netInfo.m_addr = LookupNumeric("1.1.1.1", port); proTx.scriptOperatorPayout = scriptOperatorPayout; CMutableTransaction tx; @@ -516,7 +516,7 @@ void FuncDIP3Protx(TestChainSetup& setup) nHeight++; auto dmn = dmnman.GetListAtChainTip().GetMN(dmnHashes[0]); - BOOST_REQUIRE(dmn != nullptr && dmn->pdmnState->addr.GetPort() == 1000); + BOOST_REQUIRE(dmn != nullptr && dmn->pdmnState->netInfo.m_addr.GetPort() == 1000); // test ProUpRevTx tx = CreateProUpRevTx(chainman.ActiveChain(), *(setup.m_node.mempool), utxos, dmnHashes[0], operatorKeys[dmnHashes[0]], setup.coinbaseKey); @@ -574,7 +574,7 @@ void FuncDIP3Protx(TestChainSetup& setup) nHeight++; dmn = dmnman.GetListAtChainTip().GetMN(dmnHashes[0]); - BOOST_REQUIRE(dmn != nullptr && dmn->pdmnState->addr.GetPort() == 100); + BOOST_REQUIRE(dmn != nullptr && dmn->pdmnState->netInfo.m_addr.GetPort() == 100); BOOST_REQUIRE(dmn != nullptr && !dmn->pdmnState->IsBanned()); // test that the revived MN gets payments again @@ -634,7 +634,7 @@ void FuncTestMempoolReorg(TestChainSetup& setup) CProRegTx payload; payload.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); - payload.addr = LookupNumeric("1.1.1.1", 1); + payload.netInfo.m_addr = LookupNumeric("1.1.1.1", 1); payload.keyIDOwner = ownerKey.GetPubKey().GetID(); payload.pubKeyOperator.Set(operatorKey.GetPublicKey(), bls::bls_legacy_scheme.load()); payload.keyIDVoting = ownerKey.GetPubKey().GetID(); @@ -708,7 +708,7 @@ void FuncTestMempoolDualProregtx(TestChainSetup& setup) auto scriptPayout = GetScriptForDestination(PKHash(payoutKey.GetPubKey())); CProRegTx payload; - payload.addr = LookupNumeric("1.1.1.1", 2); + payload.netInfo.m_addr = LookupNumeric("1.1.1.1", 2); payload.keyIDOwner = ownerKey.GetPubKey().GetID(); payload.pubKeyOperator.Set(operatorKey.GetPublicKey(), bls::bls_legacy_scheme.load()); payload.keyIDVoting = ownerKey.GetPubKey().GetID(); @@ -776,7 +776,7 @@ void FuncVerifyDB(TestChainSetup& setup) CProRegTx payload; payload.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); - payload.addr = LookupNumeric("1.1.1.1", 1); + payload.netInfo.m_addr = LookupNumeric("1.1.1.1", 1); payload.keyIDOwner = ownerKey.GetPubKey().GetID(); payload.pubKeyOperator.Set(operatorKey.GetPublicKey(), bls::bls_legacy_scheme.load()); payload.keyIDVoting = ownerKey.GetPubKey().GetID(); diff --git a/src/test/evo_simplifiedmns_tests.cpp b/src/test/evo_simplifiedmns_tests.cpp index fa833dbb1bf4..e91db1a31279 100644 --- a/src/test/evo_simplifiedmns_tests.cpp +++ b/src/test/evo_simplifiedmns_tests.cpp @@ -24,7 +24,7 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots) std::string ip = strprintf("%d.%d.%d.%d", 0, 0, 0, i); if (auto service = Lookup(ip, i, false); service.has_value()) { - smle.service = service.value(); + smle.netInfo.m_addr = service.value(); } else { BOOST_REQUIRE(false); } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index e2b92ba5575e..f5840eb2b0df 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -691,7 +691,7 @@ void CTxMemPool::addUncheckedProTx(indexed_transaction_set::iterator& newit, con if (!proTx.collateralOutpoint.hash.IsNull()) { mapProTxRefs.emplace(tx_hash, proTx.collateralOutpoint.hash); } - mapProTxAddresses.emplace(proTx.addr, tx_hash); + mapProTxAddresses.emplace(proTx.netInfo.m_addr, tx_hash); mapProTxPubKeyIDs.emplace(proTx.keyIDOwner, tx_hash); mapProTxBlsPubKeyHashes.emplace(proTx.pubKeyOperator.GetHash(), tx_hash); if (!proTx.collateralOutpoint.hash.IsNull()) { @@ -702,7 +702,7 @@ void CTxMemPool::addUncheckedProTx(indexed_transaction_set::iterator& newit, con } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) { auto proTx = *Assert(GetTxPayload(tx)); mapProTxRefs.emplace(proTx.proTxHash, tx_hash); - mapProTxAddresses.emplace(proTx.addr, tx_hash); + mapProTxAddresses.emplace(proTx.netInfo.m_addr, tx_hash); } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { auto proTx = *Assert(GetTxPayload(tx)); mapProTxRefs.emplace(proTx.proTxHash, tx_hash); @@ -791,7 +791,7 @@ void CTxMemPool::removeUncheckedProTx(const CTransaction& tx) if (!proTx.collateralOutpoint.IsNull()) { eraseProTxRef(tx_hash, proTx.collateralOutpoint.hash); } - mapProTxAddresses.erase(proTx.addr); + mapProTxAddresses.erase(proTx.netInfo.m_addr); mapProTxPubKeyIDs.erase(proTx.keyIDOwner); mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash()); mapProTxCollaterals.erase(proTx.collateralOutpoint); @@ -799,7 +799,7 @@ void CTxMemPool::removeUncheckedProTx(const CTransaction& tx) } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) { auto proTx = *Assert(GetTxPayload(tx)); eraseProTxRef(proTx.proTxHash, tx_hash); - mapProTxAddresses.erase(proTx.addr); + mapProTxAddresses.erase(proTx.netInfo.m_addr); } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { auto proTx = *Assert(GetTxPayload(tx)); eraseProTxRef(proTx.proTxHash, tx_hash); @@ -1026,8 +1026,8 @@ void CTxMemPool::removeProTxConflicts(const CTransaction &tx) } auto& proTx = *opt_proTx; - if (mapProTxAddresses.count(proTx.addr)) { - uint256 conflictHash = mapProTxAddresses[proTx.addr]; + if (mapProTxAddresses.count(proTx.netInfo.m_addr)) { + uint256 conflictHash = mapProTxAddresses[proTx.netInfo.m_addr]; if (conflictHash != tx_hash && mapTx.count(conflictHash)) { removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT); } @@ -1046,8 +1046,8 @@ void CTxMemPool::removeProTxConflicts(const CTransaction &tx) return; } - if (mapProTxAddresses.count(opt_proTx->addr)) { - uint256 conflictHash = mapProTxAddresses[opt_proTx->addr]; + if (mapProTxAddresses.count(opt_proTx->netInfo.m_addr)) { + uint256 conflictHash = mapProTxAddresses[opt_proTx->netInfo.m_addr]; if (conflictHash != tx_hash && mapTx.count(conflictHash)) { removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT); } @@ -1382,7 +1382,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { return true; // i.e. can't decode payload == conflict } auto& proTx = *opt_proTx; - if (mapProTxAddresses.count(proTx.addr) || mapProTxPubKeyIDs.count(proTx.keyIDOwner) || mapProTxBlsPubKeyHashes.count(proTx.pubKeyOperator.GetHash())) + if (mapProTxAddresses.count(proTx.netInfo.m_addr) || mapProTxPubKeyIDs.count(proTx.keyIDOwner) || mapProTxBlsPubKeyHashes.count(proTx.pubKeyOperator.GetHash())) return true; if (!proTx.collateralOutpoint.hash.IsNull()) { if (mapProTxCollaterals.count(proTx.collateralOutpoint)) { @@ -1401,7 +1401,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx_hash.ToString()); return true; // i.e. can't decode payload == conflict } - auto it = mapProTxAddresses.find(opt_proTx->addr); + auto it = mapProTxAddresses.find(opt_proTx->netInfo.m_addr); return it != mapProTxAddresses.end() && it->second != opt_proTx->proTxHash; } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { const auto opt_proTx = GetTxPayload(tx); From e868aff10c19c4c90ec6b19ca711b83ac0930aa0 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 4 Apr 2025 22:35:38 +0000 Subject: [PATCH 03/10] refactor: use const-ref when accessing `MnNetInfo::addr` if read-only --- src/coinjoin/client.cpp | 12 ++++++------ src/evo/core_write.cpp | 4 ++-- src/evo/deterministicmns.cpp | 22 ++++++++++++---------- src/evo/dmnstate.cpp | 6 +++--- src/evo/netinfo.h | 2 ++ src/evo/providertx.cpp | 9 +++++---- src/evo/simplifiedmns.cpp | 7 ++++--- src/llmq/utils.cpp | 6 ++++-- src/masternode/node.cpp | 4 ++-- src/masternode/utils.cpp | 5 +++-- src/net.cpp | 16 ++++++++-------- src/qt/masternodelist.cpp | 4 ++-- src/rpc/masternode.cpp | 10 +++++----- src/rpc/quorums.cpp | 2 +- src/test/evo_deterministicmns_tests.cpp | 4 ++-- src/txmempool.cpp | 20 ++++++++++---------- 16 files changed, 71 insertions(+), 62 deletions(-) diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index ccecd4dea41b..b8713a5b67bc 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -186,7 +186,7 @@ void CCoinJoinClientSession::ProcessMessage(CNode& peer, CChainState& active_cha if (!m_mn_sync.IsBlockchainSynced()) return; if (!mixingMasternode) return; - if (mixingMasternode->pdmnState->netInfo.m_addr != peer.addr) return; + if (mixingMasternode->pdmnState->netInfo.GetPrimary() != peer.addr) return; if (msg_type == NetMsgType::DSSTATUSUPDATE) { CCoinJoinStatusUpdate psssup; @@ -1106,7 +1106,7 @@ bool CCoinJoinClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized, m_clientman.AddUsedMasternode(dsq.masternodeOutpoint); - if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->netInfo.m_addr)) { + if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->netInfo.GetPrimary())) { WalletCJLogPrint(m_wallet, /* Continued */ "CCoinJoinClientSession::JoinExistingQueue -- skipping connection, masternode=%s\n", dmn->proTxHash.ToString()); continue; @@ -1178,7 +1178,7 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon continue; } - if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->netInfo.m_addr)) { + if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->netInfo.GetPrimary())) { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- skipping connection, masternode=%s\n", dmn->proTxHash.ToString()); nTries++; @@ -1218,7 +1218,7 @@ bool CCoinJoinClientSession::ProcessPendingDsaRequest(CConnman& connman) CService mn_addr; if (auto dmn = m_dmnman.GetListAtChainTip().GetMN(pendingDsaRequest.GetProTxHash())) { - mn_addr = Assert(dmn->pdmnState)->netInfo.m_addr; + mn_addr = Assert(dmn->pdmnState)->netInfo.GetPrimary(); } else { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- cannot find address to connect, masternode=%s\n", __func__, pendingDsaRequest.GetProTxHash().ToString()); @@ -1820,7 +1820,7 @@ void CCoinJoinClientSession::RelayIn(const CCoinJoinEntry& entry, CConnman& conn { if (!mixingMasternode) return; - connman.ForNode(mixingMasternode->pdmnState->netInfo.m_addr, [&entry, &connman, this](CNode* pnode) { + connman.ForNode(mixingMasternode->pdmnState->netInfo.GetPrimary(), [&entry, &connman, this](CNode* pnode) { WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::RelayIn -- found master, relaying message to %s\n", pnode->addr.ToStringAddrPort()); CNetMsgMaker msgMaker(pnode->GetCommonVersion()); @@ -1876,7 +1876,7 @@ void CCoinJoinClientSession::GetJsonInfo(UniValue& obj) const assert(mixingMasternode->pdmnState); obj.pushKV("protxhash", mixingMasternode->proTxHash.ToString()); obj.pushKV("outpoint", mixingMasternode->collateralOutpoint.ToStringShort()); - obj.pushKV("service", mixingMasternode->pdmnState->netInfo.m_addr.ToStringAddrPort()); + obj.pushKV("service", mixingMasternode->pdmnState->netInfo.GetPrimary().ToStringAddrPort()); } obj.pushKV("denomination", ValueFromAmount(CoinJoin::DenominationToAmount(nSessionDenom))); obj.pushKV("state", GetStateString()); diff --git a/src/evo/core_write.cpp b/src/evo/core_write.cpp index 24e59d8a093c..b851cc075c3c 100644 --- a/src/evo/core_write.cpp +++ b/src/evo/core_write.cpp @@ -67,7 +67,7 @@ ret.pushKV("type", ToUnderlying(nType)); ret.pushKV("collateralHash", collateralOutpoint.hash.ToString()); ret.pushKV("collateralIndex", (int)collateralOutpoint.n); - ret.pushKV("service", netInfo.m_addr.ToStringAddrPort()); + ret.pushKV("service", netInfo.GetPrimary().ToStringAddrPort()); ret.pushKV("ownerAddress", EncodeDestination(PKHash(keyIDOwner))); ret.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting))); if (CTxDestination dest; ExtractDestination(scriptPayout, dest)) { @@ -114,7 +114,7 @@ ret.pushKV("version", nVersion); ret.pushKV("type", ToUnderlying(nType)); ret.pushKV("proTxHash", proTxHash.ToString()); - ret.pushKV("service", netInfo.m_addr.ToStringAddrPort()); + ret.pushKV("service", netInfo.GetPrimary().ToStringAddrPort()); if (CTxDestination dest; ExtractDestination(scriptOperatorPayout, dest)) { ret.pushKV("operatorPayoutAddress", EncodeDestination(dest)); } diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 7c2d76f7946e..bd877f6ac9cb 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -470,10 +470,11 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTota throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate collateralOutpoint=%s", __func__, dmn->proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort()))); } - if (dmn->pdmnState->netInfo.m_addr != CService() && !AddUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { + if (dmn->pdmnState->netInfo.GetPrimary() != CService() && !AddUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s", __func__, - dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()))); + dmn->proTxHash.ToString(), + dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()))); } if (!AddUniqueProperty(*dmn, dmn->pdmnState->keyIDOwner)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; @@ -514,7 +515,8 @@ void CDeterministicMNList::UpdateMN(const CDeterministicMN& oldDmn, const std::s if (!UpdateUniqueProperty(*dmn, oldState->netInfo, pdmnState->netInfo)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; throw(std::runtime_error(strprintf("%s: Can't update a masternode %s with a duplicate address=%s", __func__, - oldDmn.proTxHash.ToString(), pdmnState->netInfo.m_addr.ToStringAddrPort()))); + oldDmn.proTxHash.ToString(), + pdmnState->netInfo.GetPrimary().ToStringAddrPort()))); } if (!UpdateUniqueProperty(*dmn, oldState->keyIDOwner, pdmnState->keyIDOwner)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; @@ -571,10 +573,10 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash) throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a collateralOutpoint=%s", __func__, proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort()))); } - if (dmn->pdmnState->netInfo.m_addr != CService() && !DeleteUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { + if (dmn->pdmnState->netInfo.GetPrimary() != CService() && !DeleteUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a address=%s", __func__, - proTxHash.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()))); + proTxHash.ToString(), dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()))); } if (!DeleteUniqueProperty(*dmn, dmn->pdmnState->keyIDOwner)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; @@ -800,7 +802,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no auto dmnState = std::make_shared(proTx); dmnState->nRegisteredHeight = nHeight; - if (proTx.netInfo.m_addr == CService()) { + if (proTx.netInfo.GetPrimary() == CService()) { // start in banned pdmnState as we need to wait for a ProUpServTx dmnState->BanIfNotBanned(nHeight); } @@ -1178,7 +1180,7 @@ void CDeterministicMNManager::CleanupCache(int nHeight) template static bool CheckService(const ProTx& proTx, TxValidationState& state) { - const auto& addr{proTx.netInfo.m_addr}; + const auto addr{proTx.netInfo.GetPrimary()}; if (!addr.IsValid()) { return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr"); } @@ -1235,8 +1237,8 @@ static bool CheckPlatformFields(const ProTx& proTx, TxValidationState& state) return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-http-port"); } - if (proTx.platformP2PPort == proTx.platformHTTPPort || proTx.platformP2PPort == proTx.netInfo.m_addr.GetPort() || - proTx.platformHTTPPort == proTx.netInfo.m_addr.GetPort()) { + if (proTx.platformP2PPort == proTx.platformHTTPPort || proTx.platformP2PPort == proTx.netInfo.GetPrimary().GetPort() || + proTx.platformHTTPPort == proTx.netInfo.GetPrimary().GetPort()) { return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-dup-ports"); } @@ -1301,7 +1303,7 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl: // It's allowed to set addr to 0, which will put the MN into PoSe-banned state and require a ProUpServTx to be issues later // If any of both is set, it must be valid however - if (opt_ptx->netInfo.m_addr != CService() && !CheckService(*opt_ptx, state)) { + if (opt_ptx->netInfo.GetPrimary() != CService() && !CheckService(*opt_ptx, state)) { // pass the state returned by the function above return false; } diff --git a/src/evo/dmnstate.cpp b/src/evo/dmnstate.cpp index 8fd3de6ae441..365336494562 100644 --- a/src/evo/dmnstate.cpp +++ b/src/evo/dmnstate.cpp @@ -31,7 +31,7 @@ std::string CDeterministicMNState::ToString() const "operatorPayoutAddress=%s)", nVersion, nRegisteredHeight, nLastPaidHeight, nPoSePenalty, nPoSeRevivedHeight, nPoSeBanHeight, nRevocationReason, EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), - EncodeDestination(PKHash(keyIDVoting)), netInfo.m_addr.ToStringAddrPort(), payoutAddress, + EncodeDestination(PKHash(keyIDVoting)), netInfo.GetPrimary().ToStringAddrPort(), payoutAddress, operatorPayoutAddress); } @@ -39,7 +39,7 @@ UniValue CDeterministicMNState::ToJson(MnType nType) const { UniValue obj(UniValue::VOBJ); obj.pushKV("version", nVersion); - obj.pushKV("service", netInfo.m_addr.ToStringAddrPort()); + obj.pushKV("service", netInfo.GetPrimary().ToStringAddrPort()); obj.pushKV("registeredHeight", nRegisteredHeight); obj.pushKV("lastPaidHeight", nLastPaidHeight); obj.pushKV("consecutivePayments", nConsecutivePayments); @@ -73,7 +73,7 @@ UniValue CDeterministicMNStateDiff::ToJson(MnType nType) const obj.pushKV("version", state.nVersion); } if (fields & Field_netInfo) { - obj.pushKV("service", state.netInfo.m_addr.ToStringAddrPort()); + obj.pushKV("service", state.netInfo.GetPrimary().ToStringAddrPort()); } if (fields & Field_nRegisteredHeight) { obj.pushKV("registeredHeight", state.nRegisteredHeight); diff --git a/src/evo/netinfo.h b/src/evo/netinfo.h index 87aedacba42e..eca2f790f0d9 100644 --- a/src/evo/netinfo.h +++ b/src/evo/netinfo.h @@ -26,6 +26,8 @@ class MnNetInfo { READWRITE(obj.m_addr); } + + const CService& GetPrimary() const { return m_addr; } }; #endif // BITCOIN_EVO_NETINFO_H diff --git a/src/evo/providertx.cpp b/src/evo/providertx.cpp index e06205cca760..7b215c92121d 100644 --- a/src/evo/providertx.cpp +++ b/src/evo/providertx.cpp @@ -90,8 +90,9 @@ std::string CProRegTx::ToString() const return strprintf("CProRegTx(nVersion=%d, nType=%d, collateralOutpoint=%s, addr=%s, nOperatorReward=%f, " "ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, scriptPayout=%s, platformNodeID=%s, " "platformP2PPort=%d, platformHTTPPort=%d)", - nVersion, ToUnderlying(nType), collateralOutpoint.ToStringShort(), netInfo.m_addr.ToStringAddrPort(), - (double)nOperatorReward / 100, EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), + nVersion, ToUnderlying(nType), collateralOutpoint.ToStringShort(), + netInfo.GetPrimary().ToStringAddrPort(), (double)nOperatorReward / 100, + EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), payee, platformNodeID.ToString(), platformP2PPort, platformHTTPPort); } @@ -118,8 +119,8 @@ std::string CProUpServTx::ToString() const return strprintf("CProUpServTx(nVersion=%d, nType=%d, proTxHash=%s, addr=%s, operatorPayoutAddress=%s, " "platformNodeID=%s, platformP2PPort=%d, platformHTTPPort=%d)", - nVersion, ToUnderlying(nType), proTxHash.ToString(), netInfo.m_addr.ToStringAddrPort(), payee, - platformNodeID.ToString(), platformP2PPort, platformHTTPPort); + nVersion, ToUnderlying(nType), proTxHash.ToString(), netInfo.GetPrimary().ToStringAddrPort(), + payee, platformNodeID.ToString(), platformP2PPort, platformHTTPPort); } bool CProUpRegTx::IsTriviallyValid(bool is_basic_scheme_active, TxValidationState& state) const diff --git a/src/evo/simplifiedmns.cpp b/src/evo/simplifiedmns.cpp index 7297373ff37d..b10db766417e 100644 --- a/src/evo/simplifiedmns.cpp +++ b/src/evo/simplifiedmns.cpp @@ -66,8 +66,9 @@ std::string CSimplifiedMNListEntry::ToString() const "pubKeyOperator=%s, votingAddress=%s, isValid=%d, payoutAddress=%s, operatorPayoutAddress=%s, " "platformHTTPPort=%d, platformNodeID=%s)", nVersion, ToUnderlying(nType), proRegTxHash.ToString(), confirmedHash.ToString(), - netInfo.m_addr.ToStringAddrPort(), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), - isValid, payoutAddress, operatorPayoutAddress, platformHTTPPort, platformNodeID.ToString()); + netInfo.GetPrimary().ToStringAddrPort(), pubKeyOperator.ToString(), + EncodeDestination(PKHash(keyIDVoting)), isValid, payoutAddress, operatorPayoutAddress, + platformHTTPPort, platformNodeID.ToString()); } UniValue CSimplifiedMNListEntry::ToJson(bool extended) const @@ -77,7 +78,7 @@ UniValue CSimplifiedMNListEntry::ToJson(bool extended) const obj.pushKV("nType", ToUnderlying(nType)); obj.pushKV("proRegTxHash", proRegTxHash.ToString()); obj.pushKV("confirmedHash", confirmedHash.ToString()); - obj.pushKV("service", netInfo.m_addr.ToStringAddrPort()); + obj.pushKV("service", netInfo.GetPrimary().ToStringAddrPort()); obj.pushKV("pubKeyOperator", pubKeyOperator.ToString()); obj.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting))); obj.pushKV("isValid", isValid); diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index 4ae040e26bc8..8966a3e6c05f 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -823,7 +823,8 @@ bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& if (!dmn) { debugMsg += strprintf(" %s (not in valid MN set anymore)\n", c.ToString()); } else { - debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); + debugMsg += strprintf(" %s (%s)\n", c.ToString(), + dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()); } } LogPrint(BCLog::NET_NETCONN, debugMsg.c_str()); /* Continued */ @@ -871,7 +872,8 @@ void AddQuorumProbeConnections(const Consensus::LLMQParams& llmqParams, CConnman if (!dmn) { debugMsg += strprintf(" %s (not in valid MN set anymore)\n", c.ToString()); } else { - debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); + debugMsg += strprintf(" %s (%s)\n", c.ToString(), + dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()); } } LogPrint(BCLog::NET_NETCONN, debugMsg.c_str()); /* Continued */ diff --git a/src/masternode/node.cpp b/src/masternode/node.cpp index 76a1bd4e107b..7fe30266da5d 100644 --- a/src/masternode/node.cpp +++ b/src/masternode/node.cpp @@ -146,7 +146,7 @@ void CActiveMasternodeManager::InitInternal(const CBlockIndex* pindex) LogPrintf("CActiveMasternodeManager::Init -- proTxHash=%s, proTx=%s\n", dmn->proTxHash.ToString(), dmn->ToString()); - if (m_info.service != dmn->pdmnState->netInfo.m_addr) { + if (m_info.service != dmn->pdmnState->netInfo.GetPrimary()) { m_state = MasternodeState::SOME_ERROR; m_error = "Local address does not match the address from ProTx"; LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error); @@ -201,7 +201,7 @@ void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, con // MN operator key changed or revoked return reset(MasternodeState::OPERATOR_KEY_CHANGED); } - if (newDmn->pdmnState->netInfo.m_addr != oldDmn->pdmnState->netInfo.m_addr) { + if (newDmn->pdmnState->netInfo.GetPrimary() != oldDmn->pdmnState->netInfo.GetPrimary()) { // MN IP changed return reset(MasternodeState::PROTX_IP_CHANGED); } diff --git a/src/masternode/utils.cpp b/src/masternode/utils.cpp index abcf6b628432..0757ac8815c1 100644 --- a/src/masternode/utils.cpp +++ b/src/masternode/utils.cpp @@ -77,8 +77,9 @@ void CMasternodeUtils::DoMaintenance(CConnman& connman, CDeterministicMNManager& } #ifdef ENABLE_WALLET - bool fFound = ranges::any_of(vecDmns, - [&pnode](const auto& dmn) { return pnode->addr == dmn->pdmnState->netInfo.m_addr; }); + bool fFound = ranges::any_of(vecDmns, [&pnode](const auto& dmn) { + return pnode->addr == dmn->pdmnState->netInfo.GetPrimary(); + }); if (fFound) return; // do NOT disconnect mixing masternodes #endif // ENABLE_WALLET if (fLogIPs) { diff --git a/src/net.cpp b/src/net.cpp index 3c82865311a2..4f6683e145cb 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3674,7 +3674,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, if (!dmn) { continue; } - const auto& addr2 = dmn->pdmnState->netInfo.m_addr; + const auto addr2 = dmn->pdmnState->netInfo.GetPrimary(); if (connectedNodes.count(addr2) && !connectedProRegTxHashes.count(proRegTxHash)) { // we probably connected to it before it became a masternode // or maybe we are still waiting for mnauth @@ -3740,8 +3740,8 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, if (!vPendingMasternodes.empty()) { auto dmn = mnList.GetValidMN(vPendingMasternodes.front()); vPendingMasternodes.erase(vPendingMasternodes.begin()); - if (dmn && !connectedNodes.count(dmn->pdmnState->netInfo.m_addr) && !IsMasternodeOrDisconnectRequested(dmn->pdmnState->netInfo.m_addr)) { - LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- opening pending masternode connection to %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); + if (dmn && !connectedNodes.count(dmn->pdmnState->netInfo.GetPrimary()) && !IsMasternodeOrDisconnectRequested(dmn->pdmnState->netInfo.GetPrimary())) { + LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- opening pending masternode connection to %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()); return dmn; } } @@ -3750,7 +3750,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, // not-null auto dmn = pending[GetRand(pending.size())]; LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- opening quorum connection to %s, service=%s\n", - _func_, dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); + _func_, dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()); return dmn; } @@ -3760,7 +3760,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, masternodePendingProbes.erase(dmn->proTxHash); isProbe = MasternodeProbeConn::IsConnection; - LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- probing masternode %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); + LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- probing masternode %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()); return dmn; } return nullptr; @@ -3776,16 +3776,16 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, mn_metaman.GetMetaInfo(connectToDmn->proTxHash)->SetLastOutboundAttempt(nANow); - OpenMasternodeConnection(CAddress(connectToDmn->pdmnState->netInfo.m_addr, NODE_NETWORK), /*use_v2transport=*/GetLocalServices() & NODE_P2P_V2, isProbe); + OpenMasternodeConnection(CAddress(connectToDmn->pdmnState->netInfo.GetPrimary(), NODE_NETWORK), /*use_v2transport=*/GetLocalServices() & NODE_P2P_V2, isProbe); // should be in the list now if connection was opened - bool connected = ForNode(connectToDmn->pdmnState->netInfo.m_addr, CConnman::AllNodes, [&](CNode* pnode) { + bool connected = ForNode(connectToDmn->pdmnState->netInfo.GetPrimary(), CConnman::AllNodes, [&](CNode* pnode) { if (pnode->fDisconnect) { return false; } return true; }); if (!connected) { - LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- connection failed for masternode %s, service=%s\n", __func__, connectToDmn->proTxHash.ToString(), connectToDmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); + LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- connection failed for masternode %s, service=%s\n", __func__, connectToDmn->proTxHash.ToString(), connectToDmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()); // Will take a few consequent failed attempts to PoSe-punish a MN. if (mn_metaman.GetMetaInfo(connectToDmn->proTxHash)->OutboundFailedTooManyTimes()) { LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- failed to connect to masternode %s too many times\n", __func__, connectToDmn->proTxHash.ToString()); diff --git a/src/qt/masternodelist.cpp b/src/qt/masternodelist.cpp index 69f151f33209..546125d92eeb 100644 --- a/src/qt/masternodelist.cpp +++ b/src/qt/masternodelist.cpp @@ -221,10 +221,10 @@ void MasternodeList::updateDIP3List() } // populate list // Address, Protocol, Status, Active Seconds, Last Seen, Pub Key - auto addr_key = dmn.pdmnState->netInfo.m_addr.GetKey(); + auto addr_key = dmn.pdmnState->netInfo.GetPrimary().GetKey(); QByteArray addr_ba(reinterpret_cast(addr_key.data()), addr_key.size()); QTableWidgetItem* addressItem = new CMasternodeListWidgetItem( - QString::fromStdString(dmn.pdmnState->netInfo.m_addr.ToStringAddrPort()), addr_ba); + QString::fromStdString(dmn.pdmnState->netInfo.GetPrimary().ToStringAddrPort()), addr_ba); QTableWidgetItem* typeItem = new QTableWidgetItem(QString::fromStdString(std::string(GetMnType(dmn.nType).description))); QTableWidgetItem* statusItem = new QTableWidgetItem(dmn.pdmnState->IsBanned() ? tr("POSE_BANNED") : tr("ENABLED")); QTableWidgetItem* PoSeScoreItem = new CMasternodeListWidgetItem(QString::number(dmn.pdmnState->nPoSePenalty), dmn.pdmnState->nPoSePenalty); diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index ed1e5ed48f8e..ee17547da764 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -566,7 +566,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite) } if (strMode == "addr") { - std::string strAddress = dmn.pdmnState->netInfo.m_addr.ToStringAddrPort(); + std::string strAddress = dmn.pdmnState->netInfo.GetPrimary().ToStringAddrPort(); if (!strFilter.empty() && strAddress.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; obj.pushKV(strOutpoint, strAddress); @@ -577,7 +577,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite) payeeStr, PadString(ToString(dmnToLastPaidTime(dmn)), 10), PadString(ToString(dmn.pdmnState->nLastPaidHeight), 6), - dmn.pdmnState->netInfo.m_addr.ToStringAddrPort()); + dmn.pdmnState->netInfo.GetPrimary().ToStringAddrPort()); if (!strFilter.empty() && strFull.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; obj.pushKV(strOutpoint, strFull); @@ -586,14 +586,14 @@ static RPCHelpMan masternodelist_helper(bool is_composite) PadString(dmnToStatus(dmn), 18), dmn.pdmnState->nPoSePenalty, payeeStr, - dmn.pdmnState->netInfo.m_addr.ToStringAddrPort()); + dmn.pdmnState->netInfo.GetPrimary().ToStringAddrPort()); if (!strFilter.empty() && strInfo.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; obj.pushKV(strOutpoint, strInfo); } else if (strMode == "json" || strMode == "recent" || strMode == "evo") { std::string strInfo = strprintf("%s %s %s %s %d %d %d %s %s %s %s", dmn.proTxHash.ToString(), - dmn.pdmnState->netInfo.m_addr.ToStringAddrPort(), + dmn.pdmnState->netInfo.GetPrimary().ToStringAddrPort(), payeeStr, dmnToStatus(dmn), dmn.pdmnState->nPoSePenalty, @@ -607,7 +607,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite) strOutpoint.find(strFilter) == std::string::npos) return; UniValue objMN(UniValue::VOBJ); objMN.pushKV("proTxHash", dmn.proTxHash.ToString()); - objMN.pushKV("address", dmn.pdmnState->netInfo.m_addr.ToStringAddrPort()); + objMN.pushKV("address", dmn.pdmnState->netInfo.GetPrimary().ToStringAddrPort()); objMN.pushKV("payee", payeeStr); objMN.pushKV("status", dmnToStatus(dmn)); objMN.pushKV("type", std::string(GetMnType(dmn.nType).description)); diff --git a/src/rpc/quorums.cpp b/src/rpc/quorums.cpp index 5b850b359758..e59b3a1df398 100644 --- a/src/rpc/quorums.cpp +++ b/src/rpc/quorums.cpp @@ -203,7 +203,7 @@ static UniValue BuildQuorumInfo(const llmq::CQuorumBlockProcessor& quorum_block_ const auto& dmn = quorum->members[i]; UniValue mo(UniValue::VOBJ); mo.pushKV("proTxHash", dmn->proTxHash.ToString()); - mo.pushKV("service", dmn->pdmnState->netInfo.m_addr.ToStringAddrPort()); + mo.pushKV("service", dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()); mo.pushKV("pubKeyOperator", dmn->pdmnState->pubKeyOperator.ToString()); mo.pushKV("valid", quorum->qc->validMembers[i]); if (quorum->qc->validMembers[i]) { diff --git a/src/test/evo_deterministicmns_tests.cpp b/src/test/evo_deterministicmns_tests.cpp index 694b74cdb0ce..aa5bf74b4db8 100644 --- a/src/test/evo_deterministicmns_tests.cpp +++ b/src/test/evo_deterministicmns_tests.cpp @@ -516,7 +516,7 @@ void FuncDIP3Protx(TestChainSetup& setup) nHeight++; auto dmn = dmnman.GetListAtChainTip().GetMN(dmnHashes[0]); - BOOST_REQUIRE(dmn != nullptr && dmn->pdmnState->netInfo.m_addr.GetPort() == 1000); + BOOST_REQUIRE(dmn != nullptr && dmn->pdmnState->netInfo.GetPrimary().GetPort() == 1000); // test ProUpRevTx tx = CreateProUpRevTx(chainman.ActiveChain(), *(setup.m_node.mempool), utxos, dmnHashes[0], operatorKeys[dmnHashes[0]], setup.coinbaseKey); @@ -574,7 +574,7 @@ void FuncDIP3Protx(TestChainSetup& setup) nHeight++; dmn = dmnman.GetListAtChainTip().GetMN(dmnHashes[0]); - BOOST_REQUIRE(dmn != nullptr && dmn->pdmnState->netInfo.m_addr.GetPort() == 100); + BOOST_REQUIRE(dmn != nullptr && dmn->pdmnState->netInfo.GetPrimary().GetPort() == 100); BOOST_REQUIRE(dmn != nullptr && !dmn->pdmnState->IsBanned()); // test that the revived MN gets payments again diff --git a/src/txmempool.cpp b/src/txmempool.cpp index f5840eb2b0df..538d8851868c 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -691,7 +691,7 @@ void CTxMemPool::addUncheckedProTx(indexed_transaction_set::iterator& newit, con if (!proTx.collateralOutpoint.hash.IsNull()) { mapProTxRefs.emplace(tx_hash, proTx.collateralOutpoint.hash); } - mapProTxAddresses.emplace(proTx.netInfo.m_addr, tx_hash); + mapProTxAddresses.emplace(proTx.netInfo.GetPrimary(), tx_hash); mapProTxPubKeyIDs.emplace(proTx.keyIDOwner, tx_hash); mapProTxBlsPubKeyHashes.emplace(proTx.pubKeyOperator.GetHash(), tx_hash); if (!proTx.collateralOutpoint.hash.IsNull()) { @@ -702,7 +702,7 @@ void CTxMemPool::addUncheckedProTx(indexed_transaction_set::iterator& newit, con } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) { auto proTx = *Assert(GetTxPayload(tx)); mapProTxRefs.emplace(proTx.proTxHash, tx_hash); - mapProTxAddresses.emplace(proTx.netInfo.m_addr, tx_hash); + mapProTxAddresses.emplace(proTx.netInfo.GetPrimary(), tx_hash); } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { auto proTx = *Assert(GetTxPayload(tx)); mapProTxRefs.emplace(proTx.proTxHash, tx_hash); @@ -791,7 +791,7 @@ void CTxMemPool::removeUncheckedProTx(const CTransaction& tx) if (!proTx.collateralOutpoint.IsNull()) { eraseProTxRef(tx_hash, proTx.collateralOutpoint.hash); } - mapProTxAddresses.erase(proTx.netInfo.m_addr); + mapProTxAddresses.erase(proTx.netInfo.GetPrimary()); mapProTxPubKeyIDs.erase(proTx.keyIDOwner); mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash()); mapProTxCollaterals.erase(proTx.collateralOutpoint); @@ -799,7 +799,7 @@ void CTxMemPool::removeUncheckedProTx(const CTransaction& tx) } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) { auto proTx = *Assert(GetTxPayload(tx)); eraseProTxRef(proTx.proTxHash, tx_hash); - mapProTxAddresses.erase(proTx.netInfo.m_addr); + mapProTxAddresses.erase(proTx.netInfo.GetPrimary()); } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { auto proTx = *Assert(GetTxPayload(tx)); eraseProTxRef(proTx.proTxHash, tx_hash); @@ -1026,8 +1026,8 @@ void CTxMemPool::removeProTxConflicts(const CTransaction &tx) } auto& proTx = *opt_proTx; - if (mapProTxAddresses.count(proTx.netInfo.m_addr)) { - uint256 conflictHash = mapProTxAddresses[proTx.netInfo.m_addr]; + if (mapProTxAddresses.count(proTx.netInfo.GetPrimary())) { + uint256 conflictHash = mapProTxAddresses[proTx.netInfo.GetPrimary()]; if (conflictHash != tx_hash && mapTx.count(conflictHash)) { removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT); } @@ -1046,8 +1046,8 @@ void CTxMemPool::removeProTxConflicts(const CTransaction &tx) return; } - if (mapProTxAddresses.count(opt_proTx->netInfo.m_addr)) { - uint256 conflictHash = mapProTxAddresses[opt_proTx->netInfo.m_addr]; + if (mapProTxAddresses.count(opt_proTx->netInfo.GetPrimary())) { + uint256 conflictHash = mapProTxAddresses[opt_proTx->netInfo.GetPrimary()]; if (conflictHash != tx_hash && mapTx.count(conflictHash)) { removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT); } @@ -1382,7 +1382,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { return true; // i.e. can't decode payload == conflict } auto& proTx = *opt_proTx; - if (mapProTxAddresses.count(proTx.netInfo.m_addr) || mapProTxPubKeyIDs.count(proTx.keyIDOwner) || mapProTxBlsPubKeyHashes.count(proTx.pubKeyOperator.GetHash())) + if (mapProTxAddresses.count(proTx.netInfo.GetPrimary()) || mapProTxPubKeyIDs.count(proTx.keyIDOwner) || mapProTxBlsPubKeyHashes.count(proTx.pubKeyOperator.GetHash())) return true; if (!proTx.collateralOutpoint.hash.IsNull()) { if (mapProTxCollaterals.count(proTx.collateralOutpoint)) { @@ -1401,7 +1401,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx_hash.ToString()); return true; // i.e. can't decode payload == conflict } - auto it = mapProTxAddresses.find(opt_proTx->netInfo.m_addr); + auto it = mapProTxAddresses.find(opt_proTx->netInfo.GetPrimary()); return it != mapProTxAddresses.end() && it->second != opt_proTx->proTxHash; } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { const auto opt_proTx = GetTxPayload(tx); From e1783cb9433fc931f411b48f7c04dac13d8d947c Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Wed, 7 May 2025 17:57:26 +0000 Subject: [PATCH 04/10] refactor: remove direct access to `MnNetInfo::addr` --- src/Makefile.am | 1 + src/evo/deterministicmns.cpp | 8 ++++---- src/evo/dmnstate.h | 2 +- src/evo/netinfo.cpp | 11 +++++++++++ src/evo/netinfo.h | 11 ++++++++++- src/rpc/evo.cpp | 4 ++-- src/test/block_reward_reallocation_tests.cpp | 2 +- src/test/evo_deterministicmns_tests.cpp | 10 +++++----- src/test/evo_simplifiedmns_tests.cpp | 2 +- 9 files changed, 36 insertions(+), 15 deletions(-) create mode 100644 src/evo/netinfo.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 9e8aa5ca464d..d3839cf03a4b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -777,6 +777,7 @@ libbitcoin_common_a_SOURCES = \ core_write.cpp \ deploymentinfo.cpp \ evo/core_write.cpp \ + evo/netinfo.cpp \ governance/common.cpp \ init/common.cpp \ key.cpp \ diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index bd877f6ac9cb..a81f8b591c3b 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -470,7 +470,7 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTota throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate collateralOutpoint=%s", __func__, dmn->proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort()))); } - if (dmn->pdmnState->netInfo.GetPrimary() != CService() && !AddUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { + if (!dmn->pdmnState->netInfo.IsEmpty() && !AddUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s", __func__, dmn->proTxHash.ToString(), @@ -573,7 +573,7 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash) throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a collateralOutpoint=%s", __func__, proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort()))); } - if (dmn->pdmnState->netInfo.GetPrimary() != CService() && !DeleteUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { + if (!dmn->pdmnState->netInfo.IsEmpty() && !DeleteUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a address=%s", __func__, proTxHash.ToString(), dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()))); @@ -802,7 +802,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no auto dmnState = std::make_shared(proTx); dmnState->nRegisteredHeight = nHeight; - if (proTx.netInfo.GetPrimary() == CService()) { + if (proTx.netInfo.IsEmpty()) { // start in banned pdmnState as we need to wait for a ProUpServTx dmnState->BanIfNotBanned(nHeight); } @@ -1303,7 +1303,7 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl: // It's allowed to set addr to 0, which will put the MN into PoSe-banned state and require a ProUpServTx to be issues later // If any of both is set, it must be valid however - if (opt_ptx->netInfo.GetPrimary() != CService() && !CheckService(*opt_ptx, state)) { + if (!opt_ptx->netInfo.IsEmpty() && !CheckService(*opt_ptx, state)) { // pass the state returned by the function above return false; } diff --git a/src/evo/dmnstate.h b/src/evo/dmnstate.h index 85e7fb9434f9..49a3b4745d55 100644 --- a/src/evo/dmnstate.h +++ b/src/evo/dmnstate.h @@ -112,7 +112,7 @@ class CDeterministicMNState { nVersion = ProTxVersion::LegacyBLS; pubKeyOperator = CBLSLazyPublicKey(); - netInfo.m_addr = CService(); + netInfo.Clear(); scriptOperatorPayout = CScript(); nRevocationReason = CProUpRevTx::REASON_NOT_SPECIFIED; platformNodeID = uint160(); diff --git a/src/evo/netinfo.cpp b/src/evo/netinfo.cpp new file mode 100644 index 000000000000..ee74719fba78 --- /dev/null +++ b/src/evo/netinfo.cpp @@ -0,0 +1,11 @@ +// Copyright (c) 2025 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +NetInfoStatus MnNetInfo::AddEntry(const CService& service) +{ + m_addr = service; + return NetInfoStatus::Success; +} diff --git a/src/evo/netinfo.h b/src/evo/netinfo.h index eca2f790f0d9..5e02d0268a41 100644 --- a/src/evo/netinfo.h +++ b/src/evo/netinfo.h @@ -10,9 +10,13 @@ class CService; +enum class NetInfoStatus : uint8_t { + Success +}; + class MnNetInfo { -public: +private: CService m_addr{}; public: @@ -27,7 +31,12 @@ class MnNetInfo READWRITE(obj.m_addr); } + NetInfoStatus AddEntry(const CService& service); + const CService& GetPrimary() const { return m_addr; } + bool IsEmpty() const { return *this == MnNetInfo(); } + + void Clear() { m_addr = CService(); } }; #endif // BITCOIN_EVO_NETINFO_H diff --git a/src/rpc/evo.cpp b/src/rpc/evo.cpp index a9b558cdeeb5..83a25e13fd2d 100644 --- a/src/rpc/evo.cpp +++ b/src/rpc/evo.cpp @@ -684,7 +684,7 @@ static UniValue protx_register_common_wrapper(const JSONRPCRequest& request, if (!request.params[paramIdx].get_str().empty()) { if (auto addr = Lookup(request.params[paramIdx].get_str(), Params().GetDefaultPort(), false); addr.has_value()) { - ptx.netInfo.m_addr = addr.value(); + CHECK_NONFATAL(ptx.netInfo.AddEntry(addr.value()) == NetInfoStatus::Success); } else { throw std::runtime_error(strprintf("invalid network address %s", request.params[paramIdx].get_str())); } @@ -979,7 +979,7 @@ static UniValue protx_update_service_common_wrapper(const JSONRPCRequest& reques ptx.nVersion = dmn->pdmnState->nVersion; if (auto addr = Lookup(request.params[1].get_str().c_str(), Params().GetDefaultPort(), false); addr.has_value()) { - ptx.netInfo.m_addr = addr.value(); + CHECK_NONFATAL(ptx.netInfo.AddEntry(addr.value()) == NetInfoStatus::Success); } else { throw std::runtime_error(strprintf("invalid network address %s", request.params[1].get_str())); } diff --git a/src/test/block_reward_reallocation_tests.cpp b/src/test/block_reward_reallocation_tests.cpp index 0bf20a703e08..59f064a35a5a 100644 --- a/src/test/block_reward_reallocation_tests.cpp +++ b/src/test/block_reward_reallocation_tests.cpp @@ -117,7 +117,7 @@ static CMutableTransaction CreateProRegTx(const CChain& active_chain, const CTxM CProRegTx proTx; proTx.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); proTx.collateralOutpoint.n = 0; - proTx.netInfo.m_addr = LookupNumeric("1.1.1.1", port); + BOOST_CHECK_EQUAL(proTx.netInfo.AddEntry(LookupNumeric("1.1.1.1", port)), NetInfoStatus::Success); proTx.keyIDOwner = ownerKeyRet.GetPubKey().GetID(); proTx.pubKeyOperator.Set(operatorKeyRet.GetPublicKey(), bls::bls_legacy_scheme.load()); proTx.keyIDVoting = ownerKeyRet.GetPubKey().GetID(); diff --git a/src/test/evo_deterministicmns_tests.cpp b/src/test/evo_deterministicmns_tests.cpp index aa5bf74b4db8..ead787c57990 100644 --- a/src/test/evo_deterministicmns_tests.cpp +++ b/src/test/evo_deterministicmns_tests.cpp @@ -106,7 +106,7 @@ static CMutableTransaction CreateProRegTx(const CChain& active_chain, const CTxM CProRegTx proTx; proTx.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); proTx.collateralOutpoint.n = 0; - proTx.netInfo.m_addr = LookupNumeric("1.1.1.1", port); + BOOST_CHECK_EQUAL(proTx.netInfo.AddEntry(LookupNumeric("1.1.1.1", port)), NetInfoStatus::Success); proTx.keyIDOwner = ownerKeyRet.GetPubKey().GetID(); proTx.pubKeyOperator.Set(operatorKeyRet.GetPublicKey(), bls::bls_legacy_scheme.load()); proTx.keyIDVoting = ownerKeyRet.GetPubKey().GetID(); @@ -128,7 +128,7 @@ static CMutableTransaction CreateProUpServTx(const CChain& active_chain, const C CProUpServTx proTx; proTx.nVersion = CProUpServTx::GetMaxVersion(!bls::bls_legacy_scheme); proTx.proTxHash = proTxHash; - proTx.netInfo.m_addr = LookupNumeric("1.1.1.1", port); + BOOST_CHECK_EQUAL(proTx.netInfo.AddEntry(LookupNumeric("1.1.1.1", port)), NetInfoStatus::Success); proTx.scriptOperatorPayout = scriptOperatorPayout; CMutableTransaction tx; @@ -634,7 +634,7 @@ void FuncTestMempoolReorg(TestChainSetup& setup) CProRegTx payload; payload.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); - payload.netInfo.m_addr = LookupNumeric("1.1.1.1", 1); + BOOST_CHECK_EQUAL(payload.netInfo.AddEntry(LookupNumeric("1.1.1.1", 1)), NetInfoStatus::Success); payload.keyIDOwner = ownerKey.GetPubKey().GetID(); payload.pubKeyOperator.Set(operatorKey.GetPublicKey(), bls::bls_legacy_scheme.load()); payload.keyIDVoting = ownerKey.GetPubKey().GetID(); @@ -708,7 +708,7 @@ void FuncTestMempoolDualProregtx(TestChainSetup& setup) auto scriptPayout = GetScriptForDestination(PKHash(payoutKey.GetPubKey())); CProRegTx payload; - payload.netInfo.m_addr = LookupNumeric("1.1.1.1", 2); + BOOST_CHECK_EQUAL(payload.netInfo.AddEntry(LookupNumeric("1.1.1.1", 2)), NetInfoStatus::Success); payload.keyIDOwner = ownerKey.GetPubKey().GetID(); payload.pubKeyOperator.Set(operatorKey.GetPublicKey(), bls::bls_legacy_scheme.load()); payload.keyIDVoting = ownerKey.GetPubKey().GetID(); @@ -776,7 +776,7 @@ void FuncVerifyDB(TestChainSetup& setup) CProRegTx payload; payload.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); - payload.netInfo.m_addr = LookupNumeric("1.1.1.1", 1); + BOOST_CHECK_EQUAL(payload.netInfo.AddEntry(LookupNumeric("1.1.1.1", 1)), NetInfoStatus::Success); payload.keyIDOwner = ownerKey.GetPubKey().GetID(); payload.pubKeyOperator.Set(operatorKey.GetPublicKey(), bls::bls_legacy_scheme.load()); payload.keyIDVoting = ownerKey.GetPubKey().GetID(); diff --git a/src/test/evo_simplifiedmns_tests.cpp b/src/test/evo_simplifiedmns_tests.cpp index e91db1a31279..b14b475ccd1e 100644 --- a/src/test/evo_simplifiedmns_tests.cpp +++ b/src/test/evo_simplifiedmns_tests.cpp @@ -24,7 +24,7 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots) std::string ip = strprintf("%d.%d.%d.%d", 0, 0, 0, i); if (auto service = Lookup(ip, i, false); service.has_value()) { - smle.netInfo.m_addr = service.value(); + BOOST_CHECK_EQUAL(smle.netInfo.AddEntry(service.value()), NetInfoStatus::Success); } else { BOOST_REQUIRE(false); } From bac4a275426a4f9b2e839ff0c171c7e78b2feaee Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Wed, 7 May 2025 10:14:17 +0000 Subject: [PATCH 05/10] refactor: move address lookup to `MnNetInfo::AddEntry()` --- src/Makefile.test.include | 1 + src/evo/netinfo.cpp | 15 ++++++-- src/evo/netinfo.h | 14 ++++++- src/rpc/evo.cpp | 12 ++---- src/test/block_reward_reallocation_tests.cpp | 2 +- src/test/evo_deterministicmns_tests.cpp | 10 ++--- src/test/evo_netinfo_tests.cpp | 40 ++++++++++++++++++++ src/test/evo_simplifiedmns_tests.cpp | 7 +--- 8 files changed, 77 insertions(+), 24 deletions(-) create mode 100644 src/test/evo_netinfo_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 0791df6d2257..57765a51c155 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -113,6 +113,7 @@ BITCOIN_TESTS =\ test/evo_deterministicmns_tests.cpp \ test/evo_islock_tests.cpp \ test/evo_mnhf_tests.cpp \ + test/evo_netinfo_tests.cpp \ test/evo_simplifiedmns_tests.cpp \ test/evo_trivialvalidation.cpp \ test/evo_utils_tests.cpp \ diff --git a/src/evo/netinfo.cpp b/src/evo/netinfo.cpp index ee74719fba78..c3b91e135daa 100644 --- a/src/evo/netinfo.cpp +++ b/src/evo/netinfo.cpp @@ -4,8 +4,17 @@ #include -NetInfoStatus MnNetInfo::AddEntry(const CService& service) +#include +#include +#include + +NetInfoStatus MnNetInfo::AddEntry(const std::string& input) { - m_addr = service; - return NetInfoStatus::Success; + if (auto service = Lookup(input, /*portDefault=*/Params().GetDefaultPort(), /*fAllowLookup=*/false); + service.has_value()) { + m_addr = service.value(); + ASSERT_IF_DEBUG(m_addr != CService()); + return NetInfoStatus::Success; + } + return NetInfoStatus::BadInput; } diff --git a/src/evo/netinfo.h b/src/evo/netinfo.h index 5e02d0268a41..8f441896cd26 100644 --- a/src/evo/netinfo.h +++ b/src/evo/netinfo.h @@ -11,9 +11,21 @@ class CService; enum class NetInfoStatus : uint8_t { + BadInput, Success }; +constexpr std::string_view NISToString(const NetInfoStatus code) +{ + switch (code) { + case NetInfoStatus::BadInput: + return "invalid address"; + case NetInfoStatus::Success: + return "success"; + } // no default case, so the compiler can warn about missing cases + assert(false); +} + class MnNetInfo { private: @@ -31,7 +43,7 @@ class MnNetInfo READWRITE(obj.m_addr); } - NetInfoStatus AddEntry(const CService& service); + NetInfoStatus AddEntry(const std::string& service); const CService& GetPrimary() const { return m_addr; } bool IsEmpty() const { return *this == MnNetInfo(); } diff --git a/src/rpc/evo.cpp b/src/rpc/evo.cpp index 83a25e13fd2d..4d76a6f6c5b2 100644 --- a/src/rpc/evo.cpp +++ b/src/rpc/evo.cpp @@ -683,10 +683,8 @@ static UniValue protx_register_common_wrapper(const JSONRPCRequest& request, } if (!request.params[paramIdx].get_str().empty()) { - if (auto addr = Lookup(request.params[paramIdx].get_str(), Params().GetDefaultPort(), false); addr.has_value()) { - CHECK_NONFATAL(ptx.netInfo.AddEntry(addr.value()) == NetInfoStatus::Success); - } else { - throw std::runtime_error(strprintf("invalid network address %s", request.params[paramIdx].get_str())); + if (auto entryRet = ptx.netInfo.AddEntry(request.params[paramIdx].get_str()); entryRet != NetInfoStatus::Success) { + throw std::runtime_error(strprintf("%s (%s)", NISToString(entryRet), request.params[paramIdx].get_str())); } } @@ -978,10 +976,8 @@ static UniValue protx_update_service_common_wrapper(const JSONRPCRequest& reques ptx.nVersion = dmn->pdmnState->nVersion; - if (auto addr = Lookup(request.params[1].get_str().c_str(), Params().GetDefaultPort(), false); addr.has_value()) { - CHECK_NONFATAL(ptx.netInfo.AddEntry(addr.value()) == NetInfoStatus::Success); - } else { - throw std::runtime_error(strprintf("invalid network address %s", request.params[1].get_str())); + if (auto entryRet = ptx.netInfo.AddEntry(request.params[1].get_str()); entryRet != NetInfoStatus::Success) { + throw std::runtime_error(strprintf("%s (%s)", NISToString(entryRet), request.params[1].get_str())); } CBLSSecretKey keyOperator = ParseBLSSecretKey(request.params[2].get_str(), "operatorKey"); diff --git a/src/test/block_reward_reallocation_tests.cpp b/src/test/block_reward_reallocation_tests.cpp index 59f064a35a5a..50a1ecd477f7 100644 --- a/src/test/block_reward_reallocation_tests.cpp +++ b/src/test/block_reward_reallocation_tests.cpp @@ -117,7 +117,7 @@ static CMutableTransaction CreateProRegTx(const CChain& active_chain, const CTxM CProRegTx proTx; proTx.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); proTx.collateralOutpoint.n = 0; - BOOST_CHECK_EQUAL(proTx.netInfo.AddEntry(LookupNumeric("1.1.1.1", port)), NetInfoStatus::Success); + BOOST_CHECK_EQUAL(proTx.netInfo.AddEntry(strprintf("1.1.1.1:%d", port)), NetInfoStatus::Success); proTx.keyIDOwner = ownerKeyRet.GetPubKey().GetID(); proTx.pubKeyOperator.Set(operatorKeyRet.GetPublicKey(), bls::bls_legacy_scheme.load()); proTx.keyIDVoting = ownerKeyRet.GetPubKey().GetID(); diff --git a/src/test/evo_deterministicmns_tests.cpp b/src/test/evo_deterministicmns_tests.cpp index ead787c57990..30c2cb8b656c 100644 --- a/src/test/evo_deterministicmns_tests.cpp +++ b/src/test/evo_deterministicmns_tests.cpp @@ -106,7 +106,7 @@ static CMutableTransaction CreateProRegTx(const CChain& active_chain, const CTxM CProRegTx proTx; proTx.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); proTx.collateralOutpoint.n = 0; - BOOST_CHECK_EQUAL(proTx.netInfo.AddEntry(LookupNumeric("1.1.1.1", port)), NetInfoStatus::Success); + BOOST_CHECK_EQUAL(proTx.netInfo.AddEntry(strprintf("1.1.1.1:%d", port)), NetInfoStatus::Success); proTx.keyIDOwner = ownerKeyRet.GetPubKey().GetID(); proTx.pubKeyOperator.Set(operatorKeyRet.GetPublicKey(), bls::bls_legacy_scheme.load()); proTx.keyIDVoting = ownerKeyRet.GetPubKey().GetID(); @@ -128,7 +128,7 @@ static CMutableTransaction CreateProUpServTx(const CChain& active_chain, const C CProUpServTx proTx; proTx.nVersion = CProUpServTx::GetMaxVersion(!bls::bls_legacy_scheme); proTx.proTxHash = proTxHash; - BOOST_CHECK_EQUAL(proTx.netInfo.AddEntry(LookupNumeric("1.1.1.1", port)), NetInfoStatus::Success); + BOOST_CHECK_EQUAL(proTx.netInfo.AddEntry(strprintf("1.1.1.1:%d", port)), NetInfoStatus::Success); proTx.scriptOperatorPayout = scriptOperatorPayout; CMutableTransaction tx; @@ -634,7 +634,7 @@ void FuncTestMempoolReorg(TestChainSetup& setup) CProRegTx payload; payload.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); - BOOST_CHECK_EQUAL(payload.netInfo.AddEntry(LookupNumeric("1.1.1.1", 1)), NetInfoStatus::Success); + BOOST_CHECK_EQUAL(payload.netInfo.AddEntry("1.1.1.1:1"), NetInfoStatus::Success); payload.keyIDOwner = ownerKey.GetPubKey().GetID(); payload.pubKeyOperator.Set(operatorKey.GetPublicKey(), bls::bls_legacy_scheme.load()); payload.keyIDVoting = ownerKey.GetPubKey().GetID(); @@ -708,7 +708,7 @@ void FuncTestMempoolDualProregtx(TestChainSetup& setup) auto scriptPayout = GetScriptForDestination(PKHash(payoutKey.GetPubKey())); CProRegTx payload; - BOOST_CHECK_EQUAL(payload.netInfo.AddEntry(LookupNumeric("1.1.1.1", 2)), NetInfoStatus::Success); + BOOST_CHECK_EQUAL(payload.netInfo.AddEntry("1.1.1.1:2"), NetInfoStatus::Success); payload.keyIDOwner = ownerKey.GetPubKey().GetID(); payload.pubKeyOperator.Set(operatorKey.GetPublicKey(), bls::bls_legacy_scheme.load()); payload.keyIDVoting = ownerKey.GetPubKey().GetID(); @@ -776,7 +776,7 @@ void FuncVerifyDB(TestChainSetup& setup) CProRegTx payload; payload.nVersion = CProRegTx::GetMaxVersion(!bls::bls_legacy_scheme); - BOOST_CHECK_EQUAL(payload.netInfo.AddEntry(LookupNumeric("1.1.1.1", 1)), NetInfoStatus::Success); + BOOST_CHECK_EQUAL(payload.netInfo.AddEntry("1.1.1.1:1"), NetInfoStatus::Success); payload.keyIDOwner = ownerKey.GetPubKey().GetID(); payload.pubKeyOperator.Set(operatorKey.GetPublicKey(), bls::bls_legacy_scheme.load()); payload.keyIDVoting = ownerKey.GetPubKey().GetID(); diff --git a/src/test/evo_netinfo_tests.cpp b/src/test/evo_netinfo_tests.cpp new file mode 100644 index 000000000000..59e78e4d9a63 --- /dev/null +++ b/src/test/evo_netinfo_tests.cpp @@ -0,0 +1,40 @@ +// Copyright (c) 2025 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include + +#include + +const std::vector> vals{ + // Address and port specified + {"1.1.1.1:8888", NetInfoStatus::Success}, + // Address specified, port should default to default P2P core + {"1.1.1.1", NetInfoStatus::Success}, + // Port greater than uint16_t max + {"1.1.1.1:99999", NetInfoStatus::BadInput}, + // Domains are not allowed + {"example.com:8888", NetInfoStatus::BadInput}, + // Incorrect IPv4 address + {"1.1.1.256:8888", NetInfoStatus::BadInput}, + // Missing address + {":8888", NetInfoStatus::BadInput}, +}; + +BOOST_FIXTURE_TEST_SUITE(evo_netinfo_tests, RegTestingSetup) + +BOOST_AUTO_TEST_CASE(mnnetinfo_rules) +{ + // Validate AddEntry() rules enforcement + for (const auto& [input, expected_ret] : vals) { + MnNetInfo netInfo; + BOOST_CHECK_EQUAL(netInfo.AddEntry(input), expected_ret); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/evo_simplifiedmns_tests.cpp b/src/test/evo_simplifiedmns_tests.cpp index b14b475ccd1e..db7e3ec12db7 100644 --- a/src/test/evo_simplifiedmns_tests.cpp +++ b/src/test/evo_simplifiedmns_tests.cpp @@ -22,12 +22,7 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots) smle.proRegTxHash.SetHex(strprintf("%064x", i)); smle.confirmedHash.SetHex(strprintf("%064x", i)); - std::string ip = strprintf("%d.%d.%d.%d", 0, 0, 0, i); - if (auto service = Lookup(ip, i, false); service.has_value()) { - BOOST_CHECK_EQUAL(smle.netInfo.AddEntry(service.value()), NetInfoStatus::Success); - } else { - BOOST_REQUIRE(false); - } + BOOST_CHECK_EQUAL(smle.netInfo.AddEntry(strprintf("%d.%d.%d.%d:%d", 0, 0, 0, i, i)), NetInfoStatus::Success); std::vector vecBytes{static_cast(i)}; vecBytes.resize(CBLSSecretKey::SerSize); From 03ec604b2565398d1684c31198148316828acd56 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Mon, 3 Feb 2025 14:10:38 +0000 Subject: [PATCH 06/10] fix: correct `simplifiedmns_merkleroots` unit test In the next commit, we are going to enforce validation the moment we to set values. That will break this test because this test makes two errors. - It tries to use non-mainnet ports on BasicTestingSetup (which is mainnet), resolved by using RegTest. - It constructs the IP 0.0.0.0, which is not a routable address, resolved by counting from 1 onwards. --- src/test/evo_simplifiedmns_tests.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/evo_simplifiedmns_tests.cpp b/src/test/evo_simplifiedmns_tests.cpp index db7e3ec12db7..6c6856966d68 100644 --- a/src/test/evo_simplifiedmns_tests.cpp +++ b/src/test/evo_simplifiedmns_tests.cpp @@ -10,14 +10,14 @@ #include -BOOST_FIXTURE_TEST_SUITE(evo_simplifiedmns_tests, BasicTestingSetup) +BOOST_FIXTURE_TEST_SUITE(evo_simplifiedmns_tests, RegTestingSetup) BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots) { //TODO: Provide raw data for basic scheme as well bls::bls_legacy_scheme.store(true); std::vector entries; - for (size_t i = 0; i < 15; i++) { + for (size_t i = 1; i < 16; i++) { CSimplifiedMNListEntry smle; smle.proRegTxHash.SetHex(strprintf("%064x", i)); smle.confirmedHash.SetHex(strprintf("%064x", i)); @@ -35,7 +35,6 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots) } std::vector expectedHashes = { - "373b549f6380d8f7b04d7b04d7c58a749c5cbe3bf41536785ba819879c4870f1", "3a1010e28226558560e5296bcee6bf0b9b963b73a1514f5aa2885e270f6b90c1", "85d3d93b28689128daf3a41d706ae5002f447b9b6372776f0ca9d53b31146884", "8930eee6bd2e7971a7090edfb79f74c00a12280e59adfc2cc99d406a01e368f9", @@ -50,6 +49,7 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots) "cbc25ca965d0fa69a1fdc1d796b8ee2726a0e2137414e92fb9541630e3189901", "ac9934c4049ae952d41fb38e7e9659a558a5ce748bdb7fb613741598d1b16a27", "a61177eb14450bb8c56e5f0547035e0f3a70fe46f36901351cc568b2e48e29d0", + "67798d40a2196f446114c68d86445fe088750515a96eb65392c6bcfac8f3be9b" }; std::vector calculatedHashes; @@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots) CSimplifiedMNList sml(entries); - std::string expectedMerkleRoot = "b2303aca677ae2091c882e44b58f57869fa88a6db1f4e1a5d71975e5387fa195"; + std::string expectedMerkleRoot = "0bae2176078cf42fa3e1fda761d4255d1c1c54777c6a793d0ab2b07c85ed4022"; std::string calculatedMerkleRoot = sml.CalcMerkleRoot(nullptr).ToString(); //printf("merkleRoot=\"%s\",\n", calculatedMerkleRoot.c_str()); From 2e9bde0519b242d1d7aaf49344a357b90121689e Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Thu, 8 May 2025 01:00:50 +0000 Subject: [PATCH 07/10] refactor: move service validation to `MnNetInfo`, run during setting --- src/evo/deterministicmns.cpp | 32 +++++++--------------- src/evo/netinfo.cpp | 49 +++++++++++++++++++++++++++++++--- src/evo/netinfo.h | 7 +++++ src/test/evo_netinfo_tests.cpp | 6 +++++ 4 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index a81f8b591c3b..96f735645b2d 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -1180,29 +1180,15 @@ void CDeterministicMNManager::CleanupCache(int nHeight) template static bool CheckService(const ProTx& proTx, TxValidationState& state) { - const auto addr{proTx.netInfo.GetPrimary()}; - if (!addr.IsValid()) { - return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr"); - } - if (Params().RequireRoutableExternalIP() && !addr.IsRoutable()) { - return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr"); - } - - // TODO: use real args here - static int mainnetDefaultPort = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN)->GetDefaultPort(); - if (Params().NetworkIDString() == CBaseChainParams::MAIN) { - if (addr.GetPort() != mainnetDefaultPort) { - return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr-port"); - } - } else if (addr.GetPort() == mainnetDefaultPort) { - return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr-port"); - } - - if (!addr.IsIPv4()) { - return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr"); - } - - return true; + switch (proTx.netInfo.Validate()) { + case NetInfoStatus::BadInput: + return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-netinfo"); + case NetInfoStatus::BadPort: + return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-netinfo-port"); + case NetInfoStatus::Success: + return true; + } // no default case, so the compiler can warn about missing cases + assert(false); } template diff --git a/src/evo/netinfo.cpp b/src/evo/netinfo.cpp index c3b91e135daa..9f4641e846e0 100644 --- a/src/evo/netinfo.cpp +++ b/src/evo/netinfo.cpp @@ -7,14 +7,57 @@ #include #include #include +#include +#include + +namespace { +static std::unique_ptr g_main_params{nullptr}; +static std::once_flag g_main_params_flag; + +bool IsNodeOnMainnet() { return Params().NetworkIDString() == CBaseChainParams::MAIN; } +const CChainParams& MainParams() +{ + // TODO: use real args here + std::call_once(g_main_params_flag, + [&]() { g_main_params = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN); }); + return *Assert(g_main_params); +} +} // anonymous namespace + +NetInfoStatus MnNetInfo::ValidateService(const CService& service) +{ + if (!service.IsValid()) { + return NetInfoStatus::BadInput; + } + if (!service.IsIPv4()) { + return NetInfoStatus::BadInput; + } + if (Params().RequireRoutableExternalIP() && !service.IsRoutable()) { + return NetInfoStatus::BadInput; + } + + const auto default_port_main = MainParams().GetDefaultPort(); + if (IsNodeOnMainnet() && service.GetPort() != default_port_main) { + // Must use mainnet port on mainnet + return NetInfoStatus::BadPort; + } else if (service.GetPort() == default_port_main) { + // Using mainnet port prohibited outside of mainnet + return NetInfoStatus::BadPort; + } + + return NetInfoStatus::Success; +} NetInfoStatus MnNetInfo::AddEntry(const std::string& input) { if (auto service = Lookup(input, /*portDefault=*/Params().GetDefaultPort(), /*fAllowLookup=*/false); service.has_value()) { - m_addr = service.value(); - ASSERT_IF_DEBUG(m_addr != CService()); - return NetInfoStatus::Success; + const auto ret = ValidateService(service.value()); + if (ret == NetInfoStatus::Success) { + m_addr = service.value(); + ASSERT_IF_DEBUG(m_addr != CService()); + } + return ret; } return NetInfoStatus::BadInput; } diff --git a/src/evo/netinfo.h b/src/evo/netinfo.h index 8f441896cd26..48980af7fa2d 100644 --- a/src/evo/netinfo.h +++ b/src/evo/netinfo.h @@ -12,6 +12,7 @@ class CService; enum class NetInfoStatus : uint8_t { BadInput, + BadPort, Success }; @@ -20,6 +21,8 @@ constexpr std::string_view NISToString(const NetInfoStatus code) switch (code) { case NetInfoStatus::BadInput: return "invalid address"; + case NetInfoStatus::BadPort: + return "invalid port"; case NetInfoStatus::Success: return "success"; } // no default case, so the compiler can warn about missing cases @@ -31,6 +34,9 @@ class MnNetInfo private: CService m_addr{}; +private: + static NetInfoStatus ValidateService(const CService& service); + public: MnNetInfo() = default; ~MnNetInfo() = default; @@ -47,6 +53,7 @@ class MnNetInfo const CService& GetPrimary() const { return m_addr; } bool IsEmpty() const { return *this == MnNetInfo(); } + NetInfoStatus Validate() const { return ValidateService(m_addr); } void Clear() { m_addr = CService(); } }; diff --git a/src/test/evo_netinfo_tests.cpp b/src/test/evo_netinfo_tests.cpp index 59e78e4d9a63..5867a36f9e92 100644 --- a/src/test/evo_netinfo_tests.cpp +++ b/src/test/evo_netinfo_tests.cpp @@ -16,8 +16,14 @@ const std::vector Date: Sat, 3 May 2025 16:08:33 +0000 Subject: [PATCH 08/10] refactor: implement `MnNetInfo::ToString()` for printing internal state --- src/evo/dmnstate.cpp | 8 ++++---- src/evo/netinfo.cpp | 8 ++++++++ src/evo/netinfo.h | 1 + src/evo/providertx.cpp | 19 ++++++++++--------- src/evo/simplifiedmns.cpp | 10 +++++----- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/evo/dmnstate.cpp b/src/evo/dmnstate.cpp index 365336494562..df09e2d4611c 100644 --- a/src/evo/dmnstate.cpp +++ b/src/evo/dmnstate.cpp @@ -27,12 +27,12 @@ std::string CDeterministicMNState::ToString() const return strprintf("CDeterministicMNState(nVersion=%d, nRegisteredHeight=%d, nLastPaidHeight=%d, nPoSePenalty=%d, " "nPoSeRevivedHeight=%d, nPoSeBanHeight=%d, nRevocationReason=%d, " - "ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, addr=%s, payoutAddress=%s, " - "operatorPayoutAddress=%s)", + "ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, payoutAddress=%s, " + "operatorPayoutAddress=%s)\n" + " %s", nVersion, nRegisteredHeight, nLastPaidHeight, nPoSePenalty, nPoSeRevivedHeight, nPoSeBanHeight, nRevocationReason, EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), - EncodeDestination(PKHash(keyIDVoting)), netInfo.GetPrimary().ToStringAddrPort(), payoutAddress, - operatorPayoutAddress); + EncodeDestination(PKHash(keyIDVoting)), payoutAddress, operatorPayoutAddress, netInfo.ToString()); } UniValue CDeterministicMNState::ToJson(MnType nType) const diff --git a/src/evo/netinfo.cpp b/src/evo/netinfo.cpp index 9f4641e846e0..91e9f3eaf48e 100644 --- a/src/evo/netinfo.cpp +++ b/src/evo/netinfo.cpp @@ -61,3 +61,11 @@ NetInfoStatus MnNetInfo::AddEntry(const std::string& input) } return NetInfoStatus::BadInput; } + +std::string MnNetInfo::ToString() const +{ + // Extra padding to account for padding done by the calling function. + return strprintf("MnNetInfo()\n" + " CService(addr=%s, port=%u)\n", + m_addr.ToStringAddr(), m_addr.GetPort()); +} diff --git a/src/evo/netinfo.h b/src/evo/netinfo.h index 48980af7fa2d..2f7a2475c0f9 100644 --- a/src/evo/netinfo.h +++ b/src/evo/netinfo.h @@ -54,6 +54,7 @@ class MnNetInfo const CService& GetPrimary() const { return m_addr; } bool IsEmpty() const { return *this == MnNetInfo(); } NetInfoStatus Validate() const { return ValidateService(m_addr); } + std::string ToString() const; void Clear() { m_addr = CService(); } }; diff --git a/src/evo/providertx.cpp b/src/evo/providertx.cpp index 7b215c92121d..cb869fc2b88c 100644 --- a/src/evo/providertx.cpp +++ b/src/evo/providertx.cpp @@ -87,14 +87,14 @@ std::string CProRegTx::ToString() const payee = EncodeDestination(dest); } - return strprintf("CProRegTx(nVersion=%d, nType=%d, collateralOutpoint=%s, addr=%s, nOperatorReward=%f, " + return strprintf("CProRegTx(nVersion=%d, nType=%d, collateralOutpoint=%s, nOperatorReward=%f, " "ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, scriptPayout=%s, platformNodeID=%s, " - "platformP2PPort=%d, platformHTTPPort=%d)", - nVersion, ToUnderlying(nType), collateralOutpoint.ToStringShort(), - netInfo.GetPrimary().ToStringAddrPort(), (double)nOperatorReward / 100, + "platformP2PPort=%d, platformHTTPPort=%d)\n" + " %s", + nVersion, ToUnderlying(nType), collateralOutpoint.ToStringShort(), (double)nOperatorReward / 100, EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), payee, platformNodeID.ToString(), platformP2PPort, - platformHTTPPort); + platformHTTPPort, netInfo.ToString()); } bool CProUpServTx::IsTriviallyValid(bool is_basic_scheme_active, TxValidationState& state) const @@ -117,10 +117,11 @@ std::string CProUpServTx::ToString() const payee = EncodeDestination(dest); } - return strprintf("CProUpServTx(nVersion=%d, nType=%d, proTxHash=%s, addr=%s, operatorPayoutAddress=%s, " - "platformNodeID=%s, platformP2PPort=%d, platformHTTPPort=%d)", - nVersion, ToUnderlying(nType), proTxHash.ToString(), netInfo.GetPrimary().ToStringAddrPort(), - payee, platformNodeID.ToString(), platformP2PPort, platformHTTPPort); + return strprintf("CProUpServTx(nVersion=%d, nType=%d, proTxHash=%s, operatorPayoutAddress=%s, " + "platformNodeID=%s, platformP2PPort=%d, platformHTTPPort=%d)\n" + " %s", + nVersion, ToUnderlying(nType), proTxHash.ToString(), payee, platformNodeID.ToString(), + platformP2PPort, platformHTTPPort, netInfo.ToString()); } bool CProUpRegTx::IsTriviallyValid(bool is_basic_scheme_active, TxValidationState& state) const diff --git a/src/evo/simplifiedmns.cpp b/src/evo/simplifiedmns.cpp index b10db766417e..979c8e175bc7 100644 --- a/src/evo/simplifiedmns.cpp +++ b/src/evo/simplifiedmns.cpp @@ -62,13 +62,13 @@ std::string CSimplifiedMNListEntry::ToString() const operatorPayoutAddress = EncodeDestination(dest); } - return strprintf("CSimplifiedMNListEntry(nVersion=%d, nType=%d, proRegTxHash=%s, confirmedHash=%s, addr=%s, " + return strprintf("CSimplifiedMNListEntry(nVersion=%d, nType=%d, proRegTxHash=%s, confirmedHash=%s, " "pubKeyOperator=%s, votingAddress=%s, isValid=%d, payoutAddress=%s, operatorPayoutAddress=%s, " - "platformHTTPPort=%d, platformNodeID=%s)", + "platformHTTPPort=%d, platformNodeID=%s)\n" + " %s", nVersion, ToUnderlying(nType), proRegTxHash.ToString(), confirmedHash.ToString(), - netInfo.GetPrimary().ToStringAddrPort(), pubKeyOperator.ToString(), - EncodeDestination(PKHash(keyIDVoting)), isValid, payoutAddress, operatorPayoutAddress, - platformHTTPPort, platformNodeID.ToString()); + pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), isValid, payoutAddress, + operatorPayoutAddress, platformHTTPPort, platformNodeID.ToString(), netInfo.ToString()); } UniValue CSimplifiedMNListEntry::ToJson(bool extended) const From bcb8a7d22bbf68a42d3544aff18de7178f951d82 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Wed, 7 May 2025 10:15:48 +0000 Subject: [PATCH 09/10] refactor: impl `GetEntries()`, adapt to support multiple addresses GetEntries does nothing except wrap the one singular entry we have into a set. Right now this functionally changes nothing but this lets us change code to adapt to the possibility that a MnNetInfo-like object could store more than one value at some point down the line. --- src/evo/netinfo.cpp | 12 ++++++++ src/evo/netinfo.h | 3 ++ src/rpc/masternode.cpp | 16 ++++++++--- src/test/evo_netinfo_tests.cpp | 10 +++++++ src/txmempool.cpp | 52 ++++++++++++++++++++++++---------- 5 files changed, 74 insertions(+), 19 deletions(-) diff --git a/src/evo/netinfo.cpp b/src/evo/netinfo.cpp index 91e9f3eaf48e..ed5fc19053db 100644 --- a/src/evo/netinfo.cpp +++ b/src/evo/netinfo.cpp @@ -62,6 +62,18 @@ NetInfoStatus MnNetInfo::AddEntry(const std::string& input) return NetInfoStatus::BadInput; } +CServiceList MnNetInfo::GetEntries() const +{ + CServiceList ret; + if (!IsEmpty()) { + ASSERT_IF_DEBUG(m_addr != CService()); + ret.push_back(m_addr); + } + // If MnNetInfo is empty, we probably don't expect any entries to show up, so + // we return a blank set instead. + return ret; +} + std::string MnNetInfo::ToString() const { // Extra padding to account for padding done by the calling function. diff --git a/src/evo/netinfo.h b/src/evo/netinfo.h index 2f7a2475c0f9..a264d76b8e0d 100644 --- a/src/evo/netinfo.h +++ b/src/evo/netinfo.h @@ -29,6 +29,8 @@ constexpr std::string_view NISToString(const NetInfoStatus code) assert(false); } +using CServiceList = std::vector>; + class MnNetInfo { private: @@ -50,6 +52,7 @@ class MnNetInfo } NetInfoStatus AddEntry(const std::string& service); + CServiceList GetEntries() const; const CService& GetPrimary() const { return m_addr; } bool IsEmpty() const { return *this == MnNetInfo(); } diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index ee17547da764..82bc5b0b7af6 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -565,8 +565,16 @@ static RPCHelpMan masternodelist_helper(bool is_composite) payeeStr = EncodeDestination(payeeDest); } + std::string strAddress{}; + if (strMode == "addr" || strMode == "full" || strMode == "info" || strMode == "json" || strMode == "recent" || + strMode == "evo") { + for (const CService& entry : dmn.pdmnState->netInfo.GetEntries()) { + strAddress += entry.ToStringAddrPort() + " "; + } + if (!strAddress.empty()) strAddress.pop_back(); // Remove trailing space + } + if (strMode == "addr") { - std::string strAddress = dmn.pdmnState->netInfo.GetPrimary().ToStringAddrPort(); if (!strFilter.empty() && strAddress.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; obj.pushKV(strOutpoint, strAddress); @@ -577,7 +585,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite) payeeStr, PadString(ToString(dmnToLastPaidTime(dmn)), 10), PadString(ToString(dmn.pdmnState->nLastPaidHeight), 6), - dmn.pdmnState->netInfo.GetPrimary().ToStringAddrPort()); + strAddress); if (!strFilter.empty() && strFull.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; obj.pushKV(strOutpoint, strFull); @@ -586,14 +594,14 @@ static RPCHelpMan masternodelist_helper(bool is_composite) PadString(dmnToStatus(dmn), 18), dmn.pdmnState->nPoSePenalty, payeeStr, - dmn.pdmnState->netInfo.GetPrimary().ToStringAddrPort()); + strAddress); if (!strFilter.empty() && strInfo.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; obj.pushKV(strOutpoint, strInfo); } else if (strMode == "json" || strMode == "recent" || strMode == "evo") { std::string strInfo = strprintf("%s %s %s %s %d %d %d %s %s %s %s", dmn.proTxHash.ToString(), - dmn.pdmnState->netInfo.GetPrimary().ToStringAddrPort(), + strAddress, payeeStr, dmnToStatus(dmn), dmn.pdmnState->nPoSePenalty, diff --git a/src/test/evo_netinfo_tests.cpp b/src/test/evo_netinfo_tests.cpp index 5867a36f9e92..a7f376ff24c0 100644 --- a/src/test/evo_netinfo_tests.cpp +++ b/src/test/evo_netinfo_tests.cpp @@ -34,12 +34,22 @@ const std::vector(tx)); mapProTxRefs.emplace(proTx.proTxHash, tx_hash); - mapProTxAddresses.emplace(proTx.netInfo.GetPrimary(), tx_hash); + for (const CService& entry : proTx.netInfo.GetEntries()) { + mapProTxAddresses.emplace(entry, tx_hash); + } } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { auto proTx = *Assert(GetTxPayload(tx)); mapProTxRefs.emplace(proTx.proTxHash, tx_hash); @@ -791,7 +795,9 @@ void CTxMemPool::removeUncheckedProTx(const CTransaction& tx) if (!proTx.collateralOutpoint.IsNull()) { eraseProTxRef(tx_hash, proTx.collateralOutpoint.hash); } - mapProTxAddresses.erase(proTx.netInfo.GetPrimary()); + for (const CService& entry : proTx.netInfo.GetEntries()) { + mapProTxAddresses.erase(entry); + } mapProTxPubKeyIDs.erase(proTx.keyIDOwner); mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash()); mapProTxCollaterals.erase(proTx.collateralOutpoint); @@ -799,7 +805,9 @@ void CTxMemPool::removeUncheckedProTx(const CTransaction& tx) } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) { auto proTx = *Assert(GetTxPayload(tx)); eraseProTxRef(proTx.proTxHash, tx_hash); - mapProTxAddresses.erase(proTx.netInfo.GetPrimary()); + for (const CService& entry : proTx.netInfo.GetEntries()) { + mapProTxAddresses.erase(entry); + } } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { auto proTx = *Assert(GetTxPayload(tx)); eraseProTxRef(proTx.proTxHash, tx_hash); @@ -1026,10 +1034,12 @@ void CTxMemPool::removeProTxConflicts(const CTransaction &tx) } auto& proTx = *opt_proTx; - if (mapProTxAddresses.count(proTx.netInfo.GetPrimary())) { - uint256 conflictHash = mapProTxAddresses[proTx.netInfo.GetPrimary()]; - if (conflictHash != tx_hash && mapTx.count(conflictHash)) { - removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT); + for (const CService& entry : proTx.netInfo.GetEntries()) { + if (mapProTxAddresses.count(entry)) { + uint256 conflictHash = mapProTxAddresses[entry]; + if (conflictHash != tx_hash && mapTx.count(conflictHash)) { + removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT); + } } } removeProTxPubKeyConflicts(tx, proTx.keyIDOwner); @@ -1046,10 +1056,12 @@ void CTxMemPool::removeProTxConflicts(const CTransaction &tx) return; } - if (mapProTxAddresses.count(opt_proTx->netInfo.GetPrimary())) { - uint256 conflictHash = mapProTxAddresses[opt_proTx->netInfo.GetPrimary()]; - if (conflictHash != tx_hash && mapTx.count(conflictHash)) { - removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT); + for (const CService& entry : opt_proTx->netInfo.GetEntries()) { + if (mapProTxAddresses.count(entry)) { + uint256 conflictHash = mapProTxAddresses[entry]; + if (conflictHash != tx_hash && mapTx.count(conflictHash)) { + removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT); + } } } } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { @@ -1382,8 +1394,14 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { return true; // i.e. can't decode payload == conflict } auto& proTx = *opt_proTx; - if (mapProTxAddresses.count(proTx.netInfo.GetPrimary()) || mapProTxPubKeyIDs.count(proTx.keyIDOwner) || mapProTxBlsPubKeyHashes.count(proTx.pubKeyOperator.GetHash())) + for (const CService& entry : proTx.netInfo.GetEntries()) { + if (mapProTxAddresses.count(entry)) { + return true; + } + } + if (mapProTxPubKeyIDs.count(proTx.keyIDOwner) || mapProTxBlsPubKeyHashes.count(proTx.pubKeyOperator.GetHash())) { return true; + } if (!proTx.collateralOutpoint.hash.IsNull()) { if (mapProTxCollaterals.count(proTx.collateralOutpoint)) { // there is another ProRegTx that refers to the same collateral @@ -1401,8 +1419,12 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx_hash.ToString()); return true; // i.e. can't decode payload == conflict } - auto it = mapProTxAddresses.find(opt_proTx->netInfo.GetPrimary()); - return it != mapProTxAddresses.end() && it->second != opt_proTx->proTxHash; + for (const CService& entry : opt_proTx->netInfo.GetEntries()) { + auto it = mapProTxAddresses.find(entry); + if (it != mapProTxAddresses.end() && it->second != opt_proTx->proTxHash) { + return true; + } + } } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { const auto opt_proTx = GetTxPayload(tx); if (!opt_proTx) { From 1d5267885de1e9c81eed38c4a5577ad8eb666bd5 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Wed, 7 May 2025 10:12:04 +0000 Subject: [PATCH 10/10] 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. --- src/evo/deterministicmns.cpp | 75 ++++++++++++++++++++++++------------ src/evo/deterministicmns.h | 7 +++- 2 files changed, 56 insertions(+), 26 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 96f735645b2d..ea789de75b59 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -470,11 +470,12 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTota throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate collateralOutpoint=%s", __func__, dmn->proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort()))); } - if (!dmn->pdmnState->netInfo.IsEmpty() && !AddUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { - mnUniquePropertyMap = mnUniquePropertyMapSaved; - throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s", __func__, - dmn->proTxHash.ToString(), - dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()))); + for (const CService& entry : dmn->pdmnState->netInfo.GetEntries()) { + if (!AddUniqueProperty(*dmn, entry)) { + mnUniquePropertyMap = mnUniquePropertyMapSaved; + throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s", __func__, + dmn->proTxHash.ToString(), entry.ToStringAddrPort()))); + } } if (!AddUniqueProperty(*dmn, dmn->pdmnState->keyIDOwner)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; @@ -512,11 +513,28 @@ void CDeterministicMNList::UpdateMN(const CDeterministicMN& oldDmn, const std::s // Using this temporary map as a checkpoint to roll back to in case of any issues. decltype(mnUniquePropertyMap) mnUniquePropertyMapSaved = mnUniquePropertyMap; - if (!UpdateUniqueProperty(*dmn, oldState->netInfo, pdmnState->netInfo)) { + const auto updateNetInfo = [&]() { + if (oldState->netInfo != pdmnState->netInfo) { + // We track each individual entry in netInfo as opposed to netInfo itself (preventing us from + // using UpdateUniqueProperty()), so we need to successfully purge all old entries and insert + // new entries to successfully update. + for (const CService& old_entry : oldState->netInfo.GetEntries()) { + if (!DeleteUniqueProperty(*dmn, old_entry)) { + return strprintf("internal error"); // This shouldn't be possible + } + } + for (const CService& new_entry : pdmnState->netInfo.GetEntries()) { + if (!AddUniqueProperty(*dmn, new_entry)) { + return strprintf("duplicate (%s)", new_entry.ToStringAddrPort()); + } + } + } + return strprintf(""); + }(); + if (!updateNetInfo.empty()) { mnUniquePropertyMap = mnUniquePropertyMapSaved; - throw(std::runtime_error(strprintf("%s: Can't update a masternode %s with a duplicate address=%s", __func__, - oldDmn.proTxHash.ToString(), - pdmnState->netInfo.GetPrimary().ToStringAddrPort()))); + throw(std::runtime_error(strprintf("%s: Can't update masternode %s with addresses, reason=%s", __func__, + oldDmn.proTxHash.ToString(), updateNetInfo))); } if (!UpdateUniqueProperty(*dmn, oldState->keyIDOwner, pdmnState->keyIDOwner)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; @@ -573,10 +591,12 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash) throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a collateralOutpoint=%s", __func__, proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort()))); } - if (!dmn->pdmnState->netInfo.IsEmpty() && !DeleteUniqueProperty(*dmn, dmn->pdmnState->netInfo)) { - mnUniquePropertyMap = mnUniquePropertyMapSaved; - throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a address=%s", __func__, - proTxHash.ToString(), dmn->pdmnState->netInfo.GetPrimary().ToStringAddrPort()))); + for (const CService& entry : dmn->pdmnState->netInfo.GetEntries()) { + if (!DeleteUniqueProperty(*dmn, entry)) { + mnUniquePropertyMap = mnUniquePropertyMapSaved; + throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with an address=%s", __func__, + proTxHash.ToString(), entry.ToStringAddrPort()))); + } } if (!DeleteUniqueProperty(*dmn, dmn->pdmnState->keyIDOwner)) { mnUniquePropertyMap = mnUniquePropertyMapSaved; @@ -791,8 +811,10 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no } } - if (newList.HasUniqueProperty(proTx.netInfo)) { - return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr"); + for (const CService& entry : proTx.netInfo.GetEntries()) { + if (newList.HasUniqueProperty(entry)) { + return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-netinfo-entry"); + } } if (newList.HasUniqueProperty(proTx.keyIDOwner) || newList.HasUniqueProperty(proTx.pubKeyOperator)) { return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-key"); @@ -820,9 +842,11 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload"); } - if (newList.HasUniqueProperty(opt_proTx->netInfo) && - newList.GetUniquePropertyMN(opt_proTx->netInfo)->proTxHash != opt_proTx->proTxHash) { - return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr"); + for (const CService& entry : opt_proTx->netInfo.GetEntries()) { + if (newList.HasUniqueProperty(entry) && + newList.GetUniquePropertyMN(entry)->proTxHash != opt_proTx->proTxHash) { + return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-netinfo-entry"); + } } auto dmn = newList.GetMN(opt_proTx->proTxHash); @@ -1349,9 +1373,11 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl: auto mnList = dmnman.GetListForBlock(pindexPrev); // only allow reusing of addresses when it's for the same collateral (which replaces the old MN) - if (mnList.HasUniqueProperty(opt_ptx->netInfo) && - mnList.GetUniquePropertyMN(opt_ptx->netInfo)->collateralOutpoint != collateralOutpoint) { - return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-addr"); + for (const CService& entry : opt_ptx->netInfo.GetEntries()) { + if (mnList.HasUniqueProperty(entry) && + mnList.GetUniquePropertyMN(entry)->collateralOutpoint != collateralOutpoint) { + return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-netinfo-entry"); + } } // 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 } // don't allow updating to addresses already used by other MNs - if (mnList.HasUniqueProperty(opt_ptx->netInfo) && - mnList.GetUniquePropertyMN(opt_ptx->netInfo)->proTxHash != opt_ptx->proTxHash) { - return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-addr"); + for (const CService& entry : opt_ptx->netInfo.GetEntries()) { + if (mnList.HasUniqueProperty(entry) && mnList.GetUniquePropertyMN(entry)->proTxHash != opt_ptx->proTxHash) { + return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-netinfo-entry"); + } } // don't allow updating to platformNodeIds already used by other EvoNodes diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index b7dadf6aca68..386d98a23063 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -394,8 +394,11 @@ class CDeterministicMNList template [[nodiscard]] uint256 GetUniquePropertyHash(const T& v) const { - static_assert(!std::is_same_v, CBLSPublicKey>, - "GetUniquePropertyHash cannot be templated against CBLSPublicKey"); +#define DMNL_NO_TEMPLATE(name) \ + static_assert(!std::is_same_v, name>, "GetUniquePropertyHash cannot be templated against " #name) + DMNL_NO_TEMPLATE(CBLSPublicKey); + DMNL_NO_TEMPLATE(MnNetInfo); +#undef DMNL_NO_TEMPLATE return ::SerializeHash(v); } template