Skip to content

Commit dd349f3

Browse files
committed
refactor(config): replace manual parsing with ConfigBeanFactory binding
Replace ~850 lines of manual if/hasPath/getXxx blocks in Args.applyConfigParams() with ConfigBeanFactory.create() automatic binding. Each config.conf domain now maps to a typed Java bean class (VmConfig, BlockConfig, CommitteeConfig, MetricsConfig, NodeConfig, EventConfig, StorageConfig, etc.). - Delete ConfigKey.java (~100 string constants), config.conf is sole source of truth - Migrate Storage.java static getters to read from StorageConfig bean - Add unit tests for all config bean classes - Migrate DynamicArgs to use bean binding
1 parent bb8b4be commit dd349f3

28 files changed

Lines changed: 2947 additions & 1635 deletions

common/src/main/java/org/tron/common/parameter/RateLimiterInitialization.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ public HttpRateLimiterItem(ConfigObject asset) {
7474
strategy = asset.get("strategy").unwrapped().toString();
7575
params = asset.get("paramString").unwrapped().toString();
7676
}
77+
78+
public HttpRateLimiterItem(String component, String strategy, String params) {
79+
this.component = component;
80+
this.strategy = strategy;
81+
this.params = params;
82+
}
7783
}
7884

7985

@@ -93,5 +99,11 @@ public RpcRateLimiterItem(ConfigObject asset) {
9399
strategy = asset.get("strategy").unwrapped().toString();
94100
params = asset.get("paramString").unwrapped().toString();
95101
}
102+
103+
public RpcRateLimiterItem(String component, String strategy, String params) {
104+
this.component = component;
105+
this.strategy = strategy;
106+
this.params = params;
107+
}
96108
}
97109
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.tron.core.config.args;
2+
3+
import static org.tron.core.Constant.DEFAULT_PROPOSAL_EXPIRE_TIME;
4+
import static org.tron.core.Constant.MAX_PROPOSAL_EXPIRE_TIME;
5+
import static org.tron.core.Constant.MIN_PROPOSAL_EXPIRE_TIME;
6+
import static org.tron.core.exception.TronError.ErrCode.PARAMETER_INIT;
7+
8+
import com.typesafe.config.Config;
9+
import com.typesafe.config.ConfigBeanFactory;
10+
import com.typesafe.config.ConfigFactory;
11+
import lombok.Getter;
12+
import lombok.Setter;
13+
import lombok.extern.slf4j.Slf4j;
14+
import org.tron.core.exception.TronError;
15+
16+
/**
17+
* Block configuration bean. Field names match config.conf keys under the "block" section.
18+
*/
19+
@Slf4j
20+
@Getter
21+
@Setter
22+
public class BlockConfig {
23+
24+
private boolean needSyncCheck = false;
25+
private long maintenanceTimeInterval = 21600000L;
26+
private long proposalExpireTime = DEFAULT_PROPOSAL_EXPIRE_TIME;
27+
private int checkFrozenTime = 1;
28+
29+
private static final Config DEFAULTS = ConfigFactory.parseString(
30+
"needSyncCheck = false\n"
31+
+ "maintenanceTimeInterval = 21600000\n"
32+
+ "proposalExpireTime = " + DEFAULT_PROPOSAL_EXPIRE_TIME + "\n"
33+
+ "checkFrozenTime = 1\n"
34+
);
35+
36+
/**
37+
* Create BlockConfig from the "block" section of the application config.
38+
* Also checks that committee.proposalExpireTime is not used (must use block.proposalExpireTime).
39+
*/
40+
public static BlockConfig fromConfig(Config config) {
41+
// Reject legacy committee.proposalExpireTime location
42+
if (config.hasPath("committee.proposalExpireTime")) {
43+
throw new TronError("It is not allowed to configure committee.proposalExpireTime in "
44+
+ "config.conf, please set the value in block.proposalExpireTime.", PARAMETER_INIT);
45+
}
46+
47+
Config blockSection = config.hasPath("block")
48+
? config.getConfig("block").withFallback(DEFAULTS)
49+
: DEFAULTS;
50+
BlockConfig blockConfig = ConfigBeanFactory.create(blockSection, BlockConfig.class);
51+
blockConfig.postProcess();
52+
return blockConfig;
53+
}
54+
55+
private void postProcess() {
56+
if (proposalExpireTime <= MIN_PROPOSAL_EXPIRE_TIME
57+
|| proposalExpireTime >= MAX_PROPOSAL_EXPIRE_TIME) {
58+
throw new TronError("The value[block.proposalExpireTime] is only allowed to "
59+
+ "be greater than " + MIN_PROPOSAL_EXPIRE_TIME + " and less than "
60+
+ MAX_PROPOSAL_EXPIRE_TIME + "!", PARAMETER_INIT);
61+
}
62+
}
63+
}
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
package org.tron.core.config.args;
2+
3+
import com.typesafe.config.Config;
4+
import com.typesafe.config.ConfigBeanFactory;
5+
import com.typesafe.config.ConfigFactory;
6+
import lombok.Getter;
7+
import lombok.Setter;
8+
import lombok.extern.slf4j.Slf4j;
9+
10+
/**
11+
* Committee (governance) configuration bean.
12+
* Field names match config.conf keys under the "committee" section.
13+
* All fields are governance proposal toggles, default 0 (disabled).
14+
*/
15+
@Slf4j
16+
@Getter
17+
@Setter
18+
@SuppressWarnings("unused") // setters used by ConfigBeanFactory via reflection
19+
public class CommitteeConfig {
20+
21+
private long allowCreationOfContracts = 0;
22+
private long allowMultiSign = 0;
23+
private long allowAdaptiveEnergy = 0;
24+
private long allowDelegateResource = 0;
25+
private long allowSameTokenName = 0;
26+
private long allowTvmTransferTrc10 = 0;
27+
private long allowTvmConstantinople = 0;
28+
private long allowTvmSolidity059 = 0;
29+
private long forbidTransferToContract = 0;
30+
private long allowShieldedTRC20Transaction = 0;
31+
private long allowMarketTransaction = 0;
32+
private long allowTransactionFeePool = 0;
33+
private long allowBlackHoleOptimization = 0;
34+
private long allowNewResourceModel = 0;
35+
private long allowTvmIstanbul = 0;
36+
private long allowProtoFilterNum = 0;
37+
private long allowAccountStateRoot = 0;
38+
private long changedDelegation = 0;
39+
// NON-STANDARD NAMING: "allowPBFT" and "pBFTExpireNum" in config.conf contain
40+
// consecutive uppercase letters ("PBFT"), which violates JavaBean naming convention.
41+
// ConfigBeanFactory derives config keys from setter names using JavaBean rules:
42+
// setPBFTExpireNum -> property "PBFTExpireNum" (capital P, per JavaBean spec)
43+
// but config.conf uses "pBFTExpireNum" (lowercase p) -> mismatch -> binding fails.
44+
//
45+
// These two fields are excluded from auto-binding and handled manually in fromConfig().
46+
// TODO: Rename config keys to standard camelCase (allowPbft, pbftExpireNum) when
47+
// PBFT feature is enabled and a breaking config change is acceptable.
48+
@Getter(lombok.AccessLevel.NONE)
49+
@Setter(lombok.AccessLevel.NONE)
50+
private long allowPBFT = 0;
51+
@Getter(lombok.AccessLevel.NONE)
52+
@Setter(lombok.AccessLevel.NONE)
53+
private long pBFTExpireNum = 20;
54+
55+
public long getAllowPBFT() { return allowPBFT; }
56+
public void setAllowPBFT(long v) { this.allowPBFT = v; }
57+
public long getPBFTExpireNum() { return pBFTExpireNum; }
58+
public void setPBFTExpireNum(long v) { this.pBFTExpireNum = v; }
59+
private long allowTvmFreeze = 0;
60+
private long allowTvmVote = 0;
61+
private long allowTvmLondon = 0;
62+
private long allowTvmCompatibleEvm = 0;
63+
private long allowHigherLimitForMaxCpuTimeOfOneTx = 0;
64+
private long allowNewRewardAlgorithm = 0;
65+
private long allowOptimizedReturnValueOfChainId = 0;
66+
private long allowTvmShangHai = 0;
67+
private long allowOldRewardOpt = 0;
68+
private long allowEnergyAdjustment = 0;
69+
private long allowStrictMath = 0;
70+
private long consensusLogicOptimization = 0;
71+
private long allowTvmCancun = 0;
72+
private long allowTvmBlob = 0;
73+
private long unfreezeDelayDays = 0;
74+
private long allowReceiptsMerkleRoot = 0;
75+
private long allowAccountAssetOptimization = 0;
76+
private long allowAssetOptimization = 0;
77+
private long allowNewReward = 0;
78+
private long memoFee = 0;
79+
private long allowDelegateOptimization = 0;
80+
private long allowDynamicEnergy = 0;
81+
private long dynamicEnergyThreshold = 0;
82+
private long dynamicEnergyIncreaseFactor = 0;
83+
private long dynamicEnergyMaxFactor = 0;
84+
85+
// proposalExpireTime is NOT a committee field — it's in block.* and handled by BlockConfig
86+
87+
private static final Config DEFAULTS;
88+
89+
static {
90+
StringBuilder sb = new StringBuilder();
91+
sb.append("allowCreationOfContracts = 0\n");
92+
sb.append("allowMultiSign = 0\n");
93+
sb.append("allowAdaptiveEnergy = 0\n");
94+
sb.append("allowDelegateResource = 0\n");
95+
sb.append("allowSameTokenName = 0\n");
96+
sb.append("allowTvmTransferTrc10 = 0\n");
97+
sb.append("allowTvmConstantinople = 0\n");
98+
sb.append("allowTvmSolidity059 = 0\n");
99+
sb.append("forbidTransferToContract = 0\n");
100+
sb.append("allowShieldedTRC20Transaction = 0\n");
101+
sb.append("allowMarketTransaction = 0\n");
102+
sb.append("allowTransactionFeePool = 0\n");
103+
sb.append("allowBlackHoleOptimization = 0\n");
104+
sb.append("allowNewResourceModel = 0\n");
105+
sb.append("allowTvmIstanbul = 0\n");
106+
sb.append("allowProtoFilterNum = 0\n");
107+
sb.append("allowAccountStateRoot = 0\n");
108+
sb.append("changedDelegation = 0\n");
109+
sb.append("allowPBFT = 0\n");
110+
sb.append("pBFTExpireNum = 20\n");
111+
sb.append("allowTvmFreeze = 0\n");
112+
sb.append("allowTvmVote = 0\n");
113+
sb.append("allowTvmLondon = 0\n");
114+
sb.append("allowTvmCompatibleEvm = 0\n");
115+
sb.append("allowHigherLimitForMaxCpuTimeOfOneTx = 0\n");
116+
sb.append("allowNewRewardAlgorithm = 0\n");
117+
sb.append("allowOptimizedReturnValueOfChainId = 0\n");
118+
sb.append("allowTvmShangHai = 0\n");
119+
sb.append("allowOldRewardOpt = 0\n");
120+
sb.append("allowEnergyAdjustment = 0\n");
121+
sb.append("allowStrictMath = 0\n");
122+
sb.append("consensusLogicOptimization = 0\n");
123+
sb.append("allowTvmCancun = 0\n");
124+
sb.append("allowTvmBlob = 0\n");
125+
sb.append("unfreezeDelayDays = 0\n");
126+
sb.append("allowReceiptsMerkleRoot = 0\n");
127+
sb.append("allowAccountAssetOptimization = 0\n");
128+
sb.append("allowAssetOptimization = 0\n");
129+
sb.append("allowNewReward = 0\n");
130+
sb.append("memoFee = 0\n");
131+
sb.append("allowDelegateOptimization = 0\n");
132+
sb.append("allowDynamicEnergy = 0\n");
133+
sb.append("dynamicEnergyThreshold = 0\n");
134+
sb.append("dynamicEnergyIncreaseFactor = 0\n");
135+
sb.append("dynamicEnergyMaxFactor = 0\n");
136+
DEFAULTS = ConfigFactory.parseString(sb.toString());
137+
}
138+
139+
/**
140+
* Create CommitteeConfig from the "committee" section of the application config.
141+
*
142+
* Note: allowPBFT and pBFTExpireNum have non-standard JavaBean naming (consecutive
143+
* uppercase letters) which causes ConfigBeanFactory key mismatch. These two fields
144+
* are excluded from automatic binding and handled manually after.
145+
*/
146+
public static CommitteeConfig fromConfig(Config config) {
147+
Config section = config.hasPath("committee")
148+
? config.getConfig("committee").withFallback(DEFAULTS)
149+
: DEFAULTS;
150+
151+
// ConfigBeanFactory derives key names from setter methods. For setPBFTExpireNum()
152+
// it expects "PBFTExpireNum" (capital P), but config.conf uses "pBFTExpireNum".
153+
// Similarly, getAllowPBFT() maps to "allowPBFT" which may be missing in test configs.
154+
// Add uppercase aliases so ConfigBeanFactory can find them.
155+
Config aliased = section;
156+
if (section.hasPath("pBFTExpireNum") && !section.hasPath("PBFTExpireNum")) {
157+
aliased = aliased.withValue("PBFTExpireNum", section.getValue("pBFTExpireNum"));
158+
}
159+
160+
CommitteeConfig cc = ConfigBeanFactory.create(aliased, CommitteeConfig.class);
161+
// Ensure the manually-named fields get the right values from the original keys
162+
cc.allowPBFT = section.hasPath("allowPBFT") ? section.getLong("allowPBFT") : 0;
163+
cc.pBFTExpireNum = section.hasPath("pBFTExpireNum") ? section.getLong("pBFTExpireNum") : 20;
164+
165+
cc.postProcess();
166+
return cc;
167+
}
168+
169+
private void postProcess() {
170+
// clamp unfreezeDelayDays to 0-365
171+
if (unfreezeDelayDays < 0) {
172+
unfreezeDelayDays = 0;
173+
}
174+
if (unfreezeDelayDays > 365) {
175+
unfreezeDelayDays = 365;
176+
}
177+
178+
// clamp allowDelegateOptimization to 0-1
179+
if (allowDelegateOptimization < 0) { allowDelegateOptimization = 0; }
180+
if (allowDelegateOptimization > 1) { allowDelegateOptimization = 1; }
181+
182+
// clamp allowDynamicEnergy to 0-1
183+
if (allowDynamicEnergy < 0) { allowDynamicEnergy = 0; }
184+
if (allowDynamicEnergy > 1) { allowDynamicEnergy = 1; }
185+
186+
// clamp dynamicEnergyThreshold to 0-100_000_000_000_000_000
187+
if (dynamicEnergyThreshold < 0) { dynamicEnergyThreshold = 0; }
188+
if (dynamicEnergyThreshold > 100_000_000_000_000_000L) {
189+
dynamicEnergyThreshold = 100_000_000_000_000_000L;
190+
}
191+
192+
// clamp dynamicEnergyIncreaseFactor to 0-10_000
193+
if (dynamicEnergyIncreaseFactor < 0) { dynamicEnergyIncreaseFactor = 0; }
194+
if (dynamicEnergyIncreaseFactor > 10_000L) { dynamicEnergyIncreaseFactor = 10_000L; }
195+
196+
// clamp dynamicEnergyMaxFactor to 0-100_000
197+
if (dynamicEnergyMaxFactor < 0) { dynamicEnergyMaxFactor = 0; }
198+
if (dynamicEnergyMaxFactor > 100_000L) { dynamicEnergyMaxFactor = 100_000L; }
199+
200+
// cross-field: allowOldRewardOpt requires at least one reward/vote flag
201+
if (allowOldRewardOpt == 1 && allowNewRewardAlgorithm != 1
202+
&& allowNewReward != 1 && allowTvmVote != 1) {
203+
throw new IllegalArgumentException(
204+
"At least one of the following proposals is required to be opened first: "
205+
+ "committee.allowNewRewardAlgorithm = 1"
206+
+ " or committee.allowNewReward = 1"
207+
+ " or committee.allowTvmVote = 1.");
208+
}
209+
}
210+
}

0 commit comments

Comments
 (0)