Skip to content

fullnode: remove jsonrpc - #27907

Open
bmwill wants to merge 13 commits into
mainfrom
bmwill/remove-jsonrpc-from-fullnode
Open

fullnode: remove jsonrpc#27907
bmwill wants to merge 13 commits into
mainfrom
bmwill/remove-jsonrpc-from-fullnode

Conversation

@bmwill

@bmwill bmwill commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Description

Describe the changes or additions included in this PR.

Test plan

How did you test the new or updated feature?


Release notes

Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required.

For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates.

  • Protocol:
  • Nodes (Validators and Full nodes):
  • gRPC:
  • JSON-RPC:
  • GraphQL:
  • CLI:
  • Rust SDK:
  • Indexing Framework:

@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
sui-docs Ready Ready Preview Sep 8, 2026 6:02pm UTC
2 Skipped Deployments
Project Deployment Actions Updated
multisig-toolkit Ignored Ignored Preview Sep 8, 2026 6:02pm UTC
sui-kiosk Ignored Ignored Preview Sep 8, 2026 6:02pm UTC

Request Review

…over

Previously, the service assembled its OpenRPC document at startup from the
`Module` descriptions generated by the `open_rpc` proc macro for each API
trait, which tied the crate to the `sui-open-rpc` and `sui-open-rpc-macros`
crates that are being removed along with the fullnode JSON-RPC server.

With this commit, the document generated by those macros is checked in as
`openrpc.json` and served from `include_str!`. The `info.version` field is
patched at startup so it keeps tracking the binary version, and the method
list is trimmed to the modules that were actually registered so discovery
does not advertise, for example, the write API when no fullnode is
configured. A warning is logged for any served method the document does not
describe. The `RpcModule` trait loses its `schema()` method, and doc comments
on API parameters (which only the macro could consume) become plain comments.

The discovery test now checks that the served document is the frozen one,
filtered to the registered methods and with the version patched.
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

📋 afdocs check results

URL: https://sui-docs-2rx5khmj5-sui-foundation.vercel.app

Running checks on sui-docs-2rx5khmj5-sui-foundation.vercel.app...

Agent-Friendly Docs Check: https://sui-docs-2rx5khmj5-sui-foundation.vercel.app
Timestamp: 2026-09-08T18:06:17.181Z

llms-txt
  ✓ llms-txt-exists: llms.txt found at 1 location(s)
  ✓ llms-txt-valid: llms.txt follows the proposed structure (H1, blockquote, heading-delimited link sections)
  ✓ llms-txt-size: llms.txt is 42,829 characters (under 50,000 threshold)
  ✓ llms-txt-links-resolve: All 436 tested links resolve (436 total links)
  ✓ llms-txt-links-markdown: 434/436 links point to markdown content (100%)

markdown-availability
  ✓ markdown-url-support: 434/434 pages support .md URLs (100%)
  ✗ content-negotiation: Server ignores Accept: text/markdown header (0/434 pages return markdown)
      Learn more: https://agentdocsspec.com/spec/#content-negotiation

page-size
  ✓ rendering-strategy: All 434 pages contain server-rendered content
  ✓ page-size-markdown: All 434 pages under 50K chars (median 4K, max 48K)
  ✓ page-size-html: All 434 pages convert under 50K chars (median 4K, 0% boilerplate)
  ✗ content-start-position: 1 of 434 pages have content starting past 50% (worst 100%)
      Learn more: https://agentdocsspec.com/spec/#content-start-position

content-structure
  ✓ tabbed-content-serialization: No tabbed content detected across 434 pages
  ✓ section-header-quality: No tabbed content found; header quality check not applicable
  ✓ markdown-code-fence-validity: All 4128 code fences properly closed across 435 pages

url-stability
  ✓ http-status-codes: All 434 pages return proper error codes for bad URLs
  ✓ redirect-behavior: No redirects detected across 434 pages

agent-discoverability
  ✓ llms-txt-directive: llms.txt directive found in all 434 pages, near the top of content

observability
  ○ llms-txt-freshness: No sitemap found; cannot assess llms.txt freshness without a sitemap as ground truth
  ✗ markdown-content-parity: 113 of 434 pages have substantive content differences between markdown and HTML (avg 13% missing)
      Learn more: https://agentdocsspec.com/spec/#markdown-content-parity
  ✓ cache-header-hygiene: All 435 endpoints have appropriate cache headers

authentication
  ✓ auth-gate-detection: All 434 pages are publicly accessible
  ○ auth-alternative-access: All docs pages are publicly accessible; no alternative access paths needed

Summary
  17 passed, 3 failed, 2 skipped (22 total)

Full spec: https://agentdocsspec.com/spec/

@bmwill
bmwill force-pushed the bmwill/remove-jsonrpc-from-fullnode branch from 08c35e2 to 3beab46 Compare September 8, 2026 15:25
@bmwill
bmwill deployed to sui-typescript-aws-kms-test-env September 8, 2026 15:25 — with GitHub Actions Active
@bmwill
bmwill force-pushed the bmwill/remove-jsonrpc-from-fullnode branch from 3beab46 to c46e0c8 Compare September 8, 2026 16:00
@bmwill
bmwill deployed to sui-typescript-aws-kms-test-env September 8, 2026 16:00 — with GitHub Actions Active
config: &NodeConfig,
prometheus_registry: &Registry,
) -> Result<axum::Router> {
let traffic_controller = state.traffic_controller.clone();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anything that replaces traffic_controller?

@bmwill bmwill Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know what traffic_controller is expected to do here, but it seems like it is jsonrpc only functionality (as used in the RPC stack) and as such is no longer used anywhere in fullnodes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is an IP-based anti-abuse / rate-limiting component—not inherently specific to JSON-RPC. But the fullnode integration removed by this PR was JSON-RPC-specific.

What it does

  1. Before handling a request, checks whether the client IP is blocked (or permitted by an optional allowlist).
  2. After handling a request, records a traffic tally: client IP, request weight, and relevant errors.
  3. Background policies use those tallies to detect excessive request rates or client-error rates, then temporarily block offending IPs.
  4. It supports dry-run mode, metrics, and optional delegation of blocking to an external firewall.

In the old JSON-RPC middleware, every handled call—including transaction execution—counts toward the request-rate policy. Invalid requests, invalid parameters, and certain transaction client errors also count toward the error policy. Actual enforcement depends on configuration; having the component does not necessarily mean blocking is enabled.

Is it JSON-RPC-only?

• The controller itself: no. It lives in sui-core and operates on IPs and traffic tallies, independently of the wire protocol.
• Validator RPC: also uses it. ValidatorService still calls check() before requests and tally() afterward, on its tonic/gRPC path. See crates/sui-core/src/authority_server.rs:2149–2191.
• Fullnode JSON-RPC: had a dedicated adapter, which this PR removes.
• Fullnode public gRPC: the RpcService router does not wire in this controller. That is distinct from the validator gRPC service.

I think we just need to wire in the controller to fullnode grpc at some point?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

afaik traffic_controller as a part of fullnode <> jsonrpc was never fully rolled out

The fullnode JSON-RPC service is no longer used, so this commit finishes its
decommission. The `sui-json-rpc` server crate and its `sui-json-rpc-tests`
crate are deleted, along with `sui-open-rpc` and `sui-open-rpc-macros`, whose
only remaining consumer (`sui-indexer-alt-jsonrpc`) now serves a frozen
schema. `sui-json-rpc-api` stays for the client traits used by `sui-sdk`,
minus the `#[open_rpc]` schema attributes; the parameter doc comments that
only the macro could consume become plain comments.

In `sui-node`, the JSON-RPC router and the HTTP key-value store fallback
behind it are gone, and the HTTP server serves the gRPC/REST router alone.
The `json-rpc-address` config key is kept (it is the address that server
binds to), while `jsonrpc-server-type`, `disable-json-rpc`,
`transaction-kv-store-{read,write}-config`, `indexer-max-subscriptions`, and
the `name-service-*` overrides are removed. `NodeConfig` does not reject
unknown keys, so existing configs keep loading. Fullnodes no longer have a
traffic controller consumer, so the fullnode policy/firewall plumbing in the
swarm and test-cluster builders is removed too.

Tests that exercised the JSON-RPC service are deleted. Tests that only used
it as a transport (validator traffic control, framework upgrade canaries,
safe mode reconfiguration, serialized-signature execution) now go through the
gRPC client or the node's `AuthorityState` directly.

The readiness probes in CI and the stress docker image use the RPC server's
`/health` endpoint instead of `rpc.discover`, the version bump tooling stamps
the alt-jsonrpc `openrpc.json`, and the docs site reads that file for the
JSON-RPC reference (falling back to the legacy path on release branches that
predate the move).
The `TransactionKeyValueStore` abstraction, its HTTP-backed implementation,
and the primary/fallback combinator existed to let the fullnode JSON-RPC
server read transactions, effects, events, and checkpoints from a remote
store when they had been pruned locally. With the JSON-RPC server gone they
have no consumers, so this commit deletes them together with the
`http_kv_tool` binary and the key-value integration tests, and drops the
`AuthorityState` implementation of the store trait.

The few `AuthorityState` methods that took a key-value store now read from
the authority's own stores: `get_executed_transaction_and_effects` reads the
transaction cache, `get_transactions` reads checkpoint contents from the
checkpoint store, and `query_events` reads events from the transaction cache.
None of them needs to be async any more. The transactional test runner and
the e2e tests that built a key-value store just to call these methods are
updated accordingly.
The RocksDB `IndexStore` (`jsonrpc_index`) existed to answer the fullnode
JSON-RPC queries: transactions by address, object, or Move function, events by
sender, module, or time, owned objects, owned coins, dynamic fields, and the
address balance coin types. With the JSON-RPC server gone nothing reads it,
while every fullnode still paid to build it during execution. This commit
removes the store together with everything that fed and read it:

- The execution post-processing pipeline in `AuthorityState` (`index_tx`,
  `process_object_index`, `post_process_one_tx`, the pending post-processing
  map and semaphore, and the checkpoint executor's index batch commit), the
  event subscription streamer it also fed, the genesis owner index, the
  epoch-boundary index consistency check, the index db checkpoint, the index
  pruner, and the index-backed read accessors. The transaction cache keeps
  serving events for a transaction, which is all the transactional test
  runner needed.
- The `enable-index-processing`, `sync-post-process-one-tx`,
  `remove-deprecated-tables`, `perform-index-db-checkpoints-at-epoch-end`,
  `num-epochs-to-retain-for-indexes`, and `enable-secondary-index-checks`
  config keys, which only affected the index store. Existing configs keep
  loading because unknown keys are ignored.
- The `sui-tool db-tool` index store dump and search commands.
- Tests that asserted on the index contents, and the unit test helpers that
  read owned objects from the owner index (the deny tests now take gas coins
  from the genesis objects).

On startup a fullnode now removes a leftover `indexes` directory alongside the
`rpc-index` directory of the earlier legacy backend, so upgraded nodes reclaim
the disk that the dead index was using.
`ShardedLruCache` was only used by the JSON-RPC index store's coin and owner
caches. With that store gone nothing constructs it, so remove the module. The
`lru` dependency stays for the package object cache.
`sui-bridge` declared `sui-json-rpc-api`, `test-cluster` and `sui-cost`
declared `sui-json-rpc-types`, and `sui-move` declared a `jsonrpsee`
dev-dependency without any of them referencing the crate.
`AuthorityState::dry_exec_transaction` and `dev_inspect_transaction_block`
were thin wrappers over `simulate_transaction` that shaped the result into
the JSON-RPC response types (`DryRunTransactionBlockResponse` and
`DevInspectResults`). Nothing served them any more, so this commit removes
them along with the response building, which also drops `sui-core`'s
dependency on `sui-json-rpc-types`. It also removes the orphaned
`subscription_handler_tests.rs`, whose module went away with the event
subscription handler.

Their remaining callers were all test code, and they now use the shared
simulate path directly. A `dev_inspect_for_testing` helper in
`authority_test_utils` synthesizes the gas data the way dev-inspect did (the
reference gas price, the maximum budget, the sender as sponsor, and a mock
gas coin) so the transactional test adapter's `--dry-run` and
`--dev-inspect` commands, the transaction fuzzer, and the unit and e2e
tests keep their behavior. The adapter now builds its summaries from the
raw effects, rendering execution failures the way the JSON-RPC effects did,
so the expected outputs of the 44 transactional tests that use those flags
are unchanged. Unit tests that asserted on the JSON-RPC `abort_error`
rendering lose that part, since it belongs to the response types rather
than to execution. `SimulateTransactionResult` derives `Debug` so tests can
unwrap it.
Both tools drove remote fullnodes through the JSON-RPC client in `sui-sdk`,
which is being removed. `sui-replay` backed the `sui-tool replay` subcommand,
which goes with it; the `sui replay` CLI command is built on the separate
`sui-replay-2` crate and is unaffected. `sui-rpc-loadgen` was a standalone
load generator for the fullnode JSON-RPC service, which no longer exists.

The execution encapsulation test used `sui-replay` as one of its dependency
graph roots; it now checks `sui-replay-2` instead, which also replays
transactions and must respect the protocol's execution version.
The regulated-coin Rust client and the tic-tac-toe Rust CLI were built on the
`sui-sdk` JSON-RPC client, which is being removed. The Move packages, the
TypeScript clients, and the tic-tac-toe UI stay. The publish scripts no
longer write env files for the deleted clients, and the regulated tokens
guide shows only the TypeScript client.
With the fullnode JSON-RPC service gone, `SuiClientBuilder`, `SuiClient`,
and the read, coin, event, governance, and quorum driver APIs built on the
`jsonrpsee` HTTP and WebSocket clients have no in-repo users left, and the
tools that did use them (`sui-replay`, `sui-rpc-loadgen`, and the two Rust
examples) were removed in the previous commits. This commit deletes the
client, its examples, and the `json_rpc_error` module, and trims `Error` to
the two variants that survive (`DataError`, used by `sui-bridge`, and
`InvalidSignature`) plus the BCS conversion the signature verifier needs.

What remains is the wallet and client configuration layer used by the Sui
CLI and the repository's tooling: `WalletContext`, `SuiClientConfig`, the
personal message signature verifier, the chain identifier helpers, and the
network URL constants. All of it already talked to Sui over gRPC. The crate
no longer depends on `jsonrpsee`, `sui-json-rpc-api`, `sui-json-rpc-types`,
`sui-json`, or `sui-transaction-builder`, and no longer re-exports the
`rpc_types` and `json` modules, which had no users. `sui-rosetta` declared
an unused dependency on the crate, which is dropped too.

The README and the docs pages that pointed readers at the legacy JSON-RPC
client are updated to describe what the crate provides now.
The JSON-RPC client traits it defined no longer have a client to serve, now
that the `sui-sdk` JSON-RPC client is gone. Its last remaining user was the
transactional test runner, which took the default event page size from it;
that is now a local constant in the test adapter. A couple of comments in
`sui-rpc-benchmark` that pointed at the crate's source files now name the
JSON-RPC method groups instead.
The rebase picked up the allowances change to `SuiWithdrawFrom`, which now
has a `senderAllowance` variant. The frozen OpenRPC document was generated
before that change, so update its `SuiWithdrawFrom` component to the
rendering the schema macros produced for the same type on main.
The pause test read the bridged ETH coin with a single owned-objects
query straight after the transfer's onchain status became Claimed. That
status is read from live object state, while the fullnode's owned-object
index is only updated once the claiming transaction's checkpoint has
been indexed, so the read raced the index and found no coin.

The other bridge e2e tests were switched to `wait_for_eth_coin_owned_by`
for exactly this reason in #27229; use it here too.
@bmwill
bmwill force-pushed the bmwill/remove-jsonrpc-from-fullnode branch from c46e0c8 to df2944a Compare September 8, 2026 17:58
@bmwill
bmwill deployed to sui-typescript-aws-kms-test-env September 8, 2026 17:58 — with GitHub Actions Active
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants