diff --git a/common/build.gradle b/common/build.gradle index 8ea91ecd5b1..98fc3257190 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -12,7 +12,6 @@ dependencies { api "com.cedarsoftware:java-util:3.2.0" api group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1' api group: 'commons-codec', name: 'commons-codec', version: '1.11' - api group: 'com.beust', name: 'jcommander', version: '1.78' api group: 'com.typesafe', name: 'config', version: '1.3.2' api group: 'io.prometheus', name: 'simpleclient', version: '0.15.0' api group: 'io.prometheus', name: 'simpleclient_httpserver', version: '0.15.0' diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index d1210b27d6c..2bcc2e9c6f3 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -1,6 +1,6 @@ package org.tron.common.parameter; -import com.beust.jcommander.Parameter; +import com.google.common.annotations.VisibleForTesting; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.ArrayList; @@ -23,119 +23,61 @@ public class CommonParameter { - public static final String IGNORE_WRONG_WITNESS_ADDRESS_FORMAT = - "The localWitnessAccountAddress format is incorrect, ignored"; - public static CommonParameter PARAMETER = new CommonParameter(); + protected static CommonParameter PARAMETER = new CommonParameter(); + + // Runtime chain state: set by VMConfig.initVmHardFork() + // when the energy-limit governance proposal is activated. + // Legacy: should belong to VMConfig, not here. @Setter public static boolean ENERGY_LIMIT_HARD_FORK = false; + + // ── Startup parameters ──────────────────────── @Getter - @Parameter(names = {"-c", "--config"}, description = "Config file (default:config.conf)") - public String shellConfFileName = ""; - @Getter - @Setter - public String configFilePath = ""; - @Getter - @Parameter(names = {"-d", "--output-directory"}, - description = "Data directory for the databases (default:output-directory)") public String outputDirectory = "output-directory"; @Getter - @Parameter(names = {"--log-config"}, description = "Logback config file") public String logbackPath = ""; - @Getter - @Parameter(names = {"-h", "--help"}, help = true, description = "Show help message") - public boolean help = false; + // ── Flags (CLI + Config) ────────────────────── @Getter @Setter - @Parameter(names = {"-w", "--witness"}, description = "Is witness node") public boolean witness = false; @Getter @Setter - @Parameter(names = {"--support-constant"}, description = "Support constant calling for TVM. " - + "(defalut: false)") public boolean supportConstant = false; @Getter @Setter - @Parameter(names = {"--max-energy-limit-for-constant"}, description = "Max energy limit for " - + "constant calling. (default: 100,000,000)") public long maxEnergyLimitForConstant = 100_000_000L; @Getter @Setter - @Parameter(names = {"--lru-cache-size"}, description = "Max LRU size for caching bytecode and " - + "result of JUMPDEST analysis. (default: 500)") public int lruCacheSize = 500; @Getter @Setter - @Parameter(names = {"--debug"}, description = "Switch for TVM debug mode. In debug model, TVM " - + "will not check for timeout. (default: false)") public boolean debug = false; @Getter @Setter - @Parameter(names = {"--min-time-ratio"}, description = "Minimum CPU tolerance when executing " - + "timeout transactions while synchronizing blocks. (default: 0.0)") public double minTimeRatio = 0.0; @Getter @Setter - @Parameter(names = {"--max-time-ratio"}, description = "Maximum CPU tolerance when executing " - + "non-timeout transactions while synchronizing blocks. (default: 5.0)") public double maxTimeRatio = calcMaxTimeRatio(); @Getter @Setter - @Parameter(names = {"--save-internaltx"}, description = "Save internal transactions generated " - + "during TVM execution, such as create, call and suicide. (default: false)") public boolean saveInternalTx; @Getter @Setter - @Parameter(names = {"--save-featured-internaltx"}, description = "Save featured internal " - + "transactions generated during TVM execution, such as freeze, vote and so on. " - + "(default: false)") public boolean saveFeaturedInternalTx; @Getter @Setter - @Parameter(names = {"--save-cancel-all-unfreeze-v2-details"}, description = "Record the details of the internal " - + "transactions generated by the CANCELALLUNFREEZEV2 opcode, such as bandwidth/energy/tronpower cancel amount. " - + "(default: false)") public boolean saveCancelAllUnfreezeV2Details; @Getter @Setter - @Parameter(names = {"--long-running-time"}) public int longRunningTime = 10; @Getter @Setter - @Parameter(names = {"--max-connect-number"}, description = "Http server max connect number " - + "(default:50)") public int maxHttpConnectNumber = 50; @Getter - @Parameter(description = "--seed-nodes") public List seedNodes = new ArrayList<>(); - @Parameter(names = {"-p", "--private-key"}, description = "Witness private key") - public String privateKey = ""; - @Parameter(names = {"--witness-address"}, description = "witness-address") - public String witnessAddress = ""; - @Parameter(names = {"--password"}, description = "password") - public String password; - @Parameter(names = {"--storage-db-directory"}, description = "Storage db directory") - public String storageDbDirectory = ""; - @Parameter(names = { - "--storage-db-engine"}, description = "Storage db engine.(leveldb or rocksdb)") - public String storageDbEngine = ""; - @Parameter(names = { - "--storage-db-synchronous"}, - description = "Storage db is synchronous or not.(true or false)") - public String storageDbSynchronous = ""; - @Parameter(names = {"--contract-parse-enable"}, description = "Switch for contract parses in " + - "java-tron. (default: true)") - public String contractParseEnable = ""; - @Parameter(names = {"--storage-index-directory"}, - description = "Storage index directory") - public String storageIndexDirectory = ""; - @Parameter(names = {"--storage-index-switch"}, description = "Storage index switch.(on or off)") - public String storageIndexSwitch = ""; - @Parameter(names = {"--storage-transactionHistory-switch"}, - description = "Storage transaction history switch.(on or off)") - public String storageTransactionHistorySwitch = ""; - @Getter - @Parameter(names = {"--fast-forward"}) + @Getter public boolean fastForward = false; + // ── Network / P2P ───────────────────────────── @Getter @Setter public String chainId; @@ -153,7 +95,7 @@ public class CommonParameter { public boolean nodeEffectiveCheckEnable; @Getter @Setter - public int nodeConnectionTimeout; + public int nodeConnectionTimeout = 2000; // from clearParam(), consistent with mainnet.conf @Getter @Setter public int fetchBlockTimeout; @@ -162,19 +104,19 @@ public class CommonParameter { public int nodeChannelReadTimeout; @Getter @Setter - public int maxConnections; + public int maxConnections = 30; // from clearParam(), consistent with mainnet.conf @Getter @Setter - public int minConnections; + public int minConnections = 8; // from clearParam(), consistent with mainnet.conf @Getter @Setter - public int minActiveConnections; + public int minActiveConnections = 3; // from clearParam(), consistent with mainnet.conf @Getter @Setter - public int maxConnectionsWithSameIp; + public int maxConnectionsWithSameIp = 2; // from clearParam(), consistent with mainnet.conf @Getter @Setter - public int maxTps; + public int maxTps; // clearParam: 1000 @Getter @Setter public int minParticipationRate; @@ -197,26 +139,27 @@ public class CommonParameter { public boolean nodeEnableIpv6 = false; @Getter @Setter - public List dnsTreeUrls; + public List dnsTreeUrls; // clearParam: new ArrayList<>() @Getter @Setter public PublishConfig dnsPublishConfig; @Getter @Setter - public long syncFetchBatchNum; + public long syncFetchBatchNum; // clearParam: 2000 - //If you are running a solidity node for java tron, this flag is set to true + // If you are running a solidity node for java tron, + // this flag is set to true @Getter @Setter - @Parameter(names = {"--solidity"}, description = "running a solidity node for java tron") public boolean solidityNode = false; - //If you are running KeystoreFactory, this flag is set to true + // If you are running KeystoreFactory, + // this flag is set to true @Getter @Setter - @Parameter(names = {"--keystore-factory"}, description = "running KeystoreFactory") public boolean keystoreFactory = false; + // ── RPC / HTTP ──────────────────────────────── @Getter @Setter public int rpcPort; @@ -240,11 +183,9 @@ public class CommonParameter { public int jsonRpcHttpPBFTPort; @Getter @Setter - @Parameter(names = {"--rpc-thread"}, description = "Num of gRPC thread") public int rpcThreadNum; @Getter @Setter - @Parameter(names = {"--solidity-thread"}, description = "Num of solidity thread") public int solidityThreads; @Getter @Setter @@ -252,12 +193,9 @@ public class CommonParameter { @Getter @Setter public int flowControlWindow; - // the positive limit of RST_STREAM frames per connection per period for grpc, - // 0 or Integer.MAX_VALUE for unlimited, by default there is no limit. @Getter @Setter public int rpcMaxRstStream; - // the positive number of seconds per period for grpc @Getter @Setter public int rpcSecondsPerWindow; @@ -284,42 +222,44 @@ public class CommonParameter { public boolean isRpcReflectionServiceEnable; @Getter @Setter - @Parameter(names = {"--validate-sign-thread"}, description = "Num of validate thread") public int validateSignThreadNum; @Getter @Setter - public long maintenanceTimeInterval; // (ms) + public long maintenanceTimeInterval; @Getter @Setter - public long proposalExpireTime; // (ms) + public long proposalExpireTime; @Getter @Setter - public int checkFrozenTime; // for test only + public int checkFrozenTime; // clearParam: 1 + + // ── Committee parameters ────────────────────── @Getter @Setter - public long allowCreationOfContracts; //committee parameter + public long allowCreationOfContracts; @Getter @Setter - public long allowAdaptiveEnergy; //committee parameter + public long allowAdaptiveEnergy; @Getter @Setter - public long allowDelegateResource; //committee parameter + public long allowDelegateResource; @Getter @Setter - public long allowSameTokenName; //committee parameter + public long allowSameTokenName; @Getter @Setter - public long allowTvmTransferTrc10; //committee parameter + public long allowTvmTransferTrc10; @Getter @Setter - public long allowTvmConstantinople; //committee parameter + public long allowTvmConstantinople; @Getter @Setter - public long allowTvmSolidity059; //committee parameter + public long allowTvmSolidity059; @Getter @Setter - public long forbidTransferToContract; //committee parameter + public long forbidTransferToContract; + // ── Netty ───────────────────────────────────── @Getter @Setter public int tcpNettyWorkThreadNum; @@ -328,8 +268,7 @@ public class CommonParameter { public int udpNettyWorkThreadNum; @Getter @Setter - @Parameter(names = {"--trust-node"}, description = "Trust node addr") - public String trustNodeAddr; + public String trustNodeAddr; // clearParam: "" @Getter @Setter public boolean walletExtensionApi; @@ -338,7 +277,7 @@ public class CommonParameter { public boolean estimateEnergy; @Getter @Setter - public int estimateEnergyMaxRetry; + public int estimateEnergyMaxRetry = 3; // from clearParam(), consistent with mainnet.conf @Getter @Setter public int backupPriority; @@ -353,13 +292,13 @@ public class CommonParameter { public List backupMembers; @Getter @Setter - public long receiveTcpMinDataLength; + public long receiveTcpMinDataLength; // clearParam: 2048 @Getter @Setter public boolean isOpenFullTcpDisconnect; @Getter @Setter - public int inactiveThreshold; + public int inactiveThreshold = 600; // from clearParam(), consistent with mainnet.conf @Getter @Setter public boolean nodeDetectEnable; @@ -383,42 +322,34 @@ public class CommonParameter { public boolean trxCacheEnable; @Getter @Setter - public long allowMarketTransaction; //committee parameter - + public long allowMarketTransaction; @Getter @Setter public long allowTransactionFeePool; - @Getter @Setter public long allowBlackHoleOptimization; - @Getter @Setter public long allowNewResourceModel; - // @Getter - // @Setter - // public long allowShieldedTransaction; //committee parameter - // full node used this parameter to close shielded transaction @Getter @Setter - public boolean allowShieldedTransactionApi; + public boolean allowShieldedTransactionApi; // clearParam: true @Getter @Setter public long blockNumForEnergyLimit; @Getter @Setter - @Parameter(names = {"--es"}, description = "Start event subscribe server") public boolean eventSubscribe = false; @Getter @Setter - public long trxExpirationTimeInMilliseconds; // (ms) - @Parameter(names = {"-v", "--version"}, description = "Output code version", help = true) - public boolean version; + public long trxExpirationTimeInMilliseconds; + + // ── Shielded / ZK ───────────────────────────── @Getter @Setter - public String zenTokenId; + public String zenTokenId; // clearParam: "000000" @Getter @Setter public long allowProtoFilterNum; @@ -430,7 +361,7 @@ public class CommonParameter { public int validContractProtoThreadNum = 1; @Getter @Setter - public int shieldedTransInPendingMaxCounts; + public int shieldedTransInPendingMaxCounts; // clearParam: 10 @Getter @Setter public long changedDelegation; @@ -442,21 +373,21 @@ public class CommonParameter { public RateLimiterInitialization rateLimiterInitialization; @Getter @Setter - public int rateLimiterGlobalQps; + public int rateLimiterGlobalQps = 50000; // from clearParam(), consistent with mainnet.conf @Getter @Setter - public int rateLimiterGlobalIpQps; + public int rateLimiterGlobalIpQps = 10000; // from clearParam(), consistent with mainnet.conf @Getter - public int rateLimiterGlobalApiQps; + public int rateLimiterGlobalApiQps = 1000; // from clearParam(), consistent with mainnet.conf @Getter @Setter - public double rateLimiterSyncBlockChain; + public double rateLimiterSyncBlockChain; // clearParam: 3.0 @Getter @Setter - public double rateLimiterFetchInvData; + public double rateLimiterFetchInvData; // clearParam: 3.0 @Getter @Setter - public double rateLimiterDisconnect; + public double rateLimiterDisconnect; // clearParam: 1.0 @Getter public DbBackupConfig dbBackupConfig; @Getter @@ -465,19 +396,19 @@ public class CommonParameter { public GenesisBlock genesisBlock; @Getter @Setter - @Parameter(names = {"--p2p-disable"}, description = "Switch for p2p module initialization. " - + "(defalut: false)", arity = 1) public boolean p2pDisable = false; @Getter @Setter - public List activeNodes; + // from clearParam(), consistent with mainnet.conf + public List activeNodes = new ArrayList<>(); @Getter @Setter - public List passiveNodes; + // from clearParam(), consistent with mainnet.conf + public List passiveNodes = new ArrayList<>(); @Getter - public List fastForwardNodes; + public List fastForwardNodes; // clearParam: new ArrayList<>() @Getter - public int maxFastForwardNum; + public int maxFastForwardNum; // clearParam: 4 @Getter public Storage storage; @Getter @@ -495,26 +426,21 @@ public class CommonParameter { @Getter @Setter public boolean rpcEnable = true; - @Getter @Setter public boolean rpcSolidityEnable = true; - @Getter @Setter public boolean rpcPBFTEnable = true; - @Getter @Setter public boolean fullNodeHttpEnable = true; @Getter @Setter public boolean solidityNodeHttpEnable = true; - @Getter @Setter public boolean pBFTHttpEnable = true; - @Getter @Setter public boolean jsonRpcHttpFullNodeEnable = false; @@ -543,39 +469,30 @@ public class CommonParameter { @Getter @Setter public boolean nodeMetricsEnable = false; - @Getter @Setter public boolean metricsStorageEnable = false; - @Getter @Setter public String influxDbIp; - @Getter @Setter public int influxDbPort; - @Getter @Setter public String influxDbDatabase; - @Getter @Setter public int metricsReportInterval = 10; - @Getter @Setter public boolean metricsPrometheusEnable = false; - @Getter @Setter public int metricsPrometheusPort; - @Getter @Setter public int agreeNodeCount; - @Getter @Setter public long allowPBFT; @@ -587,177 +504,136 @@ public class CommonParameter { public int pBFTHttpPort; @Getter @Setter - public long pBFTExpireNum; + public long pBFTExpireNum; // clearParam: 20 @Getter @Setter public long oldSolidityBlockNum = -1; - @Getter/**/ + @Getter @Setter public long allowShieldedTRC20Transaction; - - @Getter/**/ + @Getter @Setter public long allowTvmIstanbul; - @Getter @Setter public long allowTvmFreeze; - @Getter @Setter public long allowTvmVote; - @Getter @Setter public long allowTvmLondon; - @Getter @Setter public long allowTvmCompatibleEvm; - @Getter @Setter public long allowHigherLimitForMaxCpuTimeOfOneTx; - @Getter @Setter public boolean openHistoryQueryWhenLiteFN = false; - @Getter @Setter - @Parameter(names = {"--history-balance-lookup"}) public boolean historyBalanceLookup = false; - @Getter @Setter public boolean openPrintLog = true; @Getter @Setter public boolean openTransactionSort = false; - @Getter @Setter public long allowAccountAssetOptimization; - @Getter @Setter public long allowAssetOptimization; - @Getter @Setter - public List disabledApiList; - + public List disabledApiList; // clearParam: Collections.emptyList() @Getter @Setter public CronExpression shutdownBlockTime = null; - @Getter @Setter public long shutdownBlockHeight = -1; - @Getter @Setter public long shutdownBlockCount = -1; - @Getter @Setter public long blockCacheTimeout = 60; - @Getter @Setter public long allowNewRewardAlgorithm; - @Getter @Setter public long allowNewReward = 0L; - @Getter @Setter public long memoFee = 0L; - @Getter @Setter public long allowDelegateOptimization = 0L; - @Getter @Setter public long unfreezeDelayDays = 0L; - @Getter @Setter public long allowOptimizedReturnValueOfChainId = 0L; - @Getter @Setter public long allowDynamicEnergy = 0L; - @Getter @Setter public long dynamicEnergyThreshold = 0L; - @Getter @Setter public long dynamicEnergyIncreaseFactor = 0L; - @Getter @Setter public long dynamicEnergyMaxFactor = 0L; - @Getter @Setter public boolean dynamicConfigEnable; - @Getter @Setter - public long dynamicConfigCheckInterval; - + public long dynamicConfigCheckInterval; // clearParam: 600 @Getter @Setter public long allowTvmShangHai; - @Getter @Setter public long allowCancelAllUnfreezeV2; - @Getter @Setter public boolean unsolidifiedBlockCheck; - @Getter @Setter - public int maxUnsolidifiedBlocks; - + public int maxUnsolidifiedBlocks; // clearParam: 54 @Getter @Setter public long allowOldRewardOpt; - @Getter @Setter public long allowEnergyAdjustment; - @Getter @Setter public long maxCreateAccountTxSize = 1000L; - @Getter @Setter public long allowStrictMath; - @Getter @Setter - public long consensusLogicOptimization; - + public long consensusLogicOptimization; @Getter @Setter public long allowTvmCancun; - @Getter @Setter public long allowTvmBlob; private static double calcMaxTimeRatio() { - //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; } @@ -765,13 +641,24 @@ public static CommonParameter getInstance() { return PARAMETER; } - public boolean isECKeyCryptoEngine() { + /** + * Reset to a fresh instance. Test-only. + */ + @VisibleForTesting + public static void reset() { + if (PARAMETER.storage != null) { + PARAMETER.storage.deleteAllStoragePaths(); + } + PARAMETER = new CommonParameter(); + } + public boolean isECKeyCryptoEngine() { return cryptoEngine.equalsIgnoreCase(Constant.ECKey_ENGINE); } public boolean isJsonRpcFilterEnabled() { - return jsonRpcHttpFullNodeEnable || jsonRpcHttpSolidityNodeEnable; + return jsonRpcHttpFullNodeEnable + || jsonRpcHttpSolidityNodeEnable; } public int getSafeLruCacheSize() { diff --git a/common/src/main/java/org/tron/core/config/Configuration.java b/common/src/main/java/org/tron/core/config/Configuration.java index 59e6bf11d4a..d75fc8430f8 100644 --- a/common/src/main/java/org/tron/core/config/Configuration.java +++ b/common/src/main/java/org/tron/core/config/Configuration.java @@ -19,7 +19,6 @@ package org.tron.core.config; import static org.apache.commons.lang3.StringUtils.isBlank; -import static org.apache.commons.lang3.StringUtils.isNoneBlank; import com.typesafe.config.ConfigFactory; import java.io.File; @@ -36,21 +35,15 @@ public class Configuration { * @param confFileName path to configuration file * @return loaded configuration */ - public static com.typesafe.config.Config getByFileName(final String shellConfFileName, + public static com.typesafe.config.Config getByFileName( final String confFileName) { - if (isNoneBlank(shellConfFileName)) { - File shellConfFile = new File(shellConfFileName); - resolveConfigFile(shellConfFileName, shellConfFile); - return config; - } - if (isBlank(confFileName)) { - throw new IllegalArgumentException("Configuration path is required!"); - } else { - File confFile = new File(confFileName); - resolveConfigFile(confFileName, confFile); - return config; + throw new IllegalArgumentException( + "Configuration path is required!"); } + File confFile = new File(confFileName); + resolveConfigFile(confFileName, confFile); + return config; } private static void resolveConfigFile(String fileName, File confFile) { diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index 655b6b779fe..7961bb9a9d5 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -176,7 +176,6 @@ public class Storage { public static String getDbEngineFromConfig(final Config config) { if (Arch.isArm64()) { - // if is arm64 but config is leveldb, should throw exception? logger.warn("Arm64 architecture detected, using RocksDB as db engine, ignore config."); return ROCKS_DB_ENGINE; } diff --git a/framework/build.gradle b/framework/build.gradle index 59d070e066d..f781b74617b 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -38,6 +38,7 @@ dependencies { //local libraries implementation fileTree(dir: 'libs', include: '*.jar') // end local libraries + implementation group: 'com.beust', name: 'jcommander', version: '1.78' implementation group: 'io.dropwizard.metrics', name: 'metrics-core', version: '3.1.2' implementation group: 'com.github.davidb', name: 'metrics-influxdb', version: '0.8.2' // http 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 38f1fe4f959..3d5fc321cda 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 @@ -1,7 +1,6 @@ package org.tron.core.config.args; import static java.lang.System.exit; -import static org.fusesource.jansi.Ansi.ansi; import static org.tron.common.math.Maths.max; import static org.tron.common.math.Maths.min; import static org.tron.core.Constant.ADD_PRE_FIX_BYTE_MAINNET; @@ -45,9 +44,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.fusesource.jansi.AnsiConsole; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.arch.Arch; @@ -84,6 +81,9 @@ @Component public class Args extends CommonParameter { + @Getter + private static String configFilePath = ""; + @Getter @Setter private static LocalWitnesses localWitnesses = new LocalWitnesses(); @@ -99,321 +99,44 @@ public class Args extends CommonParameter { solidityContractEventTriggerMap = new ConcurrentHashMap<>(); - public static void clearParam() { - PARAMETER.shellConfFileName = ""; - PARAMETER.configFilePath = ""; - PARAMETER.outputDirectory = "output-directory"; - PARAMETER.help = false; - PARAMETER.witness = false; - PARAMETER.seedNodes = new ArrayList<>(); - PARAMETER.privateKey = ""; - PARAMETER.witnessAddress = ""; - PARAMETER.storageDbDirectory = ""; - PARAMETER.storageIndexDirectory = ""; - PARAMETER.storageIndexSwitch = ""; - - // FIXME: PARAMETER.storage maybe null ? - if (PARAMETER.storage != null) { - // WARNING: WILL DELETE DB STORAGE PATHS - PARAMETER.storage.deleteAllStoragePaths(); - PARAMETER.storage = null; - } - - PARAMETER.overlay = null; - PARAMETER.seedNode = null; - PARAMETER.genesisBlock = null; - PARAMETER.chainId = null; - localWitnesses = null; - PARAMETER.needSyncCheck = false; - PARAMETER.nodeDiscoveryEnable = false; - PARAMETER.nodeDiscoveryPersist = false; - PARAMETER.nodeEffectiveCheckEnable = false; - PARAMETER.nodeConnectionTimeout = 2000; - PARAMETER.activeNodes = new ArrayList<>(); - PARAMETER.passiveNodes = new ArrayList<>(); - PARAMETER.fastForwardNodes = new ArrayList<>(); - PARAMETER.maxFastForwardNum = 4; - PARAMETER.nodeChannelReadTimeout = 0; - PARAMETER.maxConnections = 30; - PARAMETER.minConnections = 8; - PARAMETER.minActiveConnections = 3; - PARAMETER.maxConnectionsWithSameIp = 2; - PARAMETER.maxTps = 1000; - PARAMETER.minParticipationRate = 0; - PARAMETER.nodeListenPort = 0; - PARAMETER.nodeLanIp = ""; - PARAMETER.nodeExternalIp = ""; - PARAMETER.nodeP2pVersion = 0; - PARAMETER.nodeEnableIpv6 = false; - PARAMETER.dnsTreeUrls = new ArrayList<>(); - PARAMETER.dnsPublishConfig = null; - PARAMETER.syncFetchBatchNum = 2000; - PARAMETER.rpcPort = 0; - PARAMETER.rpcOnSolidityPort = 0; - PARAMETER.rpcOnPBFTPort = 0; - PARAMETER.fullNodeHttpPort = 0; - PARAMETER.solidityHttpPort = 0; - PARAMETER.pBFTHttpPort = 0; - PARAMETER.pBFTExpireNum = 20; - PARAMETER.jsonRpcHttpFullNodePort = 0; - PARAMETER.jsonRpcHttpSolidityPort = 0; - PARAMETER.jsonRpcHttpPBFTPort = 0; - PARAMETER.maintenanceTimeInterval = 0; - PARAMETER.proposalExpireTime = 0; - PARAMETER.checkFrozenTime = 1; - PARAMETER.allowCreationOfContracts = 0; - PARAMETER.allowAdaptiveEnergy = 0; - PARAMETER.allowTvmTransferTrc10 = 0; - PARAMETER.allowTvmConstantinople = 0; - PARAMETER.allowDelegateResource = 0; - PARAMETER.allowSameTokenName = 0; - PARAMETER.allowTvmSolidity059 = 0; - PARAMETER.forbidTransferToContract = 0; - PARAMETER.tcpNettyWorkThreadNum = 0; - PARAMETER.udpNettyWorkThreadNum = 0; - PARAMETER.solidityNode = false; - PARAMETER.keystoreFactory = false; - PARAMETER.trustNodeAddr = ""; - PARAMETER.walletExtensionApi = false; - PARAMETER.estimateEnergy = false; - PARAMETER.estimateEnergyMaxRetry = 3; - PARAMETER.receiveTcpMinDataLength = 2048; - PARAMETER.isOpenFullTcpDisconnect = false; - PARAMETER.nodeDetectEnable = false; - PARAMETER.inactiveThreshold = 600; - PARAMETER.supportConstant = false; - PARAMETER.debug = false; - PARAMETER.minTimeRatio = 0.0; - PARAMETER.maxTimeRatio = 5.0; - PARAMETER.longRunningTime = 10; - // PARAMETER.allowShieldedTransaction = 0; - PARAMETER.maxHttpConnectNumber = 50; - PARAMETER.allowMultiSign = 0; - PARAMETER.trxExpirationTimeInMilliseconds = 0; - PARAMETER.allowShieldedTransactionApi = true; - PARAMETER.zenTokenId = "000000"; - PARAMETER.allowProtoFilterNum = 0; - PARAMETER.allowAccountStateRoot = 0; - PARAMETER.validContractProtoThreadNum = 1; - PARAMETER.shieldedTransInPendingMaxCounts = 10; - PARAMETER.changedDelegation = 0; - PARAMETER.rpcEnable = true; - PARAMETER.rpcSolidityEnable = true; - PARAMETER.rpcPBFTEnable = true; - PARAMETER.fullNodeHttpEnable = true; - PARAMETER.solidityNodeHttpEnable = true; - PARAMETER.pBFTHttpEnable = true; - PARAMETER.jsonRpcHttpFullNodeEnable = false; - PARAMETER.jsonRpcHttpSolidityNodeEnable = false; - PARAMETER.jsonRpcHttpPBFTNodeEnable = false; - PARAMETER.jsonRpcMaxBlockRange = 5000; - PARAMETER.jsonRpcMaxSubTopics = 1000; - PARAMETER.jsonRpcMaxBlockFilterNum = 50000; - PARAMETER.nodeMetricsEnable = false; - PARAMETER.metricsStorageEnable = false; - PARAMETER.metricsPrometheusEnable = false; - PARAMETER.agreeNodeCount = MAX_ACTIVE_WITNESS_NUM * 2 / 3 + 1; - PARAMETER.allowPBFT = 0; - PARAMETER.allowShieldedTRC20Transaction = 0; - PARAMETER.allowMarketTransaction = 0; - PARAMETER.allowTransactionFeePool = 0; - PARAMETER.allowBlackHoleOptimization = 0; - PARAMETER.allowNewResourceModel = 0; - PARAMETER.allowTvmIstanbul = 0; - PARAMETER.allowTvmFreeze = 0; - PARAMETER.allowTvmVote = 0; - PARAMETER.allowTvmLondon = 0; - PARAMETER.allowTvmCompatibleEvm = 0; - PARAMETER.historyBalanceLookup = false; - PARAMETER.openPrintLog = true; - PARAMETER.openTransactionSort = false; - PARAMETER.allowAccountAssetOptimization = 0; - PARAMETER.allowAssetOptimization = 0; - PARAMETER.disabledApiList = Collections.emptyList(); - PARAMETER.shutdownBlockTime = null; - PARAMETER.shutdownBlockHeight = -1; - PARAMETER.shutdownBlockCount = -1; - PARAMETER.blockCacheTimeout = 60; - PARAMETER.allowNewRewardAlgorithm = 0; - PARAMETER.allowNewReward = 0; - PARAMETER.memoFee = 0; - PARAMETER.rateLimiterGlobalQps = 50000; - PARAMETER.rateLimiterGlobalIpQps = 10000; - PARAMETER.rateLimiterGlobalApiQps = 1000; - PARAMETER.rateLimiterSyncBlockChain = 3.0; - PARAMETER.rateLimiterFetchInvData = 3.0; - PARAMETER.rateLimiterDisconnect = 1.0; - PARAMETER.p2pDisable = false; - PARAMETER.dynamicConfigEnable = false; - PARAMETER.dynamicConfigCheckInterval = 600; - PARAMETER.allowTvmShangHai = 0; - PARAMETER.unsolidifiedBlockCheck = false; - PARAMETER.maxUnsolidifiedBlocks = 54; - PARAMETER.allowOldRewardOpt = 0; - PARAMETER.allowEnergyAdjustment = 0; - PARAMETER.allowStrictMath = 0; - PARAMETER.consensusLogicOptimization = 0; - PARAMETER.allowTvmCancun = 0; - PARAMETER.allowTvmBlob = 0; - PARAMETER.rpcMaxRstStream = 0; - PARAMETER.rpcSecondsPerWindow = 0; - } - - /** - * print Version. - */ - private static void printVersion() { - Properties properties = new Properties(); - boolean noGitProperties = true; - try { - InputStream in = Thread.currentThread() - .getContextClassLoader().getResourceAsStream("git.properties"); - if (in != null) { - noGitProperties = false; - properties.load(in); - } - } catch (IOException e) { - logger.error(e.getMessage()); - } - JCommander jCommander = new JCommander(); - jCommander.getConsole().println("OS : " + System.getProperty("os.name")); - jCommander.getConsole().println("JVM : " + System.getProperty("java.vendor") + " " - + System.getProperty("java.version") + " " + System.getProperty("os.arch")); - if (!noGitProperties) { - jCommander.getConsole().println("Git : " + properties.getProperty("git.commit.id")); - } - jCommander.getConsole().println("Version : " + Version.getVersion()); - jCommander.getConsole().println("Code : " + Version.VERSION_CODE); - } - - public static void printHelp(JCommander jCommander) { - List parameterDescriptionList = jCommander.getParameters(); - Map stringParameterDescriptionMap = new HashMap<>(); - for (ParameterDescription parameterDescription : parameterDescriptionList) { - String parameterName = parameterDescription.getParameterized().getName(); - stringParameterDescriptionMap.put(parameterName, parameterDescription); - } - - StringBuilder helpStr = new StringBuilder(); - helpStr.append("Name:\n\tFullNode - the java-tron command line interface\n"); - String programName = Strings.isNullOrEmpty(jCommander.getProgramName()) ? "FullNode.jar" : - jCommander.getProgramName(); - helpStr.append(String.format("%nUsage: java -jar %s [options] [seedNode ...]%n", - programName)); - helpStr.append(String.format("%nVERSION: %n%s-%s%n", Version.getVersion(), - getCommitIdAbbrev())); - - Map groupOptionListMap = Args.getOptionGroup(); - for (Map.Entry entry : groupOptionListMap.entrySet()) { - String group = entry.getKey(); - helpStr.append(String.format("%n%s OPTIONS:%n", group.toUpperCase())); - int optionMaxLength = Arrays.stream(entry.getValue()).mapToInt(p -> { - ParameterDescription tmpParameterDescription = stringParameterDescriptionMap.get(p); - if (tmpParameterDescription == null) { - return 1; - } - return tmpParameterDescription.getNames().length(); - }).max().orElse(1); - - for (String option : groupOptionListMap.get(group)) { - ParameterDescription parameterDescription = stringParameterDescriptionMap.get(option); - if (parameterDescription == null) { - logger.warn("Miss option:{}", option); - continue; - } - String tmpOptionDesc = String.format("%s\t\t\t%s%n", - Strings.padEnd(parameterDescription.getNames(), optionMaxLength, ' '), - upperFirst(parameterDescription.getDescription())); - helpStr.append(tmpOptionDesc); - } - } - jCommander.getConsole().println(helpStr.toString()); - } - - public static String upperFirst(String name) { - if (name.length() <= 1) { - return name; - } - name = name.substring(0, 1).toUpperCase() + name.substring(1); - return name; - } - - private static String getCommitIdAbbrev() { - Properties properties = new Properties(); - try { - InputStream in = Thread.currentThread() - .getContextClassLoader().getResourceAsStream("git.properties"); - properties.load(in); - } catch (IOException e) { - logger.warn("Load resource failed,git.properties {}", e.getMessage()); - } - return properties.getProperty("git.commit.id.abbrev"); - } - - private static Map getOptionGroup() { - String[] tronOption = new String[] {"version", "help", "shellConfFileName", "logbackPath", - "eventSubscribe", "solidityNode", "keystoreFactory"}; - String[] dbOption = new String[] {"outputDirectory"}; - String[] witnessOption = new String[] {"witness", "privateKey"}; - String[] vmOption = new String[] {"debug"}; - - Map optionGroupMap = new LinkedHashMap<>(); - optionGroupMap.put("tron", tronOption); - optionGroupMap.put("db", dbOption); - optionGroupMap.put("witness", witnessOption); - optionGroupMap.put("virtual machine", vmOption); - - for (String[] optionList : optionGroupMap.values()) { - for (String option : optionList) { - try { - CommonParameter.class.getField(option); - } catch (NoSuchFieldException e) { - logger.warn("NoSuchFieldException:{},{}", option, e.getMessage()); - } - } - } - return optionGroupMap; - } - /** * set parameters. */ public static void setParam(final String[] args, final String confFileName) { - try { - Arch.throwIfUnsupportedJavaVersion(); - } catch (UnsupportedOperationException e) { - AnsiConsole.systemInstall(); - // To avoid confusion caused by silent execution when using -h or -v flags, - // errors are explicitly logged to the console in this context. - // Console output is not required for errors in other scenarios. - System.out.println(ansi().fgRed().a(e.getMessage()).reset()); - AnsiConsole.systemUninstall(); - throw new TronError(e, TronError.ErrCode.JDK_VERSION); - } - JCommander.newBuilder().addObject(PARAMETER).build().parse(args); - if (PARAMETER.version) { + // 1. Parse CLI args into a separate object + CLIParameter cmd = new CLIParameter(); + JCommander jc = JCommander.newBuilder().addObject(cmd).build(); + jc.parse(args); + + if (cmd.version) { printVersion(); exit(0); } - - if (PARAMETER.isHelp()) { - JCommander jCommander = JCommander.newBuilder().addObject(Args.PARAMETER).build(); - jCommander.parse(args); - Args.printHelp(jCommander); + if (cmd.help) { + Args.printHelp(jc); exit(0); } - PARAMETER.setConfigFilePath( - StringUtils.isNoneBlank(PARAMETER.shellConfFileName) - ? PARAMETER.shellConfFileName : confFileName); - Config config = Configuration.getByFileName(PARAMETER.shellConfFileName, confFileName); - setParam(config); + // Resolve config file path + configFilePath = StringUtils.isNoneBlank(cmd.shellConfFileName) + ? cmd.shellConfFileName : confFileName; + Config config = Configuration.getByFileName(configFilePath); + + // 2. Config overrides defaults + applyConfigParams(config); + + // 3. CLI overrides Config (highest priority) + applyCLIParams(cmd, jc); + + // 4. Init witness (depends on CLI witness flag) + initLocalWitnesses(config, cmd); } /** - * set parameters. + * Apply parameters from config file. */ - public static void setParam(final Config config) { + public static void applyConfigParams( + final Config config) { Wallet.setAddressPreFixByte(ADD_PRE_FIX_BYTE_MAINNET); Wallet.setAddressPreFixString(Constant.ADD_PRE_FIX_STRING_MAINNET); @@ -421,13 +144,6 @@ public static void setParam(final Config config) { PARAMETER.cryptoEngine = config.hasPath(ConfigKey.CRYPTO_ENGINE) ? config .getString(ConfigKey.CRYPTO_ENGINE) : Constant.ECKey_ENGINE; - localWitnesses = new WitnessInitializer(config).initLocalWitnesses(); - if (PARAMETER.isWitness() - && CollectionUtils.isEmpty(localWitnesses.getPrivateKeys())) { - throw new TronError("This is a witness node, but localWitnesses is null", - TronError.ErrCode.WITNESS_INIT); - } - if (config.hasPath(ConfigKey.VM_SUPPORT_CONSTANT)) { PARAMETER.supportConstant = config.getBoolean(ConfigKey.VM_SUPPORT_CONSTANT); } @@ -509,37 +225,14 @@ public static void setParam(final Config config) { PARAMETER.storage = new Storage(); - PARAMETER.storage.setDbEngine(Optional.ofNullable(PARAMETER.storageDbEngine) - .filter(StringUtils::isNotEmpty) - .orElse(Storage.getDbEngineFromConfig(config))); - - PARAMETER.storage.setDbSync(Optional.ofNullable(PARAMETER.storageDbSynchronous) - .filter(StringUtils::isNotEmpty) - .map(Boolean::valueOf) - .orElse(Storage.getDbVersionSyncFromConfig(config))); - - PARAMETER.storage.setContractParseSwitch(Optional.ofNullable(PARAMETER.contractParseEnable) - .filter(StringUtils::isNotEmpty) - .map(Boolean::valueOf) - .orElse(Storage.getContractParseSwitchFromConfig(config))); - - PARAMETER.storage.setDbDirectory(Optional.ofNullable(PARAMETER.storageDbDirectory) - .filter(StringUtils::isNotEmpty) - .orElse(Storage.getDbDirectoryFromConfig(config))); - - PARAMETER.storage.setIndexDirectory(Optional.ofNullable(PARAMETER.storageIndexDirectory) - .filter(StringUtils::isNotEmpty) - .orElse(Storage.getIndexDirectoryFromConfig(config))); - - PARAMETER.storage.setIndexSwitch(Optional.ofNullable(PARAMETER.storageIndexSwitch) - .filter(StringUtils::isNotEmpty) - .orElse(Storage.getIndexSwitchFromConfig(config))); - - PARAMETER.storage - .setTransactionHistorySwitch( - Optional.ofNullable(PARAMETER.storageTransactionHistorySwitch) - .filter(StringUtils::isNotEmpty) - .orElse(Storage.getTransactionHistorySwitchFromConfig(config))); + PARAMETER.storage.setDbEngine(Storage.getDbEngineFromConfig(config)); + PARAMETER.storage.setDbSync(Storage.getDbVersionSyncFromConfig(config)); + PARAMETER.storage.setContractParseSwitch(Storage.getContractParseSwitchFromConfig(config)); + PARAMETER.storage.setDbDirectory(Storage.getDbDirectoryFromConfig(config)); + PARAMETER.storage.setIndexDirectory(Storage.getIndexDirectoryFromConfig(config)); + PARAMETER.storage.setIndexSwitch(Storage.getIndexSwitchFromConfig(config)); + PARAMETER.storage.setTransactionHistorySwitch( + Storage.getTransactionHistorySwitchFromConfig(config)); PARAMETER.storage .setCheckpointVersion(Storage.getCheckpointVersionFromConfig(config)); @@ -1292,6 +985,157 @@ public static void setParam(final Config config) { logConfig(); } + /** + * Apply CLI parameters that were explicitly passed. + * Only assigned parameters override Config values. + */ + private static void applyCLIParams(CLIParameter cmd, JCommander jc) { + Map assigned = jc.getParameters().stream() + .filter(ParameterDescription::isAssigned) + .collect(Collectors.toMap(ParameterDescription::getLongestName, p -> p)); + + if (assigned.containsKey("--output-directory")) { + PARAMETER.outputDirectory = cmd.outputDirectory; + } + if (assigned.containsKey("--witness")) { + PARAMETER.witness = cmd.witness; + } + if (assigned.containsKey("--support-constant")) { + PARAMETER.supportConstant = cmd.supportConstant; + } + if (assigned.containsKey("--max-energy-limit-for-constant")) { + PARAMETER.maxEnergyLimitForConstant = cmd.maxEnergyLimitForConstant; + } + if (assigned.containsKey("--lru-cache-size")) { + PARAMETER.lruCacheSize = cmd.lruCacheSize; + } + if (assigned.containsKey("--debug")) { + PARAMETER.debug = cmd.debug; + } + if (assigned.containsKey("--min-time-ratio")) { + PARAMETER.minTimeRatio = cmd.minTimeRatio; + } + if (assigned.containsKey("--max-time-ratio")) { + PARAMETER.maxTimeRatio = cmd.maxTimeRatio; + } + if (assigned.containsKey("--save-internaltx")) { + PARAMETER.saveInternalTx = cmd.saveInternalTx; + } + if (assigned.containsKey("--save-featured-internaltx")) { + PARAMETER.saveFeaturedInternalTx = cmd.saveFeaturedInternalTx; + } + if (assigned.containsKey("--save-cancel-all-unfreeze-v2-details")) { + PARAMETER.saveCancelAllUnfreezeV2Details = cmd.saveCancelAllUnfreezeV2Details; + } + if (assigned.containsKey("--long-running-time")) { + PARAMETER.longRunningTime = cmd.longRunningTime; + } + if (assigned.containsKey("--max-connect-number")) { + PARAMETER.maxHttpConnectNumber = cmd.maxHttpConnectNumber; + } + if (assigned.containsKey("--storage-db-directory")) { + PARAMETER.storage.setDbDirectory(cmd.storageDbDirectory); + } + if (assigned.containsKey("--storage-db-engine")) { + PARAMETER.storage.setDbEngine(cmd.storageDbEngine); + } + if (assigned.containsKey("--storage-db-synchronous")) { + PARAMETER.storage.setDbSync(Boolean.valueOf(cmd.storageDbSynchronous)); + } + if (assigned.containsKey("--contract-parse-enable")) { + PARAMETER.storage.setContractParseSwitch(Boolean.valueOf(cmd.contractParseEnable)); + } + if (assigned.containsKey("--storage-index-directory")) { + PARAMETER.storage.setIndexDirectory(cmd.storageIndexDirectory); + } + if (assigned.containsKey("--storage-index-switch")) { + PARAMETER.storage.setIndexSwitch(cmd.storageIndexSwitch); + } + if (assigned.containsKey("--storage-transactionHistory-switch")) { + PARAMETER.storage.setTransactionHistorySwitch(cmd.storageTransactionHistorySwitch); + } + if (assigned.containsKey("--fast-forward")) { + PARAMETER.fastForward = cmd.fastForward; + } + if (assigned.containsKey("--solidity")) { + PARAMETER.solidityNode = cmd.solidityNode; + } + if (assigned.containsKey("--keystore-factory")) { + PARAMETER.keystoreFactory = cmd.keystoreFactory; + } + if (assigned.containsKey("--rpc-thread")) { + PARAMETER.rpcThreadNum = cmd.rpcThreadNum; + } + if (assigned.containsKey("--solidity-thread")) { + PARAMETER.solidityThreads = cmd.solidityThreads; + } + if (assigned.containsKey("--validate-sign-thread")) { + PARAMETER.validateSignThreadNum = cmd.validateSignThreadNum; + } + if (assigned.containsKey("--trust-node")) { + PARAMETER.trustNodeAddr = cmd.trustNodeAddr; + } + if (assigned.containsKey("--es")) { + PARAMETER.eventSubscribe = cmd.eventSubscribe; + } + if (assigned.containsKey("--p2p-disable")) { + PARAMETER.p2pDisable = cmd.p2pDisable; + } + if (assigned.containsKey("--history-balance-lookup")) { + PARAMETER.historyBalanceLookup = cmd.historyBalanceLookup; + } + if (assigned.containsKey("--log-config")) { + PARAMETER.logbackPath = cmd.logbackPath; + } + } + + private static void initLocalWitnesses(Config config, CLIParameter cmd) { + // not a witness node, skip + if (!PARAMETER.isWitness()) { + localWitnesses = new LocalWitnesses(); + return; + } + + // path 1: CLI --private-key + if (StringUtils.isNotBlank(cmd.privateKey)) { + localWitnesses = WitnessInitializer.initFromCLIPrivateKey( + cmd.privateKey, cmd.witnessAddress); + return; + } + + String witnessAddr = config.hasPath(ConfigKey.LOCAL_WITNESS_ACCOUNT_ADDRESS) + ? config.getString(ConfigKey.LOCAL_WITNESS_ACCOUNT_ADDRESS) : null; + + // path 2: config localwitness (private key list) + if (config.hasPath(ConfigKey.LOCAL_WITNESS)) { + List keys = config.getStringList(ConfigKey.LOCAL_WITNESS); + if (!keys.isEmpty()) { + localWitnesses = WitnessInitializer.initFromCFGPrivateKey(keys, witnessAddr); + return; + } + } + + // path 3: config localwitnesskeystore + password + if (config.hasPath(ConfigKey.LOCAL_WITNESS_KEYSTORE)) { + List keystores = config.getStringList(ConfigKey.LOCAL_WITNESS_KEYSTORE); + if (!keystores.isEmpty()) { + localWitnesses = WitnessInitializer.initFromKeystore( + keystores, cmd.password, witnessAddr); + return; + } + } + + // no private key source configured + throw new TronError("This is a witness node, but localWitnesses is null", + TronError.ErrCode.WITNESS_INIT); + } + + public static void clearParam() { + CommonParameter.reset(); + configFilePath = ""; + localWitnesses = null; + } + private static long getProposalExpirationTime(final Config config) { if (config.hasPath(ConfigKey.COMMITTEE_PROPOSAL_EXPIRE_TIME)) { throw new TronError("It is not allowed to configure committee.proposalExpireTime in " @@ -1793,5 +1637,120 @@ public String getOutputDirectory() { } return this.outputDirectory; } + + // ── CLI help / version utilities ───────────────── + + private static void printVersion() { + Properties properties = new Properties(); + boolean noGitProperties = true; + try { + InputStream in = Thread.currentThread() + .getContextClassLoader().getResourceAsStream("git.properties"); + if (in != null) { + noGitProperties = false; + properties.load(in); + } + } catch (IOException e) { + logger.error(e.getMessage()); + } + JCommander jCommander = new JCommander(); + jCommander.getConsole().println("OS : " + System.getProperty("os.name")); + jCommander.getConsole().println("JVM : " + System.getProperty("java.vendor") + " " + + System.getProperty("java.version") + " " + System.getProperty("os.arch")); + if (!noGitProperties) { + jCommander.getConsole().println("Git : " + properties.getProperty("git.commit.id")); + } + jCommander.getConsole().println("Version : " + Version.getVersion()); + jCommander.getConsole().println("Code : " + Version.VERSION_CODE); + } + + public static void printHelp(JCommander jCommander) { + List parameterDescriptionList = jCommander.getParameters(); + Map stringParameterDescriptionMap = new HashMap<>(); + for (ParameterDescription parameterDescription : parameterDescriptionList) { + String parameterName = parameterDescription.getParameterized().getName(); + stringParameterDescriptionMap.put(parameterName, parameterDescription); + } + + StringBuilder helpStr = new StringBuilder(); + helpStr.append("Name:\n\tFullNode - the java-tron command line interface\n"); + String programName = Strings.isNullOrEmpty(jCommander.getProgramName()) ? "FullNode.jar" : + jCommander.getProgramName(); + helpStr.append(String.format("%nUsage: java -jar %s [options] [seedNode ...]%n", + programName)); + helpStr.append(String.format("%nVERSION: %n%s-%s%n", Version.getVersion(), + getCommitIdAbbrev())); + + Map groupOptionListMap = Args.getOptionGroup(); + for (Map.Entry entry : groupOptionListMap.entrySet()) { + String group = entry.getKey(); + helpStr.append(String.format("%n%s OPTIONS:%n", group.toUpperCase())); + int optionMaxLength = Arrays.stream(entry.getValue()).mapToInt(p -> { + ParameterDescription tmpParameterDescription = stringParameterDescriptionMap.get(p); + if (tmpParameterDescription == null) { + return 1; + } + return tmpParameterDescription.getNames().length(); + }).max().orElse(1); + + for (String option : groupOptionListMap.get(group)) { + ParameterDescription parameterDescription = stringParameterDescriptionMap.get(option); + if (parameterDescription == null) { + logger.warn("Miss option:{}", option); + continue; + } + String tmpOptionDesc = String.format("%s\t\t\t%s%n", + Strings.padEnd(parameterDescription.getNames(), optionMaxLength, ' '), + upperFirst(parameterDescription.getDescription())); + helpStr.append(tmpOptionDesc); + } + } + jCommander.getConsole().println(helpStr.toString()); + } + + public static String upperFirst(String name) { + if (name.length() <= 1) { + return name; + } + name = name.substring(0, 1).toUpperCase() + name.substring(1); + return name; + } + + private static String getCommitIdAbbrev() { + Properties properties = new Properties(); + try { + InputStream in = Thread.currentThread() + .getContextClassLoader().getResourceAsStream("git.properties"); + properties.load(in); + } catch (IOException e) { + logger.warn("Load resource failed,git.properties {}", e.getMessage()); + } + return properties.getProperty("git.commit.id.abbrev"); + } + + private static Map getOptionGroup() { + String[] tronOption = new String[] {"version", "help", "shellConfFileName", "logbackPath", + "eventSubscribe", "solidityNode", "keystoreFactory"}; + String[] dbOption = new String[] {"outputDirectory"}; + String[] witnessOption = new String[] {"witness", "privateKey"}; + String[] vmOption = new String[] {"debug"}; + + Map optionGroupMap = new LinkedHashMap<>(); + optionGroupMap.put("tron", tronOption); + optionGroupMap.put("db", dbOption); + optionGroupMap.put("witness", witnessOption); + optionGroupMap.put("virtual machine", vmOption); + + for (String[] optionList : optionGroupMap.values()) { + for (String option : optionList) { + try { + CLIParameter.class.getField(option); + } catch (NoSuchFieldException e) { + logger.warn("NoSuchFieldException:{},{}", option, e.getMessage()); + } + } + } + return optionGroupMap; + } } diff --git a/framework/src/main/java/org/tron/core/config/args/CLIParameter.java b/framework/src/main/java/org/tron/core/config/args/CLIParameter.java new file mode 100644 index 00000000000..f65ed7063eb --- /dev/null +++ b/framework/src/main/java/org/tron/core/config/args/CLIParameter.java @@ -0,0 +1,156 @@ +package org.tron.core.config.args; + +import com.beust.jcommander.Parameter; +import java.util.ArrayList; +import java.util.List; +import lombok.NoArgsConstructor; + +/** + * CLI parameter definitions parsed by JCommander. + * Fields here have NO default values — defaults live in CommonParameter. + * JCommander only populates fields that are explicitly passed on the + * command line. + */ +@NoArgsConstructor +public class CLIParameter { + + // ── Startup parameters ────────────────────────── + + @Parameter(names = {"-c", "--config"}, description = "Config file (default:config.conf)") + public String shellConfFileName; + + @Parameter(names = {"-d", "--output-directory"}, description = "Data directory for the " + + "databases (default:output-directory)") + public String outputDirectory; + + @Parameter(names = {"--log-config"}, description = "Logback config file") + public String logbackPath; + + @Parameter(names = {"-h", "--help"}, help = true, description = "Show help message") + public boolean help; + + @Parameter(names = {"-v", "--version"}, description = "Output code version", help = true) + public boolean version; + + @Parameter(names = {"-w", "--witness"}, description = "Is witness node") + public boolean witness; + + @Parameter(names = {"-p", "--private-key"}, description = "Witness private key") + public String privateKey; + + @Parameter(names = {"--witness-address"}, description = "witness-address") + public String witnessAddress; + + @Parameter(names = {"--password"}, description = "password") + public String password; + + @Parameter(names = {"--solidity"}, description = "running a solidity node for java tron") + public boolean solidityNode; + + @Parameter(names = {"--keystore-factory"}, description = "running KeystoreFactory") + public boolean keystoreFactory; + + @Parameter(names = {"--fast-forward"}) + public boolean fastForward; + + @Parameter(names = {"--es"}, description = "Start event subscribe server") + public boolean eventSubscribe; + + @Parameter(names = {"--p2p-disable"}, description = "Switch for p2p module initialization. " + + "(defalut: false)", arity = 1) + public boolean p2pDisable; + + @Parameter(description = "--seed-nodes") + public List seedNodes = new ArrayList<>(); + + // ── Storage parameters ────────────────────────── + + @Parameter(names = {"--storage-db-directory"}, description = "Storage db directory") + public String storageDbDirectory; + + @Parameter(names = {"--storage-db-engine"}, + description = "Storage db engine.(leveldb or rocksdb)") + public String storageDbEngine; + + @Parameter(names = {"--storage-db-synchronous"}, + description = "Storage db is synchronous or not.(true or false)") + public String storageDbSynchronous; + + @Parameter(names = {"--storage-index-directory"}, description = "Storage index directory") + public String storageIndexDirectory; + + @Parameter(names = {"--storage-index-switch"}, + description = "Storage index switch.(on or off)") + public String storageIndexSwitch; + + @Parameter(names = {"--storage-transactionHistory-switch"}, + description = "Storage transaction history switch.(on or off)") + public String storageTransactionHistorySwitch; + + @Parameter(names = {"--contract-parse-enable"}, description = "Switch for contract parses in " + + "java-tron. (default: true)") + public String contractParseEnable; + + // ── Runtime parameters ────────────────────────── + + @Parameter(names = {"--support-constant"}, description = "Support constant calling for TVM. " + + "(defalut: false)") + public boolean supportConstant; + + @Parameter(names = {"--max-energy-limit-for-constant"}, + description = "Max energy limit for constant calling. (default: 100,000,000)") + public long maxEnergyLimitForConstant; + + @Parameter(names = {"--lru-cache-size"}, description = "Max LRU size for caching bytecode and " + + "result of JUMPDEST analysis. (default: 500)") + public int lruCacheSize; + + @Parameter(names = {"--debug"}, description = "Switch for TVM debug mode. In debug model, TVM " + + "will not check for timeout. (default: false)") + public boolean debug; + + @Parameter(names = {"--min-time-ratio"}, description = "Minimum CPU tolerance when executing " + + "timeout transactions while synchronizing blocks. (default: 0.0)") + public double minTimeRatio; + + @Parameter(names = {"--max-time-ratio"}, description = "Maximum CPU tolerance when executing " + + "non-timeout transactions while synchronizing blocks. (default: 5.0)") + public double maxTimeRatio; + + @Parameter(names = {"--save-internaltx"}, description = "Save internal transactions generated " + + "during TVM execution, such as create, call and suicide. (default: false)") + public boolean saveInternalTx; + + @Parameter(names = {"--save-featured-internaltx"}, description = "Save featured internal " + + "transactions generated during TVM execution, such as freeze, vote and so on. " + + "(default: false)") + public boolean saveFeaturedInternalTx; + + @Parameter(names = {"--save-cancel-all-unfreeze-v2-details"}, + description = "Record the details of the internal transactions generated by the " + + "CANCELALLUNFREEZEV2 opcode, such as bandwidth/energy/tronpower cancel amount. " + + "(default: false)") + public boolean saveCancelAllUnfreezeV2Details; + + @Parameter(names = {"--long-running-time"}) + public int longRunningTime; + + @Parameter(names = {"--max-connect-number"}, description = "Http server max connect number " + + "(default:50)") + public int maxHttpConnectNumber; + + @Parameter(names = {"--rpc-thread"}, description = "Num of gRPC thread") + public int rpcThreadNum; + + @Parameter(names = {"--solidity-thread"}, description = "Num of solidity thread") + public int solidityThreads; + + @Parameter(names = {"--validate-sign-thread"}, description = "Num of validate thread") + public int validateSignThreadNum; + + @Parameter(names = {"--trust-node"}, description = "Trust node addr") + public String trustNodeAddr; + + @Parameter(names = {"--history-balance-lookup"}) + public boolean historyBalanceLookup; +} diff --git a/framework/src/main/java/org/tron/core/config/args/ConfigKey.java b/framework/src/main/java/org/tron/core/config/args/ConfigKey.java index e160eb7a346..0cce5867d8b 100644 --- a/framework/src/main/java/org/tron/core/config/args/ConfigKey.java +++ b/framework/src/main/java/org/tron/core/config/args/ConfigKey.java @@ -10,7 +10,7 @@ private ConfigKey() { } // local witness - public static final String LOCAL_WITNESS = "localwitness"; + public static final String LOCAL_WITNESS = "localwitness"; //private key public static final String LOCAL_WITNESS_ACCOUNT_ADDRESS = "localWitnessAccountAddress"; public static final String LOCAL_WITNESS_KEYSTORE = "localwitnesskeystore"; diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index 9963ac1f419..04ba1b306eb 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -34,7 +34,7 @@ public void init() { reloadExecutor = ExecutorServiceManager.newSingleThreadScheduledExecutor(esName); logger.info("Start the dynamic loading configuration service"); long checkInterval = parameter.getDynamicConfigCheckInterval(); - configFile = new File(parameter.getConfigFilePath()); + configFile = new File(Args.getConfigFilePath()); if (!configFile.exists()) { logger.warn("Configuration path is required! No such file {}", configFile); return; @@ -60,7 +60,7 @@ public void run() { public void reload() { logger.debug("Reloading ... "); - Config config = Configuration.getByFileName(parameter.getConfigFilePath(), null); + Config config = Configuration.getByFileName(Args.getConfigFilePath()); updateActiveNodes(config); diff --git a/framework/src/main/java/org/tron/core/config/args/WitnessInitializer.java b/framework/src/main/java/org/tron/core/config/args/WitnessInitializer.java index 2a97b6ab631..30711eb6190 100644 --- a/framework/src/main/java/org/tron/core/config/args/WitnessInitializer.java +++ b/framework/src/main/java/org/tron/core/config/args/WitnessInitializer.java @@ -1,6 +1,5 @@ package org.tron.core.config.args; -import com.typesafe.config.Config; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -19,97 +18,68 @@ @Slf4j public class WitnessInitializer { - private final Config config; - - private LocalWitnesses localWitnesses; - - public WitnessInitializer(Config config) { - this.config = config; - this.localWitnesses = new LocalWitnesses(); - } - - public LocalWitnesses initLocalWitnesses() { - if (!Args.PARAMETER.isWitness()) { - return localWitnesses; - } - - if (tryInitFromCommandLine()) { - return localWitnesses; - } - - if (tryInitFromConfig()) { - return localWitnesses; - } - - tryInitFromKeystore(); - - return localWitnesses; - } - - private boolean tryInitFromCommandLine() { - if (StringUtils.isBlank(Args.PARAMETER.privateKey)) { - return false; - } - - byte[] witnessAddress = null; - this.localWitnesses = new LocalWitnesses(Args.PARAMETER.privateKey); - if (StringUtils.isNotEmpty(Args.PARAMETER.witnessAddress)) { - witnessAddress = Commons.decodeFromBase58Check(Args.PARAMETER.witnessAddress); - if (witnessAddress == null) { - throw new TronError("LocalWitnessAccountAddress format from cmd is incorrect", + /** + * Init from a single private key (and optional witness address). + */ + public static LocalWitnesses initFromCLIPrivateKey( + String privateKey, String witnessAddress) { + LocalWitnesses witnesses = new LocalWitnesses(privateKey); + + byte[] address = null; + if (StringUtils.isNotEmpty(witnessAddress)) { + address = Commons.decodeFromBase58Check(witnessAddress); + if (address == null) { + throw new TronError( + "LocalWitnessAccountAddress format from cmd is incorrect", TronError.ErrCode.WITNESS_INIT); } logger.debug("Got localWitnessAccountAddress from cmd"); } - this.localWitnesses.initWitnessAccountAddress(witnessAddress, - Args.PARAMETER.isECKeyCryptoEngine()); + witnesses.initWitnessAccountAddress( + address, Args.getInstance().isECKeyCryptoEngine()); logger.debug("Got privateKey from cmd"); - return true; + return witnesses; } - private boolean tryInitFromConfig() { - if (!config.hasPath(ConfigKey.LOCAL_WITNESS) || config.getStringList(ConfigKey.LOCAL_WITNESS) - .isEmpty()) { - return false; - } - - List localWitness = config.getStringList(ConfigKey.LOCAL_WITNESS); - this.localWitnesses.setPrivateKeys(localWitness); + /** + * Init from a list of private keys. + */ + public static LocalWitnesses initFromCFGPrivateKey( + List privateKeys, String witnessAccountAddress) { + LocalWitnesses witnesses = new LocalWitnesses(); + witnesses.setPrivateKeys(privateKeys); logger.debug("Got privateKey from config.conf"); - byte[] witnessAddress = getWitnessAddress(); - this.localWitnesses.initWitnessAccountAddress(witnessAddress, - Args.PARAMETER.isECKeyCryptoEngine()); - return true; - } - private void tryInitFromKeystore() { - if (!config.hasPath(ConfigKey.LOCAL_WITNESS_KEYSTORE) - || config.getStringList(ConfigKey.LOCAL_WITNESS_KEYSTORE).isEmpty()) { - return; - } + byte[] address = resolveWitnessAddress(witnesses, witnessAccountAddress); + witnesses.initWitnessAccountAddress( + address, Args.getInstance().isECKeyCryptoEngine()); + return witnesses; + } - List localWitness = config.getStringList(ConfigKey.LOCAL_WITNESS_KEYSTORE); - if (localWitness.size() > 1) { - logger.warn( - "Multiple keystores detected. Only the first keystore will be used as witness, all " - + "others will be ignored."); + /** + * Init from keystore files with password. + */ + public static LocalWitnesses initFromKeystore( + List keystoreFiles, String password, + String witnessAccountAddress) { + if (keystoreFiles.size() > 1) { + logger.warn("Multiple keystores detected. Only the first keystore will be used" + + " as witness, all others will be ignored."); } - List privateKeys = new ArrayList<>(); - String fileName = System.getProperty("user.dir") + "/" + localWitness.get(0); - String password; - if (StringUtils.isEmpty(Args.PARAMETER.password)) { + String fileName = System.getProperty("user.dir") + "/" + keystoreFiles.get(0); + String pwd; + if (StringUtils.isEmpty(password)) { System.out.println("Please input your password."); - password = WalletUtils.inputPassword(); + pwd = WalletUtils.inputPassword(); } else { - password = Args.PARAMETER.password; - Args.PARAMETER.password = null; + pwd = password; } + List privateKeys = new ArrayList<>(); try { - Credentials credentials = WalletUtils - .loadCredentials(password, new File(fileName)); + Credentials credentials = WalletUtils.loadCredentials(pwd, new File(fileName)); SignInterface sign = credentials.getSignInterface(); String prikey = ByteArray.toHexString(sign.getPrivateKey()); privateKeys.add(prikey); @@ -118,31 +88,33 @@ private void tryInitFromKeystore() { throw new TronError(e, TronError.ErrCode.WITNESS_KEYSTORE_LOAD); } - this.localWitnesses.setPrivateKeys(privateKeys); - byte[] witnessAddress = getWitnessAddress(); - this.localWitnesses.initWitnessAccountAddress(witnessAddress, - Args.PARAMETER.isECKeyCryptoEngine()); + LocalWitnesses witnesses = new LocalWitnesses(); + witnesses.setPrivateKeys(privateKeys); + byte[] address = resolveWitnessAddress(witnesses, witnessAccountAddress); + witnesses.initWitnessAccountAddress( + address, Args.getInstance().isECKeyCryptoEngine()); logger.debug("Got privateKey from keystore"); + return witnesses; } - private byte[] getWitnessAddress() { - if (!config.hasPath(ConfigKey.LOCAL_WITNESS_ACCOUNT_ADDRESS)) { + static byte[] resolveWitnessAddress( + LocalWitnesses witnesses, String witnessAccountAddress) { + if (StringUtils.isEmpty(witnessAccountAddress)) { return null; } - if (localWitnesses.getPrivateKeys().size() != 1) { + if (witnesses.getPrivateKeys().size() != 1) { throw new TronError( "LocalWitnessAccountAddress can only be set when there is only one private key", TronError.ErrCode.WITNESS_INIT); } - byte[] witnessAddress = Commons - .decodeFromBase58Check(config.getString(ConfigKey.LOCAL_WITNESS_ACCOUNT_ADDRESS)); - if (witnessAddress != null) { + byte[] address = Commons.decodeFromBase58Check(witnessAccountAddress); + if (address != null) { logger.debug("Got localWitnessAccountAddress from config.conf"); } else { throw new TronError("LocalWitnessAccountAddress format from config is incorrect", TronError.ErrCode.WITNESS_INIT); } - return witnessAddress; + return address; } } diff --git a/framework/src/main/java/org/tron/program/FullNode.java b/framework/src/main/java/org/tron/program/FullNode.java index b93a4d79b82..95257d77f8e 100644 --- a/framework/src/main/java/org/tron/program/FullNode.java +++ b/framework/src/main/java/org/tron/program/FullNode.java @@ -5,12 +5,14 @@ import org.tron.common.application.Application; import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; +import org.tron.common.arch.Arch; import org.tron.common.exit.ExitManager; import org.tron.common.log.LogService; import org.tron.common.parameter.CommonParameter; import org.tron.common.prometheus.Metrics; import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; +import org.tron.core.exception.TronError; @Slf4j(topic = "app") public class FullNode { @@ -20,6 +22,7 @@ public class FullNode { */ public static void main(String[] args) { ExitManager.initExceptionHandler(); + checkJdkVersion(); Args.setParam(args, "config.conf"); CommonParameter parameter = Args.getInstance(); @@ -54,4 +57,13 @@ public static void main(String[] args) { appT.startup(); appT.blockUntilShutdown(); } + + private static void checkJdkVersion() { + try { + Arch.throwIfUnsupportedJavaVersion(); + } catch (UnsupportedOperationException e) { + System.err.println(e.getMessage()); + throw new TronError(e, TronError.ErrCode.JDK_VERSION); + } + } } diff --git a/framework/src/test/java/org/tron/common/ParameterTest.java b/framework/src/test/java/org/tron/common/ParameterTest.java index 2f65189ac1c..d5dbced87fe 100644 --- a/framework/src/test/java/org/tron/common/ParameterTest.java +++ b/framework/src/test/java/org/tron/common/ParameterTest.java @@ -63,7 +63,6 @@ public void testCommonParameter() { assertEquals(1000000L, parameter.getMaxEnergyLimitForConstant()); assertEquals(5, parameter.getLruCacheSize()); assertEquals(60, parameter.getLongRunningTime()); - assertFalse(parameter.isHelp()); assertFalse(parameter.isSaveFeaturedInternalTx()); assertFalse(parameter.isSaveInternalTx()); CollectionUtils.isEmpty(parameter.getSeedNodes()); diff --git a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java index 9a7283d18dc..6081021c74f 100644 --- a/framework/src/test/java/org/tron/common/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/common/config/args/ArgsTest.java @@ -13,6 +13,7 @@ import org.tron.common.TestConstants; import org.tron.common.parameter.RateLimiterInitialization; import org.tron.core.config.args.Args; +import org.tron.core.config.args.CLIParameter; public class ArgsTest { @@ -53,7 +54,7 @@ public void testConfig() { @Test public void testHelpMessage() { - JCommander jCommander = JCommander.newBuilder().addObject(Args.PARAMETER).build(); + JCommander jCommander = JCommander.newBuilder().addObject(new CLIParameter()).build(); Method method; try { method = Args.class.getDeclaredMethod("printVersion"); diff --git a/framework/src/test/java/org/tron/core/WalletMockTest.java b/framework/src/test/java/org/tron/core/WalletMockTest.java index ab7ad7ba10c..efcf0da8d0d 100644 --- a/framework/src/test/java/org/tron/core/WalletMockTest.java +++ b/framework/src/test/java/org/tron/core/WalletMockTest.java @@ -87,7 +87,7 @@ public class WalletMockTest { @Before public void init() { - CommonParameter.PARAMETER.setMinEffectiveConnection(0); + CommonParameter.getInstance().setMinEffectiveConnection(0); } @After diff --git a/framework/src/test/java/org/tron/core/config/ConfigurationTest.java b/framework/src/test/java/org/tron/core/config/ConfigurationTest.java index 11ceb88bfcc..b066bc1e6be 100644 --- a/framework/src/test/java/org/tron/core/config/ConfigurationTest.java +++ b/framework/src/test/java/org/tron/core/config/ConfigurationTest.java @@ -58,17 +58,17 @@ public void testGetEcKey() { @Test(expected = IllegalArgumentException.class) public void whenNullPathGetShouldThrowIllegalArgumentException() { - Configuration.getByFileName(null, null); + Configuration.getByFileName(null); } @Test(expected = IllegalArgumentException.class) public void whenEmptyPathGetShouldThrowIllegalArgumentException() { - Configuration.getByFileName(StringUtils.EMPTY, StringUtils.EMPTY); + Configuration.getByFileName(StringUtils.EMPTY); } @Test(expected = IllegalArgumentException.class) public void getShouldNotFindConfiguration() { - Config config = Configuration.getByFileName("notExistingPath", "notExistingPath"); + Config config = Configuration.getByFileName("notExistingPath"); assertFalse(config.hasPath("storage")); assertFalse(config.hasPath("overlay")); assertFalse(config.hasPath("seed.node")); @@ -77,7 +77,7 @@ public void getShouldNotFindConfiguration() { @Test public void getShouldReturnConfiguration() { - Config config = Configuration.getByFileName(TestConstants.TEST_CONF, TestConstants.TEST_CONF); + Config config = Configuration.getByFileName(TestConstants.TEST_CONF); assertTrue(config.hasPath("storage")); assertTrue(config.hasPath("seed.node")); assertTrue(config.hasPath("genesis.block")); @@ -86,7 +86,7 @@ public void getShouldReturnConfiguration() { @Test public void getConfigurationWhenOnlyConfFileName() { URL res = getClass().getClassLoader().getResource(TestConstants.TEST_CONF); - Config config = Configuration.getByFileName("", res.getPath()); + Config config = Configuration.getByFileName(res.getPath()); assertTrue(config.hasPath("storage")); assertTrue(config.hasPath("seed.node")); assertTrue(config.hasPath("genesis.block")); diff --git a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java index bdca1f02af5..a4ce9a5030e 100644 --- a/framework/src/test/java/org/tron/core/config/args/ArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/ArgsTest.java @@ -32,6 +32,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.tron.common.TestConstants; +import org.tron.common.arch.Arch; import org.tron.common.args.GenesisBlock; import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; @@ -71,8 +72,7 @@ public void get() { address = ByteArray.toHexString(Args.getLocalWitnesses() .getWitnessAccountAddress()); Assert.assertEquals("41", DecodeUtil.addressPreFixString); - // configFilePath should be set to shellConfFileName when -c is specified - Assert.assertEquals(TestConstants.TEST_CONF, parameter.getConfigFilePath()); + Assert.assertEquals(TestConstants.TEST_CONF, Args.getConfigFilePath()); Assert.assertEquals(0, parameter.getBackupPriority()); Assert.assertEquals(3000, parameter.getKeepAliveInterval()); @@ -139,13 +139,12 @@ public void testIpFromLibP2p() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Args.setParam(new String[] {}, TestConstants.TEST_CONF); CommonParameter parameter = Args.getInstance(); - // configFilePath should fall back to confFileName when -c is not specified - Assert.assertEquals(TestConstants.TEST_CONF, parameter.getConfigFilePath()); + Assert.assertEquals(TestConstants.TEST_CONF, Args.getConfigFilePath()); String configuredExternalIp = parameter.getNodeExternalIp(); Assert.assertEquals("46.168.1.1", configuredExternalIp); - Config config = Configuration.getByFileName(null, TestConstants.TEST_CONF); + Config config = Configuration.getByFileName(TestConstants.TEST_CONF); Config config3 = config.withoutPath(ConfigKey.NODE_DISCOVERY_EXTERNAL_IP); CommonParameter.getInstance().setNodeExternalIp(null); @@ -170,7 +169,7 @@ public void testInitService() { storage.put("storage.db.directory", "database"); Config config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); // test default value - Args.setParam(config); + Args.applyConfigParams(config); Assert.assertTrue(Args.getInstance().isRpcEnable()); Assert.assertTrue(Args.getInstance().isRpcSolidityEnable()); Assert.assertTrue(Args.getInstance().isRpcPBFTEnable()); @@ -197,7 +196,7 @@ public void testInitService() { storage.put("node.jsonrpc.maxSubTopics", "20"); config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); // test value - Args.setParam(config); + Args.applyConfigParams(config); Assert.assertTrue(Args.getInstance().isRpcEnable()); Assert.assertTrue(Args.getInstance().isRpcSolidityEnable()); Assert.assertTrue(Args.getInstance().isRpcPBFTEnable()); @@ -224,7 +223,7 @@ public void testInitService() { storage.put("node.jsonrpc.maxSubTopics", "1000"); config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); // test value - Args.setParam(config); + Args.applyConfigParams(config); Assert.assertFalse(Args.getInstance().isRpcEnable()); Assert.assertFalse(Args.getInstance().isRpcSolidityEnable()); Assert.assertFalse(Args.getInstance().isRpcPBFTEnable()); @@ -251,7 +250,7 @@ public void testInitService() { storage.put("node.jsonrpc.maxSubTopics", "40"); config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); // test value - Args.setParam(config); + Args.applyConfigParams(config); Assert.assertFalse(Args.getInstance().isRpcEnable()); Assert.assertFalse(Args.getInstance().isRpcSolidityEnable()); Assert.assertTrue(Args.getInstance().isRpcPBFTEnable()); @@ -269,7 +268,7 @@ public void testInitService() { storage.put("node.jsonrpc.maxSubTopics", "0"); config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); // check value - Args.setParam(config); + Args.applyConfigParams(config); Assert.assertEquals(0, Args.getInstance().getJsonRpcMaxBlockRange()); Assert.assertEquals(0, Args.getInstance().getJsonRpcMaxSubTopics()); @@ -278,11 +277,69 @@ public void testInitService() { storage.put("node.jsonrpc.maxSubTopics", "-4"); config = ConfigFactory.defaultOverrides().withFallback(ConfigFactory.parseMap(storage)); // check value - Args.setParam(config); + Args.applyConfigParams(config); Assert.assertEquals(-2, Args.getInstance().getJsonRpcMaxBlockRange()); Assert.assertEquals(-4, Args.getInstance().getJsonRpcMaxSubTopics()); Args.clearParam(); } + + /** + * Verify that CLI storage parameters correctly override config file values. + * + *

config-test.conf defines: db.directory = "database", db.engine = "LEVELDB". + * When CLI passes different values (e.g. --storage-db-directory cli-db-dir), + * the Storage object should reflect the CLI values, not the config file values. + * + *

This ensures the three-layer override chain works: + * Storage defaults -> config file -> CLI arguments. + */ + @Test + public void testCliOverridesStorageConfig() { + Args.setParam(new String[] { + "--storage-db-directory", "cli-db-dir", + "--storage-db-engine", "ROCKSDB", + "--storage-db-synchronous", "true", + "--storage-index-directory", "cli-index-dir", + "--storage-index-switch", "cli-index-switch", + "--storage-transactionHistory-switch", "off", + "--contract-parse-enable", "false" + }, TestConstants.TEST_CONF); + + CommonParameter parameter = Args.getInstance(); + + Assert.assertEquals("cli-db-dir", parameter.getStorage().getDbDirectory()); + Assert.assertEquals("ROCKSDB", parameter.getStorage().getDbEngine()); + Assert.assertTrue(parameter.getStorage().isDbSync()); + Assert.assertEquals("cli-index-dir", parameter.getStorage().getIndexDirectory()); + Assert.assertEquals("cli-index-switch", parameter.getStorage().getIndexSwitch()); + Assert.assertEquals("off", parameter.getStorage().getTransactionHistorySwitch()); + Assert.assertFalse(parameter.getStorage().isContractParseSwitch()); + + Args.clearParam(); + } + + /** + * Verify that config file storage values are applied when no CLI override is present. + * + *

config-test.conf defines: db.directory = "database", db.engine = "LEVELDB". + * Without any CLI storage arguments, the Storage object should use these config values. + * On ARM64, the silent override in Storage.getDbEngineFromConfig() forces ROCKSDB. + */ + @Test + public void testConfigStorageDefaults() { + Args.setParam(new String[] {}, TestConstants.TEST_CONF); + + CommonParameter parameter = Args.getInstance(); + + Assert.assertEquals("database", parameter.getStorage().getDbDirectory()); + if (Arch.isArm64()) { + Assert.assertEquals("ROCKSDB", parameter.getStorage().getDbEngine()); + } else { + Assert.assertEquals("LEVELDB", parameter.getStorage().getDbEngine()); + } + + Args.clearParam(); + } } diff --git a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java index 43fa59a17a0..99469f9ce59 100644 --- a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java @@ -40,13 +40,11 @@ public void destroy() { @Test public void start() { CommonParameter parameter = Args.getInstance(); - // configFilePath should be resolved from confFileName at startup - Assert.assertEquals(TestConstants.TEST_CONF, parameter.getConfigFilePath()); + Assert.assertEquals(TestConstants.TEST_CONF, Args.getConfigFilePath()); Assert.assertTrue(parameter.isDynamicConfigEnable()); Assert.assertEquals(600, parameter.getDynamicConfigCheckInterval()); dynamicArgs.init(); - // configFile should be initialized from configFilePath during init() File configFile = (File) ReflectUtils.getFieldObject(dynamicArgs, "configFile"); Assert.assertNotNull(configFile); Assert.assertEquals(TestConstants.TEST_CONF, configFile.getName()); @@ -54,7 +52,7 @@ public void start() { TronNetService tronNetService = context.getBean(TronNetService.class); ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); - File config = new File(parameter.getConfigFilePath()); + File config = new File(Args.getConfigFilePath()); if (!config.exists()) { try { config.createNewFile(); diff --git a/framework/src/test/java/org/tron/core/config/args/WitnessInitializerTest.java b/framework/src/test/java/org/tron/core/config/args/WitnessInitializerTest.java index b38286ca84d..3ecef5b10c9 100644 --- a/framework/src/test/java/org/tron/core/config/args/WitnessInitializerTest.java +++ b/framework/src/test/java/org/tron/core/config/args/WitnessInitializerTest.java @@ -5,31 +5,22 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.typesafe.config.Config; -import com.typesafe.config.ConfigFactory; import java.io.File; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.bouncycastle.util.encoders.Hex; import org.junit.After; -import org.junit.Before; import org.junit.Test; import org.mockito.MockedStatic; import org.tron.common.crypto.SignInterface; -import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.ByteArray; import org.tron.common.utils.LocalWitnesses; import org.tron.common.utils.PublicMethod; @@ -41,227 +32,121 @@ public class WitnessInitializerTest { - private Config config; - private WitnessInitializer witnessInitializer; - private static final String privateKey = PublicMethod.getRandomPrivateKey(); private static final String address = Base58.encode58Check( ByteArray.fromHexString(PublicMethod.getHexAddressByPrivateKey(privateKey))); private static final String invalidAddress = "RJCzdnv88Hvqa2jB1C9dMmMYHr5DFdF2R3"; - @Before - public void setUp() { - config = ConfigFactory.empty(); - witnessInitializer = new WitnessInitializer(config); - } - @After public void clear() { Args.clearParam(); } @Test - public void testInitLocalWitnessesEmpty() { - Args.PARAMETER.setWitness(false); - - LocalWitnesses result = witnessInitializer.initLocalWitnesses(); + public void testInitFromCLI() { + // privateKey only + LocalWitnesses result = + WitnessInitializer.initFromCLIPrivateKey(privateKey, null); assertNotNull(result); - assertTrue(result.getPrivateKeys().isEmpty()); - - Args.PARAMETER.setWitness(true); - LocalWitnesses localWitnesses = witnessInitializer.initLocalWitnesses(); - assertTrue(localWitnesses.getPrivateKeys().isEmpty()); - - String configString = "localwitness = [] \n localwitnesskeystore = []"; - config = ConfigFactory.parseString(configString); - witnessInitializer = new WitnessInitializer(config); - localWitnesses = witnessInitializer.initLocalWitnesses(); - assertTrue(localWitnesses.getPrivateKeys().isEmpty()); - } - - @Test - public void testTryInitFromCommandLine() - throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, - InvocationTargetException { - Field privateKeyField = CommonParameter.class.getDeclaredField("privateKey"); - privateKeyField.setAccessible(true); - privateKeyField.set(Args.getInstance(), ""); - - witnessInitializer = new WitnessInitializer(config); - Method method = WitnessInitializer.class.getDeclaredMethod( - "tryInitFromCommandLine"); - method.setAccessible(true); - boolean result = (boolean) method.invoke(witnessInitializer); - assertFalse(result); - - privateKeyField.set(Args.getInstance(), privateKey); - method.invoke(witnessInitializer); - result = (boolean) method.invoke(witnessInitializer); - assertTrue(result); - - Field witnessAddress = CommonParameter.class.getDeclaredField("witnessAddress"); - witnessAddress.setAccessible(true); - witnessAddress.set(Args.getInstance(), address); - result = (boolean) method.invoke(witnessInitializer); - assertTrue(result); - - witnessAddress.set(Args.getInstance(), invalidAddress); - InvocationTargetException thrown = assertThrows(InvocationTargetException.class, - () -> method.invoke(witnessInitializer)); - TronError targetException = (TronError) thrown.getTargetException(); - assertEquals(ErrCode.WITNESS_INIT, targetException.getErrCode()); - } + assertFalse(result.getPrivateKeys().isEmpty()); + assertEquals(privateKey, result.getPrivateKeys().get(0)); - @Test - public void testTryInitFromConfig() - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - witnessInitializer = new WitnessInitializer(config); - Method method = WitnessInitializer.class.getDeclaredMethod( - "tryInitFromConfig"); - method.setAccessible(true); - boolean result = (boolean) method.invoke(witnessInitializer); - assertFalse(result); - - String configString = "localwitness = []"; - config = ConfigFactory.parseString(configString); - witnessInitializer = new WitnessInitializer(config); - result = (boolean) method.invoke(witnessInitializer); - assertFalse(result); - - configString = "localwitness = [" + privateKey + "]"; - config = ConfigFactory.parseString(configString); - witnessInitializer = new WitnessInitializer(config); - result = (boolean) method.invoke(witnessInitializer); - assertTrue(result); - - configString = "localWitnessAccountAddress = " + address + "\n" - + "localwitness = [\n" + privateKey + "]"; - config = ConfigFactory.parseString(configString); - witnessInitializer = new WitnessInitializer(config); - result = (boolean) method.invoke(witnessInitializer); - assertTrue(result); - - configString = "localwitness = [\n" + privateKey + "\n" + privateKey + "]"; - config = ConfigFactory.parseString(configString); - witnessInitializer = new WitnessInitializer(config); - result = (boolean) method.invoke(witnessInitializer); - assertTrue(result); - - configString = "localWitnessAccountAddress = " + invalidAddress + "\n" - + "localwitness = [\n" + privateKey + "]"; - config = ConfigFactory.parseString(configString); - witnessInitializer = new WitnessInitializer(config); - InvocationTargetException thrown = assertThrows(InvocationTargetException.class, - () -> method.invoke(witnessInitializer)); - TronError targetException = (TronError) thrown.getTargetException(); - assertEquals(ErrCode.WITNESS_INIT, targetException.getErrCode()); + // with valid witnessAddress + result = WitnessInitializer.initFromCLIPrivateKey(privateKey, address); + assertNotNull(result); + assertFalse(result.getPrivateKeys().isEmpty()); - configString = "localWitnessAccountAddress = " + address + "\n" - + "localwitness = [\n" + privateKey + "\n" + privateKey + "]"; - config = ConfigFactory.parseString(configString); - witnessInitializer = new WitnessInitializer(config); - thrown = assertThrows(InvocationTargetException.class, - () -> method.invoke(witnessInitializer)); - targetException = (TronError) thrown.getTargetException(); - assertEquals(ErrCode.WITNESS_INIT, targetException.getErrCode()); + // with invalid witnessAddress + TronError err = assertThrows(TronError.class, + () -> WitnessInitializer.initFromCLIPrivateKey( + privateKey, invalidAddress)); + assertEquals(ErrCode.WITNESS_INIT, err.getErrCode()); } @Test - public void testTryInitFromKeystore() - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, - NoSuchFieldException { - witnessInitializer = new WitnessInitializer(config); - Method method = WitnessInitializer.class.getDeclaredMethod( - "tryInitFromKeystore"); - method.setAccessible(true); - method.invoke(witnessInitializer); - Field localWitnessField = WitnessInitializer.class.getDeclaredField("localWitnesses"); - localWitnessField.setAccessible(true); - LocalWitnesses localWitnesses = (LocalWitnesses) localWitnessField.get(witnessInitializer); - assertTrue(localWitnesses.getPrivateKeys().isEmpty()); - - String configString = "localwitnesskeystore = []"; - Config emptyListConfig = ConfigFactory.parseString(configString); - witnessInitializer = new WitnessInitializer(emptyListConfig); - method.invoke(witnessInitializer); - localWitnesses = (LocalWitnesses) localWitnessField.get(witnessInitializer); - assertTrue(localWitnesses.getPrivateKeys().isEmpty()); + public void testInitFromConfig() { + // single private key, no address + LocalWitnesses result = WitnessInitializer.initFromCFGPrivateKey( + Collections.singletonList(privateKey), null); + assertFalse(result.getPrivateKeys().isEmpty()); + + // single key + valid address + result = WitnessInitializer.initFromCFGPrivateKey( + Collections.singletonList(privateKey), address); + assertFalse(result.getPrivateKeys().isEmpty()); + + // multiple keys, no address + result = WitnessInitializer.initFromCFGPrivateKey( + Arrays.asList(privateKey, privateKey), null); + assertFalse(result.getPrivateKeys().isEmpty()); + + // single key + invalid address + TronError err = assertThrows(TronError.class, + () -> WitnessInitializer.initFromCFGPrivateKey( + Collections.singletonList(privateKey), invalidAddress)); + assertEquals(ErrCode.WITNESS_INIT, err.getErrCode()); + + // multiple keys + address = error + err = assertThrows(TronError.class, + () -> WitnessInitializer.initFromCFGPrivateKey( + Arrays.asList(privateKey, privateKey), address)); + assertEquals(ErrCode.WITNESS_INIT, err.getErrCode()); } @Test - public void testTryInitFromKeyStore2() - throws NoSuchFieldException, IllegalAccessException { - Args.PARAMETER.setWitness(true); - Config mockConfig = mock(Config.class); - when(mockConfig.hasPath(ConfigKey.LOCAL_WITNESS_KEYSTORE)).thenReturn(false); - witnessInitializer = new WitnessInitializer(mockConfig); - witnessInitializer.initLocalWitnesses(); - verify(mockConfig, never()).getStringList(anyString()); - - when(mockConfig.hasPath(ConfigKey.LOCAL_WITNESS_KEYSTORE)).thenReturn(true); - when(mockConfig.getStringList(ConfigKey.LOCAL_WITNESS_KEYSTORE)).thenReturn(new ArrayList<>()); - witnessInitializer = new WitnessInitializer(mockConfig); - witnessInitializer.initLocalWitnesses(); - verify(mockConfig, times(1)).getStringList(ConfigKey.LOCAL_WITNESS_KEYSTORE); - - List keystores = new ArrayList<>(); - keystores.add("keystore1.json"); - keystores.add("keystore2.json"); - when(mockConfig.hasPath(ConfigKey.LOCAL_WITNESS_KEYSTORE)).thenReturn(true); - when(mockConfig.getStringList(ConfigKey.LOCAL_WITNESS_KEYSTORE)).thenReturn(keystores); + public void testInitFromKeystore() { + List keystores = Arrays.asList("keystore1.json", "keystore2.json"); - Field password = CommonParameter.class.getDeclaredField("password"); - password.setAccessible(true); - password.set(Args.getInstance(), "password"); + try (MockedStatic mockedWallet = mockStatic(WalletUtils.class); + MockedStatic mockedByteArray = mockStatic(ByteArray.class)) { - try (MockedStatic mockedWalletUtils = mockStatic(WalletUtils.class); - MockedStatic mockedByteArray = mockStatic(ByteArray.class)) { - // Mock WalletUtils.loadCredentials Credentials credentials = mock(Credentials.class); SignInterface signInterface = mock(SignInterface.class); when(credentials.getSignInterface()).thenReturn(signInterface); byte[] keyBytes = Hex.decode(privateKey); when(signInterface.getPrivateKey()).thenReturn(keyBytes); - mockedWalletUtils.when(() -> WalletUtils.loadCredentials(anyString(), any(File.class))) - .thenReturn(credentials); - mockedByteArray.when(() -> ByteArray.toHexString(any())).thenReturn(privateKey); - mockedByteArray.when(() -> ByteArray.fromHexString(anyString())).thenReturn(keyBytes); - - witnessInitializer = new WitnessInitializer(mockConfig); - Field localWitnessField = WitnessInitializer.class.getDeclaredField("localWitnesses"); - localWitnessField.setAccessible(true); - localWitnessField.set(witnessInitializer, new LocalWitnesses(privateKey)); - LocalWitnesses localWitnesses = witnessInitializer.initLocalWitnesses(); - assertFalse(localWitnesses.getPrivateKeys().isEmpty()); + mockedWallet.when(() -> WalletUtils.loadCredentials( + anyString(), any(File.class))).thenReturn(credentials); + mockedByteArray.when(() -> ByteArray.toHexString(any())) + .thenReturn(privateKey); + mockedByteArray.when(() -> ByteArray.fromHexString(anyString())) + .thenReturn(keyBytes); + + LocalWitnesses result = WitnessInitializer.initFromKeystore( + keystores, "password", null); + assertFalse(result.getPrivateKeys().isEmpty()); } } @Test - public void testGetWitnessAddress() - throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, - NoSuchFieldException { - witnessInitializer = new WitnessInitializer(config); - Method method = WitnessInitializer.class.getDeclaredMethod( - "getWitnessAddress"); - method.setAccessible(true); - byte[] result = (byte[]) method.invoke(witnessInitializer); + public void testResolveWitnessAddress() { + // null address -> null + LocalWitnesses witnesses = new LocalWitnesses(privateKey); + byte[] result = WitnessInitializer.resolveWitnessAddress(witnesses, null); + assertNull(result); + + // empty address -> null + result = WitnessInitializer.resolveWitnessAddress(witnesses, ""); assertNull(result); - String configString = "localWitnessAccountAddress = " + address; - config = ConfigFactory.parseString(configString); - witnessInitializer = new WitnessInitializer(config); - Field localWitnessField = WitnessInitializer.class.getDeclaredField("localWitnesses"); - localWitnessField.setAccessible(true); - localWitnessField.set(witnessInitializer, new LocalWitnesses(privateKey)); - result = (byte[]) method.invoke(witnessInitializer); + // valid address with single key + result = WitnessInitializer.resolveWitnessAddress(witnesses, address); assertNotNull(result); - configString = "localWitnessAccountAddress = " + invalidAddress; - config = ConfigFactory.parseString(configString); - witnessInitializer = new WitnessInitializer(config); - InvocationTargetException thrown = assertThrows(InvocationTargetException.class, - () -> method.invoke(witnessInitializer)); - TronError targetException = (TronError) thrown.getTargetException(); - assertEquals(ErrCode.WITNESS_INIT, targetException.getErrCode()); + // invalid address + TronError err = assertThrows(TronError.class, + () -> WitnessInitializer.resolveWitnessAddress( + new LocalWitnesses(privateKey), invalidAddress)); + assertEquals(ErrCode.WITNESS_INIT, err.getErrCode()); + + // multiple keys + address = error + LocalWitnesses multiKey = new LocalWitnesses(); + List keys = new ArrayList<>(); + keys.add(privateKey); + keys.add(privateKey); + multiKey.setPrivateKeys(keys); + err = assertThrows(TronError.class, + () -> WitnessInitializer.resolveWitnessAddress(multiKey, address)); + assertEquals(ErrCode.WITNESS_INIT, err.getErrCode()); } } diff --git a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java index e4b6b190b0b..8e1b295a4ca 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java @@ -45,7 +45,7 @@ public class TransactionExpireTest { public void init() throws IOException { Args.setParam(new String[] {"--output-directory", temporaryFolder.newFolder().toString()}, TestConstants.TEST_CONF); - CommonParameter.PARAMETER.setMinEffectiveConnection(0); + CommonParameter.getInstance().setMinEffectiveConnection(0); CommonParameter.getInstance().setP2pDisable(true); context = new TronApplicationContext(DefaultConfig.class); diff --git a/framework/src/test/java/org/tron/core/exception/TronErrorTest.java b/framework/src/test/java/org/tron/core/exception/TronErrorTest.java index 3b238f50edc..e965ae3fd60 100644 --- a/framework/src/test/java/org/tron/core/exception/TronErrorTest.java +++ b/framework/src/test/java/org/tron/core/exception/TronErrorTest.java @@ -141,7 +141,7 @@ public void shutdownBlockTimeInitTest() { params.put("storage.db.directory", "database"); Config config = ConfigFactory.defaultOverrides().withFallback( ConfigFactory.parseMap(params)); - TronError thrown = assertThrows(TronError.class, () -> Args.setParam(config)); + TronError thrown = assertThrows(TronError.class, () -> Args.applyConfigParams(config)); assertEquals(TronError.ErrCode.AUTO_STOP_PARAMS, thrown.getErrCode()); } @@ -177,15 +177,16 @@ private void runArchTest(String osArch, String javaVersion, boolean expectThrow) mocked.when(Arch::throwIfUnsupportedJavaVersion).thenCallRealMethod(); if (expectThrow) { - TronError err = assertThrows( - TronError.class, () -> Args.setParam(new String[]{}, TestConstants.TEST_CONF)); + UnsupportedOperationException err = assertThrows( + UnsupportedOperationException.class, + Arch::throwIfUnsupportedJavaVersion); String expectedJavaVersion = isX86 ? "1.8" : "17"; String expectedMessage = String.format( - "Java %s is required for %s architecture. Detected version %s", + "Java %s is required for %s architecture." + + " Detected version %s", expectedJavaVersion, osArch, javaVersion); - assertEquals(expectedMessage, err.getCause().getMessage()); - assertEquals(TronError.ErrCode.JDK_VERSION, err.getErrCode()); + assertEquals(expectedMessage, err.getMessage()); mocked.verify(Arch::withAll, times(1)); } else { try { diff --git a/framework/src/test/java/org/tron/core/net/NodeTest.java b/framework/src/test/java/org/tron/core/net/NodeTest.java index 69bb8aae312..cbf545af646 100644 --- a/framework/src/test/java/org/tron/core/net/NodeTest.java +++ b/framework/src/test/java/org/tron/core/net/NodeTest.java @@ -79,7 +79,7 @@ public void testEndpointFromNode() { @Test public void testPublishConfig() { - Config config = Configuration.getByFileName(TestConstants.TEST_CONF, TestConstants.TEST_CONF); + Config config = Configuration.getByFileName(TestConstants.TEST_CONF); PublishConfig publishConfig = new PublishConfig(); Assert.assertFalse(publishConfig.isDnsPublishEnable());