Skip to content

Conversation

@kwvg
Copy link
Collaborator

@kwvg kwvg commented Apr 7, 2025

Additional Information

  • The reason why we track individual entries within MnNetInfo in the unique properties map instead of MnNetInfo is that while MnNetInfo-like objects (because MnNetInfo itself only stores one value) could check internally for duplicates, the uniqueness requirement for addresses is across ProTx'es and therefore, we are concerned not so much as how the addresses are bundled (MnNetInfo) but if the individual addresses (CService) are unique across all known addresses.

  • We cannot use const auto& when iterating through GetEntries() as it uses std::reference_wrapper<const T> and auto will take on the type of const std::reference_wrapper<const T>& instead of the underlying const T& as intended, to trigger the conversion to the underlying reference, we have to explicitly specify the type, hence the usage of const T&.

Breaking Changes

None expected.

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation (note: N/A)
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@kwvg kwvg added this to the 23 milestone Apr 7, 2025
@kwvg kwvg requested a review from PastaPastaPasta April 8, 2025 13:25
@kwvg kwvg removed the request for review from PastaPastaPasta April 21, 2025 16:18
PastaPastaPasta added a commit that referenced this pull request Apr 22, 2025
…up index code, consolidate ProTx versioning and make it friendlier to upgrades

86bec48 refactor: rearrange checks in ProTx RPC wrapper to bail out faster (Kittywhiskers Van Gogh)
14b7cf3 refactor: rename CPro*Tx::GetVersion() to GetMaxVersion(), increase use (Kittywhiskers Van Gogh)
714fb3a refactor: consolidate ProTx versioning, make logic friendly to upgrades (Kittywhiskers Van Gogh)
2f9d65d refactor: cleanup index code, style updates, deduplication (Kittywhiskers Van Gogh)
eaca912 refactor: defer resolving masternode service in CoinJoin code (Kittywhiskers Van Gogh)
e722272 chore: use ProTx hash to identify masternodes in logs when possible (Kittywhiskers Van Gogh)

Pull request description:

  ## Additional Information

  * Dependency for #6627

  * As [dash#6627](#6627) aims to abstract away masternode network information (so far stored as a `CService`) behind an interface in preparation for supporting multiple addresses of different types, it still needs to be exposed to networking logic that actively relies on the "primary" address (i.e. the address used by masternodes to connect to each other). This is done through `MnNetInfo::GetPrimary()`.

    To reduce the `GetPrimary()` invocations needed to a minimum in [dash#6627](#6627), debug log messages have been changed to identify masternodes using the ProTx hash instead of the primary address and `CPendingDsaRequest` has been refactored to delay resolving the primary address, tracking the ProTx hash instead.

  * Currently, valid versions of `CPro*Tx` are expressed as `CPro*Tx::*_VERSION`. This isn't necessary as the `*_VERSION` (currently `{BASIC,LEGACY}_BLS_VERSION`) are the same for all `CPro*Tx`es, so they have been consolidated into a namespaced enum `ProTxVersion`.

    * Additionally, some checks in the codebase assume that are only two versions ([source](https://github.com/dashpay/dash/blob/bcd14b05cec7d94986f114ca17bbdadbee701d9b/src/evo/providertx.cpp#L20), [source](https://github.com/dashpay/dash/blob/bcd14b05cec7d94986f114ca17bbdadbee701d9b/src/evo/providertx.h#L150)), which isn't conducive to adding new versions. Those checks have been modified to allow higher versions.

    * `CPro*Tx::GetVersion()` has been renamed to `CPro*Tx::GetMaxVersion()` as its actually used to check what is the highest _allowed_ version given a set of consensus rules. `GetMaxVersion()` has not been consolidated like `ProTxVersion` as any changes to `addr` (as intended in [dash#6627](#6627)) would only affect `CProRegTx` and `CProUpServTx` (i.e. the remaining ProTx transactions would not be getting a version upgrade).

  * In later PRs, the change to a multiple-address capable implementation is hidden away using a `shared_ptr` to the interface class. To decide _what_ implementation to use, we need to set the version of `CPro*Tx`, as early as possible so that the version can be used to determine the applicable implementation. This is easy enough to do in serialization code but requires additional care when constructing a `CPro*Tx` in-place as it will be initialized with an empty `shared_ptr` and the applicable implementation needs to be explicitly set.

    To avoid problems in those later PRs, some instances of  `CPro*Tx` construction have been reshuffled to set `nVersion` as early as possible.

  ## Breaking Changes

  None expected.

  ## Checklist

  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)**
  - [x] I have added or updated relevant unit/integration/functional/e2e tests **(note: N/A)**
  - [x] I have made corresponding changes to the documentation **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  UdjinM6:
    utACK 86bec48
  knst:
    utACK 86bec48

Tree-SHA512: 3439ea4c51bed09b6147bb0bc26580cbb960ba1856855827d1db01e5303d6d9dce654e87b2982794aa6349a560e73b4b3fd99ca3bb7402e1b95f24a852657ffb
@github-actions
Copy link

This pull request has conflicts, please rebase.

PastaPastaPasta added a commit that referenced this pull request Apr 22, 2025
…h `boost::hana`

0073e9a refactor: replace `CDeterministicMNStateDiff` macros with `boost::hana` (Kittywhiskers Van Gogh)

Pull request description:

  ## Additional Information

  * Dependency for #6627

  * Currently, we rely on a set of macros to use a different set of instructions for (de)serializing `pubKeyOperator` in `CDeterministicMNStateDiff`, one of those macros is the following

    https://github.com/dashpay/dash/blob/bcd14b05cec7d94986f114ca17bbdadbee701d9b/src/evo/dmnstate.h#L219-L226

    If we pretend `DMN_STATE_DIFF_ALL_FIELDS` only pertains to `pubKeyOperator`, the macro would expand as

    ```c++
    if (strcmp("pubKeyOperator", "pubKeyOperator") == 0 && (obj.fields & Field_pubKeyOperator)) {
        SER_READ(obj, read_pubkey = true);
        READWRITE(CBLSLazyPublicKeyVersionWrapper(const_cast<CBLSLazyPublicKey&>(obj.state.pubKeyOperator), obj.state.nVersion == CProRegTx::LEGACY_BLS_VERSION));
    } else if (obj.fields & Field_pubKeyOperator) READWRITE(obj.state.pubKeyOperator);
    ```

    Even though `READWRITE(obj.state.pubKeyOperator)` is _logically_ unreachable, it is something the compiler still has to evaluate and it can because `READWRITE(obj.state.pubKeyOperator)` is still a valid expression.

    But if we need to carve out a similar different rule in a later PR for `newThing` where `newThing` is a `std::shared_ptr<Interface>` that is implemented by the serializable type `Implementation`, the unreachable but still evaluable expression `READWRITE(obj.state.newThing)` cannot be evaluated as you _cannot_ do anything with a pure virtual class, which `Interface` is even though the code right before it uses a wrapper to handle `newThing` correctly.

    To sidestep this issue, we need to be able to `constexpr` evaluate what field is being (de)serialized and decide the (de)serialization logic for it accordingly, which will _exclude_ all other logic that doesn't apply _at compile time_. The current macro-based solution doesn't allow for that.

    While `std::tuple` allows for storing a heterogenous collection of elements, iterating through it proves to be difficult. `std::apply` proves to be too restrictive for what we need to do ([source](https://stackoverflow.com/a/54053084)) and the capability needed to do this properly, "expansion statements" could be available in C++26 ([source](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2996r0.html)), which is a long time from now.

    So, our best option is to use a library that specializes in working with heterogenous collections and thankfully, such a library is already available in Boost called Hana ([source](https://www.boost.org/doc/libs/1_81_0/libs/hana/doc/html/index.html)) and it is headers-only ([source](https://www.boost.org/doc/libs/1_81_0/more/getting_started/unix-variants.html#header-only-libraries), list of all libraries that need building, Hana is not on the list) and is therefore, already available to us.

  ## Breaking Changes

  None expected.

  ## Checklist

  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)**
  - [x] I have added or updated relevant unit/integration/functional/e2e tests
  - [x] I have made corresponding changes to the documentation **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  UdjinM6:
    utACK 0073e9a

Tree-SHA512: c0b7e4214e6180f755e6d030bc24f7cb0d5ab0d5fb262a6394bc17d60bf4de0be9148cd0b07cd00f5e78c1b07c156d65c54c25c2ac6fa49bf7d2ae9a406650a8
PastaPastaPasta added a commit that referenced this pull request Apr 29, 2025
…ble to object during construction, reduce `GetHash()` usage

f292483 refactor: use empty() instead of comparing against empty string literal (Kittywhiskers Van Gogh)
d30b9ae refactor: reduce ostringstream usage when constructing strings (Kittywhiskers Van Gogh)
7200505 refactor: stop using ostringstream to construct filter strings (Kittywhiskers Van Gogh)
1c4f441 util: implement string padding function (Kittywhiskers Van Gogh)
5bfc4bc refactor: use `UniValue::VOBJ` instead of `setObject()` when possible (Kittywhiskers Van Gogh)
8b09188 refactor: store `tx_hash` instead of calling `GetHash()` repeatedly (Kittywhiskers Van Gogh)

Pull request description:

  ## Additional Information

  * Dependency for #6627

  * We use `std::ostringstream` in `masternodelist` to pad values using `std::setw` ([source](https://github.com/dashpay/dash/blob/bcd14b05cec7d94986f114ca17bbdadbee701d9b/src/rpc/masternode.cpp#L574-L575)) for consistency, this was fine because we didn't plan on removing anything from the stream after it was added.

    But in [dash#6627](#6627), we intend to print multiple addresses and need to remove excess padding after the last entry, which can be trivially done with a `pop_back()` ([source](https://github.com/dashpay/dash/blob/bba9c6dd8e2edbbb83a26763a1d64209409b5b82/src/rpc/masternode.cpp#L569-L572)) but that cannot be done with a `std::ostringstream`. The best that can be done is rewinding the cursor but that doesn't change its contents and at most lets you overwrite it ([source](https://stackoverflow.com/a/26492431)), which is fine when you do have something to overwrite it with but this isn't always the case.

    To get around this, `PadString()` has been implemented and `std::ostringstream` usage has been replaced with constructing a string with `strprintf`.

  ## Breaking Changes

  None expected.

  ## Checklist

  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)**
  - [x] I have added or updated relevant unit/integration/functional/e2e tests
  - [x] I have made corresponding changes to the documentation **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  UdjinM6:
    utACK f292483
  PastaPastaPasta:
    utACK f292483

Tree-SHA512: a3ca9dffc4d13bae80469f669af64d924a9bc6fd02d04832dc1bd07a7016b64973ce41c4dc54dc9c6f580ae92e00edb1cafeeb3b2ee29ae93f2f565ec7f18008
@github-actions
Copy link

This pull request has conflicts, please rebase.

@kwvg kwvg marked this pull request as ready for review April 29, 2025 17:28
@kwvg kwvg changed the title refactor: section off masternode network information to MnNetInfo, set some groundwork for managing multiple entries refactor: section off masternode network information to MnNetInfo, lay some groundwork for managing multiple entries Apr 29, 2025
@coderabbitai
Copy link

coderabbitai bot commented Apr 29, 2025

Walkthrough

This change set introduces a comprehensive migration from using a single network address (CService addr) to a new structure, MnNetInfo, which supports multiple network addresses for masternodes across the codebase. The new MnNetInfo class and its supporting types are implemented in src/evo/netinfo.cpp and declared in src/evo/netinfo.h. All relevant classes, such as CProRegTx, CProUpServTx, CDeterministicMNState, and CSimplifiedMNListEntry, replace their addr member with netInfo and update serialization, deserialization, and equality logic accordingly.

All code that previously accessed or manipulated a masternode's address now uses netInfo methods, most commonly GetPrimary() or GetEntries(), to retrieve addresses. This affects masternode management, validation, quorum handling, connection logic, RPC commands, and UI display. The build system is updated to include the new module, and all test code is refactored to use the new interface, with a new dedicated test suite for MnNetInfo validation. The mempool and uniqueness logic are adapted to handle multiple addresses per masternode, ensuring proper conflict detection and state management. No changes are made to function signatures except for internal template and enum updates to support the new types.

Tip

⚡️ Faster reviews with caching
  • CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.

Enjoy the performance boost—your workflow just got faster.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

🔭 Outside diff range comments (2)
src/evo/simplifiedmns.h (1)

38-44: 💡 Verification agent

🧩 Analysis chain

Guard against empty MnNetInfo & maintain backward-compat fields

MnNetInfo is now the single source of truth for the service address, but neither
CSimplifiedMNListEntry’s ctor nor its (de)serialisation ensure that at least one
entry is present. If netInfo is default-constructed (e.g. when reading pre-fork
data or in fuzz tests) the equality operator and the READWRITE(obj.netInfo, …)
statement will silently process an empty list, while later code assumes a primary
entry always exists (GetPrimary() will CHECK_LOCK-abort).

  1. Add an explicit run-time check (or an assert) in the ctor and deserialiser
    that netInfo.HasEntries() is true.
  2. Consider serialising the legacy CService as a fallback when
    s.GetVersion() < NETINFO_PROTO_VERSION so older peers don’t fail.
+    if ((s.GetType() & SER_NETWORK) && !obj.netInfo.HasEntries()) {
+        throw std::ios_base::failure("MnNetInfo must contain at least one entry");
+    }

Also applies to: 52-63, 71-80


🏁 Script executed:

#!/bin/bash
set -e

# Locate the simplifiedmns.h file
FILE=$(fd simplifiedmns.h | head -n1)
echo "Inspecting file: $FILE"

# Show the class definition and constructor region
echo -e "\n--- Class and constructor snippet ---"
sed -n '1,200p' "$FILE" | sed -n '1,200!d'

# Search for serialization of netInfo
echo -e "\n--- Serialization occurrences of netInfo ---"
rg -n "netInfo" -C3 src/evo

Length of output: 20380


🏁 Script executed:

#!/bin/bash
set -e

# Locate the MnNetInfo class definition and its methods
echo "--- MnNetInfo class definition ---"
rg -n "class MnNetInfo" -C10 src

# Check for any HasEntries method in MnNetInfo
echo -e "\n--- HasEntries or equivalent methods ---"
rg -n -C2 "HasEntries" -g "*.h" src
rg -n -C2 "IsEmpty" -g "*.h" src

# Find the protocol version constant for netInfo serialization
echo -e "\n--- NETINFO_PROTO_VERSION ---"
rg -n "NETINFO_PROTO_VERSION" -C2 src

Length of output: 1178


🏁 Script executed:

#!/bin/bash
set -e

# Show full MnNetInfo class definition to locate methods for entry checks
echo "--- MnNetInfo class definition ---"
sed -n '/class MnNetInfo/,/};/p' src/evo/netinfo.h

# Look for methods that expose entries or primary service
echo -e "\n--- GetEntries and GetPrimary in MnNetInfo ---"
rg -n "GetEntries" -C2 src/evo/netinfo.h
rg -n "GetPrimary" -C2 src/evo/netinfo.h

Length of output: 789


Add runtime guard for empty MnNetInfo using IsEmpty() and handle legacy serialization

The MnNetInfo class doesn’t expose HasEntries()—it uses IsEmpty() to detect a default‐constructed (empty) state. We still need to prevent downstream GetPrimary() calls from aborting when reading old or malformed data, and we should fall back to the legacy CService for pre-protocol data.

• In src/evo/simplifiedmns.h, inside the SerializationOp of CSimplifiedMNListEntry (around lines 75–80), add:

+   // Guard against empty netInfo (default-constructed) on network deserialisation
+   if ((s.GetType() & SER_NETWORK) && obj.netInfo.IsEmpty()) {
+       throw std::ios_base::failure("MnNetInfo must contain at least one service entry");
+   }

• If you need to preserve compatibility with peers before the netInfo‐serialization bump, wrap the READWRITE of obj.netInfo in a version check, e.g.:

if (s.GetVersion() < MY_NETINFO_PROTO_VERSION) {
    // legacy fallback: serialise single CService then construct MnNetInfo
    CService legacyService;
    READWRITE(legacyService);
    obj.netInfo = MnNetInfo(legacyService);
} else {
    READWRITE(obj.netInfo);
}

Define MY_NETINFO_PROTO_VERSION to match the release where netInfo switched from CService to MnNetInfo.

src/txmempool.cpp (1)

694-710: 💡 Verification agent

❓ Verification inconclusive

mapProTxAddresses.emplace() may silently drop duplicates

std::unordered_map::emplace ignores additional inserts with an existing key.
If two different pending ProTx transactions manage to claim the same address
before conflict detection runs, only the first hash is stored and the second
one will never be removed from the map, leaking state.

Safer alternative:

-            mapProTxAddresses.emplace(entry, tx_hash);
+            mapProTxAddresses.insert_or_assign(entry, tx_hash);

Same applies to the CProUpServTx branch below.


Prevent silent drop of duplicate ProTx address mappings

The use of mapProTxAddresses.emplace(entry, tx_hash) will ignore any insert where the key already exists, causing a later removal to miss stale entries and leak state. Replace it with insert_or_assign to ensure the mapping is always updated.

Locations to update in src/txmempool.cpp:

  • In the TRANSACTION_PROVIDER_REGISTER branch (around line 696)
  • In the TRANSACTION_PROVIDER_UPDATE_SERVICE branch (around line 706)

Suggested diff:

-            mapProTxAddresses.emplace(entry, tx_hash);
+            mapProTxAddresses.insert_or_assign(entry, tx_hash);

Apply this change in both branches to guarantee consistent insertion and removal.

🧹 Nitpick comments (9)
src/evo/providertx.h (1)

63-63: Fix the Clang formatting issue.

Clang format differences were found on this line. Please run clang-format to fix the style issues.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 63-63: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/dmnstate.h (1)

98-98: Fix the Clang formatting issues.

Clang format differences were found on lines 98 and 181. Please run clang-format to fix the style issues.

Also applies to: 181-181

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 98-98: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/simplifiedmns.h (1)

71-79: clang-format violations break CI

The CI pipeline (Clang Diff Format Check) flagged this block. Please run
clang-format -i src/evo/simplifiedmns.h (or git clang-format) before pushing
the next revision to avoid rebasing only for style fixes.

src/evo/dmnstate.cpp (1)

28-36: Minor: expensive ToString() call constructed but unused on old log levels

netInfo.ToString() allocates a temporary std::string. In very verbose
debug builds that’s fine, but consider wrapping the whole strprintf in
LogAcceptCategory(BCLog::MASTERNODE) or similar to avoid the cost when the
string is eventually dropped by the compiler.

src/rpc/masternode.cpp (1)

574-600: Run clang-format to satisfy CI

CI reports formatting issues around these blocks. Re-running clang-format
will realign the closing parentheses and spacing inside the lambdas.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 574-574: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.


[error] 585-585: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.


[error] 600-600: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/txmempool.cpp (1)

1397-1404: Loop can be replaced with any_of for clarity

A tiny readability suggestion:

if (std::any_of(proTx.netInfo.Begin(), proTx.netInfo.End(),
                [&](const CService& s){ return mapProTxAddresses.count(s); }))
    return true;
src/test/evo_netinfo_tests.cpp (1)

1-4: Copyright year should be current year.

The copyright year is set to 2025, but should be the current year when the file was created.

-// Copyright (c) 2025 The Dash Core developers
+// Copyright (c) 2024 The Dash Core developers
src/evo/netinfo.cpp (2)

1-4: Copyright year should be current year.

The copyright year is set to 2025, but should be the current year when the file was created.

-// Copyright (c) 2025 The Dash Core developers
+// Copyright (c) 2024 The Dash Core developers

11-21: Consider initializing main params during startup rather than on-demand.

The MainParams() function initializes g_main_params on the first call with a TODO comment about real args. Consider initializing this during application startup to avoid potential thread safety issues with lazy initialization.

 namespace {
 static std::unique_ptr<const CChainParams> g_main_params{nullptr};
 
 bool IsNodeOnMainnet() { return Params().NetworkIDString() == CBaseChainParams::MAIN; }
 const CChainParams& MainParams()
 {
-    // TODO: use real args here
-    if (!g_main_params) g_main_params = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN);
+    assert(g_main_params != nullptr); // Should be initialized during startup
     return *g_main_params;
 }
 } // anonymous namespace
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 420615c and f27f931.

📒 Files selected for processing (27)
  • src/Makefile.am (2 hunks)
  • src/Makefile.test.include (1 hunks)
  • src/coinjoin/client.cpp (6 hunks)
  • src/evo/core_write.cpp (3 hunks)
  • src/evo/deterministicmns.cpp (12 hunks)
  • src/evo/deterministicmns.h (3 hunks)
  • src/evo/dmnstate.cpp (2 hunks)
  • src/evo/dmnstate.h (6 hunks)
  • src/evo/netinfo.cpp (1 hunks)
  • src/evo/netinfo.h (1 hunks)
  • src/evo/providertx.cpp (2 hunks)
  • src/evo/providertx.h (5 hunks)
  • src/evo/simplifiedmns.cpp (3 hunks)
  • src/evo/simplifiedmns.h (4 hunks)
  • src/llmq/utils.cpp (2 hunks)
  • src/masternode/node.cpp (2 hunks)
  • src/masternode/utils.cpp (1 hunks)
  • src/net.cpp (5 hunks)
  • src/qt/masternodelist.cpp (1 hunks)
  • src/rpc/evo.cpp (2 hunks)
  • src/rpc/masternode.cpp (2 hunks)
  • src/rpc/quorums.cpp (1 hunks)
  • src/test/block_reward_reallocation_tests.cpp (1 hunks)
  • src/test/evo_deterministicmns_tests.cpp (7 hunks)
  • src/test/evo_netinfo_tests.cpp (1 hunks)
  • src/test/evo_simplifiedmns_tests.cpp (3 hunks)
  • src/txmempool.cpp (7 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (6)
src/test/evo_simplifiedmns_tests.cpp (1)
src/test/util/setup_common.h (1)
  • RegTestingSetup (127-128)
src/evo/simplifiedmns.h (2)
src/evo/netinfo.h (4)
  • rhs (46-46)
  • rhs (46-46)
  • rhs (47-47)
  • rhs (47-47)
src/evo/simplifiedmns.cpp (2)
  • rhs (137-146)
  • rhs (137-137)
src/test/evo_netinfo_tests.cpp (1)
src/test/util/setup_common.h (1)
  • RegTestingSetup (127-128)
src/evo/netinfo.cpp (4)
src/evo/netinfo.h (5)
  • ValidateService (59-59)
  • service (40-40)
  • service (54-54)
  • m_addr (57-57)
  • m_addr (62-62)
src/evo/dmnstate.cpp (2)
  • ToString (16-36)
  • ToString (16-16)
src/evo/providertx.cpp (8)
  • ToString (82-98)
  • ToString (82-82)
  • ToString (112-125)
  • ToString (112-112)
  • ToString (148-158)
  • ToString (148-148)
  • ToString (174-178)
  • ToString (174-174)
src/evo/simplifiedmns.cpp (2)
  • ToString (53-73)
  • ToString (53-53)
src/evo/simplifiedmns.cpp (2)
src/evo/dmnstate.h (1)
  • nVersion (111-119)
src/evo/dmnstate.cpp (2)
  • obj (40-40)
  • obj (71-71)
src/net.cpp (2)
test/functional/test_framework/messages.py (1)
  • CAddress (252-375)
src/net.h (4)
  • ForNode (1310-1313)
  • ForNode (1310-1310)
  • ForNode (1316-1319)
  • ForNode (1316-1316)
🪛 GitHub Actions: Clang Diff Format Check
src/masternode/utils.cpp

[error] 77-77: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/llmq/utils.cpp

[error] 823-823: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.


[error] 872-872: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/providertx.cpp

[error] 91-91: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.


[error] 120-120: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/test/evo_simplifiedmns_tests.cpp

[error] 34-34: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/providertx.h

[error] 63-63: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/dmnstate.h

[error] 98-98: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.


[error] 181-181: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/rpc/masternode.cpp

[error] 574-574: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.


[error] 585-585: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.


[error] 600-600: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/simplifiedmns.h

[error] 51-51: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/test/evo_netinfo_tests.cpp

[error] 21-21: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/deterministicmns.h

[error] 394-394: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/netinfo.cpp

[error] 46-46: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.


[error] 72-72: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/simplifiedmns.cpp

[error] 67-67: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/netinfo.h

[error] 10-10: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.


[error] 46-46: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/deterministicmns.cpp

[error] 840-840: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

🪛 Cppcheck (2.10-2)
src/test/evo_simplifiedmns_tests.cpp

[error] 13-13: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)

src/test/evo_netinfo_tests.cpp

[error] 14-14: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)

⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: mac-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: linux64_multiprocess-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
🔇 Additional comments (64)
src/qt/masternodelist.cpp (1)

224-227: Properly updated to use the new MnNetInfo structure.

The code correctly updates the way masternode network addresses are accessed, using the new MnNetInfo structure's GetPrimary() method instead of directly accessing the previous addr field.

src/Makefile.test.include (1)

116-116: Added test for the new MnNetInfo functionality.

Good addition of a specific test file for the new MnNetInfo functionality to ensure proper test coverage for the refactoring.

src/test/block_reward_reallocation_tests.cpp (1)

120-120: Improved validation with the new MnNetInfo API.

The test has been updated to use the new MnNetInfo API, with added validation through BOOST_CHECK_EQUAL to verify that the address was successfully added. This is a good improvement over the previous direct assignment.

src/rpc/quorums.cpp (1)

206-206: Updated to use the new MnNetInfo structure for service address.

The code correctly accesses the masternode service address through the new MnNetInfo structure's GetPrimary() method, maintaining compatibility with the rest of the codebase's refactoring.

src/Makefile.am (2)

194-194: Correctly added the new netinfo.h header file to the build system.

The addition of the evo/netinfo.h to BITCOIN_CORE_H is necessary for making the new MnNetInfo class available throughout the codebase. This change properly integrates the header into the build system.


778-778: Correctly added the new netinfo.cpp source file to the build system.

The addition of evo/netinfo.cpp to libbitcoin_common_a_SOURCES ensures the implementation of the MnNetInfo class is compiled into the common library. This is the appropriate location given the usage of this class across different components of the codebase.

src/evo/core_write.cpp (3)

9-9: Properly included the new netinfo header.

The inclusion of <evo/netinfo.h> is correct and necessary to access the MnNetInfo class definitions used in this file.


70-70: Updated JSON serialization to use the new network information structure.

The change correctly adapts the JSON serialization to use netInfo.GetPrimary().ToStringAddrPort() instead of direct addr access, maintaining the same output format while supporting the new architecture for potentially multiple network addresses.


117-117: Updated JSON serialization for CProUpServTx class.

Similar to the change for CProRegTx, this update correctly adapts the JSON serialization to use the new netInfo structure, maintaining consistent handling across different transaction types.

src/test/evo_simplifiedmns_tests.cpp (4)

13-13: Fixture upgrade is appropriate

Changing from BasicTestingSetup to RegTestingSetup is appropriate since the PR aims to improve address validation. The regtest network environment provides proper context for validating CService objects.

🧰 Tools
🪛 Cppcheck (2.10-2)

[error] 13-13: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)


20-20: Improved address generation

Starting the loop from 1 instead of 0 prevents the creation of invalid "0.0.0.0:0" addresses, which is in line with the PR objectives to improve address validation.


25-25: Verify IP address format is sufficient

While you've changed to start indexes at 1 to avoid "0.0.0.0:0", the IP addresses still use zeros in the first three octets (e.g., "0.0.0.1:1").

Verify that these addresses are valid in your context. If you need actual valid IP addresses for proper testing, consider using something like:

-BOOST_CHECK_EQUAL(smle.netInfo.AddEntry(strprintf("%d.%d.%d.%d:%d", 0, 0, 0, i, i)), NetInfoStatus::Success);
+BOOST_CHECK_EQUAL(smle.netInfo.AddEntry(strprintf("127.0.0.%d:%d", i, i)), NetInfoStatus::Success);

52-52: Updated hash values consistent with code changes

The updated hash values and merkle root are necessary consequences of the address changes and migration to MnNetInfo. These changes ensure the tests pass with the new implementation.

Also applies to: 65-65

src/net.cpp (7)

3677-3700: Correctly migrated from direct addr access to netInfo.GetPrimary()

The code has been properly updated to use netInfo.GetPrimary() instead of directly accessing addr. This ensures consistency with the broader refactoring of masternode network information to use the new MnNetInfo structure.


3743-3746: Address retrieval properly updated to use new MnNetInfo structure

This condition has been correctly updated to check connection status using the primary address from the netInfo structure rather than directly accessing the addr field.


3752-3754: Log message appropriately updated to use netInfo.GetPrimary()

Log message has been properly updated to retrieve the address from the new MnNetInfo structure.


3763-3764: Probe log message correctly updated to use new address access pattern

The log message for probing a masternode has been properly updated to use netInfo.GetPrimary() for address retrieval.


3779-3780: Masternode connection function updated to use primary address from netInfo

The function call to OpenMasternodeConnection has been correctly modified to use the primary address from the masternode's netInfo structure.


3781-3787: ForNode method call updated to use the proper address retrieval

The call to ForNode has been properly updated to use netInfo.GetPrimary() to check connection status after an attempt to connect.


3788-3792: Connection failure log updated to use new address access pattern

The log message for connection failures has been properly updated to use the primary address from netInfo for consistent logging.

src/evo/providertx.h (5)

9-9: Header inclusion for the new MnNetInfo type added correctly.

The new #include <evo/netinfo.h> header inclusion is properly added to support the MnNetInfo type used in the refactoring.


44-44: CProRegTx field changed from addr to netInfo.

The single CService addr member has been correctly replaced with MnNetInfo netInfo as part of the refactoring to support multiple network addresses.


70-70: Serialization updated for netInfo.

Serialization of CProRegTx has been properly updated to use obj.netInfo instead of the previous obj.addr.


113-113: CProUpServTx field changed from addr to netInfo.

The single CService addr member has been correctly replaced with MnNetInfo netInfo as part of the refactoring to support multiple network addresses.


136-136: Serialization updated for netInfo.

Serialization of CProUpServTx has been properly updated to use obj.netInfo instead of the previous obj.addr.

src/test/evo_deterministicmns_tests.cpp (7)

109-109: Network address properly added through netInfo.AddEntry()

The test properly uses the new netInfo.AddEntry() method instead of direct assignment to addr. Good practice to verify the success of the addition with BOOST_CHECK_EQUAL.


131-131: Network address properly added through netInfo.AddEntry()

The test properly uses the new netInfo.AddEntry() method instead of direct assignment to addr for service transactions. The success verification is consistent with the approach used in other tests.


519-519: Address verification correctly updated to use netInfo.GetPrimary()

The test now properly accesses the port through netInfo.GetPrimary().GetPort() instead of directly from addr, maintaining backward compatibility while using the new structure.


577-577: Address verification correctly updated to use netInfo.GetPrimary()

The test now properly accesses the port through netInfo.GetPrimary().GetPort() instead of directly from addr, maintaining consistency with the overall refactoring approach.


637-638: Network address properly added through netInfo.AddEntry() in mempool test

The function test for mempool organization correctly uses the new netInfo.AddEntry() method with success verification, consistent with the structure changes.


711-711: Network address properly added through netInfo.AddEntry() in dual proTx test

The function test for dual ProRegTx in mempool correctly uses the new netInfo.AddEntry() method with success verification, aligned with the structure changes.


779-779: Network address properly added through netInfo.AddEntry() in verifyDB test

The function test for DB verification correctly uses the new netInfo.AddEntry() method with success verification, maintaining consistency throughout the test suite.

src/evo/dmnstate.h (6)

57-57: CDeterministicMNState field changed from addr to netInfo.

The single CService addr member has been correctly replaced with MnNetInfo netInfo in the CDeterministicMNState class as part of the refactoring.


72-72: Constructor initialization updated for netInfo.

The class constructor now properly initializes netInfo from proTx.netInfo, maintaining the expected behavior during object construction.


103-103: Serialization updated for netInfo.

Serialization has been properly updated to use netInfo instead of the previous addr field.


115-115: ResetOperatorFields updated for netInfo.

The ResetOperatorFields method now correctly uses netInfo.Clear() instead of addr = CService() to reset the network information.


169-169: CDeterministicMNStateDiff enum field renamed to Field_netInfo.

The enum value Field_addr has been renamed to Field_netInfo while maintaining the same bit value (0x0800), ensuring serialization compatibility with existing data.


201-201: Member reference updated in state diff for netInfo.

The member reference in the state differencing code has been updated to use netInfo instead of addr.

src/masternode/node.cpp (2)

149-149: Local address comparison updated to use netInfo.GetPrimary()

The code correctly updates the comparison between the local service address and the masternode's address to use netInfo.GetPrimary() instead of directly accessing addr. This maintains the same functionality while using the new network info structure.


204-204: Address change detection updated to use netInfo.GetPrimary()

The code that detects changes in a masternode's IP address now correctly compares netInfo.GetPrimary() values instead of comparing addr directly. This maintains consistency with the overall refactoring approach.

src/test/evo_netinfo_tests.cpp (2)

14-20: LGTM: Helper validation function is well-structured.

The ValidateGetEntries helper function appropriately checks the size of entries returned by the GetEntries() method, which will be useful throughout the test cases.

🧰 Tools
🪛 Cppcheck (2.10-2)

[error] 14-14: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)


21-53:

❓ Verification inconclusive

Test structure looks good with comprehensive validation rules.

The test case covers a wide range of validation scenarios for the MnNetInfo::AddEntry method, including valid IPv4 addresses, invalid ports, invalid IP formats, and disallowed address types.


🏁 Script executed:

#!/bin/bash
# Run clang-format on the file to fix formatting issues flagged by the pipeline
clang-format -i src/test/evo_netinfo_tests.cpp

Length of output: 151


Comprehensive MnNetInfo test, but formatting needs manual fix

Your test covers all key MnNetInfo::AddEntry validation scenarios and looks solid. However, the CI pipeline reported formatting issues in src/test/evo_netinfo_tests.cpp, and clang-format isn’t available in this environment. Please run the following locally and commit the updated file:

clang-format -i src/test/evo_netinfo_tests.cpp

Once formatted, re-run the pipeline to confirm there are no style errors.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 21-21: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/evo/netinfo.cpp (4)

23-45: Solid validation implementation for node services.

The ValidateService method correctly enforces important validation rules for network services: valid IPv4 format, routability checks, and appropriate port usage based on network type.


59-68: GetEntries implementation handles current single-entry model well.

The method returns a list containing the single address if not empty, with a helpful comment explaining the empty case behavior. This design will support future extension to multiple entries.


70-75: ToString method delivers clear formatting of network details.

The method provides a well-structured string representation of the network info, including IP address and port, with appropriate padding for caller formatting.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 72-72: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.


47-57:

❓ Verification inconclusive

Proper address parsing and validation in AddEntry.

The AddEntry method effectively parses the input string into a CService object and applies validation before storing it. The method handles errors appropriately and returns the validation status.


🏁 Script executed:

#!/bin/bash
# Run clang-format on the file to fix formatting issues flagged by the pipeline
clang-format -i src/evo/netinfo.cpp

Length of output: 140


Manual formatting required for src/evo/netinfo.cpp

The CI pipeline indicates formatting issues in src/evo/netinfo.cpp, but clang-format isn’t available in this environment. Please ensure the file is formatted according to the project’s style guidelines:

  • Run clang-format -i src/evo/netinfo.cpp locally (or use your configured formatter).
  • Verify that there are no remaining style violations before merging.
src/evo/deterministicmns.h (4)

403-422: Improved initialization safety with value-initialized nullValue.

The change from uninitialized declaration to value-initialized declaration (static const T nullValue{};) ensures proper default construction for any type used in the unique property templates.


423-442: Consistent value initialization applied to DeleteUniqueProperty.

The same pattern of using value initialization for nullValue is consistently applied here, improving type safety.


443-459: UpdateUniqueProperty completes consistent value initialization pattern.

The value initialization pattern is completed in this method, providing consistent behavior across all unique property management methods.


393-402:

❓ Verification inconclusive

Added type restriction for MnNetInfo in GetUniquePropertyHash.

The static assertion now properly prevents MnNetInfo from being used as a template parameter alongside CBLSPublicKey, aligning with the PR's goal of handling network address uniqueness more specifically.


🏁 Script executed:

#!/bin/bash
# Run clang-format on the file to fix formatting issues flagged by the pipeline
clang-format -i src/evo/deterministicmns.h

Length of output: 147


Type Restriction Added for MnNetInfo in GetUniquePropertyHash

The static_assert now prevents both CBLSPublicKey and MnNetInfo from being used as template parameters, which aligns with the PR’s intent to handle network‐address uniqueness explicitly.

• File: src/evo/deterministicmns.h
• Lines: 393–402
• Verify that the following line is present:

DMNL_NO_TEMPLATE(MnNetInfo);

• Please run clang-format -i src/evo/deterministicmns.h locally and confirm the file passes CI formatting checks.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 394-394: Clang format differences found. Code formatting does not match the expected style. Please run clang-format to fix.

src/coinjoin/client.cpp (6)

186-186: LGTM: Network address access updated to use MnNetInfo.

Changed from direct access to addr to using the getter method GetPrimary() on the new netInfo structure, maintaining the same functionality.


1106-1110: LGTM: Consistent update to use netInfo.GetPrimary().

Changed from direct access to addr to using the getter method GetPrimary() on the new netInfo structure when checking if a masternode connection is requested.


1178-1183: LGTM: Updated masternode connection check to use netInfo.GetPrimary().

Similar to previous changes, updated to use netInfo.GetPrimary() instead of direct addr access, maintaining functionality.


1218-1224: LGTM: Updated masternode address retrieval with GetPrimary().

Changed from direct access to addr to using the getter method GetPrimary() when retrieving the masternode's address for connection.


1820-1827: LGTM: Updated node connection address with GetPrimary().

Changed the connection target from direct addr access to using netInfo.GetPrimary() in the ForNode call.


1876-1877: LGTM: Updated JSON info generation with netInfo.GetPrimary().

Changed the address used in JSON output from direct addr access to using netInfo.GetPrimary(), maintaining the same functionality.

src/evo/simplifiedmns.cpp (2)

33-33: Constructor updated to use new netInfo field

The masternode constructor now correctly initializes netInfo from dmn.pdmnState->netInfo instead of the previous service member, aligning with the refactoring to use the new MnNetInfo class.


82-82: JSON representation updated for network information

The ToJson() method now correctly uses netInfo.GetPrimary().ToStringAddrPort() instead of the previous service.ToStringAddrPort() for the "service" JSON key, maintaining compatibility with existing JSON interfaces while using the new MnNetInfo structure.

src/rpc/evo.cpp (2)

684-686: Improved error handling with address validation

The refactored code now uses the MnNetInfo.AddEntry() method instead of direct address assignment, with better error handling that includes specific error messages from NISToString(). This provides more informative feedback when invalid addresses are provided.


977-979: Consistent use of MnNetInfo in update service RPC

Similar to the registration function, the service update function now properly uses MnNetInfo.AddEntry() with improved error reporting. This provides consistent validation and error handling across different RPC functions.

src/evo/netinfo.h (4)

1-4: LGTM: Proper copyright and license header

The file includes appropriate copyright and license information.


13-31: Well-defined status enumeration with string conversion

The NetInfoStatus enum and NISToString function provide a clean way to represent and communicate validation results. The deliberate omission of a default case in the switch statement is good practice as it enables the compiler to warn about missing enum values.


32-32: Type alias for service list simplifies future expansion

Using std::reference_wrapper<const CService> with a type alias CServiceList is a good design choice. It allows returning references to internal objects without ownership transfer and prepares for future multiple address support.


64-66: LGTM: Proper file termination

The file correctly ends with the closing include guard.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
src/evo/deterministicmns.cpp (2)

469-475: ⚠️ Potential issue

Skip sentinel CService() values when registering unique netInfo entries

When registering unique network entries, default-constructed CService() values should be skipped to prevent failures when processing nodes with empty/placeholder entries.

for (const CService& entry : dmn->pdmnState->netInfo.GetEntries()) {
-    if (!AddUniqueProperty(*dmn, entry)) {
+    if (entry != CService() && !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())));
    }
}

This fix is important because without it, masternodes with empty address lists could fail to register once another such masternode exists, as the same default value would be treated as a global unique key.


590-596: ⚠️ Potential issue

Symmetry with AddMN / UpdateMN: skip default CService() when erasing

The removal path should also skip default-constructed CService() values for consistency with the update path.

for (const CService& entry : dmn->pdmnState->netInfo.GetEntries()) {
-    if (!DeleteUniqueProperty(*dmn, entry)) {
+    if (entry != CService() && !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())));
    }
}

Keeping the guard consistent across add/update/remove avoids hard-to-trace runtime exceptions when trying to delete keys that were never added.

🧹 Nitpick comments (3)
src/test/evo_simplifiedmns_tests.cpp (1)

1-1: Clang formatting issue reported

The pipeline shows a Clang format check failure. This doesn't affect functionality but should be fixed to maintain consistent code style.

Run clang-format on this file to fix formatting issues before merging.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 1-1: Clang format differences found. Code formatting does not match the required style.

src/test/evo_netinfo_tests.cpp (1)

1-3: Future copyright year

The copyright year is set to 2025, which is in the future.

-// Copyright (c) 2025 The Dash Core developers
+// Copyright (c) 2024 The Dash Core developers
src/evo/deterministicmns.cpp (1)

524-524: Fix printf specifier in error message

The strprintf call should use %s for string values, not %d which is for integers.

-    return strprintf("duplicate (%s)", new_entry.ToStringAddrPort());
+    return strprintf("duplicate (%s)", new_entry.ToStringAddrPort());

Note: This actually appears to be correct in the current code (%s), so no change is needed. This was flagged in a previous review comment but has been fixed.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f27f931 and 132238f.

📒 Files selected for processing (27)
  • src/Makefile.am (2 hunks)
  • src/Makefile.test.include (1 hunks)
  • src/coinjoin/client.cpp (6 hunks)
  • src/evo/core_write.cpp (3 hunks)
  • src/evo/deterministicmns.cpp (12 hunks)
  • src/evo/deterministicmns.h (3 hunks)
  • src/evo/dmnstate.cpp (2 hunks)
  • src/evo/dmnstate.h (6 hunks)
  • src/evo/netinfo.cpp (1 hunks)
  • src/evo/netinfo.h (1 hunks)
  • src/evo/providertx.cpp (2 hunks)
  • src/evo/providertx.h (5 hunks)
  • src/evo/simplifiedmns.cpp (3 hunks)
  • src/evo/simplifiedmns.h (4 hunks)
  • src/llmq/utils.cpp (2 hunks)
  • src/masternode/node.cpp (2 hunks)
  • src/masternode/utils.cpp (1 hunks)
  • src/net.cpp (5 hunks)
  • src/qt/masternodelist.cpp (1 hunks)
  • src/rpc/evo.cpp (2 hunks)
  • src/rpc/masternode.cpp (4 hunks)
  • src/rpc/quorums.cpp (1 hunks)
  • src/test/block_reward_reallocation_tests.cpp (1 hunks)
  • src/test/evo_deterministicmns_tests.cpp (7 hunks)
  • src/test/evo_netinfo_tests.cpp (1 hunks)
  • src/test/evo_simplifiedmns_tests.cpp (3 hunks)
  • src/txmempool.cpp (7 hunks)
✅ Files skipped from review due to trivial changes (5)
  • src/Makefile.am
  • src/llmq/utils.cpp
  • src/evo/providertx.cpp
  • src/masternode/node.cpp
  • src/rpc/masternode.cpp
🚧 Files skipped from review as they are similar to previous changes (19)
  • src/Makefile.test.include
  • src/qt/masternodelist.cpp
  • src/rpc/quorums.cpp
  • src/masternode/utils.cpp
  • src/test/block_reward_reallocation_tests.cpp
  • src/evo/core_write.cpp
  • src/txmempool.cpp
  • src/evo/simplifiedmns.h
  • src/evo/dmnstate.cpp
  • src/evo/dmnstate.h
  • src/evo/providertx.h
  • src/test/evo_deterministicmns_tests.cpp
  • src/net.cpp
  • src/rpc/evo.cpp
  • src/evo/netinfo.cpp
  • src/evo/deterministicmns.h
  • src/evo/netinfo.h
  • src/evo/simplifiedmns.cpp
  • src/coinjoin/client.cpp
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/test/evo_netinfo_tests.cpp (1)
src/test/util/setup_common.h (1)
  • RegTestingSetup (127-128)
src/test/evo_simplifiedmns_tests.cpp (1)
src/test/util/setup_common.h (1)
  • RegTestingSetup (127-128)
🪛 Cppcheck (2.10-2)
src/test/evo_netinfo_tests.cpp

[error] 35-35: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)

src/test/evo_simplifiedmns_tests.cpp

[error] 13-13: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)

🪛 GitHub Actions: Clang Diff Format Check
src/test/evo_simplifiedmns_tests.cpp

[error] 1-1: Clang format differences found. Code formatting does not match the required style.

⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: mac-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: linux64_multiprocess-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
🔇 Additional comments (15)
src/test/evo_simplifiedmns_tests.cpp (5)

13-13: Test fixture updated to RegTestingSetup

Updating from BasicTestingSetup to RegTestingSetup is appropriate for this test as it provides the necessary network configuration for validating the masternode network addresses.

🧰 Tools
🪛 Cppcheck (2.10-2)

[error] 13-13: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)


20-20: Addressing validation issue by starting from index 1

Starting the loop from index 1 instead of 0 prevents invalid IP addresses like "0.0.0.0" from being used, which is consistent with the PR objectives of improving validation.


25-25: Updated to use new MnNetInfo structure

The code now uses netInfo.AddEntry() instead of directly assigning to service, reflecting the migration to the new MnNetInfo structure. The check for NetInfoStatus::Success ensures proper validation.


52-52: Updated hash value for new test data

The hash value was updated to match the expected outcome with the new data format using netInfo instead of service.


65-65: Updated Merkle root for new test data

The expected Merkle root was updated to match the changes in the underlying data structure.

src/test/evo_netinfo_tests.cpp (3)

14-33: Comprehensive network validation test cases

The test vector covers important validation scenarios including valid addresses, invalid ports, invalid IP formats, disallowed IPv6 addresses, domain names, and missing address parts. This provides good coverage for the new validation rules.


37-40: Helper function for entry validation

The ValidateGetEntries helper function provides a clean way to verify the expected number of entries in a MnNetInfo object, making the tests more readable.


42-54: Thorough validation testing

The test case properly validates both success and failure cases for AddEntry(), ensuring that failed validation results in no entries being added, while successful validation results in exactly one entry.

src/evo/deterministicmns.cpp (7)

811-815: Validation of unique network entries for ProRegTx

The code now validates each entry in the netInfo object for uniqueness, instead of just checking a single address, which is consistent with the multi-entry approach of MnNetInfo.


824-827: Updated empty check using netInfo.IsEmpty()

The empty service check now uses netInfo.IsEmpty() rather than comparing against a default CService(), which is cleaner and more consistent with the new structure.


842-847: Validation of unique network entries for ProUpServTx

Similar to the ProRegTx validation, the code now checks each entry in the netInfo object for uniqueness, ensuring that no address is reused across masternodes.


861-861: Migrated from addr to netInfo in state updates

The state update now assigns the entire netInfo structure instead of just the addr field, properly handling the multi-entry network information.


1204-1213: Improved service validation with detailed error states

The CheckService template function has been rewritten to validate the entire netInfo structure and provide detailed error states for invalid input or port issues, enhancing the robustness of validation.


1247-1248: Updated platform port duplication checks for primary netInfo entry

The platform port duplication check now compares against the port of the primary entry in netInfo instead of the single addr port, maintaining compatibility with the new structure.


512-529: ⚠️ Potential issue

Same sentinel check needed in updateNetInfo lambda

Similar to the AddMN function, the updateNetInfo lambda should skip default CService() values when adding new entries.

for (const CService& new_entry : pdmnState->netInfo.GetEntries()) {
-    if (new_entry != CService() && !AddUniqueProperty(*dmn, new_entry)) {
+    if (new_entry != CService() && !AddUniqueProperty(*dmn, new_entry)) {
        return strprintf("duplicate (%s)", new_entry.ToStringAddrPort());
    }
}

The check is present (so no change needed), but I want to verify that this consistent with the other parts of the code.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/test/evo_netinfo_tests.cpp (1)

37-40: Helper function has limited utility in current form

The ValidateGetEntries function only wraps a single check and is used in just one place. While it's mentioned that this will be expanded in subsequent PRs, consider adding a brief comment explaining its future use to provide context for other developers.

void ValidateGetEntries(const CServiceList& entries, const size_t expected_size)
{
    BOOST_CHECK_EQUAL(entries.size(), expected_size);
+    // Note: This helper will be expanded in subsequent PRs
}
🧹 Nitpick comments (1)
src/test/evo_simplifiedmns_tests.cpp (1)

1-72:

❓ Verification inconclusive

Code formatting issue detected

The pipeline reports a clang format issue in this file. The code should be formatted according to the project's style guide.


🏁 Script executed:

#!/bin/bash
# Run clang-format to identify formatting issues
if command -v clang-format >/dev/null 2>&1; then
  clang-format --style=file -n --Werror src/test/evo_simplifiedmns_tests.cpp
  echo "You can fix this by running: clang-format -i --style=file src/test/evo_simplifiedmns_tests.cpp"
else
  echo "clang-format not found. Please install it or use the project's formatting tools."
fi

Length of output: 199


Install clang-format and apply project style

Please ensure src/test/evo_simplifiedmns_tests.cpp is formatted according to our clang-format style. Since the CI environment couldn’t run clang-format, manually install it and run:

clang-format -i --style=file src/test/evo_simplifiedmns_tests.cpp

then commit the resulting changes.

🧰 Tools
🪛 Cppcheck (2.10-2)

[error] 13-13: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)

🪛 GitHub Actions: Clang Diff Format Check

[error] 1-1: Clang format differences found. Code formatting does not match the expected style.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 489b9e2 and 0fa7ce2.

📒 Files selected for processing (27)
  • src/Makefile.am (2 hunks)
  • src/Makefile.test.include (1 hunks)
  • src/coinjoin/client.cpp (6 hunks)
  • src/evo/core_write.cpp (3 hunks)
  • src/evo/deterministicmns.cpp (12 hunks)
  • src/evo/deterministicmns.h (3 hunks)
  • src/evo/dmnstate.cpp (2 hunks)
  • src/evo/dmnstate.h (6 hunks)
  • src/evo/netinfo.cpp (1 hunks)
  • src/evo/netinfo.h (1 hunks)
  • src/evo/providertx.cpp (2 hunks)
  • src/evo/providertx.h (5 hunks)
  • src/evo/simplifiedmns.cpp (3 hunks)
  • src/evo/simplifiedmns.h (4 hunks)
  • src/llmq/utils.cpp (2 hunks)
  • src/masternode/node.cpp (2 hunks)
  • src/masternode/utils.cpp (1 hunks)
  • src/net.cpp (5 hunks)
  • src/qt/masternodelist.cpp (1 hunks)
  • src/rpc/evo.cpp (2 hunks)
  • src/rpc/masternode.cpp (4 hunks)
  • src/rpc/quorums.cpp (1 hunks)
  • src/test/block_reward_reallocation_tests.cpp (1 hunks)
  • src/test/evo_deterministicmns_tests.cpp (7 hunks)
  • src/test/evo_netinfo_tests.cpp (1 hunks)
  • src/test/evo_simplifiedmns_tests.cpp (3 hunks)
  • src/txmempool.cpp (7 hunks)
✅ Files skipped from review due to trivial changes (2)
  • src/Makefile.test.include
  • src/evo/dmnstate.cpp
🚧 Files skipped from review as they are similar to previous changes (23)
  • src/evo/core_write.cpp
  • src/masternode/utils.cpp
  • src/qt/masternodelist.cpp
  • src/Makefile.am
  • src/evo/providertx.cpp
  • src/llmq/utils.cpp
  • src/evo/providertx.h
  • src/rpc/masternode.cpp
  • src/rpc/quorums.cpp
  • src/test/block_reward_reallocation_tests.cpp
  • src/evo/dmnstate.h
  • src/evo/simplifiedmns.h
  • src/masternode/node.cpp
  • src/txmempool.cpp
  • src/test/evo_deterministicmns_tests.cpp
  • src/rpc/evo.cpp
  • src/evo/deterministicmns.h
  • src/evo/simplifiedmns.cpp
  • src/coinjoin/client.cpp
  • src/evo/netinfo.cpp
  • src/evo/netinfo.h
  • src/net.cpp
  • src/evo/deterministicmns.cpp
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/test/evo_netinfo_tests.cpp (1)
src/test/util/setup_common.h (1)
  • RegTestingSetup (127-128)
src/test/evo_simplifiedmns_tests.cpp (1)
src/test/util/setup_common.h (1)
  • RegTestingSetup (127-128)
🪛 Cppcheck (2.10-2)
src/test/evo_netinfo_tests.cpp

[error] 35-35: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)

src/test/evo_simplifiedmns_tests.cpp

[error] 13-13: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)

🪛 GitHub Actions: Clang Diff Format Check
src/test/evo_simplifiedmns_tests.cpp

[error] 1-1: Clang format differences found. Code formatting does not match the expected style.

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: x86_64-apple-darwin / Build depends
  • GitHub Check: x86_64-w64-mingw32 / Build depends
  • GitHub Check: x86_64-pc-linux-gnu_nowallet / Build depends
  • GitHub Check: arm-linux-gnueabihf / Build depends
  • GitHub Check: x86_64-pc-linux-gnu / Build depends
  • GitHub Check: x86_64-pc-linux-gnu_multiprocess / Build depends
🔇 Additional comments (9)
src/test/evo_netinfo_tests.cpp (4)

1-13: Well-structured new test file for the MnNetInfo class

This new test file provides a good foundation for testing the MnNetInfo class functionality, particularly its input validation through the AddEntry method. The setup includes all necessary headers and is organized within the appropriate test fixture.


14-33: Comprehensive test cases for network address validation

The test vector includes a wide range of important test cases covering valid formats, port validations, invalid addresses, and unsupported address types. This provides good coverage for the input validation rules of MnNetInfo.


35-35: Good choice of test fixture

Using RegTestingSetup rather than BasicTestingSetup is appropriate here as it provides a more complete environment for testing network-related functionality, consistent with the PR objectives mentioning the switch to RegTestingSetup.

🧰 Tools
🪛 Cppcheck (2.10-2)

[error] 35-35: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)


42-54: Well-structured test case for input validation

The test case effectively validates that AddEntry correctly enforces the rules for different input formats, and properly manages the internal state (empty on failure, one entry on success). This helps ensure the robustness of the new MnNetInfo class.

src/test/evo_simplifiedmns_tests.cpp (5)

13-13: Appropriate test fixture change

Switching from BasicTestingSetup to RegTestingSetup aligns with the PR objectives to address validation issues related to CService assignments by providing a more complete testing environment.

🧰 Tools
🪛 Cppcheck (2.10-2)

[error] 13-13: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)


20-20: Fixed potential validation issue by starting from index 1

Changing the loop to start from 1 instead of 0 addresses the PR objective of preventing invalid addresses like 0.0.0.0, which aligns with proper validation in the MnNetInfo class.


25-25: Properly integrated MnNetInfo with validation

The updated code now uses netInfo.AddEntry() with validation instead of direct assignment to a CService object, which helps enforce address validity constraints mentioned in the PR objectives.


37-53: Updated hash expectations to match new serialization format

The change in expected hashes is consistent with the updated network information storage approach. The test still maintains comprehensive coverage of the simplified masternode list entry hashing.


65-65: Updated merkle root to match new network information format

The expected merkle root has been updated to reflect changes in the underlying data structure, ensuring test compatibility with the MnNetInfo refactoring.

@kwvg kwvg requested review from PastaPastaPasta and UdjinM6 May 7, 2025 13:26
UdjinM6
UdjinM6 previously approved these changes May 7, 2025
Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 0fa7ce2

PastaPastaPasta
PastaPastaPasta previously approved these changes May 7, 2025
Copy link
Member

@PastaPastaPasta PastaPastaPasta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 0fa7ce2

Copy link
Collaborator

@knst knst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here's bunch of nits that maybe addressed later by new PR, but please answer to 2 my comments:

  • LookupNumeric vs Lookup
  • possible UB behaviour due to missing mutex for g_main_params

class CService;

enum NetInfoStatus : uint8_t {
BadInput,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just BadAddress or InvalidAddress? seems confusing that "bad input" and "invalid address" are not exactly same.

Copy link
Collaborator Author

@kwvg kwvg May 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BadInput and BadPort correspond to the old bad-protx-ipaddr and bad-protx-ipaddr-port error codes

if (!proTx.addr.IsValid()) {
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr");
}
if (Params().RequireRoutableExternalIP() && !proTx.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) {
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr-port");
}
} else if (proTx.addr.GetPort() == mainnetDefaultPort) {
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr-port");
}
if (!proTx.addr.IsIPv4()) {
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr");
}

Making it more granular will be addressed in a future PR as the error codes would be renamed there.

{
m_addr = service;
return NetInfoStatus::Success;
if (auto service = Lookup(input, /*portDefault=*/Params().GetDefaultPort(), /*fAllowLookup=*/false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why here is not LookupNumeric but Lookup?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the lookup code was moved from protx_{register,update_service}_common_wrapper and they used Lookup (see below), see no harm in using LookupNumeric if insisted.

dash/src/rpc/evo.cpp

Lines 685 to 691 in e14a8bd

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();
} else {
throw std::runtime_error(strprintf("invalid network address %s", request.params[paramIdx].get_str()));
}
}

dash/src/rpc/evo.cpp

Lines 981 to 985 in e14a8bd

if (auto addr = Lookup(request.params[1].get_str().c_str(), Params().GetDefaultPort(), false); addr.has_value()) {
ptx.addr = addr.value();
} else {
throw std::runtime_error(strprintf("invalid network address %s", request.params[1].get_str()));
}

std::string MnNetInfo::ToString() const
{
// Extra padding to account for padding done by the calling function.
return strprintf("MnNetInfo()\n"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's do it in one line? \n are not friendly for logs without a good reason; especially if that's part of complex object such as SimplifiedMNListEntry's logging

return strprintf("MnNetInfo(m_addr=CService(addr=%s, port=%u))"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not feasible, see ToString() for ExtNetInfo (see below, WIP code). Would like MnNetInfo to retain a similar structure.

dash/src/evo/netinfo.cpp

Lines 320 to 327 in 17f34c6

std::string ExtNetInfo::ToString() const
{
std::string ret{"ExtNetInfo()\n"};
for (const auto& entry : m_data) {
ret += strprintf(" %s\n", entry.ToString());
}
return ret;
}

When purpose codes are introduced, the structure gets more complicated (see below, WIP code)

dash/src/evo/netinfo.cpp

Lines 577 to 591 in 7a9bfa2

std::string ExtNetInfo::ToString() const
{
std::string ret{"ExtNetInfo()\n"};
for (const auto& [purpose, entries] : m_data) {
ret += strprintf(" NetInfo(purpose=%s)\n", PurposeToString(purpose));
if (entries.empty()) {
ret += strprintf(" [invalid list]\n");
} else {
for (const auto& entry : entries) {
ret += strprintf(" %s\n", entry.ToString());
}
}
}
return ret;
}

Which MnNetInfo will be emulating (see below, WIP code)

dash/src/evo/netinfo.cpp

Lines 336 to 342 in 7a9bfa2

std::string MnNetInfo::ToString() const
{
// Extra padding to account for padding done by the calling function.
return strprintf("MnNetInfo()\n"
" NetInfo(purpose=%s)\n"
" %s\n", PurposeToString(Purpose::CORE_P2P), m_addr.ToString());
}

static_assert(!std::is_same_v<std::decay_t<T>, name>, "GetUniquePropertyHash cannot be templated against " #name)
DMNL_NO_TEMPLATE(CBLSPublicKey);
DMNL_NO_TEMPLATE(MnNetInfo);
#undef DMNL_NO_TEMPLATE
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I'd personally prefer copy-paste here rather than using define

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocklist expands in later PRs (see below, WIP code) and would also include ExtNetInfo since we only want to allow storing individual CServices and DomainPorts and therefore need to prohibit higher-level components.

#define DMNL_NO_TEMPLATE(name) static_assert(!std::is_same_v<std::decay_t<T>, name>, "GetUniquePropertyHash cannot be templated against "#name)
DMNL_NO_TEMPLATE(CBLSPublicKey);
DMNL_NO_TEMPLATE(MnNetInfo);
DMNL_NO_TEMPLATE(NetInfoEntry);
DMNL_NO_TEMPLATE(std::shared_ptr<NetInfoInterface>);
#undef DMNL_NO_TEMPLATE

kwvg added 7 commits May 7, 2025 17:57
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.
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.
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.
@kwvg kwvg dismissed stale reviews from PastaPastaPasta and UdjinM6 via 1d52678 May 8, 2025 10:22
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/test/evo_simplifiedmns_tests.cpp (1)

1-72: Fix the clang formatting issues.

The pipeline indicates Clang format differences. Please run clang-format on this file to ensure consistent formatting.

#!/bin/bash
# Description: Check and fix formatting issues
clang-format -i src/test/evo_simplifiedmns_tests.cpp
🧰 Tools
🪛 Cppcheck (2.10-2)

[error] 13-13: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)

🪛 GitHub Actions: Clang Diff Format Check

[error] 1-1: Clang format differences found. Code formatting does not match the expected style.

src/test/evo_netinfo_tests.cpp (1)

1-1: Update the copyright year.

The copyright year is set to 2025, which is beyond the current year. Update it to match the current year.

-// Copyright (c) 2025 The Dash Core developers
+// Copyright (c) 2024 The Dash Core developers
src/evo/netinfo.cpp (2)

20-22: Remove the TODO comment and consider a more robust ArgsManager.

The TODO comment should be addressed or removed before merging. Additionally, using an empty ArgsManager might cause issues if there are parameters that need to be passed.

-    // TODO: use real args here
     std::call_once(g_main_params_flag,
-                   [&]() { g_main_params = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN); });
+                   [&]() { g_main_params = CreateChainParams(gArgs, CBaseChainParams::MAIN); });

1-1: Update the copyright year.

The copyright year is set to 2025, which is beyond the current year. Update it to match the current year.

-// Copyright (c) 2025 The Dash Core developers
+// Copyright (c) 2024 The Dash Core developers
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0fa7ce2 and 1d52678.

📒 Files selected for processing (17)
  • src/Makefile.am (2 hunks)
  • src/Makefile.test.include (1 hunks)
  • src/evo/deterministicmns.cpp (12 hunks)
  • src/evo/deterministicmns.h (3 hunks)
  • src/evo/dmnstate.cpp (2 hunks)
  • src/evo/dmnstate.h (6 hunks)
  • src/evo/netinfo.cpp (1 hunks)
  • src/evo/netinfo.h (1 hunks)
  • src/evo/providertx.cpp (2 hunks)
  • src/evo/simplifiedmns.cpp (3 hunks)
  • src/rpc/evo.cpp (2 hunks)
  • src/rpc/masternode.cpp (4 hunks)
  • src/test/block_reward_reallocation_tests.cpp (1 hunks)
  • src/test/evo_deterministicmns_tests.cpp (7 hunks)
  • src/test/evo_netinfo_tests.cpp (1 hunks)
  • src/test/evo_simplifiedmns_tests.cpp (3 hunks)
  • src/txmempool.cpp (7 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/evo/dmnstate.cpp
🚧 Files skipped from review as they are similar to previous changes (13)
  • src/test/block_reward_reallocation_tests.cpp
  • src/Makefile.am
  • src/evo/dmnstate.h
  • src/Makefile.test.include
  • src/evo/providertx.cpp
  • src/rpc/masternode.cpp
  • src/evo/deterministicmns.h
  • src/rpc/evo.cpp
  • src/evo/simplifiedmns.cpp
  • src/txmempool.cpp
  • src/test/evo_deterministicmns_tests.cpp
  • src/evo/netinfo.h
  • src/evo/deterministicmns.cpp
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/evo/netinfo.cpp (1)
src/evo/netinfo.h (5)
  • ValidateService (59-59)
  • service (40-40)
  • service (54-54)
  • m_addr (57-57)
  • m_addr (62-62)
src/test/evo_netinfo_tests.cpp (1)
src/test/util/setup_common.h (1)
  • RegTestingSetup (127-128)
src/test/evo_simplifiedmns_tests.cpp (1)
src/test/util/setup_common.h (1)
  • RegTestingSetup (127-128)
🪛 Cppcheck (2.10-2)
src/test/evo_netinfo_tests.cpp

[error] 35-35: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)

src/test/evo_simplifiedmns_tests.cpp

[error] 13-13: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)

🪛 GitHub Actions: Clang Diff Format Check
src/test/evo_simplifiedmns_tests.cpp

[error] 1-1: Clang format differences found. Code formatting does not match the expected style.

⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: mac-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: linux64_multiprocess-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: win64-build / Build source
🔇 Additional comments (12)
src/test/evo_simplifiedmns_tests.cpp (4)

13-13: Test fixture update aligns with the new validation requirements.

Switching from BasicTestingSetup to RegTestingSetup allows the test to use the regtest network configuration which is needed for validating network addresses with MnNetInfo.

🧰 Tools
🪛 Cppcheck (2.10-2)

[error] 13-13: There is an unknown macro here somewhere. Configuration is required. If BOOST_FIXTURE_TEST_SUITE is a macro then please configure it.

(unknownMacro)


20-20: Starting iteration from 1 prevents invalid address issues.

This change avoids creating entries with invalid IP addresses like 0.0.0.0 that would now be rejected by the new validation logic in MnNetInfo.


25-25: Good use of the new netInfo.AddEntry API with result validation.

The code correctly uses the new MnNetInfo::AddEntry method and validates the result with BOOST_CHECK_EQUAL, ensuring that address addition succeeds.


52-52: Updated hash values reflect the modified test data.

The expected hash values have been correctly updated to match the new data generated by the modified test setup (starting from 1 instead of 0 and using the new network information structure).

Also applies to: 65-65

src/test/evo_netinfo_tests.cpp (3)

14-33: Comprehensive test cases for network address validation.

The test cases cover a wide range of scenarios including valid IPv4 addresses, port validation, invalid IP formatting, IPv6 addresses (not allowed), domain names (not allowed), and malformed addresses. This thorough validation will help ensure proper address handling.


37-40: Helper function for entry validation noted for future expansion.

Based on past review comments, this function is intentionally separate to allow for expansion in subsequent PRs.


42-54: Well-structured test case with proper validation checks.

The test covers:

  1. Correct return status from AddEntry
  2. Empty entries list on failure
  3. Single entry added on success

This ensures that MnNetInfo correctly validates and stores network entries.

src/evo/netinfo.cpp (5)

13-25: Properly implemented lazy initialization of mainnet parameters.

The use of std::once_flag and std::call_once correctly handles thread-safety concerns for the initialization of g_main_params.


27-49: Thorough service validation logic.

The ValidateService method properly enforces important validation rules:

  1. Service must be a valid IPv4 address
  2. Service must be routable when required
  3. Port must match network expectations (mainnet port on mainnet, non-mainnet port elsewhere)

This robust validation will help prevent configuration errors.


51-63: Effective implementation of AddEntry with appropriate validation.

The method correctly:

  1. Uses Lookup with the default port and disables DNS lookups
  2. Validates the parsed service using ValidateService
  3. Stores the service only if validation succeeds
  4. Includes debug assertions to verify the stored service is valid

The use of Lookup instead of LookupNumeric aligns with existing code patterns as noted in the past review comments.


65-75: Clear implementation of GetEntries with proper state validation.

The method correctly:

  1. Returns an empty list if MnNetInfo is empty
  2. Includes debug assertions to verify the state
  3. Returns a list with the single address if one is present

This design supports the future expansion to multiple entries mentioned in the PR objectives.


77-83: ToString format supports future extensions.

The multi-line format is necessary for consistency with future implementations that will handle multiple entries, as indicated in the past review comments.

@kwvg kwvg requested review from PastaPastaPasta, UdjinM6 and knst May 8, 2025 10:27
Copy link
Collaborator

@knst knst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 1d52678

Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 1d52678

@PastaPastaPasta PastaPastaPasta merged commit e19aadb into dashpay:develop May 8, 2025
85 of 88 checks passed
PastaPastaPasta added a commit that referenced this pull request May 12, 2025
2e8c7ef refactor: simplify (non-)mainnet port check condition (UdjinM6)
78ebaeb test: use mainnet setup in evo_netinfo_tests (Kittywhiskers Van Gogh)
20afc99 fix: MN port validation is broken after 6627 (UdjinM6)

Pull request description:

  ## Issue being fixed or feature implemented
  #6627 broke MN port validation on mainnet - `develop` fails with `bad-protx-netinfo-port` for a completely valid protx

  ## What was done?
  Implement it the way it was before https://github.com/dashpay/dash/pull/6627/files#diff-0998f8dfc4c1089e90cbaafe9607b361035b904cd103df31e3c2339a3cbf790dL1189-L1195

  ## How Has This Been Tested?
  Sync on mainnet

  ## Breaking Changes
  n/a

  ## Checklist:
  - [ ] I have performed a self-review of my own code
  - [ ] I have commented my code, particularly in hard-to-understand areas
  - [ ] I have added or updated relevant unit/integration/functional/e2e tests
  - [ ] I have made corresponding changes to the documentation
  - [ ] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  kwvg:
    utACK 2e8c7ef
  knst:
    utACK 2e8c7ef

Tree-SHA512: 1601d5013479c05e06d2f78f5d0ab133f69d37a4580eb7f69fb2c5c0797623bca4f9e55a0048245abbfeb0fcb44de8a43dae6b8b8e58f5f8501d36277bbdc26d
PastaPastaPasta added a commit that referenced this pull request May 28, 2025
…n-`CService` entries, use in `MnNetInfo`

3a72f2f evo: fast-fail `MnNetInfo::AddEntry()` if invalid characters found (Kittywhiskers Van Gogh)
e0a1c64 evo: prohibit overwriting entry in `MnNetInfo` (Kittywhiskers Van Gogh)
c69184b evo: utilize `NetInfoEntry::IsTriviallyValid()` in ProTx trivial checks (Kittywhiskers Van Gogh)
06cf4ee evo: return `MnNetInfo::GetEntries()` with `NetInfoEntry` (Kittywhiskers Van Gogh)
6286c9b evo: change internal type of `MnNetInfo` to `NetInfoEntry` (Kittywhiskers Van Gogh)
b0a634e evo: ensure the ADDRV2 serialization is always used in `NetInfoEntry` (Kittywhiskers Van Gogh)
6d97bda evo: introduce type-flexible `NetInfoEntry` to allow non-`CService` data (Kittywhiskers Van Gogh)
069583d evo: expand error codes for `netInfo` validation (Kittywhiskers Van Gogh)

Pull request description:

  ## Motivation

  The upcoming extended addresses specification envisions the ability to store address information _beyond_ the set of addresses that can be represented by BIP-155 (i.e. `CService`). To enable this, we need to devise a backwards-compatible way to allow storing and manipulating address information with differing serialization formats and validation rules.

  Backwards compatibility is a priority as the unique properties set (used to detect attempts at storing already-registered values) only stores a hashed representation of the value and therefore, in-place migration is not a viable option.

  With this in mind, this pull request introduces `NetInfoEntry`, which is wrapper around an `std::variant` that provides dispatching for common endpoints with `std::visit`, serialization and trivial validity enforcement between potential implementations and the ability to access the underlying type if necessary (for code that relies on backwards-compatibility, like hashing). It doesn't implement any network rules itself but requires that it must hold a valid instance of any underlying type that it supports.

  While `MnNetInfo` (the current implementation) has and always will store a `CService`, to ensure a conformity between it and `ExtNetInfo` (the upcoming extended implementation), its public functions will return a `NetInfoEntry` when applicable so that both can be abstracted by a common interface to aid with the transition.

  ## Additional Information

  * Depends on #6627

  * Depends on #6664

  * Dependency for #6665

  * ~~2e9bde0519b242d1d7aaf49344a357b90121689e in [dash#6627](#6627) incorrectly migrated validation conditions such that attempting to set a valid `addr:port` combination on mainnet would result in a `BadPort` error because the non-mainnet rules were applied _regardless_ of network.~~

    ~~This evaded testing as our unit and functional tests do not run on mainnet. To prevent this from occurring again, the whole `evo_netinfo_tests` suite now uses `BasicTestingSetup` (which advertises itself as mainnet), which comes with the added benefit of greater coverage as mainnet rules are _stricter_.~~

    ~~The port validation check for non-mainnet networks are tested _indirectly_ through tests like `evo_simplifiedmns_merkleroots`'s usage of `NetInfoInterface::*` methods ([source](https://github.com/dashpay/dash/blob/0f94e3e3e793925caa24a73ad54d843770b1a8c5/src/test/evo_simplifiedmns_tests.cpp#L25)).~~ Superseded by [dash#6664](#6664).

  * Per replies to review comments ([comment](#6627 (comment)), [comment](#6627 (comment))) from [dash#6627](#6627), reported error codes from `netInfo` interactions have been expanded to be more specific.

  * `CService` by default is serialized using ADDRV1 and utilizing ADDRV2 serialization is either explicitly opted into ([source](https://github.com/dashpay/dash/blob/0f94e3e3e793925caa24a73ad54d843770b1a8c5/src/addrman.cpp#L173-L175)) or determined on-the-fly ([source](https://github.com/dashpay/dash/blob/0f94e3e3e793925caa24a73ad54d843770b1a8c5/src/net_processing.cpp#L3960-L3965)). As we envision the ability to store Tor and I2P addresses, using ADDRV2 is mandatory.

    Though this affects (de)serialization of `NetInfoEntry`, it does not affect `MnNetInfo` as `NetInfoEntry` is only used for the sake of a consistent interface _but_ internally still (de)serializes to an ADDRV1 `CService`.

  * The introduction of fast-failing based on permitted characters is meant to mirror the upcoming extended addresses implementation where permitted characters are used as a quick way to classify the intended underlying type before running more expensive checks.

    As a side effect, this may cause inconsistency where attempting to use `MnNetInfo::AddEntry()` with, for example, an IPv6 address will result in `BadInput` as the delimiter used in IPv6 addresses are not part of the permitted characters filter _but_ validating a `MnNetInfo` with an IPv6 address _already stored_ will return a `BadType`.

  ## Breaking Changes

  None expected.

  ## 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 **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  PastaPastaPasta:
    utACK 3a72f2f
  UdjinM6:
    utACK 3a72f2f

Tree-SHA512: abd84db309b6011480431b12cccd649878bab06aa44ca2c81563e9598d4424fd61888b12e2e439b9c2180bc5e0edee3431b1008ae7af4b676b164af1455fda3c
PastaPastaPasta added a commit that referenced this pull request Jul 7, 2025
…switching impls, add new ProTx version

3e65628 evo: introduce new ProTx version for extended addresses (`ExtNetInfo`) (Kittywhiskers Van Gogh)
b4fa7a2 evo: add helper to get highest ProTx version based on deployment status (Kittywhiskers Van Gogh)
c7948e6 evo: allow deciding `NetInfoInterface` impl based on object version (Kittywhiskers Van Gogh)
22d9e93 evo: use interface shared ptr for `netInfo` instead of implementation (Kittywhiskers Van Gogh)
f212caa evo: introduce `NetInfoInterface`, make `MnNetInfo` an implementation (Kittywhiskers Van Gogh)
0b04978 evo: make `netInfo` a shared pointer (Kittywhiskers Van Gogh)
0a4e726 util: add deep comparison helpers for shared_ptr (Kittywhiskers Van Gogh)
c4f1175 evo: cleanup CDeterministicMN{,List,ListDiff,StateDiff} ser logic (Kittywhiskers Van Gogh)

Pull request description:

  ## Motivation

  To enable the switch to extended addresses, the current `CService` entry was first encapsulated in `MnNetInfo` and exposed through a public interface (see [dash#6627](#6627)) that restricted access to the underlying type, then the underlying type of the address was abstracted away through `NetInfoEntry` (see [dash#6629](#6629)), allowing us to store different types of addresses.

  This pull request finally abstracts away `MnNetInfo` as an implementation detail and sets the stage for alternate implementations (i.e. extended addresses) to be selected in based on the version number. This should allow the switchover logic to be insulated from most of the codebase.

  ## Additional Information

  * Depends on #6669

  * Depends on #6629

  * Dependency for #6674

  * Since [dash#6579](#6579) got rid of legacy `CDeterministicMNState` serialization, there is no more logic that can attempt legacy deserialization, making the version check ([source](https://github.com/dashpay/dash/blob/da8a475dfac9ad80d566eef8cf119c8036d6ebcc/src/evo/deterministicmns.h#L75-L78)) vestigial. We can safely remove the leftover version fields and simplify the serialization logic.

    It is done as part of this PR because the serialization version is manipulated with `OverrideStream` to ensure proper ADDRv2 serialization ([source](https://github.com/dashpay/dash/blob/da8a475dfac9ad80d566eef8cf119c8036d6ebcc/src/addrman.cpp#L175)) and as the  extended implementation uses it for that reason, the otherwise-vestigial version-based check could now trigger a crash, so it has been removed.

  * ~~As implementing operators in virtual classes (needed to allow switching implementations) is not possible (unlike regular pointers where a `lhs && rhs ? *lhs == *rhs : lhs == rhs` would be enough), a separate equality function `NetInfoInterface::IsEqual()` has been implemented that attempts to downcast `lhs` and `rhs` to the same type and returns the implementation-specific equality result.~~

    A solution that uses `typeid` to help define comparison operators has been implemented but `std::shared_ptr` does not deep compare, to aid with that, the deep comparison helpers `util::shared_ptr_{,not_}equal` have been implemented and can be used with any pair of `shared_ptr`s so long as their underlying types define the necessary operators.

    Care needs to be taken to ensure that all equality comparisons involving `netInfo` use those functions.

  * A new ProTx version has been introduced for the upcoming extended addresses implementation. It is only applicable to `CProRegTx` and `CProUpServTx` as no other special transaction stores `netInfo` and is therefore, unaffected by the switchover. No code has been implemented in this PR that uses this new version, that is reserved for the PR that introduces the extended implementation.

    * Additionally, as the transaction version is used to determine the underlying implementation, make sure that `nVersion` is set *before* calling `MakeNetInfo()` (also remember to call `MakeNetInfo()` as the default constructor will set `netInfo` to `nullptr` and a missing call will result in a `nullptr` dereference when `netInfo` is eventually accessed). This is only relevant if a transaction is being constructed in-place as deserialization logic handles this for you.

    * ~~An earlier approach involved setting the new version only for `CProRegTx` and `CProUpServTx`. In light of _multiple_ ProTx types being able to modify the version of the masternode state (`pdmnState`), this may prove to be more dangerous than beneficial. In light of that, the version bump now affects all ProTx types but is still only effective in `CProRegTx` and `CProUpServTx`.~~ See [comment](#6665 (comment)).

  ## Breaking Changes

  None expected.

  ## 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 **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  UdjinM6:
    utACK 3e65628

Tree-SHA512: 2675712351c9bbcf8bff2c6f032df40a52503abc62f8cd74b4b4f70bbcca0b68a32c1f4e1310c8a674bad1e605a2949337a7ab862a2129c4753cf8f4dbfa8789
PastaPastaPasta added a commit that referenced this pull request Sep 23, 2025
… 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants