22
33import com .typesafe .config .Config ;
44import com .typesafe .config .ConfigBeanFactory ;
5+ import com .typesafe .config .ConfigValue ;
56import lombok .Getter ;
67import lombok .Setter ;
78import lombok .extern .slf4j .Slf4j ;
@@ -35,29 +36,10 @@ public class CommitteeConfig {
3536 private long allowProtoFilterNum = 0 ;
3637 private long allowAccountStateRoot = 0 ;
3738 private long changedDelegation = 0 ;
38- // NON-STANDARD NAMING: "allowPBFT" and "pBFTExpireNum" in config.conf contain
39- // consecutive uppercase letters ("PBFT"), which violates JavaBean naming convention.
40- // ConfigBeanFactory derives config keys from setter names using JavaBean rules:
41- // setPBFTExpireNum -> property "PBFTExpireNum" (capital P, per JavaBean spec)
42- // but config.conf uses "pBFTExpireNum" (lowercase p) -> mismatch -> binding fails.
43- //
44- // These two fields are excluded from auto-binding and handled manually in fromConfig().
45- // TODO: Rename config keys to standard camelCase (allowPbft, pbftExpireNum) when
46- // PBFT feature is enabled and a breaking config change is acceptable.
47- @ Getter (lombok .AccessLevel .NONE )
48- @ Setter (lombok .AccessLevel .NONE )
49- private long allowPBFT = 0 ;
50- @ Getter (lombok .AccessLevel .NONE )
51- @ Setter (lombok .AccessLevel .NONE )
52- private long pBFTExpireNum = 20 ;
53-
54- // Only getters are exposed. No public setters — ConfigBeanFactory scans public
55- // setters via reflection and would derive key "PBFTExpireNum" / "AllowPBFT"
56- // (JavaBean uppercase rule), which does not match config keys "pBFTExpireNum"
57- // / "allowPBFT" and would throw. Values are assigned to fields directly in
58- // fromConfig() below.
59- public long getAllowPBFT () { return allowPBFT ; }
60- public long getPBFTExpireNum () { return pBFTExpireNum ; }
39+ // "allowPBFT" / "pBFTExpireNum" in config.conf use non-standard casing; they are
40+ // remapped to standard camelCase by normalizeNonStandardKeys() before binding.
41+ private long allowPbft = 0 ;
42+ private long pbftExpireNum = 20 ;
6143 private long allowTvmFreeze = 0 ;
6244 private long allowTvmVote = 0 ;
6345 private long allowTvmLondon = 0 ;
@@ -85,32 +67,30 @@ public class CommitteeConfig {
8567 private long dynamicEnergyMaxFactor = 0 ;
8668
8769 // proposalExpireTime is NOT a committee field — it's in block.* and handled by BlockConfig
88-
8970 // Defaults come from reference.conf (loaded globally via Configuration.java)
90-
91- /**
92- * Create CommitteeConfig from the "committee" section of the application config.
93- *
94- * Note: allowPBFT and pBFTExpireNum have non-standard JavaBean naming (consecutive
95- * uppercase letters) which causes ConfigBeanFactory key mismatch. These two fields
96- * are excluded from automatic binding and handled manually after.
97- */
98- private static final String PBFT_EXPIRE_NUM_KEY = "pBFTExpireNum" ;
99- private static final String ALLOW_PBFT_KEY = "allowPBFT" ;
100-
10171 public static CommitteeConfig fromConfig (Config config ) {
102- Config section = config .getConfig ("committee" );
103-
72+ Config section = normalizeNonStandardKeys (config .getConfig ("committee" ));
10473 CommitteeConfig cc = ConfigBeanFactory .create (section , CommitteeConfig .class );
105- // Ensure the manually-named fields get the right values from the original keys
106- cc .allowPBFT = section .hasPath (ALLOW_PBFT_KEY ) ? section .getLong (ALLOW_PBFT_KEY ) : 0 ;
107- cc .pBFTExpireNum = section .hasPath (PBFT_EXPIRE_NUM_KEY )
108- ? section .getLong (PBFT_EXPIRE_NUM_KEY ) : 20 ;
109-
11074 cc .postProcess ();
11175 return cc ;
11276 }
11377
78+ // "allowPBFT" and "pBFTExpireNum" use non-standard casing that JavaBean Introspector
79+ // cannot derive correctly (setPBFTExpireNum -> property "PBFTExpireNum", not "pBFTExpireNum").
80+ // Remap them to standard camelCase keys so ConfigBeanFactory binds them normally.
81+ // Config is immutable; withValue() returns a new object.
82+ private static Config normalizeNonStandardKeys (Config section ) {
83+ if (section .hasPath ("allowPBFT" )) {
84+ ConfigValue v = section .getValue ("allowPBFT" );
85+ section = section .withValue ("allowPbft" , v ); // rename allowPBFT -> allowPbft
86+ }
87+ if (section .hasPath ("pBFTExpireNum" )) {
88+ ConfigValue v = section .getValue ("pBFTExpireNum" );
89+ section = section .withValue ("pbftExpireNum" , v ); // rename pBFTExpireNum -> pbftExpireNum
90+ }
91+ return section ;
92+ }
93+
11494 private void postProcess () {
11595 // clamp unfreezeDelayDays to 0-365
11696 if (unfreezeDelayDays < 0 ) {
@@ -121,35 +101,61 @@ private void postProcess() {
121101 }
122102
123103 // clamp allowDelegateOptimization to 0-1
124- if (allowDelegateOptimization < 0 ) { allowDelegateOptimization = 0 ; }
125- if (allowDelegateOptimization > 1 ) { allowDelegateOptimization = 1 ; }
104+ if (allowDelegateOptimization < 0 ) {
105+ allowDelegateOptimization = 0 ;
106+ }
107+ if (allowDelegateOptimization > 1 ) {
108+ allowDelegateOptimization = 1 ;
109+ }
126110
127111 // clamp allowDynamicEnergy to 0-1
128- if (allowDynamicEnergy < 0 ) { allowDynamicEnergy = 0 ; }
129- if (allowDynamicEnergy > 1 ) { allowDynamicEnergy = 1 ; }
112+ if (allowDynamicEnergy < 0 ) {
113+ allowDynamicEnergy = 0 ;
114+ }
115+ if (allowDynamicEnergy > 1 ) {
116+ allowDynamicEnergy = 1 ;
117+ }
130118
131119 // clamp dynamicEnergyThreshold to 0-100_000_000_000_000_000
132- if (dynamicEnergyThreshold < 0 ) { dynamicEnergyThreshold = 0 ; }
120+ if (dynamicEnergyThreshold < 0 ) {
121+ dynamicEnergyThreshold = 0 ;
122+ }
133123 if (dynamicEnergyThreshold > 100_000_000_000_000_000L ) {
134124 dynamicEnergyThreshold = 100_000_000_000_000_000L ;
135125 }
136126
137127 // clamp dynamicEnergyIncreaseFactor to 0-10_000
138- if (dynamicEnergyIncreaseFactor < 0 ) { dynamicEnergyIncreaseFactor = 0 ; }
139- if (dynamicEnergyIncreaseFactor > 10_000L ) { dynamicEnergyIncreaseFactor = 10_000L ; }
128+ if (dynamicEnergyIncreaseFactor < 0 ) {
129+ dynamicEnergyIncreaseFactor = 0 ;
130+ }
131+ if (dynamicEnergyIncreaseFactor > 10_000L ) {
132+ dynamicEnergyIncreaseFactor = 10_000L ;
133+ }
140134
141135 // clamp dynamicEnergyMaxFactor to 0-100_000
142- if (dynamicEnergyMaxFactor < 0 ) { dynamicEnergyMaxFactor = 0 ; }
143- if (dynamicEnergyMaxFactor > 100_000L ) { dynamicEnergyMaxFactor = 100_000L ; }
136+ if (dynamicEnergyMaxFactor < 0 ) {
137+ dynamicEnergyMaxFactor = 0 ;
138+ }
139+ if (dynamicEnergyMaxFactor > 100_000L ) {
140+ dynamicEnergyMaxFactor = 100_000L ;
141+ }
144142
145143 // clamp allowNewReward to 0-1 (must run BEFORE the cross-field check below,
146144 // which depends on allowNewReward != 1)
147- if (allowNewReward < 0 ) { allowNewReward = 0 ; }
148- if (allowNewReward > 1 ) { allowNewReward = 1 ; }
145+ if (allowNewReward < 0 ) {
146+ allowNewReward = 0 ;
147+ }
148+ if (allowNewReward > 1 ) {
149+ allowNewReward = 1 ;
150+ }
149151
150152 // clamp memoFee to 0-1_000_000_000
151- if (memoFee < 0 ) { memoFee = 0 ; }
152- if (memoFee > 1_000_000_000L ) { memoFee = 1_000_000_000L ; }
153+ if (memoFee < 0 ) {
154+ memoFee = 0 ;
155+ }
156+ if (memoFee > 1_000_000_000L ) {
157+ memoFee = 1_000_000_000L ;
158+ }
153159
154160 // cross-field: allowOldRewardOpt requires at least one reward/vote flag
155161 if (allowOldRewardOpt == 1 && allowNewRewardAlgorithm != 1
0 commit comments