This guide explains the two-layer configuration system used by java-tron and walks through the most common customizations a node operator needs.
java-tron uses Typesafe Config and applies configuration in priority order at startup:
| File | Location | Purpose |
|---|---|---|
reference.conf |
Bundled inside the jar (common module) |
Declares every parameter with its default value |
Bundled config.conf |
Bundled inside the jar (framework module) |
Shipped template; active only when -c is omitted |
Your config file (e.g. node.conf) |
Operator-supplied, passed via -c |
Overrides values that differ from defaults; replaces the bundled config.conf entirely |
Loading priority: values in your config file always win. Any parameter your file omits is automatically filled in from reference.conf. You never need to copy the entire reference.conf into your own file — only include the parameters you actually want to change.
startup resolution order (highest wins):
1. your config file (passed with -c; replaces bundled config.conf)
2. bundled config.conf (only when -c is omitted)
3. reference.conf (always loaded; fallback for every key)
reference.conf is the authoritative source of truth for every parameter name and its default. When in doubt, consult that file to see what a parameter does and what value the node will use if you leave it out.
# Using the distribution script
java-tron-1.0.0/bin/FullNode -c /path/to/node.conf
# Using the jar directly
java -jar FullNode.jar -c /path/to/node.conf
# SR (Super Representative) mode
java-tron-1.0.0/bin/FullNode -c /path/to/node.conf -wIf -c is omitted, the node loads the config.conf bundled inside the jar (the same file shipped with the distribution) merged with reference.conf as fallback. The bundled file already enables discovery/persist for mainnet operation. For production, copy it out, edit, and pass the edited copy via -c to make your configuration visible to operators.
Your config file only needs to contain what you want to change. The following is sufficient for a mainnet full node:
node.discovery = {
enable = true
persist = true
}
node {
listen.port = 18888
minParticipationRate = 15
p2p.version = 11111 # mainnet
}
seed.node.ip.list = [
"3.225.171.164:18888",
"52.8.46.215:18888",
# ... (see reference.conf for the full seed list)
]node.discovery = {
enable = true # join the peer-discovery network
persist = true # save discovered peers across restarts
}
node {
listen.port = 18888 # TCP port for peer connections
maxConnections = 30 # maximum peer connections
minConnections = 8 # minimum peer connections to maintain
minParticipationRate = 15 # minimum % of active witnesses before producing blocks
p2p {
version = 11111 # Mainnet:11111 Nile:201910292 Shasta:1
}
}
seed.node.ip.list = [
"3.225.171.164:18888",
# add more entries as needed
]node {
http {
fullNodeEnable = true
fullNodePort = 8090
solidityEnable = true
solidityPort = 8091
}
rpc {
enable = true
port = 50051
solidityEnable = true
solidityPort = 50061
# Maximum concurrent calls per connection. 0 uses the secure default of 100.
maxConcurrentCallsPerConnection = 100
# Idle connection timeout (ms). 0 = no limit.
maxConnectionIdleInMillis = 0
# Minimum active connections required before broadcasting transactions.
minEffectiveConnection = 1
}
}Upgrade note:
node.rpc.maxConcurrentCallsPerConnection = 0previously meant no limit. It now selects the secure default of 100. Configure an explicit positive value if a client needs more than 100 concurrent calls on one connection.
To disable an API endpoint that you do not want to expose publicly, set its Enable flag to false or add endpoints to node.disabledApi:
node.disabledApi = [
"getaccount",
"getnowblock2"
]storage {
db.engine = "LEVELDB" # "LEVELDB" or "ROCKSDB"; ARM64 requires "ROCKSDB"
db.sync = false # set true for maximum durability (slower writes)
db.directory = "database"
}To override the storage path for individual databases:
storage.properties = [
{
name = "account",
path = "/data/tron/account-db"
}
]# Plain private key (use localwitnesskeystore for production)
localwitness = [
"your-private-key-hex"
]
# Recommended: keystore file
# localwitnesskeystore = [
# "/path/to/localwitnesskeystore.json"
# ]
# Required when the witness account has delegated block-signing to a separate key
# localWitnessAccountAddress = "T..."node.jsonrpc {
httpFullNodeEnable = true
httpFullNodePort = 8545
maxBlockRange = 5000 # max block range for eth_getLogs
maxResponseSize = 26214400 # 25 MB
}event.subscribe = {
enable = true
native {
useNativeQueue = true
bindport = 5555
sendqueuelength = 1000
}
topics = [
{ triggerName = "block", enable = true, topic = "block" },
{ triggerName = "transaction", enable = true, topic = "transaction" },
{ triggerName = "solidity", enable = true, topic = "solidity" }
]
}rate.limiter = {
# Available strategies:
# GlobalPreemptibleAdapter — semaphore-based, paramString = "permit=N"
# QpsRateLimiterAdapter — node-wide QPS cap, paramString = "qps=N"
# IPQPSRateLimiterAdapter — per-IP QPS cap, paramString = "qps=N"
http = [
{
component = "GetAccountServlet",
strategy = "IPQPSRateLimiterAdapter",
paramString = "qps=10"
}
]
global.qps = 50000
global.ip.qps = 10000
}When enabled, the node re-reads your config file periodically without restarting:
node.dynamicConfig = {
enable = true
checkInterval = 600 # seconds between checks
}Not all parameters support hot-reload. Parameters that affect node identity, genesis block, or database layout require a full restart.
| Parameter | Reason |
|---|---|
crypto.engine |
Changing the key-derivation algorithm will fork the node |
genesis.block.* |
Must be identical on every node in the network |
committee.* |
Controlled by on-chain governance proposals; manual overrides are for private chains only |
node.p2p.version |
Must match the network (11111 for mainnet) |
enery.limit.block.num |
Intentional typo preserved for backward compatibility; do not rename |
- Edit your config file — only add or change the keys you need.
- If
node.dynamicConfig.enable = true, wait up tocheckIntervalseconds; the node picks up the change automatically. - Otherwise, restart the node:
kill <pid>then relaunch with the same-cflag. - Check startup logs for a
[config]line confirming the file was loaded and watch for anyERRORlines about unknown or invalid keys.
At startup, the node unconditionally logs a summary of key parameters under Net config, Backup config, Code version, DB config, and shutDown config headers (see Args.logConfig() for the exact fields). For parameters not in this summary, you must inspect runtime behavior or consult reference.conf directly — the full merged configuration is never dumped.
Note: node.openPrintLog is a separate flag that controls runtime verbosity of P2P/inventory/pending-tx logs, not startup config logging.
Every parameter with its default value and an inline comment is documented in:
common/src/main/resources/reference.conf
When you need the authoritative default for a parameter or want to understand what a key does, consult that file directly.