Repository navigation
feat(API): refactor merge http servlets - #6976
SeriousCoding789 wants to merge 14 commits into
Conversation
6516c41 to
2544637
Compare
a81782d to
6de341d
Compare
waynercheung
left a comment
There was a problem hiding this comment.
Requesting changes for two reproduced regressions:
- [MUST] PBFT cursor selection now happens before rate-limit admission, which can block, so reads can go beyond the PBFT-finalized height.
- [MUST] Replacing the wrappers silently ignores legacy limiter configurations and merges per-surface quotas that used to be independent.
Details and suggested fixes are in the two inline comments.
[SHOULD] Before merging, please:
- add the independent old-route fixture discussed in the existing thread, and the startup-order test promised on #6922;
- reconcile the PR description and commit message with the current diff:
- both former SolidityNode copies already used
Util.processErrorat the merge base; MetricsServletis@HttpApiExcludedbut is still reachable at/monitor/getstatsinfo;- no fixture covers an endpoint declared on an abstract class;
- the commit body says the PBFT shielded endpoints are "restored", but they are removed;
- both former SolidityNode copies already used
- document the intentional compatibility changes, including the
IOExceptionhandling oftriggerconstantcontract/estimateenergyon SOLIDITY/PBFT.
Validation: the PR's 24 new tests and 30 related existing tests pass locally. The two additional compatibility tests that reproduce the issues above fail consistently, and the control test with the old cursor order passes.
Replace the hand-maintained servlet wiring across the FullNode, solidity and PBFT HTTP surfaces with a single registry derived from @httpapi annotations, and validate it at startup. - Introduce HttpApiRegistry as the single source of truth for which endpoint is mounted on which port, with what access level. - Drive the FullNode, solidity, SolidityNode and PBFT HTTP services from the registry instead of per-service servlet lists. - Group servlets into a subpackage and flatten the solidity and PBFT service packages. - Serve solidity, SolidityNode and PBFT endpoints with the shared base servlets; add cursor filters on the solidity and PBFT ports. - Fail fast on any registry initialisation error, and align the lite-fullnode history gate with the set of endpoints actually mounted. - Set shielded contract parameter endpoints to BUILD access, and remove the five shielded endpoints that only the PBFT port still mounted.
Reconcile the error-sanitizing changes from tronprotocol#6954 with the servlet package restructure on this branch, which left the test sources referencing classes that had moved or been removed. - Move UtilProcessErrorTest alongside Util in the servlets subpackage. - Import RateLimiterServlet in JsonRpcRateLimiterServletTest, which no longer shares a package with it. - Drop GetTransactionInfoByIdSolidityServletTest: the solidity-specific servlet it exercised was removed with the registry refactor, and its sibling GetTransactionByIdSolidityServletTest was already deleted in the same commit. The sanitized-error behaviour it asserted is covered by Util.processError and UtilProcessErrorTest.
The mount-parity tests compare each service's mounts with the registry that also drives the mounting, so an @httpapi edit that drops or moves an endpoint keeps them green. Add pre-refactor-routes.txt, the routes the four hand-written registration lists mounted on release_v4.8.3, extracted from those lists rather than from the registry. HttpApiRegistryTest now requires the derived registry to differ from it by exactly the reviewed PBFT delta: five shielded endpoints removed, two read endpoints added.
HttpApiRegistry no longer derives an audit matrix; the registry itself is the only view derived from @httpapi.
Two regressions from replacing the per-surface wrapper servlets: - Rate limiting: RateLimiterServlet keys its limiters by class name, so the shared servlets merged the quotas of the fullnode, solidity and PBFT ports and ignored *OnSolidityServlet / *OnPBFTServlet entries. Each service now tags its context with its surface, and a servlet builds and looks up one limiter per surface under the name the removed class had: <Name>OnSolidityServlet, <Name>OnPBFTServlet, and <Name>SolidityServlet for the two SolidityNode copies. reference.conf and config.conf document the names. - PBFT cursor: a PBFT cursor is an offset from the live head, and the cursor filter selected it before a rate-limit admission that can block, so a waiting request could read past the PBFT-finalized block. RateLimiterServlet now selects it after both limiters admit, and the PBFT filter is removed; the registry requires PBFT endpoints to extend RateLimiterServlet. The solidity filter stays, since that view is resolved from the live head on every read. pre-refactor-routes.txt records the class each old list mounted, and HttpApiRegistryTest checks that every endpoint keeps that limiter name.
The registry is validated and every servlet bean resolved while a service mounts its servlets, before the port is bound. Pin that order: a bean-resolution failure while mounting leaves the port free, and the same service binds it once mounting succeeds.
MetricsServlet is @HttpApiExcluded and stays mounted at /monitor/getstatsinfo; say in the annotation's javadoc that excluded means not registered through HttpApiRegistry, not unreachable.
4c759f5 to
c1cc0a4
Compare
Thanks for the careful review and for reproducing both issues. Both MUST items are fixed in f78a695; the SHOULD items are below. The branch was force-pushed to correct the first commit's message; the content of the earlier commits is unchanged. [MUST] PBFT cursor selected before rate-limit admission The PBFT port no longer installs a cursor filter.
[MUST] Per-surface rate-limit identity Kept the existing behaviour. A servlet builds and looks up one limiter per surface, under the name the removed class had: Every per-surface class the old lists mounted follows this naming. SHOULD items
|
- RateLimiterServlet: a servlet mounted on a surface its @httpapi does not declare has no limiter under that surface's name, and a missing limiter skipped per-endpoint limiting; fall back to the class-name limiter instead. - RateLimiterServletJettyTest: one servlet instance mounted in a tagged PBFT context and an untagged one, driven by real requests through jetty: the PBFT request uses the PBFT limiter and selects the cursor, the other uses the class-name limiter and no cursor. - GetTransactionByIdServletTest and GetTransactionInfoByIdServletResponseTest: the response cases of the removed SolidityNode copies, run against the base servlets that now serve those endpoints on every surface.
* release_v4.8.3: refactor(framework): decouple Manager from TronJsonRpcImpl (tronprotocol#6990) refactor(api): replace response copy wrappers with Jetty content count (tronprotocol#6982) update a new version. version name:GreatVoyage-v4.8.2.2-1-gf3e81404fe,version code:18830 (tronprotocol#7008) feat: improve node stability and execution efficiency (tronprotocol#7007) chore(p2p): internalize libp2p v2.2.9 as a local `p2p` module (tronprotocol#6992) refactor(vm): remove unreachable trace compression path (tronprotocol#6997) fix(test): isolate cross-test state leaks and stabilize flaky suites (tronprotocol#6974) refactor(config): improve startup errors and remove inactive assertions (tronprotocol#6960) ci: optimize pull request checks (tronprotocol#6938) fix(config): remove inactive RocksDB options (tronprotocol#6944) # Conflicts: # framework/src/main/java/org/tron/core/services/http/servlets/CreateShieldedTransactionWithoutSpendAuthSigServlet.java
halibobo1205
left a comment
There was a problem hiding this comment.
[MUST] Please check CI status and fix it.
waynercheung
left a comment
There was a problem hiding this comment.
[MUST] Complete the test package migration and restore CI before merge.
At 483d44c532, :framework:compileTestJava fails with 35 compilation errors; I reproduced this locally. The release_v4.8.3 merge brought in three tests that remain in org.tron.core.services.http, while the classes they use have moved to org.tron.core.services.http.servlets:
JsonFormatIdentifierTestJsonFormatUnicodeErrorTestOutboundJsonTest
Please move these tests to org.tron.core.services.http.servlets, updating both the package declarations and the source paths. Updating imports alone is insufficient: JsonFormatUnicodeErrorTest accesses package-private members of JsonFormat (unescapeText, InvalidEscapeSequence) and the protected nested Tokenizer.
After applying only this package move in a local copy, the targeted tests covering both earlier MUST fixes pass. Please rerun the affected tests and the required CI checks on the updated HEAD; I'll complete the final re-review once those checks pass.
The release_v4.8.3 merge added JsonFormatIdentifierTest, JsonFormatUnicodeErrorTest and OutboundJsonTest under org.tron.core.services.http, while JsonFormat, Util and the servlets they exercise live in org.tron.core.services.http.servlets. Move the tests next to those classes so their package-private access compiles.
* release_v4.8.3: refactor(api): remove dead WalletExtension gRPC service and config (tronprotocol#6975)
|
@halibobo1205 @waynercheung thanks fixed it late. |
waynercheung
left a comment
There was a problem hiding this comment.
Re-reviewed at 46b5be8838.
The test package migration is complete, and both earlier MUST items are addressed: PBFT cursor selection happens after both rate limiters admit the request, with cleanup on exceptional paths; legacy limiter names and per-surface quotas are preserved.
I ran 110 relevant tests against the unmodified HEAD and five additional regression tests covering the production cursor calculation and actual limiter permit isolation. All passed. The PR's own tests also caught each of 15 mutations to the cursor ordering, per-surface limiter names, surface tagging and the registry PBFT check. I also independently checked the route baseline and legacy limiter names against the current target branch. Current CI checks are green.
[NIT] The rate.limiter.http comments in reference.conf / config.conf describe the FullNode, Solidity and SolidityNode naming conventions but omit PBFT. Please also document <Name>OnPBFTServlet, e.g. GetAccountOnPBFTServlet for /walletpbft/getaccount.
No remaining blocking findings from this review. Approved.
What does this PR do?
Implements #6922.
release_v4.8.3serves the four HTTP surfaces (FULL, SOLIDITY, PBFT, and the standalone SolidityNode) with parallel sets of servlets and four hand-written registration lists. This PR collapses them onto one servlet per endpoint:*OnSolidityServlet,*OnPBFTServlet,http/solidity/*SolidityServlet). 96 of them only switch the read cursor — the class body iswalletOnSolidity.futureGet(() -> super.doGet(req, resp)), a class per endpoint; the other 2 are the standalone SolidityNode's hand-copied implementations.SolidityCursorFilteron/*. On the PBFT port,RateLimiterServletselects the PBFT cursor once the request has passed rate limiting: a PBFT cursor is an offset from the live head, so selecting it before an admission that blocks would let reads pass the PBFT-finalized block while the head advances.GetAccountOnSolidityServlet,GetAccountOnPBFTServlet, …), so existingrate.limiter.httpentries keep applying and each port keeps its own quota.reference.confandconfig.confdocument the names.@HttpApi/@HttpApiExcludeddeclared on the servlet itself, and derives a read-onlyHttpApiRegistryfrom them by classpath scan. Adding an endpoint becomes a one-place change instead of a four-place change.HttpApiRegistryis built and validated the first time a service reads it, whileHttpService.start()mounts servlets, and the check covers every surface whether or not the node enables it. Servlet beans are resolved from the Spring context in the same step; the port is opened only afterwards, byapiServer.start(). Duplicate or malformed suffixes, a non-READendpoint on a cursor surface, a PBFT endpoint that does not extendRateLimiterServlet, a servlet declaring neither annotation or both, an endpoint declared on a nested or abstract class, and a missing@Componentall fail the node withTronError(API_SERVER_INIT)instead of silently dropping an endpoint.367 files changed, +3006 / −4828.
Why are these changes required?
Duplicating an endpoint across surfaces is not free — it drifts silently, and two live examples on
release_v4.8.3came out of this work:gettransactioninfobyidnever picked up thevisible=true→convertLogAddressToTronAddressstep the base servlet has, so it returnslog[].addressin hex where FullNode returns base58.Both are "change one place, forget the other" bugs. With one servlet per endpoint and a derived registry, a surface can no longer fall behind on its own.
Behaviour differences vs
release_v4.8.3Every per-surface servlet was classified by whether its body contains
futureGet: 96 cursor delegations (cannot drift) and 2 hand-copied implementations (can). Per-surface result:gettransactioninfobyiddiffers, item 1Client-visible changes, all deliberate and worth a release note:
/walletsolidity/gettransactioninfobyid— withvisible=trueon a transaction that has logs,log[].addresschanges from hex to Tron base58, matching FullNode. This is the drift fix above;visible=falseand log-free transactions are unaffected.getmerkletreevoucherinfo,isspend,scanandmarknotebyivk,scannotebyivk,scannotebyovknow return 404 on/walletpbft/*. They were disabled on every other surface in 2020; PBFT is catching up, not regressing.getpaginatednowwitnesslistandgettransactioninfobyblocknum, which FULL / SOLIDITY / SolidityNode already expose. Pure addition.triggerconstantcontract/estimateenergyPOST on the solidity and PBFT ports — the removed wrappers caught anIOExceptionthrown by the servlet and only logged it; it now reaches Jetty, which answers with an error response. The servlets handle every request-processing failure themselves, so only a failing response writer raises it.Rate limiting is unchanged: every endpoint keeps its limiter name and its own quota on each port.
This PR has been tested by:
RateLimiterServletTest, all passing:HttpApiRegistryTest(22):http/regtest/*and assert the boot failure it produces: a servlet declaring neither annotation or both, an endpoint on a nested class or an abstract class, a duplicate(surface, suffix), a blank suffix, a/in a suffix, a*or whitespace suffix, a missing@Component, an empty surface list, a non-READendpoint on a cursor surface, and a PBFT endpoint that does not extendRateLimiterServlet. One builds a valid fixture package.pre-refactor-routes.txt— the 255 endpoints the four hand-written lists mounted onrelease_v4.8.3and the class each list mounted, extracted from those lists and not from the registry. The routes the registry derives must differ from it by exactly the reviewed PBFT delta above, and every endpoint must keep, on each port, the rate-limiter name of the class the old list mounted. An@HttpApiedit that adds, drops or moves an endpoint, or a naming change that orphans a limiter configuration, fails them.RateLimiterServletTest(7 new): per-port limiter names; each port's limiter is built from its own configuration entry; one port's traffic is admitted only by that port's limiter; on PBFT the cursor is selected only after both limiters admit, never when either rejects, and is reset even when the endpoint throws; no other port selects a cursor in the servlet.HttpApiStartupOrderTest(2): a bean-resolution failure while mounting leaves the port unbound; as a control, the same service binds its port once mounting succeeds.CursorFilterInstallationTest(4): the solidity port installs exactly one cursor filter on/*; the FULL, PBFT and standalone SolidityNode ports install none.WalletCursorFilterTest(2) andWalletOnCursorTest(1): the cursor is selected before the servlet runs and always reset.@HttpApiExcludedare unreachable, exceptMetricsServlet, which stays mounted at/monitor/getstatsinfo.Follow up
Extra details
@HttpApi/@HttpApiExcludedare deliberately not@Inherited, and the registry reads them withgetDeclaredAnnotationonly. Inheritable exposure is exactly what produced the 98 wrapper classes this PR removes — a subclass must never silently inherit its parent's surface set.