Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
aa8006d
feat(http): add Jetty SizeLimitHandler to enforce request body size l…
bladehan1 Mar 19, 2026
e81cef5
feat(http) : wait for HttpService startup future in SizeLimitHandlerTest
bladehan1 Mar 19, 2026
9fc6a29
feat(http): add independent maxMessageSize for HTTP and JSON-RPC
bladehan1 Mar 23, 2026
adb49d6
opt(checkstyle): optimize checkstyle
bladehan1 Apr 1, 2026
2cc14e2
change(config): update default size
bladehan1 Apr 2, 2026
e182fb2
test(framework): align ArgsTest with 4M defaults
bladehan1 Apr 2, 2026
e0df7d4
test(http): doc for default value
bladehan1 Apr 3, 2026
baa4d88
fix(api): use httpMaxMessageSize in checkBodySize instead of gRPC limit
bladehan1 Apr 9, 2026
cd1ebad
test(http): add chunked transfer and zero-limit tests for SizeLimitHa…
bladehan1 Apr 10, 2026
8c539d1
refactor(config): use getMemorySize() for size limit configs
bladehan1 Apr 10, 2026
757470c
fix(config): allow zero value for maxMessageSize parameters
bladehan1 Apr 10, 2026
0b45cbb
test(http): verify checkBodySize consistency with SizeLimitHandler
bladehan1 Apr 10, 2026
c28405c
fix(config): correct comment from "positive" to "non-negative"
bladehan1 Apr 10, 2026
c8bacc8
fix(http): add safe default for maxRequestSize and fix misleading var…
bladehan1 Apr 14, 2026
8938c52
test(config): add maxMessageSize parsing and zero-value documentation
bladehan1 Apr 14, 2026
aea0be8
test(http): add real JSON-RPC integration test and clean up SizeLimit…
bladehan1 Apr 15, 2026
58c258d
refactor(http): replace reflection with @VisibleForTesting accessor a…
bladehan1 Apr 16, 2026
f360750
test(http): address review comments - assertThrows, ASCII punctuation…
bladehan1 Apr 20, 2026
bb14edd
fix(config): cap http/jsonrpc maxMessageSize at Integer.MAX_VALUE
bladehan1 Apr 22, 2026
5cdcebd
refactor(framework): extract parseMaxMessageSize helper
bladehan1 Apr 27, 2026
19c6674
Merge upstream/develop into feat/request_size
bladehan1 Apr 28, 2026
da0c6d0
Merge remote-tracking branch 'upstream/develop' into feat/request_size
bladehan1 May 7, 2026
9e3ea6b
Merge upstream/develop into feat/request_size
bladehan1 May 8, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,19 @@ public class CommonParameter {
@Getter
@Setter
public long maxConnectionAgeInMillis;
// Refers to RPC (gRPC) max message size; see httpMaxMessageSize / jsonRpcMaxMessageSize
// below for the HTTP / JSON-RPC counterparts.
@Getter
@Setter
public int maxMessageSize;
@Getter
@Setter
public long httpMaxMessageSize;
@Getter
@Setter
public long jsonRpcMaxMessageSize;
@Getter
@Setter
public int maxHeaderListSize;
@Getter
@Setter
Expand Down
41 changes: 40 additions & 1 deletion common/src/main/java/org/tron/core/config/args/NodeConfig.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package org.tron.core.config.args;

import static org.tron.core.config.Parameter.ChainConstant.MAX_ACTIVE_WITNESS_NUM;
import static org.tron.core.exception.TronError.ErrCode.PARAMETER_INIT;

import com.typesafe.config.Config;
import com.typesafe.config.ConfigBeanFactory;
import com.typesafe.config.ConfigFactory;
import com.typesafe.config.ConfigValueFactory;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.tron.core.exception.TronError;

// Node configuration bean for the "node" section of config.conf.
// ConfigBeanFactory auto-binds all fields including sub-beans, dot-notation keys,
Expand Down Expand Up @@ -198,6 +201,7 @@ public static class HttpConfig {
private int fullNodePort = 8090;
private boolean solidityEnable = true;
private int solidityPort = 8091;
private long maxMessageSize = 4194304;
// PBFT fields — handled manually (same naming issue as CommitteeConfig)
// Default must match CommonParameter.pBFTHttpEnable = true
@Getter(lombok.AccessLevel.NONE)
Expand Down Expand Up @@ -303,6 +307,7 @@ public void setHttpPBFTPort(int v) {
private int maxBlockRange = 5000;
private int maxSubTopics = 1000;
private int maxBlockFilterNum = 50000;
private long maxMessageSize = 4194304;
}

@Getter
Expand Down Expand Up @@ -360,7 +365,11 @@ public static class DnsConfig {
* since ConfigBeanFactory expects typed bean lists, not string lists.
*/
public static NodeConfig fromConfig(Config config) {
Config section = config.getConfig("node");
// Normalize human-readable size values (e.g. "4m") to numeric bytes so
// ConfigBeanFactory's primitive int/long binding succeeds; same step
// enforces non-negative and <= Integer.MAX_VALUE before bean creation
// so failures point at the user-facing config path.
Config section = normalizeMaxMessageSizes(config).getConfig("node");

// Auto-bind all fields and sub-beans. ConfigBeanFactory fails fast with a
// descriptive path on any `= null` value — external configs that use the
Expand Down Expand Up @@ -500,4 +509,34 @@ private static String getString(Config config, String path, String defaultValue)
return config.hasPath(path) ? config.getString(path) : defaultValue;
}

// Pre-normalize size paths so ConfigBeanFactory's primitive int/long binding succeeds
// for human-readable values like "4m" / "128MB". For each maxMessageSize key, parse
// via getMemorySize, validate non-negative and <= Integer.MAX_VALUE, and write the
// numeric byte value back into the Config tree. Validation errors propagate before
// bean creation so the failure points at the user-facing config path.
private static Config normalizeMaxMessageSizes(Config config) {
String[] paths = {
"node.rpc.maxMessageSize",
"node.http.maxMessageSize",
"node.jsonrpc.maxMessageSize"
};
Config result = config;
for (String path : paths) {
if (config.hasPath(path)) {
long bytes = parseMaxMessageSize(config, path);
result = result.withValue(path, ConfigValueFactory.fromAnyRef(bytes));
}
}
return result;
}

private static long parseMaxMessageSize(Config config, String key) {
long value = config.getMemorySize(key).toBytes();
if (value < 0 || value > Integer.MAX_VALUE) {
throw new TronError(key + " must be non-negative and <= "
+ Integer.MAX_VALUE + ", got: " + value, PARAMETER_INIT);
}
return value;
}

}
6 changes: 6 additions & 0 deletions common/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ node {
solidityPort = 8091
PBFTEnable = true
PBFTPort = 8092

# Maximum HTTP request body size, default 4MB. Independent from rpc.maxMessageSize.
maxMessageSize = 4M
}

rpc {
Expand Down Expand Up @@ -402,6 +405,9 @@ node {

# Maximum number for blockFilter
maxBlockFilterNum = 50000

# Maximum JSON-RPC request body size, default 4MB. Independent from rpc.maxMessageSize.
maxMessageSize = 4M
}

# Disabled API list (works for http, rpc and pbft, not jsonrpc). Case insensitive.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@

package org.tron.common.application;

import com.google.common.annotations.VisibleForTesting;
import java.util.concurrent.CompletableFuture;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jetty.server.ConnectionLimit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.SizeLimitHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.tron.core.config.args.Args;

Expand All @@ -29,6 +31,18 @@ public abstract class HttpService extends AbstractService {

protected String contextPath;

protected long maxRequestSize = 4 * 1024 * 1024; // 4MB

@VisibleForTesting
public long getMaxRequestSize() {
return this.maxRequestSize;
}

@VisibleForTesting
public void setMaxRequestSize(long maxRequestSize) {
this.maxRequestSize = maxRequestSize;
}

@Override
public void innerStart() throws Exception {
if (this.apiServer != null) {
Expand Down Expand Up @@ -63,7 +77,9 @@ protected void initServer() {
protected ServletContextHandler initContextHandler() {
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath(this.contextPath);
this.apiServer.setHandler(context);
SizeLimitHandler sizeLimitHandler = new SizeLimitHandler(this.maxRequestSize, -1);
sizeLimitHandler.setHandler(context);
this.apiServer.setHandler(sizeLimitHandler);
return context;
}

Expand Down
2 changes: 2 additions & 0 deletions framework/src/main/java/org/tron/core/config/args/Args.java
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ private static void applyNodeConfig(NodeConfig nc) {
PARAMETER.fullNodeHttpPort = http.getFullNodePort();
PARAMETER.solidityHttpPort = http.getSolidityPort();
PARAMETER.pBFTHttpPort = http.getPBFTPort();
PARAMETER.httpMaxMessageSize = http.getMaxMessageSize();

// ---- JSON-RPC sub-bean ----
NodeConfig.JsonRpcConfig jsonrpc = nc.getJsonrpc();
Expand All @@ -585,6 +586,7 @@ private static void applyNodeConfig(NodeConfig nc) {
PARAMETER.jsonRpcMaxBlockRange = jsonrpc.getMaxBlockRange();
PARAMETER.jsonRpcMaxSubTopics = jsonrpc.getMaxSubTopics();
PARAMETER.jsonRpcMaxBlockFilterNum = jsonrpc.getMaxBlockFilterNum();
PARAMETER.jsonRpcMaxMessageSize = jsonrpc.getMaxMessageSize();

// ---- P2P sub-bean ----
PARAMETER.nodeP2pVersion = nc.getP2p().getVersion();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ public FullNodeHttpApiService() {
port = Args.getInstance().getFullNodeHttpPort();
enable = isFullNode() && Args.getInstance().isFullNodeHttpEnable();
contextPath = "/";
maxRequestSize = Args.getInstance().getHttpMaxMessageSize();
}

@Override
Expand Down
6 changes: 4 additions & 2 deletions framework/src/main/java/org/tron/core/services/http/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,12 @@ public static Transaction packTransaction(String strTransaction, boolean selfTyp
}
}

@Deprecated
public static void checkBodySize(String body) throws Exception {
CommonParameter parameter = Args.getInstance();
if (body.getBytes().length > parameter.getMaxMessageSize()) {
throw new Exception("body size is too big, the limit is " + parameter.getMaxMessageSize());
if (body.getBytes().length > parameter.getHttpMaxMessageSize()) {
throw new Exception("body size is too big, the limit is "
+ parameter.getHttpMaxMessageSize());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ public SolidityNodeHttpApiService() {
port = Args.getInstance().getSolidityHttpPort();
enable = !isFullNode() && Args.getInstance().isSolidityNodeHttpEnable();
contextPath = "/";
maxRequestSize = Args.getInstance().getHttpMaxMessageSize();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public JsonRpcServiceOnPBFT() {
port = Args.getInstance().getJsonRpcHttpPBFTPort();
enable = isFullNode() && Args.getInstance().isJsonRpcHttpPBFTNodeEnable();
contextPath = "/";
maxRequestSize = Args.getInstance().getJsonRpcMaxMessageSize();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public JsonRpcServiceOnSolidity() {
port = Args.getInstance().getJsonRpcHttpSolidityPort();
enable = isFullNode() && Args.getInstance().isJsonRpcHttpSolidityNodeEnable();
contextPath = "/";
maxRequestSize = Args.getInstance().getJsonRpcMaxMessageSize();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ public HttpApiOnPBFTService() {
port = Args.getInstance().getPBFTHttpPort();
enable = isFullNode() && Args.getInstance().isPBFTHttpEnable();
contextPath = "/walletpbft";
maxRequestSize = Args.getInstance().getHttpMaxMessageSize();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ public HttpApiOnSolidityService() {
port = Args.getInstance().getSolidityHttpPort();
enable = isFullNode() && Args.getInstance().isSolidityNodeHttpEnable();
contextPath = "/";
maxRequestSize = Args.getInstance().getHttpMaxMessageSize();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public FullNodeJsonRpcHttpService() {
port = Args.getInstance().getJsonRpcHttpFullNodePort();
enable = isFullNode() && Args.getInstance().isJsonRpcHttpFullNodeEnable();
contextPath = "/";
maxRequestSize = Args.getInstance().getJsonRpcMaxMessageSize();
}

@Override
Expand Down
19 changes: 17 additions & 2 deletions framework/src/main/resources/config.conf
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,12 @@ node {
solidityPort = 8091
PBFTEnable = true
PBFTPort = 8092

# The maximum request body size for HTTP API, default 4M (4194304 bytes).
# Supports human-readable sizes: 4m, 4MB, 4194304.
# Must be non-negative and <= 2147483647 (Integer.MAX_VALUE, ~2 GiB).
# Setting to 0 rejects all non-empty request bodies (not "unlimited").
# maxMessageSize = 4m
}

rpc {
Expand All @@ -254,8 +260,11 @@ node {
# Connection lasting longer than which will be gracefully terminated
# maxConnectionAgeInMillis =

# The maximum message size allowed to be received on the server, default 4MB
# maxMessageSize =
# The maximum message size allowed to be received on the server, default 4M (4194304 bytes).
# Supports human-readable sizes: 4m, 4MB, 4194304.
# Must be non-negative and <= 2147483647 (Integer.MAX_VALUE, ~2 GiB).
# Setting to 0 rejects all non-empty request bodies (not "unlimited").
# maxMessageSize = 4m

# The maximum size of header list allowed to be received, default 8192
# maxHeaderListSize =
Expand Down Expand Up @@ -363,6 +372,12 @@ node {
# openHistoryQueryWhenLiteFN = false

jsonrpc {
# The maximum request body size for JSON-RPC API, default 4M (4194304 bytes).
# Supports human-readable sizes: 4m, 4MB, 4194304.
# Must be non-negative and <= 2147483647 (Integer.MAX_VALUE, ~2 GiB).
# Setting to 0 rejects all non-empty request bodies (not "unlimited").
# maxMessageSize = 4m

# Note: Before release_4.8.1, if you turn on jsonrpc and run it for a while and then turn it off,
# you will not be able to get the data from eth_getLogs for that period of time. Default: false
# httpFullNodeEnable = false
Expand Down
Loading
Loading