Skip to content

Commit

Permalink
Return Revet result as Data
Browse files Browse the repository at this point in the history
  • Loading branch information
0xcb9ff9 committed Jun 17, 2023
1 parent c202b4e commit c72d160
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 12 deletions.
25 changes: 22 additions & 3 deletions jsonrpc/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,25 @@ func (e *ObjectError) Error() string {
return string(data)
}

func (e *ObjectError) MarshalJSON() ([]byte, error) {
var ds string

data, ok := e.Data.([]byte)
if ok && len(data) > 0 {
ds = "0x" + string(data)
}

return json.Marshal(&struct {
Code int `json:"code"`
Message string `json:"message"`
Data string `json:"data,omitempty"`
}{
Code: e.Code,
Message: e.Message,
Data: ds,
})
}

const (
PendingBlockFlag = "pending"
LatestBlockFlag = "latest"
Expand Down Expand Up @@ -192,8 +211,8 @@ func (b *BlockNumber) UnmarshalJSON(buffer []byte) error {
}

// NewRPCErrorResponse is used to create a custom error response
func NewRPCErrorResponse(id interface{}, errCode int, err string, jsonrpcver string) Response {
errObject := &ObjectError{errCode, err, nil}
func NewRPCErrorResponse(id interface{}, errCode int, err string, data []byte, jsonrpcver string) Response {
errObject := &ObjectError{errCode, err, data}

response := &ErrorResponse{
JSONRPC: jsonrpcver,
Expand All @@ -211,7 +230,7 @@ func NewRPCResponse(id interface{}, jsonrpcver string, reply []byte, err Error)
case nil:
response = &SuccessResponse{JSONRPC: jsonrpcver, ID: id, Result: reply}
default:
response = NewRPCErrorResponse(id, err.ErrorCode(), err.Error(), jsonrpcver)
response = NewRPCErrorResponse(id, err.ErrorCode(), err.Error(), reply, jsonrpcver)
}

return response
Expand Down
23 changes: 16 additions & 7 deletions jsonrpc/dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ func (d *Dispatcher) Handle(reqBody []byte) ([]byte, error) {
for _, req := range requests {
var response, err = d.handleReq(req)
if err != nil {
errorResponse := NewRPCResponse(req.ID, "2.0", nil, err)
errorResponse := NewRPCResponse(req.ID, "2.0", response, err)
responses = append(responses, errorResponse)

continue
Expand Down Expand Up @@ -371,17 +371,26 @@ func (d *Dispatcher) handleReq(req Request) ([]byte, Error) {
}
}

var (
data []byte
err error
ok bool
)

output := fd.fv.Call(inArgs)
if err := getError(output[1]); err != nil {
d.logInternalError(req.Method, err)

return nil, NewInvalidRequestError(err.Error())
}
if res := output[0].Interface(); res != nil {
data, ok = res.([]byte)

var (
data []byte
err error
)
if !ok {
return nil, NewInternalError(err.Error())
}
}

return data, NewInvalidRequestError(err.Error())
}

if res := output[0].Interface(); res != nil {
data, err = json.Marshal(res)
Expand Down
32 changes: 31 additions & 1 deletion jsonrpc/eth_blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"testing"

"github.com/dogechain-lab/dogechain/blockchain"
"github.com/dogechain-lab/dogechain/helper/hex"
"github.com/dogechain-lab/dogechain/helper/progress"
"github.com/dogechain-lab/dogechain/state/runtime"
"github.com/dogechain-lab/dogechain/types"
Expand Down Expand Up @@ -292,6 +293,31 @@ func TestEth_Call(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, res)
})

t.Run("returns error and result as data of a reverted transaction execution", func(t *testing.T) {
returnValue := []byte("Reverted()")

store := newMockBlockStore()
store.add(newTestBlock(100, hash1))
store.ethCallError = runtime.ErrExecutionReverted
store.returnValue = returnValue
eth := newTestEthEndpoint(store)
contractCall := &txnArgs{
From: &addr0,
To: &addr1,
Gas: argUintPtr(100000),
GasPrice: argBytesPtr([]byte{0x64}),
Value: argBytesPtr([]byte{0x64}),
Data: nil,
Nonce: argUintPtr(0),
}

res, err := eth.Call(contractCall, BlockNumberOrHash{})
assert.Error(t, err)
assert.NotNil(t, res)
bres := res.([]byte) //nolint:forcetypeassert
assert.Equal(t, []byte(hex.EncodeToString(returnValue)), bres)
})
}

type mockBlockStore struct {
Expand All @@ -303,6 +329,7 @@ type mockBlockStore struct {
isSyncing bool
averageGasPrice int64
ethCallError error
returnValue []byte
}

func newMockBlockStore() *mockBlockStore {
Expand Down Expand Up @@ -482,7 +509,10 @@ func (m *mockBlockStore) GetAvgGasPrice() *big.Int {
}

func (m *mockBlockStore) ApplyTxn(header *types.Header, txn *types.Transaction) (*runtime.ExecutionResult, error) {
return &runtime.ExecutionResult{Err: m.ethCallError}, nil
return &runtime.ExecutionResult{
Err: m.ethCallError,
ReturnValue: m.returnValue,
}, nil
}

func (m *mockBlockStore) SubscribeEvents() blockchain.Subscription {
Expand Down
2 changes: 1 addition & 1 deletion jsonrpc/eth_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ func (e *Eth) Call(arg *txnArgs, filter BlockNumberOrHash) (interface{}, error)

// Check if an EVM revert happened
if result.Reverted() {
return nil, constructErrorFromRevert(result)
return []byte(hex.EncodeToString(result.ReturnValue)), constructErrorFromRevert(result)
}

if result.Failed() {
Expand Down

0 comments on commit c72d160

Please sign in to comment.