From 6996f72b381b4bd24c4da2d7681f5d72888d8c5b Mon Sep 17 00:00:00 2001 From: Alex Peters Date: Thu, 18 Mar 2021 15:27:18 +0100 Subject: [PATCH] Handle non default ibc tranfer port --- app/app.go | 2 + x/wasm/internal/keeper/genesis_test.go | 2 +- x/wasm/internal/keeper/handler_plugin.go | 4 +- .../keeper/handler_plugin_encoders.go | 55 ++++++++++--------- .../keeper/handler_plugin_encoders_test.go | 33 ++++++----- x/wasm/internal/keeper/keeper.go | 3 +- x/wasm/internal/keeper/options_test.go | 2 +- x/wasm/internal/keeper/test_common.go | 2 + .../keeper/wasmtesting/mock_keepers.go | 14 ++++- x/wasm/internal/types/expected_keepers.go | 5 ++ 10 files changed, 76 insertions(+), 46 deletions(-) diff --git a/app/app.go b/app/app.go index 3f4a3e2ad1..32d633330f 100644 --- a/app/app.go +++ b/app/app.go @@ -366,6 +366,7 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b app.ibcKeeper.ChannelKeeper, &app.ibcKeeper.PortKeeper, scopedWasmKeeper, + app.transferKeeper, app.Router(), app.GRPCQueryRouter(), wasmDir, @@ -442,6 +443,7 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, ibctransfertypes.ModuleName, + // wasm after ibc transfer wasm.ModuleName, ) diff --git a/x/wasm/internal/keeper/genesis_test.go b/x/wasm/internal/keeper/genesis_test.go index f7ff5e2044..27fd6edaf7 100644 --- a/x/wasm/internal/keeper/genesis_test.go +++ b/x/wasm/internal/keeper/genesis_test.go @@ -643,7 +643,7 @@ func setupKeeper(t *testing.T) (*Keeper, sdk.Context, []sdk.StoreKey) { wasmConfig := wasmTypes.DefaultWasmConfig() pk := paramskeeper.NewKeeper(encodingConfig.Marshaler, encodingConfig.Amino, keyParams, tkeyParams) - srcKeeper := NewKeeper(encodingConfig.Marshaler, keyWasm, pk.Subspace(wasmTypes.DefaultParamspace), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, tempDir, wasmConfig, SupportedFeatures) + srcKeeper := NewKeeper(encodingConfig.Marshaler, keyWasm, pk.Subspace(wasmTypes.DefaultParamspace), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, tempDir, wasmConfig, SupportedFeatures) return &srcKeeper, ctx, []sdk.StoreKey{keyWasm, keyParams} } diff --git a/x/wasm/internal/keeper/handler_plugin.go b/x/wasm/internal/keeper/handler_plugin.go index 61c9436869..e5cb369375 100644 --- a/x/wasm/internal/keeper/handler_plugin.go +++ b/x/wasm/internal/keeper/handler_plugin.go @@ -24,8 +24,8 @@ type SDKMessageHandler struct { encoders msgEncoder } -func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, unpacker codectypes.AnyUnpacker, customEncoders ...*MessageEncoders) messenger { - encoders := DefaultEncoders(unpacker) +func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, unpacker codectypes.AnyUnpacker, portSource types.ICS20TransferPortSource, customEncoders ...*MessageEncoders) messenger { + encoders := DefaultEncoders(unpacker, portSource) for _, e := range customEncoders { encoders = encoders.Merge(e) } diff --git a/x/wasm/internal/keeper/handler_plugin_encoders.go b/x/wasm/internal/keeper/handler_plugin_encoders.go index 20b19414da..d2668f26d0 100644 --- a/x/wasm/internal/keeper/handler_plugin_encoders.go +++ b/x/wasm/internal/keeper/handler_plugin_encoders.go @@ -32,11 +32,11 @@ type MessageEncoders struct { Wasm func(sender sdk.AccAddress, msg *wasmvmtypes.WasmMsg) ([]sdk.Msg, error) } -func DefaultEncoders(unpacker codectypes.AnyUnpacker) MessageEncoders { +func DefaultEncoders(unpacker codectypes.AnyUnpacker, portSource types.ICS20TransferPortSource) MessageEncoders { return MessageEncoders{ Bank: EncodeBankMsg, Custom: NoCustomMsg, - IBC: EncodeIBCMsg, + IBC: EncodeIBCMsg(portSource), Staking: EncodeStakingMsg, Stargate: EncodeStargateMsg(unpacker), Wasm: EncodeWasmMsg, @@ -225,32 +225,33 @@ func EncodeWasmMsg(sender sdk.AccAddress, msg *wasmvmtypes.WasmMsg) ([]sdk.Msg, } } -func EncodeIBCMsg(ctx sdk.Context, sender sdk.AccAddress, contractIBCPortID string, msg *wasmvmtypes.IBCMsg) ([]sdk.Msg, error) { - switch { - case msg.CloseChannel != nil: - return []sdk.Msg{&channeltypes.MsgChannelCloseInit{ - PortId: PortIDForContract(sender), - ChannelId: msg.CloseChannel.ChannelID, - Signer: sender.String(), - }}, nil - case msg.Transfer != nil: - amount, err := convertWasmCoinToSdkCoin(msg.Transfer.Amount) - if err != nil { - return nil, sdkerrors.Wrap(err, "amount") +func EncodeIBCMsg(portSource types.ICS20TransferPortSource) func(ctx sdk.Context, sender sdk.AccAddress, contractIBCPortID string, msg *wasmvmtypes.IBCMsg) ([]sdk.Msg, error) { + return func(ctx sdk.Context, sender sdk.AccAddress, contractIBCPortID string, msg *wasmvmtypes.IBCMsg) ([]sdk.Msg, error) { + switch { + case msg.CloseChannel != nil: + return []sdk.Msg{&channeltypes.MsgChannelCloseInit{ + PortId: PortIDForContract(sender), + ChannelId: msg.CloseChannel.ChannelID, + Signer: sender.String(), + }}, nil + case msg.Transfer != nil: + amount, err := convertWasmCoinToSdkCoin(msg.Transfer.Amount) + if err != nil { + return nil, sdkerrors.Wrap(err, "amount") + } + msg := &ibctransfertypes.MsgTransfer{ + SourcePort: portSource.GetPort(ctx), + SourceChannel: msg.Transfer.ChannelID, + Token: amount, + Sender: sender.String(), + Receiver: msg.Transfer.ToAddress, + TimeoutHeight: convertWasmIBCTimeoutHeightToCosmosHeight(msg.Transfer.TimeoutBlock), + TimeoutTimestamp: convertWasmIBCTimeoutTimestampToCosmosTimestamp(msg.Transfer.TimeoutTimestamp), + } + return []sdk.Msg{msg}, nil + default: + return nil, sdkerrors.Wrap(types.ErrUnknownMsg, "Unknown variant of IBC") } - portID := ibctransfertypes.ModuleName //todo: port can be customized in genesis. make this more flexible - msg := &ibctransfertypes.MsgTransfer{ - SourcePort: portID, - SourceChannel: msg.Transfer.ChannelID, - Token: amount, - Sender: sender.String(), - Receiver: msg.Transfer.ToAddress, - TimeoutHeight: convertWasmIBCTimeoutHeightToCosmosHeight(msg.Transfer.TimeoutBlock), - TimeoutTimestamp: convertWasmIBCTimeoutTimestampToCosmosTimestamp(msg.Transfer.TimeoutTimestamp), - } - return []sdk.Msg{msg}, nil - default: - return nil, sdkerrors.Wrap(types.ErrUnknownMsg, "Unknown variant of IBC") } } diff --git a/x/wasm/internal/keeper/handler_plugin_encoders_test.go b/x/wasm/internal/keeper/handler_plugin_encoders_test.go index 0151a4bf33..bd70eeb6d1 100644 --- a/x/wasm/internal/keeper/handler_plugin_encoders_test.go +++ b/x/wasm/internal/keeper/handler_plugin_encoders_test.go @@ -2,6 +2,7 @@ package keeper import ( "encoding/json" + "github.com/CosmWasm/wasmd/x/wasm/internal/keeper/wasmtesting" codectypes "github.com/cosmos/cosmos-sdk/codec/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" @@ -55,9 +56,10 @@ func TestEncoding(t *testing.T) { require.NoError(t, err) cases := map[string]struct { - sender sdk.AccAddress - srcMsg wasmvmtypes.CosmosMsg - srcIBCPort string + sender sdk.AccAddress + srcMsg wasmvmtypes.CosmosMsg + srcContractIBCPort string + transferPortSource types.ICS20TransferPortSource // set if valid output []sdk.Msg // set if invalid @@ -349,8 +351,8 @@ func TestEncoding(t *testing.T) { isError: true, }, "IBC transfer with block timeout": { - sender: addr1, - srcIBCPort: "myIBCPort", + sender: addr1, + srcContractIBCPort: "myIBCPort", srcMsg: wasmvmtypes.CosmosMsg{ IBC: &wasmvmtypes.IBCMsg{ Transfer: &wasmvmtypes.TransferMsg{ @@ -364,9 +366,12 @@ func TestEncoding(t *testing.T) { }, }, }, + transferPortSource: wasmtesting.MockIBCTransferKeeper{GetPortFn: func(ctx sdk.Context) string { + return "myTransferPort" + }}, output: []sdk.Msg{ &ibctransfertypes.MsgTransfer{ - SourcePort: "transfer", + SourcePort: "myTransferPort", SourceChannel: "myChanID", Token: sdk.Coin{ Denom: "ALX", @@ -379,8 +384,8 @@ func TestEncoding(t *testing.T) { }, }, "IBC transfer with time timeout": { - sender: addr1, - srcIBCPort: "myIBCPort", + sender: addr1, + srcContractIBCPort: "myIBCPort", srcMsg: wasmvmtypes.CosmosMsg{ IBC: &wasmvmtypes.IBCMsg{ Transfer: &wasmvmtypes.TransferMsg{ @@ -394,6 +399,9 @@ func TestEncoding(t *testing.T) { }, }, }, + transferPortSource: wasmtesting.MockIBCTransferKeeper{GetPortFn: func(ctx sdk.Context) string { + return "transfer" + }}, output: []sdk.Msg{ &ibctransfertypes.MsgTransfer{ SourcePort: "transfer", @@ -409,8 +417,8 @@ func TestEncoding(t *testing.T) { }, }, "IBC close channel": { - sender: addr1, - srcIBCPort: "myIBCPort", + sender: addr1, + srcContractIBCPort: "myIBCPort", srcMsg: wasmvmtypes.CosmosMsg{ IBC: &wasmvmtypes.IBCMsg{ CloseChannel: &wasmvmtypes.CloseChannelMsg{ @@ -428,12 +436,11 @@ func TestEncoding(t *testing.T) { }, } encodingConfig := MakeEncodingConfig(t) - encoder := DefaultEncoders(encodingConfig.Marshaler) for name, tc := range cases { - tc := tc t.Run(name, func(t *testing.T) { var ctx sdk.Context - res, err := encoder.Encode(ctx, tc.sender, tc.srcIBCPort, tc.srcMsg) + encoder := DefaultEncoders(encodingConfig.Marshaler, tc.transferPortSource) + res, err := encoder.Encode(ctx, tc.sender, tc.srcContractIBCPort, tc.srcMsg) if tc.isError { require.Error(t, err) } else { diff --git a/x/wasm/internal/keeper/keeper.go b/x/wasm/internal/keeper/keeper.go index e8cfad3731..206ab65545 100644 --- a/x/wasm/internal/keeper/keeper.go +++ b/x/wasm/internal/keeper/keeper.go @@ -97,6 +97,7 @@ func NewKeeper( channelKeeper types.ChannelKeeper, portKeeper types.PortKeeper, capabilityKeeper types.CapabilityKeeper, + portSource types.ICS20TransferPortSource, router sdk.Router, queryRouter GRPCQueryRouter, homeDir string, @@ -122,7 +123,7 @@ func NewKeeper( ChannelKeeper: channelKeeper, portKeeper: portKeeper, capabilityKeeper: capabilityKeeper, - messenger: NewDefaultMessageHandler(router, channelKeeper, capabilityKeeper, cdc), + messenger: NewDefaultMessageHandler(router, channelKeeper, capabilityKeeper, cdc, portSource), queryGasLimit: wasmConfig.SmartQueryGasLimit, authZPolicy: DefaultAuthorizationPolicy{}, paramSpace: paramSpace, diff --git a/x/wasm/internal/keeper/options_test.go b/x/wasm/internal/keeper/options_test.go index eac62378f0..eb6860f7fd 100644 --- a/x/wasm/internal/keeper/options_test.go +++ b/x/wasm/internal/keeper/options_test.go @@ -43,7 +43,7 @@ func TestConstructorOptions(t *testing.T) { } for name, spec := range specs { t.Run(name, func(t *testing.T) { - k := NewKeeper(nil, nil, paramtypes.NewSubspace(nil, nil, nil, nil, ""), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, "tempDir", types.DefaultWasmConfig(), SupportedFeatures, spec.srcOpt) + k := NewKeeper(nil, nil, paramtypes.NewSubspace(nil, nil, nil, nil, ""), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, "tempDir", types.DefaultWasmConfig(), SupportedFeatures, spec.srcOpt) spec.verify(k) }) } diff --git a/x/wasm/internal/keeper/test_common.go b/x/wasm/internal/keeper/test_common.go index 601c3837dc..80f40d2286 100644 --- a/x/wasm/internal/keeper/test_common.go +++ b/x/wasm/internal/keeper/test_common.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "encoding/json" "fmt" + "github.com/CosmWasm/wasmd/x/wasm/internal/keeper/wasmtesting" types "github.com/CosmWasm/wasmd/x/wasm/internal/types" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" @@ -292,6 +293,7 @@ func createTestInput( ibcKeeper.ChannelKeeper, &ibcKeeper.PortKeeper, scopedWasmKeeper, + wasmtesting.MockIBCTransferKeeper{}, router, querier, tempDir, diff --git a/x/wasm/internal/keeper/wasmtesting/mock_keepers.go b/x/wasm/internal/keeper/wasmtesting/mock_keepers.go index 7d216911bc..f6eba2b5a4 100644 --- a/x/wasm/internal/keeper/wasmtesting/mock_keepers.go +++ b/x/wasm/internal/keeper/wasmtesting/mock_keepers.go @@ -1,6 +1,7 @@ package wasmtesting import ( + "github.com/CosmWasm/wasmd/x/wasm/internal/types" sdk "github.com/cosmos/cosmos-sdk/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" @@ -87,7 +88,6 @@ func (m MockCapabilityKeeper) ClaimCapability(ctx sdk.Context, cap *capabilityty panic("not supposed to be called!") } return m.ClaimCapabilityFn(ctx, cap, name) - } func (m MockCapabilityKeeper) AuthenticateCapability(ctx sdk.Context, capability *capabilitytypes.Capability, name string) bool { @@ -95,5 +95,17 @@ func (m MockCapabilityKeeper) AuthenticateCapability(ctx sdk.Context, capability panic("not supposed to be called!") } return m.AuthenticateCapabilityFn(ctx, capability, name) +} +var _ types.ICS20TransferPortSource = &MockIBCTransferKeeper{} + +type MockIBCTransferKeeper struct { + GetPortFn func(ctx sdk.Context) string +} + +func (m MockIBCTransferKeeper) GetPort(ctx sdk.Context) string { + if m.GetPortFn == nil { + panic("not expected to be called") + } + return m.GetPortFn(ctx) } diff --git a/x/wasm/internal/types/expected_keepers.go b/x/wasm/internal/types/expected_keepers.go index 2638f74fcd..6baf00a29a 100644 --- a/x/wasm/internal/types/expected_keepers.go +++ b/x/wasm/internal/types/expected_keepers.go @@ -88,3 +88,8 @@ type CapabilityKeeper interface { ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) error AuthenticateCapability(ctx sdk.Context, capability *capabilitytypes.Capability, name string) bool } + +// ICS20TransferPortSource is a subset of the ibc transfer keeper. +type ICS20TransferPortSource interface { + GetPort(ctx sdk.Context) string +}