New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handling integer IDs in JSON-RPC requests -- fixes #2366 #2811
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #2811 +/- ##
===========================================
- Coverage 62.4% 62.16% -0.24%
===========================================
Files 212 212
Lines 17254 17352 +98
===========================================
+ Hits 10767 10787 +20
- Misses 5583 5657 +74
- Partials 904 908 +4
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking this on, and welcome to Tendermint dev!
A few minor points to address, but otherwise looks good :)
rpc/lib/types/types.go
Outdated
func NewRPCRequest(id string, method string, params json.RawMessage) RPCRequest { | ||
// UnmarshalJSON custom JSON unmarshalling due to jsonrpcid being string or int | ||
func (request *RPCRequest) UnmarshalJSON(data []byte) error { | ||
type AliasStr RPCRequest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should Unmarshal interface{} and then use switch for different possible types
switch ID.(type) {
case string:
XXX
case int:
YYY
default:
return fmt.Errorf("Unknown ID type. Got %T, expected string or int", ID)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes! also you can do without intermediate struct
unsafeResp := &struct {
JSONRPC string `json:"jsonrpc"`
ID interface{} `json:"id"`
Method string `json:"method"`
Params json.RawMessage `json:"params"` // must be map[string]interface{} or []interface{}
}{}
you just use the original one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@melekes @ebuchman I've changed it here: f2a71d7#diff-f595cd0be03b00ec17ec43d65afb7780
I'm not that experienced with Go, so not sure how to do it without the intermediate struct -- or by using the original, did you mean that jsonrpcid
should be an empty interface and it should get rid of the extra ID type wrappers (JSONRPCStringID
/JSONRPCIntID
)?
…ndermint#2366) * added a wrapper interface `jsonrpcid` that represents both string and int IDs in JSON-RPC requests/responses + custom JSON unmarshallers * changed client-side code in RPC that uses it * added extra tests for integer IDs
* added table driven tests for request type marshalling/unmarshalling * expanded handler test to check IDs * changed pending changelog note
71fe74d
to
73bd3c6
Compare
Pushed a commit to do some minor cleanup, hope you don't mind. PTAL! Otherwise LGTM |
* develop: types: Emit tags from BeginBlock/EndBlock (tendermint#2747) Fix fast sync stack with wrong block tendermint#2457 (tendermint#2731) It's better read from genDoc than from state.validators when appHeight==0 in replay (tendermint#2893) update encoding spec (tendermint#2903) return back initially allowed level if we encounter allowed key (tendermint#2889) Handling integer IDs in JSON-RPC requests -- fixes tendermint#2366 (tendermint#2811) # Conflicts: # blockchain/reactor_test.go # blockchain/store_test.go # node/node_test.go # types/events.go
Addresses #2366
Hi everyone, we're using one JSON-RPC client library that only does integer IDs (incrementally), so rather than having a workaround for that, I guess it'd be better to fix this issue in Tendermint.
This is the first Go code I ever wrote, so apologies if it's too bad.
I decided to use this "interface wrapper with a single method" workaround for the lack of sum types in Go, as it seems to be an OK tradeoff between type safety (e.g. "empty interface" wrapper would work as well here, but passing in booleans / objects / arrays as IDs wouldn't result in an error) and boilerplate.