Skip to content
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

Simplify EncryptedRPC Client #1877

Merged
merged 4 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions go/common/errutil/evm_serialisable.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package errutil

// EVMSerialisableError is an API error that encompasses an EVM error with a code and a reason
type EVMSerialisableError struct {
Err string
Reason interface{}
Code int
// DataError is an API error that encompasses an EVM error with a code and a reason
type DataError struct {
Code int `json:"code"`
Err string `json:"message"`
Reason interface{} `json:"data,omitempty"`
}

func (e EVMSerialisableError) Error() string {
func (e DataError) Error() string {
return e.Err
}

func (e EVMSerialisableError) ErrorCode() int {
func (e DataError) ErrorCode() int {
return e.Code
}

func (e EVMSerialisableError) ErrorData() interface{} {
func (e DataError) ErrorData() interface{} {
return e.Reason
}
31 changes: 21 additions & 10 deletions go/common/log_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ten-protocol/go-ten/go/common/viewingkey"
"github.com/ten-protocol/go-ten/lib/gethfork/rpc"
Expand All @@ -25,16 +24,28 @@ type LogSubscription struct {
Filter *FilterCriteriaJSON
}

// IDAndEncLog pairs an encrypted log with the ID of the subscription that generated it.
type IDAndEncLog struct {
SubID rpc.ID
EncLog []byte
}
func CreateAuthenticatedLogSubscriptionPayload(args []interface{}, vk *viewingkey.ViewingKey) (*LogSubscription, error) {
logSubscription := &LogSubscription{
ViewingKey: &viewingkey.RPCSignedViewingKey{
PublicKey: vk.PublicKey,
SignatureWithAccountKey: vk.SignatureWithAccountKey,
SignatureType: vk.SignatureType,
},
}

// IDAndLog pairs a log with the ID of the subscription that generated it.
type IDAndLog struct {
SubID rpc.ID
Log *types.Log
// If there are less than two arguments, it means no filter criteria was passed.
if len(args) < 2 {
logSubscription.Filter = &FilterCriteriaJSON{}
return logSubscription, nil
}

filterCriteria, ok := args[1].(FilterCriteria)
if !ok {
return nil, fmt.Errorf("invalid subscription")
}
fc := FromCriteria(filterCriteria)
logSubscription.Filter = &fc
return logSubscription, nil
}

// FilterCriteriaJSON is a structure that JSON-serialises to a format that can be successfully deserialised into a
Expand Down
4 changes: 2 additions & 2 deletions go/common/subscription/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ func ForwardFromChannels[R any](inputChannels []chan R, unsubscribed *atomic.Boo
continue
}

if unsubscribed.Load() {
if unsubscribed != nil && unsubscribed.Load() {
return
}

switch v := value.Interface().(type) {
case time.Time:
// exit the loop to avoid a goroutine leak
if unsubscribed.Load() {
if unsubscribed != nil && unsubscribed.Load() {
return
}
case R:
Expand Down
2 changes: 1 addition & 1 deletion go/enclave/events/subscription_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func NewSubscriptionManager(storage storage.Storage, chainID int64, logger gethl
func (s *SubscriptionManager) AddSubscription(id gethrpc.ID, encodedSubscription []byte) error {
subscription := &common.LogSubscription{}
if err := json.Unmarshal(encodedSubscription, subscription); err != nil {
return fmt.Errorf("could not decocde log subscription from RLP. Cause: %w", err)
return fmt.Errorf("could not decode log subscription. Cause: %w", err)
}

// verify the viewing key
Expand Down
4 changes: 2 additions & 2 deletions go/enclave/evm/evm_facade.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ func initParams(storage storage.Storage, gethEncodingService gethencoding.Encodi
}

func newErrorWithReasonAndCode(err error) error {
result := &errutil.EVMSerialisableError{
result := &errutil.DataError{
Err: err.Error(),
}

Expand All @@ -316,7 +316,7 @@ func newRevertError(result *gethcore.ExecutionResult) error {
if errUnpack == nil {
err = fmt.Errorf("execution reverted: %v", reason)
}
return &errutil.EVMSerialisableError{
return &errutil.DataError{
Err: err.Error(),
Reason: hexutil.Encode(result.Revert()),
Code: 3, // todo - magic number, really needs thought around the value and made a constant
Expand Down
4 changes: 0 additions & 4 deletions go/enclave/rpc/EstimateGas.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,6 @@ func EstimateGasExecute(builder *CallBuilder[CallParamsWithBlock, hexutil.Uint64
}

// return EVM error
evmErr, err := serializeEVMError(err)
if err == nil {
err = fmt.Errorf(string(evmErr))
}
builder.Err = err
return nil
}
Expand Down
27 changes: 0 additions & 27 deletions go/enclave/rpc/TenEthCall.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package rpc

import (
"encoding/json"
"errors"
"fmt"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ten-protocol/go-ten/go/common/errutil"
"github.com/ten-protocol/go-ten/go/common/gethencoding"
"github.com/ten-protocol/go-ten/go/common/log"
"github.com/ten-protocol/go-ten/go/common/syserr"
Expand Down Expand Up @@ -60,11 +58,6 @@ func TenCallExecute(builder *CallBuilder[CallParamsWithBlock, string], rpc *Encr
return err
}

// extract the EVM error
evmErr, err := serializeEVMError(err)
if err == nil {
err = fmt.Errorf(string(evmErr))
}
builder.Err = err
return nil
}
Expand All @@ -78,23 +71,3 @@ func TenCallExecute(builder *CallBuilder[CallParamsWithBlock, string], rpc *Encr
}
return nil
}

func serializeEVMError(err error) ([]byte, error) {
var errReturn interface{}

// check if it's a serialized error and handle any error wrapping that might have occurred
var e *errutil.EVMSerialisableError
if ok := errors.As(err, &e); ok {
errReturn = e
} else {
// it's a generic error, serialise it
errReturn = &errutil.EVMSerialisableError{Err: err.Error()}
}

// serialise the error object returned by the evm into a json
errSerializedBytes, marshallErr := json.Marshal(errReturn)
if marshallErr != nil {
return nil, marshallErr
}
return errSerializedBytes, nil
}
17 changes: 1 addition & 16 deletions go/host/rpc/clientapi/client_api_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,9 @@ func (api *FilterAPI) Logs(ctx context.Context, encryptedParams common.Encrypted
return nil, fmt.Errorf("could not subscribe for logs. Cause: %w", err)
}

// We send the ID of the newly-created subscription, before sending any log events. This is because the wallet
// extension needs to return the subscription ID to the end client, but this information is not exposed to it
// (since the subscription ID is automatically converted to a subscription object).
err = notifier.Notify(subscription.ID, common.IDAndEncLog{
SubID: subscription.ID,
})
if err != nil {
api.host.UnsubscribeLogs(subscription.ID)
return nil, fmt.Errorf("could not send subscription ID to client on subscription %s", subscription.ID)
}

var unsubscribed atomic.Bool
go subscriptioncommon.ForwardFromChannels([]chan []byte{logsFromSubscription}, &unsubscribed, func(elem []byte) error {
msg := &common.IDAndEncLog{
SubID: subscription.ID,
EncLog: elem,
}
return notifier.Notify(subscription.ID, msg)
return notifier.Notify(subscription.ID, elem)
})
go subscriptioncommon.HandleUnsubscribe(subscription, &unsubscribed, func() {
api.host.UnsubscribeLogs(subscription.ID)
Expand Down
2 changes: 1 addition & 1 deletion go/obsclient/authclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func (ac *AuthObsClient) BalanceAt(ctx context.Context, blockNumber *big.Int) (*
return (*big.Int)(&result), err
}

func (ac *AuthObsClient) SubscribeFilterLogs(ctx context.Context, filterCriteria common.FilterCriteria, ch chan common.IDAndLog) (ethereum.Subscription, error) {
func (ac *AuthObsClient) SubscribeFilterLogs(ctx context.Context, filterCriteria common.FilterCriteria, ch chan types.Log) (ethereum.Subscription, error) {
return ac.rpcClient.Subscribe(ctx, rpc.SubscribeNamespace, ch, rpc.SubscriptionTypeLogs, filterCriteria)
}

Expand Down
19 changes: 15 additions & 4 deletions go/responses/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package responses

import (
"encoding/json"
"errors"
"fmt"

"github.com/ten-protocol/go-ten/go/common/errutil"

"github.com/ten-protocol/go-ten/go/common/syserr"
)

Expand Down Expand Up @@ -116,9 +119,8 @@ func AsEncryptedEmptyResponse(encryptHandler Encryptor) *EnclaveResponse {

// AsEncryptedError - Encodes and encrypts an error to be returned for a concrete user.
func AsEncryptedError(err error, encrypt Encryptor) *EnclaveResponse {
errStr := err.Error()
userResp := UserResponse[string]{
ErrStr: &errStr,
Err: convertError(err),
}

encoded, err := json.Marshal(userResp)
Expand Down Expand Up @@ -161,9 +163,18 @@ func DecodeResponse[T any](encoded []byte) (*T, error) {
if err != nil {
return nil, err
}
if resp.ErrStr != nil {
return nil, fmt.Errorf(*resp.ErrStr)
if resp.Err != nil {
return nil, resp.Err
}

return resp.Result, nil
}

func convertError(err error) *errutil.DataError {
// check if it's a serialized error and handle any error wrapping that might have occurred
var e *errutil.DataError
if ok := errors.As(err, &e); ok {
return e
}
return &errutil.DataError{Err: err.Error()}
}
10 changes: 3 additions & 7 deletions go/responses/types.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package responses

import (
"fmt"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ten-protocol/go-ten/go/common/errutil"
)

type ViewingKeyEncryptor func([]byte) ([]byte, error)
Expand All @@ -14,15 +13,12 @@ type ViewingKeyEncryptor func([]byte) ([]byte, error)
// which will be decoded only on the client side.
type UserResponse[T any] struct {
Result *T
ErrStr *string
Err *errutil.DataError
}

// Error - converts the encoded string in the response into a normal error and returns it.
func (ur *UserResponse[T]) Error() error {
if ur.ErrStr != nil {
return fmt.Errorf(*ur.ErrStr)
}
return nil
return ur.Err
}

// Responses
Expand Down
Loading
Loading