Skip to content

feat: introduce type-flexible NetInfoEntry to allow non-CService entries, use in MnNetInfo #6629

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from

Conversation

kwvg
Copy link
Collaborator

@kwvg kwvg commented Apr 12, 2025

Additional Information

  • Depends on refactor: section off masternode network information to MnNetInfo, lay some groundwork for managing multiple entries  #6627

  • Depends on fix: MN port validation on mainnet is broken after 6627 #6664

  • Dependency for refactor: model interface after MnNetInfo and support switching impls, add new ProTx version, introduce DEPLOYMENT_EXTADDR params #6665

  • 2e9bde0 in dash#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). Superseded by dash#6664.

  • Per replies to review comments (comment, comment) from dash#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) or determined on-the-fly (source). 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

  • 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 12, 2025
@kwvg kwvg requested a review from PastaPastaPasta April 12, 2025 11:25
@kwvg kwvg changed the title evo: introduce type-flexible NetInfoEntry to allow non-CService entries, use in MnNetInfo feat: introduce type-flexible NetInfoEntry to allow non-CService entries, use in MnNetInfo Apr 12, 2025
@kwvg kwvg removed the request for review from PastaPastaPasta April 21, 2025 16:18
Copy link

This pull request has conflicts, please rebase.

@kwvg kwvg force-pushed the netinfo_p2 branch 3 times, most recently from c495aee to bfc833c Compare May 3, 2025 16:26
PastaPastaPasta added a commit that referenced this pull request May 8, 2025
…`MnNetInfo`, lay some groundwork for managing multiple entries

1d52678 refactor: track every `MnNetInfo` entry in the unique property map (Kittywhiskers Van Gogh)
bcb8a7d refactor: impl `GetEntries()`, adapt to support multiple addresses (Kittywhiskers Van Gogh)
ecc9368 refactor: implement `MnNetInfo::ToString()` for printing internal state (Kittywhiskers Van Gogh)
2e9bde0 refactor: move service validation to `MnNetInfo`, run during setting (Kittywhiskers Van Gogh)
03ec604 fix: correct `simplifiedmns_merkleroots` unit test (Kittywhiskers Van Gogh)
bac4a27 refactor: move address lookup to `MnNetInfo::AddEntry()` (Kittywhiskers Van Gogh)
e1783cb refactor: remove direct access to `MnNetInfo::addr` (Kittywhiskers Van Gogh)
e868aff refactor: use const-ref when accessing `MnNetInfo::addr` if read-only (Kittywhiskers Van Gogh)
aaabc35 refactor: section off masternode service to `MnNetInfo` (Kittywhiskers Van Gogh)
2c6dd05 fix: avoid potential "no user-provided default constructor" error (Kittywhiskers Van Gogh)

Pull request description:

  ## Additional Information

  * Depends on #6626

  * Depends on #6635

  * Depends on #6636

  * Dependency for #6629

  * The `simplifiedmns_merkleroots` test constructs 15 `CSimplifiedMNListEntry` elements and populates them with a `CService`. So far, since we allowed direct assignment of the `CService` without validation, no checks were made to see if they would pass validation but if we start enforcing validation rules _when setting values_, two problems emerge.

    * Using non-default ports on mainnet (`BasicTestingSetup` is mainnet by default, [source](https://github.com/dashpay/dash/blob/bcd14b05cec7d94986f114ca17bbdadbee701d9b/src/test/util/setup_common.h#L100)), this has been resolved by using `RegTestingSetup` (which is based on regtest) instead.

    * As the index is used to generate the address, starting from 0, the first address is `0.0.0.0`, which is not a valid `CService` address ([source](https://github.com/dashpay/dash/blob/bcd14b05cec7d94986f114ca17bbdadbee701d9b/src/test/net_tests.cpp#L140)) and therefore, would fail validation ([source](https://github.com/dashpay/dash/blob/bcd14b05cec7d94986f114ca17bbdadbee701d9b/src/evo/deterministicmns.cpp#L1219)). This has been resolved by changing the index to start from 1.

  * To avoid a potential "no user-provided default constructor" compile-time error, we now explicitly request the default constructor

    <details>

    <summary>Compile error:</summary>

    ```
    In file included from evo/deterministicmns.cpp:5:
    ./evo/deterministicmns.h:404:24: error: default initialization of an object of const type 'const ExampleType' without a user-provided default constructor
      404 |         static const T nullValue;
          |                        ^
          |                                 {}
    evo/deterministicmns.cpp:479:18: note: in instantiation of function template specialization 'CDeterministicMNList::AddUniqueProperty<ExampleType>' requested here
      479 |             if (!AddUniqueProperty(*dmn, domain)) {
          |                  ^
    ```

   </details>

  * 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

  - [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:
  knst:
    utACK 1d52678
  UdjinM6:
    utACK 1d52678

Tree-SHA512: 0f13f51fff6c279e8c4e3f88ea4db925f4137e25b030d28afd48b5db9c073421d5bb3a3dc3e067ee4f559887bec9e8a981d2e6ae5f2d0a042e5817a3d59ea0bf
Copy link

github-actions bot commented May 8, 2025

This pull request has conflicts, please rebase.

@kwvg kwvg marked this pull request as ready for review May 10, 2025 00:30
Copy link

coderabbitai bot commented May 10, 2025

Walkthrough

The changes introduce a new abstraction, NetInfoEntry, to encapsulate network address information in a type-safe and extensible manner, replacing direct use of CService in masternode and provider transaction code. Methods and data structures handling masternode network info, transaction validation, and mempool address management are updated to operate on NetInfoEntry objects, with explicit validation and error handling for malformed or invalid addresses. Serialization, deserialization, and comparison logic are adapted to support the new abstraction. The NetInfoStatus enum is extended with additional error codes to improve validation feedback. Test suites are updated to reflect these changes and to verify compatibility, stricter validation, and single-entry constraints for network info. No public API signatures are changed.

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


Note

⚡️ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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: 12

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

38-60: 🛠️ Refactor suggestion

Avoid comparing shared-ptr identity inside operator==

netInfo is now a std::shared_ptr<NetInfoInterface>, yet the equality operator still performs
netInfo == rhs.netInfo, i.e. compares pointer identity instead of value.
Two logically identical objects that were deserialized independently will hold different
shared_ptr instances and will therefore evaluate as unequal even when the contained
entries are byte-for-byte identical. This breaks deterministic-MN-list diffing and can
cause spurious re-broadcasts.

-               netInfo == rhs.netInfo &&
+               (!!netInfo && !!rhs.netInfo
+                   ? *netInfo == *rhs.netInfo   // deep-compare
+                   : netInfo == rhs.netInfo) && // handles null vs null

(Requires operator== for NetInfoInterface, or AsVector() comparison.)

src/evo/providertx.h (2)

40-48: ⚠️ Potential issue

netInfo left default-initialised to nullptr – introduces UB risk

CProRegTx and CProUpServTx default-construct with netInfo == nullptr, yet their
IsTriviallyValid, ToString, and other routines now dereference it unconditionally.
Either

  1. initialise the member immediately:
-    std::shared_ptr<NetInfoInterface> netInfo;
+    std::shared_ptr<NetInfoInterface> netInfo{MakeNetInfo()};
  1. or add explicit null-checks wherever the pointer is used (preferred together with an early-fail
    consensus rule: "bad-protx-netinfo-null").

Failing to do so allows a crafted tx to crash a node before validation.


66-72: 🛠️ Refactor suggestion

const_cast in NetInfoSerWrapper hides const-correctness issues

The need for const_cast means READWRITE cannot handle a const std::shared_ptr<...>&.
Instead of mutating through a const reference, declare the wrapper to accept auto& ptr
and pass obj.netInfo directly – this removes the cast and the clang-format warning flagged
by CI.

♻️ Duplicate comments (8)
src/coinjoin/client.cpp (4)

1109-1113: Repeat of null-check issue (netInfo access)

This dereference has the same unchecked assumption as above. Applying the helper-method proposal once will fix all call-sites.


1181-1186: Repeat of null-check issue (netInfo access)


1220-1223: Repeat of null-check issue (netInfo access)


1823-1829: Repeat of null-check issue (netInfo access)

src/evo/providertx.h (1)

132-138: Duplicate const_cast problem in CProUpServTx

Same remark as above – fix once in the wrapper template and both call-sites become clean.

src/evo/providertx.cpp (1)

135-138: Same ToString() crash-risk in CProUpServTx

src/evo/deterministicmns.cpp (2)

528-546: Same issue as above in updateNetInfo helper

The update path still assumes CService entries only; duplicate logic
should follow the relaxed rule proposed earlier.


610-621: Same issue in RemoveMN

Deletion should skip entries that carry no CService, rather than
aborting with an exception.

🧹 Nitpick comments (14)
src/evo/simplifiedmns.h (1)

79-81: const_cast on shared_ptr leaks const-correctness

NetInfoSerWrapper(const_cast<std::shared_ptr<NetInfoInterface>&>(obj.netInfo))
forces away constness to satisfy the wrapper, but this lets serialization routines
mutate netInfo through a const reference. Consider adding an overload of
NetInfoSerWrapper that accepts a const std::shared_ptr<…>& and only mutates
through mutable members, or move the cast inside the wrapper.

This prevents subtle UB and makes the intent clearer.

src/test/evo_simplifiedmns_tests.cpp (1)

22-28: Use routable test IPs to avoid future validation failures

"0.0.0.%d:%d" produces addresses in the 0.0.0.0/8 range which is reserved and
often rejected by stricter validators. A later hardening of NetInfoEntry
could make this test fail. Prefer a well-known documentation subnet such as
192.0.2.0/24 (RFC 5737) or 198.51.100.0/24.

-        strprintf("%d.%d.%d.%d:%d", 0, 0, 0, i, i)
+        strprintf("192.0.2.%d:%d",  i, 10000 + i)   // 10000+ i keeps ports >1024
src/rpc/masternode.cpp (2)

571-575: Use const auto& for range-based loop to avoid copies
Iterating over entries by value can be expensive if NetInfoEntry grows. Change to:

- for (const NetInfoEntry& entry : dmn.pdmnState->netInfo->GetEntries()) {
+ for (const auto& entry : dmn.pdmnState->netInfo->GetEntries()) {
      strAddress += entry.ToStringAddrPort() + " ";
  }

571-575: Expose all network entries in JSON mode
Currently, in JSON output you only return the primary address. Since masternodes can have multiple network entries (IPv4, Tor, I2P), clients may need full visibility. Consider adding:

UniValue addrs(UniValue::VARR);
for (const auto& entry : dmn.pdmnState->netInfo->GetEntries()) {
    addrs.push_back(entry.ToStringAddrPort());
}
objMN.pushKV("addresses", addrs);

This preserves the existing "address" field for compatibility while surfacing the full list.

src/test/evo_deterministicmns_tests.cpp (3)

108-111: Order of initialisation is correct – but capture failure status

AddEntry can return non-Success. In tests we currently ignore the status (except the CHECK_EQUAL just below here). Consider BOOST_REQUIRE_EQUAL to abort early on failure and aid debugging.


130-134: Same remark as above – tighten assertion

Use BOOST_REQUIRE_EQUAL for proTx.netInfo->AddEntry(...) so that the test fails fast when the address unexpectedly becomes invalid.


714-717: Potential copy-paste maintenance burden

The triple-line pattern (version, MakeNetInfo, AddEntry) is duplicated many times across the test file. A tiny helper such as InitNetInfo(payload, "1.1.1.1:port") would make future signature changes trivial.

src/test/evo_netinfo_tests.cpp (4)

18-37: Test vector covers edge-cases well – one missing case

Consider adding "1.1.1.1:0" which should fail (BadPort) because port 0 is invalid and often pops up in fuzzing.


63-69: Single-entry limit test OK – could also assert status of second add

You already check size==1; an additional BOOST_CHECK_EQUAL(..., NetInfoStatus::MaxLimit) would make intent explicit.


72-78: CheckIfSerSame – ensure endian safety

Comparing SHA-256 hashes is portable, but serialising both objects with the same CHashWriter version 0 does not include network (little/big) meta-data. That’s fine for regression tests now; just document that this is wire serialisation, not disk serialisation, to avoid future confusion.


80-109: Robust compatibility test – consider negative round-trip

After the positive CheckIfSerSame cases, also test that different services yield different hashes to prevent false positives (e.g., compare "1.1.1.1:9999" vs "1.1.1.2:9999").

src/evo/netinfo.cpp (2)

198-205: Dereference optional once, not twice

GetPrimary() calls service->get() twice – first when retrieving the
optional, then again when returning the static empty_service. While
this works, the intent is clearer (and avoids accidental copies) by
binding the reference once:

-    if (const auto& service{m_addr.GetAddrPort()}; service.has_value()) {
-        return *service;
+    if (const auto service{m_addr.GetAddrPort()}) {
+        return service->get();
     }

A small readability tweak, but helps avoid dangling-reference mistakes.


206-213: Empty MnNetInfo reported as Malformed

Validate() returns Malformed when m_addr.IsTriviallyValid() is
false, which happens for an intentionally empty MnNetInfo. Up-stream
call-sites (CheckProRegTx, etc.) already guard against empty objects,
but other callers (future code, RPC helpers, tests) will mis-interpret an
empty list as malformed.

Consider treating emptiness as Success to make the API symmetric with
IsEmpty():

-    if (!m_addr.IsTriviallyValid()) {
-        return NetInfoStatus::Malformed;
+    if (IsEmpty()) {
+        return NetInfoStatus::Success;
+    }
+    if (!m_addr.IsTriviallyValid()) {
+        return NetInfoStatus::Malformed;
     }
src/evo/netinfo.h (1)

161-170: IsEmpty() comparison allocates temporary

bool IsEmpty() const override { return *this == MnNetInfo(); }

This constructs a temporary every call. A lighter/faster alternative:

-    bool IsEmpty() const override { return *this == MnNetInfo(); }
+    bool IsEmpty() const override { return m_addr == NetInfoEntry(); }

Minor, but avoids needless instantiation.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0f94e3e and 8e8ad0b.

📒 Files selected for processing (26)
  • src/coinjoin/client.cpp (6 hunks)
  • src/evo/core_write.cpp (2 hunks)
  • src/evo/deterministicmns.cpp (12 hunks)
  • src/evo/deterministicmns.h (1 hunks)
  • src/evo/dmnstate.cpp (2 hunks)
  • src/evo/dmnstate.h (4 hunks)
  • src/evo/netinfo.cpp (3 hunks)
  • src/evo/netinfo.h (1 hunks)
  • src/evo/providertx.cpp (4 hunks)
  • src/evo/providertx.h (4 hunks)
  • src/evo/simplifiedmns.cpp (2 hunks)
  • src/evo/simplifiedmns.h (2 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 (3 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 (2 hunks)
  • src/test/evo_simplifiedmns_tests.cpp (1 hunks)
  • src/txmempool.cpp (8 hunks)
  • src/txmempool.h (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (8)
src/test/block_reward_reallocation_tests.cpp (1)
src/evo/netinfo.h (2)
  • MakeNetInfo (225-229)
  • MakeNetInfo (225-225)
src/txmempool.cpp (1)
src/txmempool.h (14)
  • entry (187-190)
  • entry (187-187)
  • entry (519-519)
  • entry (535-535)
  • entry (536-536)
  • entry (608-608)
  • entry (609-609)
  • entry (611-611)
  • entry (616-616)
  • entry (705-705)
  • entry (883-883)
  • entry (899-899)
  • entry (1031-1035)
  • entry (1031-1031)
src/net.cpp (1)
test/functional/test_framework/messages.py (1)
  • CAddress (252-375)
src/rpc/evo.cpp (1)
src/evo/netinfo.h (2)
  • MakeNetInfo (225-229)
  • MakeNetInfo (225-225)
src/test/evo_simplifiedmns_tests.cpp (1)
src/evo/netinfo.h (2)
  • MakeNetInfo (225-229)
  • MakeNetInfo (225-225)
src/evo/dmnstate.h (1)
src/evo/netinfo.h (7)
  • NetInfoSerWrapper (237-237)
  • NetInfoSerWrapper (238-238)
  • NetInfoSerWrapper (239-242)
  • NetInfoSerWrapper (243-243)
  • NetInfoSerWrapper (245-245)
  • MakeNetInfo (225-229)
  • MakeNetInfo (225-225)
src/evo/deterministicmns.h (1)
src/evo/netinfo.h (6)
  • NetInfoEntry (66-66)
  • NetInfoEntry (67-72)
  • NetInfoEntry (73-73)
  • NetInfoEntry (75-75)
  • NetInfoInterface (159-159)
  • NetInfoInterface (159-159)
src/test/evo_netinfo_tests.cpp (2)
src/evo/netinfo.cpp (4)
  • rhs (40-51)
  • rhs (40-40)
  • rhs (53-73)
  • rhs (53-53)
src/evo/netinfo.h (11)
  • rhs (77-77)
  • rhs (78-78)
  • rhs (79-79)
  • rhs (79-79)
  • rhs (186-186)
  • rhs (186-186)
  • rhs (187-187)
  • rhs (187-187)
  • service (161-161)
  • service (178-178)
  • service (212-212)
🪛 GitHub Actions: Clang Diff Format Check
src/evo/simplifiedmns.h

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

src/evo/dmnstate.h

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

src/evo/providertx.h

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

src/evo/netinfo.h

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

🪛 Cppcheck (2.10-2)
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 (5)
  • GitHub Check: linux64_tsan-test / Test source
  • GitHub Check: linux64_ubsan-test / Test source
  • GitHub Check: linux64_sqlite-test / Test source
  • GitHub Check: linux64-test / Test source
  • GitHub Check: linux64_multiprocess-build / Build source
🔇 Additional comments (41)
src/llmq/utils.cpp (2)

827-827: Syntax update for pointer-based netInfo access.

The code now correctly uses the arrow operator (->) to access methods on the netInfo pointer rather than the dot operator (.). This change is consistent with the broader refactoring where netInfo was changed from a direct MnNetInfo object to a std::shared_ptr<NetInfoInterface>.


876-876: Syntax update for pointer-based netInfo access.

The code now correctly uses the arrow operator (->) to access methods on the netInfo pointer rather than the dot operator (.). This change is consistent with the broader refactoring where netInfo was changed from a direct MnNetInfo object to a std::shared_ptr<NetInfoInterface>.

src/masternode/utils.cpp (1)

81-81: Syntax update for pointer-based netInfo access.

The code now correctly uses the arrow operator (->) to access methods on the netInfo pointer rather than the dot operator (.). This change is consistent with the broader refactoring where netInfo was changed from a direct MnNetInfo object to a std::shared_ptr<NetInfoInterface>.

src/qt/masternodelist.cpp (2)

224-224: Syntax update for pointer-based netInfo access.

The code now correctly uses the arrow operator (->) to access methods on the netInfo pointer rather than the dot operator (.). This change is consistent with the broader refactoring where netInfo was changed from a direct MnNetInfo object to a std::shared_ptr<NetInfoInterface>.


227-227: Syntax update for pointer-based netInfo access.

The code now correctly uses the arrow operator (->) to access methods on the netInfo pointer rather than the dot operator (.). This change is consistent with the broader refactoring where netInfo was changed from a direct MnNetInfo object to a std::shared_ptr<NetInfoInterface>.

src/rpc/quorums.cpp (1)

206-206: Syntax update for pointer-based netInfo access.

The code now correctly uses the arrow operator (->) to access methods on the netInfo pointer rather than the dot operator (.). This change is consistent with the broader refactoring where netInfo was changed from a direct MnNetInfo object to a std::shared_ptr<NetInfoInterface>.

src/masternode/node.cpp (2)

149-149: Access updated to use pointer dereference

The change from direct member access to pointer dereference correctly aligns with the updated type of netInfo from a concrete MnNetInfo object to a std::shared_ptr<NetInfoInterface>.


204-204: Access updated to use pointer dereference

The change from direct member access to pointer dereference correctly aligns with the updated type of netInfo from a concrete MnNetInfo object to a std::shared_ptr<NetInfoInterface>.

src/evo/simplifiedmns.cpp (2)

71-71: Access updated to use pointer dereference

The change from direct member access (netInfo.ToString()) to pointer dereference (netInfo->ToString()) correctly reflects the type change from a concrete object to a shared pointer.


81-81: Access updated to use pointer dereference

The change from direct member access to pointer dereference correctly reflects the type change from a concrete object to a shared pointer, maintaining the same logical functionality while adapting to the new interface.

src/evo/dmnstate.cpp (2)

35-35: Access updated to use pointer dereference

The change from direct member access to pointer dereference correctly aligns with the updated type of netInfo from a concrete object to a shared pointer of an interface type.


76-76: Access updated to use pointer dereference

The change in the CDeterministicMNStateDiff::ToJson method correctly updates the access pattern to use pointer dereferencing for the netInfo member, consistent with its type change to a shared pointer.

src/evo/core_write.cpp (2)

70-70: Access updated to use pointer dereference

The change in CProRegTx::ToJson() method correctly updates the access pattern for the netInfo member to use pointer dereferencing, consistent with the refactoring of this member to a shared pointer type.


117-117: Access updated to use pointer dereference

The change in CProUpServTx::ToJson() method correctly updates the access pattern for the netInfo member to use pointer dereferencing, consistent with the refactoring of this member to a shared pointer type.

src/test/block_reward_reallocation_tests.cpp (2)

119-119: Initialized netInfo with the new shared_ptr-based approach.

The code correctly initializes the netInfo member of proTx using the MakeNetInfo function, which creates a std::shared_ptr<NetInfoInterface>. This aligns with the implementation of type-flexible network info entries.


121-121: Updated access syntax to use pointer dereference.

The code has been properly updated to use pointer dereferencing (->) instead of direct member access (.) to call the AddEntry method on the netInfo shared pointer. This change matches the transition to pointer-based access in the netInfo refactoring.

src/txmempool.h (2)

20-20: Added necessary header for NetInfoEntry.

The include for evo/netinfo.h is correctly added to provide access to the NetInfoEntry class and related types used in the mempool implementation.


529-529: Updated map key type from CService to NetInfoEntry.

The code now uses NetInfoEntry instead of CService as the key type in mapProTxAddresses. This is a necessary change to support the new type-flexible network information entries.

src/txmempool.cpp (8)

694-697: Updated iteration over network entries in addUncheckedProTx.

The code has been modified to use the new pointer-based netInfo->GetEntries() access pattern and correctly iterates over NetInfoEntry objects instead of CService objects.


707-709: Updated iteration over network entries in addUncheckedProTx for update service.

The code correctly uses the pointer-based access for NetInfo entries in the provider update service transaction processing path.


798-800: Updated iteration over network entries in removeUncheckedProTx.

The removal of ProTx entries now correctly uses the pointer-based access pattern for the network info entries.


808-810: Updated iteration over network entries in removeUncheckedProTx for update service.

The code properly handles the removal of service update transactions with the new pointer-based access pattern for network entries.


1037-1044: Updated iteration and conflict checking for network entries in removeProTxConflicts.

The code now iterates over NetInfoEntry objects using pointer-based access and handles conflict detection correctly with the new type.


1059-1066: Updated iteration and conflict checking for update service transactions.

The code correctly handles conflict detection for service update transactions using the new NetInfoEntry type and pointer-based access pattern.


1397-1401: Updated network entry iteration in existsProviderTxConflict.

The code now properly iterates over NetInfoEntry objects when checking for provider transaction conflicts.


1422-1427: Updated network entry iteration in existsProviderTxConflict for update service.

The conflict detection code for service update transactions has been correctly updated to use the new network info entry type.

src/evo/deterministicmns.h (1)

401-403: Added type exclusions for GetUniquePropertyHash template method.

The code adds necessary exclusions to prevent GetUniquePropertyHash from being instantiated with the new network info types (NetInfoEntry, NetInfoInterface, and std::shared_ptr<NetInfoInterface>). This prevents potential misuse of these types with the generic hash calculation method, which may not be appropriate for the network info classes.

src/rpc/evo.cpp (1)

979-983: Possible state loss when rebuilding netInfo for ProUpServTx

ptx.netInfo = MakeNetInfo(ptx); discards the current net-info entries stored
in dmn->pdmnState->netInfo (e.g. Tor/I2P addr or multiple addresses).
If the update only intends to change the service address, the other previously
valid entries are silently dropped.

Consider cloning the existing object instead:

ptx.netInfo = std::make_shared<MnNetInfo>(*dmn->pdmnState->netInfo);

or provide a Clone() in NetInfoInterface.

src/rpc/masternode.cpp (1)

618-619: Guard against empty entries and clarify key naming
GetPrimary() assumes at least one entry exists; if netInfo->GetEntries() is empty this will crash. Consider returning std::optional<NetInfoEntry> or asserting non-emptiness before calling. Also, renaming the JSON key to "primary_address" may improve clarity now that multiple addresses exist.

src/net.cpp (7)

3677-3677: Access to netInfo updated to use pointer dereferencing

The code correctly updates the access pattern from direct member access (netInfo.GetPrimary()) to pointer dereferencing (netInfo->GetPrimary()), which aligns with the refactoring of masternode network information where netInfo changed from a concrete MnNetInfo object to a std::shared_ptr<NetInfoInterface>.


3743-3744: Updated conditional check using pointer dereferencing

The conditional check has been properly updated to use pointer dereferencing syntax for the netInfo member, consistent with the architectural change to std::shared_ptr<NetInfoInterface>.


3752-3753: Log message updated to use pointer-based accessor

The log formatting code correctly uses the new pointer dereferencing syntax to access the primary address from netInfo.


3763-3763: Updated probing log message

The log message for masternode probing has been properly updated to use pointer dereferencing syntax for accessing the primary address.


3779-3779: OpenMasternodeConnection call updated

The call to OpenMasternodeConnection now correctly uses the pointer dereferencing syntax to access the primary address from the netInfo shared pointer.


3781-3781: ForNode call updated to use pointer dereferencing

The call to ForNode has been properly updated to use the pointer dereferencing syntax when accessing the primary network address.


3788-3788: Connection failure log message updated

The log message for connection failures has been correctly updated to use pointer dereferencing for accessing the primary address from the netInfo shared pointer.

src/evo/dmnstate.h (2)

115-116: Good move – re-initialises after operator reset

Re-creating netInfo via MakeNetInfo instead of calling Clear() on a concrete type is the correct abstraction-preserving approach.


249-252: Missing dependency flag for netInfo diff field

pubKeyOperator requires nVersion; netInfo may equally depend on nVersion (e.g. if validation rules vary between versions). If that is the case, emit Field_nVersion when Field_netInfo is present, mirroring the logic above for pubKeyOperator. Otherwise upgrading rules in the future will silently mis-interpret old diffs.

src/test/evo_deterministicmns_tests.cpp (1)

637-641: Good adaptation to new API

The test correctly creates a fresh MnNetInfo for the payload and validates the return code.

src/test/evo_netinfo_tests.cpp (2)

14-15: Switch to BasicTestingSetup improves realism

Great choice – this now exercises mainnet-like port rules and caught the earlier BadPort bug.

🧰 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)


55-60: Good assertion change on malformed vs. success

The distinction between Malformed/Success aligns with new status codes.

Comment on lines 188 to 190
if (!mixingMasternode) return;
if (mixingMasternode->pdmnState->netInfo.GetPrimary() != peer.addr) return;
if (mixingMasternode->pdmnState->netInfo->GetPrimary() != peer.addr) return;

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Guard against nullptr before dereferencing netInfo

mixingMasternode->pdmnState->netInfo is assumed to be non-null, but there is no invariant guaranteeing this.
If a masternode state gets deserialised incorrectly or a future refactor forgets to initialise netInfo, this line will seg-fault long before any validation code notices.

-    if (mixingMasternode->pdmnState->netInfo->GetPrimary() != peer.addr) return;
+    if (!mixingMasternode->pdmnState ||            // paranoia
+        !mixingMasternode->pdmnState->netInfo ||   // make sure pointer exists
+        mixingMasternode->pdmnState->netInfo->IsEmpty() ||
+        mixingMasternode->pdmnState->netInfo->GetPrimary() != peer.addr) {
+        return;
+    }

The same pattern appears in multiple places below (see lines ~1109, ~1181, ~1220, ~1823).
Consider introducing a small helper, GetMnPrimaryService(const CDeterministicMNState* state), that returns an
std::optional<CService> and centralises the null/empty checks.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!mixingMasternode) return;
if (mixingMasternode->pdmnState->netInfo.GetPrimary() != peer.addr) return;
if (mixingMasternode->pdmnState->netInfo->GetPrimary() != peer.addr) return;
if (!mixingMasternode) return;
- if (mixingMasternode->pdmnState->netInfo->GetPrimary() != peer.addr) return;
+ if (!mixingMasternode->pdmnState || // paranoia
+ !mixingMasternode->pdmnState->netInfo || // make sure pointer exists
+ mixingMasternode->pdmnState->netInfo->IsEmpty() ||
+ mixingMasternode->pdmnState->netInfo->GetPrimary() != peer.addr) {
+ return;
+ }

Comment on lines 101 to 103
EncodeDestination(PKHash(keyIDVoting)), payee, platformNodeID.ToString(), platformP2PPort,
platformHTTPPort, netInfo.ToString());
platformHTTPPort, netInfo->ToString());
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

ToString() unsafe when netInfo is null

netInfo->ToString() will crash if the pointer is missing. Guard or fall back to "{}".

Comment on lines 39 to 44
for (const NetInfoEntry& entry : netInfo->GetEntries()) {
if (!entry.IsTriviallyValid()) {
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-netinfo-bad");
}
}

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing null / empty test before iterating netInfo

netInfo may legally be nullptr (see header) or empty, yet the loop unconditionally
dereferences it. Add an early check akin to the CProUpServTx case:

-    for (const NetInfoEntry& entry : netInfo->GetEntries()) {
+    if (!netInfo || netInfo->IsEmpty()) {
+        return state.Invalid(TxValidationResult::TX_BAD_SPECIAL,
+                             "bad-protx-netinfo-empty");
+    }
+    for (const NetInfoEntry& entry : netInfo->GetEntries()) {

Also consider harmonising error codes – CProUpServTx already uses
bad-protx-netinfo-empty.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const NetInfoEntry& entry : netInfo->GetEntries()) {
if (!entry.IsTriviallyValid()) {
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-netinfo-bad");
}
}
if (!netInfo || netInfo->IsEmpty()) {
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL,
"bad-protx-netinfo-empty");
}
for (const NetInfoEntry& entry : netInfo->GetEntries()) {
if (!entry.IsTriviallyValid()) {
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-netinfo-bad");
}
}

Comment on lines 579 to 578
BOOST_REQUIRE(dmn != nullptr && dmn->pdmnState->netInfo->GetPrimary().GetPort() == 100);
BOOST_REQUIRE(dmn != nullptr && !dmn->pdmnState->IsBanned());
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Repeat of previous null-ptr issue

Same protective check should be added here.

 BOOST_REQUIRE(dmn != nullptr);
+BOOST_REQUIRE(dmn->pdmnState->netInfo);
 BOOST_REQUIRE(dmn->pdmnState->netInfo->GetPrimary().GetPort() == 100);

Committable suggestion skipped: line range outside the PR's diff.

@kwvg kwvg marked this pull request as draft May 10, 2025 01:04
@kwvg kwvg marked this pull request as ready for review May 10, 2025 11:47
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: 1

♻️ Duplicate comments (1)
src/evo/dmnstate.h (1)

57-57: 🛠️ Refactor suggestion

Consider initializing netInfo to prevent null dereference

The netInfo shared_ptr is initialized to nullptr, which could lead to dereference crashes if not properly checked. Since it's reset in ResetOperatorFields() but might be accessed before that call, consider initializing it with MakeNetInfo(*this) here instead.

-    std::shared_ptr<NetInfoInterface> netInfo{nullptr};
+    std::shared_ptr<NetInfoInterface> netInfo{MakeNetInfo(*this)};
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8e8ad0b and d342d12.

📒 Files selected for processing (26)
  • src/coinjoin/client.cpp (6 hunks)
  • src/evo/core_write.cpp (2 hunks)
  • src/evo/deterministicmns.cpp (12 hunks)
  • src/evo/deterministicmns.h (1 hunks)
  • src/evo/dmnstate.cpp (2 hunks)
  • src/evo/dmnstate.h (4 hunks)
  • src/evo/netinfo.cpp (3 hunks)
  • src/evo/netinfo.h (1 hunks)
  • src/evo/providertx.cpp (4 hunks)
  • src/evo/providertx.h (4 hunks)
  • src/evo/simplifiedmns.cpp (2 hunks)
  • src/evo/simplifiedmns.h (3 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 (3 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 (2 hunks)
  • src/test/evo_simplifiedmns_tests.cpp (1 hunks)
  • src/txmempool.cpp (8 hunks)
  • src/txmempool.h (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/masternode/utils.cpp
🚧 Files skipped from review as they are similar to previous changes (21)
  • src/llmq/utils.cpp
  • src/test/block_reward_reallocation_tests.cpp
  • src/qt/masternodelist.cpp
  • src/evo/core_write.cpp
  • src/masternode/node.cpp
  • src/evo/dmnstate.cpp
  • src/txmempool.cpp
  • src/evo/simplifiedmns.cpp
  • src/evo/simplifiedmns.h
  • src/evo/deterministicmns.h
  • src/rpc/quorums.cpp
  • src/txmempool.h
  • src/rpc/masternode.cpp
  • src/rpc/evo.cpp
  • src/evo/providertx.cpp
  • src/test/evo_simplifiedmns_tests.cpp
  • src/evo/providertx.h
  • src/coinjoin/client.cpp
  • src/net.cpp
  • src/test/evo_deterministicmns_tests.cpp
  • src/evo/deterministicmns.cpp
🧰 Additional context used
🧠 Learnings (3)
src/test/evo_netinfo_tests.cpp (1)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/test/evo_netinfo_tests.cpp:39-45
Timestamp: 2025-05-10T00:55:16.173Z
Learning: In Dash's validation testing for network entries, checking `IsTriviallyValid()` is specifically used to ensure all three validation methods (`AddEntry()`, `Validate()`, and `IsTriviallyValid()`) consistently work together rather than replacing one check with another. `AddEntry()` and `Validate()` handle the consensus rule checks, while `IsTriviallyValid()` confirms the basic validation steps.
src/evo/netinfo.cpp (2)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/deterministicmns.cpp:473-485
Timestamp: 2025-05-10T00:54:15.567Z
Learning: In the current implementation of `NetInfoEntry`, only `CService` is a valid type and `std::monostate` represents an invalid state. Entries that don't provide a valid `CService` through `GetAddrPort()` should be rejected with an exception, not silently skipped.
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/netinfo.cpp:186-196
Timestamp: 2025-05-10T00:54:10.965Z
Learning: `std::reference_wrapper<T>` can be implicitly constructed from lvalue references (T&) through its forwarding reference constructor template. Explicit use of std::ref/std::cref is not required when pushing references into containers like vectors of reference_wrappers.
src/evo/netinfo.h (1)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/netinfo.h:248-256
Timestamp: 2025-05-10T00:54:30.868Z
Learning: The Dash codebase includes a specialization for serializing std::shared_ptr objects in src/serialize.h, which allows direct serialization of shared_ptr instances with stream operators.
🧬 Code Graph Analysis (1)
src/evo/dmnstate.h (1)
src/evo/netinfo.h (7)
  • NetInfoSerWrapper (241-241)
  • NetInfoSerWrapper (242-242)
  • NetInfoSerWrapper (243-246)
  • NetInfoSerWrapper (247-247)
  • NetInfoSerWrapper (249-249)
  • MakeNetInfo (229-233)
  • MakeNetInfo (229-229)
🪛 GitHub Actions: Clang Diff Format Check
src/evo/dmnstate.h

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

src/evo/netinfo.h

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


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

🪛 Cppcheck (2.10-2)
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: linux64_multiprocess-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: mac-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: linux64-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: win64-build / Build source
🔇 Additional comments (11)
src/evo/dmnstate.h (1)

98-104:

❓ Verification inconclusive

Clang format error detected

The clang-format check is failing for this section of code. Please format this block according to the project's style guidelines.


🏁 Script executed:

#!/bin/bash
# Check which exact formatting issues are present
git diff --check || true

Length of output: 18


Please verify clang-format compliance for the affected block

I ran git diff --check (whitespace check) and didn’t find any issues, but that doesn’t guarantee full .clang-format compliance. Please double-check that this section in src/evo/dmnstate.h (lines 98–104) is formatted according to the project’s style (for example, by running your local clang-format check or reviewing the CI logs).

• File: src/evo/dmnstate.h
• Lines: 98–104

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

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

src/test/evo_netinfo_tests.cpp (4)

14-15: Updated test fixture to BasicTestingSetup aligns with PR objectives

Changing from RegTestingSetup to BasicTestingSetup properly implements the PR objective to simulate mainnet conditions, providing stricter validation coverage as mentioned in the PR description.

🧰 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)


39-45: The validation triangle approach is appropriate

Using IsTriviallyValid() in ValidateGetEntries() maintains consistency with your approach of ensuring all three validation methods (AddEntry(), Validate(), and IsTriviallyValid()) work harmoniously together, as clarified in the previous review.


63-69: Good test for MaxLimit validation

This new test case correctly verifies that MnNetInfo enforces the single-entry limit by rejecting additional entries with a MaxLimit status, consistent with the updated AddEntry logic.


72-78: Well-designed serialization compatibility check

The CheckIfSerSame helper function is a clean approach to compare serialized representations, supporting the new compatibility checks between CService and MnNetInfo.

src/evo/netinfo.cpp (2)

29-37: Effective input validation approach

The MatchCharsFilter function provides an efficient way to quickly reject invalid inputs before more expensive operations like DNS lookups, aligning with the PR objective of introducing a fast-failing mechanism.


209-235: Comprehensive validation approach

The approach of checking IsTriviallyValid() first before proceeding to detailed validation in Validate() creates a clear separation between basic structural validity and domain-specific validation rules, making the code more maintainable.

src/evo/netinfo.h (4)

154-155: Efficient reference-based collection

Using std::reference_wrapper in NetInfoList definition is an excellent choice, preventing unnecessary copying while maintaining reference semantics and standard container compatibility.


227-233: Extensible factory pattern

The MakeNetInfo function provides a clean extension point for potentially versioned implementations in the future while maintaining a consistent interface for users, good forward-thinking design.


71-90:

❓ Verification inconclusive

Clang format error detected

The clang-format check is failing for this section of code. Please format this block according to the project's style guidelines.


🏁 Script executed:

#!/bin/bash
# Check which exact formatting issues are present
git diff HEAD^ HEAD | grep -A 10 -B 10 "src/evo/netinfo.h" | grep -A 50 -B 5 "^+.*{" || true

Length of output: 93


Clang-format check inconclusive

I wasn’t able to reproduce any formatting errors in the diff for src/evo/netinfo.h. Please manually run clang-format against this file and confirm it adheres to the project’s style:

  • Run
    clang-format -style=file -i src/evo/netinfo.h
    git diff src/evo/netinfo.h
    
    to see if any changes are needed.
🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

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


183-210:

❓ Verification inconclusive

Clang format error detected

The clang-format check is failing for this section of code. Please format this block according to the project's style guidelines.


🏁 Script executed:

#!/bin/bash
# Check which exact formatting issues are present
git diff HEAD^ HEAD | grep -A 10 -B 10 "src/evo/netinfo.h" | grep -A 50 -B 5 "180-210" || true

Length of output: 93


🏁 Script executed:

#!/bin/bash
set -e

# Locate the header file
FILE=$(fd --exclude node_modules --type f netinfo.h | head -n 1)
if [[ -z "$FILE" ]]; then
  echo "netinfo.h not found"
  exit 1
fi

echo "Inspecting $FILE (lines 180-210):"
sed -n '180,210p' "$FILE"

echo -e "\nRunning clang-format dry-run (style=file) on $FILE:"
# Run clang-format in dry-run mode to detect style issues
clang-format -style=file --dry-run --Werror "$FILE" 2>&1 || true

Length of output: 1401


Format src/evo/netinfo.h (lines 180–210)
I couldn’t run clang-format in this environment to pinpoint the exact style violations. Please run the formatter locally (e.g.

clang-format -i --style=file src/evo/netinfo.h

) or check your CI logs and commit the resulting changes to ensure this block conforms to the project’s style guidelines.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

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

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 (2)
src/test/evo_netinfo_tests.cpp (1)

80-110: Test lacks verification of IPv6 rejection behavior described in PR

The PR objectives mention a specific behavior: "MnNetInfo::AddEntry() rejecting IPv6 addresses with a BadInput error due to delimiter filtering, while validating an already stored IPv6 address returns a BadType error." However, this test only verifies the BadInput error from AddEntry() but doesn't test the different error code (BadType) when validating an already stored IPv6 address.

Consider adding a test case that:

  1. Creates a NetInfoEntry directly with an IPv6 CService
  2. Verifies that Validate() returns BadType instead of BadInput
// Test IPv6 rejection behavior difference
{
    CService ipv6 = LookupNumeric("[2606:4700:4700::1111]", 9999);
    MnNetInfo netInfo;
    
    // Direct construction bypasses delimiter filtering
    netInfo.m_addr = NetInfoEntry{ipv6};
    
    // Should return BadType, not BadInput
    BOOST_CHECK_EQUAL(netInfo.Validate(), NetInfoStatus::BadType);
}
src/evo/netinfo.cpp (1)

29-37: Consider more descriptive naming for the filtering function

The function checks if all characters in the input are contained in the filter set (i.e., it only allows characters from the filter).

A more descriptive name would be ContainsOnlyAllowedChars or HasOnlyAllowedChars to better convey the purpose.

-bool MatchCharsFilter(const std::string& input, const std::string_view& filter)
+bool ContainsOnlyAllowedChars(const std::string& input, const std::string_view& filter)
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d342d12 and 076abb3.

📒 Files selected for processing (25)
  • src/coinjoin/client.cpp (6 hunks)
  • src/evo/core_write.cpp (2 hunks)
  • src/evo/deterministicmns.cpp (12 hunks)
  • src/evo/deterministicmns.h (1 hunks)
  • src/evo/dmnstate.cpp (2 hunks)
  • src/evo/dmnstate.h (4 hunks)
  • src/evo/netinfo.cpp (3 hunks)
  • src/evo/netinfo.h (1 hunks)
  • src/evo/providertx.cpp (4 hunks)
  • src/evo/providertx.h (4 hunks)
  • src/evo/simplifiedmns.cpp (2 hunks)
  • src/evo/simplifiedmns.h (3 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 (3 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 (2 hunks)
  • src/test/evo_simplifiedmns_tests.cpp (1 hunks)
  • src/txmempool.cpp (8 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/llmq/utils.cpp
🚧 Files skipped from review as they are similar to previous changes (21)
  • src/masternode/utils.cpp
  • src/masternode/node.cpp
  • src/evo/dmnstate.cpp
  • src/evo/deterministicmns.h
  • src/test/block_reward_reallocation_tests.cpp
  • src/evo/core_write.cpp
  • src/rpc/masternode.cpp
  • src/rpc/quorums.cpp
  • src/test/evo_simplifiedmns_tests.cpp
  • src/evo/simplifiedmns.h
  • src/txmempool.cpp
  • src/qt/masternodelist.cpp
  • src/evo/providertx.cpp
  • src/evo/simplifiedmns.cpp
  • src/evo/dmnstate.h
  • src/rpc/evo.cpp
  • src/coinjoin/client.cpp
  • src/evo/providertx.h
  • src/test/evo_deterministicmns_tests.cpp
  • src/net.cpp
  • src/evo/deterministicmns.cpp
🧰 Additional context used
🧠 Learnings (3)
src/test/evo_netinfo_tests.cpp (1)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/test/evo_netinfo_tests.cpp:39-45
Timestamp: 2025-05-10T00:55:16.173Z
Learning: In Dash's validation testing for network entries, checking `IsTriviallyValid()` is specifically used to ensure all three validation methods (`AddEntry()`, `Validate()`, and `IsTriviallyValid()`) consistently work together rather than replacing one check with another. `AddEntry()` and `Validate()` handle the consensus rule checks, while `IsTriviallyValid()` confirms the basic validation steps.
src/evo/netinfo.cpp (2)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/deterministicmns.cpp:473-485
Timestamp: 2025-05-10T00:54:15.567Z
Learning: In the current implementation of `NetInfoEntry`, only `CService` is a valid type and `std::monostate` represents an invalid state. Entries that don't provide a valid `CService` through `GetAddrPort()` should be rejected with an exception, not silently skipped.
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/netinfo.cpp:186-196
Timestamp: 2025-05-10T00:54:10.965Z
Learning: `std::reference_wrapper<T>` can be implicitly constructed from lvalue references (T&) through its forwarding reference constructor template. Explicit use of std::ref/std::cref is not required when pushing references into containers like vectors of reference_wrappers.
src/evo/netinfo.h (1)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/netinfo.h:248-256
Timestamp: 2025-05-10T00:54:30.868Z
Learning: The Dash codebase includes a specialization for serializing std::shared_ptr objects in src/serialize.h, which allows direct serialization of shared_ptr instances with stream operators.
🧬 Code Graph Analysis (1)
src/evo/netinfo.h (1)
src/evo/netinfo.cpp (4)
  • rhs (40-51)
  • rhs (40-40)
  • rhs (53-73)
  • rhs (53-53)
🪛 Cppcheck (2.10-2)
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)

🪛 GitHub Actions: Clang Diff Format Check
src/evo/netinfo.h

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


[error] 183-210: 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_ubsan-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: linux64_multiprocess-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: arm-linux-build / Build source
🔇 Additional comments (25)
src/test/evo_netinfo_tests.cpp (6)

14-14: Test fixture changed to BasicTestingSetup for improved test coverage

The switch from RegTestingSetup to BasicTestingSetup aligns with the PR objectives to provide stricter validation coverage by simulating mainnet conditions rather than regtest.

🧰 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)


16-37: LGTM: Test vectors updated with more specific error codes

The test vectors now properly reflect the expanded NetInfoStatus enum with more specific error codes such as BadAddress, BadType, NotRoutable, etc. This provides better test coverage for the detailed validation behavior.


39-45: Appropriate use of IsTriviallyValid() in test validation

This function now correctly takes NetInfoList instead of CServiceList and validates each entry using IsTriviallyValid(). This approach properly aligns with the PR's validation strategy where all three validation methods (AddEntry(), Validate(), and IsTriviallyValid()) work together consistently.


54-56: Status code updated for clarity

The change from a generic error to NetInfoStatus::Malformed for empty MnNetInfo objects aligns with the improved error reporting in the PR.


63-69: Good test for single-entry limit enforcement

This test case properly verifies that MnNetInfo enforces its single-entry constraint by rejecting additional entries with a MaxLimit status.


72-78: Verify serialization consistency between CService and MnNetInfo

The helper function correctly compares serialized representations to ensure backward compatibility.

src/evo/netinfo.cpp (10)

16-19: LGTM: Added empty service constant and character filter

These additions support the new validation approach with a static empty service for fallback and a constant for fast validation of IPv4 inputs.


40-73: The comparison operators are well-implemented for variant types

These operators correctly handle comparison of the variant types in NetInfoEntry, providing proper equality and ordering semantics necessary for container usage.


75-82: Safe accessor with appropriate debug assertion

The GetAddrPort method safely accesses the underlying CService with proper type checking and includes an assertion for debug builds to catch programmer errors early.


84-107: Clear implementation of IsTriviallyValid with good documentation

The implementation properly checks that the entry is correctly constructed with valid data, and the comment clearly explains its role in the validation hierarchy.


109-135: LGTM: String conversion methods handle all variant cases

These methods properly convert each variant type to an appropriate string representation, with fallback for invalid entries.


137-158: LGTM: Strong implementation of polymorphic equality comparison

The IsEqual method handles all the edge cases for comparing shared pointers to interface objects: null checks, identity checks, and proper downcasting for deep comparison.


160-182: Improved service validation with specific error codes

The ValidateService method now returns more specific error codes like BadAddress, BadType, and NotRoutable instead of generic errors, aligning with the PR objectives.


184-207: Fast-failing input validation improves performance

The AddEntry method now implements a fast character-based pre-filter before the more expensive lookup and validation, which aligns with the PR's optimization goals.


209-219: GetEntries now returns NetInfoList with proper reference handling

The implementation correctly uses the implicit conversion from T& to std::reference_wrapper when pushing into the vector, as noted in the retrieved learning.


221-235: LGTM: GetPrimary and Validate methods handle empty/invalid cases

These methods correctly handle the case when there's no valid entry, returning an empty service or appropriate error code.

src/evo/netinfo.h (9)

17-29: LGTM: Expanded NetInfoStatus enum with more specific codes

The enum now provides more granular error reporting with categories for entry management and validation issues.


32-52: Error message strings updated for new status codes

The NISToString function properly handles all the new enum values with descriptive error messages.


54-65: Implementation limits initial type support despite PR title

While the PR title mentions allowing "non-CService entries", the NetInfoType enum only defines Service (0x01) and Invalid (0xff), without additional type codes for other entry types.

Does this implementation set the foundation for other entry types that will be added later, or is the PR title referring to a different aspect of flexibility? The current implementation only supports CService as a valid type.


66-153: LGTM: Well-designed NetInfoEntry class with proper variant handling

The NetInfoEntry class correctly handles serialization, deserialization, construction, and validation with appropriate error handling and ADDRV2_FORMAT support as mentioned in the PR objectives.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

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


157-174: Clean interface design with polymorphic methods

The NetInfoInterface provides a well-defined abstract interface for different network info implementations, supporting the extensibility goal mentioned in the PR objectives.


176-182: MnNetInfo updated to use NetInfoEntry and implement interface

The class now properly implements the NetInfoInterface and uses NetInfoEntry for storage.


193-214: LGTM: Serialization maintains backward compatibility

The Serialize/Unserialize methods properly handle the transition between NetInfoEntry and CService, maintaining compatibility as mentioned in the PR objectives.


227-233: Factory method prepared for future versioning

The MakeNetInfo template function sets up infrastructure for version-based instantiation of appropriate implementations, though currently it always returns MnNetInfo.


235-273:

❓ Verification inconclusive

Strong serialization wrapper with proper error handling

The NetInfoSerWrapper correctly handles serialization of shared pointers to interface objects, with proper type checking and error handling.


🏁 Script executed:

#!/bin/bash
# Check for clang-format issues
git diff --name-only | grep -E '\.cpp$|\.h$' | xargs clang-format -style=file --Werror --dry-run

Length of output: 145


Approve serialization wrapper – formatting verification needed

The NetInfoSerWrapper implementation correctly handles serialization of std::shared_ptr<NetInfoInterface> with proper type checking and error handling. However, the automated clang-format check could not run in this environment (clang-format not found). Please run the following locally to ensure style compliance:

git diff --name-only | grep -E '\.cpp$|\.h$' | xargs clang-format -style=file --Werror --dry-run

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/test/evo_netinfo_tests.cpp (1)

39-45: NetInfoList API properly validates entries

The ValidateGetEntries function has been updated to work with the new NetInfoList type (vector of references to NetInfoEntry) and validates that each entry passes IsTriviallyValid(). This approach correctly ensures consistency between the validation methods as highlighted in the previous feedback.

src/evo/netinfo.h (1)

235-273: Serialization wrapper ensures type safety

The NetInfoSerWrapper class correctly:

  1. Wraps shared pointers to NetInfoInterface
  2. Enforces type safety through dynamic casting
  3. Throws descriptive exceptions on malformed data
  4. Uses the specialized shared_ptr serialization in the codebase

This ensures proper serialization of the polymorphic types.

🧹 Nitpick comments (1)
src/evo/netinfo.h (1)

71-90: Fix clang-format issues in highlighted regions

The pipeline has identified formatting issues in these line ranges. Please run clang-format on these sections to fix the formatting.

Also applies to: 183-210

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 71-90: 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 076abb3 and 4058151.

📒 Files selected for processing (25)
  • src/coinjoin/client.cpp (6 hunks)
  • src/evo/core_write.cpp (2 hunks)
  • src/evo/deterministicmns.cpp (12 hunks)
  • src/evo/deterministicmns.h (1 hunks)
  • src/evo/dmnstate.cpp (2 hunks)
  • src/evo/dmnstate.h (4 hunks)
  • src/evo/netinfo.cpp (3 hunks)
  • src/evo/netinfo.h (1 hunks)
  • src/evo/providertx.cpp (4 hunks)
  • src/evo/providertx.h (4 hunks)
  • src/evo/simplifiedmns.cpp (2 hunks)
  • src/evo/simplifiedmns.h (3 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 (3 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 (2 hunks)
  • src/test/evo_simplifiedmns_tests.cpp (1 hunks)
  • src/txmempool.cpp (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (22)
  • src/masternode/utils.cpp
  • src/test/block_reward_reallocation_tests.cpp
  • src/llmq/utils.cpp
  • src/evo/dmnstate.cpp
  • src/qt/masternodelist.cpp
  • src/txmempool.cpp
  • src/rpc/quorums.cpp
  • src/test/evo_simplifiedmns_tests.cpp
  • src/evo/deterministicmns.h
  • src/evo/simplifiedmns.cpp
  • src/evo/providertx.cpp
  • src/rpc/evo.cpp
  • src/evo/simplifiedmns.h
  • src/evo/dmnstate.h
  • src/rpc/masternode.cpp
  • src/evo/core_write.cpp
  • src/test/evo_deterministicmns_tests.cpp
  • src/masternode/node.cpp
  • src/evo/providertx.h
  • src/coinjoin/client.cpp
  • src/net.cpp
  • src/evo/deterministicmns.cpp
🧰 Additional context used
🧠 Learnings (3)
src/test/evo_netinfo_tests.cpp (1)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/test/evo_netinfo_tests.cpp:39-45
Timestamp: 2025-05-10T00:55:16.173Z
Learning: In Dash's validation testing for network entries, checking `IsTriviallyValid()` is specifically used to ensure all three validation methods (`AddEntry()`, `Validate()`, and `IsTriviallyValid()`) consistently work together rather than replacing one check with another. `AddEntry()` and `Validate()` handle the consensus rule checks, while `IsTriviallyValid()` confirms the basic validation steps.
src/evo/netinfo.h (1)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/netinfo.h:248-256
Timestamp: 2025-05-10T00:54:30.868Z
Learning: The Dash codebase includes a specialization for serializing std::shared_ptr objects in src/serialize.h, which allows direct serialization of shared_ptr instances with stream operators.
src/evo/netinfo.cpp (2)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/deterministicmns.cpp:473-485
Timestamp: 2025-05-10T00:54:15.567Z
Learning: In the current implementation of `NetInfoEntry`, only `CService` is a valid type and `std::monostate` represents an invalid state. Entries that don't provide a valid `CService` through `GetAddrPort()` should be rejected with an exception, not silently skipped.
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/netinfo.cpp:186-196
Timestamp: 2025-05-10T00:54:10.965Z
Learning: `std::reference_wrapper<T>` can be implicitly constructed from lvalue references (T&) through its forwarding reference constructor template. Explicit use of std::ref/std::cref is not required when pushing references into containers like vectors of reference_wrappers.
🪛 Cppcheck (2.10-2)
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)

🪛 GitHub Actions: Clang Diff Format Check
src/evo/netinfo.h

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


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

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: win64-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: x86_64-pc-linux-gnu / Build depends
🔇 Additional comments (15)
src/test/evo_netinfo_tests.cpp (4)

14-15: Improved test setup to match production environment

Changing from RegTestingSetup to BasicTestingSetup ensures tests run in conditions that more closely mirror mainnet, providing stricter validation coverage. This change aligns with the PR objective of preventing incorrect validation rules from being applied.

🧰 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)


16-37: Test vectors updated to reflect accurate validation rules

The test vectors have been properly updated to test:

  1. Non-mainnet port validation on mainnet (line 22)
  2. Internal address rejection on mainnet (line 24)
  3. More specific error codes, like changing from BadInput to BadAddress for invalid IPv4 (line 26)

These changes properly validate the port enforcement rules mentioned in the PR objectives, ensuring that valid addr:port combinations on mainnet no longer fail incorrectly.


63-69: Verify single-entry constraint for MnNetInfo

Good addition of a test case that verifies the single-entry constraint for MnNetInfo, confirming that attempts to add a second entry are rejected with NetInfoStatus::MaxLimit.


72-110: Comprehensive serialization compatibility tests

The new CheckIfSerSame helper and cservice_compatible test case properly verify serialization compatibility between CService and MnNetInfo across multiple scenarios:

  1. Empty values
  2. Valid IPv4 addresses
  3. Invalid inputs (domains, IPv6)

These tests ensure backward compatibility with the serialization format, which is critical for a blockchain application.

src/evo/netinfo.cpp (8)

16-18: Static empty service and character filter for fast validation

Good introduction of:

  1. A static empty service for consistent empty object returns
  2. A character filter for IPv4 to enable fast failing for invalid addresses

This aligns with the PR's goal of introducing a fast-failing mechanism based on permitted characters.


29-37: Helper for character validation enhances code maintainability

The MatchCharsFilter function provides a clean way to validate input strings against character sets, which is used for pre-filtering address inputs before more expensive validation. This implementation supports the fast-failing mechanism mentioned in the PR objectives.


75-82: Robust GetAddrPort implementation returns std::optional

The GetAddrPort method properly uses std::optional to safely retrieve the underlying CService from the variant, with appropriate validation checks. This provides clean error handling for cases where the service is invalid.


87-107: IsTriviallyValid implementation provides fast validation

The IsTriviallyValid method performs quick validation without expensive checks, properly examining both type and basic validity. The comment at lines 84-86 correctly documents the purpose of this method in relation to the validation responsibility hierarchy.


137-158: IsEqual implementation handles pointer comparison edge cases

The NetInfoInterface::IsEqual static method correctly handles:

  1. Same object reference (or both null)
  2. Unequal initialization status
  3. Type checking through dynamic_pointer_cast
  4. Deep comparison when types match

This is important for correct equality testing in the polymorphic design.


186-207: AddEntry implements single-entry constraint and fast filtering

The MnNetInfo::AddEntry method now:

  1. Checks for existing entries (MaxLimit)
  2. Parses host and port separately
  3. Fast-fails on invalid characters before expensive lookup

These changes improve input validation performance and enforce the single-entry constraint described in the PR.


221-227: GetPrimary safely handles invalid entries

The GetPrimary method properly checks if the underlying service exists before returning it, falling back to the static empty service when needed. This prevents null pointer dereferences and provides consistent behavior.


229-235: Two-stage validation improves performance

The Validate method performs a quick check with IsTriviallyValid before proceeding to the more expensive ValidateService, which is an efficient approach to validation.

src/evo/netinfo.h (3)

16-52: Enhanced NetInfoStatus enum provides more specific error codes

The NetInfoStatus enum has been expanded with new error codes:

  • MaxLimit for entry constraints
  • BadAddress, BadType, and NotRoutable for specific validation failures
  • Malformed for internal structure issues

This enhances error reporting as mentioned in the PR objectives.


54-156: Type-flexible NetInfoEntry uses variant for extensibility

The NetInfoEntry class correctly implements:

  1. Type-safe variant storage with std::variant
  2. Proper serialization with ADDRV2_FORMAT flag
  3. Comparison operators for sorting and equality
  4. Utility methods for validation and string conversion

This design allows for future extension beyond CService types as mentioned in the PR objectives.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

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


157-174: NetInfoInterface enables polymorphic usage

The abstract NetInfoInterface class provides a clean interface with:

  1. Entry management methods (AddEntry, GetEntries)
  2. Accessor methods (GetPrimary, IsEmpty)
  3. Validation and conversion methods (Validate, ToString)
  4. A static IsEqual method for deep comparison

This polymorphic design supports the architecture described in the PR.

@kwvg kwvg requested review from knst and UdjinM6 May 10, 2025 13:06
@kwvg kwvg requested a review from PastaPastaPasta May 10, 2025 13:06
@kwvg kwvg force-pushed the netinfo_p2 branch 2 times, most recently from 282daa7 to 0388f0e Compare May 11, 2025 23:13
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)

53-61: Added check for malformed validation after failed entry addition

This validates that the MnNetInfo object correctly reports Malformed status when entries fail to be added, and Success when they are valid, completing the validation triangle between AddEntry, Validate, and IsTriviallyValid.

🧹 Nitpick comments (1)
src/evo/netinfo.h (1)

179-188: Fix clang-format issues

The pipeline indicates formatting issues in this section of code. Please run clang-format to resolve these issues.

#!/bin/bash
# Run clang-format on the file
clang-format -i src/evo/netinfo.h
🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 282daa7 and 0388f0e.

📒 Files selected for processing (9)
  • src/evo/deterministicmns.cpp (8 hunks)
  • src/evo/deterministicmns.h (1 hunks)
  • src/evo/netinfo.cpp (3 hunks)
  • src/evo/netinfo.h (2 hunks)
  • src/evo/providertx.cpp (2 hunks)
  • src/rpc/masternode.cpp (1 hunks)
  • src/test/evo_netinfo_tests.cpp (2 hunks)
  • src/txmempool.cpp (8 hunks)
  • src/txmempool.h (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/rpc/masternode.cpp
  • src/evo/deterministicmns.h
  • src/txmempool.h
  • src/txmempool.cpp
  • src/evo/providertx.cpp
  • src/evo/deterministicmns.cpp
🧰 Additional context used
🧠 Learnings (3)
src/evo/netinfo.h (2)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/netinfo.h:248-256
Timestamp: 2025-05-10T00:54:30.887Z
Learning: The Dash codebase includes a specialization for serializing std::shared_ptr objects in src/serialize.h, which allows direct serialization of shared_ptr instances with stream operators.
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/deterministicmns.cpp:473-485
Timestamp: 2025-05-10T00:54:15.597Z
Learning: In the current implementation of `NetInfoEntry`, only `CService` is a valid type and `std::monostate` represents an invalid state. Entries that don't provide a valid `CService` through `GetAddrPort()` should be rejected with an exception, not silently skipped.
src/evo/netinfo.cpp (2)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/deterministicmns.cpp:473-485
Timestamp: 2025-05-10T00:54:15.597Z
Learning: In the current implementation of `NetInfoEntry`, only `CService` is a valid type and `std::monostate` represents an invalid state. Entries that don't provide a valid `CService` through `GetAddrPort()` should be rejected with an exception, not silently skipped.
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/evo/netinfo.cpp:186-196
Timestamp: 2025-05-10T00:54:10.998Z
Learning: `std::reference_wrapper<T>` can be implicitly constructed from lvalue references (T&) through its forwarding reference constructor template. Explicit use of std::ref/std::cref is not required when pushing references into containers like vectors of reference_wrappers.
src/test/evo_netinfo_tests.cpp (1)
Learnt from: kwvg
PR: dashpay/dash#6629
File: src/test/evo_netinfo_tests.cpp:39-45
Timestamp: 2025-05-10T00:55:16.184Z
Learning: In Dash's validation testing for network entries, checking `IsTriviallyValid()` is specifically used to ensure all three validation methods (`AddEntry()`, `Validate()`, and `IsTriviallyValid()`) consistently work together rather than replacing one check with another. `AddEntry()` and `Validate()` handle the consensus rule checks, while `IsTriviallyValid()` confirms the basic validation steps.
🧬 Code Graph Analysis (2)
src/evo/netinfo.h (1)
src/evo/netinfo.cpp (4)
  • rhs (40-51)
  • rhs (40-40)
  • rhs (53-73)
  • rhs (53-53)
src/test/evo_netinfo_tests.cpp (2)
src/evo/netinfo.cpp (4)
  • rhs (40-51)
  • rhs (40-40)
  • rhs (53-73)
  • rhs (53-53)
src/evo/netinfo.h (10)
  • rhs (77-77)
  • rhs (78-78)
  • rhs (79-79)
  • rhs (79-79)
  • rhs (169-169)
  • rhs (169-169)
  • rhs (170-170)
  • rhs (170-170)
  • service (163-163)
  • service (195-195)
🪛 GitHub Actions: Clang Diff Format Check
src/evo/netinfo.h

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

🪛 GitHub Actions: Check Potential Conflicts
src/evo/netinfo.cpp

[error] 1-1: Merge conflict detected in this file requiring rebase.

src/test/evo_netinfo_tests.cpp

[error] 1-1: Merge conflict detected in this file requiring rebase.

🪛 Cppcheck (2.10-2)
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 (4)
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: x86_64-pc-linux-gnu / Build depends
🔇 Additional comments (31)
src/test/evo_netinfo_tests.cpp (7)

14-14: Change from RegTestingSetup to BasicTestingSetup aligns with PR objectives

This fixture change properly implements the PR's goal of testing with mainnet conditions to prevent port validation issues. BasicTestingSetup provides a simpler environment without the regtest-specific settings that were causing inconsistent validation.

🧰 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)


18-37: Updated test vectors reflect mainnet port requirements

The test vectors now use port 9999 (mainnet port) instead of 8888, and properly test both valid and invalid scenarios including:

  • Non-mainnet port rejection on mainnet (line 22)
  • Internal address non-routability on mainnet (line 24)
  • Changed error code from BadInput to more specific BadAddress for 0.0.0.0 (line 26)

This provides more precise validation coverage as described in the PR objectives.


39-45: Updated ValidateGetEntries to use NetInfoList and check triviality

Function signature and implementation now correctly work with the new NetInfoEntry abstraction, adding a check for IsTriviallyValid() on each entry to ensure completeness of validation.


63-69: Added test for single-entry constraint

This new test block verifies that MnNetInfo enforces the single-entry limit, rejecting additional entries with MaxLimit status. This aligns with the PR's changes to limit entry storage.


72-78: Added serialization compatibility helper

The CheckIfSerSame function properly verifies serialization compatibility between CService and MnNetInfo by comparing their hash representations, which is crucial for backward compatibility.


80-110: Added comprehensive serialization compatibility tests

This new test case ensures backward compatibility between CService and MnNetInfo serialization, testing empty values, valid IPv4 addresses with explicit and default ports, and failure cases. This is critical for ensuring the new NetInfoEntry abstraction maintains compatibility with existing serialized data.


1-1:

❌ Incorrect review comment

Fix merge conflict before merging

Pipeline failure indicates a merge conflict in this file. Please rebase your branch to resolve conflicts before merging.


🏁 Script executed:

#!/bin/bash
# Check if there are merge conflicts in the file
grep -n "<<<<<<< HEAD" "src/test/evo_netinfo_tests.cpp" || echo "No merge conflict markers found in current working copy"

Length of output: 176


No merge conflict markers detected in src/test/evo_netinfo_tests.cpp

The grep check confirmed there are no <<<<<<<, =======, or >>>>>>> markers remaining in this file, so the merge-conflict issue mentioned in the original comment no longer applies. You can ignore the previous “Fix merge conflict” request.

Likely an incorrect or invalid review comment.

🧰 Tools
🪛 GitHub Actions: Check Potential Conflicts

[error] 1-1: Merge conflict detected in this file requiring rebase.

src/evo/netinfo.h (9)

17-28: Extended NetInfoStatus enum with more specific error codes

The NetInfoStatus enum has been appropriately expanded with more descriptive status codes (MaxLimit, BadAddress, BadType, NotRoutable, Malformed) that provide clearer feedback on validation failures, as mentioned in the PR objectives.


31-52: Updated status code string representations

The status code string representations have been updated to match the expanded enum, providing human-readable descriptions for all possible validation outcomes.


54-107: New NetInfoEntry class with appropriate variant-based design

The NetInfoEntry class provides a type-flexible container for network info entries beyond CService as mentioned in the PR objectives. Key observations:

  • Uses variant with monostate for invalid state
  • Properly defines type code enum
  • Includes constructors and comparison operators
  • Implements serialization with ADDRV2_FORMAT enforcement

This is the core abstraction that enables the PR's goal of supporting entries beyond CService.


108-153: NetInfoEntry includes comprehensive utility methods

The class provides well-designed utility methods:

  • Clear() for resetting to invalid state
  • GetAddrPort() for safely accessing the CService data
  • IsTriviallyValid() for basic validation
  • ToString() methods for different formatting needs

These methods provide a comprehensive API for working with network info entries.


155-155: Added NetInfoList type alias for collections

This type alias correctly defines collections of NetInfoEntry references, which is used throughout the codebase for returning lists of entries.


160-160: Updated MnNetInfo to use NetInfoEntry instead of CService

This is the key change that implements the PR objective of using the type-flexible NetInfoEntry instead of directly using CService.


172-193: Updated MnNetInfo serialization for compatibility

The serialization and deserialization methods have been updated to:

  • Extract CService from NetInfoEntry for serialization
  • Fall back to empty CService when no valid service is available
  • Create NetInfoEntry from deserialized CService

This ensures backward compatibility with existing serialized data while supporting the new abstraction.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

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


195-204: Updated API methods for NetInfoEntry integration

The API methods have been properly updated to work with NetInfoEntry:

  • AddEntry signature remains the same for compatibility
  • GetEntries returns NetInfoList instead of CServiceList
  • GetPrimary provides access to the primary CService
  • Validate now returns more specific status codes
  • Clear resets the NetInfoEntry

This maintains API compatibility while enhancing functionality.


1-1:

❌ Incorrect review comment

Fix merge conflict before merging

Pipeline failure indicates a merge conflict in this file. Please rebase your branch to resolve conflicts before merging.


🏁 Script executed:

#!/bin/bash
# Check if there are merge conflicts in the file
grep -n "<<<<<<< HEAD" "src/evo/netinfo.h" || echo "No merge conflict markers found in current working copy"

Length of output: 163


No merge conflict markers remaining in src/evo/netinfo.h

I ran a check for common conflict markers (<<<<<<< HEAD) and found none—this file is already free of merge conflict markers. You can disregard the merge conflict warning.

Likely an incorrect or invalid review comment.

src/evo/netinfo.cpp (15)

16-18: Added static empty service and safe character filter

The empty_service provides a safe fallback when no valid service is available, and SAFE_CHARS_IPV4 defines the allowed characters for fast input validation, supporting the PR's goal of introducing a fast-failing mechanism.


29-37: Added MatchCharsFilter helper for input validation

This helper efficiently checks if a string contains only characters from a defined filter, supporting the fast-failing mechanism mentioned in the PR objectives for quickly classifying address types.


40-73: Implemented comparison operators for NetInfoEntry

The equality and ordering operators use std::visit to handle the variant content appropriately, with explicit handling for comparing different types and monostate (invalid state). This enables NetInfoEntry to be used in containers and comparisons.


75-82: Implemented GetAddrPort with appropriate validation

This method safely extracts the CService from the variant, using assertions to verify validity in debug builds and returning an optional reference for caller safety.


84-107: Well-documented IsTriviallyValid method

The method includes clear documentation explaining its purpose and properly handles all possible variant states, checking both type codes and underlying data validity.


109-149: Implemented string conversion methods

These methods properly handle all variant states, returning appropriate string representations for each case and handling invalid entries gracefully.


151-170: Enhanced ValidateService with specific error codes

The method now returns more specific error codes (BadAddress, BadType, NotRoutable, BadPort) instead of generic BadInput, as mentioned in the PR objectives about expanding error codes for more specific reporting.


163-167: Fixed network port validation

This check correctly validates that mainnet port is used only on mainnet and non-mainnet ports are used only on other networks, addressing the issue mentioned in the PR where validation conditions were incorrectly migrated.


172-195: Enhanced AddEntry with better parsing and validation

The method now:

  • Checks for single-entry constraint
  • Parses host and port separately
  • Uses character filtering for fast rejection
  • Creates a NetInfoEntry from validated service

This implements the fast-failing mechanism mentioned in the PR objectives.


182-184: Fast character filtering for quick invalid detection

This implements the "new fast-failing mechanism based on permitted characters" mentioned in the PR objectives, allowing quick rejection of inputs with invalid characters before more expensive validation.


197-207: Updated GetEntries to return NetInfoList

The method now returns a list of NetInfoEntry references instead of CService objects, with appropriate assertion to verify valid services in debug builds.


209-215: Added GetPrimary method with safe fallback

This method safely extracts the primary CService or returns an empty service as fallback, providing a convenient way to access the underlying address without dealing with optional references.


217-223: Implemented Validate with trivial check first

The method first checks if the entry is trivially valid before performing full validation, providing an efficient validation path for obviously invalid entries.


225-231: Updated ToString to use NetInfoEntry's string representation

The method now delegates to NetInfoEntry::ToString() for consistent string representation across the codebase.


1-1:

✅ Verification successful

Fix merge conflict before merging

Pipeline failure indicates a merge conflict in this file. Please rebase your branch to resolve conflicts before merging.


🏁 Script executed:

#!/bin/bash
# Check if there are merge conflicts in the file
grep -n "<<<<<<< HEAD" "src/evo/netinfo.cpp" || echo "No merge conflict markers found in current working copy"

Length of output: 165


No merge conflict markers found in src/evo/netinfo.cpp
The file no longer contains any <<<<<<<, =======, or >>>>>>> markers. Ready to merge.

🧰 Tools
🪛 GitHub Actions: Check Potential Conflicts

[error] 1-1: Merge conflict detected in this file requiring rebase.

}
} else {
throw std::runtime_error(
strprintf("%s: Can't add a masternode %s with invalid address", __func__, dmn->proTxHash.ToString()));
Copy link

Choose a reason for hiding this comment

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

0f3519d: #6665 (comment), same for other new "invalid address" errors

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since we need to register the underlying type in the unique properties map, this check has to be later expanded for DomainPort (see below, WIP code).

if (const auto& service_opt{entry.GetAddrPort()}; service_opt.has_value()) {
const CService& service{service_opt.value()};
if (!AddUniqueProperty(*dmn, service)) {
mnUniquePropertyMap = mnUniquePropertyMapSaved;
throw std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s",
__func__, dmn->proTxHash.ToString(), service.ToStringAddrPort()));
}
} else if (const auto& domain_opt{entry.GetDomainPort()}; domain_opt.has_value()) {
const DomainPort& domain{domain_opt.value()};
if (!AddUniqueProperty(*dmn, domain)) {
mnUniquePropertyMap = mnUniquePropertyMapSaved;
throw std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s",
__func__, dmn->proTxHash.ToString(), domain.ToStringAddrPort()));
}
} else {
throw std::runtime_error(
strprintf("%s: Can't add a masternode %s with invalid address", __func__, dmn->proTxHash.ToString()));
}

As for potentially invalid addresses, we try to prevent construction of an malformed NetInfoEntry (see below).

dash/src/evo/netinfo.h

Lines 68 to 73 in 66ee55c

NetInfoEntry(const CService& service)
{
if (!service.IsValid()) return;
m_type = NetInfoType::Service;
m_data = service;
}

But they can still be empty (i.e. invalid) and well-formed so I would still keep this check even if we have earlier checks against this (IsTriviallyValid())

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors how network information is handled by introducing the type‐flexible NetInfoEntry and updating its usage in various components, including mempool interactions, RPC responses, and masternode deterministic lists. Key changes include:

  • Replacing CService with NetInfoEntry in mappings and iterators.
  • Adjusting validation and error status codes for network entries.
  • Updating serialization, deserialization, and tests to support the new abstraction.

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/txmempool.h Update mapping type from CService to NetInfoEntry for address storage.
src/txmempool.cpp Iterate over NetInfoEntry instead of CService in address processing.
src/test/evo_netinfo_tests.cpp Update test expectations and validation for new status codes.
src/rpc/masternode.cpp Use NetInfoEntry for formatting masternode address information.
src/evo/providertx.cpp Validate each NetInfoEntry during ProTx processing.
src/evo/netinfo.h & netinfo.cpp Introduce NetInfoEntry, update serialization, and validation logic.
src/evo/deterministicmns.* Update unique property handling to work with NetInfoEntry.
Comments suppressed due to low confidence (1)

src/test/evo_netinfo_tests.cpp:24

  • The expected error status for a loopback address has been updated; please confirm that this change aligns with the overall design for address validation.
{"127.0.0.1:9999", NetInfoStatus::NotRoutable},

@kwvg kwvg requested a review from UdjinM6 May 14, 2025 01:33
@kwvg kwvg force-pushed the netinfo_p2 branch 3 times, most recently from c08ab6a to 4538e37 Compare May 15, 2025 14:44
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_netinfo_tests.cpp (1)

177-183: Consider more efficient comparison for small serialized objects

The CheckIfSerSame function uses SHA256 hashing to compare serialization equivalence, which is reliable but might be unnecessarily expensive for small objects.

For testing small objects, direct comparison of serialized data might be more readable:

-bool CheckIfSerSame(const CService& lhs, const MnNetInfo& rhs)
-{
-    CHashWriter ss_lhs(SER_GETHASH, 0), ss_rhs(SER_GETHASH, 0);
-    ss_lhs << lhs;
-    ss_rhs << rhs;
-    return ss_lhs.GetSHA256() == ss_rhs.GetSHA256();
-}
+bool CheckIfSerSame(const CService& lhs, const MnNetInfo& rhs)
+{
+    CDataStream ss_lhs(SER_DISK, 0), ss_rhs(SER_DISK, 0);
+    ss_lhs << lhs;
+    ss_rhs << rhs;
+    return ss_lhs.vch == ss_rhs.vch;
+}

However, as this is test code and the current approach works correctly, this is purely a nitpick.

src/evo/netinfo.cpp (2)

79-91: Add clarification for default port value

The GetPort method returns 0 as the default value for unknown types or invalid entries, but this isn't documented.

 uint16_t NetInfoEntry::GetPort() const
 {
     return std::visit(
         [](auto&& input) -> uint16_t {
             using T1 = std::decay_t<decltype(input)>;
             if constexpr (std::is_same_v<T1, CService>) {
                 return input.GetPort();
             } else {
+                // Return 0 for invalid or unknown entry types
                 return 0;
             }
         },
         m_data);
 }

190-193: Consider clarifying error behavior for IPv6 addresses

As noted in the PR objectives, the character filtering can cause inconsistent error reporting: IPv6 addresses are rejected with BadInput due to delimiter filtering, while validating an existing IPv6 address returns BadType.

     // Contains invalid characters, unlikely to pass Lookup(), fast-fail
     if (!MatchCharsFilter(addr, SAFE_CHARS_IPV4)) {
+        // Note: This filter rejects IPv6 addresses at the character level, which is
+        // intentional as only IPv4 addresses are supported. IPv6 addresses will fail
+        // here with BadInput rather than BadType from ValidateService
         return NetInfoStatus::BadInput;
     }
src/evo/netinfo.h (1)

105-122: Consider more efficient error handling for deserialization

The deserialization method uses a try-catch block to handle invalid CService objects, which works but could be more efficient.

Since IsValid() checks can be performed without needing to catch exceptions, consider:

     if (m_type == NetInfoType::Service) {
         m_data = CService{};
         try {
             CService& service{std::get<CService>(m_data)};
             s >> service;
-            if (!service.IsValid()) {
-                throw std::ios_base::failure("Invalid CService");
-            }
+            if (!service.IsValid()) {
+                Clear();
+                return;
+            }
         } catch (const std::ios_base::failure&) {
             Clear();
         }
     } else {
         // Invalid type, reset to mark object as invalid
         Clear();
     }

This change could slightly improve performance by avoiding exception handling for the common case of invalid but well-formed input.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 966c90b and c3e48ab.

📒 Files selected for processing (9)
  • src/evo/deterministicmns.cpp (8 hunks)
  • src/evo/deterministicmns.h (1 hunks)
  • src/evo/netinfo.cpp (3 hunks)
  • src/evo/netinfo.h (2 hunks)
  • src/evo/providertx.cpp (2 hunks)
  • src/rpc/masternode.cpp (1 hunks)
  • src/test/evo_netinfo_tests.cpp (4 hunks)
  • src/txmempool.cpp (8 hunks)
  • src/txmempool.h (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/evo/providertx.cpp
  • src/txmempool.h
  • src/txmempool.cpp
  • src/evo/deterministicmns.cpp
  • src/rpc/masternode.cpp
  • src/evo/deterministicmns.h
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: ClangFormat
  • GitHub Check: x86_64-pc-linux-gnu_multiprocess / Build depends
  • GitHub Check: main
🔇 Additional comments (15)
src/test/evo_netinfo_tests.cpp (5)

25-26: Error code changes align with refined validation model

The change from what was likely Internal to NotRoutable for internal addresses reflects the more specific error classification introduced in the enum updates. This correctly associates non-routability as the primary issue with internal addresses on mainnet.


40-46: Function updated to verify new validation triangle

The modified ValidateGetEntries function now accepts NetInfoList and verifies IsTriviallyValid() on each entry, completing the validation triangle as intended. This is consistent with your explanation in previous reviews that all three validation methods (AddEntry(), Validate(), and IsTriviallyValid()) should work in harmony.


64-70: Good test for single-entry constraint

This test properly verifies the new single-entry constraint for MnNetInfo, ensuring that additional entries are rejected with MaxLimit status.

Consider adding a test for the behavior after Clear() is called, to verify that a new entry can be added after clearing:

+    {
+        // After Clear(), a new entry should be accepted
+        MnNetInfo netInfo;
+        BOOST_CHECK_EQUAL(netInfo.AddEntry("1.1.1.1:9999"), NetInfoStatus::Success);
+        netInfo.Clear();
+        BOOST_CHECK_EQUAL(netInfo.AddEntry("1.1.1.2:9999"), NetInfoStatus::Success);
+        ValidateGetEntries(netInfo.GetEntries(), /*expected_size=*/1);
+    }

92-108: Good serialization edge case testing

The tests properly verify edge cases for reading malformed data, such as:

  • Reading nonsensical type bytes (line 87)
  • Reading an invalid CService (line 96)
  • Reading an unrecognized combination of type and data (line 105)

These tests are crucial for ensuring robust error handling during deserialization.


123-143: Comprehensive test for ADDRV2 format handling

This test ensures that NetInfoEntry correctly handles the ADDRV2 format requirement for special addresses like Tor onions. It verifies both direct construction and serialization/deserialization round-trips maintain address integrity.

src/evo/netinfo.cpp (5)

16-19: Well-defined static constants

Good addition of a static empty service and character filter for IPv4 addresses. The SAFE_CHARS_IPV4 will properly handle the fast-fail mechanism for IPv4 inputs.


29-32: Clean implementation of character filter

The MatchCharsFilter function is a simple and efficient implementation for checking if all characters in an input string are contained in a filter. This supports the fast-fail validation mechanism described in the PR objectives.


35-68: Well-implemented comparison operators for variant-based class

The comparison operators correctly handle the variant-based approach, comparing both type codes and the underlying data. The ordering logic is sensible, with invalid entries (std::monostate) being considered less than valid ones.


183-193: Single-entry constraint is enforced correctly

The AddEntry method now properly enforces the single-entry limit for MnNetInfo by checking if the object already has an entry and returning MaxLimit if so. This aligns with the PR objectives.

The character filtering based on SAFE_CHARS_IPV4 implements the fast-failing mechanism mentioned in the PR objectives.


217-223: Well-implemented fallback for invalid entries

The GetPrimary method correctly returns the underlying CService if it exists, or an empty service otherwise. This provides a sensible fallback for cases where the entry is invalid.

src/evo/netinfo.h (5)

17-27: Enhanced error status codes

The expanded NetInfoStatus enum provides more specific error codes, improving error reporting as mentioned in the PR objectives. The categorization into management and validation errors is a good organizational approach.


54-80: Clean variant-based implementation for NetInfoEntry

The NetInfoEntry class uses a well-designed discriminated union pattern with std::variant to hold either a valid CService or an invalid state. The type code and constructors provide a clean interface for creating and checking validity.


84-91: ADDRV2_FORMAT required for serialization

The serialization method for NetInfoEntry explicitly sets the ADDRV2_FORMAT flag, which aligns with the PR objective stating that "ADDRV2 serialization is mandatory for storing Tor and I2P addresses." This ensures proper serialization of special addresses.


141-141: Type alias improves code readability

The NetInfoList type alias using std::reference_wrapper is a good design choice. It enables containers of references which aligns with the codebase pattern of returning references to internal data structures.


158-179: Backward compatible serialization

The serialization and deserialization methods for MnNetInfo maintain backward compatibility by continuing to serialize to and deserialize from CService. This ensures that existing data can still be read correctly.

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.

2 participants