diff --git a/Dockerfile b/Dockerfile index f62f239526..d21d68cbfc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,8 +15,8 @@ WORKDIR /code COPY . /code/ # See https://github.com/CosmWasm/wasmvm/releases -ADD https://github.com/CosmWasm/wasmvm/releases/download/v0.14.0/libwasmvm_muslc.a /lib/libwasmvm_muslc.a -RUN sha256sum /lib/libwasmvm_muslc.a | grep 220b85158d1ae72008f099a7ddafe27f6374518816dd5873fd8be272c5418026 +ADD https://github.com/CosmWasm/wasmvm/releases/download/v0.15.1/libwasmvm_muslc.a /lib/libwasmvm_muslc.a +RUN sha256sum /lib/libwasmvm_muslc.a | grep 379c61d2e53f87f63639eaa8ba8bbe687e5833158bb10e0dc0523c3377248d01 # force it to use static lib (from above) not standard libgo_cosmwasm.so file RUN LEDGER_ENABLED=false BUILD_TAGS=muslc make build diff --git a/README.md b/README.md index 116d60e9c3..dfdef254fa 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ compatibility list: | wasmd | cosmwasm-vm | cosmwasm-std | | ----- | ----------- | ------------ | +| 0.18 | 0.15 | 0.15 | | 0.17 | 0.14 | 0.14 | | 0.16 | 0.14 | 0.14 | | 0.15 | 0.13 | 0.11-0.13 | diff --git a/go.mod b/go.mod index 1a4fc33a5a..8dc56ac775 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/CosmWasm/wasmd go 1.15 require ( - github.com/CosmWasm/wasmvm v0.14.0 - github.com/cosmos/cosmos-sdk v0.42.6 + github.com/CosmWasm/wasmvm v0.15.1 + github.com/cosmos/cosmos-sdk v0.42.7 github.com/cosmos/iavl v0.16.0 github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b github.com/gogo/protobuf v1.3.3 diff --git a/go.sum b/go.sum index 98848f4504..99bb207737 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/CosmWasm/wasmvm v0.14.0 h1:oceacwdwD9d9GzqElOrB8Qu1topx4+zM47VEqnJ/9Jo= -github.com/CosmWasm/wasmvm v0.14.0/go.mod h1:Id107qllDJyJjVQQsKMOy2YYF98sqPJ2t+jX1QES40A= +github.com/CosmWasm/wasmvm v0.15.1 h1:5hPBqPzHzVGtISJy/Mr89PbNIe+a3Q6qaFbnOFu/m64= +github.com/CosmWasm/wasmvm v0.15.1/go.mod h1:Id107qllDJyJjVQQsKMOy2YYF98sqPJ2t+jX1QES40A= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= @@ -134,6 +134,8 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/cosmos-sdk v0.42.6 h1:ps1QWfvaX6VLNcykA7wzfii/5IwBfYgTIik6NOVDq/c= github.com/cosmos/cosmos-sdk v0.42.6/go.mod h1:kh37gwYQoWdgR7N/9zeqW2rJ7cnP2W4A7nqIaf6m3zg= +github.com/cosmos/cosmos-sdk v0.42.7 h1:f+ZUjao2y93I37RZ7P2d94JdcEsS7Vq64SBLcNITAVc= +github.com/cosmos/cosmos-sdk v0.42.7/go.mod h1:SrclJP9lMXxz2fCbngxb0brsPNuZXqoQQ9VHuQ3Tpf4= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= diff --git a/x/wasm/alias.go b/x/wasm/alias.go index 49cee03e23..e2d457bab4 100644 --- a/x/wasm/alias.go +++ b/x/wasm/alias.go @@ -22,7 +22,7 @@ const ( MaxLabelSize = types.MaxLabelSize BuildTagRegexp = types.BuildTagRegexp MaxBuildTagSize = types.MaxBuildTagSize - CustomEventType = types.CustomEventType + WasmModuleEventType = types.WasmModuleEventType AttributeKeyContractAddr = types.AttributeKeyContractAddr ProposalTypeStoreCode = types.ProposalTypeStoreCode ProposalTypeInstantiateContract = types.ProposalTypeInstantiateContract @@ -53,7 +53,6 @@ var ( NewContractInfo = types.NewContractInfo NewEnv = types.NewEnv NewWasmCoins = types.NewWasmCoins - ParseEvents = types.ParseEvents DefaultWasmConfig = types.DefaultWasmConfig DefaultParams = types.DefaultParams InitGenesis = keeper.InitGenesis diff --git a/x/wasm/ibc.go b/x/wasm/ibc.go index e935598795..f22a4e38ee 100644 --- a/x/wasm/ibc.go +++ b/x/wasm/ibc.go @@ -195,14 +195,14 @@ func (i IBCHandler) OnRecvPacket( if err != nil { return nil, nil, sdkerrors.Wrapf(err, "contract port id") } - msgBz, err := i.keeper.OnRecvPacket(ctx, contractAddr, newIBCPacket(packet)) + ack, err := i.keeper.OnRecvPacket(ctx, contractAddr, newIBCPacket(packet)) if err != nil { return nil, nil, err } - return &sdk.Result{ + return &sdk.Result{ // the response is ignored Events: ctx.EventManager().Events().ToABCIEvents(), - }, msgBz, nil + }, ack, nil } // OnAcknowledgementPacket implements the IBCModule interface @@ -212,8 +212,8 @@ func (i IBCHandler) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes return nil, sdkerrors.Wrapf(err, "contract port id") } - err = i.keeper.OnAckPacket(ctx, contractAddr, wasmvmtypes.IBCAcknowledgement{ - Acknowledgement: acknowledgement, + err = i.keeper.OnAckPacket(ctx, contractAddr, wasmvmtypes.IBCAcknowledgementWithPacket{ + Acknowledgement: wasmvmtypes.IBCAcknowledgement{Data: acknowledgement}, OriginalPacket: newIBCPacket(packet), }) if err != nil { diff --git a/x/wasm/keeper/api.go b/x/wasm/keeper/api.go index c0c09f9eeb..5e33458e34 100644 --- a/x/wasm/keeper/api.go +++ b/x/wasm/keeper/api.go @@ -3,6 +3,7 @@ package keeper import ( "fmt" wasmvm "github.com/CosmWasm/wasmvm" + wasmvmtypes "github.com/CosmWasm/wasmvm/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -11,11 +12,18 @@ const ( DefaultGasCostHumanAddress = 5 // DefaultGasCostCanonicalAddress is how moch SDK gas we charge to convert to a canonical address format DefaultGasCostCanonicalAddress = 4 + + // DefaultDeserializationCostPerByte The formular should be `len(data) * deserializationCostPerByte` + DefaultDeserializationCostPerByte = 1 ) var ( - costHumanize = DefaultGasCostHumanAddress * DefaultGasMultiplier - costCanonical = DefaultGasCostCanonicalAddress * DefaultGasMultiplier + costHumanize = DefaultGasCostHumanAddress * DefaultGasMultiplier + costCanonical = DefaultGasCostCanonicalAddress * DefaultGasMultiplier + costJsonDeserialization = wasmvmtypes.UFraction{ + Numerator: DefaultDeserializationCostPerByte * DefaultGasMultiplier, + Denominator: 1, + } ) func humanAddress(canon []byte) (string, uint64, error) { diff --git a/x/wasm/keeper/events.go b/x/wasm/keeper/events.go new file mode 100644 index 0000000000..03ee978de5 --- /dev/null +++ b/x/wasm/keeper/events.go @@ -0,0 +1,59 @@ +package keeper + +import ( + "fmt" + "github.com/CosmWasm/wasmd/x/wasm/types" + wasmvmtypes "github.com/CosmWasm/wasmvm/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// newWasmModuleEvent creates with wasm module event for interacting with the given contract. Adds custom attributes +// to this event. +func newWasmModuleEvent(customAttributes []wasmvmtypes.EventAttribute, contractAddr sdk.AccAddress) sdk.Events { + attrs := contractSDKEventAttributes(customAttributes, contractAddr) + + // each wasm invocation always returns one sdk.Event + return sdk.Events{sdk.NewEvent(types.WasmModuleEventType, attrs...)} +} + +// returns true when a wasm module event was emitted for this contract already +func hasWasmModuleEvent(ctx sdk.Context, contractAddr sdk.AccAddress) bool { + for _, e := range ctx.EventManager().Events() { + if e.Type == types.WasmModuleEventType { + for _, a := range e.Attributes { + if string(a.Key) == types.AttributeKeyContractAddr && string(a.Value) == contractAddr.String() { + return true + } + } + } + } + return false +} + +const eventTypeMinLength = 2 + +// newCustomEvents converts wasmvm events from a contract response to sdk type events +func newCustomEvents(evts wasmvmtypes.Events, contractAddr sdk.AccAddress) sdk.Events { + events := make(sdk.Events, 0, len(evts)) + for _, e := range evts { + if len(e.Type) <= eventTypeMinLength { + continue + } + attributes := contractSDKEventAttributes(e.Attributes, contractAddr) + events = append(events, sdk.NewEvent(fmt.Sprintf("%s%s", types.CustomContractEventPrefix, e.Type), attributes...)) + } + return events +} + +// convert and add contract address issuing this event +func contractSDKEventAttributes(customAttributes []wasmvmtypes.EventAttribute, contractAddr sdk.AccAddress) []sdk.Attribute { + attrs := []sdk.Attribute{sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddr.String())} + // append attributes from wasm to the sdk.Event + for _, l := range customAttributes { + // and reserve the contract_address key for our use (not contract) + if l.Key != types.AttributeKeyContractAddr { + attrs = append(attrs, sdk.NewAttribute(l.Key, l.Value)) + } + } + return attrs +} diff --git a/x/wasm/keeper/events_test.go b/x/wasm/keeper/events_test.go new file mode 100644 index 0000000000..8982c84e9c --- /dev/null +++ b/x/wasm/keeper/events_test.go @@ -0,0 +1,160 @@ +package keeper + +import ( + "context" + "github.com/CosmWasm/wasmd/x/wasm/types" + wasmvmtypes "github.com/CosmWasm/wasmvm/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestHasWasmModuleEvent(t *testing.T) { + myContractAddr := RandomAccountAddress(t) + specs := map[string]struct { + srcEvents []sdk.Event + exp bool + }{ + "event found": { + srcEvents: []sdk.Event{ + sdk.NewEvent(types.WasmModuleEventType, sdk.NewAttribute("contract_address", myContractAddr.String())), + }, + exp: true, + }, + "different event: not found": { + srcEvents: []sdk.Event{ + sdk.NewEvent(types.CustomContractEventPrefix, sdk.NewAttribute("contract_address", myContractAddr.String())), + }, + exp: false, + }, + "event with different address: not found": { + srcEvents: []sdk.Event{ + sdk.NewEvent(types.WasmModuleEventType, sdk.NewAttribute("contract_address", RandomBech32AccountAddress(t))), + }, + exp: false, + }, + "no event": { + srcEvents: []sdk.Event{}, + exp: false, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + em := sdk.NewEventManager() + em.EmitEvents(spec.srcEvents) + ctx := sdk.Context{}.WithContext(context.Background()).WithEventManager(em) + + got := hasWasmModuleEvent(ctx, myContractAddr) + assert.Equal(t, spec.exp, got) + }) + } +} + +func TestNewCustomEvents(t *testing.T) { + myContract := RandomAccountAddress(t) + specs := map[string]struct { + src wasmvmtypes.Events + exp sdk.Events + }{ + "all good": { + src: wasmvmtypes.Events{{ + Type: "foo", + Attributes: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myVal"}}, + }}, + exp: sdk.Events{sdk.NewEvent("wasm-foo", + sdk.NewAttribute("contract_address", myContract.String()), + sdk.NewAttribute("myKey", "myVal"))}, + }, + "multiple attributes": { + src: wasmvmtypes.Events{{ + Type: "foo", + Attributes: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myVal"}, + {Key: "myOtherKey", Value: "myOtherVal"}}, + }}, + exp: sdk.Events{sdk.NewEvent("wasm-foo", + sdk.NewAttribute("contract_address", myContract.String()), + sdk.NewAttribute("myKey", "myVal"), + sdk.NewAttribute("myOtherKey", "myOtherVal"))}, + }, + "multiple events": { + src: wasmvmtypes.Events{{ + Type: "foo", + Attributes: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myVal"}}, + }, { + Type: "bar", + Attributes: []wasmvmtypes.EventAttribute{{Key: "otherKey", Value: "otherVal"}}, + }}, + exp: sdk.Events{sdk.NewEvent("wasm-foo", + sdk.NewAttribute("contract_address", myContract.String()), + sdk.NewAttribute("myKey", "myVal")), + sdk.NewEvent("wasm-bar", + sdk.NewAttribute("contract_address", myContract.String()), + sdk.NewAttribute("otherKey", "otherVal"))}, + }, + "without attributes": { + src: wasmvmtypes.Events{{ + Type: "foo", + }}, + exp: sdk.Events{sdk.NewEvent("wasm-foo", + sdk.NewAttribute("contract_address", myContract.String()))}, + }, + "min length not reached": { + src: wasmvmtypes.Events{{ + Type: "f", + }}, + exp: sdk.Events{}, + }, + "overwrite contract_address": { + src: wasmvmtypes.Events{{ + Type: "foo", + Attributes: []wasmvmtypes.EventAttribute{{Key: "contract_address", Value: RandomBech32AccountAddress(t)}}, + }}, + exp: sdk.Events{sdk.NewEvent("wasm-foo", + sdk.NewAttribute("contract_address", myContract.String()))}, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + gotEvent := newCustomEvents(spec.src, myContract) + assert.Equal(t, spec.exp, gotEvent) + }) + } +} + +func TestNewWasmModuleEvent(t *testing.T) { + myContract := RandomAccountAddress(t) + specs := map[string]struct { + src []wasmvmtypes.EventAttribute + exp sdk.Events + }{ + "all good": { + src: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myVal"}}, + exp: sdk.Events{sdk.NewEvent("wasm", + sdk.NewAttribute("contract_address", myContract.String()), + sdk.NewAttribute("myKey", "myVal"))}, + }, + "multiple attributes": { + src: []wasmvmtypes.EventAttribute{{Key: "myKey", Value: "myVal"}, + {Key: "myOtherKey", Value: "myOtherVal"}}, + exp: sdk.Events{sdk.NewEvent("wasm", + sdk.NewAttribute("contract_address", myContract.String()), + sdk.NewAttribute("myKey", "myVal"), + sdk.NewAttribute("myOtherKey", "myOtherVal"))}, + }, + "without attributes": { + exp: sdk.Events{sdk.NewEvent("wasm", + sdk.NewAttribute("contract_address", myContract.String()))}, + }, + "overwrite contract_address": { + src: []wasmvmtypes.EventAttribute{{Key: "contract_address", Value: RandomBech32AccountAddress(t)}}, + exp: sdk.Events{sdk.NewEvent("wasm", + sdk.NewAttribute("contract_address", myContract.String()))}, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + gotEvent := newWasmModuleEvent(spec.src, myContract) + assert.Equal(t, spec.exp, gotEvent) + }) + } +} diff --git a/x/wasm/keeper/gas_register.go b/x/wasm/keeper/gas_register.go index 25fb56e8f3..a78b28c6c7 100644 --- a/x/wasm/keeper/gas_register.go +++ b/x/wasm/keeper/gas_register.go @@ -29,6 +29,8 @@ const ( DefaultContractMessageDataCost uint64 = 1 // DefaultPerAttributeCost is how much SDK gas we charge per attribute count. DefaultPerAttributeCost uint64 = 10 + // DefaultPerCustomEventCost is how much SDK gas we charge per event count. + DefaultPerCustomEventCost uint64 = 20 // DefaultEventAttributeDataFreeTier number of bytes of total attribute data we do not charge. DefaultEventAttributeDataFreeTier = 100 ) @@ -44,7 +46,7 @@ type GasRegister interface { // ReplyCosts costs to to handle a message reply ReplyCosts(pinned bool, reply wasmvmtypes.Reply) sdk.Gas // EventCosts costs to persist an event - EventCosts(evts []wasmvmtypes.EventAttribute) sdk.Gas + EventCosts(attrs []wasmvmtypes.EventAttribute, events wasmvmtypes.Events) sdk.Gas // ToWasmVMGas converts from sdk gas to wasmvm gas ToWasmVMGas(source sdk.Gas) uint64 // FromWasmVMGas converts from wasmvm gas to sdk gas @@ -67,10 +69,12 @@ type WasmGasRegisterConfig struct { // This is used with len(key) + len(value) EventAttributeDataCost sdk.Gas // EventAttributeDataFreeTier number of bytes of total attribute data that is free of charge - EventAttributeDataFreeTier int + EventAttributeDataFreeTier uint64 // ContractMessageDataCost SDK gas charged *per byte* of the message that goes to the contract // This is used with len(msg) ContractMessageDataCost sdk.Gas + // CustomEventCost cost per custom event + CustomEventCost uint64 } // DefaultGasRegisterConfig default values @@ -80,6 +84,7 @@ func DefaultGasRegisterConfig() WasmGasRegisterConfig { CompileCost: DefaultCompileCost, GasMultiplier: DefaultGasMultiplier, EventPerAttributeCost: DefaultPerAttributeCost, + CustomEventCost: DefaultPerCustomEventCost, EventAttributeDataCost: DefaultEventAttributeDataCost, EventAttributeDataFreeTier: DefaultEventAttributeDataFreeTier, ContractMessageDataCost: DefaultContractMessageDataCost, @@ -143,33 +148,49 @@ func (g WasmGasRegister) ReplyCosts(pinned bool, reply wasmvmtypes.Reply) sdk.Ga attrs = append(e.Attributes) } // apply free tier on the whole set not per event - eventGas += g.EventCosts(attrs) + eventGas += g.EventCosts(attrs, nil) } return eventGas + g.InstantiateContractCosts(pinned, msgLen) } // EventCosts costs to persist an event -func (g WasmGasRegister) EventCosts(evts []wasmvmtypes.EventAttribute) sdk.Gas { - if len(evts) == 0 { - return 0 +func (g WasmGasRegister) EventCosts(attrs []wasmvmtypes.EventAttribute, events wasmvmtypes.Events) sdk.Gas { + gas, remainingFreeTier := g.eventAttributeCosts(attrs, g.c.EventAttributeDataFreeTier) + for _, e := range events { + gas += g.c.CustomEventCost + gas += sdk.Gas(len(e.Type)) * g.c.EventAttributeDataCost // no free tier with event type + var attrCost sdk.Gas + attrCost, remainingFreeTier = g.eventAttributeCosts(e.Attributes, remainingFreeTier) + gas += attrCost } - var storedBytes int - for _, l := range evts { - storedBytes += len(l.Key) + len(l.Value) + return gas +} + +func (g WasmGasRegister) eventAttributeCosts(attrs []wasmvmtypes.EventAttribute, freeTier uint64) (sdk.Gas, uint64) { + if len(attrs) == 0 { + return 0, freeTier } - // apply free tier - if storedBytes <= g.c.EventAttributeDataFreeTier { - storedBytes = 0 - } else { - storedBytes -= g.c.EventAttributeDataFreeTier + var storedBytes uint64 + for _, l := range attrs { + storedBytes += uint64(len(l.Key)) + uint64(len(l.Value)) } + storedBytes, freeTier = calcWithFreeTier(storedBytes, freeTier) // total Length * costs + attribute count * costs - r := sdk.NewIntFromUint64(g.c.EventAttributeDataCost).Mul(sdk.NewIntFromUint64(uint64(storedBytes))). - Add(sdk.NewIntFromUint64(g.c.EventPerAttributeCost).Mul(sdk.NewIntFromUint64(uint64(len(evts))))) + r := sdk.NewIntFromUint64(g.c.EventAttributeDataCost).Mul(sdk.NewIntFromUint64(storedBytes)). + Add(sdk.NewIntFromUint64(g.c.EventPerAttributeCost).Mul(sdk.NewIntFromUint64(uint64(len(attrs))))) if !r.IsUint64() { panic(sdk.ErrorOutOfGas{Descriptor: "overflow"}) } - return r.Uint64() + return r.Uint64(), freeTier +} + +// apply free tier +func calcWithFreeTier(storedBytes uint64, freeTier uint64) (uint64, uint64) { + if storedBytes <= freeTier { + return 0, freeTier - storedBytes + } + storedBytes -= freeTier + return storedBytes, 0 } // ToWasmVMGas convert to wasmVM contract runtime gas unit diff --git a/x/wasm/keeper/handler_plugin_encoders.go b/x/wasm/keeper/handler_plugin_encoders.go index 75acfdcee4..18d0a7757e 100644 --- a/x/wasm/keeper/handler_plugin_encoders.go +++ b/x/wasm/keeper/handler_plugin_encoders.go @@ -10,6 +10,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" ibcclienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" @@ -32,6 +33,7 @@ type MessageEncoders struct { Staking func(sender sdk.AccAddress, msg *wasmvmtypes.StakingMsg) ([]sdk.Msg, error) Stargate func(sender sdk.AccAddress, msg *wasmvmtypes.StargateMsg) ([]sdk.Msg, error) Wasm func(sender sdk.AccAddress, msg *wasmvmtypes.WasmMsg) ([]sdk.Msg, error) + Gov func(sender sdk.AccAddress, msg *wasmvmtypes.GovMsg) ([]sdk.Msg, error) } func DefaultEncoders(unpacker codectypes.AnyUnpacker, portSource types.ICS20TransferPortSource) MessageEncoders { @@ -43,6 +45,7 @@ func DefaultEncoders(unpacker codectypes.AnyUnpacker, portSource types.ICS20Tran Staking: EncodeStakingMsg, Stargate: EncodeStargateMsg(unpacker), Wasm: EncodeWasmMsg, + Gov: EncodeGovMsg, } } @@ -71,6 +74,9 @@ func (e MessageEncoders) Merge(o *MessageEncoders) MessageEncoders { if o.Wasm != nil { e.Wasm = o.Wasm } + if o.Gov != nil { + e.Gov = o.Gov + } return e } @@ -90,6 +96,8 @@ func (e MessageEncoders) Encode(ctx sdk.Context, contractAddr sdk.AccAddress, co return e.Stargate(contractAddr, msg.Stargate) case msg.Wasm != nil: return e.Wasm(contractAddr, msg.Wasm) + case msg.Gov != nil: + return EncodeGovMsg(contractAddr, msg.Gov) } return nil, sdkerrors.Wrap(types.ErrUnknownMsg, "unknown variant of Wasm") } @@ -198,7 +206,7 @@ func EncodeStargateMsg(unpacker codectypes.AnyUnpacker) StargateEncoder { func EncodeWasmMsg(sender sdk.AccAddress, msg *wasmvmtypes.WasmMsg) ([]sdk.Msg, error) { switch { case msg.Execute != nil: - coins, err := convertWasmCoinsToSdkCoins(msg.Execute.Send) + coins, err := convertWasmCoinsToSdkCoins(msg.Execute.Funds) if err != nil { return nil, err } @@ -211,7 +219,7 @@ func EncodeWasmMsg(sender sdk.AccAddress, msg *wasmvmtypes.WasmMsg) ([]sdk.Msg, } return []sdk.Msg{&sdkMsg}, nil case msg.Instantiate != nil: - coins, err := convertWasmCoinsToSdkCoins(msg.Instantiate.Send) + coins, err := convertWasmCoinsToSdkCoins(msg.Instantiate.Funds) if err != nil { return nil, err } @@ -280,6 +288,27 @@ func EncodeIBCMsg(portSource types.ICS20TransferPortSource) func(ctx sdk.Context } } } + +func EncodeGovMsg(sender sdk.AccAddress, msg *wasmvmtypes.GovMsg) ([]sdk.Msg, error) { + var option govtypes.VoteOption + switch msg.Vote.Vote { + case wasmvmtypes.Yes: + option = govtypes.OptionYes + case wasmvmtypes.No: + option = govtypes.OptionNo + case wasmvmtypes.NoWithVeto: + option = govtypes.OptionNoWithVeto + case wasmvmtypes.Abstain: + option = govtypes.OptionAbstain + } + vote := &govtypes.MsgVote{ + ProposalId: msg.Vote.ProposalId, + Voter: sender.String(), + Option: option, + } + return []sdk.Msg{vote}, nil +} + func convertWasmIBCTimeoutHeightToCosmosHeight(ibcTimeoutBlock *wasmvmtypes.IBCTimeoutBlock) ibcclienttypes.Height { if ibcTimeoutBlock == nil { return ibcclienttypes.NewHeight(0, 0) diff --git a/x/wasm/keeper/handler_plugin_encoders_test.go b/x/wasm/keeper/handler_plugin_encoders_test.go index 1b90b718e4..ae10886fc0 100644 --- a/x/wasm/keeper/handler_plugin_encoders_test.go +++ b/x/wasm/keeper/handler_plugin_encoders_test.go @@ -147,7 +147,7 @@ func TestEncoding(t *testing.T) { Execute: &wasmvmtypes.ExecuteMsg{ ContractAddr: addr2.String(), Msg: jsonMsg, - Send: []wasmvmtypes.Coin{ + Funds: []wasmvmtypes.Coin{ wasmvmtypes.NewCoin(12, "eth"), }, }, @@ -169,7 +169,7 @@ func TestEncoding(t *testing.T) { Instantiate: &wasmvmtypes.InstantiateMsg{ CodeID: 7, Msg: jsonMsg, - Send: []wasmvmtypes.Coin{ + Funds: []wasmvmtypes.Coin{ wasmvmtypes.NewCoin(123, "eth"), }, Label: "myLabel", @@ -499,6 +499,70 @@ func TestEncoding(t *testing.T) { }, }, }, + "Gov vote: yes": { + sender: addr1, + srcContractIBCPort: "myIBCPort", + srcMsg: wasmvmtypes.CosmosMsg{ + Gov: &wasmvmtypes.GovMsg{ + Vote: &wasmvmtypes.VoteMsg{ProposalId: 1, Vote: wasmvmtypes.Yes}, + }, + }, + output: []sdk.Msg{ + &govtypes.MsgVote{ + ProposalId: 1, + Voter: addr1.String(), + Option: govtypes.OptionYes, + }, + }, + }, + "Gov vote: No": { + sender: addr1, + srcContractIBCPort: "myIBCPort", + srcMsg: wasmvmtypes.CosmosMsg{ + Gov: &wasmvmtypes.GovMsg{ + Vote: &wasmvmtypes.VoteMsg{ProposalId: 1, Vote: wasmvmtypes.No}, + }, + }, + output: []sdk.Msg{ + &govtypes.MsgVote{ + ProposalId: 1, + Voter: addr1.String(), + Option: govtypes.OptionNo, + }, + }, + }, + "Gov vote: Abstain": { + sender: addr1, + srcContractIBCPort: "myIBCPort", + srcMsg: wasmvmtypes.CosmosMsg{ + Gov: &wasmvmtypes.GovMsg{ + Vote: &wasmvmtypes.VoteMsg{ProposalId: 10, Vote: wasmvmtypes.Abstain}, + }, + }, + output: []sdk.Msg{ + &govtypes.MsgVote{ + ProposalId: 10, + Voter: addr1.String(), + Option: govtypes.OptionAbstain, + }, + }, + }, + "Gov vote: No with veto": { + sender: addr1, + srcContractIBCPort: "myIBCPort", + srcMsg: wasmvmtypes.CosmosMsg{ + Gov: &wasmvmtypes.GovMsg{ + Vote: &wasmvmtypes.VoteMsg{ProposalId: 1, Vote: wasmvmtypes.NoWithVeto}, + }, + }, + output: []sdk.Msg{ + &govtypes.MsgVote{ + ProposalId: 1, + Voter: addr1.String(), + Option: govtypes.OptionNoWithVeto, + }, + }, + }, } encodingConfig := MakeEncodingConfig(t) for name, tc := range cases { diff --git a/x/wasm/keeper/handler_plugin_test.go b/x/wasm/keeper/handler_plugin_test.go index 7bc6f48dad..b0e98c6459 100644 --- a/x/wasm/keeper/handler_plugin_test.go +++ b/x/wasm/keeper/handler_plugin_test.go @@ -364,9 +364,9 @@ func TestBurnCoinMessageHandlerIntegration(t *testing.T) { for name, spec := range specs { t.Run(name, func(t *testing.T) { ctx, _ = parentCtx.CacheContext() - k.wasmVM = &wasmtesting.MockWasmer{ExecuteFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { - return &wasmvmtypes.Response{Messages: []wasmvmtypes.CosmosMsg{ - {Bank: &wasmvmtypes.BankMsg{Burn: &spec.msg}}, + k.wasmVM = &wasmtesting.MockWasmer{ExecuteFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { + return &wasmvmtypes.Response{Messages: []wasmvmtypes.SubMsg{ + {Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{Burn: &spec.msg}}, ReplyOn: wasmvmtypes.ReplyNever}, }, }, 0, nil }} diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 40c66d0ae8..90b47f4b29 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -47,8 +47,7 @@ type WasmVMResponseHandler interface { ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, - submessages []wasmvmtypes.SubMsg, - messages []wasmvmtypes.CosmosMsg, + messages []wasmvmtypes.SubMsg, origRspData []byte, ) ([]byte, error) } @@ -259,7 +258,7 @@ func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A // instantiate wasm contract gas := k.runtimeGasForContract(ctx) - res, gasUsed, err := k.wasmVM.Instantiate(codeInfo.CodeHash, env, info, initMsg, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas) + res, gasUsed, err := k.wasmVM.Instantiate(codeInfo.CodeHash, env, info, initMsg, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas, costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if err != nil { return contractAddress, nil, sdkerrors.Wrap(types.ErrInstantiateFailed, err.Error()) @@ -290,7 +289,7 @@ func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A k.storeContractInfo(ctx, contractAddress, &contractInfo) // dispatch submessages then messages - data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Submessages, res.Messages, res.Attributes, res.Data) + data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) if err != nil { return nil, nil, sdkerrors.Wrap(err, "dispatch") } @@ -322,14 +321,14 @@ func (k Keeper) execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller // prepare querier querier := k.newQueryHandler(ctx, contractAddress) gas := k.runtimeGasForContract(ctx) - res, gasUsed, execErr := k.wasmVM.Execute(codeInfo.CodeHash, env, info, msg, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas) + res, gasUsed, execErr := k.wasmVM.Execute(codeInfo.CodeHash, env, info, msg, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas, costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if execErr != nil { return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) } // dispatch submessages then messages - data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Submessages, res.Messages, res.Attributes, res.Data) + data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) if err != nil { return nil, sdkerrors.Wrap(err, "dispatch") } @@ -378,7 +377,7 @@ func (k Keeper) migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller prefixStoreKey := types.GetContractStorePrefix(contractAddress) prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), prefixStoreKey) gas := k.runtimeGasForContract(ctx) - res, gasUsed, err := k.wasmVM.Migrate(newCodeInfo.CodeHash, env, msg, &prefixStore, cosmwasmAPI, &querier, k.gasMeter(ctx), gas) + res, gasUsed, err := k.wasmVM.Migrate(newCodeInfo.CodeHash, env, msg, &prefixStore, cosmwasmAPI, &querier, k.gasMeter(ctx), gas, costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if err != nil { return nil, sdkerrors.Wrap(types.ErrMigrationFailed, err.Error()) @@ -393,7 +392,7 @@ func (k Keeper) migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller k.storeContractInfo(ctx, contractAddress, contractInfo) // dispatch submessages then messages - data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Submessages, res.Messages, res.Attributes, res.Data) + data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) if err != nil { return nil, sdkerrors.Wrap(err, "dispatch") } @@ -418,14 +417,14 @@ func (k Keeper) Sudo(ctx sdk.Context, contractAddress sdk.AccAddress, msg []byte // prepare querier querier := k.newQueryHandler(ctx, contractAddress) gas := k.runtimeGasForContract(ctx) - res, gasUsed, execErr := k.wasmVM.Sudo(codeInfo.CodeHash, env, msg, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas) + res, gasUsed, execErr := k.wasmVM.Sudo(codeInfo.CodeHash, env, msg, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas, costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if execErr != nil { return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) } // dispatch submessages then messages - data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Submessages, res.Messages, res.Attributes, res.Data) + data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) if err != nil { return nil, sdkerrors.Wrap(err, "dispatch") } @@ -451,14 +450,14 @@ func (k Keeper) reply(ctx sdk.Context, contractAddress sdk.AccAddress, reply was Plugins: k.wasmVMQueryHandler, } gas := k.runtimeGasForContract(ctx) - res, gasUsed, execErr := k.wasmVM.Reply(codeInfo.CodeHash, env, reply, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas) + res, gasUsed, execErr := k.wasmVM.Reply(codeInfo.CodeHash, env, reply, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas, costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if execErr != nil { return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) } // dispatch submessages then messages - data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Submessages, res.Messages, res.Attributes, res.Data) + data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events) if err != nil { return nil, sdkerrors.Wrap(err, "dispatch") } @@ -556,7 +555,7 @@ func (k Keeper) QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []b querier := k.newQueryHandler(ctx, contractAddr) env := types.NewEnv(ctx, contractAddr) - queryResult, gasUsed, qErr := k.wasmVM.Query(codeInfo.CodeHash, env, req, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), k.runtimeGasForContract(ctx)) + queryResult, gasUsed, qErr := k.wasmVM.Query(codeInfo.CodeHash, env, req, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), k.runtimeGasForContract(ctx), costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if qErr != nil { return nil, sdkerrors.Wrap(types.ErrQueryFailed, qErr.Error()) @@ -763,17 +762,21 @@ func (k *Keeper) handleContractResponse( ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, - subMsg []wasmvmtypes.SubMsg, - msgs []wasmvmtypes.CosmosMsg, + msgs []wasmvmtypes.SubMsg, attrs []wasmvmtypes.EventAttribute, data []byte, + evts wasmvmtypes.Events, ) ([]byte, error) { - attributeGasCost := k.gasRegister.EventCosts(attrs) + attributeGasCost := k.gasRegister.EventCosts(attrs, evts) ctx.GasMeter().ConsumeGas(attributeGasCost, "Custom contract event attributes") // emit all events from this contract itself - events := types.ParseEvents(attrs, contractAddr) - ctx.EventManager().EmitEvents(events) - return k.wasmVMResponseHandler.Handle(ctx, contractAddr, ibcPort, subMsg, msgs, data) + if len(attrs) != 0 || !hasWasmModuleEvent(ctx, contractAddr) { + ctx.EventManager().EmitEvents(newWasmModuleEvent(attrs, contractAddr)) + } + if len(evts) > 0 { + ctx.EventManager().EmitEvents(newCustomEvents(evts, contractAddr)) + } + return k.wasmVMResponseHandler.Handle(ctx, contractAddr, ibcPort, msgs, data) } func (k Keeper) runtimeGasForContract(ctx sdk.Context) uint64 { @@ -952,7 +955,6 @@ func (c BankCoinTransferrer) TransferCoins(ctx sdk.Context, fromAddr sdk.AccAddr } type msgDispatcher interface { - DispatchMessages(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.CosmosMsg) error DispatchSubmessages(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) } @@ -968,21 +970,13 @@ func NewDefaultWasmVMContractResponseHandler(md msgDispatcher) *DefaultWasmVMCon } // Handle processes the data returned by a contract invocation. -func (h DefaultWasmVMContractResponseHandler) Handle( - ctx sdk.Context, - contractAddr sdk.AccAddress, - ibcPort string, - submessages []wasmvmtypes.SubMsg, - messages []wasmvmtypes.CosmosMsg, - origRspData []byte, -) ([]byte, error) { +func (h DefaultWasmVMContractResponseHandler) Handle(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, messages []wasmvmtypes.SubMsg, origRspData []byte) ([]byte, error) { result := origRspData - switch rsp, err := h.md.DispatchSubmessages(ctx, contractAddr, ibcPort, submessages); { + switch rsp, err := h.md.DispatchSubmessages(ctx, contractAddr, ibcPort, messages); { case err != nil: return nil, sdkerrors.Wrap(err, "submessages") case rsp != nil: result = rsp } - // then dispatch all the normal messages - return result, sdkerrors.Wrap(h.md.DispatchMessages(ctx, contractAddr, ibcPort, messages), "messages") + return result, nil } diff --git a/x/wasm/keeper/keeper_test.go b/x/wasm/keeper/keeper_test.go index 08b58442ce..13182e45f7 100644 --- a/x/wasm/keeper/keeper_test.go +++ b/x/wasm/keeper/keeper_test.go @@ -284,7 +284,7 @@ func TestInstantiate(t *testing.T) { gasAfter := ctx.GasMeter().GasConsumed() if types.EnableGasVerification { - require.Equal(t, uint64(0x12324), gasAfter-gasBefore) + require.Equal(t, uint64(0x12361), gasAfter-gasBefore) } // ensure it is stored properly @@ -443,7 +443,7 @@ func TestInstantiateWithContractDataResponse(t *testing.T) { ctx, keepers := CreateTestInput(t, false, SupportedFeatures) wasmerMock := &wasmtesting.MockWasmer{ - InstantiateFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { + InstantiateFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { return &wasmvmtypes.Response{Data: []byte("my-response-data")}, 0, nil }, AnalyzeCodeFn: wasmtesting.WithoutIBCAnalyzeFn, @@ -517,7 +517,7 @@ func TestExecute(t *testing.T) { // make sure gas is properly deducted from ctx gasAfter := ctx.GasMeter().GasConsumed() if types.EnableGasVerification { - require.Equal(t, uint64(0x12939), gasAfter-gasBefore) + require.Equal(t, uint64(0x12afd), gasAfter-gasBefore) } // ensure bob now exists and got both payments released bobAcct = accKeeper.GetAccount(ctx, bob) @@ -1098,7 +1098,7 @@ func TestIterateContractsByCode(t *testing.T) { func TestIterateContractsByCodeWithMigration(t *testing.T) { // mock migration so that it does not fail when migrate example1 to example2.codeID - mockWasmVM := wasmtesting.MockWasmer{MigrateFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, migrateMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { + mockWasmVM := wasmtesting.MockWasmer{MigrateFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, migrateMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { return &wasmvmtypes.Response{}, 1, nil }} wasmtesting.MakeInstantiable(&mockWasmVM) @@ -1402,10 +1402,10 @@ func TestPinnedContractLoops(t *testing.T) { require.NoError(t, k.pinCode(ctx, example.CodeID)) var loops int anyMsg := []byte(`{}`) - mock.ExecuteFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { + mock.ExecuteFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { loops++ return &wasmvmtypes.Response{ - Submessages: []wasmvmtypes.SubMsg{ + Messages: []wasmvmtypes.SubMsg{ { ID: 1, ReplyOn: wasmvmtypes.ReplyError, @@ -1431,10 +1431,6 @@ func TestPinnedContractLoops(t *testing.T) { } func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) { - noopDMsgs := func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.CosmosMsg) error { - return nil - } - specs := map[string]struct { srcData []byte setup func(m *wasmtesting.MockMsgDispatcher) @@ -1447,7 +1443,6 @@ func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) { m.DispatchSubmessagesFn = func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) { return []byte("mySubMsgData"), nil } - m.DispatchMessagesFn = noopDMsgs }, expErr: false, expData: []byte("mySubMsgData"), @@ -1458,7 +1453,6 @@ func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) { m.DispatchSubmessagesFn = func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) { return []byte(""), nil } - m.DispatchMessagesFn = noopDMsgs }, expErr: false, expData: []byte(""), @@ -1469,7 +1463,6 @@ func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) { m.DispatchSubmessagesFn = func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) { return nil, nil } - m.DispatchMessagesFn = noopDMsgs }, expErr: false, expData: []byte("otherData"), @@ -1482,30 +1475,18 @@ func TestNewDefaultWasmVMContractResponseHandler(t *testing.T) { }, expErr: true, }, - "message error aborts process": { - setup: func(m *wasmtesting.MockMsgDispatcher) { - m.DispatchSubmessagesFn = func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) { - return []byte("mySubMsgData"), nil - } - m.DispatchMessagesFn = func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.CosmosMsg) error { - return errors.New("test - ignore") - } - }, - expErr: true, - }, } for name, spec := range specs { t.Run(name, func(t *testing.T) { var ( - subMsgs []wasmvmtypes.SubMsg - msgs []wasmvmtypes.CosmosMsg + msgs []wasmvmtypes.SubMsg ) var mock wasmtesting.MockMsgDispatcher spec.setup(&mock) d := NewDefaultWasmVMContractResponseHandler(&mock) // when - gotData, gotErr := d.Handle(sdk.Context{}, RandomAccountAddress(t), "ibc-port", subMsgs, msgs, spec.srcData) + gotData, gotErr := d.Handle(sdk.Context{}, RandomAccountAddress(t), "ibc-port", msgs, spec.srcData) if spec.expErr { require.Error(t, gotErr) return diff --git a/x/wasm/keeper/msg_dispatcher.go b/x/wasm/keeper/msg_dispatcher.go index a81a57014e..18e774ac86 100644 --- a/x/wasm/keeper/msg_dispatcher.go +++ b/x/wasm/keeper/msg_dispatcher.go @@ -76,12 +76,14 @@ func (d MessageDispatcher) DispatchSubmessages(ctx sdk.Context, contractAddr sdk var rsp []byte for _, msg := range msgs { switch msg.ReplyOn { - case wasmvmtypes.ReplySuccess, wasmvmtypes.ReplyError, wasmvmtypes.ReplyAlways: + case wasmvmtypes.ReplySuccess, wasmvmtypes.ReplyError, wasmvmtypes.ReplyAlways, wasmvmtypes.ReplyNever: default: return nil, sdkerrors.Wrap(types.ErrInvalid, "replyOn value") } // first, we build a sub-context which we can use inside the submessages subCtx, commit := ctx.CacheContext() + em := sdk.NewEventManager() + subCtx = subCtx.WithEventManager(em) // check how much gas left locally, optionally wrap the gas meter gasRemaining := ctx.GasMeter().Limit() - ctx.GasMeter().GasConsumed() @@ -99,15 +101,15 @@ func (d MessageDispatcher) DispatchSubmessages(ctx sdk.Context, contractAddr sdk // if it succeeds, commit state changes from submessage, and pass on events to Event Manager if err == nil { commit() + ctx.EventManager().EmitEvents(em.Events()) ctx.EventManager().EmitEvents(events) - } - // on failure, revert state from sandbox, and ignore events (just skip doing the above) + } // on failure, revert state from sandbox, and ignore events (just skip doing the above) - // we only callback if requested. Short-circuit here the two cases we don't want to - if msg.ReplyOn == wasmvmtypes.ReplySuccess && err != nil { + // we only callback if requested. Short-circuit here the cases we don't want to + if (msg.ReplyOn == wasmvmtypes.ReplySuccess || msg.ReplyOn == wasmvmtypes.ReplyNever) && err != nil { return nil, err } - if msg.ReplyOn == wasmvmtypes.ReplyError && err == nil { + if msg.ReplyOn == wasmvmtypes.ReplyNever || (msg.ReplyOn == wasmvmtypes.ReplyError && err == nil) { continue } diff --git a/x/wasm/keeper/msg_dispatcher_test.go b/x/wasm/keeper/msg_dispatcher_test.go index dde46773a0..94d6f322ad 100644 --- a/x/wasm/keeper/msg_dispatcher_test.go +++ b/x/wasm/keeper/msg_dispatcher_test.go @@ -101,6 +101,39 @@ func TestDispatchSubmessages(t *testing.T) { Attributes: []abci.EventAttribute{{Key: []byte("foo"), Value: []byte("bar")}}, }}, }, + "with context events - released on commit": { + msgs: []wasmvmtypes.SubMsg{{ + ReplyOn: wasmvmtypes.ReplyNever, + }}, + replyer: &mockReplyer{}, + msgHandler: &wasmtesting.MockMessageHandler{ + DispatchMsgFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { + myEvents := []sdk.Event{{Type: "myEvent", Attributes: []abci.EventAttribute{{Key: []byte("foo"), Value: []byte("bar")}}}} + ctx.EventManager().EmitEvents(myEvents) + return nil, nil, nil + }, + }, + expCommits: []bool{true}, + expEvents: []sdk.Event{{ + Type: "myEvent", + Attributes: []abci.EventAttribute{{Key: []byte("foo"), Value: []byte("bar")}}, + }}, + }, + "with context events - discarded on failure": { + msgs: []wasmvmtypes.SubMsg{{ + ReplyOn: wasmvmtypes.ReplyNever, + }}, + replyer: &mockReplyer{}, + msgHandler: &wasmtesting.MockMessageHandler{ + DispatchMsgFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { + myEvents := []sdk.Event{{Type: "myEvent", Attributes: []abci.EventAttribute{{Key: []byte("foo"), Value: []byte("bar")}}}} + ctx.EventManager().EmitEvents(myEvents) + return nil, nil, errors.New("testing") + }, + }, + expCommits: []bool{false}, + expErr: true, + }, "reply returns error": { msgs: []wasmvmtypes.SubMsg{{ ReplyOn: wasmvmtypes.ReplySuccess, @@ -151,7 +184,38 @@ func TestDispatchSubmessages(t *testing.T) { }, expCommits: []bool{true}, }, - "multiple msg - last reply": { + "never reply - with nil response": { + msgs: []wasmvmtypes.SubMsg{{ID: 1, ReplyOn: wasmvmtypes.ReplyNever}, {ID: 2, ReplyOn: wasmvmtypes.ReplyNever}}, + replyer: &mockReplyer{}, + msgHandler: &wasmtesting.MockMessageHandler{ + DispatchMsgFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { + return nil, [][]byte{nil}, nil + }, + }, + expCommits: []bool{true, true}, + }, + "never reply - with any non nil response": { + msgs: []wasmvmtypes.SubMsg{{ID: 1, ReplyOn: wasmvmtypes.ReplyNever}, {ID: 2, ReplyOn: wasmvmtypes.ReplyNever}}, + replyer: &mockReplyer{}, + msgHandler: &wasmtesting.MockMessageHandler{ + DispatchMsgFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { + return nil, [][]byte{{}}, nil + }, + }, + expCommits: []bool{true, true}, + }, + "never reply - with error": { + msgs: []wasmvmtypes.SubMsg{{ID: 1, ReplyOn: wasmvmtypes.ReplyNever}, {ID: 2, ReplyOn: wasmvmtypes.ReplyNever}}, + replyer: &mockReplyer{}, + msgHandler: &wasmtesting.MockMessageHandler{ + DispatchMsgFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { + return nil, [][]byte{{}}, errors.New("testing") + }, + }, + expCommits: []bool{false, false}, + expErr: true, + }, + "multiple msg - last reply returned": { msgs: []wasmvmtypes.SubMsg{{ID: 1, ReplyOn: wasmvmtypes.ReplyError}, {ID: 2, ReplyOn: wasmvmtypes.ReplyError}}, replyer: &mockReplyer{ replyFn: func(ctx sdk.Context, contractAddress sdk.AccAddress, reply wasmvmtypes.Reply) ([]byte, error) { @@ -166,7 +230,7 @@ func TestDispatchSubmessages(t *testing.T) { expData: []byte("myReplyData:2"), expCommits: []bool{false, false}, }, - "multiple msg - last non nil reply to overwrite responose": { + "multiple msg - last non nil reply returned": { msgs: []wasmvmtypes.SubMsg{{ID: 1, ReplyOn: wasmvmtypes.ReplyError}, {ID: 2, ReplyOn: wasmvmtypes.ReplyError}}, replyer: &mockReplyer{ replyFn: func(ctx sdk.Context, contractAddress sdk.AccAddress, reply wasmvmtypes.Reply) ([]byte, error) { @@ -202,19 +266,6 @@ func TestDispatchSubmessages(t *testing.T) { expData: []byte{}, expCommits: []bool{false, false}, }, - "empty replyOn rejected": { - msgs: []wasmvmtypes.SubMsg{{}}, - replyer: noReplyCalled, - msgHandler: &wasmtesting.MockMessageHandler{}, - expErr: true, - }, - "invalid replyOn rejected": { - msgs: []wasmvmtypes.SubMsg{{ReplyOn: "invalid"}}, - replyer: noReplyCalled, - msgHandler: &wasmtesting.MockMessageHandler{}, - expCommits: []bool{false}, - expErr: true, - }, } for name, spec := range specs { t.Run(name, func(t *testing.T) { @@ -227,6 +278,7 @@ func TestDispatchSubmessages(t *testing.T) { gotData, gotErr := d.DispatchSubmessages(ctx, RandomAccountAddress(t), "any_port", spec.msgs) if spec.expErr { require.Error(t, gotErr) + assert.Empty(t, em.Events()) return } else { require.NoError(t, gotErr) diff --git a/x/wasm/keeper/querier_test.go b/x/wasm/keeper/querier_test.go index da0f01bd8a..40228ddec2 100644 --- a/x/wasm/keeper/querier_test.go +++ b/x/wasm/keeper/querier_test.go @@ -179,7 +179,7 @@ func TestQuerySmartContractPanics(t *testing.T) { } for msg, spec := range specs { t.Run(msg, func(t *testing.T) { - keepers.WasmKeeper.wasmVM = &wasmtesting.MockWasmer{QueryFn: func(checksum cosmwasm.Checksum, env wasmvmtypes.Env, queryMsg []byte, store cosmwasm.KVStore, goapi cosmwasm.GoAPI, querier cosmwasm.Querier, gasMeter cosmwasm.GasMeter, gasLimit uint64) ([]byte, uint64, error) { + keepers.WasmKeeper.wasmVM = &wasmtesting.MockWasmer{QueryFn: func(checksum cosmwasm.Checksum, env wasmvmtypes.Env, queryMsg []byte, store cosmwasm.KVStore, goapi cosmwasm.GoAPI, querier cosmwasm.Querier, gasMeter cosmwasm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) ([]byte, uint64, error) { spec.doInContract() return nil, 0, nil }} diff --git a/x/wasm/keeper/recurse_test.go b/x/wasm/keeper/recurse_test.go index 1508c0849d..0912cb8e3a 100644 --- a/x/wasm/keeper/recurse_test.go +++ b/x/wasm/keeper/recurse_test.go @@ -57,12 +57,12 @@ func initRecurseContract(t *testing.T) (contract sdk.AccAddress, creator sdk.Acc func TestGasCostOnQuery(t *testing.T) { const ( - GasNoWork uint64 = 44_163 + GasNoWork uint64 = 44_240 // Note: about 100 SDK gas (10k wasmer gas) for each round of sha256 - GasWork50 uint64 = 49_856 // this is a little shy of 50k gas - to keep an eye on the limit + GasWork50 uint64 = 49_901 // this is a little shy of 50k gas - to keep an eye on the limit - GasReturnUnhashed uint64 = 224 - GasReturnHashed uint64 = 198 + GasReturnUnhashed uint64 = 197 + GasReturnHashed uint64 = 173 ) cases := map[string]struct { @@ -221,9 +221,9 @@ func TestLimitRecursiveQueryGas(t *testing.T) { const ( // Note: about 100 SDK gas (10k wasmer gas) for each round of sha256 - GasWork2k uint64 = 273_661 // = NewContractInstanceCosts + x // we have 6x gas used in cpu than in the instance + GasWork2k uint64 = 273_170 // = NewContractInstanceCosts + x // we have 6x gas used in cpu than in the instance // This is overhead for calling into a sub-contract - GasReturnHashed uint64 = 203 + GasReturnHashed uint64 = 177 ) cases := map[string]struct { diff --git a/x/wasm/keeper/reflect_test.go b/x/wasm/keeper/reflect_test.go index c4cba0b07d..f6538fe924 100644 --- a/x/wasm/keeper/reflect_test.go +++ b/x/wasm/keeper/reflect_test.go @@ -24,9 +24,9 @@ import ( // ReflectHandleMsg is used to encode handle messages type ReflectHandleMsg struct { - Reflect *reflectPayload `json:"reflect_msg,omitempty"` - ReflectSubCall *reflectSubPayload `json:"reflect_sub_call,omitempty"` - Change *ownerPayload `json:"change_owner,omitempty"` + Reflect *reflectPayload `json:"reflect_msg,omitempty"` + ReflectSubMsg *reflectSubPayload `json:"reflect_sub_msg,omitempty"` + Change *ownerPayload `json:"change_owner,omitempty"` } type ownerPayload struct { @@ -43,10 +43,10 @@ type reflectSubPayload struct { // ReflectQueryMsg is used to encode query messages type ReflectQueryMsg struct { - Owner *struct{} `json:"owner,omitempty"` - Capitalized *Text `json:"capitalized,omitempty"` - Chain *ChainQuery `json:"chain,omitempty"` - SubCallResult *SubCall `json:"sub_call_result,omitempty"` + Owner *struct{} `json:"owner,omitempty"` + Capitalized *Text `json:"capitalized,omitempty"` + Chain *ChainQuery `json:"chain,omitempty"` + SubMsgResult *SubCall `json:"sub_msg_result,omitempty"` } type ChainQuery struct { @@ -139,7 +139,7 @@ func TestReflectContractSend(t *testing.T) { Execute: &wasmvmtypes.ExecuteMsg{ ContractAddr: escrowAddr.String(), Msg: approveMsg, - Send: []wasmvmtypes.Coin{{ + Funds: []wasmvmtypes.Coin{{ Denom: "denom", Amount: "14000", }}, diff --git a/x/wasm/keeper/relay.go b/x/wasm/keeper/relay.go index 8d59956ca7..af142cca5a 100644 --- a/x/wasm/keeper/relay.go +++ b/x/wasm/keeper/relay.go @@ -30,7 +30,7 @@ func (k Keeper) OnOpenChannel( querier := k.newQueryHandler(ctx, contractAddr) gas := k.runtimeGasForContract(ctx) - gasUsed, execErr := k.wasmVM.IBCChannelOpen(codeInfo.CodeHash, env, channel, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas) + gasUsed, execErr := k.wasmVM.IBCChannelOpen(codeInfo.CodeHash, env, channel, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas, costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if execErr != nil { return sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) @@ -61,7 +61,7 @@ func (k Keeper) OnConnectChannel( querier := k.newQueryHandler(ctx, contractAddr) gas := k.runtimeGasForContract(ctx) - res, gasUsed, execErr := k.wasmVM.IBCChannelConnect(codeInfo.CodeHash, env, channel, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas) + res, gasUsed, execErr := k.wasmVM.IBCChannelConnect(codeInfo.CodeHash, env, channel, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas, costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if execErr != nil { return sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) @@ -92,7 +92,7 @@ func (k Keeper) OnCloseChannel( querier := k.newQueryHandler(ctx, contractAddr) gas := k.runtimeGasForContract(ctx) - res, gasUsed, execErr := k.wasmVM.IBCChannelClose(codeInfo.CodeHash, params, channel, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas) + res, gasUsed, execErr := k.wasmVM.IBCChannelClose(codeInfo.CodeHash, params, channel, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas, costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if execErr != nil { return sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) @@ -122,13 +122,13 @@ func (k Keeper) OnRecvPacket( querier := k.newQueryHandler(ctx, contractAddr) gas := k.runtimeGasForContract(ctx) - res, gasUsed, execErr := k.wasmVM.IBCPacketReceive(codeInfo.CodeHash, env, packet, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas) + res, gasUsed, execErr := k.wasmVM.IBCPacketReceive(codeInfo.CodeHash, env, packet, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas, costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if execErr != nil { return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) } - - return k.handleContractResponse(ctx, contractAddr, contractInfo.IBCPortID, res.Submessages, res.Messages, res.Attributes, res.Acknowledgement) + // note submessage reply results can overwrite the `Acknowledgement` data + return k.handleContractResponse(ctx, contractAddr, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Acknowledgement, nil) } // OnAckPacket calls the contract to handle the "acknowledgement" data which can contain success or failure of a packet @@ -141,7 +141,7 @@ func (k Keeper) OnRecvPacket( func (k Keeper) OnAckPacket( ctx sdk.Context, contractAddr sdk.AccAddress, - acknowledgement wasmvmtypes.IBCAcknowledgement, + acknowledgement wasmvmtypes.IBCAcknowledgementWithPacket, ) error { defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "ibc-ack-packet") contractInfo, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddr) @@ -153,7 +153,7 @@ func (k Keeper) OnAckPacket( querier := k.newQueryHandler(ctx, contractAddr) gas := k.runtimeGasForContract(ctx) - res, gasUsed, execErr := k.wasmVM.IBCPacketAck(codeInfo.CodeHash, env, acknowledgement, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas) + res, gasUsed, execErr := k.wasmVM.IBCPacketAck(codeInfo.CodeHash, env, acknowledgement, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas, costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if execErr != nil { return sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) @@ -180,7 +180,7 @@ func (k Keeper) OnTimeoutPacket( querier := k.newQueryHandler(ctx, contractAddr) gas := k.runtimeGasForContract(ctx) - res, gasUsed, execErr := k.wasmVM.IBCPacketTimeout(codeInfo.CodeHash, env, packet, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas) + res, gasUsed, execErr := k.wasmVM.IBCPacketTimeout(codeInfo.CodeHash, env, packet, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas, costJsonDeserialization) k.consumeRuntimeGas(ctx, gasUsed) if execErr != nil { return sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) @@ -190,6 +190,6 @@ func (k Keeper) OnTimeoutPacket( } func (k Keeper) handleIBCBasicContractResponse(ctx sdk.Context, addr sdk.AccAddress, id string, res *wasmvmtypes.IBCBasicResponse) error { - _, err := k.handleContractResponse(ctx, addr, id, res.Submessages, res.Messages, res.Attributes, nil) + _, err := k.handleContractResponse(ctx, addr, id, res.Messages, res.Attributes, nil, nil) return err } diff --git a/x/wasm/keeper/relay_test.go b/x/wasm/keeper/relay_test.go index c0287ad3d0..84cdef2439 100644 --- a/x/wasm/keeper/relay_test.go +++ b/x/wasm/keeper/relay_test.go @@ -52,7 +52,7 @@ func TestOnOpenChannel(t *testing.T) { for name, spec := range specs { t.Run(name, func(t *testing.T) { myChannel := wasmvmtypes.IBCChannel{Version: "my test channel"} - m.IBCChannelOpenFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (uint64, error) { + m.IBCChannelOpenFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (uint64, error) { assert.Equal(t, myChannel, channel) return spec.contractGas * DefaultGasMultiplier, spec.contractErr } @@ -103,7 +103,7 @@ func TestOnConnectChannel(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}}, Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, }, contractErr: errors.New("test, ignore"), @@ -114,7 +114,7 @@ func TestOnConnectChannel(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}, {Custom: json.RawMessage(`{"foo":"bar"}`)}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, }, }, "emit contract events on success": { @@ -129,7 +129,7 @@ func TestOnConnectChannel(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas + 10, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}, {Custom: json.RawMessage(`{"foo":"bar"}`)}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, }, overwriteMessenger: wasmtesting.NewErroringMessageHandler(), @@ -145,7 +145,7 @@ func TestOnConnectChannel(t *testing.T) { for name, spec := range specs { t.Run(name, func(t *testing.T) { myChannel := wasmvmtypes.IBCChannel{Version: "my test channel"} - m.IBCChannelConnectFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + m.IBCChannelConnectFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { assert.Equal(t, channel, myChannel) return spec.contractResp, myContractGas * DefaultGasMultiplier, spec.contractErr } @@ -181,7 +181,12 @@ func TestOnConnectChannel(t *testing.T) { const storageCosts = sdk.Gas(0xa9d) assert.Equal(t, spec.expContractGas, ctx.GasMeter().GasConsumed()-before-storageCosts) // verify msgs dispatched - assert.Equal(t, spec.contractResp.Messages, *capturedMsgs) + require.Len(t, *capturedMsgs, len(spec.contractResp.Messages)) + for i, m := range spec.contractResp.Messages { + assert.Equal(t, (*capturedMsgs)[i], m.Msg) + } + // verify events + require.Len(t, events, 1) assert.Len(t, events[0].Attributes, 1+spec.expContractEventAttrs) }) } @@ -214,7 +219,7 @@ func TestOnCloseChannel(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}}, Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, }, contractErr: errors.New("test, ignore"), @@ -225,7 +230,7 @@ func TestOnCloseChannel(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}, {Custom: json.RawMessage(`{"foo":"bar"}`)}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, }, }, "emit contract events on success": { @@ -240,7 +245,7 @@ func TestOnCloseChannel(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas + 10, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}, {Custom: json.RawMessage(`{"foo":"bar"}`)}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, }, overwriteMessenger: wasmtesting.NewErroringMessageHandler(), @@ -256,7 +261,7 @@ func TestOnCloseChannel(t *testing.T) { for name, spec := range specs { t.Run(name, func(t *testing.T) { myChannel := wasmvmtypes.IBCChannel{Version: "my test channel"} - m.IBCChannelCloseFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + m.IBCChannelCloseFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { assert.Equal(t, channel, myChannel) return spec.contractResp, myContractGas * DefaultGasMultiplier, spec.contractErr } @@ -291,7 +296,10 @@ func TestOnCloseChannel(t *testing.T) { const storageCosts = sdk.Gas(0xa9d) assert.Equal(t, spec.expContractGas, ctx.GasMeter().GasConsumed()-before-storageCosts) // verify msgs dispatched - assert.Equal(t, spec.contractResp.Messages, *capturedMsgs) + require.Len(t, *capturedMsgs, len(spec.contractResp.Messages)) + for i, m := range spec.contractResp.Messages { + assert.Equal(t, (*capturedMsgs)[i], m.Msg) + } require.Len(t, events, 1) assert.Len(t, events[0].Attributes, 1+spec.expContractEventAttrs) }) @@ -311,7 +319,9 @@ func TestOnRecvPacket(t *testing.T) { contractResp *wasmvmtypes.IBCReceiveResponse contractErr error overwriteMessenger *wasmtesting.MockMessageHandler + mockReplyFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) expContractGas sdk.Gas + expAck []byte expErr bool expContractEventAttrs int expNoEvents bool @@ -322,6 +332,7 @@ func TestOnRecvPacket(t *testing.T) { contractResp: &wasmvmtypes.IBCReceiveResponse{ Acknowledgement: []byte("myAck"), }, + expAck: []byte("myAck"), }, "can return empty ack": { contractAddr: example.Contract, @@ -333,7 +344,7 @@ func TestOnRecvPacket(t *testing.T) { expContractGas: myContractGas, contractResp: &wasmvmtypes.IBCReceiveResponse{ Acknowledgement: []byte("myAck"), - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}}, Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, }, contractErr: errors.New("test, ignore"), @@ -345,8 +356,9 @@ func TestOnRecvPacket(t *testing.T) { expContractGas: myContractGas, contractResp: &wasmvmtypes.IBCReceiveResponse{ Acknowledgement: []byte("myAck"), - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}, {Custom: json.RawMessage(`{"foo":"bar"}`)}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, }, + expAck: []byte("myAck"), }, "emit contract events on success": { contractAddr: example.Contract, @@ -356,19 +368,32 @@ func TestOnRecvPacket(t *testing.T) { Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, }, expContractEventAttrs: 1, + expAck: []byte("myAck"), }, "messenger errors returned, events stored": { contractAddr: example.Contract, expContractGas: myContractGas + 10, contractResp: &wasmvmtypes.IBCReceiveResponse{ Acknowledgement: []byte("myAck"), - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}, {Custom: json.RawMessage(`{"foo":"bar"}`)}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, }, overwriteMessenger: wasmtesting.NewErroringMessageHandler(), expErr: true, expContractEventAttrs: 1, }, + "submessage reply can overwrite ack data": { + contractAddr: example.Contract, + expContractGas: myContractGas + 10 + DefaultInstanceCost + 3708, + contractResp: &wasmvmtypes.IBCReceiveResponse{ + Acknowledgement: []byte("myAck"), + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyAlways, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}}, + }, + mockReplyFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { + return &wasmvmtypes.Response{Data: []byte("myBetterAck")}, 0, nil + }, + expAck: []byte("myBetterAck"), + }, "unknown contract address": { contractAddr: RandomAccountAddress(t), expErr: true, @@ -379,10 +404,16 @@ func TestOnRecvPacket(t *testing.T) { t.Run(name, func(t *testing.T) { myPacket := wasmvmtypes.IBCPacket{Data: []byte("my data")} - m.IBCPacketReceiveFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { + m.IBCPacketReceiveFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { assert.Equal(t, myPacket, packet) return spec.contractResp, myContractGas * DefaultGasMultiplier, spec.contractErr } + if spec.mockReplyFn != nil { + m.ReplyFn = spec.mockReplyFn + h, ok := keepers.WasmKeeper.wasmVMResponseHandler.(*DefaultWasmVMContractResponseHandler) + require.True(t, ok) + h.md = NewMessageDispatcher(messenger, keepers.WasmKeeper) + } ctx, _ := parentCtx.CacheContext() before := ctx.GasMeter().GasConsumed() @@ -411,13 +442,16 @@ func TestOnRecvPacket(t *testing.T) { return } require.NoError(t, err) - require.Equal(t, spec.contractResp.Acknowledgement, gotAck) + require.Equal(t, spec.expAck, gotAck) // verify gas consumed const storageCosts = sdk.Gas(0xa9d) assert.Equal(t, spec.expContractGas, ctx.GasMeter().GasConsumed()-before-storageCosts) // verify msgs dispatched - assert.Equal(t, spec.contractResp.Messages, *capturedMsgs) + require.Len(t, *capturedMsgs, len(spec.contractResp.Messages)) + for i, m := range spec.contractResp.Messages { + assert.Equal(t, (*capturedMsgs)[i], m.Msg) + } require.Len(t, events, 1) assert.Len(t, events[0].Attributes, 1+spec.expContractEventAttrs) }) @@ -451,7 +485,7 @@ func TestOnAckPacket(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}}, Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, }, contractErr: errors.New("test, ignore"), @@ -462,7 +496,7 @@ func TestOnAckPacket(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}, {Custom: json.RawMessage(`{"foo":"bar"}`)}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, }, }, "emit contract events on success": { @@ -477,7 +511,7 @@ func TestOnAckPacket(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas + 10, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}, {Custom: json.RawMessage(`{"foo":"bar"}`)}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, }, overwriteMessenger: wasmtesting.NewErroringMessageHandler(), @@ -493,8 +527,8 @@ func TestOnAckPacket(t *testing.T) { for name, spec := range specs { t.Run(name, func(t *testing.T) { - myAck := wasmvmtypes.IBCAcknowledgement{Acknowledgement: []byte("myAck")} - m.IBCPacketAckFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCAcknowledgement, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + myAck := wasmvmtypes.IBCAcknowledgementWithPacket{Acknowledgement: wasmvmtypes.IBCAcknowledgement{Data: []byte("myAck")}} + m.IBCPacketAckFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCAcknowledgementWithPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { assert.Equal(t, myAck, ack) return spec.contractResp, myContractGas * DefaultGasMultiplier, spec.contractErr } @@ -529,7 +563,11 @@ func TestOnAckPacket(t *testing.T) { const storageCosts = sdk.Gas(0xa9d) assert.Equal(t, spec.expContractGas, ctx.GasMeter().GasConsumed()-before-storageCosts) // verify msgs dispatched - assert.Equal(t, spec.contractResp.Messages, *capturedMsgs) + require.Len(t, *capturedMsgs, len(spec.contractResp.Messages)) + for i, m := range spec.contractResp.Messages { + assert.Equal(t, (*capturedMsgs)[i], m.Msg) + } + require.Len(t, events, 1) assert.Len(t, events[0].Attributes, 1+spec.expContractEventAttrs) }) @@ -563,7 +601,7 @@ func TestOnTimeoutPacket(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}}, Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, }, contractErr: errors.New("test, ignore"), @@ -574,7 +612,7 @@ func TestOnTimeoutPacket(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}, {Custom: json.RawMessage(`{"foo":"bar"}`)}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, }, }, "emit contract events on success": { @@ -589,7 +627,7 @@ func TestOnTimeoutPacket(t *testing.T) { contractAddr: example.Contract, expContractGas: myContractGas + 10, contractResp: &wasmvmtypes.IBCBasicResponse{ - Messages: []wasmvmtypes.CosmosMsg{{Bank: &wasmvmtypes.BankMsg{}}, {Custom: json.RawMessage(`{"foo":"bar"}`)}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: &wasmvmtypes.BankMsg{}}}, {ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Custom: json.RawMessage(`{"foo":"bar"}`)}}}, Attributes: []wasmvmtypes.EventAttribute{{Key: "Foo", Value: "Bar"}}, }, overwriteMessenger: wasmtesting.NewErroringMessageHandler(), @@ -605,7 +643,7 @@ func TestOnTimeoutPacket(t *testing.T) { for name, spec := range specs { t.Run(name, func(t *testing.T) { myPacket := wasmvmtypes.IBCPacket{Data: []byte("my test packet")} - m.IBCPacketTimeoutFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + m.IBCPacketTimeoutFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { assert.Equal(t, myPacket, packet) return spec.contractResp, myContractGas * DefaultGasMultiplier, spec.contractErr } @@ -640,7 +678,10 @@ func TestOnTimeoutPacket(t *testing.T) { const storageCosts = sdk.Gas(0xa9d) assert.Equal(t, spec.expContractGas, ctx.GasMeter().GasConsumed()-before-storageCosts) // verify msgs dispatched - assert.Equal(t, spec.contractResp.Messages, *capturedMsgs) + require.Len(t, *capturedMsgs, len(spec.contractResp.Messages)) + for i, m := range spec.contractResp.Messages { + assert.Equal(t, (*capturedMsgs)[i], m.Msg) + } require.Len(t, events, 1) assert.Len(t, events[0].Attributes, 1+spec.expContractEventAttrs) }) diff --git a/x/wasm/keeper/submsg_test.go b/x/wasm/keeper/submsg_test.go index c33a4de36e..af3a001957 100644 --- a/x/wasm/keeper/submsg_test.go +++ b/x/wasm/keeper/submsg_test.go @@ -57,7 +57,7 @@ func TestDispatchSubMsgSuccessCase(t *testing.T) { }, } reflectSend := ReflectHandleMsg{ - ReflectSubCall: &reflectSubPayload{ + ReflectSubMsg: &reflectSubPayload{ Msgs: []wasmvmtypes.SubMsg{{ ID: 7, Msg: msg, @@ -78,7 +78,7 @@ func TestDispatchSubMsgSuccessCase(t *testing.T) { // query the reflect state to ensure the result was stored query := ReflectQueryMsg{ - SubCallResult: &SubCall{ID: 7}, + SubMsgResult: &SubCall{ID: 7}, } queryBz, err := json.Marshal(query) require.NoError(t, err) @@ -318,7 +318,7 @@ func TestDispatchSubMsgErrorHandling(t *testing.T) { msg := tc.msg(contractAddr.String(), empty.String()) reflectSend := ReflectHandleMsg{ - ReflectSubCall: &reflectSubPayload{ + ReflectSubMsg: &reflectSubPayload{ Msgs: []wasmvmtypes.SubMsg{{ ID: tc.submsgID, Msg: msg, @@ -349,7 +349,7 @@ func TestDispatchSubMsgErrorHandling(t *testing.T) { // query the reply query := ReflectQueryMsg{ - SubCallResult: &SubCall{ID: tc.submsgID}, + SubMsgResult: &SubCall{ID: tc.submsgID}, } queryBz, err := json.Marshal(query) require.NoError(t, err) @@ -421,7 +421,7 @@ func TestDispatchSubMsgEncodeToNoSdkMsg(t *testing.T) { }, } reflectSend := ReflectHandleMsg{ - ReflectSubCall: &reflectSubPayload{ + ReflectSubMsg: &reflectSubPayload{ Msgs: []wasmvmtypes.SubMsg{{ ID: 7, Msg: msg, @@ -436,7 +436,7 @@ func TestDispatchSubMsgEncodeToNoSdkMsg(t *testing.T) { // query the reflect state to ensure the result was stored query := ReflectQueryMsg{ - SubCallResult: &SubCall{ID: 7}, + SubMsgResult: &SubCall{ID: 7}, } queryBz, err := json.Marshal(query) require.NoError(t, err) @@ -547,7 +547,7 @@ func TestDispatchSubMsgConditionalReplyOn(t *testing.T) { } reflectSend := ReflectHandleMsg{ - ReflectSubCall: &reflectSubPayload{ + ReflectSubMsg: &reflectSubPayload{ Msgs: []wasmvmtypes.SubMsg{subMsg}, }, } @@ -563,7 +563,7 @@ func TestDispatchSubMsgConditionalReplyOn(t *testing.T) { // query the reflect state to check if the result was stored query := ReflectQueryMsg{ - SubCallResult: &SubCall{ID: id}, + SubMsgResult: &SubCall{ID: id}, } queryBz, err := json.Marshal(query) require.NoError(t, err) diff --git a/x/wasm/keeper/testdata/burner.wasm b/x/wasm/keeper/testdata/burner.wasm index a060cb5a64..376de569a4 100644 Binary files a/x/wasm/keeper/testdata/burner.wasm and b/x/wasm/keeper/testdata/burner.wasm differ diff --git a/x/wasm/keeper/testdata/hackatom.wasm b/x/wasm/keeper/testdata/hackatom.wasm index e9f0b90503..de26a77b62 100644 Binary files a/x/wasm/keeper/testdata/hackatom.wasm and b/x/wasm/keeper/testdata/hackatom.wasm differ diff --git a/x/wasm/keeper/testdata/hackatom.wasm.gzip b/x/wasm/keeper/testdata/hackatom.wasm.gzip index 8ce63272f4..5f1f92f2d6 100644 Binary files a/x/wasm/keeper/testdata/hackatom.wasm.gzip and b/x/wasm/keeper/testdata/hackatom.wasm.gzip differ diff --git a/x/wasm/keeper/testdata/ibc_reflect.wasm b/x/wasm/keeper/testdata/ibc_reflect.wasm index 33f49b33e0..8f2dda3bda 100644 Binary files a/x/wasm/keeper/testdata/ibc_reflect.wasm and b/x/wasm/keeper/testdata/ibc_reflect.wasm differ diff --git a/x/wasm/keeper/testdata/ibc_reflect_send.wasm b/x/wasm/keeper/testdata/ibc_reflect_send.wasm index dca7f5f0d2..547a8bccd4 100644 Binary files a/x/wasm/keeper/testdata/ibc_reflect_send.wasm and b/x/wasm/keeper/testdata/ibc_reflect_send.wasm differ diff --git a/x/wasm/keeper/testdata/reflect.wasm b/x/wasm/keeper/testdata/reflect.wasm index 4606c4a8df..2455801fa8 100644 Binary files a/x/wasm/keeper/testdata/reflect.wasm and b/x/wasm/keeper/testdata/reflect.wasm differ diff --git a/x/wasm/keeper/testdata/staking.wasm b/x/wasm/keeper/testdata/staking.wasm index 93c7cb4564..b7b9d32cf1 100644 Binary files a/x/wasm/keeper/testdata/staking.wasm and b/x/wasm/keeper/testdata/staking.wasm differ diff --git a/x/wasm/keeper/wasmtesting/gas_register.go b/x/wasm/keeper/wasmtesting/gas_register.go index a8533709af..1c1a319ba0 100644 --- a/x/wasm/keeper/wasmtesting/gas_register.go +++ b/x/wasm/keeper/wasmtesting/gas_register.go @@ -44,7 +44,7 @@ func (m MockGasRegister) ReplyCosts(pinned bool, reply wasmvmtypes.Reply) sdk.Ga return m.ReplyCostFn(pinned, reply) } -func (m MockGasRegister) EventCosts(evts []wasmvmtypes.EventAttribute) sdk.Gas { +func (m MockGasRegister) EventCosts(evts []wasmvmtypes.EventAttribute, events wasmvmtypes.Events) sdk.Gas { if m.EventCostsFn == nil { panic("not expected to be called") } diff --git a/x/wasm/keeper/wasmtesting/messenger.go b/x/wasm/keeper/wasmtesting/messenger.go index ae964011d7..dbafda3886 100644 --- a/x/wasm/keeper/wasmtesting/messenger.go +++ b/x/wasm/keeper/wasmtesting/messenger.go @@ -12,6 +12,9 @@ type MockMessageHandler struct { } func (m *MockMessageHandler) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { + if m.DispatchMsgFn == nil { + panic("not expected to be called") + } return m.DispatchMsgFn(ctx, contractAddr, contractIBCPortID, msg) } diff --git a/x/wasm/keeper/wasmtesting/mock_engine.go b/x/wasm/keeper/wasmtesting/mock_engine.go index dc8a4c8ca1..689a44db88 100644 --- a/x/wasm/keeper/wasmtesting/mock_engine.go +++ b/x/wasm/keeper/wasmtesting/mock_engine.go @@ -17,65 +17,65 @@ var _ types.WasmerEngine = &MockWasmer{} type MockWasmer struct { CreateFn func(codeID wasmvm.WasmCode) (wasmvm.Checksum, error) AnalyzeCodeFn func(codeID wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error) - InstantiateFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) - ExecuteFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) - QueryFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, queryMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) ([]byte, uint64, error) - MigrateFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, migrateMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) - SudoFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, sudoMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) - ReplyFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) + InstantiateFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) + ExecuteFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) + QueryFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, queryMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) ([]byte, uint64, error) + MigrateFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, migrateMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) + SudoFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, sudoMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) + ReplyFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) GetCodeFn func(codeID wasmvm.Checksum) (wasmvm.WasmCode, error) CleanupFn func() - IBCChannelOpenFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (uint64, error) - IBCChannelConnectFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) - IBCChannelCloseFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) - IBCPacketReceiveFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCReceiveResponse, uint64, error) - IBCPacketAckFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCAcknowledgement, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) - IBCPacketTimeoutFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) + IBCChannelOpenFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (uint64, error) + IBCChannelConnectFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) + IBCChannelCloseFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) + IBCPacketReceiveFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) + IBCPacketAckFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCAcknowledgementWithPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) + IBCPacketTimeoutFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) PinFn func(checksum wasmvm.Checksum) error UnpinFn func(checksum wasmvm.Checksum) error GetMetricsFn func() (*wasmvmtypes.Metrics, error) } -func (m *MockWasmer) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (uint64, error) { +func (m *MockWasmer) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (uint64, error) { if m.IBCChannelOpenFn == nil { panic("not supposed to be called!") } - return m.IBCChannelOpenFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit) + return m.IBCChannelOpenFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit, deserCost) } -func (m *MockWasmer) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (m *MockWasmer) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { if m.IBCChannelConnectFn == nil { panic("not supposed to be called!") } - return m.IBCChannelConnectFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit) + return m.IBCChannelConnectFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit, deserCost) } -func (m *MockWasmer) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (m *MockWasmer) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { if m.IBCChannelCloseFn == nil { panic("not supposed to be called!") } - return m.IBCChannelCloseFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit) + return m.IBCChannelCloseFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit, deserCost) } -func (m *MockWasmer) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { +func (m *MockWasmer) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { if m.IBCPacketReceiveFn == nil { panic("not supposed to be called!") } - return m.IBCPacketReceiveFn(codeID, env, packet, store, goapi, querier, gasMeter, gasLimit) + return m.IBCPacketReceiveFn(codeID, env, packet, store, goapi, querier, gasMeter, gasLimit, deserCost) } -func (m *MockWasmer) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCAcknowledgement, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (m *MockWasmer) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCAcknowledgementWithPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { if m.IBCPacketAckFn == nil { panic("not supposed to be called!") } - return m.IBCPacketAckFn(codeID, env, ack, store, goapi, querier, gasMeter, gasLimit) + return m.IBCPacketAckFn(codeID, env, ack, store, goapi, querier, gasMeter, gasLimit, deserCost) } -func (m *MockWasmer) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (m *MockWasmer) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { if m.IBCPacketTimeoutFn == nil { panic("not supposed to be called!") } - return m.IBCPacketTimeoutFn(codeID, env, packet, store, goapi, querier, gasMeter, gasLimit) + return m.IBCPacketTimeoutFn(codeID, env, packet, store, goapi, querier, gasMeter, gasLimit, deserCost) } func (m *MockWasmer) Create(codeID wasmvm.WasmCode) (wasmvm.Checksum, error) { @@ -92,47 +92,47 @@ func (m *MockWasmer) AnalyzeCode(codeID wasmvm.Checksum) (*wasmvmtypes.AnalysisR return m.AnalyzeCodeFn(codeID) } -func (m *MockWasmer) Instantiate(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { +func (m *MockWasmer) Instantiate(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { if m.InstantiateFn == nil { panic("not supposed to be called!") } - return m.InstantiateFn(codeID, env, info, initMsg, store, goapi, querier, gasMeter, gasLimit) + return m.InstantiateFn(codeID, env, info, initMsg, store, goapi, querier, gasMeter, gasLimit, deserCost) } -func (m *MockWasmer) Execute(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { +func (m *MockWasmer) Execute(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { if m.ExecuteFn == nil { panic("not supposed to be called!") } - return m.ExecuteFn(codeID, env, info, executeMsg, store, goapi, querier, gasMeter, gasLimit) + return m.ExecuteFn(codeID, env, info, executeMsg, store, goapi, querier, gasMeter, gasLimit, deserCost) } -func (m *MockWasmer) Query(codeID wasmvm.Checksum, env wasmvmtypes.Env, queryMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) ([]byte, uint64, error) { +func (m *MockWasmer) Query(codeID wasmvm.Checksum, env wasmvmtypes.Env, queryMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) ([]byte, uint64, error) { if m.QueryFn == nil { panic("not supposed to be called!") } - return m.QueryFn(codeID, env, queryMsg, store, goapi, querier, gasMeter, gasLimit) + return m.QueryFn(codeID, env, queryMsg, store, goapi, querier, gasMeter, gasLimit, deserCost) } -func (m *MockWasmer) Migrate(codeID wasmvm.Checksum, env wasmvmtypes.Env, migrateMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { +func (m *MockWasmer) Migrate(codeID wasmvm.Checksum, env wasmvmtypes.Env, migrateMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { if m.MigrateFn == nil { panic("not supposed to be called!") } - return m.MigrateFn(codeID, env, migrateMsg, store, goapi, querier, gasMeter, gasLimit) + return m.MigrateFn(codeID, env, migrateMsg, store, goapi, querier, gasMeter, gasLimit, deserCost) } -func (m *MockWasmer) Sudo(codeID wasmvm.Checksum, env wasmvmtypes.Env, sudoMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { +func (m *MockWasmer) Sudo(codeID wasmvm.Checksum, env wasmvmtypes.Env, sudoMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { if m.SudoFn == nil { panic("not supposed to be called!") } - return m.SudoFn(codeID, env, sudoMsg, store, goapi, querier, gasMeter, gasLimit) + return m.SudoFn(codeID, env, sudoMsg, store, goapi, querier, gasMeter, gasLimit, deserCost) } -func (m *MockWasmer) Reply(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { +func (m *MockWasmer) Reply(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { if m.ReplyFn == nil { panic("not supposed to be called!") } - return m.ReplyFn(codeID, env, reply, store, goapi, querier, gasMeter, gasLimit) + return m.ReplyFn(codeID, env, reply, store, goapi, querier, gasMeter, gasLimit, deserCost) } func (m *MockWasmer) GetCode(codeID wasmvm.Checksum) (wasmvm.WasmCode, error) { @@ -180,15 +180,17 @@ func SelfCallingInstMockWasmer(executeCalled *bool) *MockWasmer { anyCodeID := bytes.Repeat([]byte{0x1}, 32) return anyCodeID, nil }, - InstantiateFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { + InstantiateFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { return &wasmvmtypes.Response{ - Messages: []wasmvmtypes.CosmosMsg{ - {Wasm: &wasmvmtypes.WasmMsg{Execute: &wasmvmtypes.ExecuteMsg{ContractAddr: env.Contract.Address, Msg: []byte(`{}`)}}}, + Messages: []wasmvmtypes.SubMsg{ + {Msg: wasmvmtypes.CosmosMsg{ + Wasm: &wasmvmtypes.WasmMsg{Execute: &wasmvmtypes.ExecuteMsg{ContractAddr: env.Contract.Address, Msg: []byte(`{}`)}}, + }}, }, }, 1, nil }, AnalyzeCodeFn: WithoutIBCAnalyzeFn, - ExecuteFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { + ExecuteFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { *executeCalled = true return &wasmvmtypes.Response{}, 1, nil }, @@ -207,6 +209,7 @@ type IBCContractCallbacks interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (uint64, error) IBCChannelConnect( @@ -218,6 +221,7 @@ type IBCContractCallbacks interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.IBCBasicResponse, uint64, error) IBCChannelClose( @@ -229,6 +233,7 @@ type IBCContractCallbacks interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.IBCBasicResponse, uint64, error) IBCPacketReceive( @@ -240,17 +245,19 @@ type IBCContractCallbacks interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.IBCReceiveResponse, uint64, error) IBCPacketAck( codeID wasmvm.Checksum, env wasmvmtypes.Env, - ack wasmvmtypes.IBCAcknowledgement, + ack wasmvmtypes.IBCAcknowledgementWithPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.IBCBasicResponse, uint64, error) IBCPacketTimeout( @@ -262,6 +269,7 @@ type IBCContractCallbacks interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.IBCBasicResponse, uint64, error) } @@ -276,6 +284,7 @@ type contractExecutable interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.Response, uint64, error) } @@ -320,7 +329,7 @@ func HashOnlyCreateFn(code wasmvm.WasmCode) (wasmvm.Checksum, error) { return hash[:], nil } -func NoOpInstantiateFn(wasmvm.Checksum, wasmvmtypes.Env, wasmvmtypes.MessageInfo, []byte, wasmvm.KVStore, wasmvm.GoAPI, wasmvm.Querier, wasmvm.GasMeter, uint64) (*wasmvmtypes.Response, uint64, error) { +func NoOpInstantiateFn(wasmvm.Checksum, wasmvmtypes.Env, wasmvmtypes.MessageInfo, []byte, wasmvm.KVStore, wasmvm.GoAPI, wasmvm.Querier, wasmvm.GasMeter, uint64, wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { return &wasmvmtypes.Response{}, 0, nil } diff --git a/x/wasm/keeper/wasmtesting/msg_dispatcher.go b/x/wasm/keeper/wasmtesting/msg_dispatcher.go index b05d25dfc8..a6600941a5 100644 --- a/x/wasm/keeper/wasmtesting/msg_dispatcher.go +++ b/x/wasm/keeper/wasmtesting/msg_dispatcher.go @@ -6,17 +6,9 @@ import ( ) type MockMsgDispatcher struct { - DispatchMessagesFn func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.CosmosMsg) error DispatchSubmessagesFn func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) } -func (m MockMsgDispatcher) DispatchMessages(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.CosmosMsg) error { - if m.DispatchMessagesFn == nil { - panic("not expected to be called") - } - return m.DispatchMessagesFn(ctx, contractAddr, ibcPort, msgs) -} - func (m MockMsgDispatcher) DispatchSubmessages(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) { if m.DispatchSubmessagesFn == nil { panic("not expected to be called") diff --git a/x/wasm/module_test.go b/x/wasm/module_test.go index 6d0f2aa271..438c2915b7 100644 --- a/x/wasm/module_test.go +++ b/x/wasm/module_test.go @@ -270,26 +270,30 @@ func TestHandleExecute(t *testing.T) { // from https://github.com/CosmWasm/cosmwasm/blob/master/contracts/hackatom/src/contract.rs#L167 assertExecuteResponse(t, res.Data, []byte{0xf0, 0x0b, 0xaa}) - // this should be standard x/wasm init event, plus 2 bank send event, plus a special event from the contract - require.Equal(t, 4, len(res.Events), prettyEvents(res.Events)) + // this should be standard message event, plus x/wasm init event, plus 2 bank send event, plus a special event from the contract + require.Equal(t, 5, len(res.Events), prettyEvents(res.Events)) require.Equal(t, "transfer", res.Events[0].Type) require.Len(t, res.Events[0].Attributes, 3) assertAttribute(t, "recipient", contractBech32Addr, res.Events[0].Attributes[0]) assertAttribute(t, "sender", fred.String(), res.Events[0].Attributes[1]) assertAttribute(t, "amount", "5000denom", res.Events[0].Attributes[2]) - // custom contract event + // custom contract event attribute assert.Equal(t, "wasm", res.Events[1].Type) assertAttribute(t, "contract_address", contractBech32Addr, res.Events[1].Attributes[0]) assertAttribute(t, "action", "release", res.Events[1].Attributes[1]) + // custom contract event + assert.Equal(t, "wasm-hackatom", res.Events[2].Type) + assertAttribute(t, "contract_address", contractBech32Addr, res.Events[1].Attributes[0]) + assertAttribute(t, "action", "release", res.Events[1].Attributes[1]) // second transfer (this without conflicting message) - assert.Equal(t, "transfer", res.Events[2].Type) - assertAttribute(t, "recipient", bob.String(), res.Events[2].Attributes[0]) - assertAttribute(t, "sender", contractBech32Addr, res.Events[2].Attributes[1]) - assertAttribute(t, "amount", "105000denom", res.Events[2].Attributes[2]) + assert.Equal(t, "transfer", res.Events[3].Type) + assertAttribute(t, "recipient", bob.String(), res.Events[3].Attributes[0]) + assertAttribute(t, "sender", contractBech32Addr, res.Events[3].Attributes[1]) + assertAttribute(t, "amount", "105000denom", res.Events[3].Attributes[2]) // finally, standard x/wasm tag - assert.Equal(t, "message", res.Events[3].Type) - assertAttribute(t, "module", "wasm", res.Events[3].Attributes[0]) + assert.Equal(t, "message", res.Events[4].Type) + assertAttribute(t, "module", "wasm", res.Events[4].Attributes[0]) // ensure bob now exists and got both payments released bobAcct = data.acctKeeper.GetAccount(data.ctx, bob) diff --git a/x/wasm/relay_pingpong_test.go b/x/wasm/relay_pingpong_test.go index 7b986f0f60..57361095c3 100644 --- a/x/wasm/relay_pingpong_test.go +++ b/x/wasm/relay_pingpong_test.go @@ -65,8 +65,7 @@ func TestPinPong(t *testing.T) { connA.NextChannelVersion = ping connB.NextChannelVersion = pong - channelA, channelB := coordinator.CreateChannel(chainA, chainB, connA, connB, sourcePortID, counterpartyPortID, channeltypes.UNORDERED) - var err error + channelA, _ := coordinator.CreateChannel(chainA, chainB, connA, connB, sourcePortID, counterpartyPortID, channeltypes.UNORDERED) const startValue uint64 = 100 const rounds = 3 @@ -80,43 +79,19 @@ func TestPinPong(t *testing.T) { Msg: s.GetBytes(), } // send message to chainA - err = coordinator.SendMsg(chainA, chainB, clientB, startMsg) + err := coordinator.SendMsg(chainA, chainB, clientB, startMsg) require.NoError(t, err) t.Log("Duplicate messages are due to check/deliver tx calls") - var ( - activePlayer = ping - pingBallValue = startValue - ) for i := 1; i <= rounds; i++ { t.Logf("++ round: %d\n", i) - ball := NewHit(activePlayer, pingBallValue) - - seq := uint64(i) - pkg := channeltypes.NewPacket(ball.GetBytes(), seq, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, doNotTimeout, 0) - ack := ball.BuildAck() - - err = coordinator.RelayPacket(chainA, chainB, clientA, clientB, pkg, ack.GetBytes()) - require.NoError(t, err) - //coordinator.CommitBlock(chainA, chainB) - err = coordinator.UpdateClient(chainA, chainB, clientA, ibcexported.Tendermint) + err := coordinator.RelayAndAckPendingPackets(chainA, chainB, clientA, clientB) require.NoError(t, err) // switch side - activePlayer = counterParty(activePlayer) - ball = NewHit(activePlayer, uint64(i)) - pkg = channeltypes.NewPacket(ball.GetBytes(), seq, channelB.PortID, channelB.ID, channelA.PortID, channelA.ID, doNotTimeout, 0) - ack = ball.BuildAck() - - err = coordinator.RelayPacket(chainB, chainA, clientB, clientA, pkg, ack.GetBytes()) - require.NoError(t, err) - err = coordinator.UpdateClient(chainB, chainA, clientB, ibcexported.Tendermint) + err = coordinator.RelayAndAckPendingPackets(chainB, chainA, clientB, clientA) require.NoError(t, err) - - // switch side for next round - activePlayer = counterParty(activePlayer) - pingBallValue++ } assert.Equal(t, startValue+rounds, pingContract.QueryState(lastBallSentKey)) assert.Equal(t, uint64(rounds), pingContract.QueryState(lastBallReceivedKey)) @@ -145,7 +120,7 @@ type player struct { // Execute starts the ping pong game // Contracts finds all connected channels and broadcasts a ping message -func (p *player) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { +func (p *player) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { p.execCalls++ if p.execCalls%2 == 1 { // skip checkTx step because of no rollback with `chain.GetContext()` return &wasmvmtypes.Response{}, 0, nil @@ -165,8 +140,8 @@ func (p *player) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmt p.incrementCounter(sentBallsCountKey, store) store.Set(lastBallSentKey, sdk.Uint64ToBigEndian(start.Value)) return &wasmvmtypes.Response{ - Messages: []wasmvmtypes.CosmosMsg{ - { + Messages: []wasmvmtypes.SubMsg{ + {Msg: wasmvmtypes.CosmosMsg{ IBC: &wasmvmtypes.IBCMsg{ SendPacket: &wasmvmtypes.SendPacketMsg{ ChannelID: start.ChannelID, @@ -178,12 +153,14 @@ func (p *player) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmt }, }, }, + ReplyOn: wasmvmtypes.ReplyNever, + }, }, }, 0, nil } // OnIBCChannelOpen ensures to accept only configured version -func (p player) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (uint64, error) { +func (p player) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (uint64, error) { if channel.Version != p.actor { return 0, nil } @@ -191,7 +168,7 @@ func (p player) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, chan } // OnIBCChannelConnect persists connection endpoints -func (p player) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (p player) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { p.storeEndpoint(store, channel) return &wasmvmtypes.IBCBasicResponse{}, 0, nil } @@ -232,7 +209,7 @@ func (p player) storeEndpoint(store wasmvm.KVStore, channel wasmvmtypes.IBCChann store.Set(ibcEndpointsKey, bz) } -func (p player) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (p player) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { panic("implement me") } @@ -245,7 +222,7 @@ var ( // store keys ) // IBCPacketReceive receives the hit and serves a response hit via `wasmvmtypes.IBCPacket` -func (p player) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { +func (p player) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { // parse received data and store var receivedBall hit if err := json.Unmarshal(packet.Data, &receivedBall); err != nil { @@ -281,12 +258,12 @@ func (p player) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, pa return &wasmvmtypes.IBCReceiveResponse{ Acknowledgement: receivedBall.BuildAck().GetBytes(), - Messages: []wasmvmtypes.CosmosMsg{{IBC: respHit}}, + Messages: []wasmvmtypes.SubMsg{{Msg: wasmvmtypes.CosmosMsg{IBC: respHit}, ReplyOn: wasmvmtypes.ReplyNever}}, }, 0, nil } // OnIBCPacketAcknowledgement handles the packet acknowledgment frame. Stops the game on an any error -func (p player) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, packetAck wasmvmtypes.IBCAcknowledgement, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (p player) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, packetAck wasmvmtypes.IBCAcknowledgementWithPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { // parse received data and store var sentBall hit if err := json.Unmarshal(packetAck.OriginalPacket.Data, &sentBall); err != nil { @@ -294,7 +271,7 @@ func (p player) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet } var ack hitAcknowledgement - if err := json.Unmarshal(packetAck.Acknowledgement, &ack); err != nil { + if err := json.Unmarshal(packetAck.Acknowledgement.Data, &ack); err != nil { return nil, 0, err } if ack.Success != nil { @@ -309,7 +286,7 @@ func (p player) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet return &wasmvmtypes.IBCBasicResponse{}, 0, nil } -func (p player) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (p player) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { panic("implement me") } diff --git a/x/wasm/relay_test.go b/x/wasm/relay_test.go index 163551d6f8..0fc07f5050 100644 --- a/x/wasm/relay_test.go +++ b/x/wasm/relay_test.go @@ -302,7 +302,7 @@ type captureCloseContract struct { closeCalled bool } -func (c *captureCloseContract) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (c *captureCloseContract) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { c.closeCalled = true return &wasmvmtypes.IBCBasicResponse{}, 1, nil } @@ -315,7 +315,7 @@ type sendViaIBCTransferContract struct { t *testing.T } -func (s *sendViaIBCTransferContract) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { +func (s *sendViaIBCTransferContract) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { var in startTransfer if err := json.Unmarshal(executeMsg, &in); err != nil { return nil, 0, err @@ -332,7 +332,8 @@ func (s *sendViaIBCTransferContract) Execute(code wasmvm.Checksum, env wasmvmtyp }, } - return &wasmvmtypes.Response{Messages: []wasmvmtypes.CosmosMsg{{IBC: ibcMsg}}}, 0, nil + return &wasmvmtypes.Response{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{IBC: ibcMsg}}}}, 0, nil + return &wasmvmtypes.Response{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{IBC: ibcMsg}}}}, 0, nil } var _ wasmtesting.IBCContractCallbacks = &sendEmulatedIBCTransferContract{} @@ -345,7 +346,7 @@ type sendEmulatedIBCTransferContract struct { contractAddr string } -func (s *sendEmulatedIBCTransferContract) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { +func (s *sendEmulatedIBCTransferContract) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { var in startTransfer if err := json.Unmarshal(executeMsg, &in); err != nil { return nil, 0, err @@ -365,10 +366,10 @@ func (s *sendEmulatedIBCTransferContract) Execute(code wasmvm.Checksum, env wasm Timeout: wasmvmtypes.IBCTimeout{Timestamp: in.Timeout}, }, } - return &wasmvmtypes.Response{Messages: []wasmvmtypes.CosmosMsg{{IBC: ibcMsg}}}, 0, nil + return &wasmvmtypes.Response{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{IBC: ibcMsg}}}}, 0, nil } -func (c *sendEmulatedIBCTransferContract) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (c *sendEmulatedIBCTransferContract) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { var data ibctransfertypes.FungibleTokenPacketData if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packet.Data, &data); err != nil { return nil, 0, err @@ -380,7 +381,7 @@ func (c *sendEmulatedIBCTransferContract) IBCPacketTimeout(codeID wasmvm.Checksu Amount: wasmvmtypes.Coins{wasmvmtypes.NewCoin(data.Amount, data.Denom)}, }} - return &wasmvmtypes.IBCBasicResponse{Messages: []wasmvmtypes.CosmosMsg{{Bank: returnTokens}}}, 0, nil + return &wasmvmtypes.IBCBasicResponse{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{Bank: returnTokens}}}}, 0, nil } // custom contract execute payload @@ -410,7 +411,7 @@ type receiverContract struct { chain *ibctesting.TestChain } -func (c *receiverContract) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { +func (c *receiverContract) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { var src ibctransfertypes.FungibleTokenPacketData if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packet.Data, &src); err != nil { return nil, 0, err @@ -428,7 +429,7 @@ func (c *receiverContract) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmty return &wasmvmtypes.IBCReceiveResponse{Acknowledgement: ack, Attributes: log}, 0, nil } -func (c *receiverContract) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, packetAck wasmvmtypes.IBCAcknowledgement, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (c *receiverContract) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, packetAck wasmvmtypes.IBCAcknowledgementWithPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { var data ibctransfertypes.FungibleTokenPacketData if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packetAck.OriginalPacket.Data, &data); err != nil { return nil, 0, err @@ -436,7 +437,7 @@ func (c *receiverContract) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes. // call original ibctransfer keeper to not copy all code into this var ack channeltypes.Acknowledgement - if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packetAck.Acknowledgement, &ack); err != nil { + if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packetAck.Acknowledgement.Data, &ack); err != nil { return nil, 0, err } @@ -454,27 +455,27 @@ func (c *receiverContract) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes. // simple helper struct that implements connection setup methods. type contractStub struct{} -func (s *contractStub) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (uint64, error) { +func (s *contractStub) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (uint64, error) { return 0, nil } -func (s *contractStub) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (s *contractStub) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { return &wasmvmtypes.IBCBasicResponse{}, 0, nil } -func (s *contractStub) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (s *contractStub) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { panic("implement me") } -func (s *contractStub) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { +func (s *contractStub) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { panic("implement me") } -func (s *contractStub) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCAcknowledgement, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (s *contractStub) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCAcknowledgementWithPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { return &wasmvmtypes.IBCBasicResponse{}, 0, nil } -func (s *contractStub) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (s *contractStub) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { panic("implement me") } diff --git a/x/wasm/types/events.go b/x/wasm/types/events.go index 4f7e44b4d1..7fd40910c4 100644 --- a/x/wasm/types/events.go +++ b/x/wasm/types/events.go @@ -1,9 +1,12 @@ package types const ( - CustomEventType = "wasm" - EventTypePinCode = "pin_code" - EventTypeUnpinCode = "unpin_code" + // WasmModuleEventType is stored with any contract TX + WasmModuleEventType = "wasm" + // CustomContractEventPrefix contracts can create custom events. To not mix them with other system events they got the `wasm-` prefix. + CustomContractEventPrefix = "wasm-" + EventTypePinCode = "pin_code" + EventTypeUnpinCode = "unpin_code" ) const ( // event attributes AttributeKeyContractAddr = "contract_address" diff --git a/x/wasm/types/exported_keepers.go b/x/wasm/types/exported_keepers.go index 15e0936797..5c3f76a418 100644 --- a/x/wasm/types/exported_keepers.go +++ b/x/wasm/types/exported_keepers.go @@ -1,7 +1,7 @@ package types import ( - types2 "github.com/CosmWasm/wasmvm/types" + wasmvmtypes "github.com/CosmWasm/wasmvm/types" "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" @@ -58,32 +58,32 @@ type IBCContractKeeper interface { OnOpenChannel( ctx sdk.Context, contractAddr sdk.AccAddress, - channel types2.IBCChannel, + channel wasmvmtypes.IBCChannel, ) error OnConnectChannel( ctx sdk.Context, contractAddr sdk.AccAddress, - channel types2.IBCChannel, + channel wasmvmtypes.IBCChannel, ) error OnCloseChannel( ctx sdk.Context, contractAddr sdk.AccAddress, - channel types2.IBCChannel, + channel wasmvmtypes.IBCChannel, ) error OnRecvPacket( ctx sdk.Context, contractAddr sdk.AccAddress, - packet types2.IBCPacket, + packet wasmvmtypes.IBCPacket, ) ([]byte, error) OnAckPacket( ctx sdk.Context, contractAddr sdk.AccAddress, - acknowledgement types2.IBCAcknowledgement, + acknowledgement wasmvmtypes.IBCAcknowledgementWithPacket, ) error OnTimeoutPacket( ctx sdk.Context, contractAddr sdk.AccAddress, - packet types2.IBCPacket, + packet wasmvmtypes.IBCPacket, ) error // ClaimCapability allows the transfer module to claim a capability //that IBC module passes to it diff --git a/x/wasm/types/types.go b/x/wasm/types/types.go index bedd78f7ea..2e706368ac 100644 --- a/x/wasm/types/types.go +++ b/x/wasm/types/types.go @@ -297,23 +297,6 @@ func NewWasmCoins(cosmosCoins sdk.Coins) (wasmCoins []wasmvmtypes.Coin) { return wasmCoins } -// ParseEvents converts wasm LogAttributes into an sdk.Events. Returns events and number of bytes for custom attributes -func ParseEvents(wasmOutputAttrs []wasmvmtypes.EventAttribute, contractAddr sdk.AccAddress) sdk.Events { - // we always tag with the contract address issuing this event - attrs := []sdk.Attribute{sdk.NewAttribute(AttributeKeyContractAddr, contractAddr.String())} - // append attributes from wasm to the sdk.Event - for _, l := range wasmOutputAttrs { - // and reserve the contract_address key for our use (not contract) - if l.Key != AttributeKeyContractAddr { - attr := sdk.NewAttribute(l.Key, l.Value) - attrs = append(attrs, attr) - } - } - - // each wasm invokation always returns one sdk.Event - return sdk.Events{sdk.NewEvent(CustomEventType, attrs...)} -} - // WasmConfig is the extra config required for wasm type WasmConfig struct { SmartQueryGasLimit uint64 diff --git a/x/wasm/types/wasmer_engine.go b/x/wasm/types/wasmer_engine.go index 7a7d08f72e..676d3d4720 100644 --- a/x/wasm/types/wasmer_engine.go +++ b/x/wasm/types/wasmer_engine.go @@ -31,7 +31,7 @@ type WasmerEngine interface { // Under the hood, we may recompile the wasm, use a cached native compile, or even use a cached instance // for performance. Instantiate( - code wasmvm.Checksum, + checksum wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, @@ -40,6 +40,7 @@ type WasmerEngine interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.Response, uint64, error) // Execute calls a given contract. Since the only difference between contracts with the same CodeID is the @@ -58,6 +59,7 @@ type WasmerEngine interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.Response, uint64, error) // Query allows a client to execute a contract-specific query. If the result is not empty, it should be @@ -72,6 +74,7 @@ type WasmerEngine interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) ([]byte, uint64, error) // Migrate will migrate an existing contract to a new code binary. @@ -81,7 +84,7 @@ type WasmerEngine interface { // // MigrateMsg has some data on how to perform the migration. Migrate( - codeID wasmvm.Checksum, + checksum wasmvm.Checksum, env wasmvmtypes.Env, migrateMsg []byte, store wasmvm.KVStore, @@ -89,6 +92,7 @@ type WasmerEngine interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.Response, uint64, error) // Sudo runs an existing contract in read/write mode (like Execute), but is never exposed to external callers @@ -97,7 +101,7 @@ type WasmerEngine interface { // This allows a contract to expose custom "super user" functions or priviledged operations that can be // deeply integrated with native modules. Sudo( - codeID wasmvm.Checksum, + checksum wasmvm.Checksum, env wasmvmtypes.Env, sudoMsg []byte, store wasmvm.KVStore, @@ -105,11 +109,12 @@ type WasmerEngine interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.Response, uint64, error) // Reply is called on the original dispatching contract after running a submessage Reply( - codeID wasmvm.Checksum, + checksum wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, @@ -117,6 +122,7 @@ type WasmerEngine interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.Response, uint64, error) // GetCode will load the original wasm code for the given code id. @@ -134,7 +140,7 @@ type WasmerEngine interface { // IBCChannelOpen is available on IBC-enabled contracts and is a hook to call into // during the handshake pahse IBCChannelOpen( - codeID wasmvm.Checksum, + checksum wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, @@ -142,12 +148,13 @@ type WasmerEngine interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (uint64, error) // IBCChannelConnect is available on IBC-enabled contracts and is a hook to call into // during the handshake pahse IBCChannelConnect( - codeID wasmvm.Checksum, + checksum wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, @@ -155,12 +162,13 @@ type WasmerEngine interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.IBCBasicResponse, uint64, error) // IBCChannelClose is available on IBC-enabled contracts and is a hook to call into // at the end of the channel lifetime IBCChannelClose( - codeID wasmvm.Checksum, + checksum wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, @@ -168,12 +176,13 @@ type WasmerEngine interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.IBCBasicResponse, uint64, error) // IBCPacketReceive is available on IBC-enabled contracts and is called when an incoming // packet is received on a channel belonging to this contract IBCPacketReceive( - codeID wasmvm.Checksum, + checksum wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, @@ -181,26 +190,29 @@ type WasmerEngine interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.IBCReceiveResponse, uint64, error) + // IBCPacketAck is available on IBC-enabled contracts and is called when an // the response for an outgoing packet (previously sent by this contract) // is received IBCPacketAck( - codeID wasmvm.Checksum, + checksum wasmvm.Checksum, env wasmvmtypes.Env, - ack wasmvmtypes.IBCAcknowledgement, + ack wasmvmtypes.IBCAcknowledgementWithPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.IBCBasicResponse, uint64, error) // IBCPacketTimeout is available on IBC-enabled contracts and is called when an // outgoing packet (previously sent by this contract) will provably never be executed. // Usually handled like ack returning an error IBCPacketTimeout( - codeID wasmvm.Checksum, + checksum wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, @@ -208,6 +220,7 @@ type WasmerEngine interface { querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, + deserCost wasmvmtypes.UFraction, ) (*wasmvmtypes.IBCBasicResponse, uint64, error) // Pin pins a code to an in-memory cache, such that is