Skip to content

Commit

Permalink
Add flattened msgResponses to SubMsgResponse
Browse files Browse the repository at this point in the history
  • Loading branch information
webmaster128 committed Jan 31, 2024
1 parent 796907e commit 705805c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 33 deletions.
56 changes: 30 additions & 26 deletions x/wasm/keeper/handler_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

Expand Down Expand Up @@ -66,18 +67,19 @@ func NewSDKMessageHandler(cdc codec.Codec, router MessageRouter, encoders msgEnc
}
}

func (h SDKMessageHandler) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) {
func (h SDKMessageHandler) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, msgResponses [][]*codectypes.Any, err error) {
sdkMsgs, err := h.encoders.Encode(ctx, contractAddr, contractIBCPortID, msg)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
for _, sdkMsg := range sdkMsgs {
res, err := h.handleSdkMessage(ctx, contractAddr, sdkMsg)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
// append data
// append data and msgResponses
data = append(data, res.Data)
msgResponses = append(msgResponses, res.MsgResponses)
// append events
sdkEvents := make([]sdk.Event, len(res.Events))
for i := range res.Events {
Expand Down Expand Up @@ -141,19 +143,19 @@ func NewMessageHandlerChain(first Messenger, others ...Messenger) *MessageHandle
// order to find the right one to process given message. If a handler cannot
// process given message (returns ErrUnknownMsg), its result is ignored and the
// next handler is executed.
func (m MessageHandlerChain) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) ([]sdk.Event, [][]byte, error) {
func (m MessageHandlerChain) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) ([]sdk.Event, [][]byte, [][]*codectypes.Any, error) {
for _, h := range m.handlers {
events, data, err := h.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg)
events, data, msgResponses, err := h.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg)
switch {
case err == nil:
return events, data, nil
return events, data, msgResponses, nil
case errors.Is(err, types.ErrUnknownMsg):
continue
default:
return events, data, err
return events, data, msgResponses, err
}
}
return nil, nil, errorsmod.Wrap(types.ErrUnknownMsg, "no handler found")
return nil, nil, nil, errorsmod.Wrap(types.ErrUnknownMsg, "no handler found")
}

// IBCRawPacketHandler handles IBC.SendPacket messages which are published to an IBC channel.
Expand All @@ -173,67 +175,69 @@ func NewIBCRawPacketHandler(ics4Wrapper types.ICS4Wrapper, channelKeeper types.C
}

// DispatchMsg publishes a raw IBC packet onto the channel.
func (h IBCRawPacketHandler) DispatchMsg(ctx sdk.Context, _ sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) ([]sdk.Event, [][]byte, error) {
func (h IBCRawPacketHandler) DispatchMsg(ctx sdk.Context, _ sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) ([]sdk.Event, [][]byte, [][]*codectypes.Any, error) {
if msg.IBC == nil || msg.IBC.SendPacket == nil {
return nil, nil, types.ErrUnknownMsg
return nil, nil, nil, types.ErrUnknownMsg
}
if contractIBCPortID == "" {
return nil, nil, errorsmod.Wrapf(types.ErrUnsupportedForContract, "ibc not supported")
return nil, nil, nil, errorsmod.Wrapf(types.ErrUnsupportedForContract, "ibc not supported")
}
contractIBCChannelID := msg.IBC.SendPacket.ChannelID
if contractIBCChannelID == "" {
return nil, nil, errorsmod.Wrapf(types.ErrEmpty, "ibc channel")
return nil, nil, nil, errorsmod.Wrapf(types.ErrEmpty, "ibc channel")
}

channelCap, ok := h.capabilityKeeper.GetCapability(ctx, host.ChannelCapabilityPath(contractIBCPortID, contractIBCChannelID))
if !ok {
return nil, nil, errorsmod.Wrap(channeltypes.ErrChannelCapabilityNotFound, "module does not own channel capability")
return nil, nil, nil, errorsmod.Wrap(channeltypes.ErrChannelCapabilityNotFound, "module does not own channel capability")
}
seq, err := h.ics4Wrapper.SendPacket(ctx, channelCap, contractIBCPortID, contractIBCChannelID, ConvertWasmIBCTimeoutHeightToCosmosHeight(msg.IBC.SendPacket.Timeout.Block), msg.IBC.SendPacket.Timeout.Timestamp, msg.IBC.SendPacket.Data)
if err != nil {
return nil, nil, errorsmod.Wrap(err, "channel")
return nil, nil, nil, errorsmod.Wrap(err, "channel")
}
moduleLogger(ctx).Debug("ibc packet set", "seq", seq)

var msgResponse [][]*codectypes.Any
resp := &types.MsgIBCSendResponse{Sequence: seq}
val, err := resp.Marshal()
if err != nil {
return nil, nil, errorsmod.Wrap(err, "failed to marshal IBC send response")
return nil, nil, nil, errorsmod.Wrap(err, "failed to marshal IBC send response")
}
// TODO: fill msgResponse

return nil, [][]byte{val}, nil
return nil, [][]byte{val}, msgResponse, nil
}

var _ Messenger = MessageHandlerFunc(nil)

// MessageHandlerFunc is a helper to construct a function based message handler.
type MessageHandlerFunc func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error)
type MessageHandlerFunc func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, msgResponses [][]*codectypes.Any, err error)

// DispatchMsg delegates dispatching of provided message into the MessageHandlerFunc.
func (m MessageHandlerFunc) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) {
func (m MessageHandlerFunc) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, msgResponses [][]*codectypes.Any, err error) {
return m(ctx, contractAddr, contractIBCPortID, msg)
}

// NewBurnCoinMessageHandler handles wasmvm.BurnMsg messages
func NewBurnCoinMessageHandler(burner types.Burner) MessageHandlerFunc {
return func(ctx sdk.Context, contractAddr sdk.AccAddress, _ string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) {
return func(ctx sdk.Context, contractAddr sdk.AccAddress, _ string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, msgResponses [][]*codectypes.Any, err error) {
if msg.Bank != nil && msg.Bank.Burn != nil {
coins, err := ConvertWasmCoinsToSdkCoins(msg.Bank.Burn.Amount)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
if coins.IsZero() {
return nil, nil, types.ErrEmpty.Wrap("amount")
return nil, nil, nil, types.ErrEmpty.Wrap("amount")
}
if err := burner.SendCoinsFromAccountToModule(ctx, contractAddr, types.ModuleName, coins); err != nil {
return nil, nil, errorsmod.Wrap(err, "transfer to module")
return nil, nil, nil, errorsmod.Wrap(err, "transfer to module")
}
if err := burner.BurnCoins(ctx, types.ModuleName, coins); err != nil {
return nil, nil, errorsmod.Wrap(err, "burn coins")
return nil, nil, nil, errorsmod.Wrap(err, "burn coins")
}
moduleLogger(ctx).Info("Burned", "amount", coins)
return nil, nil, nil
return nil, nil, nil, nil
}
return nil, nil, types.ErrUnknownMsg
return nil, nil, nil, types.ErrUnknownMsg
}
}
29 changes: 22 additions & 7 deletions x/wasm/keeper/msg_dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
errorsmod "cosmossdk.io/errors"
storetypes "cosmossdk.io/store/types"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

Expand All @@ -20,7 +21,7 @@ import (
// Messenger is an extension point for custom wasmd message handling
type Messenger interface {
// DispatchMsg encodes the wasmVM message and dispatches it.
DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error)
DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, msgResponses [][]*codectypes.Any, err error)
}

// replyer is a subset of keeper that can handle replies to submessages
Expand All @@ -42,7 +43,7 @@ func NewMessageDispatcher(messenger Messenger, keeper replyer) *MessageDispatche
// DispatchMessages sends all messages.
func (d MessageDispatcher) DispatchMessages(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.CosmosMsg) error {
for _, msg := range msgs {
events, _, err := d.messenger.DispatchMsg(ctx, contractAddr, ibcPort, msg)
events, _, _, err := d.messenger.DispatchMsg(ctx, contractAddr, ibcPort, msg)
if err != nil {
return err
}
Expand All @@ -53,7 +54,7 @@ func (d MessageDispatcher) DispatchMessages(ctx sdk.Context, contractAddr sdk.Ac
}

// dispatchMsgWithGasLimit sends a message with gas limit applied
func (d MessageDispatcher) dispatchMsgWithGasLimit(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msg wasmvmtypes.CosmosMsg, gasLimit uint64) (events []sdk.Event, data [][]byte, err error) {
func (d MessageDispatcher) dispatchMsgWithGasLimit(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msg wasmvmtypes.CosmosMsg, gasLimit uint64) (events []sdk.Event, data [][]byte, msgResponses [][]*codectypes.Any, err error) {
limitedMeter := storetypes.NewGasMeter(gasLimit)
subCtx := ctx.WithGasMeter(limitedMeter)

Expand All @@ -70,13 +71,13 @@ func (d MessageDispatcher) dispatchMsgWithGasLimit(ctx sdk.Context, contractAddr
err = errorsmod.Wrap(sdkerrors.ErrOutOfGas, "SubMsg hit gas limit")
}
}()
events, data, err = d.messenger.DispatchMsg(subCtx, contractAddr, ibcPort, msg)
events, data, msgResponses, err = d.messenger.DispatchMsg(subCtx, contractAddr, ibcPort, msg)

// make sure we charge the parent what was spent
spent := subCtx.GasMeter().GasConsumed()
ctx.GasMeter().ConsumeGas(spent, "From limited Sub-Message")

return events, data, err
return events, data, msgResponses, err
}

// DispatchSubmessages builds a sandbox to execute these messages and returns the execution result to the contract
Expand All @@ -101,10 +102,11 @@ func (d MessageDispatcher) DispatchSubmessages(ctx sdk.Context, contractAddr sdk
var err error
var events []sdk.Event
var data [][]byte
var msgResponses [][]*codectypes.Any
if limitGas {
events, data, err = d.dispatchMsgWithGasLimit(subCtx, contractAddr, ibcPort, msg.Msg, *msg.GasLimit)
events, data, msgResponses, err = d.dispatchMsgWithGasLimit(subCtx, contractAddr, ibcPort, msg.Msg, *msg.GasLimit)
} else {
events, data, err = d.messenger.DispatchMsg(subCtx, contractAddr, ibcPort, msg.Msg)
events, data, msgResponses, err = d.messenger.DispatchMsg(subCtx, contractAddr, ibcPort, msg.Msg)
}

// if it succeeds, commit state changes from submessage, and pass on events to Event Manager
Expand Down Expand Up @@ -142,10 +144,23 @@ func (d MessageDispatcher) DispatchSubmessages(ctx sdk.Context, contractAddr sdk
if len(data) > 0 {
responseData = data[0]
}

// For msgResponses we flatten the nested list into a flat list. In the majority of cases
// we only expect one message to be emitted and one response per message. But it might be possible
// to create multiple SDK messages from one CosmWasm message or we have multiple responses for one message.
// See https://github.com/CosmWasm/cosmwasm/issues/2009 for more information.
var msgResponsesFlattened []*codectypes.Any
for _, singleMsgResponses := range msgResponses {
msgResponsesFlattened = append(msgResponsesFlattened, singleMsgResponses...)
}

_ = msgResponsesFlattened // silences unused lint

result = wasmvmtypes.SubMsgResult{
Ok: &wasmvmtypes.SubMsgResponse{
Events: sdkEventsToWasmVMEvents(filteredEvents),
Data: responseData,
// msgResponsesFlattened goes here
},
}
} else {
Expand Down

0 comments on commit 705805c

Please sign in to comment.