rpc: take integers for boolean parameters.

This is for backward compatibility with lbrycrd/bitcoind where some clients
use intger values (0/1) for boolean.
This commit is contained in:
Roy Lee 2022-02-10 14:47:25 -08:00
parent 20d761441c
commit eecc55d94c
2 changed files with 92 additions and 1 deletions

View file

@ -134,6 +134,16 @@ func UnmarshalCmd(r *Request) (interface{}, error) {
// Unmarshal the parameter into the struct field. // Unmarshal the parameter into the struct field.
concreteVal := rvf.Addr().Interface() concreteVal := rvf.Addr().Interface()
if err := json.Unmarshal(r.Params[i], &concreteVal); err != nil { if err := json.Unmarshal(r.Params[i], &concreteVal); err != nil {
// Parse Integer into Bool for compatibility with lbrycrd.
if rvf.Kind() == reflect.Ptr &&
rvf.Elem().Type().Kind() == reflect.Bool {
boolInt, errBoolInt := strconv.Atoi(string(r.Params[i]))
if errBoolInt == nil {
rvf.Elem().SetBool(boolInt != 0)
continue
}
}
// The most common error is the wrong type, so // The most common error is the wrong type, so
// explicitly detect that error and make it nicer. // explicitly detect that error and make it nicer.
fieldName := strings.ToLower(rt.Field(i).Name) fieldName := strings.ToLower(rt.Field(i).Name)

View file

@ -557,7 +557,7 @@ func TestUnmarshalCmdErrors(t *testing.T) {
request: btcjson.Request{ request: btcjson.Request{
Jsonrpc: btcjson.RpcVersion1, Jsonrpc: btcjson.RpcVersion1,
Method: "getblock", Method: "getblock",
Params: []json.RawMessage{[]byte("1")}, Params: []json.RawMessage{[]byte("1.0")},
ID: nil, ID: nil,
}, },
err: btcjson.Error{ErrorCode: btcjson.ErrInvalidType}, err: btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
@ -591,3 +591,84 @@ func TestUnmarshalCmdErrors(t *testing.T) {
} }
} }
} }
// TestUnmarshalCmdBoolParams tests the parsing of boolean paramers of the UnmarshalCmd function.
func TestUnmarshalCmdBoolParams(t *testing.T) {
t.Parallel()
txid := []byte(`"ab91c149aff2b37a4a1856e9935ea623c973f47886d032ed7511ad8ca37855bb"`)
tests := []struct {
name string
request btcjson.Request
expect bool
}{
{
name: "parse true",
request: btcjson.Request{
Jsonrpc: btcjson.RpcVersion1,
Method: "getrawtransaction",
Params: []json.RawMessage{txid, []byte("true")},
ID: nil,
},
expect: true,
},
{
name: "parse false",
request: btcjson.Request{
Jsonrpc: btcjson.RpcVersion1,
Method: "getrawtransaction",
Params: []json.RawMessage{txid, []byte("false")},
ID: nil,
},
expect: false,
},
{
name: "parse integer 0 to false",
request: btcjson.Request{
Jsonrpc: btcjson.RpcVersion1,
Method: "getrawtransaction",
Params: []json.RawMessage{txid, []byte("0")},
ID: nil,
},
expect: false,
},
{
name: "parse integer 1 to true",
request: btcjson.Request{
Jsonrpc: btcjson.RpcVersion1,
Method: "getrawtransaction",
Params: []json.RawMessage{txid, []byte("1")},
ID: nil,
},
expect: true,
},
{
name: "parse integer 100 to true",
request: btcjson.Request{
Jsonrpc: btcjson.RpcVersion1,
Method: "getrawtransaction",
Params: []json.RawMessage{txid, []byte("100")},
ID: nil,
},
expect: true,
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
cmd, err := btcjson.UnmarshalCmd(&test.request)
if err != nil {
t.Errorf("Test #%d (%s) error - got %T (%v)", i, test.name,
err, err)
continue
}
cc := cmd.(*btcjson.GetRawTransactionCmd)
verbose := *cc.Verbose
if verbose != test.expect {
t.Errorf("Test #%d (%s) got %t, want %v", i, test.name,
verbose, test.expect)
continue
}
}
}