Skip to content

Commit

Permalink
Better contract callback params
Browse files Browse the repository at this point in the history
  • Loading branch information
alpe committed Aug 18, 2020
1 parent 7d760b4 commit 239c0c3
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 118 deletions.
24 changes: 0 additions & 24 deletions x/wasm/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ func NewHandler(k Keeper) sdk.Handler {
return handleUpdateContractAdmin(ctx, k, msg)
case *MsgClearAdmin:
return handleClearContractAdmin(ctx, k, msg)
case *MsgWasmIBCCall:
return handleIBCCall(ctx, k, msg)
default:
errMsg := fmt.Sprintf("unrecognized wasm message type: %T", msg)
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
Expand Down Expand Up @@ -166,25 +164,3 @@ func handleClearContractAdmin(ctx sdk.Context, k Keeper, msg *MsgClearAdmin) (*s
Events: append(events, ourEvent).ToABCIEvents(),
}, nil
}

func handleIBCCall(ctx sdk.Context, k Keeper, msg *MsgWasmIBCCall) (*sdk.Result, error) {
if err := k.IBCCallFromContract(ctx, msg.SourcePort, msg.SourceChannel, msg.Sender, msg.TimeoutHeight, msg.TimeoutTimestamp, msg.Msg); err != nil {
return nil, err
}

//k.Logger(ctx).Info("IBC transfer: %s from %s to %s", msg.Amount, msg.Sender, msg.Receiver)

//ctx.EventManager().EmitEvent(
// sdk.NewEvent(
// sdk.EventTypeMessage,
// sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
// sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender.String()),
// sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver),
// ),
//)
//
return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil

}
21 changes: 4 additions & 17 deletions x/wasm/ibc.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (i IBCHandler) OnChanOpenInit(ctx sdk.Context, order channeltypes.Order, co
return sdkerrors.Wrapf(err, "contract port id")
}

_, err = i.keeper.AcceptChannel(ctx, contractAddr, order, version, connectionHops, cosmwasm.IBCInfo{
err = i.keeper.AcceptChannel(ctx, contractAddr, order, version, connectionHops, cosmwasm.IBCInfo{
PortID: portID,
ChannelID: channelID,
})
Expand All @@ -50,26 +50,13 @@ func (i IBCHandler) OnChanOpenTry(ctx sdk.Context, order channeltypes.Order, con
return sdkerrors.Wrapf(err, "contract port id")
}

restrictCounterpartyVersions, err := i.keeper.AcceptChannel(ctx, contractAddr, order, version, connectionHops, cosmwasm.IBCInfo{
err = i.keeper.AcceptChannel(ctx, contractAddr, order, version, connectionHops, cosmwasm.IBCInfo{
PortID: portID,
ChannelID: channelID,
})
if err != nil {
return err
}
if len(restrictCounterpartyVersions) != 0 {
var found bool
for _, accept := range restrictCounterpartyVersions {
if accept == counterpartyVersion {
found = true
break
}
}
if !found {
return sdkerrors.Wrapf(types.ErrInvalidCounterparty, "not in supported versions: %q", restrictCounterpartyVersions)
}
}

// Claim channel capability passed back by IBC module
if err := i.keeper.ClaimCapability(ctx, channelCap, host.ChannelCapabilityPath(portID, channelID)); err != nil {
return sdkerrors.Wrap(channeltypes.ErrChannelCapabilityNotFound, err.Error())
Expand All @@ -86,7 +73,7 @@ func (i IBCHandler) OnChanOpenAck(ctx sdk.Context, portID, channelID string, cou
if !ok {
return sdkerrors.Wrap(types.ErrInvalidCounterparty, "not found")
}
return i.keeper.OnOpenChannel(ctx, contractAddr, channelInfo.Counterparty, cosmwasm.IBCInfo{
return i.keeper.OnOpenChannel(ctx, contractAddr, channelInfo.Counterparty, counterpartyVersion, cosmwasm.IBCInfo{
PortID: portID,
ChannelID: channelID,
})
Expand All @@ -101,7 +88,7 @@ func (i IBCHandler) OnChanOpenConfirm(ctx sdk.Context, portID, channelID string)
if !ok {
return sdkerrors.Wrap(types.ErrInvalidCounterparty, "not found")
}
return i.keeper.OnOpenChannel(ctx, contractAddr, channelInfo.Counterparty, cosmwasm.IBCInfo{
return i.keeper.OnOpenChannel(ctx, contractAddr, channelInfo.Counterparty, channelInfo.Version, cosmwasm.IBCInfo{
PortID: portID,
ChannelID: channelID,
})
Expand Down
6 changes: 3 additions & 3 deletions x/wasm/internal/keeper/cosmwasm/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type OnConnectIBCResponse struct {

// AcceptChannelResponse is a frame for flow control in wasmd.
type AcceptChannelResponse struct {
Result bool `json:"result"`
Reason string `json:"reason"`
RestrictCounterpartyVersions []string `json:"accepted_counterpary_versions"`
Result bool `json:"result"`
Reason string `json:"reason"`
RestrictCounterpartyVersions string `json:"accepted_counterparty_version"` // todo: return only 1
}
83 changes: 21 additions & 62 deletions x/wasm/internal/keeper/ibc.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package keeper

import (
"encoding/json"
"strings"

wasm "github.com/CosmWasm/go-cosmwasm"
Expand Down Expand Up @@ -64,23 +63,26 @@ func (k Keeper) ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability
return k.ScopedKeeper.ClaimCapability(ctx, cap, name)
}

type IBCCallbacks interface {
// IBCContractCallbacks the contract methods that should be implemeted in rust without `ctx sdk.Context`
type IBCContractCallbacks interface {
// todo: Rename methods #214

// IBC packet lifecycle
OnReceive(ctx sdk.Context, hash []byte, params cosmwasm.Env, msg []byte, store prefix.Store, api wasm.GoAPI, querier QueryHandler, meter sdk.GasMeter, gas uint64) (*cosmwasm.OnReceiveIBCResponse, uint64, error)
OnAcknowledgement(ctx sdk.Context, hash []byte, params cosmwasm.Env, originalData []byte, acknowledgement []byte, store prefix.Store, api wasm.GoAPI, querier QueryHandler, meter sdk.GasMeter, gas uint64) (*cosmwasm.OnAcknowledgeIBCResponse, uint64, error)
OnTimeout(ctx sdk.Context, hash []byte, params cosmwasm.Env, msg []byte, store prefix.Store, api wasm.GoAPI, querier QueryHandler, meter sdk.GasMeter, gas uint64) (*cosmwasm.OnTimeoutIBCResponse, uint64, error)
OnReceive(hash []byte, params cosmwasm.Env, msg []byte, store prefix.Store, api wasm.GoAPI, querier QueryHandler, meter sdk.GasMeter, gas uint64) (*cosmwasm.OnReceiveIBCResponse, uint64, error)
OnAcknowledgement(hash []byte, params cosmwasm.Env, originalData []byte, acknowledgement []byte, store prefix.Store, api wasm.GoAPI, querier QueryHandler, meter sdk.GasMeter, gas uint64) (*cosmwasm.OnAcknowledgeIBCResponse, uint64, error)
OnTimeout(hash []byte, params cosmwasm.Env, msg []byte, store prefix.Store, api wasm.GoAPI, querier QueryHandler, meter sdk.GasMeter, gas uint64) (*cosmwasm.OnTimeoutIBCResponse, uint64, error)
// IBC channel livecycle
AcceptChannel(ctx sdk.Context, hash []byte, params cosmwasm.Env, order channeltypes.Order, version string, connectionHops []string, store prefix.Store, api wasm.GoAPI, querier QueryHandler, meter sdk.GasMeter, gas uint64) (*cosmwasm.AcceptChannelResponse, uint64, error)
OnConnect(ctx sdk.Context, hash []byte, params cosmwasm.Env, counterpartyPortID string, counterpartyChannelID string, store prefix.Store, api wasm.GoAPI, querier QueryHandler, meter sdk.GasMeter, gas uint64) (*cosmwasm.OnConnectIBCResponse, uint64, error)
AcceptChannel(hash []byte, params cosmwasm.Env, order channeltypes.Order, version string, connectionHops []string, store prefix.Store, api wasm.GoAPI, querier QueryHandler, meter sdk.GasMeter, gas uint64) (*cosmwasm.AcceptChannelResponse, uint64, error)
OnConnect(hash []byte, params cosmwasm.Env, counterpartyPortID string, counterpartyChannelID string, store prefix.Store, api wasm.GoAPI, querier QueryHandler, meter sdk.GasMeter, gas uint64) (*cosmwasm.OnConnectIBCResponse, uint64, error)
//OnClose(ctx sdk.Context, hash []byte, params cosmwasm.Env, counterpartyPortID string, counterpartyChannelID string, store prefix.Store, api wasm.GoAPI, querier QueryHandler, meter sdk.GasMeter, gas uint64) (*cosmwasm.OnCloseIBCResponse, uint64, error)
}

var MockContracts = make(map[string]IBCCallbacks, 0)
var MockContracts = make(map[string]IBCContractCallbacks, 0)

func (k Keeper) AcceptChannel(ctx sdk.Context, contractAddr sdk.AccAddress, order channeltypes.Order, version string, connectionHops []string, ibcInfo cosmwasm.IBCInfo) ([]string, error) {
func (k Keeper) AcceptChannel(ctx sdk.Context, contractAddr sdk.AccAddress, order channeltypes.Order, version string, connectionHops []string, ibcInfo cosmwasm.IBCInfo) error {
codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddr)
if err != nil {
return nil, err
return err
}

var sender sdk.AccAddress // we don't know the sender
Expand All @@ -97,15 +99,15 @@ func (k Keeper) AcceptChannel(ctx sdk.Context, contractAddr sdk.AccAddress, orde
if !ok { // hack for testing without wasmer
panic("not supported")
}
res, gasUsed, execErr := mock.AcceptChannel(ctx, codeInfo.CodeHash, params, order, version, connectionHops, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
res, gasUsed, execErr := mock.AcceptChannel(codeInfo.CodeHash, params, order, version, connectionHops, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
consumeGas(ctx, gasUsed)
if execErr != nil {
return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
return sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
}
if !res.Result { // todo: would it make more sense to let the contract return an error instead?
return nil, sdkerrors.Wrap(types.ErrInvalid, res.Reason)
return sdkerrors.Wrap(types.ErrInvalid, res.Reason)
}
return res.RestrictCounterpartyVersions, nil
return nil
}

func (k Keeper) OnRecvPacket(ctx sdk.Context, contractAddr sdk.AccAddress, payloadData []byte, ibcInfo cosmwasm.IBCInfo) ([]byte, error) {
Expand All @@ -128,7 +130,7 @@ func (k Keeper) OnRecvPacket(ctx sdk.Context, contractAddr sdk.AccAddress, paylo
if !ok { // hack for testing without wasmer
panic("not supported")
}
res, gasUsed, execErr := mock.OnReceive(ctx, codeInfo.CodeHash, params, payloadData, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
res, gasUsed, execErr := mock.OnReceive(codeInfo.CodeHash, params, payloadData, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
consumeGas(ctx, gasUsed)
if execErr != nil {
return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
Expand Down Expand Up @@ -167,7 +169,7 @@ func (k Keeper) OnAckPacket(ctx sdk.Context, contractAddr sdk.AccAddress, payloa
if !ok {
panic("not supported")
}
res, gasUsed, execErr := mock.OnAcknowledgement(ctx, codeInfo.CodeHash, params, payloadData, acknowledgement, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
res, gasUsed, execErr := mock.OnAcknowledgement(codeInfo.CodeHash, params, payloadData, acknowledgement, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
consumeGas(ctx, gasUsed)
if execErr != nil {
return sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
Expand Down Expand Up @@ -206,7 +208,7 @@ func (k Keeper) OnTimeoutPacket(ctx sdk.Context, contractAddr sdk.AccAddress, pa
if !ok { // hack for testing without wasmer
panic("not supported")
}
res, gasUsed, execErr := mock.OnTimeout(ctx, codeInfo.CodeHash, params, payloadData, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
res, gasUsed, execErr := mock.OnTimeout(codeInfo.CodeHash, params, payloadData, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
consumeGas(ctx, gasUsed)
if execErr != nil {
return sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
Expand All @@ -225,7 +227,7 @@ func (k Keeper) OnTimeoutPacket(ctx sdk.Context, contractAddr sdk.AccAddress, pa
return nil
}

func (k Keeper) OnOpenChannel(ctx sdk.Context, contractAddr sdk.AccAddress, counterparty channeltypes.Counterparty, ibcInfo cosmwasm.IBCInfo) error {
func (k Keeper) OnOpenChannel(ctx sdk.Context, contractAddr sdk.AccAddress, counterparty channeltypes.Counterparty, version string, ibcInfo cosmwasm.IBCInfo) error {
codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddr)
if err != nil {
return err
Expand All @@ -245,7 +247,7 @@ func (k Keeper) OnOpenChannel(ctx sdk.Context, contractAddr sdk.AccAddress, coun
if !ok { // hack for testing without wasmer
panic("not supported")
}
res, gasUsed, execErr := mock.OnConnect(ctx, codeInfo.CodeHash, params, counterparty.PortId, counterparty.ChannelId, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
res, gasUsed, execErr := mock.OnConnect(codeInfo.CodeHash, params, counterparty.PortId, counterparty.ChannelId, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
consumeGas(ctx, gasUsed)
if execErr != nil {
return sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
Expand All @@ -263,46 +265,3 @@ func (k Keeper) OnOpenChannel(ctx sdk.Context, contractAddr sdk.AccAddress, coun
}
return nil
}

func (k Keeper) IBCCallFromContract(ctx sdk.Context, sourcePort, sourceChannel string, sender sdk.AccAddress, timeoutHeight, timeoutTimestamp uint64, msg json.RawMessage) error {
contractInfo := k.GetContractInfo(ctx, sender)
if contractInfo == nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "unknown contract")
}
if sourcePort != contractInfo.IBCPortID {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "not sender's port")
}

sourceChannelEnd, found := k.ChannelKeeper.GetChannel(ctx, sourcePort, sourceChannel)
if !found {
return sdkerrors.Wrap(channeltypes.ErrChannelNotFound, sourceChannel)
}

destinationPort := sourceChannelEnd.GetCounterparty().GetPortID()
destinationChannel := sourceChannelEnd.GetCounterparty().GetChannelID()

// get the next sequence
sequence, found := k.ChannelKeeper.GetNextSequenceSend(ctx, sourcePort, sourceChannel)
if !found {
return sdkerrors.Wrapf(
channeltypes.ErrSequenceSendNotFound,
"source port: %s, source channel: %s", sourcePort, sourceChannel,
)
}
channelCap, ok := k.ScopedKeeper.GetCapability(ctx, host.ChannelCapabilityPath(sourcePort, sourceChannel))
if !ok {
return sdkerrors.Wrap(channeltypes.ErrChannelCapabilityNotFound, "module does not own channel capability")
}

packet := channeltypes.NewPacket(
msg,
sequence,
sourcePort,
sourceChannel,
destinationPort,
destinationChannel,
timeoutHeight,
timeoutTimestamp,
)
return k.ChannelKeeper.SendPacket(ctx, channelCap, packet)
}
Loading

0 comments on commit 239c0c3

Please sign in to comment.