Skip to content

Commit

Permalink
Merge pull request #30 from kaleido-io/err-propagation
Browse files Browse the repository at this point in the history
Use RPCError as return from CallRPC() to catch error details
  • Loading branch information
peterbroadhurst authored Dec 6, 2022
2 parents d1d08fb + 4ced6ea commit 21e2d61
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 18 deletions.
6 changes: 3 additions & 3 deletions internal/rpcserver/rpcprocessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ func (s *rpcServer) processEthSendTransaction(ctx context.Context, rpcReq *rpcba
if err != nil {
return nil, err
}
err = s.backend.CallRPC(ctx, &txn.Nonce, "eth_getTransactionCount", &from, "pending")
if err != nil {
return rpcbackend.RPCErrorResponse(err, rpcReq.ID, rpcbackend.RPCCodeInternalError), err
rpcErr := s.backend.CallRPC(ctx, &txn.Nonce, "eth_getTransactionCount", &from, "pending")
if rpcErr != nil {
return rpcbackend.RPCErrorResponse(rpcErr.Error(), rpcReq.ID, rpcbackend.RPCCodeInternalError), rpcErr.Error()
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/rpcserver/rpcprocessor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ func TestSignGetNonceFail(t *testing.T) {
defer done()

bm := s.backend.(*rpcbackendmocks.Backend)
bm.On("CallRPC", mock.Anything, mock.Anything, "eth_getTransactionCount", mock.Anything, "pending").Return(fmt.Errorf("pop"))
bm.On("CallRPC", mock.Anything, mock.Anything, "eth_getTransactionCount", mock.Anything, "pending").Return(&rpcbackend.RPCError{Message: "pop"})

_, err := s.processRPC(s.ctx, &rpcbackend.RPCRequest{
ID: fftypes.JSONAnyPtr("1"),
Expand Down
6 changes: 3 additions & 3 deletions internal/rpcserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ func (s *rpcServer) runAPIServer() {
func (s *rpcServer) Start() error {
if s.chainID < 0 {
var chainID ethtypes.HexInteger
err := s.backend.CallRPC(s.ctx, &chainID, "net_version")
if err != nil {
return i18n.WrapError(s.ctx, err, signermsgs.MsgQueryChainID)
rpcErr := s.backend.CallRPC(s.ctx, &chainID, "net_version")
if rpcErr != nil {
return i18n.WrapError(s.ctx, rpcErr.Error(), signermsgs.MsgQueryChainID)
}
s.chainID = chainID.BigInt().Int64()
}
Expand Down
3 changes: 2 additions & 1 deletion internal/rpcserver/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/hyperledger/firefly-signer/mocks/ethsignermocks"
"github.com/hyperledger/firefly-signer/mocks/rpcbackendmocks"
"github.com/hyperledger/firefly-signer/pkg/ethtypes"
"github.com/hyperledger/firefly-signer/pkg/rpcbackend"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
Expand Down Expand Up @@ -87,7 +88,7 @@ func TestStartFailChainID(t *testing.T) {
bm.On("CallRPC", mock.Anything, mock.Anything, "net_version").Run(func(args mock.Arguments) {
hi := args[1].(*ethtypes.HexInteger)
hi.BigInt().SetInt64(12345)
}).Return(fmt.Errorf("pop"))
}).Return(&rpcbackend.RPCError{Message: "pop"})

err := s.Start()
assert.Regexp(t, "pop", err)
Expand Down
10 changes: 6 additions & 4 deletions mocks/rpcbackendmocks/backend.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 16 additions & 5 deletions pkg/rpcbackend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const (

// Backend performs communication with a backend
type Backend interface {
CallRPC(ctx context.Context, result interface{}, method string, params ...interface{}) error
CallRPC(ctx context.Context, result interface{}, method string, params ...interface{}) *RPCError
SyncRequest(ctx context.Context, rpcReq *RPCRequest) (rpcRes *RPCResponse, err error)
}

Expand Down Expand Up @@ -70,6 +70,10 @@ type RPCError struct {
Data fftypes.JSONAny `json:"data,omitempty"`
}

func (e *RPCError) Error() error {
return fmt.Errorf(e.Message)
}

type RPCResponse struct {
JSONRpc string `json:"jsonrpc"`
ID *fftypes.JSONAny `json:"id"`
Expand All @@ -90,7 +94,7 @@ func (rc *RPCClient) allocateRequestID(req *RPCRequest) string {
return reqID
}

func (rc *RPCClient) CallRPC(ctx context.Context, result interface{}, method string, params ...interface{}) error {
func (rc *RPCClient) CallRPC(ctx context.Context, result interface{}, method string, params ...interface{}) *RPCError {
req := &RPCRequest{
JSONRpc: "2.0",
Method: method,
Expand All @@ -99,15 +103,22 @@ func (rc *RPCClient) CallRPC(ctx context.Context, result interface{}, method str
for i, param := range params {
b, err := json.Marshal(param)
if err != nil {
return i18n.NewError(ctx, signermsgs.MsgInvalidParam, i, method, err)
return &RPCError{Code: int64(RPCCodeInvalidRequest), Message: i18n.NewError(ctx, signermsgs.MsgInvalidParam, i, method, err).Error()}
}
req.Params[i] = fftypes.JSONAnyPtrBytes(b)
}
res, err := rc.SyncRequest(ctx, req)
if err != nil {
return err
if res.Error != nil && res.Error.Code != 0 {
return res.Error
}
return &RPCError{Code: int64(RPCCodeInternalError), Message: err.Error()}
}
err = json.Unmarshal(res.Result.Bytes(), &result)
if err != nil {
return &RPCError{Code: int64(RPCCodeParseError), Message: err.Error()}
}
return json.Unmarshal(res.Result.Bytes(), &result)
return nil
}

// SyncRequest sends an individual RPC request to the backend (always over HTTP currently),
Expand Down
2 changes: 1 addition & 1 deletion pkg/rpcbackend/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func TestSyncRPCCallOK(t *testing.T) {

var txCount ethtypes.HexInteger
err := rb.CallRPC(ctx, &txCount, "eth_getTransactionCount", ethtypes.MustNewAddress("0xfb075bb99f2aa4c49955bf703509a227d7a12248"), "pending")
assert.NoError(t, err)
assert.Empty(t, err)
assert.Equal(t, int64(0x26), txCount.BigInt().Int64())
}

Expand Down

0 comments on commit 21e2d61

Please sign in to comment.