Skip to content

Commit 8b5310a

Browse files
Merge #6666: feat: introduce basic extended addresses implementation, stop using platform{HTTP,P2P}Port
90713a2 doc: add release notes for base extended addresses and shims (Kittywhiskers Van Gogh) 5b1b168 rpc: don't report Platform-specific fields in CoinJoin RPCs (Kittywhiskers Van Gogh) e97a650 test: validate address reporting behavior for empty address ProRegTxes (Kittywhiskers Van Gogh) 5317eef test: validate post-fork shim behavior (Kittywhiskers Van Gogh) 8843fc2 test: activate v23 fork and test post-fork input validation rules (Kittywhiskers Van Gogh) fef8332 refactor(test): remove non-EvoNode paths from `rpc_netinfo`, cleanup (Kittywhiskers Van Gogh) 30500f7 refactor(test): deduplicate common input validation in `MasternodeInfo` (Kittywhiskers Van Gogh) 885e223 test: allow passing empty `coreP2PAddrs` to `MasternodeInfo` helpers (Kittywhiskers Van Gogh) b69ca87 rpc: allow `platform{P2P,HTTP}Port` to return port of first address (Kittywhiskers Van Gogh) 245a6ee rpc: implement special platform port shim for `CDeterministicMNStateDiff` (Kittywhiskers Van Gogh) 17d17af rpc: allow `addresses` to report data from legacy platform port fields (Kittywhiskers Van Gogh) 8efbad8 refactor(test): `coreP2PAddrs` > `addrs_core_p2p` (Kittywhiskers Van Gogh) f04ed99 refactor(test): `platform_{http,p2p}_port` > `addrs_platform_{https,p2p}` (Kittywhiskers Van Gogh) f59f9f5 refactor(rpc): `platform{HTTP,P2P}Port` > `platform{HTTPS,P2P}Addrs` (Kittywhiskers Van Gogh) d519eea rpc: allow multiple entries in `platform{HTTP,P2P}Port` (Kittywhiskers Van Gogh) 01ee293 rpc: make setting `platform{HTTP,P2P}Port` optional if using `netInfo` (Kittywhiskers Van Gogh) 1d36005 rpc: set `platform{HTTP,P2P}Port` with `netInfo`, allow addr:port str (Kittywhiskers Van Gogh) 7664ecf refactor: consolidate input processing in ProcessNetInfo*, update errs (Kittywhiskers Van Gogh) e155529 evo: stop using `platform{HTTP,P2P}Port` fields if using extended addrs (Kittywhiskers Van Gogh) bfbfe3c evo: allow storing platform P2P and HTTPS addresses in `ExtNetInfo` (Kittywhiskers Van Gogh) 53f993c evo: allow address entries to be differentiated by port (Kittywhiskers Van Gogh) 4ca6542 evo: introduce the ability to store multiple lists of addresses (Kittywhiskers Van Gogh) a35d9c6 evo: prohibit entries with duplicate addresses in `ExtNetInfo` (Kittywhiskers Van Gogh) 56b1bb6 evo: introduce versioning for `ExtNetInfo` (Kittywhiskers Van Gogh) e9cac47 evo: introduce barebones extended addresses (`ExtNetInfo`) impl (Kittywhiskers Van Gogh) ef2fb7b evo: drop `std::reference_wrapper` usage, make copies instead (Kittywhiskers Van Gogh) 50cdc84 fix: don't return invalid values with empty `MnNetInfo` (Kittywhiskers Van Gogh) Pull request description: ## Motivation Currently, we store an address and port pair for all masternodes and two port numbers for Evonodes. The first pair is used by Dash Core and the latter two port numbers are paired with the address from the first pair and are used by Dash Platform. This arrangement has allowed the network to grow and sustain its current operations but proves to be rigid as it imposes the constraint that all advertised activity (Core P2P, Platform P2P and the Platform HTTPS API) happen only on one network (IPv4), from the same public IP (as we can only register one address). This prevents specifying different networks (like IPv6), alternate addresses (e.g. on privacy-oriented networks), expanding to advertise other purposes or deferring resolution of the underlying address (e.g. specifying domain names). To allow for these use cases, the changes made to transaction, storage and state formats alongside changes made to RPC input and output fields are collectively referred to as "extended addresses". This pull request includes the following: * A basic extended addresses implementation that allows storing 4 addresses per purpose code, recognizing the following purpose codes, `CORE_P2P`, `PLATFORM_P2P` and `PLATFORM_HTTPS`. * Support for specifying (arrays of) addr:port pairs to `platformP2PAddrs` (formerly known as `platformP2PPort`) and `platformHTTPSAddrs` (formerly known as `platformHTTPPort`). * Compatibility code to allow * Reporting `platformP2PPort` and `platformHTTPPort` for extended address payloads even though they have been subsumed into `netInfo` * Reporting `platformP2PPort` and `platformHTTPPort` data from legacy address payloads through `addresses` even though they aren't stored in `netInfo` * Specifying only ports in `platformP2PAddrs` and `platformHTTPSAddrs` when using `protx register{,_evo}`, `protx register_fund{,_evo}` and `protx update_service{,_evo}` to create/update an extended addresses eligible masternode by reading the address of the first `coreP2PAddrs` entry and pairing it with the supplied port. This pull request **does not** include the the full set of validation rules applicable on extended addresses as they have been reserved for a subsequent pull request. This pull request's scope is to lay down the base implementation, its surrounding compatibility code and tests to ensure its sanity. ## Additional Information * Depends on #6674 * Depends on #6813 * The adoption of `std::reference_wrapper` (starting with [dash#6627](#6627)) has been reverted as while it there were performance considerations that led to its adoption, the risk of dangling references due to a race condition (e.g. iterating through `GetEntries()` while `Clear()` is called) are more pronounced for extended addresses. The underlying structures (`NetInfoEntry`, which will predominantly hold a `CService`) are not heavy enough to justify the usage of locking (i.e. mutexes). Making copies are deemed affordable enough for the safety that it provides. * ~~`CDeterministicMNStateDiff` is an append-only structure populated based on flags, which has made it a source of attention throughout work on extended addresses (see [dash#6636](#6636)). It is the reason `NetInfoSerWrapper` was introduced, as `nVersion` is placed _after_ `netInfo` ([source](https://github.com/dashpay/dash/blob/d4202b54b514e0f9f3736d9082c76a418e1bbbcb/src/evo/dmnstate.h#L199-L206)), which means, we cannot determine what format to use when deserializing based on the version of the format.~~ ~~To work around this, extended address payloads are prepended with the magic `0x23232323` ([source](https://github.com/dashpay/dash/blob/541d574050f40749080470deee5fadc051c07071/src/evo/netinfo.h#L374)) when serializing and deserialization will read the first four bytes to determine if the payload is extended or legacy.~~ No longer true after [dash#6813](#6813), thanks Udjin! * As we require a flattened list of all addresses associated with a masternode in order to check it against the mempool or unique properties map ([example](https://github.com/dashpay/dash/blob/d4202b54b514e0f9f3736d9082c76a418e1bbbcb/src/evo/deterministicmns.cpp#L435-L442)), it would be inefficient to regenerate that list every time `GetEntries()` is called. To get around that, we use a memory-only cache, `m_all_entries` is used. It is populated when deserialized or added to when new entries are successful. This proves to be sufficient as `ExtNetInfo` is an append-only structure (i.e. they can either be added to with `AddEntry()` or `Clear()`ed). * This cache is also used for addr:port duplicates checking (while purpose-specific lists are used for addr duplicates checking) * As `rpc_netinfo.py` is unlikely to use regular masternodes (as Platform-related fields can only be tested with Evonodes), non-Evonode code paths were removed and the following additional changes were made * Implementing the helper functions `reconnect_nodes()` and `set_active_state()`, the former to reconnect restarted nodes to their peers (which is not done automatically by the test framework) and the latter to restart the node to enable it in active masternode state (and/or optionally define extra arguments). * Fix a minor bug where `destroy_mn()` overwrote the ProTx hash of the destroyed masternode before checking for removal from the masternode list and logging it. ## Breaking Changes Refer to release notes. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ Top commit has no ACKs. Tree-SHA512: 25728319c1ca6d4a3c6c8a97e7dddcc87397e7c6dd181dd5796fd1f34de36481f9bfd53afca18ca90dce91a9dd0571c2c96cb1fb4970d14aecee185036c691cc
2 parents f30d340 + 90713a2 commit 8b5310a

30 files changed

+1493
-433
lines changed

contrib/seeds/makeseeds.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def main():
164164
mns = filtermulticollateraladdress(mns)
165165
mns = filtermultipayoutaddress(mns)
166166
# Extract IPs
167-
ips = [parseip(mn['state']['addresses'][0]) for mn in mns]
167+
ips = [parseip(mn['state']['addresses']['core_p2p'][0]) for mn in mns]
168168
for onion in onions:
169169
parsed = parseip(onion)
170170
if parsed is not None:

doc/release-notes-6666.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
Notable Changes
2+
---------------
3+
4+
* Dash Core has added support for the ability to register multiple addr:port pairs to a masternode and for specifying
5+
distinct addresses for platform P2P and platform HTTPS endpoints. The consensus and format changes needed to enable
6+
this capability is referred to as "extended addresses" and is enabled by the deployment of the v23 fork, affecting
7+
new masternode registrations and service updates to basic BLS masternodes.
8+
* Operators must upgrade from legacy BLS scheme to basic BLS scheme before utilizing extended address capabilities
9+
10+
Additional Notes
11+
----------------
12+
13+
* While the field `service` is deprecated (see dash#6665), its effective value can be obtained by querying
14+
`addresses['core_p2p'][0]`.
15+
16+
* If the masternode is eligible for extended addresses, operators may register non-IPv4 addresses, subject to validation
17+
and consensus rules.
18+
19+
Updated RPCs
20+
------------
21+
22+
* The input field `platformP2PPort` has been renamed to `platformP2PAddrs`. In addition to numeric inputs (i.e. ports),
23+
the field can now accept a string (i.e. an addr:port pair) and arrays of strings (i.e. multiple addr:port pairs),
24+
subject to validation rules.
25+
26+
* The input field `platformHTTPPort` has been renamed to `platformHTTPSAddrs`. In addition to numeric inputs (i.e. ports),
27+
the field can now accept a string (i.e. an addr:port pair) and arrays of strings (i.e. multiple addr:port pairs),
28+
subject to validation rules.
29+
30+
* The field `addresses` will now also report on platform P2P and platform HTTPS endpoints as `addresses['platform_p2p']`
31+
and `addresses['platform_https']` respectively.
32+
* On payloads before extended addresses, if a masternode update affects `platformP2PPort` and/or `platformHTTPPort`
33+
but does not affect `netInfo`, `protx listdiff` does not contain enough information to report on the masternode's
34+
address and will report the changed port paired with the dummy address `255.255.255.255`.
35+
36+
This does not affect `protx listdiff` queries where `netInfo` was updated or diffs relating to masternodes that
37+
have upgraded to extended addresses.
38+
39+
* If the masternode is eligible for extended addresses, `protx register{,_evo}` and `register_fund{,_evo}` will continue
40+
allowing `coreP2PAddrs` to be left blank, as long as `platformP2PAddrs` and `platformHTTPSAddrs` are _also_ left blank.
41+
* Attempting to populate any three address fields will make populating all fields mandatory.
42+
* This does not affect nodes ineligible for extended addresses (i.e. all nodes before fork activation or legacy BLS nodes)
43+
and they will have to continue specifying `platformP2PAddrs` and `platformHTTPSAddrs` even if they wish to keep
44+
`coreP2PAddrs` blank.
45+
46+
* If the masternode is eligible for extended addresses, `protx register{,_evo}` and `register_fund{,_evo}` will no longer
47+
default to the core P2P port if a port is not specified in the addr:port pair. All ports must be specified explicitly.
48+
* This does not affect nodes ineligible for extended addresses, continuing to default to the core P2P port if provided an
49+
addr without a port.
50+
51+
* `protx register{,_evo}` and `register_fund{,_evo}` will continue to allow specifying only the port number for `platformP2PAddrs`
52+
and `platformHTTPSAddrs`, pairing it with the address from the first `coreP2PAddrs` entry. This mirrors existing behavior.
53+
* This method of entry may not be available in future releases of Dash Core and operators are recommended to switch over to
54+
explicitly specifying (arrays of) addr:port strings for all address fields.
55+
56+
* When reporting on extended address payloads, `platformP2PPort` and `platformHTTPPort` will read the port value from
57+
`netInfo[PLATFORM_P2P][0]` and `netInfo[PLATFORM_HTTPS][0]` respectively as both fields are subsumed into `netInfo`.
58+
* If `netInfo` is blank (which is allowed by ProRegTx), `platformP2PPort` and `platformHTTPPort` will report `-1` to indicate
59+
that the port number cannot be determined.
60+
* `protx listdiff` will not report `platformP2PPort` or `platformHTTPPort` if the legacy fields were not updated (i.e.
61+
changes to `netInfo` will not translate into reporting). This is because `platformP2PPort` or `platformHTTPPort` have
62+
dedicated diff flags and post-consolidation, all changes are now affected by `netInfo`'s diff flag.
63+
64+
To avoid the perception of changes to fields that not serialized by extended address payloads, data from `netInfo` will
65+
not be translated for this RPC call.

src/coinjoin/client.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <net.h>
1515
#include <net_processing.h>
1616
#include <netmessagemaker.h>
17+
#include <rpc/evo_util.h>
1718
#include <shutdown.h>
1819
#include <util/check.h>
1920
#include <util/irange.h>
@@ -1875,7 +1876,7 @@ void CCoinJoinClientSession::GetJsonInfo(UniValue& obj) const
18751876
if (m_wallet->chain().rpcEnableDeprecated("service")) {
18761877
obj.pushKV("service", mixingMasternode->pdmnState->netInfo->GetPrimary().ToStringAddrPort());
18771878
}
1878-
obj.pushKV("addresses", mixingMasternode->pdmnState->netInfo->ToJson());
1879+
obj.pushKV("addrs_core_p2p", mixingMasternode->pdmnState->netInfo->ToJson(NetInfoPurpose::CORE_P2P));
18791880
}
18801881
obj.pushKV("denomination", ValueFromAmount(CoinJoin::DenominationToAmount(nSessionDenom)));
18811882
obj.pushKV("state", GetStateString());

src/evo/core_write.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <evo/simplifiedmns.h>
1414
#include <evo/smldiff.h>
1515
#include <llmq/commitment.h>
16+
#include <rpc/evo_util.h>
1617

1718
#include <univalue.h>
1819

@@ -74,7 +75,7 @@
7475
if (IsServiceDeprecatedRPCEnabled()) {
7576
ret.pushKV("service", netInfo->GetPrimary().ToStringAddrPort());
7677
}
77-
ret.pushKV("addresses", netInfo->ToJson());
78+
ret.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType));
7879
ret.pushKV("ownerAddress", EncodeDestination(PKHash(keyIDOwner)));
7980
ret.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting)));
8081
if (CTxDestination dest; ExtractDestination(scriptPayout, dest)) {
@@ -84,8 +85,8 @@
8485
ret.pushKV("operatorReward", (double)nOperatorReward / 100);
8586
if (nType == MnType::Evo) {
8687
ret.pushKV("platformNodeID", platformNodeID.ToString());
87-
ret.pushKV("platformP2PPort", platformP2PPort);
88-
ret.pushKV("platformHTTPPort", platformHTTPPort);
88+
ret.pushKV("platformP2PPort", GetPlatformPort</*is_p2p=*/true>(*this));
89+
ret.pushKV("platformHTTPPort", GetPlatformPort</*is_p2p=*/false>(*this));
8990
}
9091
ret.pushKV("inputsHash", inputsHash.ToString());
9192
return ret;
@@ -124,14 +125,14 @@
124125
if (IsServiceDeprecatedRPCEnabled()) {
125126
ret.pushKV("service", netInfo->GetPrimary().ToStringAddrPort());
126127
}
127-
ret.pushKV("addresses", netInfo->ToJson());
128+
ret.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType));
128129
if (CTxDestination dest; ExtractDestination(scriptOperatorPayout, dest)) {
129130
ret.pushKV("operatorPayoutAddress", EncodeDestination(dest));
130131
}
131132
if (nType == MnType::Evo) {
132133
ret.pushKV("platformNodeID", platformNodeID.ToString());
133-
ret.pushKV("platformP2PPort", platformP2PPort);
134-
ret.pushKV("platformHTTPPort", platformHTTPPort);
134+
ret.pushKV("platformP2PPort", GetPlatformPort</*is_p2p=*/true>(*this));
135+
ret.pushKV("platformHTTPPort", GetPlatformPort</*is_p2p=*/false>(*this));
135136
}
136137
ret.pushKV("inputsHash", inputsHash.ToString());
137138
return ret;
@@ -164,12 +165,12 @@
164165
if (IsServiceDeprecatedRPCEnabled()) {
165166
obj.pushKV("service", netInfo->GetPrimary().ToStringAddrPort());
166167
}
167-
obj.pushKV("addresses", netInfo->ToJson());
168+
obj.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType));
168169
obj.pushKV("pubKeyOperator", pubKeyOperator.ToString());
169170
obj.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting)));
170171
obj.pushKV("isValid", isValid);
171172
if (nType == MnType::Evo) {
172-
obj.pushKV("platformHTTPPort", platformHTTPPort);
173+
obj.pushKV("platformHTTPPort", GetPlatformPort</*is_p2p=*/false>(*this));
173174
obj.pushKV("platformNodeID", platformNodeID.ToString());
174175
}
175176

src/evo/deterministicmns.cpp

Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -432,13 +432,12 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTota
432432
throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate collateralOutpoint=%s", __func__,
433433
dmn->proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort())));
434434
}
435-
for (const NetInfoEntry& entry : dmn->pdmnState->netInfo->GetEntries()) {
436-
if (const auto& service_opt{entry.GetAddrPort()}; service_opt.has_value()) {
437-
const CService& service{service_opt.value()};
438-
if (!AddUniqueProperty(*dmn, service)) {
435+
for (const auto& entry : dmn->pdmnState->netInfo->GetEntries()) {
436+
if (const auto service_opt{entry.GetAddrPort()}) {
437+
if (!AddUniqueProperty(*dmn, *service_opt)) {
439438
mnUniquePropertyMap = mnUniquePropertyMapSaved;
440-
throw std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s",
441-
__func__, dmn->proTxHash.ToString(), service.ToStringAddrPort()));
439+
throw std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s", __func__,
440+
dmn->proTxHash.ToString(), service_opt->ToStringAddrPort()));
442441
}
443442
} else {
444443
mnUniquePropertyMap = mnUniquePropertyMapSaved;
@@ -489,21 +488,19 @@ void CDeterministicMNList::UpdateMN(const CDeterministicMN& oldDmn, const std::s
489488
// We track each individual entry in netInfo as opposed to netInfo itself (preventing us from
490489
// using UpdateUniqueProperty()), so we need to successfully purge all old entries and insert
491490
// new entries to successfully update.
492-
for (const NetInfoEntry& old_entry : oldInfo->GetEntries()) {
493-
if (const auto& service_opt{old_entry.GetAddrPort()}) {
494-
const CService& service{service_opt.value()};
495-
if (!DeleteUniqueProperty(dmn, service)) {
491+
for (const auto& old_entry : oldInfo->GetEntries()) {
492+
if (const auto service_opt{old_entry.GetAddrPort()}) {
493+
if (!DeleteUniqueProperty(dmn, *service_opt)) {
496494
return "internal error"; // This shouldn't be possible
497495
}
498496
} else {
499497
return "invalid address";
500498
}
501499
}
502-
for (const NetInfoEntry& new_entry : newInfo->GetEntries()) {
503-
if (const auto& service_opt{new_entry.GetAddrPort()}) {
504-
const CService& service{service_opt.value()};
505-
if (!AddUniqueProperty(dmn, service)) {
506-
return strprintf("duplicate (%s)", service.ToStringAddrPort());
500+
for (const auto& new_entry : newInfo->GetEntries()) {
501+
if (const auto service_opt{new_entry.GetAddrPort()}) {
502+
if (!AddUniqueProperty(dmn, *service_opt)) {
503+
return strprintf("duplicate (%s)", service_opt->ToStringAddrPort());
507504
}
508505
} else {
509506
return "invalid address";
@@ -578,13 +575,12 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash)
578575
throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a collateralOutpoint=%s", __func__,
579576
proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort())));
580577
}
581-
for (const NetInfoEntry& entry : dmn->pdmnState->netInfo->GetEntries()) {
582-
if (const auto& service_opt{entry.GetAddrPort()}; service_opt.has_value()) {
583-
const CService& service{service_opt.value()};
584-
if (!DeleteUniqueProperty(*dmn, service)) {
578+
for (const auto& entry : dmn->pdmnState->netInfo->GetEntries()) {
579+
if (const auto service_opt{entry.GetAddrPort()}) {
580+
if (!DeleteUniqueProperty(*dmn, *service_opt)) {
585581
mnUniquePropertyMap = mnUniquePropertyMapSaved;
586582
throw std::runtime_error(strprintf("%s: Can't delete a masternode %s with an address=%s", __func__,
587-
proTxHash.ToString(), service.ToStringAddrPort()));
583+
proTxHash.ToString(), service_opt->ToStringAddrPort()));
588584
}
589585
} else {
590586
mnUniquePropertyMap = mnUniquePropertyMapSaved;
@@ -914,46 +910,49 @@ static bool CheckService(const ProTx& proTx, TxValidationState& state)
914910
return true;
915911
// Shouldn't be possible during self-checks
916912
case NetInfoStatus::BadInput:
913+
case NetInfoStatus::Duplicate:
917914
case NetInfoStatus::MaxLimit:
918915
assert(false);
919916
} // no default case, so the compiler can warn about missing cases
920917
assert(false);
921918
}
922919

923920
template <typename ProTx>
924-
static bool CheckPlatformFields(const ProTx& proTx, TxValidationState& state)
921+
static bool CheckPlatformFields(const ProTx& proTx, bool is_extended_addr, TxValidationState& state)
925922
{
926923
if (proTx.platformNodeID.IsNull()) {
927924
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-nodeid");
928925
}
929926

930-
// TODO: use real args here
931-
static int mainnetPlatformP2PPort = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN)->GetDefaultPlatformP2PPort();
932-
if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
933-
if (proTx.platformP2PPort != mainnetPlatformP2PPort) {
927+
if (is_extended_addr) {
928+
// platformHTTPPort and platformP2PPort have been subsumed by netInfo. They should always be zero.
929+
if (proTx.platformP2PPort != 0) {
934930
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-p2p-port");
935931
}
932+
if (proTx.platformHTTPPort != 0) {
933+
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-http-port");
934+
}
935+
return true;
936936
}
937937

938-
// TODO: use real args here
939-
static int mainnetPlatformHTTPPort = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN)->GetDefaultPlatformHTTPPort();
940-
if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
941-
if (proTx.platformHTTPPort != mainnetPlatformHTTPPort) {
938+
if (::IsNodeOnMainnet()) {
939+
if (proTx.platformP2PPort != ::MainParams().GetDefaultPlatformP2PPort()) {
940+
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-p2p-port");
941+
}
942+
if (proTx.platformHTTPPort != ::MainParams().GetDefaultPlatformHTTPPort()) {
942943
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-http-port");
943944
}
944945
}
945-
946-
// TODO: use real args here
947-
static int mainnetDefaultP2PPort = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN)->GetDefaultPort();
948-
if (proTx.platformP2PPort == mainnetDefaultP2PPort) {
946+
if (proTx.platformP2PPort == ::MainParams().GetDefaultPort()) {
949947
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-p2p-port");
950948
}
951-
if (proTx.platformHTTPPort == mainnetDefaultP2PPort) {
949+
if (proTx.platformHTTPPort == ::MainParams().GetDefaultPort()) {
952950
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-http-port");
953951
}
954952

955-
if (proTx.platformP2PPort == proTx.platformHTTPPort || proTx.platformP2PPort == proTx.netInfo->GetPrimary().GetPort() ||
956-
proTx.platformHTTPPort == proTx.netInfo->GetPrimary().GetPort()) {
953+
const uint16_t core_port{proTx.netInfo->GetPrimary().GetPort()};
954+
if (proTx.platformP2PPort == proTx.platformHTTPPort || proTx.platformP2PPort == core_port ||
955+
proTx.platformHTTPPort == core_port) {
957956
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-dup-ports");
958957
}
959958

@@ -1065,7 +1064,7 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl:
10651064
}
10661065

10671066
if (opt_ptx->nType == MnType::Evo) {
1068-
if (!CheckPlatformFields(*opt_ptx, state)) {
1067+
if (!CheckPlatformFields(*opt_ptx, opt_ptx->nVersion >= ProTxVersion::ExtAddr, state)) {
10691068
return false;
10701069
}
10711070
}
@@ -1119,11 +1118,10 @@ bool CheckProRegTx(CDeterministicMNManager& dmnman, const CTransaction& tx, gsl:
11191118
auto mnList = dmnman.GetListForBlock(pindexPrev);
11201119

11211120
// only allow reusing of addresses when it's for the same collateral (which replaces the old MN)
1122-
for (const NetInfoEntry& entry : opt_ptx->netInfo->GetEntries()) {
1123-
if (const auto& service_opt{entry.GetAddrPort()}; service_opt.has_value()) {
1124-
const CService& service{service_opt.value()};
1125-
if (mnList.HasUniqueProperty(service) &&
1126-
mnList.GetUniquePropertyMN(service)->collateralOutpoint != collateralOutpoint) {
1121+
for (const auto& entry : opt_ptx->netInfo->GetEntries()) {
1122+
if (const auto service_opt{entry.GetAddrPort()}) {
1123+
if (mnList.HasUniqueProperty(*service_opt) &&
1124+
mnList.GetUniquePropertyMN(*service_opt)->collateralOutpoint != collateralOutpoint) {
11271125
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-netinfo-entry");
11281126
}
11291127
} else {
@@ -1185,7 +1183,7 @@ bool CheckProUpServTx(CDeterministicMNManager& dmnman, const CTransaction& tx, g
11851183
}
11861184

11871185
if (opt_ptx->nType == MnType::Evo) {
1188-
if (!CheckPlatformFields(*opt_ptx, state)) {
1186+
if (!CheckPlatformFields(*opt_ptx, opt_ptx->nVersion >= ProTxVersion::ExtAddr, state)) {
11891187
return false;
11901188
}
11911189
}
@@ -1202,10 +1200,10 @@ bool CheckProUpServTx(CDeterministicMNManager& dmnman, const CTransaction& tx, g
12021200
}
12031201

12041202
// don't allow updating to addresses already used by other MNs
1205-
for (const NetInfoEntry& entry : opt_ptx->netInfo->GetEntries()) {
1206-
if (const auto& service_opt{entry.GetAddrPort()}; service_opt.has_value()) {
1207-
const CService& service{service_opt.value()};
1208-
if (mnList.HasUniqueProperty(service) && mnList.GetUniquePropertyMN(service)->proTxHash != opt_ptx->proTxHash) {
1203+
for (const auto& entry : opt_ptx->netInfo->GetEntries()) {
1204+
if (const auto service_opt{entry.GetAddrPort()}) {
1205+
if (mnList.HasUniqueProperty(*service_opt) &&
1206+
mnList.GetUniquePropertyMN(*service_opt)->proTxHash != opt_ptx->proTxHash) {
12091207
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-netinfo-entry");
12101208
}
12111209
} else {

src/evo/deterministicmns.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ class CDeterministicMNList
434434
#define DMNL_NO_TEMPLATE(name) \
435435
static_assert(!std::is_same_v<std::decay_t<T>, name>, "GetUniquePropertyHash cannot be templated against " #name)
436436
DMNL_NO_TEMPLATE(CBLSPublicKey);
437+
DMNL_NO_TEMPLATE(ExtNetInfo);
437438
DMNL_NO_TEMPLATE(MnNetInfo);
438439
DMNL_NO_TEMPLATE(NetInfoEntry);
439440
DMNL_NO_TEMPLATE(NetInfoInterface);

0 commit comments

Comments
 (0)