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

Commit 86f045c

Browse files
boojamyaagouinxlab
authored
Merge PR #85: Backports #78, #80, #81 into v5
* Fix same bool being used for all 3 (#81) * fix: middleware panic upon receiving amount that is not int64; added test (#78) resolves #77 * Fix: Allows timeout field to accept both uint64 and string durations (#80) * timeout accetps both string and time.duration * feedback * handle invalid unmarshalls * Update router/ibc_middleware.go Co-authored-by: Andrew Gouin <andrew@gouin.io> * add test case for empty valid json --------- Co-authored-by: Andrew Gouin <andrew@gouin.io> * fix for ibc-go version * re gen protos * remove unused make test command * fix lint --------- Co-authored-by: Andrew Gouin <andrew@gouin.io> Co-authored-by: Max Kupriianov <max@kc.vc>
1 parent e10c580 commit 86f045c

File tree

8 files changed

+273
-94
lines changed

8 files changed

+273
-94
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ go.sum: go.mod
177177
###############################################################################
178178

179179
test: test-unit
180-
test-all: test-unit test-ledger-mock test-race test-cover
180+
test-all: test-unit test-ledger-mock test-race
181181

182182
TEST_PACKAGES=./...
183183
TEST_TARGETS := test-unit test-unit-amino test-unit-proto test-ledger-mock test-race test-ledger test-race

router/ibc_middleware.go

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@ func getDenomForThisChain(port, channel, counterpartyPort, counterpartyChannel,
119119
return transfertypes.ParseDenomTrace(prefixedDenom).IBCDenom()
120120
}
121121

122+
// getBoolFromAny returns the bool value is any is a valid bool, otherwise false.
123+
func getBoolFromAny(value any) bool {
124+
if value == nil {
125+
return false
126+
}
127+
boolVal, ok := value.(bool)
128+
if !ok {
129+
return false
130+
}
131+
return boolVal
132+
}
133+
122134
// OnRecvPacket checks the memo field on this packet and if the metadata inside's root key indicates this packet
123135
// should be handled by the swap middleware it attempts to perform a swap. If the swap is successful
124136
// the underlying application's OnRecvPacket callback is invoked, an ack error is returned otherwise.
@@ -136,40 +148,28 @@ func (im IBCMiddleware) OnRecvPacket(
136148
"sequence", packet.Sequence,
137149
"src-channel", packet.SourceChannel, "src-port", packet.SourcePort,
138150
"dst-channel", packet.DestinationChannel, "dst-port", packet.DestinationPort,
139-
"amount", data.Amount, "denom", data.Denom,
151+
"amount", data.Amount, "denom", data.Denom, "memo", data.Memo,
140152
)
141153

142-
m := &types.PacketMetadata{}
143-
err := json.Unmarshal([]byte(data.Memo), m)
144-
if err != nil || m.Forward == nil {
154+
d := make(map[string]interface{})
155+
err := json.Unmarshal([]byte(data.Memo), &d)
156+
if err != nil || d["forward"] == nil {
145157
// not a packet that should be forwarded
146158
im.keeper.Logger(ctx).Debug("packetForwardMiddleware OnRecvPacket forward metadata does not exist")
147159
return im.app.OnRecvPacket(ctx, packet, relayer)
148160
}
161+
m := &types.PacketMetadata{}
162+
err = json.Unmarshal([]byte(data.Memo), m)
163+
if err != nil {
164+
return channeltypes.NewErrorAcknowledgement(fmt.Errorf("packetForwardMiddleware error parsing forward metadata, %s", err))
165+
}
149166

150167
metadata := m.Forward
151168

152-
var processed, nonrefundable, disableDenomComposition bool
153169
goCtx := ctx.Context()
154-
p := goCtx.Value(types.ProcessedKey{})
155-
nr := goCtx.Value(types.NonrefundableKey{})
156-
ddc := goCtx.Value(types.DisableDenomCompositionKey{})
157-
158-
if p != nil {
159-
if pb, ok := p.(bool); ok {
160-
processed = pb
161-
}
162-
}
163-
if nr != nil {
164-
if nrb, ok := p.(bool); ok {
165-
nonrefundable = nrb
166-
}
167-
}
168-
if ddc != nil {
169-
if ddcb, ok := p.(bool); ok {
170-
disableDenomComposition = ddcb
171-
}
172-
}
170+
processed := getBoolFromAny(goCtx.Value(types.ProcessedKey{}))
171+
nonrefundable := getBoolFromAny(goCtx.Value(types.NonrefundableKey{}))
172+
disableDenomComposition := getBoolFromAny(goCtx.Value(types.DisableDenomCompositionKey{}))
173173

174174
if err := metadata.Validate(); err != nil {
175175
return channeltypes.NewErrorAcknowledgement(err)
@@ -203,10 +203,9 @@ func (im IBCMiddleware) OnRecvPacket(
203203

204204
token := sdk.NewCoin(denomOnThisChain, amountInt)
205205

206-
var timeout time.Duration
207-
if metadata.Timeout.Nanoseconds() > 0 {
208-
timeout = metadata.Timeout
209-
} else {
206+
timeout := time.Duration(metadata.Timeout)
207+
208+
if timeout.Nanoseconds() <= 0 {
210209
timeout = im.forwardTimeout
211210
}
212211

router/keeper/keeper.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func (k *Keeper) WriteAcknowledgementForForwardedPacket(
100100
ack channeltypes.Acknowledgement,
101101
) error {
102102
// Lookup module by channel capability
103-
_, cap, err := k.channelKeeper.LookupModuleByChannel(ctx, inFlightPacket.RefundPortId, inFlightPacket.RefundChannelId)
103+
_, chanCap, err := k.channelKeeper.LookupModuleByChannel(ctx, inFlightPacket.RefundPortId, inFlightPacket.RefundChannelId)
104104
if err != nil {
105105
return errorsmod.Wrap(err, "could not retrieve module from port-id")
106106
}
@@ -115,7 +115,7 @@ func (k *Keeper) WriteAcknowledgementForForwardedPacket(
115115
ackResult := fmt.Sprintf("packet forward failed after point of no return: %s", ack.GetError())
116116
newAck := channeltypes.NewResultAcknowledgement([]byte(ackResult))
117117

118-
return k.ics4Wrapper.WriteAcknowledgement(ctx, cap, channeltypes.Packet{
118+
return k.ics4Wrapper.WriteAcknowledgement(ctx, chanCap, channeltypes.Packet{
119119
Data: inFlightPacket.PacketData,
120120
Sequence: inFlightPacket.RefundSequence,
121121
SourcePort: inFlightPacket.PacketSrcPortId,
@@ -183,7 +183,7 @@ func (k *Keeper) WriteAcknowledgementForForwardedPacket(
183183
}
184184
}
185185

186-
return k.ics4Wrapper.WriteAcknowledgement(ctx, cap, channeltypes.Packet{
186+
return k.ics4Wrapper.WriteAcknowledgement(ctx, chanCap, channeltypes.Packet{
187187
Data: inFlightPacket.PacketData,
188188
Sequence: inFlightPacket.RefundSequence,
189189
SourcePort: inFlightPacket.PacketSrcPortId,
@@ -303,11 +303,13 @@ func (k *Keeper) ForwardTransferPacket(
303303
store.Set(key, bz)
304304

305305
defer func() {
306-
telemetry.SetGaugeWithLabels(
307-
[]string{"tx", "msg", "ibc", "transfer"},
308-
float32(token.Amount.Int64()),
309-
[]metrics.Label{telemetry.NewLabel(coretypes.LabelDenom, token.Denom)},
310-
)
306+
if token.Amount.IsInt64() {
307+
telemetry.SetGaugeWithLabels(
308+
[]string{"tx", "msg", "ibc", "transfer"},
309+
float32(token.Amount.Int64()),
310+
[]metrics.Label{telemetry.NewLabel(coretypes.LabelDenom, token.Denom)},
311+
)
312+
}
311313

312314
telemetry.IncrCounterWithLabels(
313315
[]string{"ibc", types.ModuleName, "send"},

router/module.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ func (AppModuleBasic) Name() string {
3636
}
3737

3838
// RegisterLegacyAminoCodec implements AppModuleBasic interface
39-
func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {}
39+
func (AppModuleBasic) RegisterLegacyAminoCodec(_ *codec.LegacyAmino) {}
4040

4141
// RegisterInterfaces registers module concrete types into protobuf Any.
42-
func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {}
42+
func (AppModuleBasic) RegisterInterfaces(_ codectypes.InterfaceRegistry) {}
4343

4444
// DefaultGenesis returns default genesis state as raw bytes for the ibc
4545
// router module.
@@ -48,7 +48,7 @@ func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
4848
}
4949

5050
// ValidateGenesis performs genesis state validation for the router module.
51-
func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error {
51+
func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error {
5252
var gs types.GenesisState
5353
if err := cdc.UnmarshalJSON(bz, &gs); err != nil {
5454
return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
@@ -58,7 +58,7 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod
5858
}
5959

6060
// RegisterRESTRoutes implements AppModuleBasic interface
61-
func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) {}
61+
func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {}
6262

6363
// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the ibc-router module.
6464
func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
@@ -89,7 +89,7 @@ func NewAppModule(k *keeper.Keeper) AppModule {
8989
}
9090

9191
// RegisterInvariants implements the AppModule interface
92-
func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {}
92+
func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
9393

9494
// Route implements the AppModule interface
9595
func (am AppModule) Route() sdk.Route {
@@ -131,30 +131,30 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw
131131
func (AppModule) ConsensusVersion() uint64 { return 1 }
132132

133133
// BeginBlock implements the AppModule interface
134-
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {}
134+
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
135135

136136
// EndBlock implements the AppModule interface
137-
func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate {
137+
func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
138138
return []abci.ValidatorUpdate{}
139139
}
140140

141141
// AppModuleSimulation functions
142142

143143
// GenerateGenesisState creates a randomized GenState of the router module.
144-
func (AppModule) GenerateGenesisState(simState *module.SimulationState) {}
144+
func (AppModule) GenerateGenesisState(_ *module.SimulationState) {}
145145

146146
// ProposalContents doesn't return any content functions for governance proposals.
147147
func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent {
148148
return nil
149149
}
150150

151151
// RandomizedParams creates randomized ibc-router param changes for the simulator.
152-
func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange {
152+
func (AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange {
153153
return nil
154154
}
155155

156156
// RegisterStoreDecoder registers a decoder for router module's types
157-
func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {}
157+
func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
158158

159159
// WeightedOperations returns the all the router module operations with their respective weights.
160160
func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation {

router/module_test.go

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ import (
1717
)
1818

1919
var (
20-
testDenom = "uatom"
21-
testAmount = "100"
20+
testDenom = "uatom"
21+
testAmount = "100"
22+
testAmount256 = "100000000000000000000"
2223

2324
testSourcePort = "transfer"
2425
testSourceChannel = "channel-10"
@@ -64,6 +65,36 @@ func transferPacket(t *testing.T, receiver string, metadata any) channeltypes.Pa
6465
}
6566
}
6667

68+
func transferPacket256(t *testing.T, receiver string, metadata any) channeltypes.Packet {
69+
t.Helper()
70+
transferPacket := transfertypes.FungibleTokenPacketData{
71+
Denom: testDenom,
72+
Amount: testAmount256,
73+
Receiver: receiver,
74+
}
75+
76+
if metadata != nil {
77+
if mStr, ok := metadata.(string); ok {
78+
transferPacket.Memo = mStr
79+
} else {
80+
memo, err := json.Marshal(metadata)
81+
require.NoError(t, err)
82+
transferPacket.Memo = string(memo)
83+
}
84+
}
85+
86+
transferData, err := transfertypes.ModuleCdc.MarshalJSON(&transferPacket)
87+
require.NoError(t, err)
88+
89+
return channeltypes.Packet{
90+
SourcePort: testSourcePort,
91+
SourceChannel: testSourceChannel,
92+
DestinationPort: testDestinationPort,
93+
DestinationChannel: testDestinationChannel,
94+
Data: transferData,
95+
}
96+
}
97+
6798
func TestOnRecvPacket_EmptyPacket(t *testing.T) {
6899
ctl := gomock.NewController(t)
69100
defer ctl.Finish()
@@ -138,6 +169,33 @@ func TestOnRecvPacket_NoForward(t *testing.T) {
138169
require.Equal(t, "test", string(expectedAck.GetResult()))
139170
}
140171

172+
func TestOnRecvPacket_NoMemo(t *testing.T) {
173+
ctl := gomock.NewController(t)
174+
defer ctl.Finish()
175+
setup := test.NewTestSetup(t, ctl)
176+
ctx := setup.Initializer.Ctx
177+
cdc := setup.Initializer.Marshaler
178+
forwardMiddleware := setup.ForwardMiddleware
179+
180+
// Test data
181+
senderAccAddr := test.AccAddress()
182+
packet := transferPacket(t, "cosmos16plylpsgxechajltx9yeseqexzdzut9g8vla4k", "{}")
183+
184+
// Expected mocks
185+
gomock.InOrder(
186+
setup.Mocks.IBCModuleMock.EXPECT().OnRecvPacket(ctx, packet, senderAccAddr).
187+
Return(channeltypes.NewResultAcknowledgement([]byte("test"))),
188+
)
189+
190+
ack := forwardMiddleware.OnRecvPacket(ctx, packet, senderAccAddr)
191+
require.True(t, ack.Success())
192+
193+
expectedAck := &channeltypes.Acknowledgement{}
194+
err := cdc.UnmarshalJSON(ack.Acknowledgement(), expectedAck)
195+
require.NoError(t, err)
196+
require.Equal(t, "test", string(expectedAck.GetResult()))
197+
}
198+
141199
func TestOnRecvPacket_RecvPacketFailed(t *testing.T) {
142200
ctl := gomock.NewController(t)
143201
defer ctl.Finish()
@@ -227,6 +285,72 @@ func TestOnRecvPacket_ForwardNoFee(t *testing.T) {
227285
require.NoError(t, err)
228286
}
229287

288+
func TestOnRecvPacket_ForwardAmountInt256(t *testing.T) {
289+
var err error
290+
ctl := gomock.NewController(t)
291+
defer ctl.Finish()
292+
setup := test.NewTestSetup(t, ctl)
293+
ctx := setup.Initializer.Ctx
294+
cdc := setup.Initializer.Marshaler
295+
forwardMiddleware := setup.ForwardMiddleware
296+
297+
// Test data
298+
const (
299+
hostAddr = "cosmos1vzxkv3lxccnttr9rs0002s93sgw72h7ghukuhs"
300+
destAddr = "cosmos16plylpsgxechajltx9yeseqexzdzut9g8vla4k"
301+
port = "transfer"
302+
channel = "channel-0"
303+
)
304+
denom := makeIBCDenom(testDestinationPort, testDestinationChannel, testDenom)
305+
senderAccAddr := test.AccAddress()
306+
307+
amount256, ok := sdk.NewIntFromString(testAmount256)
308+
require.True(t, ok)
309+
310+
testCoin := sdk.NewCoin(denom, amount256)
311+
packetOrig := transferPacket256(t, hostAddr, &types.PacketMetadata{
312+
Forward: &types.ForwardMetadata{
313+
Receiver: destAddr,
314+
Port: port,
315+
Channel: channel,
316+
},
317+
})
318+
packetFwd := transferPacket256(t, destAddr, nil)
319+
320+
acknowledgement := channeltypes.NewResultAcknowledgement([]byte("test"))
321+
successAck := cdc.MustMarshalJSON(&acknowledgement)
322+
323+
// Expected mocks
324+
gomock.InOrder(
325+
setup.Mocks.IBCModuleMock.EXPECT().OnRecvPacket(ctx, packetOrig, senderAccAddr).
326+
Return(acknowledgement),
327+
328+
setup.Mocks.TransferKeeperMock.EXPECT().Transfer(
329+
sdk.WrapSDKContext(ctx),
330+
transfertypes.NewMsgTransfer(
331+
port,
332+
channel,
333+
testCoin,
334+
hostAddr,
335+
destAddr,
336+
keeper.DefaultTransferPacketTimeoutHeight,
337+
uint64(ctx.BlockTime().UnixNano())+uint64(keeper.DefaultForwardTransferPacketTimeoutTimestamp.Nanoseconds()),
338+
),
339+
).Return(&transfertypes.MsgTransferResponse{Sequence: 0}, nil),
340+
341+
setup.Mocks.IBCModuleMock.EXPECT().OnAcknowledgementPacket(ctx, packetFwd, successAck, senderAccAddr).
342+
Return(nil),
343+
)
344+
345+
// chain B with router module receives packet and forwards. ack should be nil so that it is not written yet.
346+
ack := forwardMiddleware.OnRecvPacket(ctx, packetOrig, senderAccAddr)
347+
require.Nil(t, ack)
348+
349+
// ack returned from chain C
350+
err = forwardMiddleware.OnAcknowledgementPacket(ctx, packetFwd, successAck, senderAccAddr)
351+
require.NoError(t, err)
352+
}
353+
230354
func TestOnRecvPacket_ForwardWithFee(t *testing.T) {
231355
var err error
232356
ctl := gomock.NewController(t)

0 commit comments

Comments
 (0)