Context
We use the go-playground/validator library to validate incoming RPC request structs via struct tags. The validator is integrated into the jsonrpc.Server and each RPC version has its own singleton (rpc/v10/validator.go, rpc/v9/validator.go, rpc/v8/validator.go). When a struct is a handler parameter, the server automatically calls validator.Struct() on it before the handler runs (jsonrpc/server.go#L655-L672).
You can see good examples of validate tags already in use:
Task 1: Audit all RPC handler methods for missing validation tag opportunities
Go through every handler method registered in rpc/v10/, rpc/v9/, and rpc/v8/ (you can find the full list in each version's Methods() function) and check the starkent API specification for each one of them (refs for v10, v9, and v8). For each handler, look at the input parameter structs and check:
- Are there fields that should be
required but have no validate tag?
- Are there conditional requirements (e.g., "field X is required when Type is Y") that are not expressed via
required_if, required_unless, excluded_unless, etc.?
- Are there range/size constraints (like the
min=1 on ChunkSize) that are not being enforced via tags?
For each finding, make the appropriate improvements.
Task 2: Identify and remove dead/redundant custom validation code
There is already custom validation logic that duplicates what the validate tags should handle. A clear example is in rpc/v10/simulation.go#L261-L272:
func checkTxHasSenderAddress(tx *BroadcastedTransaction) bool {
return (tx.Type == TxnDeclare ||
tx.Type == TxnInvoke) &&
tx.SenderAddress == nil
}
func checkTxHasResourceBounds(tx *BroadcastedTransaction) bool {
return (tx.Type == TxnInvoke ||
tx.Type == TxnDeployAccount ||
tx.Type == TxnDeclare) &&
tx.ResourceBounds == nil
}
These are called in prepareTransactions() (rpc/v10/simulation.go#L283-L301) and are checking conditions that are already expressed in the validate tags on the Transaction struct (rpc/v10/transaction_types.go#L402-L424):
SenderAddress has validate:"required_if=Type DECLARE,required_if=Type INVOKE" (line 412)
ResourceBounds has validate:"required" (line 417)
Search the codebase for other patterns like:
- Manual nil checks that mirror
required tags
- Manual type-conditional checks that mirror
required_if tags
- Any
if field == nil { return error } blocks on fields that already have validate tags
- Verify existing validate tags are up-to-date. Cross-reference the current validate tags against the Starknet API spec. Some tags may be stale or incorrect — for example, a field that was once optional may now be required (or vice versa), or a
required_if condition may reference transaction types that have changed. Compare what the tags enforce vs. what the spec actually demands for each field and transaction type.
For each finding, make the appropriate improvements.
Task 3: Add tests for every validation tag
For every struct that has validate tags (existing or newly added), write unit tests that:
- Test the happy path — a fully valid struct passes validation.
- Test each validate rule — for every tagged field, submit a struct that violates that specific rule and assert the validator returns an error.
- Test conditional rules — for
required_if and excluded_unless tags, test both sides of the condition (e.g., for required_if=Type DECLARE, test that the field IS required when Type=DECLARE and is NOT required when Type=INVOKE).
- Add a sentinel test that fails when new validate tags are added without corresponding tests.. If someone adds a new validate tag to any struct in the future and doesn't update the test, the test will fail, reminding them to add coverage.
References
Context
We use the
go-playground/validatorlibrary to validate incoming RPC request structs via struct tags. The validator is integrated into thejsonrpc.Serverand each RPC version has its own singleton (rpc/v10/validator.go,rpc/v9/validator.go,rpc/v8/validator.go). When a struct is a handler parameter, the server automatically callsvalidator.Struct()on it before the handler runs (jsonrpc/server.go#L655-L672).You can see good examples of validate tags already in use:
rpc/v10/transaction_types.go#L402-L424— theTransactionstruct uses tags likevalidate:"required",validate:"required_if=Type DECLARE",validate:"excluded_unless=Type INVOKE", etc.rpc/v10/transaction_types.go#L449-L454— theBroadcastedTransactionstruct usesvalidate:"required_if=Transaction.Type DECLARE".rpc/v10/events.go#L22—ResultPageRequest.ChunkSizeusesvalidate:"min=1".rpc/v10/estimate_fee.go#L14-L22—MsgFromL1fields usevalidate:"required".rpc/v10/trace.go#L27-L30—TransactionTraceusesvalidate:"required_if=Type INVOKE"on invocation fields.Task 1: Audit all RPC handler methods for missing validation tag opportunities
Go through every handler method registered in
rpc/v10/,rpc/v9/, andrpc/v8/(you can find the full list in each version'sMethods()function) and check the starkent API specification for each one of them (refs for v10, v9, and v8). For each handler, look at the input parameter structs and check:requiredbut have no validate tag?required_if,required_unless,excluded_unless, etc.?min=1onChunkSize) that are not being enforced via tags?For each finding, make the appropriate improvements.
Task 2: Identify and remove dead/redundant custom validation code
There is already custom validation logic that duplicates what the validate tags should handle. A clear example is in
rpc/v10/simulation.go#L261-L272:These are called in
prepareTransactions()(rpc/v10/simulation.go#L283-L301) and are checking conditions that are already expressed in the validate tags on theTransactionstruct (rpc/v10/transaction_types.go#L402-L424):SenderAddresshasvalidate:"required_if=Type DECLARE,required_if=Type INVOKE"(line 412)ResourceBoundshasvalidate:"required"(line 417)Search the codebase for other patterns like:
requiredtagsrequired_iftagsif field == nil { return error }blocks on fields that already have validate tagsrequired_ifcondition may reference transaction types that have changed. Compare what the tags enforce vs. what the spec actually demands for each field and transaction type.For each finding, make the appropriate improvements.
Task 3: Add tests for every validation tag
For every struct that has validate tags (existing or newly added), write unit tests that:
required_ifandexcluded_unlesstags, test both sides of the condition (e.g., forrequired_if=Type DECLARE, test that the field IS required whenType=DECLAREand is NOT required whenType=INVOKE).References
rpc/v10/validator.go— custom validator setup withversion_0x3rule and custom type registrations forfelt.FeltandTransactionTypejsonrpc/server.go#L655-L672— where the server callsvalidator.Struct()on handler paramsrpc/handlers_test.go#L78-L137—TestHandlerParamValidatorCompatibilityshows how the validator is tested for type safety across versions