diff --git a/x/wasm/ibc.go b/x/wasm/ibc.go index d4f68b2b71..ce53b3abe3 100644 --- a/x/wasm/ibc.go +++ b/x/wasm/ibc.go @@ -50,7 +50,7 @@ func (i IBCHandler) OnChanOpenInit( if err := ValidateChannelParams(channelID); err != nil { return "", err } - contractAddr, err := i.keeper.ContractFromPortID(portID) + contractAddr, err := i.keeper.ContractFromPortID(ctx, portID) if err != nil { return "", errorsmod.Wrapf(err, "contract port id") } @@ -102,7 +102,7 @@ func (i IBCHandler) OnChanOpenTry( return "", err } - contractAddr, err := i.keeper.ContractFromPortID(portID) + contractAddr, err := i.keeper.ContractFromPortID(ctx, portID) if err != nil { return "", errorsmod.Wrapf(err, "contract port id") } @@ -150,7 +150,7 @@ func (i IBCHandler) OnChanOpenAck( counterpartyChannelID string, counterpartyVersion string, ) error { - contractAddr, err := i.keeper.ContractFromPortID(portID) + contractAddr, err := i.keeper.ContractFromPortID(ctx, portID) if err != nil { return errorsmod.Wrapf(err, "contract port id") } @@ -176,7 +176,7 @@ func (i IBCHandler) OnChanOpenAck( // OnChanOpenConfirm implements the IBCModule interface func (i IBCHandler) OnChanOpenConfirm(ctx sdk.Context, portID, channelID string) error { - contractAddr, err := i.keeper.ContractFromPortID(portID) + contractAddr, err := i.keeper.ContractFromPortID(ctx, portID) if err != nil { return errorsmod.Wrapf(err, "contract port id") } @@ -198,7 +198,7 @@ func (i IBCHandler) OnChanOpenConfirm(ctx sdk.Context, portID, channelID string) // OnChanCloseInit implements the IBCModule interface func (i IBCHandler) OnChanCloseInit(ctx sdk.Context, portID, channelID string) error { - contractAddr, err := i.keeper.ContractFromPortID(portID) + contractAddr, err := i.keeper.ContractFromPortID(ctx, portID) if err != nil { return errorsmod.Wrapf(err, "contract port id") } @@ -226,7 +226,7 @@ func (i IBCHandler) OnChanCloseInit(ctx sdk.Context, portID, channelID string) e // OnChanCloseConfirm implements the IBCModule interface func (i IBCHandler) OnChanCloseConfirm(ctx sdk.Context, portID, channelID string) error { // counterparty has closed the channel - contractAddr, err := i.keeper.ContractFromPortID(portID) + contractAddr, err := i.keeper.ContractFromPortID(ctx, portID) if err != nil { return errorsmod.Wrapf(err, "contract port id") } @@ -267,7 +267,7 @@ func (i IBCHandler) OnRecvPacket( packet channeltypes.Packet, relayer sdk.AccAddress, ) ibcexported.Acknowledgement { - contractAddr, err := i.keeper.ContractFromPortID(packet.DestinationPort) + contractAddr, err := i.keeper.ContractFromPortID(ctx, packet.DestinationPort) if err != nil { // this must not happen as ports were registered before panic(errorsmod.Wrapf(err, "contract port id")) @@ -295,7 +295,7 @@ func (i IBCHandler) OnAcknowledgementPacket( acknowledgement []byte, relayer sdk.AccAddress, ) error { - contractAddr, err := i.keeper.ContractFromPortID(packet.SourcePort) + contractAddr, err := i.keeper.ContractFromPortID(ctx, packet.SourcePort) if err != nil { return errorsmod.Wrapf(err, "contract port id") } @@ -313,7 +313,7 @@ func (i IBCHandler) OnAcknowledgementPacket( // OnTimeoutPacket implements the IBCModule interface func (i IBCHandler) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error { - contractAddr, err := i.keeper.ContractFromPortID(packet.SourcePort) + contractAddr, err := i.keeper.ContractFromPortID(ctx, packet.SourcePort) if err != nil { return errorsmod.Wrapf(err, "contract port id") } diff --git a/x/wasm/ibc_test.go b/x/wasm/ibc_test.go index 2d0dec2a90..5d95f35e7f 100644 --- a/x/wasm/ibc_test.go +++ b/x/wasm/ibc_test.go @@ -1,6 +1,7 @@ package wasm import ( + "context" "testing" wasmvmtypes "github.com/CosmWasm/wasmvm/types" @@ -202,14 +203,14 @@ var _ types.IBCContractKeeper = &IBCContractKeeperMock{} type IBCContractKeeperMock struct { types.IBCContractKeeper OnRecvPacketFn func(ctx sdk.Context, contractAddr sdk.AccAddress, msg wasmvmtypes.IBCPacketReceiveMsg) (ibcexported.Acknowledgement, error) - ContractFromPortIDFn func(portID string) (sdk.AccAddress, error) + ContractFromPortIDFn func(ctx context.Context, portID string) (sdk.AccAddress, error) } -func (m IBCContractKeeperMock) ContractFromPortID(portID string) (sdk.AccAddress, error) { +func (m IBCContractKeeperMock) ContractFromPortID(ctx context.Context, portID string) (sdk.AccAddress, error) { if m.ContractFromPortIDFn == nil { panic("not expected to be called") } - return m.ContractFromPortIDFn(portID) + return m.ContractFromPortIDFn(ctx, portID) } func (m IBCContractKeeperMock) OnRecvPacket(ctx sdk.Context, contractAddr sdk.AccAddress, msg wasmvmtypes.IBCPacketReceiveMsg) (ibcexported.Acknowledgement, error) { diff --git a/x/wasm/keeper/handler_plugin_encoders.go b/x/wasm/keeper/handler_plugin_encoders.go index 39ee412df3..ea33f22225 100644 --- a/x/wasm/keeper/handler_plugin_encoders.go +++ b/x/wasm/keeper/handler_plugin_encoders.go @@ -308,7 +308,7 @@ func EncodeIBCMsg( switch { case msg.CloseChannel != nil: return []sdk.Msg{&channeltypes.MsgChannelCloseInit{ - PortId: ibcPortAllocator.PortIDForContract(sender), + PortId: ibcPortAllocator.PortIDForContract(ctx, sender), ChannelId: msg.CloseChannel.ChannelID, Signer: sender.String(), }}, nil diff --git a/x/wasm/keeper/handler_plugin_encoders_test.go b/x/wasm/keeper/handler_plugin_encoders_test.go index ef1e7ea749..35785d8cc3 100644 --- a/x/wasm/keeper/handler_plugin_encoders_test.go +++ b/x/wasm/keeper/handler_plugin_encoders_test.go @@ -6,7 +6,7 @@ import ( wasmvmtypes "github.com/CosmWasm/wasmvm/types" "github.com/cosmos/gogoproto/proto" ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" //nolint:staticcheck + clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/x/wasm/keeper/ibc.go b/x/wasm/keeper/ibc.go index 00f0e98930..32263eb25b 100644 --- a/x/wasm/keeper/ibc.go +++ b/x/wasm/keeper/ibc.go @@ -1,6 +1,8 @@ package keeper import ( + "context" + "encoding/hex" "strings" capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" @@ -26,7 +28,7 @@ func (k Keeper) bindIbcPort(ctx sdk.Context, portID string) error { // Returns success if we already registered or just registered and error if we cannot // (lack of permissions or someone else has it) func (k Keeper) ensureIBCPort(ctx sdk.Context, contractAddr sdk.AccAddress) (string, error) { - portID := k.ibcPortNameGenerator.PortIDForContract(contractAddr) + portID := k.ibcPortNameGenerator.PortIDForContract(ctx, contractAddr) if _, ok := k.capabilityKeeper.GetCapability(ctx, host.PortPath(portID)); ok { return portID, nil } @@ -34,25 +36,46 @@ func (k Keeper) ensureIBCPort(ctx sdk.Context, contractAddr sdk.AccAddress) (str } type IBCPortNameGenerator interface { - PortIDForContract(addr sdk.AccAddress) string - ContractFromPortID(portID string) (sdk.AccAddress, error) + // PortIDForContract converts an address into an ibc port-id. + PortIDForContract(ctx context.Context, addr sdk.AccAddress) string + // ContractFromPortID returns the contract address for given port-id. The method does not check if the contract exists + ContractFromPortID(ctx context.Context, portID string) (sdk.AccAddress, error) } const portIDPrefix = "wasm." +// DefaultIBCPortNameGenerator uses Bech32 address string in port-id type DefaultIBCPortNameGenerator struct{} -func (DefaultIBCPortNameGenerator) PortIDForContract(addr sdk.AccAddress) string { +// PortIDForContract coverts contract into port-id in the format "wasm." +func (DefaultIBCPortNameGenerator) PortIDForContract(ctx context.Context, addr sdk.AccAddress) string { return portIDPrefix + addr.String() } -func (DefaultIBCPortNameGenerator) ContractFromPortID(portID string) (sdk.AccAddress, error) { +// ContractFromPortID reads the contract address from bech32 address in the port-id. +func (DefaultIBCPortNameGenerator) ContractFromPortID(ctx context.Context, portID string) (sdk.AccAddress, error) { if !strings.HasPrefix(portID, portIDPrefix) { return nil, errorsmod.Wrapf(types.ErrInvalid, "without prefix") } return sdk.AccAddressFromBech32(portID[len(portIDPrefix):]) } +// HexIBCPortNameGenerator uses Hex address string +type HexIBCPortNameGenerator struct{} + +// PortIDForContract coverts contract into port-id in the format "wasm." +func (HexIBCPortNameGenerator) PortIDForContract(ctx context.Context, addr sdk.AccAddress) string { + return portIDPrefix + hex.EncodeToString(addr) +} + +// ContractFromPortID reads the contract address from hex address in the port-id. +func (HexIBCPortNameGenerator) ContractFromPortID(ctx context.Context, portID string) (sdk.AccAddress, error) { + if !strings.HasPrefix(portID, portIDPrefix) { + return nil, errorsmod.Wrapf(types.ErrInvalid, "without prefix") + } + return sdk.AccAddressFromHexUnsafe(portID[len(portIDPrefix):]) +} + // AuthenticateCapability wraps the scopedKeeper's AuthenticateCapability function func (k Keeper) AuthenticateCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) bool { return k.capabilityKeeper.AuthenticateCapability(ctx, cap, name) diff --git a/x/wasm/keeper/ibc_test.go b/x/wasm/keeper/ibc_test.go index ab20df2db3..2c0465e02f 100644 --- a/x/wasm/keeper/ibc_test.go +++ b/x/wasm/keeper/ibc_test.go @@ -36,7 +36,7 @@ func TestBindingPortForIBCContractOnInstantiate(t *testing.T) { require.NoError(t, err) require.NotEqual(t, example.Contract, addr) - portID2 := keepers.WasmKeeper.ibcPortNameGenerator.PortIDForContract(addr) + portID2 := keepers.WasmKeeper.ibcPortNameGenerator.PortIDForContract(ctx, addr) owner, _, err = keepers.IBCKeeper.PortKeeper.LookupModuleByPort(ctx, portID2) require.NoError(t, err) require.Equal(t, "wasm", owner) @@ -72,7 +72,7 @@ func TestContractFromPortID(t *testing.T) { } for name, spec := range specs { t.Run(name, func(t *testing.T) { - gotAddr, gotErr := DefaultIBCPortNameGenerator{}.ContractFromPortID(spec.srcPort) + gotAddr, gotErr := DefaultIBCPortNameGenerator{}.ContractFromPortID(nil, spec.srcPort) if spec.expErr { require.Error(t, gotErr) return diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 9ca1c48b20..0a730c3f2a 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -1195,8 +1195,9 @@ func (k Keeper) importContract(ctx context.Context, contractAddr sdk.AccAddress, return k.importContractState(ctx, contractAddr, state) } -func (k Keeper) ContractFromPortID(portID string) (sdk.AccAddress, error) { - return k.ibcPortNameGenerator.ContractFromPortID(portID) +// ContractFromPortID returns the contract address for given port-id. The method does not check if the contract exists +func (k Keeper) ContractFromPortID(ctx context.Context, portID string) (sdk.AccAddress, error) { + return k.ibcPortNameGenerator.ContractFromPortID(ctx, portID) } func (k Keeper) newQueryHandler(ctx sdk.Context, contractAddress sdk.AccAddress) QueryHandler { diff --git a/x/wasm/relay_pingpong_test.go b/x/wasm/relay_pingpong_test.go index 7cb81aca33..3a326f31f9 100644 --- a/x/wasm/relay_pingpong_test.go +++ b/x/wasm/relay_pingpong_test.go @@ -67,8 +67,8 @@ func TestPinPong(t *testing.T) { pongContract.contractAddr = pongContractAddr var ( - sourcePortID = wasmkeeper.DefaultIBCPortNameGenerator{}.PortIDForContract(pingContractAddr) - counterpartyPortID = wasmkeeper.DefaultIBCPortNameGenerator{}.PortIDForContract(pongContractAddr) + sourcePortID = wasmkeeper.DefaultIBCPortNameGenerator{}.PortIDForContract(nil, pingContractAddr) + counterpartyPortID = wasmkeeper.DefaultIBCPortNameGenerator{}.PortIDForContract(nil, pongContractAddr) ) path := wasmibctesting.NewPath(chainA, chainB) diff --git a/x/wasm/types/exported_keepers.go b/x/wasm/types/exported_keepers.go index f229b5eccc..742bd79ccf 100644 --- a/x/wasm/types/exported_keepers.go +++ b/x/wasm/types/exported_keepers.go @@ -122,5 +122,5 @@ type IBCContractKeeper interface { AuthenticateCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) bool // ContractFromPortID resolves contract address from the ibc port-di - ContractFromPortID(portID string) (sdk.AccAddress, error) + ContractFromPortID(ctx context.Context, portID string) (sdk.AccAddress, error) }