Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Fix: Allows timeout field to accept both uint64 and string durations #80

Merged
merged 5 commits into from
May 23, 2023
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
20 changes: 12 additions & 8 deletions router/ibc_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,21 @@ func (im IBCMiddleware) OnRecvPacket(
"sequence", packet.Sequence,
"src-channel", packet.SourceChannel, "src-port", packet.SourcePort,
"dst-channel", packet.DestinationChannel, "dst-port", packet.DestinationPort,
"amount", data.Amount, "denom", data.Denom,
"amount", data.Amount, "denom", data.Denom, "memo", data.Memo,
)

m := &types.PacketMetadata{}
err := json.Unmarshal([]byte(data.Memo), m)
if err != nil || m.Forward == nil {
d := make(map[string]interface{})
err := json.Unmarshal([]byte(data.Memo), &d)
if err != nil || d["forward"] == nil {
// not a packet that should be forwarded
im.keeper.Logger(ctx).Debug("packetForwardMiddleware OnRecvPacket forward metadata does not exist")
return im.app.OnRecvPacket(ctx, packet, relayer)
}
m := &types.PacketMetadata{}
err = json.Unmarshal([]byte(data.Memo), m)
if err != nil {
return channeltypes.NewErrorAcknowledgement(fmt.Sprintf("packetForwardMiddleware error parsing forward metadata, %s", err))
}

metadata := m.Forward

Expand Down Expand Up @@ -202,10 +207,9 @@ func (im IBCMiddleware) OnRecvPacket(

token := sdk.NewCoin(denomOnThisChain, amountInt)

var timeout time.Duration
if metadata.Timeout.Nanoseconds() > 0 {
timeout = metadata.Timeout
} else {
timeout := time.Duration(metadata.Timeout)

if timeout.Nanoseconds() <= 0 {
timeout = im.forwardTimeout
}

Expand Down
27 changes: 27 additions & 0 deletions router/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,33 @@ func TestOnRecvPacket_NoForward(t *testing.T) {
require.Equal(t, "test", string(expectedAck.GetResult()))
}

func TestOnRecvPacket_NoMemo(t *testing.T) {
ctl := gomock.NewController(t)
defer ctl.Finish()
setup := test.NewTestSetup(t, ctl)
ctx := setup.Initializer.Ctx
cdc := setup.Initializer.Marshaler
forwardMiddleware := setup.ForwardMiddleware

// Test data
senderAccAddr := test.AccAddress()
packet := transferPacket(t, "cosmos16plylpsgxechajltx9yeseqexzdzut9g8vla4k", "{}")

// Expected mocks
gomock.InOrder(
setup.Mocks.IBCModuleMock.EXPECT().OnRecvPacket(ctx, packet, senderAccAddr).
Return(channeltypes.NewResultAcknowledgement([]byte("test"))),
)

ack := forwardMiddleware.OnRecvPacket(ctx, packet, senderAccAddr)
require.True(t, ack.Success())

expectedAck := &channeltypes.Acknowledgement{}
err := cdc.UnmarshalJSON(ack.Acknowledgement(), expectedAck)
require.NoError(t, err)
require.Equal(t, "test", string(expectedAck.GetResult()))
}

func TestOnRecvPacket_RecvPacketFailed(t *testing.T) {
ctl := gomock.NewController(t)
defer ctl.Finish()
Expand Down
38 changes: 33 additions & 5 deletions router/types/forward.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package types

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

Expand All @@ -14,17 +15,19 @@ type PacketMetadata struct {
}

type ForwardMetadata struct {
Receiver string `json:"receiver,omitempty"`
Port string `json:"port,omitempty"`
Channel string `json:"channel,omitempty"`
Timeout time.Duration `json:"timeout,omitempty"`
Retries *uint8 `json:"retries,omitempty"`
Receiver string `json:"receiver,omitempty"`
Port string `json:"port,omitempty"`
Channel string `json:"channel,omitempty"`
Timeout Duration `json:"timeout,omitempty"`
Retries *uint8 `json:"retries,omitempty"`

// Using JSONObject so that objects for next property will not be mutated by golang's lexicographic key sort on map keys during Marshal.
// Supports primitives for Unmarshal/Marshal so that an escaped JSON-marshaled string is also valid.
Next *JSONObject `json:"next,omitempty"`
}

type Duration time.Duration

func (m *ForwardMetadata) Validate() error {
if m.Receiver == "" {
return fmt.Errorf("failed to validate forward metadata. receiver cannot be empty")
Expand Down Expand Up @@ -86,3 +89,28 @@ func (o JSONObject) MarshalJSON() ([]byte, error) {
// primitive, return raw bytes.
return o.primitive, nil
}

func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(time.Duration(d).Nanoseconds())
}

func (d *Duration) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
switch value := v.(type) {
case float64:
*d = Duration(time.Duration(value))
return nil
case string:
tmp, err := time.ParseDuration(value)
if err != nil {
return err
}
*d = Duration(tmp)
return nil
default:
return errors.New("invalid duration")
}
}
26 changes: 26 additions & 0 deletions router/types/forward_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,29 @@ func TestForwardMetadataUnmarshalJSONNext(t *testing.T) {
require.NoError(t, err)
require.Equal(t, `{"forward":{"receiver":"noble1l505zhahp24v5jsmps9vs5asah759fdce06sfp","port":"transfer","channel":"channel-0","timeout":0}}`, string(nextBz))
}

func TestTimeoutUnmarshalString(t *testing.T) {
const memo = "{\"forward\":{\"receiver\":\"noble1f4cur2krsua2th9kkp7n0zje4stea4p9tu70u8\",\"port\":\"transfer\",\"channel\":\"channel-0\",\"timeout\":\"60s\"}}"
var packetMetadata types.PacketMetadata

err := json.Unmarshal([]byte(memo), &packetMetadata)
require.NoError(t, err)

timeoutBz, err := json.Marshal(packetMetadata.Forward.Timeout)
require.NoError(t, err)

require.Equal(t, "60000000000", string(timeoutBz))
}

func TestTimeoutUnmarshalJSON(t *testing.T) {
const memo = "{\"forward\":{\"receiver\":\"noble1f4cur2krsua2th9kkp7n0zje4stea4p9tu70u8\",\"port\":\"transfer\",\"channel\":\"channel-0\",\"timeout\": 60000000000}}"
var packetMetadata types.PacketMetadata

err := json.Unmarshal([]byte(memo), &packetMetadata)
require.NoError(t, err)

timeoutBz, err := json.Marshal(packetMetadata.Forward.Timeout)
require.NoError(t, err)

require.Equal(t, "60000000000", string(timeoutBz))
}