From f040f31ea3a2b13d15da4d75c780c6d7921d0e16 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 15 Apr 2026 19:00:23 +0800 Subject: [PATCH 1/5] support domain for seed and backup members --- common/build.gradle | 3 +- .../org/tron/common/backup/BackupManager.java | 89 +++++++++++++++---- .../java/org/tron/core/config/args/Args.java | 50 ++++++++++- gradle/verification-metadata.xml | 8 ++ 4 files changed, 130 insertions(+), 20 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index 98fc3257190..b7494f1c1d4 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -21,7 +21,8 @@ dependencies { api 'org.aspectj:aspectjrt:1.9.8' api 'org.aspectj:aspectjweaver:1.9.8' api 'org.aspectj:aspectjtools:1.9.8' - api group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.7',{ + api group: 'com.github.317787106', name: 'libp2p', version: 'v0.0.9',{ + //api group: 'io.github.tronprotocol', name: 'libp2p', version: '2.2.7',{ exclude group: 'io.grpc', module: 'grpc-context' exclude group: 'io.grpc', module: 'grpc-core' exclude group: 'io.grpc', module: 'grpc-netty' diff --git a/framework/src/main/java/org/tron/common/backup/BackupManager.java b/framework/src/main/java/org/tron/common/backup/BackupManager.java index a8812a62bb4..a2fa904c5d4 100644 --- a/framework/src/main/java/org/tron/common/backup/BackupManager.java +++ b/framework/src/main/java/org/tron/common/backup/BackupManager.java @@ -8,9 +8,13 @@ import io.netty.util.internal.ConcurrentSet; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.tron.common.backup.message.KeepAliveMessage; @@ -20,46 +24,44 @@ import org.tron.common.backup.socket.UdpEvent; import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; +import org.tron.p2p.dns.lookup.LookUpTxt; +import org.tron.p2p.utils.NetUtil; @Slf4j(topic = "backup") @Component public class BackupManager implements EventHandler { - private CommonParameter parameter = CommonParameter.getInstance(); + private final CommonParameter parameter = CommonParameter.getInstance(); - private int priority = parameter.getBackupPriority(); + private final int priority = parameter.getBackupPriority(); - private int port = parameter.getBackupPort(); + private final int port = parameter.getBackupPort(); - private int keepAliveInterval = parameter.getKeepAliveInterval(); + private final int keepAliveInterval = parameter.getKeepAliveInterval(); - private int keepAliveTimeout = keepAliveInterval * 6; + private final int keepAliveTimeout = keepAliveInterval * 6; private String localIp = ""; - private Set members = new ConcurrentSet<>(); + private final Set members = new ConcurrentSet<>(); + + private final Map domainIpCache = new ConcurrentHashMap<>(); private final String esName = "backup-manager"; - private ScheduledExecutorService executorService = + private final ScheduledExecutorService executorService = ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); + @Setter private MessageHandler messageHandler; + @Getter private BackupStatusEnum status = MASTER; private volatile long lastKeepAliveTime; private volatile boolean isInit = false; - public void setMessageHandler(MessageHandler messageHandler) { - this.messageHandler = messageHandler; - } - - public BackupStatusEnum getStatus() { - return status; - } - public void setStatus(BackupStatusEnum status) { logger.info("Change backup status to {}", status); this.status = status; @@ -78,10 +80,15 @@ public void init() { logger.warn("Failed to get local ip"); } - for (String member : parameter.getBackupMembers()) { - if (!localIp.equals(member)) { - members.add(member); + for (String raw : parameter.getBackupMembers()) { + String ip = resolveToIp(raw); + if (ip == null || localIp.equals(ip)) { + continue; + } + if (!NetUtil.validIpV4(raw) && !NetUtil.validIpV6(raw)) { + domainIpCache.put(raw, ip); } + members.add(ip); } logger.info("Backup localIp:{}, members: size= {}, {}", localIp, members.size(), members); @@ -111,6 +118,14 @@ public void init() { logger.error("Exception in send keep alive", t); } }, 1000, keepAliveInterval, TimeUnit.MILLISECONDS); + + executorService.scheduleWithFixedDelay(() -> { + try { + refreshMemberIps(); + } catch (Throwable t) { + logger.error("Exception in backup DNS refresh", t); + } + }, 60_000L, 60_000L, TimeUnit.MILLISECONDS); } @Override @@ -162,4 +177,42 @@ public enum BackupStatusEnum { MASTER } + private String resolveToIp(String raw) { + if (NetUtil.validIpV4(raw) || NetUtil.validIpV6(raw)) { + return raw; + } + InetAddress address = LookUpTxt.lookUpIp(raw, true); + if (address == null) { + address = LookUpTxt.lookUpIp(raw, false); + } + if (address == null) { + logger.warn("Failed to resolve backup member domain: {}", raw); + return null; + } + return address.getHostAddress(); + } + + /** + * Re-resolves all tracked domain entries. If an IP has changed, the old IP is + * removed from {@link #members} and the new IP is added. + */ + private void refreshMemberIps() { + for (Map.Entry entry : domainIpCache.entrySet()) { + String domain = entry.getKey(); + String oldIp = entry.getValue(); + String newIp = resolveToIp(domain); + if (newIp == null) { + logger.warn("DNS refresh: failed to re-resolve backup member domain {}, keep it", domain); + continue; + } + 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); + } + } + } } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 83d7fd2c63d..f2a1a80414c 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -74,6 +74,7 @@ import org.tron.core.exception.TronError; import org.tron.core.store.AccountStore; import org.tron.p2p.P2pConfig; +import org.tron.p2p.dns.lookup.LookUpTxt; import org.tron.p2p.dns.update.DnsType; import org.tron.p2p.dns.update.PublishConfig; import org.tron.p2p.utils.NetUtil; @@ -1308,8 +1309,13 @@ public static List getInetSocketAddress( return ret; } List list = config.getStringList(path); + for (String configString : list) { - InetSocketAddress inetSocketAddress = NetUtil.parseInetSocketAddress(configString); + InetSocketAddress inetSocketAddress = resolveInetSocketAddress(configString); + if (inetSocketAddress == null) { + logger.warn("Failed to resolve address, skip: {}", configString); + continue; + } if (filter) { String ip = inetSocketAddress.getAddress().getHostAddress(); int port = inetSocketAddress.getPort(); @@ -1326,6 +1332,30 @@ public static List getInetSocketAddress( return ret; } + /** + * Parses an address string and, if the host part is a domain name rather than an IP literal, + * resolves it to an {@link InetAddress} via {@link LookUpTxt#lookUpIp}. Support IPv4 domain now + * + * @param configString address in {@code ip:port} or {@code [ipv6]:port} or + * {@code domain:port} format + * @return a fully resolved {@link InetSocketAddress}, or {@code null} if DNS resolution fails + */ + private static InetSocketAddress resolveInetSocketAddress(String configString) { + InetSocketAddress parsed = NetUtil.parseInetSocketAddress(configString); + String host = parsed.getHostString(); + int port = parsed.getPort(); + if (NetUtil.validIpV4(host) || NetUtil.validIpV6(host)) { + return parsed; + } + + // The host is a domain name, resolve it to an IP address, only support IPv4 now + InetAddress address = LookUpTxt.lookUpIp(host, true); + if (address == null) { + return null; + } + return new InetSocketAddress(address, port); + } + public static List getInetAddress( final com.typesafe.config.Config config, String path) { List ret = new ArrayList<>(); @@ -1660,6 +1690,24 @@ private static void initBackupProperty(Config config) { PARAMETER.backupMembers = config.hasPath(ConfigKey.NODE_BACKUP_MEMBERS) ? config.getStringList(ConfigKey.NODE_BACKUP_MEMBERS) : new ArrayList<>(); + checkBackupMembers(); + } + + private static void checkBackupMembers() { + for (String member : PARAMETER.backupMembers) { + if (NetUtil.validIpV4(member) || NetUtil.validIpV6(member)) { + continue; + } + // Determine whether a domain name can be resolved to an IP address. + InetAddress address = LookUpTxt.lookUpIp(member, true); + if (address == null) { + address = LookUpTxt.lookUpIp(member, false); + } + if (address == null) { + throw new TronError("Failed to resolve backup member domain: " + member, + TronError.ErrCode.PARAMETER_INIT); + } + } } public static void logConfig() { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 4d0bf1013d6..db17d29e0cf 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -247,6 +247,14 @@ + + + + + + + + From cbf122257c998e06aa69b5af4e0d39a68a9183e4 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 15 Apr 2026 20:06:56 +0800 Subject: [PATCH 2/5] use isolate executor for dns lookup --- .../org/tron/common/backup/BackupManager.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/framework/src/main/java/org/tron/common/backup/BackupManager.java b/framework/src/main/java/org/tron/common/backup/BackupManager.java index a2fa904c5d4..10e90690f6d 100644 --- a/framework/src/main/java/org/tron/common/backup/BackupManager.java +++ b/framework/src/main/java/org/tron/common/backup/BackupManager.java @@ -48,10 +48,13 @@ public class BackupManager implements EventHandler { private final Map domainIpCache = new ConcurrentHashMap<>(); private final String esName = "backup-manager"; - private final ScheduledExecutorService executorService = ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); + private final String dnsEsName = "backup-dns-refresh"; + private final ScheduledExecutorService dnsExecutorService = + ExecutorServiceManager.newSingleThreadScheduledExecutor(dnsEsName); + @Setter private MessageHandler messageHandler; @@ -119,13 +122,15 @@ public void init() { } }, 1000, keepAliveInterval, TimeUnit.MILLISECONDS); - executorService.scheduleWithFixedDelay(() -> { - try { - refreshMemberIps(); - } catch (Throwable t) { - logger.error("Exception in backup DNS refresh", t); - } - }, 60_000L, 60_000L, TimeUnit.MILLISECONDS); + if (!domainIpCache.isEmpty()) { + dnsExecutorService.scheduleWithFixedDelay(() -> { + try { + refreshMemberIps(); + } catch (Throwable t) { + logger.error("Exception in backup DNS refresh", t); + } + }, 60_000L, 60_000L, TimeUnit.MILLISECONDS); + } } @Override @@ -164,6 +169,7 @@ public void handleEvent(UdpEvent udpEvent) { public void stop() { ExecutorServiceManager.shutdownAndAwaitTermination(executorService, esName); + ExecutorServiceManager.shutdownAndAwaitTermination(dnsExecutorService, dnsEsName); } @Override From b3706efb7108cfc3a0d3be86fb0a14b27b4f4c33 Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Wed, 15 Apr 2026 23:48:26 +0800 Subject: [PATCH 3/5] add one log when resolve domain success --- framework/src/main/java/org/tron/core/config/args/Args.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index f2a1a80414c..659d0530682 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -1353,6 +1353,7 @@ private static InetSocketAddress resolveInetSocketAddress(String configString) { if (address == null) { return null; } + logger.info("Resolve {} to {}", host, address.getHostAddress()); return new InetSocketAddress(address, port); } From 1483681e2619c5bb6c98644bd520bc1af504d13a Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 16 Apr 2026 16:14:22 +0800 Subject: [PATCH 4/5] parallet get ip by dns --- .../org/tron/common/backup/BackupManager.java | 24 ++++--- .../java/org/tron/core/config/args/Args.java | 70 +++++++++++++++---- 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/framework/src/main/java/org/tron/common/backup/BackupManager.java b/framework/src/main/java/org/tron/common/backup/BackupManager.java index 10e90690f6d..cf66d070987 100644 --- a/framework/src/main/java/org/tron/common/backup/BackupManager.java +++ b/framework/src/main/java/org/tron/common/backup/BackupManager.java @@ -83,13 +83,13 @@ public void init() { logger.warn("Failed to get local ip"); } - for (String raw : parameter.getBackupMembers()) { - String ip = resolveToIp(raw); + for (String ipOrDomain : parameter.getBackupMembers()) { + String ip = resolveToIp(ipOrDomain); if (ip == null || localIp.equals(ip)) { continue; } - if (!NetUtil.validIpV4(raw) && !NetUtil.validIpV6(raw)) { - domainIpCache.put(raw, ip); + if (!NetUtil.validIpV4(ipOrDomain) && !NetUtil.validIpV6(ipOrDomain)) { + domainIpCache.put(ipOrDomain, ip); } members.add(ip); } @@ -183,16 +183,20 @@ public enum BackupStatusEnum { MASTER } - private String resolveToIp(String raw) { - if (NetUtil.validIpV4(raw) || NetUtil.validIpV6(raw)) { - return raw; + /** + * Resolves a hostname or IP string to a numeric IP address string. + */ + private String resolveToIp(String ipOrDomain) { + // Fast path: already a numeric address — no lookup needed. + if (NetUtil.validIpV4(ipOrDomain) || NetUtil.validIpV6(ipOrDomain)) { + return ipOrDomain; } - InetAddress address = LookUpTxt.lookUpIp(raw, true); + InetAddress address = LookUpTxt.lookUpIp(ipOrDomain, true); if (address == null) { - address = LookUpTxt.lookUpIp(raw, false); + address = LookUpTxt.lookUpIp(ipOrDomain, false); } if (address == null) { - logger.warn("Failed to resolve backup member domain: {}", raw); + logger.warn("Failed to resolve backup member domain: {}", ipOrDomain); return null; } return address.getHostAddress(); diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 659d0530682..e394037636c 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -37,11 +37,13 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; import java.util.stream.Collectors; import lombok.Getter; import lombok.NoArgsConstructor; @@ -56,6 +58,7 @@ import org.tron.common.args.Witness; import org.tron.common.config.DbBackupConfig; import org.tron.common.cron.CronExpression; +import org.tron.common.es.ExecutorServiceManager; import org.tron.common.logsfilter.EventPluginConfig; import org.tron.common.logsfilter.FilterQuery; import org.tron.common.logsfilter.TriggerConfig; @@ -1309,11 +1312,57 @@ public static List getInetSocketAddress( return ret; } List list = config.getStringList(path); + if (list.isEmpty()) { + return ret; + } + // Collect entries whose host part is a domain name (not an IP literal). + List domainEntries = new ArrayList<>(); for (String configString : list) { - InetSocketAddress inetSocketAddress = resolveInetSocketAddress(configString); + String host = NetUtil.parseInetSocketAddress(configString).getHostString(); + if (!NetUtil.validIpV4(host) && !NetUtil.validIpV6(host)) { + domainEntries.add(configString); + } + } + + // Resolve domain names: spin up a thread pool only when there are multiple domains + Map domainResolved = new HashMap<>(); + if (domainEntries.size() > 1) { + String poolName = "args-dns-lookup"; + ExecutorService dnsPool = ExecutorServiceManager + .newFixedThreadPool(poolName, domainEntries.size(), true); + List> 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 { + domainResolved.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, poolName); + } else if (domainEntries.size() == 1) { + String entry = domainEntries.get(0); + domainResolved.put(entry, resolveInetSocketAddress(entry)); + } + + // Build the result list preserving the original config order. + for (String configString : list) { + InetSocketAddress inetSocketAddress; + InetSocketAddress parsed = NetUtil.parseInetSocketAddress(configString); + if (NetUtil.validIpV4(parsed.getHostString()) || NetUtil.validIpV6(parsed.getHostString())) { + inetSocketAddress = parsed; + } else { + inetSocketAddress = domainResolved.get(configString); + } + if (inetSocketAddress == null) { - logger.warn("Failed to resolve address, skip: {}", configString); continue; } if (filter) { @@ -1333,23 +1382,16 @@ public static List getInetSocketAddress( } /** - * Parses an address string and, if the host part is a domain name rather than an IP literal, - * resolves it to an {@link InetAddress} via {@link LookUpTxt#lookUpIp}. Support IPv4 domain now - * - * @param configString address in {@code ip:port} or {@code [ipv6]:port} or - * {@code domain:port} format - * @return a fully resolved {@link InetSocketAddress}, or {@code null} if DNS resolution fails + * Resolves a {@code domain:port} address string to an {@link InetSocketAddress} via DNS. */ private static InetSocketAddress resolveInetSocketAddress(String configString) { InetSocketAddress parsed = NetUtil.parseInetSocketAddress(configString); String host = parsed.getHostString(); int port = parsed.getPort(); - if (NetUtil.validIpV4(host) || NetUtil.validIpV6(host)) { - return parsed; - } - - // The host is a domain name, resolve it to an IP address, only support IPv4 now InetAddress address = LookUpTxt.lookUpIp(host, true); + if (address == null) { + address = LookUpTxt.lookUpIp(host, false); + } if (address == null) { return null; } From aadffe7492393823c15da3d2a7564abe6a3e89ed Mon Sep 17 00:00:00 2001 From: jiangyuanshu <317787106@qq.com> Date: Thu, 16 Apr 2026 17:28:22 +0800 Subject: [PATCH 5/5] add InetUtil --- .../org/tron/common/backup/BackupManager.java | 35 ++---- .../java/org/tron/core/config/args/Args.java | 90 +------------- .../org/tron/core/config/args/InetUtil.java | 115 ++++++++++++++++++ 3 files changed, 131 insertions(+), 109 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/config/args/InetUtil.java diff --git a/framework/src/main/java/org/tron/common/backup/BackupManager.java b/framework/src/main/java/org/tron/common/backup/BackupManager.java index cf66d070987..c70d6df4d63 100644 --- a/framework/src/main/java/org/tron/common/backup/BackupManager.java +++ b/framework/src/main/java/org/tron/common/backup/BackupManager.java @@ -4,6 +4,7 @@ import static org.tron.common.backup.BackupManager.BackupStatusEnum.MASTER; import static org.tron.common.backup.BackupManager.BackupStatusEnum.SLAVER; import static org.tron.common.backup.message.UdpMessageTypeEnum.BACKUP_KEEP_ALIVE; +import static org.tron.core.config.args.InetUtil.resolveInetAddress; import io.netty.util.internal.ConcurrentSet; import java.net.InetAddress; @@ -24,7 +25,6 @@ import org.tron.common.backup.socket.UdpEvent; import org.tron.common.es.ExecutorServiceManager; import org.tron.common.parameter.CommonParameter; -import org.tron.p2p.dns.lookup.LookUpTxt; import org.tron.p2p.utils.NetUtil; @Slf4j(topic = "backup") @@ -84,8 +84,13 @@ public void init() { } for (String ipOrDomain : parameter.getBackupMembers()) { - String ip = resolveToIp(ipOrDomain); - if (ip == null || localIp.equals(ip)) { + 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)) { @@ -183,25 +188,6 @@ public enum BackupStatusEnum { MASTER } - /** - * Resolves a hostname or IP string to a numeric IP address string. - */ - private String resolveToIp(String ipOrDomain) { - // Fast path: already a numeric address — no lookup needed. - if (NetUtil.validIpV4(ipOrDomain) || NetUtil.validIpV6(ipOrDomain)) { - return ipOrDomain; - } - InetAddress address = LookUpTxt.lookUpIp(ipOrDomain, true); - if (address == null) { - address = LookUpTxt.lookUpIp(ipOrDomain, false); - } - if (address == null) { - logger.warn("Failed to resolve backup member domain: {}", ipOrDomain); - return null; - } - return address.getHostAddress(); - } - /** * Re-resolves all tracked domain entries. If an IP has changed, the old IP is * removed from {@link #members} and the new IP is added. @@ -210,11 +196,12 @@ private void refreshMemberIps() { for (Map.Entry entry : domainIpCache.entrySet()) { String domain = entry.getKey(); String oldIp = entry.getValue(); - String newIp = resolveToIp(domain); - if (newIp == null) { + 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); diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index e394037636c..4ef22624611 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -12,6 +12,7 @@ import static org.tron.core.Constant.MIN_PROPOSAL_EXPIRE_TIME; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCE_TIMEOUT_PERCENT; import static org.tron.core.config.Parameter.ChainConstant.MAX_ACTIVE_WITNESS_NUM; +import static org.tron.core.config.args.InetUtil.resolveInetAddress; import static org.tron.core.exception.TronError.ErrCode.PARAMETER_INIT; import com.beust.jcommander.JCommander; @@ -41,9 +42,6 @@ import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; import java.util.stream.Collectors; import lombok.Getter; import lombok.NoArgsConstructor; @@ -58,7 +56,6 @@ import org.tron.common.args.Witness; import org.tron.common.config.DbBackupConfig; import org.tron.common.cron.CronExpression; -import org.tron.common.es.ExecutorServiceManager; import org.tron.common.logsfilter.EventPluginConfig; import org.tron.common.logsfilter.FilterQuery; import org.tron.common.logsfilter.TriggerConfig; @@ -1312,59 +1309,7 @@ public static List getInetSocketAddress( return ret; } List list = config.getStringList(path); - if (list.isEmpty()) { - return ret; - } - - // Collect entries whose host part is a domain name (not an IP literal). - List domainEntries = new ArrayList<>(); - for (String configString : list) { - String host = NetUtil.parseInetSocketAddress(configString).getHostString(); - if (!NetUtil.validIpV4(host) && !NetUtil.validIpV6(host)) { - domainEntries.add(configString); - } - } - - // Resolve domain names: spin up a thread pool only when there are multiple domains - Map domainResolved = new HashMap<>(); - if (domainEntries.size() > 1) { - String poolName = "args-dns-lookup"; - ExecutorService dnsPool = ExecutorServiceManager - .newFixedThreadPool(poolName, domainEntries.size(), true); - List> 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 { - domainResolved.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, poolName); - } else if (domainEntries.size() == 1) { - String entry = domainEntries.get(0); - domainResolved.put(entry, resolveInetSocketAddress(entry)); - } - - // Build the result list preserving the original config order. - for (String configString : list) { - InetSocketAddress inetSocketAddress; - InetSocketAddress parsed = NetUtil.parseInetSocketAddress(configString); - if (NetUtil.validIpV4(parsed.getHostString()) || NetUtil.validIpV6(parsed.getHostString())) { - inetSocketAddress = parsed; - } else { - inetSocketAddress = domainResolved.get(configString); - } - - if (inetSocketAddress == null) { - continue; - } + for (InetSocketAddress inetSocketAddress : InetUtil.getInetSocketAddressList(list)) { if (filter) { String ip = inetSocketAddress.getAddress().getHostAddress(); int port = inetSocketAddress.getPort(); @@ -1381,24 +1326,6 @@ public static List getInetSocketAddress( return ret; } - /** - * Resolves a {@code domain:port} address string to an {@link InetSocketAddress} via DNS. - */ - private static InetSocketAddress resolveInetSocketAddress(String configString) { - InetSocketAddress parsed = NetUtil.parseInetSocketAddress(configString); - String host = parsed.getHostString(); - int port = parsed.getPort(); - InetAddress address = LookUpTxt.lookUpIp(host, true); - if (address == null) { - address = LookUpTxt.lookUpIp(host, false); - } - if (address == null) { - return null; - } - logger.info("Resolve {} to {}", host, address.getHostAddress()); - return new InetSocketAddress(address, port); - } - public static List getInetAddress( final com.typesafe.config.Config config, String path) { List ret = new ArrayList<>(); @@ -1738,16 +1665,9 @@ private static void initBackupProperty(Config config) { private static void checkBackupMembers() { for (String member : PARAMETER.backupMembers) { - if (NetUtil.validIpV4(member) || NetUtil.validIpV6(member)) { - continue; - } - // Determine whether a domain name can be resolved to an IP address. - InetAddress address = LookUpTxt.lookUpIp(member, true); - if (address == null) { - address = LookUpTxt.lookUpIp(member, false); - } - if (address == null) { - throw new TronError("Failed to resolve backup member domain: " + member, + InetAddress inetAddress = resolveInetAddress(member); + if (inetAddress == null) { + throw new TronError("Failed to resolve backup member: " + member, TronError.ErrCode.PARAMETER_INIT); } } diff --git a/framework/src/main/java/org/tron/core/config/args/InetUtil.java b/framework/src/main/java/org/tron/core/config/args/InetUtil.java new file mode 100644 index 00000000000..a38a6774e4e --- /dev/null +++ b/framework/src/main/java/org/tron/core/config/args/InetUtil.java @@ -0,0 +1,115 @@ +package org.tron.core.config.args; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.es.ExecutorServiceManager; +import org.tron.p2p.dns.lookup.LookUpTxt; +import org.tron.p2p.utils.NetUtil; + +@Slf4j(topic = "app") +public class InetUtil { + + public static List getInetSocketAddressList(List items) { + List ret = new ArrayList<>(); + if (items.isEmpty()) { + return ret; + } + // Collect entries whose host part is a domain name (not an IP literal). + List domainEntries = new ArrayList<>(); + for (String item : items) { + String host = NetUtil.parseInetSocketAddress(item).getHostString(); + if (!NetUtil.validIpV4(host) && !NetUtil.validIpV6(host)) { + domainEntries.add(item); + } + } + + // Resolve domain names: spin up a thread pool only when there are multiple domains + Map domainResolved = new HashMap<>(); + if (domainEntries.size() > 1) { + String poolName = "args-dns-lookup"; + ExecutorService dnsPool = ExecutorServiceManager + .newFixedThreadPool(poolName, domainEntries.size(), true); + List> 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 { + domainResolved.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, poolName); + } else if (domainEntries.size() == 1) { + String entry = domainEntries.get(0); + domainResolved.put(entry, resolveInetSocketAddress(entry)); + } + + // Build the result list preserving the original config order. + for (String configString : items) { + InetSocketAddress inetSocketAddress; + InetSocketAddress parsed = NetUtil.parseInetSocketAddress(configString); + if (NetUtil.validIpV4(parsed.getHostString()) || NetUtil.validIpV6(parsed.getHostString())) { + inetSocketAddress = parsed; + } else { + inetSocketAddress = domainResolved.get(configString); + } + if (inetSocketAddress == null) { + continue; + } + ret.add(inetSocketAddress); + } + return ret; + } + + /** + * Resolves a {@code domain:port} address string to an {@link InetSocketAddress} via DNS. + */ + private static InetSocketAddress resolveInetSocketAddress(String configString) { + InetSocketAddress parsed = NetUtil.parseInetSocketAddress(configString); + String host = parsed.getHostString(); + int port = parsed.getPort(); + InetAddress address = LookUpTxt.lookUpIp(host, true); + if (address == null) { + address = LookUpTxt.lookUpIp(host, false); + } + if (address == null) { + return null; + } + logger.info("Resolve {} to {}", host, address.getHostAddress()); + return new InetSocketAddress(address, port); + } + + /** + * Resolves a hostname or IP string to a numeric IP address string. + */ + public static InetAddress resolveInetAddress(String ipOrDomain) { + // Fast path: already a numeric address — no lookup needed. + if (NetUtil.validIpV4(ipOrDomain) || NetUtil.validIpV6(ipOrDomain)) { + try { + return InetAddress.getByName(ipOrDomain); + } catch (UnknownHostException e) { + return null; + } + } + InetAddress address = LookUpTxt.lookUpIp(ipOrDomain, true); + if (address == null) { + address = LookUpTxt.lookUpIp(ipOrDomain, false); + } + return address; + } +}