Add flattened msgResponses to SubMsgResponse
This commit is contained in:
committed by
Christoph Otter
parent
2887105814
commit
a30e083b90
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
@@ -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.
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -142,10 +144,26 @@ 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 []wasmvmtypes.MsgResponse
|
||||
for _, singleMsgResponses := range msgResponses {
|
||||
for _, singleMsgResponse := range singleMsgResponses {
|
||||
msgResponsesFlattened = append(msgResponsesFlattened, wasmvmtypes.MsgResponse{
|
||||
TypeURL: singleMsgResponse.TypeUrl,
|
||||
Value: singleMsgResponse.Value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
result = wasmvmtypes.SubMsgResult{
|
||||
Ok: &wasmvmtypes.SubMsgResponse{
|
||||
Events: sdkEventsToWasmVMEvents(filteredEvents),
|
||||
Data: responseData,
|
||||
Events: sdkEventsToWasmVMEvents(filteredEvents),
|
||||
Data: responseData,
|
||||
MsgResponses: msgResponsesFlattened,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user