Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Wasmvm 0.14.0 beta3 #487

Merged
merged 10 commits into from
Apr 13, 2021
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a reference in the Dockerfile that we need to update. 🕵️

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do that and go mod tidy

github.com/cosmos/cosmos-sdk v0.42.4
github.com/cosmos/iavl v0.15.3
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ
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-beta2 h1:8bLLNaxj796qUwu6UuQDbqpMV9zPpxG3lNZZbswNdOo=
github.com/CosmWasm/wasmvm v0.14.0-beta2/go.mod h1:Id107qllDJyJjVQQsKMOy2YYF98sqPJ2t+jX1QES40A=
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

next go mod tidy run will drop the beta1 +2.

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=
Expand Down
12 changes: 6 additions & 6 deletions x/wasm/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(),
})
}
9 changes: 9 additions & 0 deletions x/wasm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
ethanfrey marked this conversation as resolved.
Show resolved Hide resolved

// 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
Expand Down
8 changes: 4 additions & 4 deletions x/wasm/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(0x129d6), gasAfter-gasBefore)
}
// ensure bob now exists and got both payments released
bobAcct = accKeeper.GetAccount(ctx, bob)
Expand Down Expand Up @@ -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"])
})
}
}
Expand Down
12 changes: 6 additions & 6 deletions x/wasm/keeper/recurse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions x/wasm/keeper/reflect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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{
Expand Down Expand Up @@ -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) {
Expand Down
140 changes: 136 additions & 4 deletions x/wasm/keeper/submsg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}},
},
}
Expand Down Expand Up @@ -322,6 +323,7 @@ func TestDispatchSubMsgErrorHandling(t *testing.T) {
ID: tc.submsgID,
Msg: msg,
GasLimit: tc.gasLimit,
ReplyOn: wasmvmtypes.ReplyAlways,
}},
},
}
Expand Down Expand Up @@ -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,
}},
},
}
Expand Down Expand Up @@ -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 {
ethanfrey marked this conversation as resolved.
Show resolved Hide resolved
// 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice to have: you can avoid the if and increase readability if you replace the replyOnSuccess bool by the replyOn value. But no need to change this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to, but it requires me to use a private type in the struct... hmmmm

I made the type private to keep it a closed enum (there are only 3 public instances of it), rather than allow anyone to create new ReplyOn types.

}

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)
}
})
}
}
Binary file modified x/wasm/keeper/testdata/burner.wasm
Binary file not shown.
Binary file modified x/wasm/keeper/testdata/hackatom.wasm
Binary file not shown.
Binary file modified x/wasm/keeper/testdata/hackatom.wasm.gzip
Binary file not shown.
Binary file modified x/wasm/keeper/testdata/ibc_reflect.wasm
Binary file not shown.
Binary file modified x/wasm/keeper/testdata/ibc_reflect_send.wasm
Binary file not shown.
Binary file modified x/wasm/keeper/testdata/reflect.wasm
Binary file not shown.
Binary file modified x/wasm/keeper/testdata/staking.wasm
Binary file not shown.
19 changes: 9 additions & 10 deletions x/wasm/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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(),
})
}

Expand Down Expand Up @@ -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(),
})
}

Expand Down