Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
46bab31
refactor(http): derive http endpoint registry from @HttpApi annotations
Little-Peony Sep 17, 2026
ff01362
fix(http): adapt sanitized error responses to the servlet registry
Little-Peony Sep 17, 2026
0c21d25
test(http): diff the derived registry against the pre-refactor routes
Little-Peony Sep 29, 2026
fa4b77e
docs(http): drop the removed audit matrix from HttpApi javadoc
Little-Peony Sep 29, 2026
f78a695
fix(http): rate-limit per port and select PBFT cursor after admission
Little-Peony Sep 29, 2026
cb7f914
test(http): reject an endpoint declared on an abstract class
Little-Peony Sep 29, 2026
0d7e8c9
test(http): check a failed mount leaves the http port unbound
Little-Peony Sep 29, 2026
c1cc0a4
docs(http): note an excluded servlet can still be mounted directly
Little-Peony Sep 29, 2026
741fa23
fix(http): fall back to the class-name limiter and keep servlet tests
Little-Peony Sep 29, 2026
3e8896e
Merge branch 'release_v4.8.3' into refactor_merge_http_servlets
Little-Peony Oct 9, 2026
6ff7333
fix merge
Little-Peony Oct 9, 2026
483d44c
fix merge
Little-Peony Oct 9, 2026
876afa3
test(http): move JSON format tests to servlets package
Little-Peony Oct 10, 2026
46b5be8
Merge branch 'release_v4.8.3' into refactor_merge_http_servlets
Little-Peony Oct 10, 2026
23501bf
Merge branch 'release_v4.8.3' into refactor_merge_http_servlets
Little-Peony Oct 12, 2026
3d9dee6
docs(config): document OnPBFTServlet naming for rate limiter
Little-Peony Oct 12, 2026
a14f28d
fix comments
Little-Peony Oct 12, 2026
41179b7
Merge branch 'release_v4.8.3' into refactor_merge_http_servlets
SeriousCoding789 Oct 12, 2026
7b9e91e
test(http): update imports of the moved servlet utilities
Little-Peony Oct 12, 2026
c1d32ee
Merge branch 'release_v4.8.3' into refactor_merge_http_servlets
Little-Peony Oct 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
36 changes: 35 additions & 1 deletion common/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -454,22 +454,56 @@ rate.limiter = {
# If no strategy is configured for an endpoint, QpsRateLimiterAdapter with
# qps=1000 is applied automatically.

# Per-servlet HTTP rate limits. component is the servlet class simple name.
# Per-servlet HTTP rate limits. Each port limits an endpoint separately, and component names the
# endpoint on one port:
# fullnode port (/wallet/*) the servlet class simple name, e.g. GetAccountServlet
# solidity port (/walletsolidity/*) <Name>OnSolidityServlet, e.g. GetAccountOnSolidityServlet
# pbft port (/walletpbft/*) <Name>OnPBFTServlet, e.g. GetAccountOnPBFTServlet
# standalone SolidityNode the servlet class simple name as fullnode port, except
# GetTransactionByIdSolidityServlet and
# GetTransactionInfoByIdSolidityServlet
http = [
# fullnode port, /wallet/getnowblock
# {
# component = "GetNowBlockServlet",
# strategy = "GlobalPreemptibleAdapter",
# paramString = "permit=1"
# },
# fullnode port, /wallet/getaccount
# {
# component = "GetAccountServlet",
# strategy = "IPQPSRateLimiterAdapter",
# paramString = "qps=1"
# },
# fullnode port, /wallet/listwitnesses
# {
# component = "ListWitnessesServlet",
# strategy = "QpsRateLimiterAdapter",
# paramString = "qps=1"
# },
# solidity port, /walletsolidity/getaccount
# {
# component = "GetAccountOnSolidityServlet",
# strategy = "IPQPSRateLimiterAdapter",
# paramString = "qps=1"
# },
# solidity port, /walletsolidity/triggerconstantcontract
# {
# component = "TriggerConstantContractOnSolidityServlet",
# strategy = "GlobalPreemptibleAdapter",
# paramString = "permit=2"
# },
# standalone SolidityNode, /walletsolidity/getaccount
# {
# component = "GetAccountServlet",
# strategy = "IPQPSRateLimiterAdapter",
# paramString = "qps=5"
# }
# standalone SolidityNode, /walletsolidity/gettransactionbyid
# {
# component = "GetTransactionByIdSolidityServlet",
# strategy = "IPQPSRateLimiterAdapter",
# paramString = "qps=5"
# }
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
import org.tron.core.config.args.Args;
import org.tron.core.db.RevokingDatabase;
import org.tron.core.db2.core.SnapshotManager;
import org.tron.core.services.interfaceOnPBFT.HttpApiOnPBFTService;
import org.tron.core.services.interfaceOnPBFT.RpcApiServiceOnPBFT;
import org.tron.core.services.interfaceOnPBFT.http.PBFT.HttpApiOnPBFTService;
import org.tron.core.services.interfaceOnSolidity.HttpApiOnSolidityService;
import org.tron.core.services.interfaceOnSolidity.RpcApiServiceOnSolidity;
import org.tron.core.services.interfaceOnSolidity.http.solidity.HttpApiOnSolidityService;

@Slf4j(topic = "app")
@Configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
import org.tron.core.exception.VMIllegalException;
import org.tron.core.exception.ZksnarkException;
import org.tron.core.metrics.MetricsApiService;
import org.tron.core.services.http.Util;
import org.tron.core.services.http.servlets.Util;
import org.tron.core.utils.TransactionUtil;
import org.tron.core.zen.address.DiversifierT;
import org.tron.core.zen.address.IncomingViewingKey;
Expand Down
16 changes: 16 additions & 0 deletions framework/src/main/java/org/tron/core/services/WalletOnCursor.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ public void futureGet(Runnable runnable) {
}
}

/**
* Selects this view's cursor on the current thread until the returned scope is closed, for a
* body that throws checked exceptions and so cannot run through {@link #futureGet}.
*/
public CursorScope selectCursor() {
dbManager.setCursor(cursor);
return dbManager::resetCursor;
}

/** Resets the current thread's cursor to HEAD when closed. */
public interface CursorScope extends AutoCloseable {

@Override
void close();
}

public interface TronCallable<T> extends Callable<T> {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,10 @@ public static Set<String> getFilterPaths() {
filterPaths.add("/wallet/getblockbylatestnum");
filterPaths.add("/wallet/getblockbylimitnext");
filterPaths.add("/wallet/getblockbynum");
filterPaths.add("/wallet/getmerkletreevoucherinfo");
filterPaths.add("/wallet/gettransactionbyid");
filterPaths.add("/wallet/gettransactioncountbyblocknum");
filterPaths.add("/wallet/gettransactioninfobyid");
filterPaths.add("/wallet/gettransactionreceiptbyid");
filterPaths.add("/wallet/isspend");
filterPaths.add("/wallet/scanandmarknotebyivk");
filterPaths.add("/wallet/scannotebyivk");
filterPaths.add("/wallet/scannotebyovk");
filterPaths.add("/wallet/totaltransaction");
filterPaths.add("/wallet/gettransactioninfobyblocknum");
filterPaths.add("/wallet/getmarketorderbyaccount");
Expand All @@ -61,14 +56,9 @@ public static Set<String> getFilterPaths() {
filterPaths.add("/walletsolidity/getblockbylatestnum");
filterPaths.add("/walletsolidity/getblockbylimitnext");
filterPaths.add("/walletsolidity/getblockbynum");
filterPaths.add("/walletsolidity/getmerkletreevoucherinfo");
filterPaths.add("/walletsolidity/gettransactionbyid");
filterPaths.add("/walletsolidity/gettransactioncountbyblocknum");
filterPaths.add("/walletsolidity/gettransactioninfobyid");
filterPaths.add("/walletsolidity/isspend");
filterPaths.add("/walletsolidity/scanandmarknotebyivk");
filterPaths.add("/walletsolidity/scannotebyivk");
filterPaths.add("/walletsolidity/scannotebyovk");
filterPaths.add("/walletsolidity/gettransactioninfobyblocknum");
filterPaths.add("/walletsolidity/getmarketorderbyaccount");
filterPaths.add("/walletsolidity/getmarketorderbyid");
Expand All @@ -84,14 +74,10 @@ public static Set<String> getFilterPaths() {
filterPaths.add("/walletpbft/getblockbylatestnum");
filterPaths.add("/walletpbft/getblockbylimitnext");
filterPaths.add("/walletpbft/getblockbynum");
filterPaths.add("/walletpbft/getmerkletreevoucherinfo");
filterPaths.add("/walletpbft/gettransactionbyid");
filterPaths.add("/walletpbft/gettransactioncountbyblocknum");
filterPaths.add("/walletpbft/gettransactioninfobyid");
filterPaths.add("/walletpbft/isspend");
filterPaths.add("/walletpbft/scanandmarknotebyivk");
filterPaths.add("/walletpbft/scannotebyivk");
filterPaths.add("/walletpbft/scannotebyovk");
filterPaths.add("/walletpbft/gettransactioninfobyblocknum");
filterPaths.add("/walletpbft/getmarketorderbyaccount");
filterPaths.add("/walletpbft/getmarketorderbyid");
filterPaths.add("/walletpbft/getmarketpricebypair");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.tron.core.services.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.tron.core.db.Manager;
import org.tron.core.db2.core.Chainbase;

@Component
public class SolidityCursorFilter extends WalletCursorFilter {

@Autowired
public SolidityCursorFilter(Manager dbManager) {
super(dbManager, Chainbase.Cursor.SOLIDITY);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.tron.core.services.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.tron.core.db.Manager;
import org.tron.core.db2.core.Chainbase;

/**
* Selects which state view the http servlets on this port read from.
*
* <p>The read cursor is a per-thread setting ({@code ThreadLocal} in {@code Chainbase}): it only
* decides from which snapshot the current thread starts its reads, and has no effect on any
* other thread. This filter sets the cursor before the servlet runs, so the same stateless
* servlet beans can serve {@code /wallet} (HEAD) and {@code /walletsolidity} (SOLIDITY) without
* per-port subclasses. The SOLIDITY view is resolved from the live head on every read, so it can
* be selected before rate limiting; the PBFT view is an offset from the head and is selected by
* {@code RateLimiterServlet} once the request is admitted.
*
* <p>The cursor is always reset to HEAD in a finally block: jetty pools its worker threads, and
* a leftover cursor would leak into the next request served by the same thread. Only read-only
* endpoints may be mounted behind this filter — write paths must run with the HEAD cursor.
*/
public abstract class WalletCursorFilter implements Filter {

private final Manager dbManager;
private final Chainbase.Cursor cursor;

protected WalletCursorFilter(Manager dbManager, Chainbase.Cursor cursor) {
this.dbManager = dbManager;
this.cursor = cursor;
}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
// do nothing
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
try {
dbManager.setCursor(cursor);
Comment thread
SeriousCoding789 marked this conversation as resolved.
filterChain.doFilter(servletRequest, servletResponse);
} finally {
dbManager.resetCursor();
}
}

@Override
public void destroy() {
// do nothing
}
}
Loading
Loading