diff --git a/build.gradle b/build.gradle
index 65e72c0fb73..06186778971 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ plugins {
}
ext {
- grpcVersion = "1.83.0"
+ grpcVersion = "1.83.1"
}
allprojects {
diff --git a/common/build.gradle b/common/build.gradle
index 14d3eb4e637..4b36d067b70 100644
--- a/common/build.gradle
+++ b/common/build.gradle
@@ -8,7 +8,9 @@ sourceCompatibility = 1.8
dependencies {
- api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.18.6' // https://github.com/FasterXML/jackson-databind/issues/3627
+ // avoid x.y.z.w micro-patches, they may ship broken Gradle module metadata:
+ // https://github.com/FasterXML/jackson-databind/issues/3627
+ api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.18.10'
api "com.cedarsoftware:java-util:3.2.0"
api group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1'
api group: 'commons-codec', name: 'commons-codec', version: '1.11'
diff --git a/framework/src/main/java/org/tron/common/application/GrpcNettyMaxConcurrentStreamsLimiter.java b/framework/src/main/java/org/tron/common/application/GrpcNettyMaxConcurrentStreamsLimiter.java
deleted file mode 100644
index cdd71ffee3c..00000000000
--- a/framework/src/main/java/org/tron/common/application/GrpcNettyMaxConcurrentStreamsLimiter.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * java-tron is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * java-tron is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with java-tron. If not, see .
- */
-
-package org.tron.common.application;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import io.grpc.netty.GrpcHttp2ConnectionHandler;
-import io.grpc.netty.InternalProtocolNegotiator;
-import io.grpc.netty.InternalProtocolNegotiators;
-import io.grpc.netty.NettyServerBuilder;
-import io.netty.channel.ChannelHandler;
-import io.netty.util.AsciiString;
-
-/** Enforces the advertised HTTP/2 concurrent stream limit for grpc-netty servers. */
-final class GrpcNettyMaxConcurrentStreamsLimiter {
-
- private GrpcNettyMaxConcurrentStreamsLimiter() {
- }
-
- static NettyServerBuilder configurePlaintext(
- NettyServerBuilder builder, int maxConcurrentStreams) {
- checkNotNull(builder, "builder");
- checkArgument(maxConcurrentStreams > 0, "maxConcurrentStreams must be positive");
- builder.maxConcurrentCallsPerConnection(maxConcurrentStreams);
- // TODO: Remove this shim after https://github.com/grpc/grpc-java/issues/12930 is fixed.
- return builder.protocolNegotiator(newPlaintextNegotiator(maxConcurrentStreams));
- }
-
- static InternalProtocolNegotiator.ProtocolNegotiator newPlaintextNegotiator(
- int maxConcurrentStreams) {
- checkArgument(maxConcurrentStreams > 0, "maxConcurrentStreams must be positive");
- return new EnforcingProtocolNegotiator(
- InternalProtocolNegotiators.serverPlaintext(), maxConcurrentStreams);
- }
-
- private static final class EnforcingProtocolNegotiator
- implements InternalProtocolNegotiator.ProtocolNegotiator {
-
- private final InternalProtocolNegotiator.ProtocolNegotiator delegate;
- private final int maxConcurrentStreams;
-
- private EnforcingProtocolNegotiator(
- InternalProtocolNegotiator.ProtocolNegotiator delegate, int maxConcurrentStreams) {
- this.delegate = checkNotNull(delegate, "delegate");
- this.maxConcurrentStreams = maxConcurrentStreams;
- }
-
- @Override
- public AsciiString scheme() {
- return delegate.scheme();
- }
-
- @Override
- public ChannelHandler newHandler(GrpcHttp2ConnectionHandler grpcHandler) {
- // grpc-java builds the connection directly, bypassing Netty's builder-side enforcement.
- grpcHandler.connection().remote().maxActiveStreams(maxConcurrentStreams);
- return delegate.newHandler(grpcHandler);
- }
-
- @Override
- public void close() {
- delegate.close();
- }
- }
-}
diff --git a/framework/src/main/java/org/tron/common/application/RpcService.java b/framework/src/main/java/org/tron/common/application/RpcService.java
index 27fcc479f4e..c398b71ae41 100644
--- a/framework/src/main/java/org/tron/common/application/RpcService.java
+++ b/framework/src/main/java/org/tron/common/application/RpcService.java
@@ -100,9 +100,8 @@ protected NettyServerBuilder initServerBuilder() {
serverBuilder = serverBuilder.executor(this.executorService);
}
// Set configs from config.conf or default value
- serverBuilder = GrpcNettyMaxConcurrentStreamsLimiter.configurePlaintext(
- serverBuilder, parameter.getMaxConcurrentCallsPerConnection());
serverBuilder
+ .maxConcurrentCallsPerConnection(parameter.getMaxConcurrentCallsPerConnection())
.flowControlWindow(parameter.getFlowControlWindow())
.maxConnectionIdle(parameter.getMaxConnectionIdleInMillis(), TimeUnit.MILLISECONDS)
.maxConnectionAge(parameter.getMaxConnectionAgeInMillis(), TimeUnit.MILLISECONDS)
diff --git a/framework/src/test/java/org/tron/common/application/GrpcNettyMaxConcurrentStreamsLimiterTest.java b/framework/src/test/java/org/tron/common/application/GrpcNettyMaxConcurrentStreamsLimiterTest.java
deleted file mode 100644
index fc578ca7947..00000000000
--- a/framework/src/test/java/org/tron/common/application/GrpcNettyMaxConcurrentStreamsLimiterTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * java-tron is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * java-tron is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with java-tron. If not, see .
- */
-
-package org.tron.common.application;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThrows;
-
-import io.grpc.ChannelLogger;
-import io.grpc.ChannelLogger.ChannelLogLevel;
-import io.grpc.netty.GrpcHttp2ConnectionHandler;
-import io.grpc.netty.InternalProtocolNegotiator;
-import io.netty.channel.ChannelHandler;
-import io.netty.handler.codec.http2.DefaultHttp2Connection;
-import io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder;
-import io.netty.handler.codec.http2.DefaultHttp2ConnectionEncoder;
-import io.netty.handler.codec.http2.DefaultHttp2FrameReader;
-import io.netty.handler.codec.http2.DefaultHttp2FrameWriter;
-import io.netty.handler.codec.http2.Http2Connection;
-import io.netty.handler.codec.http2.Http2ConnectionDecoder;
-import io.netty.handler.codec.http2.Http2ConnectionEncoder;
-import io.netty.handler.codec.http2.Http2Error;
-import io.netty.handler.codec.http2.Http2Exception;
-import io.netty.handler.codec.http2.Http2FrameWriter;
-import io.netty.handler.codec.http2.Http2Settings;
-import org.junit.Test;
-
-public class GrpcNettyMaxConcurrentStreamsLimiterTest {
-
- private static final ChannelLogger NOOP_LOGGER = new ChannelLogger() {
- @Override
- public void log(ChannelLogLevel level, String message) {
- }
-
- @Override
- public void log(ChannelLogLevel level, String messageFormat, Object... args) {
- }
- };
-
- @Test
- public void shouldEnforceMaxStreamsBeforeSettingsAck() throws Exception {
- Http2Connection connection = new DefaultHttp2Connection(true);
- GrpcHttp2ConnectionHandler grpcHandler = newGrpcHandler(connection);
- InternalProtocolNegotiator.ProtocolNegotiator negotiator =
- GrpcNettyMaxConcurrentStreamsLimiter.newPlaintextNegotiator(2);
-
- ChannelHandler negotiationHandler = negotiator.newHandler(grpcHandler);
-
- assertNotNull(negotiationHandler);
- assertEquals(2, connection.remote().maxActiveStreams());
- connection.remote().createStream(1, true);
- connection.remote().createStream(3, true);
- Http2Exception exception = assertThrows(
- Http2Exception.class, () -> connection.remote().createStream(5, true));
- assertEquals(Http2Error.REFUSED_STREAM, exception.error());
- negotiator.close();
- }
-
- @Test
- public void shouldIgnoreClientMaxHeaderListSizeOnServer() throws Exception {
- Http2Connection connection = new DefaultHttp2Connection(true);
- Http2FrameWriter frameWriter = new DefaultHttp2FrameWriter();
- Http2ConnectionEncoder encoder =
- new DefaultHttp2ConnectionEncoder(connection, frameWriter);
- long originalMaxHeaderListSize =
- encoder.configuration().headersConfiguration().maxHeaderListSize();
-
- encoder.remoteSettings(new Http2Settings().maxHeaderListSize(1));
-
- assertEquals(originalMaxHeaderListSize,
- encoder.configuration().headersConfiguration().maxHeaderListSize());
- encoder.close();
- }
-
- @Test
- public void shouldRejectNonPositiveStreamLimit() {
- IllegalArgumentException zeroLimitException = assertThrows(IllegalArgumentException.class,
- () -> GrpcNettyMaxConcurrentStreamsLimiter.newPlaintextNegotiator(0));
- assertEquals("maxConcurrentStreams must be positive", zeroLimitException.getMessage());
- IllegalArgumentException negativeLimitException = assertThrows(IllegalArgumentException.class,
- () -> GrpcNettyMaxConcurrentStreamsLimiter.newPlaintextNegotiator(-1));
- assertEquals("maxConcurrentStreams must be positive", negativeLimitException.getMessage());
- }
-
- private static GrpcHttp2ConnectionHandler newGrpcHandler(Http2Connection connection) {
- Http2FrameWriter frameWriter = new DefaultHttp2FrameWriter();
- Http2ConnectionEncoder encoder =
- new DefaultHttp2ConnectionEncoder(connection, frameWriter);
- Http2ConnectionDecoder decoder = new DefaultHttp2ConnectionDecoder(
- connection, encoder, new DefaultHttp2FrameReader());
- return new GrpcHttp2ConnectionHandler(
- null, decoder, encoder, new Http2Settings(), NOOP_LOGGER) {
- };
- }
-}
diff --git a/framework/src/test/java/org/tron/common/application/NettyHttp2HeaderSecurityTest.java b/framework/src/test/java/org/tron/common/application/NettyHttp2HeaderSecurityTest.java
new file mode 100644
index 00000000000..6a4f4330f04
--- /dev/null
+++ b/framework/src/test/java/org/tron/common/application/NettyHttp2HeaderSecurityTest.java
@@ -0,0 +1,53 @@
+/*
+ * java-tron is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * java-tron is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with java-tron. If not, see .
+ */
+
+package org.tron.common.application;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.handler.codec.http2.DefaultHttp2Connection;
+import io.netty.handler.codec.http2.DefaultHttp2ConnectionEncoder;
+import io.netty.handler.codec.http2.DefaultHttp2FrameWriter;
+import io.netty.handler.codec.http2.Http2Connection;
+import io.netty.handler.codec.http2.Http2ConnectionEncoder;
+import io.netty.handler.codec.http2.Http2FrameWriter;
+import io.netty.handler.codec.http2.Http2Settings;
+import org.junit.Test;
+
+/** Guards the netty HTTP/2 header-size behaviour the gRPC server relies on. */
+public class NettyHttp2HeaderSecurityTest {
+
+ /**
+ * CVE-2026-50560: SETTINGS_MAX_HEADER_LIST_SIZE tells the server what the client is willing to
+ * receive, so it must not shrink the server encoder's own limit. Otherwise a hostile client can
+ * advertise a tiny value and make every response-header write throw, which is a Rapid-Reset-like
+ * denial of service. Netty enforced the client value before 4.1.135.Final / 4.2.15.Final.
+ */
+ @Test
+ public void shouldIgnoreClientMaxHeaderListSizeOnServer() throws Exception {
+ Http2Connection connection = new DefaultHttp2Connection(true);
+ Http2FrameWriter frameWriter = new DefaultHttp2FrameWriter();
+ Http2ConnectionEncoder encoder =
+ new DefaultHttp2ConnectionEncoder(connection, frameWriter);
+ long originalMaxHeaderListSize =
+ encoder.configuration().headersConfiguration().maxHeaderListSize();
+
+ encoder.remoteSettings(new Http2Settings().maxHeaderListSize(1));
+
+ assertEquals(originalMaxHeaderListSize,
+ encoder.configuration().headersConfiguration().maxHeaderListSize());
+ encoder.close();
+ }
+}
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 6a3e641d5d6..08c7f6d34b9 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -189,9 +189,9 @@
-
-
-
+
+
+
@@ -199,9 +199,9 @@
-
-
-
+
+
+
@@ -219,15 +219,15 @@
-
-
-
+
+
+
-
-
+
+
-
-
+
+
@@ -235,15 +235,15 @@
-
-
-
+
+
+
-
-
+
+
-
-
+
+
@@ -251,15 +251,15 @@
-
-
-
+
+
+
-
-
+
+
-
-
+
+
@@ -1171,76 +1171,76 @@
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
@@ -1251,18 +1251,18 @@
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+