Skip to content

feat(net): support domain names in peer configuration#75

Open
317787106 wants to merge 12 commits intodevelopfrom
feature/support_domain
Open

feat(net): support domain names in peer configuration#75
317787106 wants to merge 12 commits intodevelopfrom
feature/support_domain

Conversation

@317787106
Copy link
Copy Markdown
Owner

@317787106 317787106 commented Apr 24, 2026

Summary

Allows node.seed.ip.list, node.active, node.passive, node.fastForward, and node.backup.members configuration entries to specify domain names in addition to IP literals. Domains are resolved to IPs at startup; backup member IPs are refreshed automatically every 60 seconds when DNS returns a different address.
Closes tronprotocol#6634

Problem

All network peer configuration fields previously required numeric IP addresses. Operators running nodes behind dynamic DNS or cloud load-balancers had to manually update config files whenever IPs changed. Backup members in particular need continuous accuracy because they participate in keep-alive health checks.

Changes

New: InetUtil

Central DNS resolution utility used by both startup parsing and runtime refresh:

  • resolveInetSocketAddressList(List<String>) — converts a list of ipOrDomain:port strings to InetSocketAddress objects. IP literals are used as-is; domain entries are resolved via LookUpTxt.lookUpIp (IPv4 first, IPv6 fallback). When there are multiple domain entries, resolution is parallelised using a bounded thread pool (up to 10 threads). Unresolvable entries are silently skipped.
  • resolveInetAddress(String) — resolves a bare host (no port) to InetAddress; IP literals take the fast path without a DNS lookup.

BackupManager (framework)

  • At init(), each configured backup member is resolved via InetUtil.resolveInetAddress. The resolved IP is stored in members; entries with a domain host are additionally tracked in a domainIpCache.
  • A new dnsExecutorService scheduler runs refreshMemberIps() every 60 seconds when domainIpCache is non-empty. If DNS returns a new IP, the old IP is removed from members and the new IP is added; localIp is never added.
  • dnsExecutorService is shut down alongside executorService in stop().

Args (framework)

  • Extracted a shared getInetSockerAddress(config, path) helper that calls InetUtil.resolveInetSocketAddressList, used by both getInetSocketAddress (seed/active/passive nodes) and getInetAddress. Unresolvable domain entries in seed lists are silently dropped; unresolvable backup member entries throw TronError(PARAMETER_INIT) at startup via the new checkBackupMembers() validator.

Dependency

  • Switched libp2p from io.github.tronprotocol:libp2p:2.2.7 to io.github.tronprotocol:libp2p:2.2.8, which exposes the LookUpTxt.lookUpIp API used for DNS resolution.

Behaviour Summary

Config field Unresolvable domain Domain IP change
Seed / active / passive / fastForward Entry skipped silently Re-read at next startup
node.backup.members TronError thrown at startup Auto-refreshed every 60 s

Test

  • InetUtilTest (18 tests): resolveInetSocketAddressList — IPv4/IPv6 literals, domain resolution, IPv6 fallback, input order preserved, unresolvable entries dropped. resolveInetAddress — same coverage for the no-port variant.
  • BackupManagerTest (6 new tests): init() domain-to-IP mapping and local-IP exclusion; refreshMemberIps() — IP changed, IP unchanged, DNS failure retains old IP.
  • ArgsTest (3 new tests): checkBackupMembers() — IP members pass, unresolvable domain throws TronError(PARAMETER_INIT), resolvable domain passes.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

📝 Walkthrough

Walkthrough

Adds DNS hostname support for seed and backup configs: new InetUtil resolves hosts (IPv4-first, IPv6 fallback); Args validates backup members at startup; BackupManager caches resolved IPs and schedules periodic re-resolution; build dependency and verification metadata for libp2p updated; tests added for DNS logic.

Changes

Cohort / File(s) Summary
Dependency & Verification
common/build.gradle, gradle/verification-metadata.xml
Replaced libp2p dependency coordinate (group/version updated) and added SHA-256 verification entries for the new libp2p artifact and httpcore jar.
DNS Utility
framework/src/main/java/org/tron/core/config/args/InetUtil.java
New utility with resolveInetSocketAddressList(...) and resolveInetAddress(...) that resolves ip/domain[:port] inputs preserving order, using IPv4-first then IPv6 fallback, with bounded parallel resolution.
Args / Config Parsing
framework/src/main/java/org/tron/core/config/args/Args.java
Added checkBackupMembers() to synchronously resolve/validate node.backup.members at startup and switched address parsing to use InetUtil resolution results.
Backup Manager
framework/src/main/java/org/tron/common/backup/BackupManager.java
Resolves domain entries into IPs, maintains domainIpCache, schedules periodic DNS refreshes to update member IPs (excludes local IP), shuts down the DNS executor on stop, and replaced manual getter/setter with Lombok annotations; several fields made final.
Unit Tests
framework/src/test/java/.../BackupManagerTest.java, framework/src/test/java/.../ArgsTest.java, framework/src/test/java/.../InetUtilTest.java
Added tests covering domain/IP resolution, backup-member validation (including failure on unresolved hosts), periodic refresh behavior, and InetUtil resolution ordering and fallbacks; use Mockito static mocking for DNS stubs.

Sequence Diagram(s)

sequenceDiagram
    participant Startup as Node Startup
    participant Args as Args.checkBackupMembers()
    participant InetUtil as InetUtil
    participant DNS as DNS Resolver
    participant BackupMgr as BackupManager
    participant Scheduler as ScheduledExecutor

    Startup->>Args: Load node.backup.members config
    activate Args
    Args->>Args: Iterate each member entry
    Args->>InetUtil: resolveInetAddress(member)
    activate InetUtil
    InetUtil->>DNS: Resolve IPv4 (or IPv6 fallback)
    DNS-->>InetUtil: Return InetAddress or null
    InetUtil-->>Args: InetAddress or null
    deactivate InetUtil
    alt Resolution failed
        Args->>Args: Throw TronError(PARAMETER_INIT)
    else Resolution succeeded
        Args->>Args: Add to validated members list
    end
    Args-->>Startup: Validated members with resolved IPs
    deactivate Args

    Startup->>BackupMgr: Initialize with resolved members
    activate BackupMgr
    BackupMgr->>BackupMgr: Populate domainIpCache
    BackupMgr->>Scheduler: Schedule periodic refresh task
    deactivate BackupMgr

    Scheduler->>Scheduler: Fixed interval refresh
    loop Periodic Re-resolution
        Scheduler->>InetUtil: resolveInetAddress(domain)
        InetUtil->>DNS: Resolve IPv4/IPv6
        DNS-->>InetUtil: New InetAddress or null
        alt IP changed
            InetUtil->>BackupMgr: Update domainIpCache & members
            BackupMgr->>BackupMgr: Atomically swap IP in member set
        else IP unchanged
            InetUtil->>InetUtil: No-op
        else Resolution failed
            BackupMgr->>BackupMgr: Retain last known IP, log warning
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hop through names to find each hidden trail,

I nibble DNS crumbs until the addresses hail.
I stash the fresh hops, refresh when they roam,
IPv4 then IPv6 — I bring them home.
Cheers from a rabbit for nodes that stay whole.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(net): support domain names in peer configuration' directly and concisely describes the main change across all modified files.
Linked Issues check ✅ Passed All primary objectives from issue #6634 are implemented: domain support for backup members and seed nodes with synchronous/async resolution strategies, periodic re-resolution for backups, silent skipping of unresolvable seeds, startup failure on unresolvable backups, libp2p DNS reuse, and comprehensive unit tests.
Out of Scope Changes check ✅ Passed Changes are scoped to domain resolution implementation and supporting infrastructure; only libp2p dependency version bump appears tangential but is necessary to access the LookUpTxt.lookUpIp method required by the feature.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/support_domain

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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: 4

🧹 Nitpick comments (6)
gradle/verification-metadata.xml (1)

250-257: Remove the stale verification entry for io.github.tronprotocol:libp2p:2.2.7.

The old coordinate is commented out in common/build.gradle (line 25) and replaced with com.github.317787106:libp2p:v0.10.0 (line 24). The verification block at lines 857–867 in verification-metadata.xml for the 2.2.7 entry is no longer reachable and should be removed. Stale entries can obscure real version drift.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gradle/verification-metadata.xml` around lines 250 - 257, Remove the stale
verification entry for the old coordinate io.github.tronprotocol:libp2p:2.2.7
from gradle/verification-metadata.xml; since common/build.gradle now uses
com.github.317787106:libp2p:v0.10.0, locate the verification block that
references the io.github.tronprotocol:libp2p:2.2.7 component and delete that
entire component/artifact SHA256 entries so only the current
com.github.317787106:libp2p:v0.10.0 verification remains.
framework/src/main/java/org/tron/core/config/args/Args.java (3)

1675-1683: Sequential DNS on startup path; also duplicates work done later in BackupManager.init().

Two concerns:

  1. Each member is resolved serially with IPv4-then-IPv6 fallback. If any entry is slow/timing out, startup is blocked for N × (ipv4_timeout + ipv6_timeout). For a small backup cluster the wall-clock cost is usually fine, but a single misconfigured entry can stall the node for tens of seconds before the TronError is thrown. Consider using InetUtil.resolveInetSocketAddressList (or a similar parallel helper) and asserting every entry resolved.
  2. BackupManager.init() re-resolves the same list immediately afterwards. Caching the results once on PARAMETER (e.g. a List<InetAddress> sibling to backupMembers) would let both paths share the lookups and avoid a second round of DNS on startup.

Non-blocking for correctness, but worth considering for operational UX.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/main/java/org/tron/core/config/args/Args.java` around lines
1675 - 1683, The checkBackupMembers method does serial DNS lookups via
resolveInetAddress causing startup blocking and duplicates work in
BackupManager.init; replace the sequential loop by using a parallel resolver
such as InetUtil.resolveInetSocketAddressList to resolve PARAMETER.backupMembers
in parallel, assert every input resolved, and store the resolved InetAddress
results on PARAMETER (e.g. add a sibling List<InetAddress> like
resolvedBackupMembers) so BackupManager.init can reuse the cached addresses
instead of re-resolving; update checkBackupMembers to populate and validate that
cached list rather than calling resolveInetAddress per entry.

1333-1339: Error message reads awkwardly when wrapping a runtime exception.

String.format("config %s contains %s", path, e.getMessage()) produces messages like config node.active contains Invalid host/port ..., which is hard to parse. Prefer something like "Failed to parse %s: %s" and include the cause:

🛠️ Suggested fix
     try {
       socketAddressList = InetUtil.resolveInetSocketAddressList(list);
     } catch (RuntimeException e) {
-      throw new TronError(String.format("config %s contains %s", path, e.getMessage()),
-          TronError.ErrCode.PARAMETER_INIT);
+      throw new TronError(
+          String.format("Failed to parse %s: %s", path, e.getMessage()),
+          e, TronError.ErrCode.PARAMETER_INIT);
     }

(Assumes a TronError(String, Throwable, ErrCode) constructor exists; if not, at least propagate e.getMessage() in the same sentence structure.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/main/java/org/tron/core/config/args/Args.java` around lines
1333 - 1339, The catch block that wraps
InetUtil.resolveInetSocketAddressList(list) currently throws a TronError with an
awkward message via String.format("config %s contains %s", path,
e.getMessage()); change this to a clearer message like "Failed to parse %s: %s"
and pass the original exception as the cause when creating the TronError (i.e.,
use the TronError constructor that accepts a Throwable) so the thrown error
includes both the clearer text and the original exception; update the throw in
Args (the catch around InetUtil.resolveInetSocketAddressList) to use the new
message format and include e as the cause, or at minimum reorder message
formatting to "%s: %s" and include e.getMessage().

1326-1340: Typo in helper name: getInetSockerAddressgetInetSocketAddress.

The private helper is misspelled (Socker). Since the public overload is getInetSocketAddress, the two names differ by only a character, which is both confusing and easy to miss at a call-site. Given it's private, renaming is risk-free.

🛠️ Suggested fix
-  private static List<InetSocketAddress> getInetSockerAddress(
+  private static List<InetSocketAddress> resolveInetSocketAddresses(
       final com.typesafe.config.Config config, String path) {

(And update the two internal callers on lines 1308 and 1345.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/main/java/org/tron/core/config/args/Args.java` around lines
1326 - 1340, Private helper getInetSockerAddress is misspelled; rename it to
getInetSocketAddress to match the public overload and avoid confusion. Change
the method name getInetSockerAddress to getInetSocketAddress, update all
internal callers that reference the old name to the new name, ensure there is no
duplicate signature/conflict with the existing public getInetSocketAddress
overload, and run a build to confirm all references compile.
framework/src/main/java/org/tron/common/backup/BackupManager.java (1)

54-56: Minor: allocate the DNS-refresh executor lazily.

dnsExecutorService is created unconditionally at field-init time, but it's only scheduled when domainIpCache is non-empty (line 130). For deployments that stick to IP literals (the vast majority today), this spins up — and later shuts down — an unused scheduled-executor thread. Consider deferring creation to inside the if (!domainIpCache.isEmpty()) block.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/main/java/org/tron/common/backup/BackupManager.java` around
lines 54 - 56, The dnsExecutorService is created eagerly at field initialization
(dnsExecutorService =
ExecutorServiceManager.newSingleThreadScheduledExecutor(dnsEsName)) but only
used when domainIpCache is non-empty; change to lazy allocation by replacing the
field with a nullable/optional reference (e.g., private ScheduledExecutorService
dnsExecutorService = null) and instantiate it inside the existing if
(!domainIpCache.isEmpty()) block using
ExecutorServiceManager.newSingleThreadScheduledExecutor(dnsEsName); update any
shutdown/cleanup logic to check for null before calling shutdown on
dnsExecutorService and keep dnsEsName and domainIpCache references unchanged so
the allocator and lifecycle remain consistent.
framework/src/main/java/org/tron/core/config/args/InetUtil.java (1)

51-97: Parse each entry once and reuse.

NetUtil.parseInetSocketAddress(item) is invoked on line 54 (filter), line 88 (rebuild), and a third time inside resolveInetSocketAddress for each submitted domain. Besides the redundant work, any malformed entry will also throw from two different code paths, making error messages inconsistent. Parsing once and threading InetSocketAddress objects through the pipeline is both cleaner and more robust.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/main/java/org/tron/core/config/args/InetUtil.java` around lines
51 - 97, The code repeatedly calls NetUtil.parseInetSocketAddress(item) in the
filter loop, when submitting DNS tasks, and again when rebuilding the result;
parse each input string once up-front into an InetSocketAddress (e.g., produce a
List<Pair<String,InetSocketAddress>> or Map<String,InetSocketAddress> from
ipOrDomainWithPortList), use the parsed address to decide whether it is an IP
literal (isIpLiteral(parsed.getHostString())) and only submit unresolved domain
InetSocketAddress objects to resolveInetSocketAddress, store resolved results in
resolvedDomains keyed by the original input string, and then build the final
result from those parsed/resolved addresses so parsing is not duplicated and
malformed-entry parsing errors occur in a single place.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@common/build.gradle`:
- Around line 24-25: The build currently depends on a personal JitPack fork
(com.github.317787106:libp2p:v0.10.0) instead of the official
io.github.tronprotocol libp2p artifact; revert common/build.gradle to use the
official dependency (replace the com.github... coordinate with
io.github.tronprotocol:libp2p at the appropriate released version) or, if the
forked API (LookUpTxt.lookUpIp) is truly required and not yet upstream, move the
fork dependency behind a clearly named non-default Gradle profile (e.g.,
"jitpack-fork") and document that exception, and remove the commented-out
io.github.tronprotocol line so no dead config remains; also create a ticket to
coordinate with the libp2p maintainers to upstream LookUpTxt.lookUpIp (or get an
official 2.2.8+ release) so the fork can be removed.

In `@framework/src/main/java/org/tron/common/backup/BackupManager.java`:
- Around line 86-100: The loop over parameter.getBackupMembers() skips caching
domain names that resolve to localIp, so later DNS changes are never detected by
refreshMemberIps(); change the logic in the loop (around resolveInetAddress,
localIp, domainIpCache, members and NetUtil.validIpV4/validIpV6) to always
populate domainIpCache.put(ipOrDomain, ip) for domain names (i.e., when
!NetUtil.validIpV4(ipOrDomain) && !NetUtil.validIpV6(ipOrDomain)) before the
localIp check/continue, and only then skip adding the ip to members when
ip.equals(localIp).
- Around line 195-214: refreshMemberIps currently unconditionally removes oldIp
from members which can drop an IP still referenced by another domain; change the
removal logic to only remove oldIp when no other domain in domainIpCache maps to
that same IP and the oldIp is not present as an explicit IP-literal member or
the localIp. Specifically, inside refreshMemberIps (using domainIpCache,
members, localIp), before calling members.remove(oldIp) check: (1) iterate
domainIpCache.values() to see if any other domain (key != current domain) still
resolves to oldIp, and (2) ensure oldIp is not equal to localIp and not present
in members as an explicit IP-literal that should be preserved; only call
members.remove(oldIp) if both checks indicate it is no longer referenced. Also
ensure you still add newIp (unless it equals localIp) and update
domainIpCache.put(domain, newIp) as before.

In `@framework/src/main/java/org/tron/core/config/args/InetUtil.java`:
- Around line 60-84: The single-domain branch in InetUtil currently calls
resolveInetSocketAddress(entry) directly and can throw/propagate runtime
exceptions; change it to mirror the multi-domain path by wrapping the
single-domain resolution in a try/catch, call resolveInetSocketAddress(entry)
inside the try, only put into resolvedDomains on success, and catch and log
failures (e.g., catch RuntimeException/Exception and logger.warn("Failed to
resolve address, skip: {}", entry)); this keeps behavior consistent with the
parallel path (resolveInetSocketAddress, resolvedDomains) and prevents startup
failures observed in Args.getInetSockerAddress.

---

Nitpick comments:
In `@framework/src/main/java/org/tron/common/backup/BackupManager.java`:
- Around line 54-56: The dnsExecutorService is created eagerly at field
initialization (dnsExecutorService =
ExecutorServiceManager.newSingleThreadScheduledExecutor(dnsEsName)) but only
used when domainIpCache is non-empty; change to lazy allocation by replacing the
field with a nullable/optional reference (e.g., private ScheduledExecutorService
dnsExecutorService = null) and instantiate it inside the existing if
(!domainIpCache.isEmpty()) block using
ExecutorServiceManager.newSingleThreadScheduledExecutor(dnsEsName); update any
shutdown/cleanup logic to check for null before calling shutdown on
dnsExecutorService and keep dnsEsName and domainIpCache references unchanged so
the allocator and lifecycle remain consistent.

In `@framework/src/main/java/org/tron/core/config/args/Args.java`:
- Around line 1675-1683: The checkBackupMembers method does serial DNS lookups
via resolveInetAddress causing startup blocking and duplicates work in
BackupManager.init; replace the sequential loop by using a parallel resolver
such as InetUtil.resolveInetSocketAddressList to resolve PARAMETER.backupMembers
in parallel, assert every input resolved, and store the resolved InetAddress
results on PARAMETER (e.g. add a sibling List<InetAddress> like
resolvedBackupMembers) so BackupManager.init can reuse the cached addresses
instead of re-resolving; update checkBackupMembers to populate and validate that
cached list rather than calling resolveInetAddress per entry.
- Around line 1333-1339: The catch block that wraps
InetUtil.resolveInetSocketAddressList(list) currently throws a TronError with an
awkward message via String.format("config %s contains %s", path,
e.getMessage()); change this to a clearer message like "Failed to parse %s: %s"
and pass the original exception as the cause when creating the TronError (i.e.,
use the TronError constructor that accepts a Throwable) so the thrown error
includes both the clearer text and the original exception; update the throw in
Args (the catch around InetUtil.resolveInetSocketAddressList) to use the new
message format and include e as the cause, or at minimum reorder message
formatting to "%s: %s" and include e.getMessage().
- Around line 1326-1340: Private helper getInetSockerAddress is misspelled;
rename it to getInetSocketAddress to match the public overload and avoid
confusion. Change the method name getInetSockerAddress to getInetSocketAddress,
update all internal callers that reference the old name to the new name, ensure
there is no duplicate signature/conflict with the existing public
getInetSocketAddress overload, and run a build to confirm all references
compile.

In `@framework/src/main/java/org/tron/core/config/args/InetUtil.java`:
- Around line 51-97: The code repeatedly calls
NetUtil.parseInetSocketAddress(item) in the filter loop, when submitting DNS
tasks, and again when rebuilding the result; parse each input string once
up-front into an InetSocketAddress (e.g., produce a
List<Pair<String,InetSocketAddress>> or Map<String,InetSocketAddress> from
ipOrDomainWithPortList), use the parsed address to decide whether it is an IP
literal (isIpLiteral(parsed.getHostString())) and only submit unresolved domain
InetSocketAddress objects to resolveInetSocketAddress, store resolved results in
resolvedDomains keyed by the original input string, and then build the final
result from those parsed/resolved addresses so parsing is not duplicated and
malformed-entry parsing errors occur in a single place.

In `@gradle/verification-metadata.xml`:
- Around line 250-257: Remove the stale verification entry for the old
coordinate io.github.tronprotocol:libp2p:2.2.7 from
gradle/verification-metadata.xml; since common/build.gradle now uses
com.github.317787106:libp2p:v0.10.0, locate the verification block that
references the io.github.tronprotocol:libp2p:2.2.7 component and delete that
entire component/artifact SHA256 entries so only the current
com.github.317787106:libp2p:v0.10.0 verification remains.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c8388a78-066b-4989-9f2c-c77171921972

📥 Commits

Reviewing files that changed from the base of the PR and between f0a8f0f and 634f111.

📒 Files selected for processing (5)
  • common/build.gradle
  • framework/src/main/java/org/tron/common/backup/BackupManager.java
  • framework/src/main/java/org/tron/core/config/args/Args.java
  • framework/src/main/java/org/tron/core/config/args/InetUtil.java
  • gradle/verification-metadata.xml

Comment thread common/build.gradle Outdated
Comment on lines +24 to +25
api group: 'com.github.317787106', name: 'libp2p', version: 'v0.10.0',{
//api group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.7',{
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

Does the io.github.tronprotocol:libp2p Maven artifact have a 2.2.8 release that exposes LookUpTxt.lookUpIp?

💡 Result:

No, the io.github.tronprotocol:libp2p Maven artifact does not have a 2.2.8 release. The latest available version is 2.2.7, released on November 12, 2025. No sources mention a 2.2.8 release on Maven Central, Sonatype Central, mvnrepository.com, or the project's GitHub releases page. No evidence was found for a class or method named LookUpTxt.lookUpIp in the libp2p codebase or documentation across all versions.

Citations:


🏁 Script executed:

#!/bin/bash
# Check what the new fork coordinate actually resolves to on JitPack and whether
# LookUpTxt.lookUpIp is referenced anywhere in this repo's sources.
rg -nP -C2 '\bLookUpTxt\b|lookUpIp\s*\('
# Show every Gradle file referencing libp2p to confirm no other module pins the old coord.
rg -nP --type=gradle -C1 'libp2p'

Repository: 317787106/java-tron

Length of output: 2290


Do not ship a personal JitPack fork of libp2p as the production dependency.

This replaces the official io.github.tronprotocol:libp2p:2.2.7 with com.github.317787106:libp2p:v0.10.0. The new group coordinate com.github.317787106 is a JitPack path that resolves to a personal GitHub account (user id 317787106), not the tronprotocol organization. Several critical problems:

  1. PR summary is incorrect. The PR description states the bump is libp2p 2.2.7 -> 2.2.8 to acquire LookUpTxt.lookUpIp, but this is misleading: io.github.tronprotocol:libp2p has no 2.2.8 release (latest is 2.2.7), and LookUpTxt.lookUpIp does not exist in the official libp2p codebase. The method exists only in the fork (com.github.317787106). The actual change is 2.2.7 -> v0.10.0 from a personal account — this is a material difference from what the commit message promises.

  2. The fork is not optional, making supply chain risk acute. Because LookUpTxt.lookUpIp is used in this codebase (see framework/src/main/java/org/tron/core/config/args/InetUtil.java lines 112, 114, 141, 143) and exists nowhere else, the fork dependency is not a temporary workaround—it is a production requirement for a mainnet node's core P2P configuration. This means the trust anchor is permanently anchored to an individual contributor's GitHub account rather than the Tron Protocol organization.

  3. Commented-out coordinate. Line 25 retains the old io.github.tronprotocol dependency as a comment. Dead config should not be merged. Its presence is a strong signal that this change was a development workaround that was never properly resolved upstream.

Recommended: Coordinate with the libp2p maintainers to release LookUpTxt.lookUpIp under the official io.github.tronprotocol org (e.g., as 2.2.8 or later), then revert to the official dependency. If that is not feasible in the release timeline, gate the fork behind a clearly labeled non-default profile and document the limitation and timeline for resolution in the PR. Do not merge commented-out code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@common/build.gradle` around lines 24 - 25, The build currently depends on a
personal JitPack fork (com.github.317787106:libp2p:v0.10.0) instead of the
official io.github.tronprotocol libp2p artifact; revert common/build.gradle to
use the official dependency (replace the com.github... coordinate with
io.github.tronprotocol:libp2p at the appropriate released version) or, if the
forked API (LookUpTxt.lookUpIp) is truly required and not yet upstream, move the
fork dependency behind a clearly named non-default Gradle profile (e.g.,
"jitpack-fork") and document that exception, and remove the commented-out
io.github.tronprotocol line so no dead config remains; also create a ticket to
coordinate with the libp2p maintainers to upstream LookUpTxt.lookUpIp (or get an
official 2.2.8+ release) so the fork can be removed.

Comment on lines +86 to 100
for (String ipOrDomain : parameter.getBackupMembers()) {
InetAddress inetAddress = resolveInetAddress(ipOrDomain);
if (inetAddress == null) {
logger.warn("Failed to resolve backup member domain: {}", ipOrDomain);
continue;
}
String ip = inetAddress.getHostAddress();
if (localIp.equals(ip)) {
continue;
}
if (!NetUtil.validIpV4(ipOrDomain) && !NetUtil.validIpV6(ipOrDomain)) {
domainIpCache.put(ipOrDomain, ip);
}
members.add(ip);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Domains resolving to localIp at startup are never tracked for DNS refresh.

When a configured backup member is a domain name that currently resolves to localIp, the continue at line 94 fires before domainIpCache.put(...). If that DNS record later points to a non-local IP, the change will never be picked up by refreshMemberIps() — the only way to recover is a process restart.

Unless that's intentional, cache the domain first and only skip adding it to members:

🛠️ Suggested fix
     for (String ipOrDomain : parameter.getBackupMembers()) {
       InetAddress inetAddress = resolveInetAddress(ipOrDomain);
       if (inetAddress == null) {
         logger.warn("Failed to resolve backup member domain: {}", ipOrDomain);
         continue;
       }
       String ip = inetAddress.getHostAddress();
-      if (localIp.equals(ip)) {
-        continue;
-      }
       if (!NetUtil.validIpV4(ipOrDomain) && !NetUtil.validIpV6(ipOrDomain)) {
         domainIpCache.put(ipOrDomain, ip);
       }
+      if (localIp.equals(ip)) {
+        continue;
+      }
       members.add(ip);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/main/java/org/tron/common/backup/BackupManager.java` around
lines 86 - 100, The loop over parameter.getBackupMembers() skips caching domain
names that resolve to localIp, so later DNS changes are never detected by
refreshMemberIps(); change the logic in the loop (around resolveInetAddress,
localIp, domainIpCache, members and NetUtil.validIpV4/validIpV6) to always
populate domainIpCache.put(ipOrDomain, ip) for domain names (i.e., when
!NetUtil.validIpV4(ipOrDomain) && !NetUtil.validIpV6(ipOrDomain)) before the
localIp check/continue, and only then skip adding the ip to members when
ip.equals(localIp).

Comment on lines +195 to +214
private void refreshMemberIps() {
for (Map.Entry<String, String> entry : domainIpCache.entrySet()) {
String domain = entry.getKey();
String oldIp = entry.getValue();
InetAddress inetAddress = resolveInetAddress(domain);
if (inetAddress == null) {
logger.warn("DNS refresh: failed to re-resolve backup member domain {}, keep it", domain);
continue;
}
String newIp = inetAddress.getHostAddress();
if (!newIp.equals(oldIp)) {
logger.info("DNS refresh: backup member {} IP changed {} -> {}", domain, oldIp, newIp);
members.remove(oldIp);
if (!localIp.equals(newIp)) {
members.add(newIp);
}
domainIpCache.put(domain, newIp);
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

refreshMemberIps may drop an IP that is still in use by another tracked domain.

members.remove(oldIp) is unconditional. If two backup-member domains currently resolve to the same IP and only one of them rotates to a new address, the shared IP is removed from members even though the second domain still depends on it — keepalive messages will stop flowing to that peer until the other domain is also refreshed (or a restart happens).

Consider keeping oldIp only if no other entry in domainIpCache (or a plain IP-literal member) still maps to it:

🛠️ Sketch
       if (!newIp.equals(oldIp)) {
         logger.info("DNS refresh: backup member {} IP changed {} -> {}", domain, oldIp, newIp);
-        members.remove(oldIp);
+        boolean stillReferenced = domainIpCache.entrySet().stream()
+            .anyMatch(e -> !e.getKey().equals(domain) && oldIp.equals(e.getValue()));
+        if (!stillReferenced) {
+          members.remove(oldIp);
+        }
         if (!localIp.equals(newIp)) {
           members.add(newIp);
         }
         domainIpCache.put(domain, newIp);
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/main/java/org/tron/common/backup/BackupManager.java` around
lines 195 - 214, refreshMemberIps currently unconditionally removes oldIp from
members which can drop an IP still referenced by another domain; change the
removal logic to only remove oldIp when no other domain in domainIpCache maps to
that same IP and the oldIp is not present as an explicit IP-literal member or
the localIp. Specifically, inside refreshMemberIps (using domainIpCache,
members, localIp), before calling members.remove(oldIp) check: (1) iterate
domainIpCache.values() to see if any other domain (key != current domain) still
resolves to oldIp, and (2) ensure oldIp is not equal to localIp and not present
in members as an explicit IP-literal that should be preserved; only call
members.remove(oldIp) if both checks indicate it is no longer referenced. Also
ensure you still add newIp (unless it equals localIp) and update
domainIpCache.put(domain, newIp) as before.

Comment on lines +60 to +84
Map<String, InetSocketAddress> resolvedDomains = new HashMap<>();
if (domainEntries.size() > 1) {
int poolSize = StrictMath.min(domainEntries.size(), DNS_POOL_MAX_SIZE);
ExecutorService dnsPool = ExecutorServiceManager
.newFixedThreadPool(DNS_POOL_NAME, poolSize, true);
List<Future<InetSocketAddress>> futures = new ArrayList<>(domainEntries.size());
for (String entry : domainEntries) {
futures.add(dnsPool.submit(() -> resolveInetSocketAddress(entry)));
}
for (int i = 0; i < domainEntries.size(); i++) {
String entry = domainEntries.get(i);
try {
resolvedDomains.put(entry, futures.get(i).get());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.warn("DNS lookup interrupted for: {}", entry);
} catch (ExecutionException e) {
logger.warn("Failed to resolve address, skip: {}", entry);
}
}
ExecutorServiceManager.shutdownAndAwaitTermination(dnsPool, DNS_POOL_NAME);
} else if (domainEntries.size() == 1) {
String entry = domainEntries.get(0);
resolvedDomains.put(entry, resolveInetSocketAddress(entry));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Single-domain path skips the try/catch that the parallel path has.

When domainEntries.size() == 1, resolveInetSocketAddress(entry) is called inline (line 83). If the libp2p lookup throws a RuntimeException for any reason, it propagates up and turns into a TronError(PARAMETER_INIT) in Args.getInetSockerAddress — i.e. startup fails. The multi-domain path catches ExecutionException, logs a warning, and skips. The behavior for seed/active/passive/fastForward should be "skip on failure" per the PR objectives regardless of whether there's 1 or N domains.

🛠️ Suggested fix
     } else if (domainEntries.size() == 1) {
       String entry = domainEntries.get(0);
-      resolvedDomains.put(entry, resolveInetSocketAddress(entry));
+      try {
+        resolvedDomains.put(entry, resolveInetSocketAddress(entry));
+      } catch (RuntimeException e) {
+        logger.warn("Failed to resolve address, skip: {}", entry);
+      }
     }
📝 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
Map<String, InetSocketAddress> resolvedDomains = new HashMap<>();
if (domainEntries.size() > 1) {
int poolSize = StrictMath.min(domainEntries.size(), DNS_POOL_MAX_SIZE);
ExecutorService dnsPool = ExecutorServiceManager
.newFixedThreadPool(DNS_POOL_NAME, poolSize, true);
List<Future<InetSocketAddress>> futures = new ArrayList<>(domainEntries.size());
for (String entry : domainEntries) {
futures.add(dnsPool.submit(() -> resolveInetSocketAddress(entry)));
}
for (int i = 0; i < domainEntries.size(); i++) {
String entry = domainEntries.get(i);
try {
resolvedDomains.put(entry, futures.get(i).get());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.warn("DNS lookup interrupted for: {}", entry);
} catch (ExecutionException e) {
logger.warn("Failed to resolve address, skip: {}", entry);
}
}
ExecutorServiceManager.shutdownAndAwaitTermination(dnsPool, DNS_POOL_NAME);
} else if (domainEntries.size() == 1) {
String entry = domainEntries.get(0);
resolvedDomains.put(entry, resolveInetSocketAddress(entry));
}
Map<String, InetSocketAddress> resolvedDomains = new HashMap<>();
if (domainEntries.size() > 1) {
int poolSize = StrictMath.min(domainEntries.size(), DNS_POOL_MAX_SIZE);
ExecutorService dnsPool = ExecutorServiceManager
.newFixedThreadPool(DNS_POOL_NAME, poolSize, true);
List<Future<InetSocketAddress>> futures = new ArrayList<>(domainEntries.size());
for (String entry : domainEntries) {
futures.add(dnsPool.submit(() -> resolveInetSocketAddress(entry)));
}
for (int i = 0; i < domainEntries.size(); i++) {
String entry = domainEntries.get(i);
try {
resolvedDomains.put(entry, futures.get(i).get());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.warn("DNS lookup interrupted for: {}", entry);
} catch (ExecutionException e) {
logger.warn("Failed to resolve address, skip: {}", entry);
}
}
ExecutorServiceManager.shutdownAndAwaitTermination(dnsPool, DNS_POOL_NAME);
} else if (domainEntries.size() == 1) {
String entry = domainEntries.get(0);
try {
resolvedDomains.put(entry, resolveInetSocketAddress(entry));
} catch (RuntimeException e) {
logger.warn("Failed to resolve address, skip: {}", entry);
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/main/java/org/tron/core/config/args/InetUtil.java` around lines
60 - 84, The single-domain branch in InetUtil currently calls
resolveInetSocketAddress(entry) directly and can throw/propagate runtime
exceptions; change it to mirror the multi-domain path by wrapping the
single-domain resolution in a try/catch, call resolveInetSocketAddress(entry)
inside the try, only put into resolvedDomains on success, and catch and log
failures (e.g., catch RuntimeException/Exception and logger.warn("Failed to
resolve address, skip: {}", entry)); this keeps behavior consistent with the
parallel path (resolveInetSocketAddress, resolvedDomains) and prevents startup
failures observed in Args.getInetSockerAddress.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 5 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="framework/src/main/java/org/tron/common/backup/BackupManager.java">

<violation number="1" location="framework/src/main/java/org/tron/common/backup/BackupManager.java:93">
P1: Domains resolving to `localIp` at startup are skipped before being cached, so later DNS changes for those domains are never picked up.</violation>

<violation number="2" location="framework/src/main/java/org/tron/common/backup/BackupManager.java:207">
P1: Removing `oldIp` unconditionally can drop a still-active backup member when multiple domains share the same IP.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment on lines +93 to +99
if (localIp.equals(ip)) {
continue;
}
if (!NetUtil.validIpV4(ipOrDomain) && !NetUtil.validIpV6(ipOrDomain)) {
domainIpCache.put(ipOrDomain, ip);
}
members.add(ip);
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Apr 24, 2026

Choose a reason for hiding this comment

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

P1: Domains resolving to localIp at startup are skipped before being cached, so later DNS changes for those domains are never picked up.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At framework/src/main/java/org/tron/common/backup/BackupManager.java, line 93:

<comment>Domains resolving to `localIp` at startup are skipped before being cached, so later DNS changes for those domains are never picked up.</comment>

<file context>
@@ -78,10 +83,20 @@ public void init() {
+        continue;
+      }
+      String ip = inetAddress.getHostAddress();
+      if (localIp.equals(ip)) {
+        continue;
+      }
</file context>
Suggested change
if (localIp.equals(ip)) {
continue;
}
if (!NetUtil.validIpV4(ipOrDomain) && !NetUtil.validIpV6(ipOrDomain)) {
domainIpCache.put(ipOrDomain, ip);
}
members.add(ip);
if (!NetUtil.validIpV4(ipOrDomain) && !NetUtil.validIpV6(ipOrDomain)) {
domainIpCache.put(ipOrDomain, ip);
}
if (localIp.equals(ip)) {
continue;
}
members.add(ip);
Fix with Cubic

String newIp = inetAddress.getHostAddress();
if (!newIp.equals(oldIp)) {
logger.info("DNS refresh: backup member {} IP changed {} -> {}", domain, oldIp, newIp);
members.remove(oldIp);
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Apr 24, 2026

Choose a reason for hiding this comment

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

P1: Removing oldIp unconditionally can drop a still-active backup member when multiple domains share the same IP.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At framework/src/main/java/org/tron/common/backup/BackupManager.java, line 207:

<comment>Removing `oldIp` unconditionally can drop a still-active backup member when multiple domains share the same IP.</comment>

<file context>
@@ -162,4 +188,28 @@ public enum BackupStatusEnum {
+      String newIp = inetAddress.getHostAddress();
+      if (!newIp.equals(oldIp)) {
+        logger.info("DNS refresh: backup member {} IP changed {} -> {}", domain, oldIp, newIp);
+        members.remove(oldIp);
+        if (!localIp.equals(newIp)) {
+          members.add(newIp);
</file context>
Suggested change
members.remove(oldIp);
if (domainIpCache.entrySet().stream().noneMatch(e -> !e.getKey().equals(domain) && oldIp.equals(e.getValue()))) {
members.remove(oldIp);
}
Fix with Cubic

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="common/build.gradle">

<violation number="1" location="common/build.gradle:24">
P2: Avoid depending on a SNAPSHOT artifact in main build dependencies; use an immutable released version to keep builds reproducible.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread common/build.gradle
@317787106 317787106 force-pushed the feature/support_domain branch from 4b5588e to b2c1dcd Compare April 28, 2026 10:13
Copy link
Copy Markdown

@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: 2

🧹 Nitpick comments (1)
framework/src/test/java/org/tron/core/config/args/ArgsTest.java (1)

427-469: Prefer the public startup path here.

These tests invoke checkBackupMembers() via reflection, so they won’t catch regressions if Args.setParam(...) stops wiring the fail-fast validation. Exercising the public config-init path would give you end-to-end coverage of the new behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/test/java/org/tron/core/config/args/ArgsTest.java` around lines
427 - 469, Replace the reflective call to checkBackupMembers() with the public
startup/config initialization entrypoint so the test validates the real startup
wiring: after calling Args.setParam(...) and setting
CommonParameter.getInstance().setBackupMembers(...), invoke the public startup
method that runs config validation (for example call the Args main/init
entrypoint used by the application — e.g., Args.main(...) or Args.init()
depending on the class API) instead of using Method method =
Args.class.getDeclaredMethod("checkBackupMembers") and method.invoke(null); this
ensures failures in Args.setParam(...) wiring are caught end-to-end.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@framework/src/test/java/org/tron/common/backup/BackupManagerTest.java`:
- Around line 187-201: The test testInitSkipsDomainResolvingToLocalIp currently
asserts that members does not contain the local IP but misses verifying the
cache; update the test to also fetch and assert that the domainIpCache field on
manager remains empty after init (use getField(manager, "domainIpCache") similar
to getField(manager, "members")), ensuring domainIpCache neither contains the
local IP nor any entries for "self.local.host"; keep the existing mocking of
LookUpTxt.lookUpIp and cleanup with manager.stop().

In `@framework/src/test/java/org/tron/core/config/args/InetUtilTest.java`:
- Around line 195-204: The test testResolveInetAddressDomainIpv4FallsBackToIpv6
currently only asserts result is non-null; update the assertion to verify the
resolved address equals the mocked IPv6 address by comparing
result.getHostAddress() or result.equals(ipv6Addr) against ipv6Addr returned by
LookUpTxt.lookUpIp; locate the mock setup for LookUpTxt.lookUpIp and the call to
InetUtil.resolveInetAddress to replace assertNotNull(result) with an explicit
equality assertion ensuring the fallback produced ipv6Addr.

---

Nitpick comments:
In `@framework/src/test/java/org/tron/core/config/args/ArgsTest.java`:
- Around line 427-469: Replace the reflective call to checkBackupMembers() with
the public startup/config initialization entrypoint so the test validates the
real startup wiring: after calling Args.setParam(...) and setting
CommonParameter.getInstance().setBackupMembers(...), invoke the public startup
method that runs config validation (for example call the Args main/init
entrypoint used by the application — e.g., Args.main(...) or Args.init()
depending on the class API) instead of using Method method =
Args.class.getDeclaredMethod("checkBackupMembers") and method.invoke(null); this
ensures failures in Args.setParam(...) wiring are caught end-to-end.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1463867e-0d32-483f-ace0-756db9f98ecf

📥 Commits

Reviewing files that changed from the base of the PR and between b2c1dcd and 7c5bdf7.

📒 Files selected for processing (4)
  • framework/src/test/java/org/tron/common/backup/BackupManagerTest.java
  • framework/src/test/java/org/tron/core/config/args/ArgsTest.java
  • framework/src/test/java/org/tron/core/config/args/InetUtilTest.java
  • gradle/verification-metadata.xml
✅ Files skipped from review due to trivial changes (1)
  • gradle/verification-metadata.xml

Comment on lines +187 to +201
@Test(timeout = 5000)
public void testInitSkipsDomainResolvingToLocalIp() throws Exception {
String localIp = InetAddress.getLocalHost().getHostAddress();
CommonParameter.getInstance().setBackupMembers(
Collections.singletonList("self.local.host"));
InetAddress selfAddr = InetAddress.getByName(localIp);
try (MockedStatic<LookUpTxt> mock = mockStatic(LookUpTxt.class)) {
mock.when(() -> LookUpTxt.lookUpIp("self.local.host", true)).thenReturn(selfAddr);
manager.init();
}
Set<String> members = getField(manager, "members");
Assert.assertFalse("domain resolving to local IP should not be in members",
members.contains(localIp));
manager.stop();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Cover the cache path too.

This test only checks that members omits the local IP; it should also assert that domainIpCache stays empty so a regression that still caches the local address doesn’t slip through.

🔧 Suggested tightening
     Set<String> members = getField(manager, "members");
+    Map<String, String> cache = getField(manager, "domainIpCache");
     Assert.assertFalse("domain resolving to local IP should not be in members",
         members.contains(localIp));
+    Assert.assertTrue("domain resolving to local IP should not populate the cache",
+        cache.isEmpty());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/test/java/org/tron/common/backup/BackupManagerTest.java` around
lines 187 - 201, The test testInitSkipsDomainResolvingToLocalIp currently
asserts that members does not contain the local IP but misses verifying the
cache; update the test to also fetch and assert that the domainIpCache field on
manager remains empty after init (use getField(manager, "domainIpCache") similar
to getField(manager, "members")), ensuring domainIpCache neither contains the
local IP nor any entries for "self.local.host"; keep the existing mocking of
LookUpTxt.lookUpIp and cleanup with manager.stop().

Comment on lines +195 to +204
@Test(timeout = 5000)
public void testResolveInetAddressDomainIpv4FallsBackToIpv6() throws Exception {
InetAddress ipv6Addr = InetAddress.getByName("::1");
try (MockedStatic<LookUpTxt> mock = mockStatic(LookUpTxt.class)) {
mock.when(() -> LookUpTxt.lookUpIp("ipv6only.host", true)).thenReturn(null);
mock.when(() -> LookUpTxt.lookUpIp("ipv6only.host", false)).thenReturn(ipv6Addr);
InetAddress result = InetUtil.resolveInetAddress("ipv6only.host");
assertNotNull(result);
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Assert the IPv6 fallback result explicitly.

assertNotNull(result) does not prove the IPv4→IPv6 fallback path worked; this test would still pass if the method returned any non-null address. Please assert the resolved host address matches ipv6Addr.

🛠️ Suggested tightening
       InetAddress result = InetUtil.resolveInetAddress("ipv6only.host");
       assertNotNull(result);
+      assertEquals(ipv6Addr.getHostAddress(), result.getHostAddress());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/src/test/java/org/tron/core/config/args/InetUtilTest.java` around
lines 195 - 204, The test testResolveInetAddressDomainIpv4FallsBackToIpv6
currently only asserts result is non-null; update the assertion to verify the
resolved address equals the mocked IPv6 address by comparing
result.getHostAddress() or result.equals(ipv6Addr) against ipv6Addr returned by
LookUpTxt.lookUpIp; locate the mock setup for LookUpTxt.lookUpIp and the call to
InetUtil.resolveInetAddress to replace assertNotNull(result) with an explicit
equality assertion ensuring the fallback produced ipv6Addr.

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.

[Feature] Support domain names in node.backup.members and seed.node.ip.list

1 participant