Repository navigation
feat(framework): support admin JSON-RPC over IPC and HTTP - #6979
Conversation
Add HTTP and Unix-domain-socket transports for the shared Admin JSON-RPC API, with an attach console for trusted node operators. Include transport configuration, socket permissions, request handling, bounded client lifecycle, and startup isolation regression tests.
…ken count restrict
There was a problem hiding this comment.
Re-reviewed the complete PR at decdf68. The Admin code is unchanged since f2ce52e; the new commits only merge release_v4.8.3, and the build.gradle conflict resolution keeps the junixsocket/JLine dependencies. The previous socket-deletion, parse-error and client-validation issues are fixed. The explicit no-batch policy and the configuration layout are accepted.
The targeted regression tests and the framework Checkstyle checks pass locally on JDK 17. Additional probes confirm two remaining [MUST] issues — request-envelope validation and request id/notification handling; see the inline comments. A separate [SHOULD] covers crash recovery: SIGKILL leaves the IPC directory behind, so a node using the same persistent socket root cannot restart.
Please fix the two [MUST] items with HTTP/IPC regression tests. The crash-recovery tradeoff should either be fixed or explicitly agreed.
[SHOULD] Please document the JLine packaging/version choice, the OS/architecture/JDK combinations you tested, and junixsocket's native-library loading requirements. In particular, please verify deployment with a noexec temporary directory and document -Dorg.newsclub.net.unix.library.tmpdir=<directory> where needed. Version 2.10.1 falls back to other locations, so a noexec /tmp alone does not mean IPC startup will fail.
Please also link follow-up issues for the runtime-parameter and Peer management commands.
| import com.googlecode.jsonrpc4j.JsonRpcParam; | ||
| import org.tron.core.exception.jsonrpc.JsonRpcInvalidParamsException; | ||
|
|
||
| public interface AdminJsonRpc { |
There was a problem hiding this comment.
[QUESTION] Could you clarify the requirements and design boundaries for this Admin API?
-
The PR mentions runtime parameter export and peer management as follow-ups. Which commands are planned? Will they be read-only, or will they also change parameters, disconnect peers, or perform other state-changing operations? Is the primary audience local operators, automation scripts, or remote management systems?
-
What would the operator workflow look like? Which distinct requirements do HTTP, IPC, and the interactive console address, and do all three have concrete use cases? With only an example command available today, is it necessary to introduce all three components, together with JLine and junixsocket, in this PR?
-
What is the authentication model? IPC can rely on OS user permissions, but HTTP currently has no credentials or token authentication. If an operator accidentally exposes it externally, or a machine on the management network is compromised, would anyone with endpoint access be able to execute every administrative command? Are the bind address, Host validation, and warning log sufficient protection for the planned capabilities?
-
Have you considered a simpler initial approach: a local HTTP Admin endpoint protected by a random session key/token generated at node startup, with curl or small scripts providing interactive and automated access? If that does not meet the requirements, what essential advantages do IPC and the dedicated console provide? Token storage, rotation, and secure transport for remote access would also need to be defined.
-
As administrative commands are added, how will permissions and operational impact be controlled? Should read-only and state-changing commands share the same privileges? Will there be an audit trail to help investigate operator mistakes or credential compromise?
It would help to establish the intended capabilities, operator workflows, and security model first, then decide which parts of this infrastructure are necessary now and which could be delivered incrementally.
There was a problem hiding this comment.
Thanks for your concern. I am glad to share it.
-
Planned capabilities and intended users
Runtime parameter export is intended to provide read-only access to non-sensitive runtime settings. Peer management is specified in #6989, including
admin_addPeer,admin_removePeer,admin_disconnectPeer,admin_listActivePeers,admin_blockIp,admin_unblockIp, andadmin_listBlockedIps. These include both queries and state-changing operations. Runtime parameter modification is a separate capability and is not introduced by this PR.The primary users are node operators and automation scripts, with optional integration into management systems through HTTP.
-
Operator workflows and transport choices
The two transports support the workflows described in #6497. HTTP supports standard clients such as curl and integration with operational tooling. IPC supports local administration through OS permissions without opening a network port. The console is an IPC client providing typed commands, help, completion, and --exec for scripts. Its process-specific socket path also helps operators select the intended FullNode when several instances run on one host.
junixsocket provides Unix-domain socket support while retaining Java 8 compatibility, and JLine provides the interactive console. We intend to deliver this shared foundation in the current PR, then add operational methods separately.
-
Security and authentication model
The current model relies on OS permissions for IPC and deployment-level network/IP access restrictions for HTTP. Admin HTTP is disabled by default and binds to loopback by default. Remote exposure requires explicit external access controls; the Host allowlist and warning log are not authentication mechanisms.
Within this trusted-operator deployment model, we consider OS and network access controls sufficient for the intended access boundary, with substantially less implementation and operational complexity than introducing built-in JWT authentication.
This does mean that a caller who gains access to the HTTP endpoint can invoke all exposed Admin methods. Compromise of an allowed management host is outside the protection provided by IP restrictions alone. Deployments requiring an additional authentication boundary can use an authenticated reverse proxy or mTLS.
-
Startup-generated key/token alternative
Yes, we considered generating an access key at node startup. The difficulty is its operational lifecycle: securely storing the key, controlling who can retrieve it, distributing it to scripts or management systems, and updating those consumers whenever the key changes after a restart. We found this cumbersome for the intended operator workflow.
IPC reuses existing OS permissions without introducing an application credential lifecycle. HTTP remains available for standard tooling under externally enforced access controls. We therefore prefer the current approach and do not plan to add a startup-generated token in this PR.
-
Permissions, operational impact, and auditing
HTTP and IPC intentionally expose the same interface today. Access is controlled at the transport and deployment level, without separate method groups or privileges for read-only and state-changing calls. We have no immediate plan to split the interface, but may revisit this as access requirements evolve.
Individual operations will define their validation, idempotency, persistence, and interaction with existing configuration, as specified for peer management in [Feature] Support runtime peer management and manual IP blocking through Admin APIs #6989.
As agreed in the audit-logging discussion, structured audit events will be added before introducing state-changing methods. They should capture the transport, method, available caller context, and outcome—including notifications—without recording raw parameters or results.
waynercheung
left a comment
There was a problem hiding this comment.
Re-checked the updated PR at f40299f, including its integration with release_v4.8.3. The selected regression tests and framework Checkstyle checks pass locally on macOS arm64 with JDK 17, and CI is green. The earlier request-envelope and ID/notification fixes remain intact, and the parameter-binding change correctly distinguishes -32602 from sanitized -32603 responses.
[MUST] The chunked request-size issue still needs to be fixed before merging this PR. I reproduced it again with Jetty's LocalConnector: with a 1024-byte limit, a valid 512-byte body succeeds with Content-Length but returns 413 with either single-chunk or multi-chunk encoding. Please open the separate fix you mentioned, link it here, incorporate it before merging this PR, and restore limit-1, limit and limit+1 coverage for both chunked forms. Oversized requests should also be rejected before any Admin method is invoked.
Verified the fatal-error safeguard added in 9334b4f: Admin HTTP now returns an empty 500 response without exposing exception details, while preserving the original Error. The cleanup and Jetty regression tests pass. I understand that transport-level TronError exit-policy unification is deferred; that decision should remain explicit when future Admin operations introduce runtime TronError paths.
[SHOULD] Please complete the dependency notes in the PR description: the JLine packaging/version rationale, tested OS/architecture/JDK combinations, and junixsocket's native-library loading requirements. Include the results of testing with a noexec temporary directory and document -Dorg.newsclub.net.unix.library.tmpdir=<directory> where needed.
Please also link the follow-up items from the PR description: #6989 for Peer management, runtime-parameter export, automatic IPC stale-directory recovery, and the chunked-size fix. Carry the agreed audit-logging requirement into #6989's acceptance criteria.
@waynercheung Thanks for the review. Here are the updates and proposed follow-up arrangements:
|
| JsonNode response; | ||
| try { | ||
| response = super.handleJsonNodeRequest(request).getResponse(); | ||
| } catch (MismatchedInputException e) { |
There was a problem hiding this comment.
[SHOULD] After merging #7030 from the latest release_v4.8.3, jsonrpc4j 1.7 now directly returns -32602 / Failed to read method parameter at index N for parameter type conversion failures, bypassing the existing fallback handling in AdminJsonRpcRequestHandler. As a result, assertions expecting the previous error message will cause both HTTP and IPC tests to fail.
The public JSON-RPC contract tests on the release branch already accept the new message. Please align the Admin tests accordingly, while preserving checks for the error code, original request ID, absence of additional error data, no response to notifications, and no invocation of the underlying RPC method.
Please also preserve the original messages for business validation exceptions rather than overriding all -32602 responses with a generic message.
There was a problem hiding this comment.
Thanks for catching this. Fixed in 6d51360. The shared Admin HTTP/IPC test now checks the jsonrpc4j 1.7 index-specific conversion message for positional and named parameters, while retaining assertions for -32602, the original request ID, no additional error data, silent notifications, and no RPC method invocation. The existing business-validation test still checks that its original error message is preserved. I reran AdminJsonRpcRequestTest for both transports with dependency verification enabled; all cases pass.
waynercheung
left a comment
There was a problem hiding this comment.
Approved from the code-review perspective at 6d51360. The jsonrpc4j 1.7 integration issue is fixed, and the Admin HTTP/IPC and public JSON-RPC regression tests pass locally. No new blocking code findings were identified.
I accept deferring the documented chunked request-size limitation to a separate fix. Before merging, please open and link its tracking issue, retaining the boundary-test and no-method-invocation acceptance criteria.
The other documented follow-ups remain non-blocking.
What does this PR do?
This PR adds the Admin JSON-RPC transport foundation requested by #6497. A single annotated
AdminJsonRpcinterface is shared by an HTTP endpoint and a local Unix-domain-socket service. The initialadmin_examplemethod verifies typed command dispatch and annotation-based JSON-RPC error handling; additional administrative methods can be added to the same interface.Admin HTTP and IPC accept only individual JSON-RPC requests; batch requests are not supported.
In this PR, JSON-RPC defines the shared API and message format, while HTTP and IPC are the two transports:
Admin HTTP service
The HTTP service is available to FullNode processes at
POST /adminand is disabled by default. It binds Jetty to the configured address and port. Enabling it on a non-loopback address emits a warning.The servlet validates the
Hostheader against the configured virtual-host allowlist, while accepting IPv4 and IPv6 literals. It acceptsapplication/json,application/json-rpc, andapplication/*+jsonmedia types, and rejects unsupported content types with HTTP 415. JSON-RPC parsing reuses a constrained object mapper with nesting-depth and token-count limits. JSON-RPC results, including protocol errors, use HTTP 200 responses.Admin HTTP is intended for trusted node operators. Deployments must restrict access to loopback or a controlled management network. Under this trust model, Admin HTTP intentionally does not apply the public JSON-RPC
node.jsonrpc.maxResponseSizelimit. The existing HTTP request-size limit and JSON nesting-depth and token-count limits still apply.Known limitation: the shared HTTP request-size accounting has a pre-existing issue with chunked requests that can reject bodies below the configured limit. This PR does not introduce or fix that issue. A separate fix is planned; see Follow-up for the proposed scheduling.
The HTTP transport configuration is:
Admin IPC service
The IPC service is also FullNode-only and disabled by default. By default it creates an endpoint at:
When non-empty,
node.admin.ipc.socketDirectoryselects another socket root and must be an existing absolute directory on a POSIX-compatible filesystem; an empty value usesoutput-directory. The service creates the privateipcdirectory with owner-only access and sets the socket to0600. Startup fails if the privateipcpath already exists. Confirm that no node is using it, then remove it manually before retrying.The complete encoded socket path is limited to 100 bytes for portability across supported Unix-domain-socket implementations. If the path is longer, startup fails with guidance to configure a shorter
node.admin.ipc.socketDirectory; it does not silently relocate the endpoint.IPC uses newline-delimited, single-line JSON-RPC messages and the same
AdminJsonRpc, error resolver, and constrained JSON mapper as HTTP. Request size is bounded bynode.jsonrpc.maxMessageSize, shared with public JSON-RPC HTTP, whose default is 4 MiB. Each client has a ten-minute idle timeout. The bounded client executor supports concurrent console sessions and immediately closes connections that arrive after all handlers are occupied. Unexpected accept failures use a five-second retry delay.Startup failures and normal shutdown both clean up owned sockets and the private directory. Shutdown closes active clients before stopping executors so blocked native socket reads do not unnecessarily delay node termination.
junixsocket extracts and loads a native library, using
java.io.tmpdirby default. If loading fails because the directory is mounted withnoexec, it can fall back touser.homeanduser.dir. Native-library loading requires a writable extraction location on a filesystem that permits executable mappings.If these locations are unsuitable, set
-Dorg.newsclub.net.unix.library.tmpdir=<directory>before-jar. The directory must already exist and be writable by the process, and its filesystem must permit executable mappings. Configure this JVM option independently for the node and IPC client when needed. It controls native-library extraction and does not change the IPC socket location.IPC console
The FullNode executable can attach to an active node without initializing another node instance:
A single command can be executed for scripting:
Attach mode is handled immediately after CLI argument parsing and before
CommonParameter, Logback, database, witness, or node services are initialized.--execrequires--attach, an empty socket path is rejected, and attach mode cannot be combined with--config.The JLine console derives command names, parameter names, and parameter types from the annotated Admin API. It supports quoted arguments, typed JSON conversion, sorted help, canonical command completion, formatted JSON results,
help,exit, andquit. One-shot execution returns a non-zero process status for invalid commands, JSON-RPC errors, communication failures, disconnection before a response, or the 30-second response timeout. This timeout does not cover connection establishment or set an overall --exec deadline; unattended scripts should enforce their own overall timeout.Request construction
Interactive input and
--execuse the same command parser. It handles quoted arguments, resolves the method from the annotated Admin API, checks the argument count, and converts values to the declared parameter types. The client then builds a JSON-RPC 2.0 request with the canonical method name, a positionalparamsarray, and an incrementing numericid, and sends it as a single JSON line followed by a newline. Local commands such ashelp,exit, andquitare handled without sending an RPC request.For example, the first request for
admin_example "hello world" secondis:{"jsonrpc":"2.0","method":"admin_example","params":["hello world","second"],"id":1}Result extraction
The IPC server sends a complete JSON-RPC response. The console validates the response envelope and, when it contains
result, displays only that value: strings are printed without surrounding quotes, objects and arrays are formatted as JSON, and numbers, booleans, andnullretain their JSON representation. For example,{"jsonrpc":"2.0","id":1,"result":"done"}is displayed asdone.JSON-RPC errors are displayed as
Error <code>: <message>, while malformed responses produceInvalid IPC response.. In--execmode, the client also verifies that the response ID matches the request ID, writes results to stdout, and writes errors to stderr with a non-zero exit status.Supporting changes
HttpServiceadds configurable listen-address binding. Public JSON-RPC and both Admin transports reuse the constrained JsonRpcMapper. Admin HTTP uses JsonRpcMediaType to validate request media types; public JSON-RPC request Content-Type handling remains unchanged.JLine, already used for plugin progress bars in v4.8.2, now also supports the Admin console. Both modules use
org.jline:jline:3.30.17:jdk8for Java 8 compatibility; JLine 4.x requires Java 11+.Unix-domain-socket support uses
com.kohlschutter.junixsocket:junixsocket-core:2.11.1, the current latest release, which supports Java 8 and newer. See the junixsocket compatibility documentation. Dependency verification metadata has been updated, and obsolete JLine and junixsocket entries have been removed.GitHub Advisory Database checks on 2026-10-14 found no known advisories affecting JLine 3.30.17 or junixsocket 2.11.1, including its
commonandnative-commondependencies.Why are these changes required?
Administrative operations need a local, scriptable interface without starting a second node or exposing the existing public APIs as privileged management endpoints. The Unix-domain socket provides a private local transport, while the optional HTTP endpoint supports controlled integration when explicitly enabled.
Sharing one typed Admin API across both transports keeps command names, parameters, results, and JSON-RPC errors consistent. Explicit address binding, virtual-host validation, parser limits, filesystem permissions, bounded clients, and deterministic cleanup provide safer operational defaults.
Testing
The PR adds or updates tests covering:
The related Admin HTTP, IPC, CLI, configuration, and FullNode tests, together with production and test checkstyle checks, passed during development.
Dependency-upgrade validation covered the following environments and scopes:
available()smoke testsnoexecloading checksAn additional JDK 8 run compiled the IPC client sources and passed all 42 client tests, plus a JLine terminal/line-reader smoke test. JLine validation also covered the plugins’ progress-bar tests and Toolkit/ArchiveManifest packaging. Strict dependency verification confirmed that the compile, runtime, and test classpaths of both
frameworkandpluginsresolve onlyjline-3.30.17-jdk8.jar.On Linux ARM64/JDK 17,
noexecchecks confirmed fallback loading, expected failure when all candidate directories prohibit executable mappings, and recovery using-Dorg.newsclub.net.unix.library.tmpdir=<directory>. Native x86_64noexecvalidation remains pending.Follow-up
success: false; raw parameters, response payloads, credentials, and sensitive paths are excluded.limit-1,limit, andlimit+1coverage for Content-Length, single-chunk, and multi-chunk requests, and reject oversized requests before invoking an Admin method. The tracking link will be added when the separate PR is opened.TronErrorexit-policy unification is deferred and should be revisited before introducing Admin operations that require it. Admin HTTP currently returns an empty HTTP 500 response for fatal errors without exposing exception details, while preserving the originalError.--execin low-priority.