Skip to content
This repository was archived by the owner on May 21, 2024. It is now read-only.

Commit 0093c73

Browse files
fjlelizabethengelman
authored andcommitted
rpc: remove 'exported or builtin' restriction for parameters (ethereum#20332)
* rpc: remove 'exported or builtin' restriction for parameters There is no technial reason for this restriction because package reflect can create values of any type. Requiring parameters and return values to be exported causes a lot of noise in package exports. * rpc: fix staticcheck warnings
1 parent 61b32fd commit 0093c73

File tree

9 files changed

+36
-76
lines changed

9 files changed

+36
-76
lines changed

rpc/client_test.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ func TestClientRequest(t *testing.T) {
4040
client := DialInProc(server)
4141
defer client.Close()
4242

43-
var resp Result
44-
if err := client.Call(&resp, "test_echo", "hello", 10, &Args{"world"}); err != nil {
43+
var resp echoResult
44+
if err := client.Call(&resp, "test_echo", "hello", 10, &echoArgs{"world"}); err != nil {
4545
t.Fatal(err)
4646
}
47-
if !reflect.DeepEqual(resp, Result{"hello", 10, &Args{"world"}}) {
47+
if !reflect.DeepEqual(resp, echoResult{"hello", 10, &echoArgs{"world"}}) {
4848
t.Errorf("incorrect result %#v", resp)
4949
}
5050
}
@@ -58,13 +58,13 @@ func TestClientBatchRequest(t *testing.T) {
5858
batch := []BatchElem{
5959
{
6060
Method: "test_echo",
61-
Args: []interface{}{"hello", 10, &Args{"world"}},
62-
Result: new(Result),
61+
Args: []interface{}{"hello", 10, &echoArgs{"world"}},
62+
Result: new(echoResult),
6363
},
6464
{
6565
Method: "test_echo",
66-
Args: []interface{}{"hello2", 11, &Args{"world"}},
67-
Result: new(Result),
66+
Args: []interface{}{"hello2", 11, &echoArgs{"world"}},
67+
Result: new(echoResult),
6868
},
6969
{
7070
Method: "no_such_method",
@@ -78,13 +78,13 @@ func TestClientBatchRequest(t *testing.T) {
7878
wantResult := []BatchElem{
7979
{
8080
Method: "test_echo",
81-
Args: []interface{}{"hello", 10, &Args{"world"}},
82-
Result: &Result{"hello", 10, &Args{"world"}},
81+
Args: []interface{}{"hello", 10, &echoArgs{"world"}},
82+
Result: &echoResult{"hello", 10, &echoArgs{"world"}},
8383
},
8484
{
8585
Method: "test_echo",
86-
Args: []interface{}{"hello2", 11, &Args{"world"}},
87-
Result: &Result{"hello2", 11, &Args{"world"}},
86+
Args: []interface{}{"hello2", 11, &echoArgs{"world"}},
87+
Result: &echoResult{"hello2", 11, &echoArgs{"world"}},
8888
},
8989
{
9090
Method: "no_such_method",
@@ -104,7 +104,7 @@ func TestClientNotify(t *testing.T) {
104104
client := DialInProc(server)
105105
defer client.Close()
106106

107-
if err := client.Notify(context.Background(), "test_echo", "hello", 10, &Args{"world"}); err != nil {
107+
if err := client.Notify(context.Background(), "test_echo", "hello", 10, &echoArgs{"world"}); err != nil {
108108
t.Fatal(err)
109109
}
110110
}
@@ -393,9 +393,9 @@ func TestClientHTTP(t *testing.T) {
393393

394394
// Launch concurrent requests.
395395
var (
396-
results = make([]Result, 100)
396+
results = make([]echoResult, 100)
397397
errc = make(chan error)
398-
wantResult = Result{"a", 1, new(Args)}
398+
wantResult = echoResult{"a", 1, new(echoArgs)}
399399
)
400400
defer client.Close()
401401
for i := range results {
@@ -450,7 +450,7 @@ func TestClientReconnect(t *testing.T) {
450450
}
451451

452452
// Perform a call. This should work because the server is up.
453-
var resp Result
453+
var resp echoResult
454454
if err := client.CallContext(ctx, &resp, "test_echo", "", 1, nil); err != nil {
455455
t.Fatal(err)
456456
}
@@ -478,7 +478,7 @@ func TestClientReconnect(t *testing.T) {
478478
for i := 0; i < cap(errors); i++ {
479479
go func() {
480480
<-start
481-
var resp Result
481+
var resp echoResult
482482
errors <- client.CallContext(ctx, &resp, "test_echo", "", 3, nil)
483483
}()
484484
}

rpc/doc.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ Methods that satisfy the following criteria are made available for remote access
2929
3030
- method must be exported
3131
- method returns 0, 1 (response or error) or 2 (response and error) values
32-
- method argument(s) must be exported or builtin types
33-
- method returned value(s) must be exported or builtin types
3432
3533
An example method:
3634
@@ -74,13 +72,8 @@ An example server which uses the JSON codec:
7472
calculator := new(CalculatorService)
7573
server := NewServer()
7674
server.RegisterName("calculator", calculator)
77-
7875
l, _ := net.ListenUnix("unix", &net.UnixAddr{Net: "unix", Name: "/tmp/calculator.sock"})
79-
for {
80-
c, _ := l.AcceptUnix()
81-
codec := v2.NewJSONCodec(c)
82-
go server.ServeCodec(codec, 0)
83-
}
76+
server.ServeListener(l)
8477
8578
Subscriptions
8679
@@ -90,7 +83,6 @@ criteria:
9083
9184
- method must be exported
9285
- first method argument type must be context.Context
93-
- method argument(s) must be exported or builtin types
9486
- method must have return types (rpc.Subscription, error)
9587
9688
An example method:

rpc/handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func (h *handler) cancelAllRequests(err error, inflightReq *requestOp) {
189189
}
190190
for id, sub := range h.clientSubs {
191191
delete(h.clientSubs, id)
192-
sub.quitWithError(err, false)
192+
sub.quitWithError(false, err)
193193
}
194194
}
195195

rpc/json.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,14 +153,6 @@ type ConnRemoteAddr interface {
153153
RemoteAddr() string
154154
}
155155

156-
// connWithRemoteAddr overrides the remote address of a connection.
157-
type connWithRemoteAddr struct {
158-
Conn
159-
addr string
160-
}
161-
162-
func (c connWithRemoteAddr) RemoteAddr() string { return c.addr }
163-
164156
// jsonCodec reads and writes JSON-RPC messages to the underlying connection. It also has
165157
// support for parsing arguments and serializing (result) objects.
166158
type jsonCodec struct {

rpc/service.go

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"strings"
2626
"sync"
2727
"unicode"
28-
"unicode/utf8"
2928

3029
"github.com/ethereum/go-ethereum/log"
3130
)
@@ -139,16 +138,14 @@ func newCallback(receiver, fn reflect.Value) *callback {
139138
c := &callback{fn: fn, rcvr: receiver, errPos: -1, isSubscribe: isPubSub(fntype)}
140139
// Determine parameter types. They must all be exported or builtin types.
141140
c.makeArgTypes()
142-
if !allExportedOrBuiltin(c.argTypes) {
143-
return nil
144-
}
141+
145142
// Verify return types. The function must return at most one error
146143
// and/or one other non-error value.
147144
outs := make([]reflect.Type, fntype.NumOut())
148145
for i := 0; i < fntype.NumOut(); i++ {
149146
outs[i] = fntype.Out(i)
150147
}
151-
if len(outs) > 2 || !allExportedOrBuiltin(outs) {
148+
if len(outs) > 2 {
152149
return nil
153150
}
154151
// If an error is returned, it must be the last returned value.
@@ -218,27 +215,6 @@ func (c *callback) call(ctx context.Context, method string, args []reflect.Value
218215
return results[0].Interface(), nil
219216
}
220217

221-
// Is this an exported - upper case - name?
222-
func isExported(name string) bool {
223-
rune, _ := utf8.DecodeRuneInString(name)
224-
return unicode.IsUpper(rune)
225-
}
226-
227-
// Are all those types exported or built-in?
228-
func allExportedOrBuiltin(types []reflect.Type) bool {
229-
for _, typ := range types {
230-
for typ.Kind() == reflect.Ptr {
231-
typ = typ.Elem()
232-
}
233-
// PkgPath will be non-empty even for an exported type,
234-
// so we need to check the type name as well.
235-
if !isExported(typ.Name()) && typ.PkgPath() != "" {
236-
return false
237-
}
238-
}
239-
return true
240-
}
241-
242218
// Is t context.Context or *context.Context?
243219
func isContextType(t reflect.Type) bool {
244220
for t.Kind() == reflect.Ptr {

rpc/subscription.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,11 @@ func (sub *ClientSubscription) Err() <-chan error {
241241
// Unsubscribe unsubscribes the notification and closes the error channel.
242242
// It can safely be called more than once.
243243
func (sub *ClientSubscription) Unsubscribe() {
244-
sub.quitWithError(nil, true)
244+
sub.quitWithError(true, nil)
245245
sub.errOnce.Do(func() { close(sub.err) })
246246
}
247247

248-
func (sub *ClientSubscription) quitWithError(err error, unsubscribeServer bool) {
248+
func (sub *ClientSubscription) quitWithError(unsubscribeServer bool, err error) {
249249
sub.quitOnce.Do(func() {
250250
// The dispatch loop won't be able to execute the unsubscribe call
251251
// if it is blocked on deliver. Close sub.quit first because it
@@ -276,7 +276,7 @@ func (sub *ClientSubscription) start() {
276276
sub.quitWithError(sub.forward())
277277
}
278278

279-
func (sub *ClientSubscription) forward() (err error, unsubscribeServer bool) {
279+
func (sub *ClientSubscription) forward() (unsubscribeServer bool, err error) {
280280
cases := []reflect.SelectCase{
281281
{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.quit)},
282282
{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sub.in)},
@@ -298,14 +298,14 @@ func (sub *ClientSubscription) forward() (err error, unsubscribeServer bool) {
298298

299299
switch chosen {
300300
case 0: // <-sub.quit
301-
return nil, false
301+
return false, nil
302302
case 1: // <-sub.in
303303
val, err := sub.unmarshal(recv.Interface().(json.RawMessage))
304304
if err != nil {
305-
return err, true
305+
return true, err
306306
}
307307
if buffer.Len() == maxClientSubscriptionBuffer {
308-
return ErrSubscriptionQueueOverflow, true
308+
return true, ErrSubscriptionQueueOverflow
309309
}
310310
buffer.PushBack(val)
311311
case 2: // sub.channel<-

rpc/testservice_test.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,24 +53,24 @@ func sequentialIDGenerator() func() ID {
5353

5454
type testService struct{}
5555

56-
type Args struct {
56+
type echoArgs struct {
5757
S string
5858
}
5959

60-
type Result struct {
60+
type echoResult struct {
6161
String string
6262
Int int
63-
Args *Args
63+
Args *echoArgs
6464
}
6565

6666
func (s *testService) NoArgsRets() {}
6767

68-
func (s *testService) Echo(str string, i int, args *Args) Result {
69-
return Result{str, i, args}
68+
func (s *testService) Echo(str string, i int, args *echoArgs) echoResult {
69+
return echoResult{str, i, args}
7070
}
7171

72-
func (s *testService) EchoWithCtx(ctx context.Context, str string, i int, args *Args) Result {
73-
return Result{str, i, args}
72+
func (s *testService) EchoWithCtx(ctx context.Context, str string, i int, args *echoArgs) echoResult {
73+
return echoResult{str, i, args}
7474
}
7575

7676
func (s *testService) Sleep(ctx context.Context, duration time.Duration) {
@@ -81,6 +81,7 @@ func (s *testService) Rets() (string, error) {
8181
return "", nil
8282
}
8383

84+
//lint:ignore ST1008 returns error first on purpose.
8485
func (s *testService) InvalidRets1() (error, string) {
8586
return nil, ""
8687
}

rpc/types.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,8 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
9797
return err
9898
}
9999
if blckNum > math.MaxInt64 {
100-
return fmt.Errorf("Blocknumber too high")
100+
return fmt.Errorf("block number larger than int64")
101101
}
102-
103102
*bn = BlockNumber(blckNum)
104103
return nil
105104
}

rpc/websocket_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func TestWebsocketLargeCall(t *testing.T) {
9696
defer client.Close()
9797

9898
// This call sends slightly less than the limit and should work.
99-
var result Result
99+
var result echoResult
100100
arg := strings.Repeat("x", maxRequestContentLength-200)
101101
if err := client.Call(&result, "test_echo", arg, 1); err != nil {
102102
t.Fatalf("valid call didn't work: %v", err)

0 commit comments

Comments
 (0)