From e50d436d79a5bd57d782314d15841c271b019f2d Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 27 Feb 2026 22:52:29 +0530 Subject: [PATCH] rpc: restore `-deprecatedrpc=service` gating for legacy network fields reverts: - bbcd9d543e67a381ec92239a943ea3c519976f87 --- doc/release-notes-7181.md | 10 +++++ src/coinjoin/client.cpp | 4 +- src/evo/core_write.cpp | 52 ++++++++++++++++--------- src/evo/dmnstate.cpp | 4 +- src/evo/netinfo.cpp | 6 +++ src/evo/netinfo.h | 3 ++ src/rpc/coinjoin.cpp | 2 +- src/rpc/masternode.cpp | 14 ++++--- src/rpc/quorums.cpp | 6 ++- test/functional/rpc_netinfo.py | 70 +++++++++++++++++++++++++++++----- 10 files changed, 133 insertions(+), 38 deletions(-) create mode 100644 doc/release-notes-7181.md diff --git a/doc/release-notes-7181.md b/doc/release-notes-7181.md new file mode 100644 index 000000000000..702fedc58079 --- /dev/null +++ b/doc/release-notes-7181.md @@ -0,0 +1,10 @@ +Updated RPCs +------------ + +* The deprecated keys `service`, `platformP2PPort` and `platformHTTPPort` will now require the runtime + flag `-deprecatedrpc=service`. + * The following RPCs are affected `decoderawtransaction`, `decodepsbt`, `getblock`, + `getrawtransaction`, `gettransaction`, `masternode status` (only the `dmnState` key), `protx diff`, + `protx listdiff`. + * This runtime gate also extends to the functionally identical key, `address` in `masternode list` + (and its alias, `masternodelist`) diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index be6e7b458115..3ecc412bab08 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -1865,7 +1865,9 @@ 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->GetPrimary().ToStringAddrPort()); + if (m_wallet->chain().rpcEnableDeprecated("service")) { + obj.pushKV("service", mixingMasternode->pdmnState->netInfo->GetPrimary().ToStringAddrPort()); + } obj.pushKV("addrs_core_p2p", mixingMasternode->pdmnState->netInfo->ToJson(NetInfoPurpose::CORE_P2P)); } obj.pushKV("denomination", ValueFromAmount(CoinJoin::DenominationToAmount(nSessionDenom))); diff --git a/src/evo/core_write.cpp b/src/evo/core_write.cpp index b3e414d7c779..43590e14e7fc 100644 --- a/src/evo/core_write.cpp +++ b/src/evo/core_write.cpp @@ -53,9 +53,9 @@ const std::map RPCRESULT_MAP{{ RESULT_MAP_ENTRY("outpoint", RPCResult::Type::STR_HEX,"The outpoint of the masternode"), RESULT_MAP_ENTRY("ownerAddress", RPCResult::Type::STR, "Dash address used for payee updates and proposal voting"), RESULT_MAP_ENTRY("payoutAddress", RPCResult::Type::STR, "Dash address used for masternode reward payments"), - RESULT_MAP_ENTRY("platformHTTPPort", RPCResult::Type::NUM, "(DEPRECATED) TCP port of Platform HTTP API"), + RESULT_MAP_ENTRY("platformHTTPPort", RPCResult::Type::NUM, "TCP port of Platform HTTP API (DEPRECATED, returned only if config option -deprecatedrpc=service is passed)"), RESULT_MAP_ENTRY("platformNodeID", RPCResult::Type::STR_HEX, "Node ID derived from P2P public key for Platform P2P"), - RESULT_MAP_ENTRY("platformP2PPort", RPCResult::Type::NUM, "(DEPRECATED) TCP port of Platform P2P"), + RESULT_MAP_ENTRY("platformP2PPort", RPCResult::Type::NUM, "TCP port of Platform P2P (DEPRECATED, returned only if config option -deprecatedrpc=service is passed)"), RESULT_MAP_ENTRY("PoSeBanHeight", RPCResult::Type::NUM, "Height masternode was banned for Proof of Service violations"), RESULT_MAP_ENTRY("PoSePenalty", RPCResult::Type::NUM, "Proof of Service penalty score"), RESULT_MAP_ENTRY("PoSeRevivedHeight", RPCResult::Type::NUM, "Height masternode recovered from Proof of Service violations"), @@ -66,7 +66,7 @@ const std::map RPCRESULT_MAP{{ RESULT_MAP_ENTRY("quorumSig", RPCResult::Type::STR_HEX, "BLS recovered threshold signature of quorum"), RESULT_MAP_ENTRY("registeredHeight", RPCResult::Type::NUM, "Height masternode was registered"), RESULT_MAP_ENTRY("revocationReason", RPCResult::Type::NUM, "Reason for ProUpRegTx revocation"), - RESULT_MAP_ENTRY("service", RPCResult::Type::STR, "(DEPRECATED) IP address and port of the masternode"), + RESULT_MAP_ENTRY("service", RPCResult::Type::STR, "IP address and port of the masternode (DEPRECATED, returned only if config option -deprecatedrpc=service is passed)"), RESULT_MAP_ENTRY("type", RPCResult::Type::NUM, "Masternode type"), RESULT_MAP_ENTRY("type_str", RPCResult::Type::STR, "Masternode type (human-readable string)"), RESULT_MAP_ENTRY("version", RPCResult::Type::NUM, "Special transaction version"), @@ -197,7 +197,7 @@ RPCResult CDeterministicMNState::GetJsonHelp(const std::string& key, bool option return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The masternode state", { {RPCResult::Type::NUM, "version", "Version of the masternode state"}, - GetRpcResult("service"), + GetRpcResult("service", /*optional=*/true), GetRpcResult("addresses"), GetRpcResult("registeredHeight"), GetRpcResult("lastPaidHeight"), @@ -221,7 +221,9 @@ UniValue CDeterministicMNState::ToJson(MnType nType) const { UniValue obj(UniValue::VOBJ); obj.pushKV("version", nVersion); - obj.pushKV("service", netInfo->GetPrimary().ToStringAddrPort()); + if (IsServiceDeprecatedRPCEnabled()) { + obj.pushKV("service", netInfo->GetPrimary().ToStringAddrPort()); + } obj.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType)); obj.pushKV("registeredHeight", nRegisteredHeight); obj.pushKV("lastPaidHeight", nLastPaidHeight); @@ -234,8 +236,10 @@ UniValue CDeterministicMNState::ToJson(MnType nType) const obj.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting))); if (nType == MnType::Evo) { obj.pushKV("platformNodeID", platformNodeID.ToString()); - obj.pushKV("platformP2PPort", GetPlatformPort(*this)); - obj.pushKV("platformHTTPPort", GetPlatformPort(*this)); + if (IsServiceDeprecatedRPCEnabled()) { + obj.pushKV("platformP2PPort", GetPlatformPort(*this)); + obj.pushKV("platformHTTPPort", GetPlatformPort(*this)); + } } CTxDestination dest; @@ -283,7 +287,7 @@ RPCResult CProRegTx::GetJsonHelp(const std::string& key, bool optional) GetRpcResult("type"), GetRpcResult("collateralHash"), GetRpcResult("collateralIndex"), - GetRpcResult("service"), + GetRpcResult("service", /*optional=*/true), GetRpcResult("addresses"), GetRpcResult("ownerAddress"), GetRpcResult("votingAddress"), @@ -304,7 +308,9 @@ UniValue CProRegTx::ToJson() const ret.pushKV("type", ToUnderlying(nType)); ret.pushKV("collateralHash", collateralOutpoint.hash.ToString()); ret.pushKV("collateralIndex", collateralOutpoint.n); - ret.pushKV("service", netInfo->GetPrimary().ToStringAddrPort()); + if (IsServiceDeprecatedRPCEnabled()) { + ret.pushKV("service", netInfo->GetPrimary().ToStringAddrPort()); + } ret.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType)); ret.pushKV("ownerAddress", EncodeDestination(PKHash(keyIDOwner))); ret.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting))); @@ -315,8 +321,10 @@ UniValue CProRegTx::ToJson() const ret.pushKV("operatorReward", (double)nOperatorReward / 100); if (nType == MnType::Evo) { ret.pushKV("platformNodeID", platformNodeID.ToString()); - ret.pushKV("platformP2PPort", GetPlatformPort(*this)); - ret.pushKV("platformHTTPPort", GetPlatformPort(*this)); + if (IsServiceDeprecatedRPCEnabled()) { + ret.pushKV("platformP2PPort", GetPlatformPort(*this)); + ret.pushKV("platformHTTPPort", GetPlatformPort(*this)); + } } ret.pushKV("inputsHash", inputsHash.ToString()); return ret; @@ -377,7 +385,7 @@ RPCResult CProUpServTx::GetJsonHelp(const std::string& key, bool optional) GetRpcResult("version"), GetRpcResult("type"), GetRpcResult("proTxHash"), - GetRpcResult("service"), + GetRpcResult("service", /*optional=*/true), GetRpcResult("addresses"), GetRpcResult("operatorPayoutAddress", /*optional=*/true), GetRpcResult("platformNodeID", /*optional=*/true), @@ -393,15 +401,19 @@ UniValue CProUpServTx::ToJson() const ret.pushKV("version", nVersion); ret.pushKV("type", ToUnderlying(nType)); ret.pushKV("proTxHash", proTxHash.ToString()); - ret.pushKV("service", netInfo->GetPrimary().ToStringAddrPort()); + if (IsServiceDeprecatedRPCEnabled()) { + ret.pushKV("service", netInfo->GetPrimary().ToStringAddrPort()); + } ret.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType)); if (CTxDestination dest; ExtractDestination(scriptOperatorPayout, dest)) { ret.pushKV("operatorPayoutAddress", EncodeDestination(dest)); } if (nType == MnType::Evo) { ret.pushKV("platformNodeID", platformNodeID.ToString()); - ret.pushKV("platformP2PPort", GetPlatformPort(*this)); - ret.pushKV("platformHTTPPort", GetPlatformPort(*this)); + if (IsServiceDeprecatedRPCEnabled()) { + ret.pushKV("platformP2PPort", GetPlatformPort(*this)); + ret.pushKV("platformHTTPPort", GetPlatformPort(*this)); + } } ret.pushKV("inputsHash", inputsHash.ToString()); return ret; @@ -508,7 +520,7 @@ RPCResult CSimplifiedMNListEntry::GetJsonHelp(const std::string& key, bool optio GetRpcResult("type", /*optional=*/false, /*override_name=*/"nType"), {RPCResult::Type::STR_HEX, "proRegTxHash", "Hash of the ProRegTx identifying the masternode"}, {RPCResult::Type::STR_HEX, "confirmedHash", "Hash of the block where the masternode was confirmed"}, - GetRpcResult("service"), + GetRpcResult("service", /*optional=*/true), GetRpcResult("addresses"), GetRpcResult("pubKeyOperator"), GetRpcResult("votingAddress"), @@ -527,13 +539,17 @@ 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->GetPrimary().ToStringAddrPort()); + if (IsServiceDeprecatedRPCEnabled()) { + obj.pushKV("service", netInfo->GetPrimary().ToStringAddrPort()); + } obj.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType)); obj.pushKV("pubKeyOperator", pubKeyOperator.ToString()); obj.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting))); obj.pushKV("isValid", isValid); if (nType == MnType::Evo) { - obj.pushKV("platformHTTPPort", GetPlatformPort(*this)); + if (IsServiceDeprecatedRPCEnabled()) { + obj.pushKV("platformHTTPPort", GetPlatformPort(*this)); + } obj.pushKV("platformNodeID", platformNodeID.ToString()); } diff --git a/src/evo/dmnstate.cpp b/src/evo/dmnstate.cpp index b63cd69ef98d..9f04f4069ef9 100644 --- a/src/evo/dmnstate.cpp +++ b/src/evo/dmnstate.cpp @@ -39,7 +39,9 @@ UniValue CDeterministicMNStateDiff::ToJson(MnType nType) const obj.pushKV("version", state.nVersion); } if (fields & Field_netInfo) { - obj.pushKV("service", state.netInfo->GetPrimary().ToStringAddrPort()); + if (IsServiceDeprecatedRPCEnabled()) { + obj.pushKV("service", state.netInfo->GetPrimary().ToStringAddrPort()); + } } if (fields & Field_nRegisteredHeight) { obj.pushKV("registeredHeight", state.nRegisteredHeight); diff --git a/src/evo/netinfo.cpp b/src/evo/netinfo.cpp index 3a8a920d46eb..a3f53693ccaf 100644 --- a/src/evo/netinfo.cpp +++ b/src/evo/netinfo.cpp @@ -70,6 +70,12 @@ bool IsAllowedPlatformHTTPPort(uint16_t port) bool IsNodeOnMainnet() { return Params().NetworkIDString() == CBaseChainParams::MAIN; } +bool IsServiceDeprecatedRPCEnabled() +{ + const auto args = gArgs.GetArgs("-deprecatedrpc"); + return std::find(args.begin(), args.end(), "service") != args.end(); +} + const CChainParams& MainParams() { std::call_once(g_main_params_flag, [&]() { g_main_params = CreateChainParams(::gArgs, CBaseChainParams::MAIN); }); diff --git a/src/evo/netinfo.h b/src/evo/netinfo.h index 33d81963ca5b..9c75cd4376aa 100644 --- a/src/evo/netinfo.h +++ b/src/evo/netinfo.h @@ -100,6 +100,9 @@ constexpr std::string_view PurposeToString(const NetInfoPurpose purpose) /** Will return true if node is running on mainnet */ bool IsNodeOnMainnet(); +/** Identical to IsDeprecatedRPCEnabled("service"). For use outside of RPC code */ +bool IsServiceDeprecatedRPCEnabled(); + /** Creates a one-element array using CService::ToStringPortAddr() output */ UniValue ArrFromService(const CService& addr); diff --git a/src/rpc/coinjoin.cpp b/src/rpc/coinjoin.cpp index 976b4040f58d..3a2cc40a6977 100644 --- a/src/rpc/coinjoin.cpp +++ b/src/rpc/coinjoin.cpp @@ -433,7 +433,7 @@ static RPCHelpMan getcoinjoininfo() { {RPCResult::Type::STR_HEX, "protxhash", "The ProTxHash of the masternode"}, GetRpcResult("outpoint"), - {RPCResult::Type::STR, "service", "(DEPRECATED) The IP address and port of the masternode"}, + {RPCResult::Type::STR, "service", "The IP address and port of the masternode (DEPRECATED, returned only if config option -deprecatedrpc=service is passed)"}, {RPCResult::Type::ARR, "addrs_core_p2p", "Network addresses of the masternode used for protocol P2P", { {RPCResult::Type::STR, "address", ""}, diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 2fc9f556d1f5..cac3cb7880d1 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -182,7 +182,7 @@ static RPCHelpMan masternode_status() RPCResult::Type::OBJ, "", "", { GetRpcResult("outpoint"), - GetRpcResult("service"), + GetRpcResult("service", /*optional=*/true), GetRpcResult("proTxHash", /*optional=*/true), GetRpcResult("type_str", /*optional=*/true, /*override_name=*/"type"), GetRpcResult("collateralHash", /*optional=*/true), @@ -537,7 +537,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite) RPCResult{"for mode = info", RPCResult::Type::STR, "", "Flattened list of a masternode's status, payee address and service addresses"}, RPCResult{"for mode = evo, json or recent", RPCResult::Type::OBJ, "", "", { GetRpcResult("proTxHash"), - GetRpcResult("service", /*optional=*/false, /*override_name=*/"address"), + GetRpcResult("service", /*optional=*/true, /*override_name=*/"address"), GetRpcResult("addresses"), GetRpcResult("payoutAddress", /*optional=*/false, /*override_name=*/"payee"), {RPCResult::Type::STR, "status", "Masternode status (human-readable string)"}, @@ -690,15 +690,19 @@ static RPCHelpMan masternodelist_helper(bool is_composite) return; UniValue objMN(UniValue::VOBJ); objMN.pushKV("proTxHash", dmn.proTxHash.ToString()); - objMN.pushKV("address", dmn.pdmnState->netInfo->GetPrimary().ToStringAddrPort()); + if (IsDeprecatedRPCEnabled("service")) { + objMN.pushKV("address", dmn.pdmnState->netInfo->GetPrimary().ToStringAddrPort()); + } objMN.pushKV("addresses", GetNetInfoWithLegacyFields(*dmn.pdmnState, dmn.nType)); objMN.pushKV("payee", payeeStr); objMN.pushKV("status", dmnToStatus(dmn)); objMN.pushKV("type", std::string(GetMnType(dmn.nType).description)); if (dmn.nType == MnType::Evo) { objMN.pushKV("platformNodeID", dmn.pdmnState->platformNodeID.ToString()); - objMN.pushKV("platformP2PPort", GetPlatformPort(*dmn.pdmnState)); - objMN.pushKV("platformHTTPPort", GetPlatformPort(*dmn.pdmnState)); + if (IsDeprecatedRPCEnabled("service")) { + objMN.pushKV("platformP2PPort", GetPlatformPort(*dmn.pdmnState)); + objMN.pushKV("platformHTTPPort", GetPlatformPort(*dmn.pdmnState)); + } } objMN.pushKV("pospenaltyscore", dmn.pdmnState->nPoSePenalty); objMN.pushKV("consecutivePayments", dmn.pdmnState->nConsecutivePayments); diff --git a/src/rpc/quorums.cpp b/src/rpc/quorums.cpp index f35bd6952f4b..645d4a2a9538 100644 --- a/src/rpc/quorums.cpp +++ b/src/rpc/quorums.cpp @@ -209,7 +209,9 @@ 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->GetPrimary().ToStringAddrPort()); + if (IsDeprecatedRPCEnabled("service")) { + mo.pushKV("service", dmn->pdmnState->netInfo->GetPrimary().ToStringAddrPort()); + } mo.pushKV("addresses", GetNetInfoWithLegacyFields(*dmn->pdmnState, dmn->nType)); mo.pushKV("pubKeyOperator", dmn->pdmnState->pubKeyOperator.ToString()); mo.pushKV("valid", static_cast(quorum.qc->validMembers[i])); @@ -259,7 +261,7 @@ static RPCHelpMan quorum_info() {RPCResult::Type::OBJ, "", "", { GetRpcResult("proTxHash"), - GetRpcResult("service"), + GetRpcResult("service", /*optional=*/true), GetRpcResult("addresses"), GetRpcResult("pubKeyOperator"), {RPCResult::Type::BOOL, "valid", "True if member is valid for this DKG"}, diff --git a/test/functional/rpc_netinfo.py b/test/functional/rpc_netinfo.py index fe45b1ca7b31..041f4afa75f2 100755 --- a/test/functional/rpc_netinfo.py +++ b/test/functional/rpc_netinfo.py @@ -153,10 +153,11 @@ def add_options(self, parser): self.add_wallet_options(parser) def set_test_params(self): - self.num_nodes = 2 + self.num_nodes = 3 self.extra_args = [[ "-dip3params=2:2", f"-vbparams=v24:{self.mocktime}:999999999999:{V24_ACTIVATION_THRESHOLD}:10:8:6:5:0" ] for _ in range(self.num_nodes)] + self.extra_args[2] += ["-deprecatedrpc=service"] def skip_test_if_missing_module(self): self.skip_if_no_wallet() @@ -194,12 +195,14 @@ def run_test(self): self.node_two: EvoNode = EvoNode(self.nodes[1]) self.node_two.generate_collateral(self) self.node_two.register_mn(self, True, "", DEFAULT_PORT_PLATFORM_P2P, DEFAULT_PORT_PLATFORM_HTTP) + # Used to check deprecated field behavior + self.node_simple: TestNode = self.nodes[2] # Test routines self.log.info("Test input validation for masternode address fields (pre-fork)") self.test_validation_common() self.test_validation_legacy() self.log.info("Test output masternode address fields for consistency (pre-fork)") - self.test_fields() + self.test_deprecation() self.log.info("Mine blocks to activate DEPLOYMENT_V24") self.activate_v24() self.log.info("Test input validation for masternode address fields (post-fork)") @@ -208,10 +211,15 @@ def run_test(self): self.log.info("Test masternode address fields for ProRegTx without addresses") self.test_empty_fields() self.log.info("Test output masternode address fields for consistency (post-fork)") + # Need to restart node with deprecated fields enabled to test shims + evo_extra_args = self.node_evo.node.extra_args.copy() + self.restart_node(self.node_evo.mn.nodeIdx, extra_args=evo_extra_args + ['-deprecatedrpc=service']) + self.reconnect_nodes() self.test_shims() # Need to destroy masternodes as the next test will be re-creating them self.node_evo.destroy_mn(self) self.node_two.destroy_mn(self) + self.restart_node(self.node_evo.mn.nodeIdx, extra_args=evo_extra_args) self.reconnect_nodes() self.log.info("Test unique properties map duplication checks") self.test_uniqueness() @@ -391,7 +399,7 @@ def test_validation_extended(self): self.node_evo.register_mn(self, False, "127.0.0.1", DEFAULT_PORT_PLATFORM_P2P, DEFAULT_PORT_PLATFORM_HTTP, -8, "Error setting coreP2PAddrs[0] to '127.0.0.1' (invalid port)") - def test_fields(self): + def test_deprecation(self): # netInfo is represented with JSON in CProRegTx, CProUpServTx, CDeterministicMNState and CSimplifiedMNListEntry, # so we need to test calls that rely on these underlying implementations. Start by collecting RPC responses. self.log.info("Collect JSON RPC responses from node") @@ -404,7 +412,12 @@ def test_fields(self): self.node_evo.set_active_state(self, True) masternode_status = self.node_evo.node.masternode('status') - # Stop actively running the masternode so we can issue a CProUpServTx + # Generate deprecation-disabled response to avoid having to re-create a masternode again later on + self.node_evo.set_active_state(self, True, ['-deprecatedrpc=service']) + self.reconnect_nodes() + masternode_status_depr = self.node_evo.node.masternode('status') + + # Stop actively running the masternode so we can issue a CProUpServTx (and enable the deprecation) self.node_evo.set_active_state(self, False) self.reconnect_nodes() @@ -436,6 +449,13 @@ def test_fields(self): protx_listdiff_rpc_pl = self.node_evo.node.protx('listdiff', proupservtx_height_pl - 1, proupservtx_height_pl) protx_listdiff_rpc_pl = self.extract_from_listdiff(protx_listdiff_rpc_pl, proregtx_hash) + self.log.info("Test RPCs return an 'addresses' field") + assert "addresses" in proregtx_rpc['proRegTx'].keys() + assert "addresses" in masternode_status['dmnState'].keys() + assert "addresses" in proupservtx_rpc['proUpServTx'].keys() + assert "addresses" in protx_diff_rpc['mnList'][0].keys() + assert "addresses" in protx_listdiff_rpc.keys() + self.log.info("Test 'addresses' report correctly") self.check_netinfo_fields(proregtx_rpc['proRegTx']['addresses'], self.node_evo.mn.nodePort, DEFAULT_PORT_PLATFORM_HTTP, DEFAULT_PORT_PLATFORM_P2P) self.check_netinfo_fields(masternode_status['dmnState']['addresses'], self.node_evo.mn.nodePort, DEFAULT_PORT_PLATFORM_HTTP, DEFAULT_PORT_PLATFORM_P2P) @@ -449,10 +469,37 @@ def test_fields(self): assert_equal(protx_listdiff_rpc_pl['addresses']['platform_https'][0], f"{DMNSTATE_DIFF_DUMMY_ADDR}:{DEFAULT_PORT_PLATFORM_HTTP + 10}") assert_equal(protx_listdiff_rpc_pl['addresses']['platform_p2p'][0], f"{DMNSTATE_DIFF_DUMMY_ADDR}:{DEFAULT_PORT_PLATFORM_P2P + 10}") + self.log.info("Test RPCs by default no longer return a 'service' field") + assert "service" not in proregtx_rpc['proRegTx'].keys() + assert "service" not in masternode_status['dmnState'].keys() + assert "service" not in proupservtx_rpc['proUpServTx'].keys() + assert "service" not in protx_diff_rpc['mnList'][0].keys() + assert "service" not in protx_listdiff_rpc.keys() + # "service" in "masternode status" is exempt from the deprecation as the primary address is + # relevant on the host node as opposed to expressing payload information in most other RPCs. + assert "service" in masternode_status.keys() + # Shut down masternode self.node_evo.destroy_mn(self) self.reconnect_nodes() + self.log.info("Collect RPC responses from node with -deprecatedrpc=service") + + # Re-use chain activity from earlier + proregtx_rpc = self.node_simple.getrawtransaction(proregtx_hash, True) + proupservtx_rpc = self.node_simple.getrawtransaction(proupservtx_hash, True) + protx_diff_rpc = self.node_simple.protx('diff', masternode_active_height - 1, masternode_active_height) + masternode_status = masternode_status_depr # Pull in response generated from earlier + protx_listdiff_rpc = self.node_simple.protx('listdiff', proupservtx_height - 1, proupservtx_height) + protx_listdiff_rpc = self.extract_from_listdiff(protx_listdiff_rpc, proregtx_hash) + + self.log.info("Test RPCs return 'service' with -deprecatedrpc=service") + assert "service" in proregtx_rpc['proRegTx'].keys() + assert "service" in masternode_status['dmnState'].keys() + assert "service" in proupservtx_rpc['proUpServTx'].keys() + assert "service" in protx_diff_rpc['mnList'][0].keys() + assert "service" in protx_listdiff_rpc.keys() + def test_empty_fields(self): def empty_common(grt_dict): # Even if '[::]:0' is reported by 'service', 'addresses' should always be blank if we have nothing to report @@ -462,7 +509,7 @@ def empty_common(grt_dict): assert_equal(grt_dict['service'], "[::]:0") # Validate that our masternode was registered before the fork - grt_proregtx = self.node_two.node.getrawtransaction(self.node_two.mn.proTxHash, True)['proRegTx'] + grt_proregtx = self.node_simple.getrawtransaction(self.node_two.mn.proTxHash, True)['proRegTx'] assert_equal(grt_proregtx['version'], PROTXVER_BASIC) # Test reporting on legacy address (i.e. basic BLS and earlier) nodes @@ -478,7 +525,7 @@ def empty_common(grt_dict): self.node_two.register_mn(self, True, "", "", "") # Validate that masternode uses extended addresses - grt_proregtx = self.node_two.node.getrawtransaction(self.node_two.mn.proTxHash, True)['proRegTx'] + grt_proregtx = self.node_simple.getrawtransaction(self.node_two.mn.proTxHash, True)['proRegTx'] assert_equal(grt_proregtx['version'], PROTXVER_EXTADDR) # Test reporting for extended addresses @@ -498,7 +545,7 @@ def empty_common(grt_dict): def test_shims(self): # There are two shims there to help with migrating between legacy and extended addresses, one reads from legacy platform # fields to ensure 'addresses' is adequately populated. The other, reads from netInfo to populate platform{HTTP,P2P}Port. - # As the fork is now active, we can now evaluate the test cases that couldn't be evaluated in test_fields(). + # As the fork is now active, we can now evaluate the test cases that couldn't be evaluated in test_deprecation(). self.log.info("Collect JSON RPC responses from node") # Create an masternode that clearly uses extended addresses (hello IPv6!) @@ -536,14 +583,17 @@ def test_shims(self): # platform{HTTP,P2P}Port *won't* be populated by listdiff as that *field* is now unused and it's dangerous to report "updates" to disused fields assert "platformP2PPort" not in protx_listdiff_rpc.keys() assert "platformHTTPPort" not in protx_listdiff_rpc.keys() - # Check that 'service' correctly reports as coreP2PAddrs[0] - assert_equal(proregtx_rpc['proRegTx']['service'], f"127.0.0.1:{self.node_evo.mn.nodePort}") - assert_equal(proupservtx_rpc['proUpServTx']['service'], f"127.0.0.1:{self.node_evo.mn.nodePort}") # Restart the client to see if (de)ser works as intended (CDeterministicMNStateDiff is a special case and we just made an update) self.node_evo.set_active_state(self, False) self.reconnect_nodes() + # Check that 'service' correctly reports as coreP2PAddrs[0] + proregtx_rpc = self.node_simple.getrawtransaction(proregtx_hash, True) + proupservtx_rpc = self.node_simple.getrawtransaction(proupservtx_hash, True) + assert_equal(proregtx_rpc['proRegTx']['service'], f"127.0.0.1:{self.node_evo.mn.nodePort}") + assert_equal(proupservtx_rpc['proUpServTx']['service'], f"127.0.0.1:{self.node_evo.mn.nodePort}") + def test_uniqueness(self): # Empty registrations are not registered as conflicts self.node_evo.register_mn(self, True, "", "", "")