Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.ExtensionRegistry;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.UnknownFieldSet;
import java.io.IOException;
Expand Down Expand Up @@ -567,7 +566,6 @@ protected static void mergeField(Tokenizer tokenizer,
FieldDescriptor field;
Descriptor type = builder.getDescriptorForType();
final ExtensionRegistry.ExtensionInfo extension;
boolean unknown = false;

String name = tokenizer.consumeIdentifier();
field = type.findFieldByName(name);
Expand All @@ -591,11 +589,10 @@ protected static void mergeField(Tokenizer tokenizer,
field = null;
}

// Last try to lookup by field-index if 'name' is numeric,
// which indicates a possible unknown field
// Last try to look the field up by number if 'name' is a single digit. The alias
// resolves to the same descriptor as the field name and is parsed the same way.
if (field == null && DIGITS.matcher(name).matches()) {
field = type.findFieldByNumber(Integer.parseInt(name));
unknown = true;
}

// Finally, look for extensions
Expand Down Expand Up @@ -627,11 +624,11 @@ protected static void mergeField(Tokenizer tokenizer,

if (array) {
while (!tokenizer.tryConsume("]")) {
handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown, selfType);
handleValue(tokenizer, extensionRegistry, builder, field, extension, selfType);
tokenizer.tryConsume(",");
}
} else {
handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown, selfType);
handleValue(tokenizer, extensionRegistry, builder, field, extension, selfType);
}
}
}
Expand Down Expand Up @@ -684,12 +681,11 @@ private static void handleValue(Tokenizer tokenizer,
Message.Builder builder,
FieldDescriptor field,
ExtensionRegistry.ExtensionInfo extension,
boolean unknown, boolean selfType) throws ParseException {
boolean selfType) throws ParseException {

Object value = null;
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
value = handleObject(tokenizer, extensionRegistry, builder, field, extension, unknown,
selfType);
value = handleObject(tokenizer, extensionRegistry, builder, field, extension, selfType);
} else {
value = handlePrimitive(tokenizer, field, selfType);
}
Expand Down Expand Up @@ -798,7 +794,7 @@ private static Object handleObject(Tokenizer tokenizer,
Message.Builder builder,
FieldDescriptor field,
ExtensionRegistry.ExtensionInfo extension,
boolean unknown, boolean selfType) throws ParseException {
boolean selfType) throws ParseException {

Message.Builder subBuilder;
if (extension == null) {
Expand All @@ -807,16 +803,6 @@ private static Object handleObject(Tokenizer tokenizer,
subBuilder = extension.defaultInstance.newBuilderForType();
}

if (unknown) {
ByteString data = tokenizer.consumeByteString("", selfType);
try {
subBuilder.mergeFrom(data);
return subBuilder.build();
} catch (InvalidProtocolBufferException e) {
throw tokenizer.parseException("Failed to build " + field.getFullName() + " from " + data);
}
}

tokenizer.consume("{");
tokenizer.enterRecursion();
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,36 +107,42 @@ protected void service(HttpServletRequest req, HttpServletResponse resp)
RuntimeData runtimeData = new RuntimeData(req);
IRateLimiter rateLimiter = container.get(KEY_PREFIX_HTTP, getClass().getSimpleName());

String contextPath = req.getContextPath();
String url = Strings.isNullOrEmpty(req.getServletPath())
? MetricLabels.UNDEFINED : contextPath + req.getServletPath();

// Check per-endpoint first to avoid consuming global IP/QPS quota for requests
// that would be rejected by the per-endpoint limiter anyway. acquirePermit()
// chooses blocking or non-blocking semantics based on rate.limiter.apiNonBlocking.
boolean perEndpointAcquired = rateLimiter == null || rateLimiter.acquirePermit(runtimeData);
boolean acquireResource = perEndpointAcquired && GlobalRateLimiter.acquirePermit(runtimeData);

String contextPath = req.getContextPath();
String url = Strings.isNullOrEmpty(req.getServletPath())
? MetricLabels.UNDEFINED : contextPath + req.getServletPath();
// int64_as_string is honored only on GET requests (URL query). POST is intentionally
// unsupported because reading the body here would consume request.getReader() and
// break downstream servlets that read it themselves.
if ("GET".equalsIgnoreCase(req.getMethod())) {
JsonFormat.setInt64AsString(Util.getInt64AsString(req));
}
// The outer try only pairs the GET setup below with the cleanup in the finally block; it
// deliberately has no catch, so that setup keeps propagating its exceptions as before.
// Everything the inner try holds keeps the catch clauses it already had.
try {
resp.setContentType("application/json; charset=utf-8");

if (acquireResource) {
Histogram.Timer requestTimer = Metrics.histogramStartTimer(
MetricKeys.Histogram.HTTP_SERVICE_LATENCY, url);
super.service(req, resp);
Metrics.histogramObserve(requestTimer);
} else {
Util.writeAuditedError(Util.RATE_LIMITER_ERROR_MSG, resp);
// int64_as_string is honored only on GET requests (URL query). POST is intentionally
// unsupported because reading the body here would consume request.getReader() and
// break downstream servlets that read it themselves.
if ("GET".equalsIgnoreCase(req.getMethod())) {
JsonFormat.setInt64AsString(Util.getInt64AsString(req));
}

try {
resp.setContentType("application/json; charset=utf-8");

if (acquireResource) {
Histogram.Timer requestTimer = Metrics.histogramStartTimer(
MetricKeys.Histogram.HTTP_SERVICE_LATENCY, url);
super.service(req, resp);
Metrics.histogramObserve(requestTimer);
} else {
Util.writeAuditedError(Util.RATE_LIMITER_ERROR_MSG, resp);
}
} catch (ServletException | IOException | BadMessageException e) {
throw e;
} catch (Exception unexpected) {
logger.error("Http Api {}, Method:{}. Error:", url, req.getMethod(), unexpected);
}
} catch (ServletException | IOException | BadMessageException e) {
throw e;
} catch (Exception unexpected) {
logger.error("Http Api {}, Method:{}. Error:", url, req.getMethod(), unexpected);
} finally {
// CRITICAL: this clear pairs with the setInt64AsString call above. Removing it
// will leak int64_as_string state across requests on reused Tomcat threads,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.tron.core.services.interfaceJsonRpcOnPBFT.JsonRpcServiceOnPBFT;
import org.tron.core.services.interfaceJsonRpcOnSolidity.JsonRpcServiceOnSolidity;
import org.tron.core.services.jsonrpc.FullNodeJsonRpcHttpService;
import org.tron.core.services.jsonrpc.TronJsonRpc;
import org.tron.core.services.jsonrpc.TronJsonRpc.FilterRequest;
import org.tron.core.services.jsonrpc.TronJsonRpc.LogFilterElement;
import org.tron.core.services.jsonrpc.TronJsonRpcImpl;
Expand Down Expand Up @@ -1558,6 +1559,57 @@ public void testBuildTransactionRejectsDeeplyNestedAbi() {
Assert.assertEquals("invalid abi", e.getMessage());
}

private static BuildArguments createSmartContractArgs(String abi, boolean visible) {
BuildArguments args = new BuildArguments();
args.setFrom("0xabd4b9367799eaa3197fecb144eb71de1e049abc");
args.setData("608060405234801561001057600080fd5b50");
args.setGas("0x3b9aca00");
args.setAbi(abi);
args.setVisible(visible);
return args;
}

private static JSONObject abiOf(TronJsonRpc.TransactionJson transactionJson) {
JSONArray contracts = transactionJson.getTransaction().getJSONObject("raw_data")
.getJSONArray("contract");
Assert.assertEquals(1, contracts.size());
return contracts.getJSONObject(0).getJSONObject("parameter").getJSONObject("value")
.getJSONObject("new_contract").getJSONObject("abi");
}

@Test
public void testBuildCreateSmartContractAbiNumericAliasMatchesFieldName() throws Exception {
// ABI.Entry: name = 3, inputs = 4; ABI.Entry.Param: name = 2, type = 3
String named = "[{\"name\":\"f\",\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],"
+ "\"type\":\"function\"}]";
String alias = "[{\"3\":\"f\",\"4\":[{\"2\":\"a\",\"3\":\"uint256\"}],"
+ "\"type\":\"function\"}]";

JSONObject fromNamed = abiOf(tronJsonRpc.buildTransaction(
createSmartContractArgs(named, false)));
JSONObject fromAlias = abiOf(tronJsonRpc.buildTransaction(
createSmartContractArgs(alias, false)));

Assert.assertEquals(fromNamed.toJSONString(), fromAlias.toJSONString());
JSONObject entry = fromAlias.getJSONArray("entrys").getJSONObject(0);
Assert.assertEquals("f", entry.getString("name"));
Assert.assertEquals("uint256",
entry.getJSONArray("inputs").getJSONObject(0).getString("type"));
}

@Test
public void testBuildCreateSmartContractAbiRejectsStringForNumericMessageField() {
// ABI.Entry.inputs = 4 is a repeated message field; a string value is not a JSON object,
// whichever address format the request uses.
String abi = "[{\"name\":\"f\",\"4\":\"1201611a0775696e74323536\"}]";
for (boolean visible : new boolean[] {false, true}) {
JsonRpcInvalidParamsException e = Assert.assertThrows(
JsonRpcInvalidParamsException.class,
() -> tronJsonRpc.buildTransaction(createSmartContractArgs(abi, visible)));
Assert.assertEquals("invalid abi", e.getMessage());
}
}

@Test
public void testWeb3ClientVersion() {
try {
Expand Down
Loading
Loading