Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 0 additions & 38 deletions codecov.yml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import org.tron.common.logsfilter.FilterQuery;
import org.tron.common.setting.RocksDbSettings;
import org.tron.core.Constant;
import org.tron.core.config.args.Overlay;
import org.tron.core.config.args.SeedNode;
import org.tron.core.config.args.Storage;
import org.tron.p2p.P2pConfig;
Expand Down Expand Up @@ -435,8 +434,6 @@ public class CommonParameter {
@Getter
public Storage storage;
@Getter
public Overlay overlay;
@Getter
public SeedNode seedNode;
@Getter
public EventPluginConfig eventPluginConfig;
Expand Down
116 changes: 61 additions & 55 deletions common/src/main/java/org/tron/core/config/args/CommitteeConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.typesafe.config.Config;
import com.typesafe.config.ConfigBeanFactory;
import com.typesafe.config.ConfigValue;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -35,29 +36,10 @@ public class CommitteeConfig {
private long allowProtoFilterNum = 0;
private long allowAccountStateRoot = 0;
private long changedDelegation = 0;
// NON-STANDARD NAMING: "allowPBFT" and "pBFTExpireNum" in config.conf contain
// consecutive uppercase letters ("PBFT"), which violates JavaBean naming convention.
// ConfigBeanFactory derives config keys from setter names using JavaBean rules:
// setPBFTExpireNum -> property "PBFTExpireNum" (capital P, per JavaBean spec)
// but config.conf uses "pBFTExpireNum" (lowercase p) -> mismatch -> binding fails.
//
// These two fields are excluded from auto-binding and handled manually in fromConfig().
// TODO: Rename config keys to standard camelCase (allowPbft, pbftExpireNum) when
// PBFT feature is enabled and a breaking config change is acceptable.
@Getter(lombok.AccessLevel.NONE)
@Setter(lombok.AccessLevel.NONE)
private long allowPBFT = 0;
@Getter(lombok.AccessLevel.NONE)
@Setter(lombok.AccessLevel.NONE)
private long pBFTExpireNum = 20;

// Only getters are exposed. No public setters — ConfigBeanFactory scans public
// setters via reflection and would derive key "PBFTExpireNum" / "AllowPBFT"
// (JavaBean uppercase rule), which does not match config keys "pBFTExpireNum"
// / "allowPBFT" and would throw. Values are assigned to fields directly in
// fromConfig() below.
public long getAllowPBFT() { return allowPBFT; }
public long getPBFTExpireNum() { return pBFTExpireNum; }
// "allowPBFT" / "pBFTExpireNum" in config.conf use non-standard casing; they are
// remapped to standard camelCase by normalizeNonStandardKeys() before binding.
private long allowPbft = 0;
private long pbftExpireNum = 20;
private long allowTvmFreeze = 0;
private long allowTvmVote = 0;
private long allowTvmLondon = 0;
Expand Down Expand Up @@ -85,32 +67,30 @@ public class CommitteeConfig {
private long dynamicEnergyMaxFactor = 0;

// proposalExpireTime is NOT a committee field — it's in block.* and handled by BlockConfig

// Defaults come from reference.conf (loaded globally via Configuration.java)

/**
* Create CommitteeConfig from the "committee" section of the application config.
*
* Note: allowPBFT and pBFTExpireNum have non-standard JavaBean naming (consecutive
* uppercase letters) which causes ConfigBeanFactory key mismatch. These two fields
* are excluded from automatic binding and handled manually after.
*/
private static final String PBFT_EXPIRE_NUM_KEY = "pBFTExpireNum";
private static final String ALLOW_PBFT_KEY = "allowPBFT";

public static CommitteeConfig fromConfig(Config config) {
Config section = config.getConfig("committee");

Config section = normalizeNonStandardKeys(config.getConfig("committee"));
CommitteeConfig cc = ConfigBeanFactory.create(section, CommitteeConfig.class);
// Ensure the manually-named fields get the right values from the original keys
cc.allowPBFT = section.hasPath(ALLOW_PBFT_KEY) ? section.getLong(ALLOW_PBFT_KEY) : 0;
cc.pBFTExpireNum = section.hasPath(PBFT_EXPIRE_NUM_KEY)
? section.getLong(PBFT_EXPIRE_NUM_KEY) : 20;

cc.postProcess();
return cc;
}

// "allowPBFT" and "pBFTExpireNum" use non-standard casing that JavaBean Introspector
// cannot derive correctly (setPBFTExpireNum -> property "PBFTExpireNum", not "pBFTExpireNum").
// Remap them to standard camelCase keys so ConfigBeanFactory binds them normally.
// Config is immutable; withValue() returns a new object.
private static Config normalizeNonStandardKeys(Config section) {
if (section.hasPath("allowPBFT")) {
ConfigValue v = section.getValue("allowPBFT");
section = section.withValue("allowPbft", v); // rename allowPBFT -> allowPbft
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[NIT] normalizeNonStandardKeys cleanliness: withoutPath + hasPath guard

Two small cleanups apply to both CommitteeConfig.normalizeNonStandardKeys (this file, allowPBFT/pBFTExpireNum) and the sibling NodeConfig.normalizeNonStandardKeys (isOpenFullTcpDisconnect / discovery.external.ip):

  1. section.withValue(newKey, ...) adds the new key but does not remove the legacy one. After normalize, both keys coexist in the Config tree. This is harmless for ConfigBeanFactory (only the canonical name binds), but any downstream diagnostic that walks the raw Config (debug dumps, future read paths) will see two competing entries with no documented winner. Chaining .withoutPath(oldPath) after the rename keeps the post-normalize tree canonical.

  2. NodeConfig.normalizeNonStandardKeys calls section.getIsNull("discovery.external.ip"), which throws ConfigException.Missing if the path itself is absent (it only returns true when the path exists with a null value). The current code relies on the reference.conf default at external.ip = "" always populating this path. If a user explicitly writes node.discovery = null or node.discovery.external = null to disable a sub-tree, normalize blows up with a stack trace pointing into its internals rather than at the offending config path. A hasPath guard or an explicit javadoc precondition (section must be merged with reference.conf fallback) makes the implicit contract traceable.

Neither is a correctness bug given current reference.conf content; treat as nits.

if (section.hasPath("pBFTExpireNum")) {
ConfigValue v = section.getValue("pBFTExpireNum");
section = section.withValue("pbftExpireNum", v); // rename pBFTExpireNum -> pbftExpireNum
}
return section;
}

private void postProcess() {
// clamp unfreezeDelayDays to 0-365
if (unfreezeDelayDays < 0) {
Expand All @@ -121,35 +101,61 @@ private void postProcess() {
}

// clamp allowDelegateOptimization to 0-1
if (allowDelegateOptimization < 0) { allowDelegateOptimization = 0; }
if (allowDelegateOptimization > 1) { allowDelegateOptimization = 1; }
if (allowDelegateOptimization < 0) {
allowDelegateOptimization = 0;
}
if (allowDelegateOptimization > 1) {
allowDelegateOptimization = 1;
}

// clamp allowDynamicEnergy to 0-1
if (allowDynamicEnergy < 0) { allowDynamicEnergy = 0; }
if (allowDynamicEnergy > 1) { allowDynamicEnergy = 1; }
if (allowDynamicEnergy < 0) {
allowDynamicEnergy = 0;
}
if (allowDynamicEnergy > 1) {
allowDynamicEnergy = 1;
}

// clamp dynamicEnergyThreshold to 0-100_000_000_000_000_000
if (dynamicEnergyThreshold < 0) { dynamicEnergyThreshold = 0; }
if (dynamicEnergyThreshold < 0) {
dynamicEnergyThreshold = 0;
}
if (dynamicEnergyThreshold > 100_000_000_000_000_000L) {
dynamicEnergyThreshold = 100_000_000_000_000_000L;
}

// clamp dynamicEnergyIncreaseFactor to 0-10_000
if (dynamicEnergyIncreaseFactor < 0) { dynamicEnergyIncreaseFactor = 0; }
if (dynamicEnergyIncreaseFactor > 10_000L) { dynamicEnergyIncreaseFactor = 10_000L; }
if (dynamicEnergyIncreaseFactor < 0) {
dynamicEnergyIncreaseFactor = 0;
}
if (dynamicEnergyIncreaseFactor > 10_000L) {
dynamicEnergyIncreaseFactor = 10_000L;
}

// clamp dynamicEnergyMaxFactor to 0-100_000
if (dynamicEnergyMaxFactor < 0) { dynamicEnergyMaxFactor = 0; }
if (dynamicEnergyMaxFactor > 100_000L) { dynamicEnergyMaxFactor = 100_000L; }
if (dynamicEnergyMaxFactor < 0) {
dynamicEnergyMaxFactor = 0;
}
if (dynamicEnergyMaxFactor > 100_000L) {
dynamicEnergyMaxFactor = 100_000L;
}

// clamp allowNewReward to 0-1 (must run BEFORE the cross-field check below,
// which depends on allowNewReward != 1)
if (allowNewReward < 0) { allowNewReward = 0; }
if (allowNewReward > 1) { allowNewReward = 1; }
if (allowNewReward < 0) {
allowNewReward = 0;
}
if (allowNewReward > 1) {
allowNewReward = 1;
}

// clamp memoFee to 0-1_000_000_000
if (memoFee < 0) { memoFee = 0; }
if (memoFee > 1_000_000_000L) { memoFee = 1_000_000_000L; }
if (memoFee < 0) {
memoFee = 0;
}
if (memoFee > 1_000_000_000L) {
memoFee = 1_000_000_000L;
}

// cross-field: allowOldRewardOpt requires at least one reward/vote flag
if (allowOldRewardOpt == 1 && allowNewRewardAlgorithm != 1
Expand Down
72 changes: 23 additions & 49 deletions common/src/main/java/org/tron/core/config/args/EventConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,15 @@ public class EventConfig {
private String server = "";
private String dbconfig = "";
private boolean contractParse = true;
@Getter(lombok.AccessLevel.NONE)
// "native" is a Java reserved word; config key cannot match field name directly.
// @Setter(NONE) prevents ConfigBeanFactory from requiring a "nativeQueue" key.
@Setter(lombok.AccessLevel.NONE)
private NativeConfig nativeQueue = new NativeConfig();

public NativeConfig getNativeQueue() { return nativeQueue; }
// Topics list has optional fields (ethCompatible, redundancy, solidified) that
// not all items have. ConfigBeanFactory requires all bean fields to exist in config.
// Excluded from auto-binding, read manually in fromConfig().
@Getter(lombok.AccessLevel.NONE)
// Topics list items have optional fields; excluded from auto-binding.
// @Setter(NONE) prevents ConfigBeanFactory from requiring a "topics" key.
@Setter(lombok.AccessLevel.NONE)
private List<TopicConfig> topics = new ArrayList<>();

public List<TopicConfig> getTopics() { return topics; }
private FilterConfig filter = new FilterConfig();

@Getter
Expand Down Expand Up @@ -70,62 +66,40 @@ public static class FilterConfig {

// Defaults come from reference.conf (loaded globally via Configuration.java)

// TopicConfig fields are optional per item; this fallback ensures all keys exist
// for ConfigBeanFactory binding. Values must match TopicConfig field defaults.
private static final Config TOPIC_DEFAULTS = ConfigFactory.parseString(
"triggerName=\"\", enable=false, topic=\"\", "
+ "solidified=false, ethCompatible=false, redundancy=false");

/**
* Create EventConfig from the "event.subscribe" section of the application config.
*
* <p>Note: HOCON key "native" is a Java reserved word, so the bean field is named
* "nativeQueue" but config key is "native". We handle this manually after binding.
* <p>"native" is a Java reserved word, so the field is named "nativeQueue" and the
* sub-section is read directly after binding. "topics" items may omit optional fields;
* TOPIC_DEFAULTS provides fallback values so ConfigBeanFactory can bind each item.
*/
public static EventConfig fromConfig(Config config) {
Config section = config.getConfig("event.subscribe");

// "native" is a Java reserved word, "topics" has optional fields per item —
// strip both before binding, read manually
String nativeKey = "native";
String topicsKey = "topics";
Config bindable = section.withoutPath(nativeKey).withoutPath(topicsKey)
.withoutPath("topicDefaults");
// remove two keys to construct EventConfig because they cannot be bind automatically,
// we can bind them manually later
Config bindable = section.withoutPath(nativeKey).withoutPath(topicsKey);
EventConfig ec = ConfigBeanFactory.create(bindable, EventConfig.class);

// manually bind "native" sub-section
Config nativeSection = section.hasPath(nativeKey)
? section.getConfig(nativeKey) : ConfigFactory.empty();
ec.nativeQueue = new NativeConfig();
if (nativeSection.hasPath("useNativeQueue")) {
ec.nativeQueue.useNativeQueue = nativeSection.getBoolean("useNativeQueue");
}
if (nativeSection.hasPath("bindport")) {
ec.nativeQueue.bindport = nativeSection.getInt("bindport");
}
if (nativeSection.hasPath("sendqueuelength")) {
ec.nativeQueue.sendqueuelength = nativeSection.getInt("sendqueuelength");
}
// "native" sub-section: bind via ConfigBeanFactory when present, use defaults otherwise
ec.nativeQueue = section.hasPath(nativeKey)
? ConfigBeanFactory.create(section.getConfig(nativeKey), NativeConfig.class)
: new NativeConfig();

// manually bind topics — each item may have optional fields
// topics: withFallback fills optional fields so ConfigBeanFactory can bind each item
if (section.hasPath(topicsKey)) {
ec.topics = new ArrayList<>();
for (com.typesafe.config.ConfigObject obj : section.getObjectList(topicsKey)) {
Config tc = obj.toConfig();
TopicConfig topic = new TopicConfig();
if (tc.hasPath("triggerName")) {
topic.triggerName = tc.getString("triggerName");
}
if (tc.hasPath("enable")) {
topic.enable = tc.getBoolean("enable");
}
if (tc.hasPath("topic")) {
topic.topic = tc.getString("topic");
}
if (tc.hasPath("solidified")) {
topic.solidified = tc.getBoolean("solidified");
}
if (tc.hasPath("ethCompatible")) {
topic.ethCompatible = tc.getBoolean("ethCompatible");
}
if (tc.hasPath("redundancy")) {
topic.redundancy = tc.getBoolean("redundancy");
}
ec.topics.add(topic);
ec.topics.add(ConfigBeanFactory.create(
obj.toConfig().withFallback(TOPIC_DEFAULTS), TopicConfig.class));
}
}

Expand Down
Loading
Loading