feat(API): refactor merge http servlets - #20
SeriousCoding789 wants to merge 10 commits into
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
124abb6 to
04a92f7
Compare
4c26109 to
9e23145
Compare
|
|
||
| @Component | ||
| @Slf4j(topic = "API") | ||
| @HttpApi(value = "getaccount", access = Access.READ, |
There was a problem hiding this comment.
[MUST] The rate limiter is keyed by the servlet class name, so all surfaces now share one limiter instance.
Before this PR each surface had its own wrapper servlet class (e.g. GetAccountOnSolidityServlet, GetAccountOnPBFTServlet), so the http_<class> keys were distinct and every port had its own permit pool. After the merge, a single GetAccountServlet bean is mounted on /wallet, /walletsolidity and /walletpbft — the same simple name resolves to the same RateLimiterContainer entry, giving one shared QPS budget across three ports. Total capacity drops from 3×qps to 1×qps.
Also, existing rate.limiter.httpMap entries referencing the old *OnSolidity / *OnPBFT class names no longer match anything and are silently ignored (addRateContainer falls back to the default adapter).
Suggestion: key the limiter by surface + suffix (or request context path), and/or document the httpMap key migration in the PR.
Signed-off-by: Vaibhav Srivastava <vaibhavsri1712@gmail.com>
Clarify trigger behavior, log retention, Solidity API availability, and account-name rules.
* feat: optimize delegate and undelegate instruction handling (tronprotocol#6920) Co-authored-by: Asuka <yanghang8612@163.com> * perf: optimize jump table initialization and reuse (tronprotocol#6943) Co-authored-by: Asuka <yanghang8612@163.com> * feat: refine contract deployment transaction validation (tronprotocol#6945) Co-authored-by: Asuka <yanghang8612@163.com> * ci: run single-node smoke only and disable multinode (backport tronprotocol#6908 to release_v4.8.2.2) (tronprotocol#6953) Backport of tronprotocol#6908 to the release_v4.8.2.2 branch so CI passes there: - Switch the single-node integration CI to the smoke test subset (--clean --smoke instead of the full suite), renaming workflow, job, steps, and report artifact from "Full" to "Smoke" - Remove the multinode integration CI workflow entirely; the full single-node suite and the multinode suite are unstable in CI today (hardened assertions don't match the troninfra/troninfra-ci image fixture), causing failures unrelated to PR code --------- Co-authored-by: ouy95917 <ouy95917@gmail.com> Co-authored-by: Asuka <yanghang8612@163.com> Co-authored-by: Jeremy Zhang <50477615+warku123@users.noreply.github.com>
…,version code:18828 (tronprotocol#6955)
chore(branch): merge master into develop
…#6930) Node and network API responses populated two fields from the wrong source values because of copy-and-paste mapping errors. Map needSyncFromPeer from the corresponding peer state and assign UDP inbound traffic to the udpInTraffic protobuf field.
…me (tronprotocol#6950) * chore(deps): upgrade grpc-java from 1.83.0 to 1.83.1 1. bump grpcVersion to 1.83.1 to pick up the upstream fix for grpc/grpc-java#12930 (PR grpc/grpc-java#12942), which enforces connection.remote().maxActiveStreams(maxStreams) at handler startup 2. drop GrpcNettyMaxConcurrentStreamsLimiter, the local protocol-negotiator shim that applied the same limit while 1.83.0 left the remote endpoint unbounded until the client acknowledged SETTINGS * chore(deps): upgrade jackson from 2.18.6 to 2.18.10 bump jackson-databind from 2.18.6 to 2.18.10 to pick up cumulative fixes from the 2.18.x line * chore(deps): upgrade logback to 1.3.16 and slf4j to 2.0.17 1. bump logback-classic from 1.2.13 to 1.3.16 and slf4j-api, jcl-over-slf4j, jul-to-slf4j from 1.7.36 to 2.0.17; logback 1.3 requires the slf4j 2.0 provider model, and 1.3.16 is the last 1.3.x release and the ceiling for the x86_64 JDK 8 build, since 1.5.x requires JDK 11 2. rename DelayingShutdownHook to DefaultShutdownHook in the toolkit logback.xml; logback 1.3 removed the old class and only auto-maps the legacy name with a startup warning 3. drop the CONSOLE appender from the toolkit logback.xml; no logger ever referenced it, so it never emitted output on 1.2 either, and logback 1.3 now flags it with an unreferenced-appender warning 4. accept one known 1.3.x behavior change: SizeAndTimeBasedRollingPolicy now throttles its maxFileSize comparison to once per 60s (SimpleInvocationGate) instead of the adaptive ~100-800ms gate of 1.2.13, so under sustained heavy logging a file can overshoot the 500MB cap by up to 60s of writes before the %i rollover fires; time-based rollover and totalSizeCap/maxHistory cleanup are ungated and unaffected 5. note for operators running a custom --log-config file: well-formed 1.2-era configs using standard elements keep working unchanged (jmxConfigurator degrades to an ignored-property warning, the legacy shutdown hook name is auto-mapped), and malformed XML still fails fast via TronError(LOG_LOAD) exactly as on 1.2; however, a config that references an uninstantiable class (e.g. a custom appender missing from the classpath) now aborts the whole appender-ref phase instead of losing just that one appender, so the node starts with no log output while the ERROR statuses are printed to stdout by LogService * chore(deps): upgrade commons-lang3/collections4 and drop commons-math 1. bump commons-lang3 from 3.4 to 3.20.0; the runtime classpath already resolved 3.18.0 through libp2p 2.2.9's transitive requirement, so align the declaration with what actually ships and move past the CVE-2025-48924 range that the nominal 3.4 still sits in 2. bump commons-collections4 from 4.1 to 4.6.0 3. remove commons-math 2.2; no source file imports org.apache.commons.math and nothing else in the dependency graph requests it * chore(deps): remove joda-time and use JDK time APIs 1. drop the joda-time 2.3 dependency. 2. replace the six new DateTime(millis) log-formatting call sites in DynamicPropertiesStore, DposTask and DposService with a new Time.getIsoTimeString helper backed by java.time; its formatter (yyyy-MM-dd'T'HH:mm:ss.SSSXXX in the system zone) reproduces joda's DateTime.toString() output byte for byte where the JDK and joda 2.3 time-zone databases agree (UTC nodes are unaffected); zones whose rules changed after joda's 2013-era tzdb, e.g. Europe/Moscow, now render the corrected offset for the same instant. 3. replace DateTime.now() day arithmetic in four test classes with the java.time equivalent, ZonedDateTime.now().minusDays(n)/plusDays(n) .toInstant().toEpochMilli(), keeping joda's calendar semantics one-to-one, and map plain DateTime.now().getMillis() to System.currentTimeMillis()
* feat(api): sanitize HTTP API error responses
Standard HTTP error paths used to expose internal details to clients:
Util.processError prefixed every message with the Java exception class
name, several servlets printed raw Throwable.getMessage() directly, and
the two solidity query endpoints returned bare-text error bodies.
Centralize the client-facing text decision in Util.processError:
* keep the raw non-blank message only for the exact runtime types
JsonFormat.ParseException, ContractValidateException and
MaintenanceUnavailableException; a null, empty or whitespace-only
message falls back to "internal server error"
* preserve the events-deprecation message only for the exact
IllegalArgumentException type carrying EVENTS_DEPRECATED_MSG
* write the fixed rate-limit and INVALID address messages, along with
existing GetBlock validation messages, through the package-private
writeAuditedError helper; these audited callers bypass exception
classification, and printErrorMsg is private to the shared writer
* return {"Error":"internal server error"} for every other exception,
with no exception class name
Client-visible changes:
* all processError-based error bodies lose the "class <FQCN> : "
prefix; unclassified raw messages become "internal server error"
* the rate-limit rejection body becomes
{"Error":"lack of computing resources"} on every endpoint extending
RateLimiterServlet, including full-node, solidity and PBFT /jsonrpc
* gettransactionbyid / gettransactioninfobyid on solidity return
standard {"Error":...} JSON instead of bare text
* validateaddress, getBrokerage and getReward replace leaked library
messages in their failure branches with existing fixed texts; the
"INVALID address" body is now written via writeAuditedError and loses
the space after the colon
* getblock keeps its exact error bodies (refactor only)
Cover Solidity transaction and transaction-info GET/POST input errors,
backend failures, successful lookups and missing records directly with
mocked Wallet calls and in-memory requests and responses. Replace the
transaction servlet tests that accidentally exercised POST in both cases,
changed global stdout and used a shared temporary response file.
Verify both endpoint and global rate-limit rejections across the three
JSON-RPC servlet variants, including status, response body and the absence
of business dispatch on rejection.
HTTP status codes, success responses, request validation rules and
gRPC behavior are unchanged. JSON-RPC behavior is unchanged except for
the shared HTTP rate-limit response described above.
Closes tronprotocol#6936
* fix(api): keep server-side failure logging at error level
The previous commit routed four catch-all blocks through the shared
processError entry point, which logs at debug. Those four catches cover
server-side work only: getburntrx, getnodeinfo and getpendingsize read
no request parameters, and in getreward malformed addresses are already
handled by the preceding DecoderException | IllegalArgumentException
catch. Their failures therefore left no trace under the default log
configuration, where the API topic is INFO.
Add a dedicated processServerError entry point that logs at error and
then applies the same sanitization, and use it at those four call sites.
Logging the exception once inside the helper keeps a single record at
any log level, instead of pairing an error log in the servlet with the
debug log in the shared path.
The shared Exception entry point keeps debug on purpose: its callers
also cover request parsing, so an unauthenticated client can fail it
cheaply and repeatedly, and an unconditional stack trace per request
would amplify that into log pressure. Distinguishing client from server
faults on that path is the parameter/internal split tracked as follow-up
in tronprotocol#6936.
Client-facing responses are unchanged.
957c57d to
6516c41
Compare
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 restore the shielded transaction endpoints missing from the PBFT port. - Idle out held connections once maxHttpConnectNumber is reached. # Conflicts: # framework/src/main/java/org/tron/core/services/http/servlets/Util.java # framework/src/test/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServletTest.java
6516c41 to
2544637
Compare
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.
What does this PR do?
Implements tronprotocol#6922.
developserves 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). 98 of them carry no logic at all — the whole class body iswalletOnSolidity.futureGet(() -> super.doGet(req, resp)), i.e. a class per endpoint whose only job is to switch the read cursor.WalletCursorFilter+SolidityCursorFilter/PbftCursorFilter) mounted on/*of the solidity and pbft ports. Switching the cursor is a per-request, thread-level concern; it does not need a subclass per endpoint.@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.READendpoint on a cursor surface, 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.356 files changed, +2136 / −4751.
Why are these changes required?
Duplicating an endpoint across surfaces is not free — it drifts silently, and two live examples on
developcame 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
developEvery per-surface servlet was classified by whether its body contains
futureGet: 98 pure cursor delegations (cannot drift) and 2 hand-copied implementations (can). Per-surface result:Client-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.Error responses on the two former SolidityNode copies now go through
Util.processError(the standard{"Error": ...}body) instead of writing the raw exception message into the response.This PR has been tested by:
Unit Tests — 24 new tests, all passing:
HttpApiRegistryTest(17). Twelve drive one validation branch each through a fixture package underhttp/regtest/*and assert the boot failure it produces: a servlet declaring neither annotation or both, an endpoint on a nested or abstract class, a duplicate(surface, suffix), a blank suffix, a/in a suffix, a*or whitespace suffix, a missing@Component, an empty surface list, and a non-READendpoint on a cursor surface. One builds a valid fixture package. The remaining four are the mount-parity tests: each service's mounted path set equals the registry's derived set for its surface, so an endpoint cannot be declared and left unmounted, or mounted without being declared.CursorFilterInstallationTest(4) runs each service's realaddFilterand asserts solidity and pbft install exactly one cursor filter on/*, while the FULL port and the standalone SolidityNode install none — a cursor filter on either of those would take the port off HEAD.WalletCursorFilterTest(3) asserts the cursor is set beforechain.doFilterand reset infinallyincluding when the servlet throws, and that the PBFT subclass switches to the PBFT cursor rather than SOLIDITY.There is no frozen route snapshot: the registry is validated in full when the class is first touched — before Jetty binds, and for every surface whether or not the node enables it — so the invariants are enforced at boot and the tests drive the failure paths rather than re-asserting them over the live table.
Manual Testing — brought up a private chain and checked the mounted endpoint set on every port, including that endpoints marked
@HttpApiExcludedare unreachable.Follow up
Extra details
@HttpApi/@HttpApiExcludedare deliberately not@Inherited, and the registry reads them withgetDeclaredAnnotationonly. Inheritable exposure is exactly what produced the 100 wrapper classes this PR removes — a subclass must never silently inherit its parent's surface set.