Merge pull request #487 from CosmWasm/wasmvm-0.14.0-beta3
Upgrade to Wasmvm 0.14.0 beta3
This commit is contained in:
@@ -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-beta1/libwasmvm_muslc.a /lib/libwasmvm_muslc.a
|
||||
RUN sha256sum /lib/libwasmvm_muslc.a | grep b69cf9ffbdfb2f1bd1e6f730ecee1eb0d06a1473840a24709aec7a7df5907d45
|
||||
ADD https://github.com/CosmWasm/wasmvm/releases/download/v0.14.0-beta3/libwasmvm_muslc.a /lib/libwasmvm_muslc.a
|
||||
RUN sha256sum /lib/libwasmvm_muslc.a | grep adea8f977601daa8daa9885e02b31ca6dd0ab6d4dbbd8ba2ccfa447ffebda37c
|
||||
|
||||
# force it to use static lib (from above) not standard libgo_cosmwasm.so file
|
||||
RUN LEDGER_ENABLED=false BUILD_TAGS=muslc make build
|
||||
|
||||
@@ -181,6 +181,7 @@ var (
|
||||
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
|
||||
govtypes.ModuleName: {authtypes.Burner},
|
||||
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
|
||||
wasm.ModuleName: {authtypes.Burner},
|
||||
}
|
||||
|
||||
// module accounts that are allowed to receive tokens
|
||||
|
||||
2
go.mod
2
go.mod
@@ -3,7 +3,7 @@ module github.com/CosmWasm/wasmd
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/CosmWasm/wasmvm v0.14.0-beta1
|
||||
github.com/CosmWasm/wasmvm v0.14.0-beta3
|
||||
github.com/cosmos/cosmos-sdk v0.42.4
|
||||
github.com/cosmos/iavl v0.15.3
|
||||
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b
|
||||
|
||||
8
go.sum
8
go.sum
@@ -17,8 +17,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-beta1 h1:ASqXB/2D8CEBmAI/uljRw6eEMbeKXPQtL/wZzKXZGGA=
|
||||
github.com/CosmWasm/wasmvm v0.14.0-beta1/go.mod h1:Id107qllDJyJjVQQsKMOy2YYF98sqPJ2t+jX1QES40A=
|
||||
github.com/CosmWasm/wasmvm v0.14.0-beta3 h1:HN1+HrC2kgO/V4voGdOWrN1sdUoTnSoLuSrBXbDVnbY=
|
||||
github.com/CosmWasm/wasmvm v0.14.0-beta3/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=
|
||||
@@ -101,8 +101,6 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cosmos/cosmos-sdk v0.42.3 h1:VFYq7spDBBIlygAxwcI79Xh2JuIrG1ZCPKpvqKghIZs=
|
||||
github.com/cosmos/cosmos-sdk v0.42.3/go.mod h1:xiLp1G8mumj82S5KLJGCAyeAlD+7VNomg/aRSJV12yk=
|
||||
github.com/cosmos/cosmos-sdk v0.42.4 h1:yaD4PyOx0LnyfiWasC5egg1U76lT83GRxjJjupPo7Gk=
|
||||
github.com/cosmos/cosmos-sdk v0.42.4/go.mod h1:I1Zw1zmU4rA/NITaakTb71pXQnQrWyFBhqo3WSeg0vA=
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
|
||||
@@ -570,8 +568,6 @@ github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM
|
||||
github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4=
|
||||
github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg=
|
||||
github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ=
|
||||
github.com/tendermint/tendermint v0.34.8 h1:PMWgUx47FrNTsfhxCWzoiIlVAC1SE9+WBlnsF9oQW0I=
|
||||
github.com/tendermint/tendermint v0.34.8/go.mod h1:JVuu3V1ZexOaZG8VJMRl8lnfrGw6hEB2TVnoUwKRbss=
|
||||
github.com/tendermint/tendermint v0.34.9 h1:9P2MXDEPOcPW0NBcHQ/HDSfvczZm+q5nUUw7AZ6f1Vc=
|
||||
github.com/tendermint/tendermint v0.34.9/go.mod h1:kl4Z1JwGx1I+u1SXIzMDy7Z3T8LiMeCAOnzNn6AIMT4=
|
||||
github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4=
|
||||
|
||||
@@ -68,9 +68,9 @@ func TestInitGenesis(t *testing.T) {
|
||||
assertContractList(t, q, data.ctx, 1, []string{contractBech32Addr})
|
||||
assertContractInfo(t, q, data.ctx, contractBech32Addr, 1, creator)
|
||||
assertContractState(t, q, data.ctx, contractBech32Addr, state{
|
||||
Verifier: []byte(fred),
|
||||
Beneficiary: []byte(bob),
|
||||
Funder: []byte(creator),
|
||||
Verifier: fred.String(),
|
||||
Beneficiary: bob.String(),
|
||||
Funder: creator.String(),
|
||||
})
|
||||
|
||||
// export into genstate
|
||||
@@ -90,8 +90,8 @@ func TestInitGenesis(t *testing.T) {
|
||||
assertContractList(t, q2, newData.ctx, 1, []string{contractBech32Addr})
|
||||
assertContractInfo(t, q2, newData.ctx, contractBech32Addr, 1, creator)
|
||||
assertContractState(t, q2, newData.ctx, contractBech32Addr, state{
|
||||
Verifier: []byte(fred),
|
||||
Beneficiary: []byte(bob),
|
||||
Funder: []byte(creator),
|
||||
Verifier: fred.String(),
|
||||
Beneficiary: bob.String(),
|
||||
Funder: creator.String(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,7 +24,15 @@ type SDKMessageHandler struct {
|
||||
encoders msgEncoder
|
||||
}
|
||||
|
||||
func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, unpacker codectypes.AnyUnpacker, portSource types.ICS20TransferPortSource, customEncoders ...*MessageEncoders) Messenger {
|
||||
func NewDefaultMessageHandler(
|
||||
router sdk.Router,
|
||||
channelKeeper types.ChannelKeeper,
|
||||
capabilityKeeper types.CapabilityKeeper,
|
||||
bankKeeper types.Burner,
|
||||
unpacker codectypes.AnyUnpacker,
|
||||
portSource types.ICS20TransferPortSource,
|
||||
customEncoders ...*MessageEncoders,
|
||||
) Messenger {
|
||||
encoders := DefaultEncoders(unpacker, portSource)
|
||||
for _, e := range customEncoders {
|
||||
encoders = encoders.Merge(e)
|
||||
@@ -32,6 +40,7 @@ func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeep
|
||||
return NewMessageHandlerChain(
|
||||
NewSDKMessageHandler(router, encoders),
|
||||
NewIBCRawPacketHandler(channelKeeper, capabilityKeeper),
|
||||
NewBurnCoinMessageHandler(bankKeeper),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -168,3 +177,33 @@ func (h IBCRawPacketHandler) DispatchMsg(ctx sdk.Context, _ sdk.AccAddress, cont
|
||||
)
|
||||
return nil, nil, h.channelKeeper.SendPacket(ctx, channelCap, packet)
|
||||
}
|
||||
|
||||
var _ Messenger = MessageHandlerFunc(nil)
|
||||
|
||||
// MessageHandlerFunc is a helper to construct simple function based message handler
|
||||
type MessageHandlerFunc func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error)
|
||||
|
||||
func (m MessageHandlerFunc) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) {
|
||||
return m(ctx, contractAddr, contractIBCPortID, msg)
|
||||
}
|
||||
|
||||
// NewBurnCoinMessageHandler handles wasmvm.BurnMsg messages
|
||||
func NewBurnCoinMessageHandler(burner types.Burner) MessageHandlerFunc {
|
||||
return func(ctx sdk.Context, contractAddr sdk.AccAddress, _ string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) {
|
||||
if msg.Bank != nil && msg.Bank.Burn != nil {
|
||||
coins, err := convertWasmCoinsToSdkCoins(msg.Bank.Burn.Amount)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := burner.SendCoinsFromAccountToModule(ctx, contractAddr, types.ModuleName, coins); err != nil {
|
||||
return nil, nil, sdkerrors.Wrap(err, "transfer to module")
|
||||
}
|
||||
if err := burner.BurnCoins(ctx, types.ModuleName, coins); err != nil {
|
||||
return nil, nil, sdkerrors.Wrap(err, "burn coins")
|
||||
}
|
||||
moduleLogger(ctx).Info("Burned", "amount", coins)
|
||||
return nil, nil, nil
|
||||
}
|
||||
return nil, nil, types.ErrUnknownMsg
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@ import (
|
||||
"encoding/json"
|
||||
"github.com/CosmWasm/wasmd/x/wasm/keeper/wasmtesting"
|
||||
"github.com/CosmWasm/wasmd/x/wasm/types"
|
||||
wasmvm "github.com/CosmWasm/wasmvm"
|
||||
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
|
||||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"
|
||||
@@ -306,3 +308,87 @@ func TestIBCRawPacketHandler(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBurnCoinMessageHandlerIntegration(t *testing.T) {
|
||||
// testing via full keeper setup so that we are confident the
|
||||
// module permissions are set correct and no other handler
|
||||
// picks the message in the default handler chain
|
||||
ctx, keepers := CreateDefaultTestInput(t)
|
||||
k := keepers.WasmKeeper
|
||||
|
||||
before, err := keepers.BankKeeper.TotalSupply(sdk.WrapSDKContext(ctx), &banktypes.QueryTotalSupplyRequest{})
|
||||
require.NoError(t, err)
|
||||
example := InstantiateHackatomExampleContract(t, ctx, keepers) // with deposit of 100 stake
|
||||
|
||||
specs := map[string]struct {
|
||||
msg wasmvmtypes.BurnMsg
|
||||
expErr bool
|
||||
}{
|
||||
"all good": {
|
||||
msg: wasmvmtypes.BurnMsg{
|
||||
Amount: wasmvmtypes.Coins{{
|
||||
Denom: "denom",
|
||||
Amount: "100",
|
||||
}},
|
||||
},
|
||||
},
|
||||
"not enough funds in contract": {
|
||||
msg: wasmvmtypes.BurnMsg{
|
||||
Amount: wasmvmtypes.Coins{{
|
||||
Denom: "denom",
|
||||
Amount: "101",
|
||||
}},
|
||||
},
|
||||
expErr: true,
|
||||
},
|
||||
"zero amount rejected": {
|
||||
msg: wasmvmtypes.BurnMsg{
|
||||
Amount: wasmvmtypes.Coins{{
|
||||
Denom: "denom",
|
||||
Amount: "0",
|
||||
}},
|
||||
},
|
||||
expErr: true,
|
||||
},
|
||||
"unknown denom - insufficient funds": {
|
||||
msg: wasmvmtypes.BurnMsg{
|
||||
Amount: wasmvmtypes.Coins{{
|
||||
Denom: "unknown",
|
||||
Amount: "1",
|
||||
}},
|
||||
},
|
||||
expErr: true,
|
||||
},
|
||||
}
|
||||
parentCtx := ctx
|
||||
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}},
|
||||
},
|
||||
}, 0, nil
|
||||
}}
|
||||
|
||||
// when
|
||||
_, err = k.execute(ctx, example.Contract, example.CreatorAddr, nil, nil)
|
||||
|
||||
// then
|
||||
if spec.expErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
// and total supply reduced by burned amount
|
||||
after, err := keepers.BankKeeper.TotalSupply(sdk.WrapSDKContext(ctx), &banktypes.QueryTotalSupplyRequest{})
|
||||
require.NoError(t, err)
|
||||
diff := before.Supply.Sub(after.Supply)
|
||||
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(100))), diff)
|
||||
})
|
||||
}
|
||||
|
||||
// test cases:
|
||||
// not enough money to burn
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func NewKeeper(
|
||||
bank: NewBankCoinTransferrer(bankKeeper),
|
||||
portKeeper: portKeeper,
|
||||
capabilityKeeper: capabilityKeeper,
|
||||
messenger: NewDefaultMessageHandler(router, channelKeeper, capabilityKeeper, cdc, portSource),
|
||||
messenger: NewDefaultMessageHandler(router, channelKeeper, capabilityKeeper, bankKeeper, cdc, portSource),
|
||||
queryGasLimit: wasmConfig.SmartQueryGasLimit,
|
||||
paramSpace: paramSpace,
|
||||
}
|
||||
@@ -831,6 +831,15 @@ func (k Keeper) dispatchSubmessages(ctx sdk.Context, contractAddr sdk.AccAddress
|
||||
}
|
||||
// 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 {
|
||||
return err
|
||||
}
|
||||
if msg.ReplyOn == wasmvmtypes.ReplyError && err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// otherwise, we create a SubcallResult and pass it into the calling contract
|
||||
var result wasmvmtypes.SubcallResult
|
||||
if err == nil {
|
||||
// just take the first one for now if there are multiple sub-sdk messages
|
||||
|
||||
@@ -283,7 +283,7 @@ func TestInstantiate(t *testing.T) {
|
||||
|
||||
gasAfter := ctx.GasMeter().GasConsumed()
|
||||
if types.EnableGasVerification {
|
||||
require.Equal(t, uint64(0x11ca8), gasAfter-gasBefore)
|
||||
require.Equal(t, uint64(0x1229f), gasAfter-gasBefore)
|
||||
}
|
||||
|
||||
// ensure it is stored properly
|
||||
@@ -516,7 +516,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(0x12963), gasAfter-gasBefore)
|
||||
require.Equal(t, uint64(0x12916), gasAfter-gasBefore)
|
||||
}
|
||||
// ensure bob now exists and got both payments released
|
||||
bobAcct = accKeeper.GetAccount(ctx, bob)
|
||||
@@ -933,11 +933,11 @@ func TestMigrate(t *testing.T) {
|
||||
|
||||
// and verify contract state
|
||||
raw := keepers.WasmKeeper.QueryRaw(ctx, contractAddr, []byte("config"))
|
||||
var stored map[string][]byte
|
||||
var stored map[string]string
|
||||
require.NoError(t, json.Unmarshal(raw, &stored))
|
||||
require.Contains(t, stored, "verifier")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, spec.expVerifier, sdk.AccAddress(stored["verifier"]))
|
||||
assert.Equal(t, spec.expVerifier.String(), stored["verifier"])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,12 +57,12 @@ func initRecurseContract(t *testing.T) (contract sdk.AccAddress, creator sdk.Acc
|
||||
|
||||
func TestGasCostOnQuery(t *testing.T) {
|
||||
const (
|
||||
GasNoWork uint64 = 44_074
|
||||
GasNoWork uint64 = 44_072
|
||||
// Note: about 100 SDK gas (10k wasmer gas) for each round of sha256
|
||||
GasWork50 uint64 = 49_744 // this is a little shy of 50k gas - to keep an eye on the limit
|
||||
GasWork50 uint64 = 49_763 // this is a little shy of 50k gas - to keep an eye on the limit
|
||||
|
||||
GasReturnUnhashed uint64 = 287
|
||||
GasReturnHashed uint64 = 262
|
||||
GasReturnUnhashed uint64 = 283
|
||||
GasReturnHashed uint64 = 258
|
||||
)
|
||||
|
||||
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 = 272_797 // = InstanceCost + x // we have 6x gas used in cpu than in the instance
|
||||
GasWork2k uint64 = 273_566 // = InstanceCost + x // we have 6x gas used in cpu than in the instance
|
||||
// This is overhead for calling into a sub-contract
|
||||
GasReturnHashed uint64 = 265
|
||||
GasReturnHashed uint64 = 262
|
||||
)
|
||||
|
||||
cases := map[string]struct {
|
||||
|
||||
@@ -381,7 +381,7 @@ func TestReflectStargateQuery(t *testing.T) {
|
||||
}
|
||||
|
||||
type reflectState struct {
|
||||
Owner []byte `json:"owner"`
|
||||
Owner string `json:"owner"`
|
||||
}
|
||||
|
||||
func TestMaskReflectWasmQueries(t *testing.T) {
|
||||
@@ -418,7 +418,7 @@ func TestMaskReflectWasmQueries(t *testing.T) {
|
||||
raw := keeper.QueryRaw(ctx, reflectAddr, configKey)
|
||||
var stateRes reflectState
|
||||
mustParse(t, raw, &stateRes)
|
||||
require.Equal(t, stateRes.Owner, []byte(creator))
|
||||
require.Equal(t, stateRes.Owner, creator.String())
|
||||
|
||||
// now, let's reflect a smart query into the x/wasm handlers and see if we get the same result
|
||||
reflectOwnerQuery := ReflectQueryMsg{Chain: &ChainQuery{Request: &wasmvmtypes.QueryRequest{Wasm: &wasmvmtypes.WasmQuery{
|
||||
@@ -453,7 +453,7 @@ func TestMaskReflectWasmQueries(t *testing.T) {
|
||||
// now, with the raw data, we can parse it into state
|
||||
var reflectStateRes reflectState
|
||||
mustParse(t, reflectRawRes.Data, &reflectStateRes)
|
||||
require.Equal(t, reflectStateRes.Owner, []byte(creator))
|
||||
require.Equal(t, reflectStateRes.Owner, creator.String())
|
||||
}
|
||||
|
||||
func TestWasmRawQueryWithNil(t *testing.T) {
|
||||
|
||||
@@ -59,8 +59,9 @@ func TestDispatchSubMsgSuccessCase(t *testing.T) {
|
||||
reflectSend := ReflectHandleMsg{
|
||||
ReflectSubCall: &reflectSubPayload{
|
||||
Msgs: []wasmvmtypes.SubMsg{{
|
||||
ID: 7,
|
||||
Msg: msg,
|
||||
ID: 7,
|
||||
Msg: msg,
|
||||
ReplyOn: wasmvmtypes.ReplyAlways,
|
||||
}},
|
||||
},
|
||||
}
|
||||
@@ -322,6 +323,7 @@ func TestDispatchSubMsgErrorHandling(t *testing.T) {
|
||||
ID: tc.submsgID,
|
||||
Msg: msg,
|
||||
GasLimit: tc.gasLimit,
|
||||
ReplyOn: wasmvmtypes.ReplyAlways,
|
||||
}},
|
||||
},
|
||||
}
|
||||
@@ -421,8 +423,9 @@ func TestDispatchSubMsgEncodeToNoSdkMsg(t *testing.T) {
|
||||
reflectSend := ReflectHandleMsg{
|
||||
ReflectSubCall: &reflectSubPayload{
|
||||
Msgs: []wasmvmtypes.SubMsg{{
|
||||
ID: 7,
|
||||
Msg: msg,
|
||||
ID: 7,
|
||||
Msg: msg,
|
||||
ReplyOn: wasmvmtypes.ReplyAlways,
|
||||
}},
|
||||
},
|
||||
}
|
||||
@@ -450,3 +453,132 @@ func TestDispatchSubMsgEncodeToNoSdkMsg(t *testing.T) {
|
||||
assert.Empty(t, sub.Data)
|
||||
require.Len(t, sub.Events, 0)
|
||||
}
|
||||
|
||||
// Try a simple send, no gas limit to for a sanity check before trying table tests
|
||||
func TestDispatchSubMsgConditionalReplyOn(t *testing.T) {
|
||||
ctx, keepers := CreateTestInput(t, false, ReflectFeatures)
|
||||
accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.WasmKeeper, keepers.BankKeeper
|
||||
|
||||
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
|
||||
contractStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 40000))
|
||||
|
||||
creator := createFakeFundedAccount(t, ctx, accKeeper, bankKeeper, deposit)
|
||||
_, _, fred := keyPubAddr()
|
||||
|
||||
// upload code
|
||||
reflectCode, err := ioutil.ReadFile("./testdata/reflect.wasm")
|
||||
require.NoError(t, err)
|
||||
codeID, err := keepers.ContractKeeper.Create(ctx, creator, reflectCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// creator instantiates a contract and gives it tokens
|
||||
contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, codeID, creator, nil, []byte("{}"), "reflect contract 1", contractStart)
|
||||
require.NoError(t, err)
|
||||
|
||||
goodSend := wasmvmtypes.CosmosMsg{
|
||||
Bank: &wasmvmtypes.BankMsg{
|
||||
Send: &wasmvmtypes.SendMsg{
|
||||
ToAddress: fred.String(),
|
||||
Amount: []wasmvmtypes.Coin{{
|
||||
Denom: "denom",
|
||||
Amount: "1000",
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
failSend := wasmvmtypes.CosmosMsg{
|
||||
Bank: &wasmvmtypes.BankMsg{
|
||||
Send: &wasmvmtypes.SendMsg{
|
||||
ToAddress: fred.String(),
|
||||
Amount: []wasmvmtypes.Coin{{
|
||||
Denom: "no-such-token",
|
||||
Amount: "777777",
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cases := map[string]struct {
|
||||
// true for wasmvmtypes.ReplySuccess, false for wasmvmtypes.ReplyError
|
||||
replyOnSuccess bool
|
||||
msg wasmvmtypes.CosmosMsg
|
||||
// true if the call should return an error (it wasn't handled)
|
||||
expectError bool
|
||||
// true if the reflect contract wrote the response (success or error) - it was captured
|
||||
writeResult bool
|
||||
}{
|
||||
"all good, reply success": {
|
||||
replyOnSuccess: true,
|
||||
msg: goodSend,
|
||||
expectError: false,
|
||||
writeResult: true,
|
||||
},
|
||||
"all good, reply error": {
|
||||
replyOnSuccess: false,
|
||||
msg: goodSend,
|
||||
expectError: false,
|
||||
writeResult: false,
|
||||
},
|
||||
"bad msg, reply success": {
|
||||
replyOnSuccess: true,
|
||||
msg: failSend,
|
||||
expectError: true,
|
||||
writeResult: false,
|
||||
},
|
||||
"bad msg, reply error": {
|
||||
replyOnSuccess: false,
|
||||
msg: failSend,
|
||||
expectError: false,
|
||||
writeResult: true,
|
||||
},
|
||||
}
|
||||
|
||||
var id uint64 = 0
|
||||
for name, tc := range cases {
|
||||
id++
|
||||
t.Run(name, func(t *testing.T) {
|
||||
subMsg := wasmvmtypes.SubMsg{
|
||||
ID: id,
|
||||
Msg: tc.msg,
|
||||
ReplyOn: wasmvmtypes.ReplySuccess,
|
||||
}
|
||||
if !tc.replyOnSuccess {
|
||||
subMsg.ReplyOn = wasmvmtypes.ReplyError
|
||||
}
|
||||
|
||||
reflectSend := ReflectHandleMsg{
|
||||
ReflectSubCall: &reflectSubPayload{
|
||||
Msgs: []wasmvmtypes.SubMsg{subMsg},
|
||||
},
|
||||
}
|
||||
reflectSendBz, err := json.Marshal(reflectSend)
|
||||
require.NoError(t, err)
|
||||
_, err = keepers.ContractKeeper.Execute(ctx, contractAddr, creator, reflectSendBz, nil)
|
||||
|
||||
if tc.expectError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// query the reflect state to check if the result was stored
|
||||
query := ReflectQueryMsg{
|
||||
SubCallResult: &SubCall{ID: id},
|
||||
}
|
||||
queryBz, err := json.Marshal(query)
|
||||
require.NoError(t, err)
|
||||
queryRes, err := keeper.QuerySmart(ctx, contractAddr, queryBz)
|
||||
if tc.writeResult {
|
||||
// we got some data for this call
|
||||
require.NoError(t, err)
|
||||
var res wasmvmtypes.Reply
|
||||
err = json.Unmarshal(queryRes, &res)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, id, res.ID)
|
||||
} else {
|
||||
// nothing should be there -> error
|
||||
require.Error(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +213,7 @@ func createTestInput(
|
||||
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
|
||||
govtypes.ModuleName: {authtypes.Burner},
|
||||
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
|
||||
types.ModuleName: {authtypes.Burner},
|
||||
}
|
||||
authSubsp, _ := paramsKeeper.GetSubspace(authtypes.ModuleName)
|
||||
authKeeper := authkeeper.NewAccountKeeper(
|
||||
@@ -237,9 +238,10 @@ func createTestInput(
|
||||
blockedAddrs,
|
||||
)
|
||||
bankParams := banktypes.DefaultParams()
|
||||
bankParams = bankParams.SetSendEnabledParam("stake", true)
|
||||
bankKeeper.SetParams(ctx, bankParams)
|
||||
|
||||
bankKeeper.SetSupply(ctx, banktypes.NewSupply(sdk.NewCoins(
|
||||
sdk.NewCoin("denom", sdk.NewInt(10000)),
|
||||
)))
|
||||
stakingSubsp, _ := paramsKeeper.GetSubspace(stakingtypes.ModuleName)
|
||||
stakingKeeper := stakingkeeper.NewKeeper(appCodec, keyStaking, authKeeper, bankKeeper, stakingSubsp)
|
||||
stakingKeeper.SetParams(ctx, TestingStakeParams)
|
||||
|
||||
BIN
x/wasm/keeper/testdata/burner.wasm
vendored
BIN
x/wasm/keeper/testdata/burner.wasm
vendored
Binary file not shown.
BIN
x/wasm/keeper/testdata/hackatom.wasm
vendored
BIN
x/wasm/keeper/testdata/hackatom.wasm
vendored
Binary file not shown.
BIN
x/wasm/keeper/testdata/hackatom.wasm.gzip
vendored
BIN
x/wasm/keeper/testdata/hackatom.wasm.gzip
vendored
Binary file not shown.
BIN
x/wasm/keeper/testdata/ibc_reflect.wasm
vendored
BIN
x/wasm/keeper/testdata/ibc_reflect.wasm
vendored
Binary file not shown.
BIN
x/wasm/keeper/testdata/ibc_reflect_send.wasm
vendored
BIN
x/wasm/keeper/testdata/ibc_reflect_send.wasm
vendored
Binary file not shown.
BIN
x/wasm/keeper/testdata/reflect.wasm
vendored
BIN
x/wasm/keeper/testdata/reflect.wasm
vendored
Binary file not shown.
BIN
x/wasm/keeper/testdata/staking.wasm
vendored
BIN
x/wasm/keeper/testdata/staking.wasm
vendored
Binary file not shown.
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/CosmWasm/wasmd/x/wasm/keeper"
|
||||
"github.com/CosmWasm/wasmd/x/wasm/types"
|
||||
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
@@ -135,9 +134,9 @@ type initMsg struct {
|
||||
}
|
||||
|
||||
type state struct {
|
||||
Verifier wasmvmtypes.CanonicalAddress `json:"verifier"`
|
||||
Beneficiary wasmvmtypes.CanonicalAddress `json:"beneficiary"`
|
||||
Funder wasmvmtypes.CanonicalAddress `json:"funder"`
|
||||
Verifier string `json:"verifier"`
|
||||
Beneficiary string `json:"beneficiary"`
|
||||
Funder string `json:"funder"`
|
||||
}
|
||||
|
||||
func TestHandleInstantiate(t *testing.T) {
|
||||
@@ -192,9 +191,9 @@ func TestHandleInstantiate(t *testing.T) {
|
||||
assertContractList(t, q, data.ctx, 1, []string{contractBech32Addr})
|
||||
assertContractInfo(t, q, data.ctx, contractBech32Addr, 1, creator)
|
||||
assertContractState(t, q, data.ctx, contractBech32Addr, state{
|
||||
Verifier: []byte(fred),
|
||||
Beneficiary: []byte(bob),
|
||||
Funder: []byte(creator),
|
||||
Verifier: fred.String(),
|
||||
Beneficiary: bob.String(),
|
||||
Funder: creator.String(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -311,9 +310,9 @@ func TestHandleExecute(t *testing.T) {
|
||||
assertContractList(t, q, data.ctx, 1, []string{contractBech32Addr})
|
||||
assertContractInfo(t, q, data.ctx, contractBech32Addr, 1, creator)
|
||||
assertContractState(t, q, data.ctx, contractBech32Addr, state{
|
||||
Verifier: []byte(fred),
|
||||
Beneficiary: []byte(bob),
|
||||
Funder: []byte(creator),
|
||||
Verifier: fred.String(),
|
||||
Beneficiary: bob.String(),
|
||||
Funder: creator.String(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -12,14 +12,21 @@ import (
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
// BankKeeper defines a subset of methods implemented by the cosmos-sdk bank keeper
|
||||
// BankViewKeeper defines a subset of methods implemented by the cosmos-sdk bank keeper
|
||||
type BankViewKeeper interface {
|
||||
GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
|
||||
}
|
||||
|
||||
// Burner is a subset of the sdk bank keeper methods
|
||||
type Burner interface {
|
||||
BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
|
||||
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
|
||||
}
|
||||
|
||||
// BankKeeper defines a subset of methods implemented by the cosmos-sdk bank keeper
|
||||
type BankKeeper interface {
|
||||
BankViewKeeper
|
||||
Burner
|
||||
SendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
|
||||
BlockedAddr(addr sdk.AccAddress) bool
|
||||
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
|
||||
|
||||
Reference in New Issue
Block a user