Skip to content

jsonrpc: Add generic-based dispatch for RPC handler calls#3642

Open
brbrr wants to merge 6 commits into
try/sonic-jsonfrom
refactor/generics-json-server
Open

jsonrpc: Add generic-based dispatch for RPC handler calls#3642
brbrr wants to merge 6 commits into
try/sonic-jsonfrom
refactor/generics-json-server

Conversation

@brbrr
Copy link
Copy Markdown
Contributor

@brbrr brbrr commented May 14, 2026

Note: this PR targets try/sonic-json, not the main branch

Bench comparison against try/sonic-json branch:

Test Before ns/op After ns/op ns/op delta B/op delta allocs delta
no_params 1.272µ 1.151µ ~ −5.44% −11.11%
one_scalar_pos 2.201µ 2.032µ ~ −1.77% −3.57%
one_struct_pos 2.340µ 2.123µ −9.27% ~ ~
three_pos_mixed 3.088µ 2.435µ −21.15% −11.23% −20.00%
three_named_required 3.699µ 2.710µ −26.74% −14.68% −27.78%
named_opt_missing 2.463µ 2.268µ ~ −10.18% −13.79%
named_opt_present 3.412µ 2.735µ −19.84% −15.44% −27.78%
validator_pass 2.252µ 2.315µ ~ ~ ~
validator_fail 2.922µ 3.041µ ~ ~ +2.44%
type_error 3.217µ 3.576µ ~ +2.57% +2.38%
batch_small (5 reqs) 11.96µ 11.68µ ~ −6.40% −8.55%
batch_large (50 reqs) 109.57µ 97.19µ ~ −8.58% −11.26%
response_100_structs 12.99µ 13.73µ ~ ~ −5.56%

@brbrr brbrr self-assigned this May 14, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

❌ Patch coverage is 35.45082% with 315 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.70%. Comparing base (553042a) to head (e01fcbc).

Files with missing lines Patch % Lines
rpc/v10/register.go 2.75% 105 Missing and 1 partial ⚠️
rpc/v8/register.go 11.32% 93 Missing and 1 partial ⚠️
rpc/v9/register.go 13.76% 93 Missing and 1 partial ⚠️
jsonrpc/register.go 88.23% 8 Missing and 8 partials ⚠️
jsonrpc/server.go 73.33% 2 Missing and 2 partials ⚠️
rpc/handlers.go 92.30% 0 Missing and 1 partial ⚠️

❌ Your patch check has failed because the patch coverage (35.45%) is below the target coverage (60.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@                Coverage Diff                 @@
##           try/sonic-json    #3642      +/-   ##
==================================================
- Coverage           76.00%   74.70%   -1.30%     
==================================================
  Files                 388      392       +4     
  Lines               35000    34489     -511     
==================================================
- Hits                26600    25766     -834     
- Misses               6530     6841     +311     
- Partials             1870     1882      +12     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@brbrr brbrr marked this pull request as ready for review May 14, 2026 16:05
Copilot AI review requested due to automatic review settings May 14, 2026 16:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors JSON-RPC method registration/dispatch to use generic registration helpers that build typed per-method Dispatch closures (instead of reflecting on handler signatures at request time). It updates RPC v8/v9/v10 to expose RegisterMethods() (plus param-shape structs) and adapts server/tests to the new jsonrpc.Method shape.

Changes:

  • Introduces jsonrpc.Register/RegisterC/RegisterH/RegisterCH to generate typed Dispatch handlers and param decoding/validation logic.
  • Migrates RPC v8/v9/v10 method lists to Handler.RegisterMethods() + param structs, and simplifies rpc.Handler version method assembly.
  • Updates JSON-RPC server/tests/benchmarks to the new Method API (Dispatch + ParamStructType) and removes old reflection-based invocation.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
rpc/v9/subscriptions_test.go Switches tests to register v9 methods via handler.RegisterMethods().
rpc/v9/register.go Adds v9 method registrations using generic jsonrpc registration helpers.
rpc/v9/params.go Adds v9 param structs used by generic registration/decoding.
rpc/v9/handlers.go Removes legacy methods() used only for tests.
rpc/v8/subscriptions_test.go Switches tests to register v8 methods via handler.RegisterMethods().
rpc/v8/register.go Adds v8 method registrations using generic jsonrpc registration helpers.
rpc/v8/params.go Adds v8 param structs used by generic registration/decoding.
rpc/v8/handlers.go Removes legacy methods() used only for tests.
rpc/v10/register.go Adds v10 method registrations using generic jsonrpc registration helpers.
rpc/v10/params.go Adds v10 param structs used by generic registration/decoding.
rpc/handlers.go Rebuilds versioned method lists by composing per-version RegisterMethods() + juno_version.
rpc/handlers_test.go Updates validator-compatibility tests to inspect ParamStructType instead of handler signatures.
jsonrpc/server.go Replaces reflection-based handler invocation with Method.Dispatch and pretouch via constructor-provided type lists.
jsonrpc/register.go Adds generic registration + param decoding logic (positional/named, optional via omitempty).
jsonrpc/register_internal_test.go Adds internal unit tests for the new registration/decoding pipeline.
jsonrpc/server_test.go Updates server tests to use generic registration and adjusts expected validator error paths.
jsonrpc/http_test.go Updates HTTP tests to use generic registration with param structs.
jsonrpc/websocket_test.go Updates websocket tests to use generic registration with param structs.
jsonrpc/server_bench_test.go Updates hot-path benchmarks to use generic registration with param structs.
jsonrpc/server_internal_test.go Removes tests for now-deleted reflection helper logic.
Comments suppressed due to low confidence (3)

rpc/v10/params.go:35

  • Same issue here: response_flags is intended to be optional (missing should mean default flags). Without omitempty, the new param decoder will treat it as required and return Invalid Params for callers that omit it.
type TxHashFlagsParams struct {
	TransactionHash *felt.Felt    `json:"transaction_hash"`
	ResponseFlags   ResponseFlags `json:"response_flags"`
}

rpc/v10/params.go:47

  • response_flags for starknet_getTransactionByBlockIdAndIndex was previously optional; without omitempty it becomes required under the new registration/decoding scheme, breaking backward compatibility. Make this field optional so omitted flags decode to the zero value.
type TxByBlockIDAndIndexParams struct {
	BlockID       *BlockID      `json:"block_id"`
	Index         int           `json:"index"`
	ResponseFlags ResponseFlags `json:"response_flags"`
}

rpc/v10/params.go:64

  • response_flags on starknet_getStorageAt was previously optional; without omitempty this becomes required and existing requests that omit it will fail with Invalid Params. Mark it optional (e.g. json:"response_flags,omitempty" and/or pointer type) to preserve prior behavior.
type StorageAtParams struct {
	ContractAddress *felt.Address          `json:"contract_address"`
	Key             *felt.Felt             `json:"key"`
	BlockID         *BlockID               `json:"block_id"`
	Flags           StorageAtResponseFlags `json:"response_flags"`
}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread jsonrpc/register.go
Comment on lines +50 to +58
}
name, opts, _ := strings.Cut(tag, ",")
optional := opts == "omitempty"
plan.byName[name] = len(plan.tags)
plan.tags = append(plan.tags, name)
plan.optional = append(plan.optional, optional)
if !optional {
plan.requiredN++
}
Comment thread jsonrpc/register.go
Comment thread rpc/handlers_test.go
Comment thread rpc/v10/params.go
Comment thread rpc/v10/params.go Outdated
Comment thread rpc/v10/register.go
func (h *Handler) RegisterMethods() []jsonrpc.Method {
return []jsonrpc.Method{
jsonrpc.Register("starknet_chainId",
func(_ *jsonrpc.NoParams) (*felt.Felt, *jsonrpc.Error) { return h.ChainID() }),
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.

We wrap handler calls in closures to pass the args. Potentially, we could drop it, and pass handlers directly, but we'd need to update their signatures. I've decided not to, as the PR is big enough already, and if needed, it could be done in the follow-up.

@brbrr brbrr temporarily deployed to Development May 14, 2026 16:34 — with GitHub Actions Inactive
Comment thread rpc/v8/params.go
// on several handlers (BlockID, felt.Felt) so the param fields use
// value types where the underlying handler does.

type BlockIDParams struct {
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.

There are some inconsistencies in v8 handler params. I've decided to match these, rather than refactor/update the handler's signatures.

@brbrr brbrr temporarily deployed to Development May 14, 2026 19:25 — with GitHub Actions Inactive
@brbrr brbrr temporarily deployed to Development May 15, 2026 08:52 — with GitHub Actions Inactive
@rodrodros
Copy link
Copy Markdown
Contributor

rodrodros commented May 15, 2026

@brbrr can you do a comparison against main branch

@brbrr
Copy link
Copy Markdown
Contributor Author

brbrr commented May 15, 2026

@rodrodros bench comparison is against sonic branch. I've updated the description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants