Merge pull request #218 from CosmWasm/update-go-cosmwasm
Update go cosmwasm
This commit is contained in:
3
go.mod
3
go.mod
@@ -3,8 +3,7 @@ module github.com/CosmWasm/wasmd
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
// Note: update ENV GO_COSMWASM in Dockerfile when updating this
|
||||
github.com/CosmWasm/go-cosmwasm v0.9.1
|
||||
github.com/CosmWasm/go-cosmwasm v0.10.0-alpha2
|
||||
github.com/cosmos/cosmos-sdk v0.39.0
|
||||
github.com/golang/mock v1.4.3 // indirect
|
||||
github.com/google/gofuzz v1.0.0
|
||||
|
||||
2
go.sum
2
go.sum
@@ -11,6 +11,8 @@ 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/go-cosmwasm v0.9.1 h1:w5s2o7H3cmNexct9yv8F6OLXwgxbdfVApwam7DibPqI=
|
||||
github.com/CosmWasm/go-cosmwasm v0.9.1/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
|
||||
github.com/CosmWasm/go-cosmwasm v0.10.0-alpha2 h1:k069wQF0f24w3A52mjR3AK6AfkuvQ5d0Mdu/rpB5nEk=
|
||||
github.com/CosmWasm/go-cosmwasm v0.10.0-alpha2/go.mod h1:gAFCwllx97ejI+m9SqJQrmd2SBW7HA0fOjvWWJjM2uc=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
|
||||
@@ -6,15 +6,21 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func humanAddress(canon []byte) (string, error) {
|
||||
var (
|
||||
CostHumanize = 5 * GasMultiplier
|
||||
CostCanonical = 4 * GasMultiplier
|
||||
)
|
||||
|
||||
func humanAddress(canon []byte) (string, uint64, error) {
|
||||
if len(canon) != sdk.AddrLen {
|
||||
return "", fmt.Errorf("Expected %d byte address", sdk.AddrLen)
|
||||
return "", CostHumanize, fmt.Errorf("Expected %d byte address", sdk.AddrLen)
|
||||
}
|
||||
return sdk.AccAddress(canon).String(), nil
|
||||
return sdk.AccAddress(canon).String(), CostHumanize, nil
|
||||
}
|
||||
|
||||
func canonicalAddress(human string) ([]byte, error) {
|
||||
return sdk.AccAddressFromBech32(human)
|
||||
func canonicalAddress(human string) ([]byte, uint64, error) {
|
||||
bz, err := sdk.AccAddressFromBech32(human)
|
||||
return bz, CostCanonical, err
|
||||
}
|
||||
|
||||
var cosmwasmAPI = cosmwasm.GoAPI{
|
||||
|
||||
@@ -369,9 +369,9 @@ func TestImportContractWithCodeHistoryReset(t *testing.T) {
|
||||
},
|
||||
"codes": [
|
||||
{
|
||||
"code_id": 1,
|
||||
"code_id": "1",
|
||||
"code_info": {
|
||||
"code_hash": "mrFpzGE5s+Qfn9Xe7OikXc0q169m7sMm4ZuV6pVA8Mc=",
|
||||
"code_hash": %q,
|
||||
"creator": "cosmos1qtu5n0cnhfkjj6l2rq97hmky9fd89gwca9yarx",
|
||||
"source": "https://example.com",
|
||||
"builder": "foo/bar:tag",
|
||||
@@ -387,41 +387,52 @@ func TestImportContractWithCodeHistoryReset(t *testing.T) {
|
||||
{
|
||||
"contract_address": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5",
|
||||
"contract_info": {
|
||||
"code_id": 1,
|
||||
"code_id": "1",
|
||||
"creator": "cosmos13x849jzd03vne42ynpj25hn8npjecxqrjghd8x",
|
||||
"admin": "cosmos1h5t8zxmjr30e9dqghtlpl40f2zz5cgey6esxtn",
|
||||
"label": "ȀĴnZV芢毤"
|
||||
}
|
||||
}
|
||||
],
|
||||
"sequences": [
|
||||
{"id_key": %q, "value": "2"},
|
||||
{"id_key": %q, "value": "2"}
|
||||
]
|
||||
}`
|
||||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
keeper, ctx, _, dstCleanup := setupKeeper(t)
|
||||
defer dstCleanup()
|
||||
|
||||
ctx = ctx.WithBlockHeight(0).WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
wasmCodeHash := sha256.Sum256(wasmCode)
|
||||
enc64 := base64.StdEncoding.EncodeToString
|
||||
var importState wasmTypes.GenesisState
|
||||
err = json.Unmarshal([]byte(fmt.Sprintf(genesis, base64.StdEncoding.EncodeToString(wasmCode))), &importState)
|
||||
err = keeper.cdc.UnmarshalJSON([]byte(
|
||||
fmt.Sprintf(genesis, enc64(wasmCodeHash[:]), enc64(wasmCode),
|
||||
enc64(append([]byte{0x04}, []byte("lastCodeId")...)),
|
||||
enc64(append([]byte{0x04}, []byte("lastContractId")...))),
|
||||
), &importState)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, importState.ValidateBasic())
|
||||
|
||||
ctx = ctx.WithBlockHeight(0).WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
|
||||
// when
|
||||
InitGenesis(ctx, keeper, importState)
|
||||
err = InitGenesis(ctx, keeper, importState)
|
||||
require.NoError(t, err)
|
||||
|
||||
// verify wasm code
|
||||
gotWasmCode, err := keeper.GetByteCode(ctx, 1)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, wasmCode, gotWasmCode)
|
||||
assert.Equal(t, wasmCode, gotWasmCode, "byte code does not match")
|
||||
|
||||
// verify code info
|
||||
gotCodeInfo := keeper.GetCodeInfo(ctx, 1)
|
||||
require.NotNil(t, gotCodeInfo)
|
||||
codeCreatorAddr, _ := sdk.AccAddressFromBech32("cosmos1qtu5n0cnhfkjj6l2rq97hmky9fd89gwca9yarx")
|
||||
codeHash := sha256.Sum256(wasmCode)
|
||||
expCodeInfo := types.CodeInfo{
|
||||
CodeHash: codeHash[:],
|
||||
CodeHash: wasmCodeHash[:],
|
||||
Creator: codeCreatorAddr,
|
||||
Source: "https://example.com",
|
||||
Builder: "foo/bar:tag",
|
||||
|
||||
@@ -26,7 +26,9 @@ import (
|
||||
// SDK reference costs can be found here: https://github.com/cosmos/cosmos-sdk/blob/02c6c9fafd58da88550ab4d7d494724a477c8a68/store/types/gas.go#L153-L164
|
||||
// A write at ~3000 gas and ~200us = 10 gas per us (microsecond) cpu/io
|
||||
// Rough timing have 88k gas at 90us, which is equal to 1k sdk gas... (one read)
|
||||
const GasMultiplier = 100
|
||||
//
|
||||
// Please not that all gas prices returned to the wasmer engine should have this multiplied
|
||||
const GasMultiplier uint64 = 100
|
||||
|
||||
// MaxGas for a contract is 10 billion wasmer gas (enforced in rust to prevent overflow)
|
||||
// The limit for v0.9.3 is defined here: https://github.com/CosmWasm/cosmwasm/blob/v0.9.3/packages/vm/src/backends/singlepass.rs#L15-L23
|
||||
@@ -225,7 +227,7 @@ func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A
|
||||
|
||||
// instantiate wasm contract
|
||||
gas := gasForContract(ctx)
|
||||
res, gasUsed, err := k.wasmer.Instantiate(codeInfo.CodeHash, params, initMsg, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
|
||||
res, gasUsed, err := k.wasmer.Instantiate(codeInfo.CodeHash, params, initMsg, prefixStore, cosmwasmAPI, querier, gasMeter(ctx), gas)
|
||||
consumeGas(ctx, gasUsed)
|
||||
if err != nil {
|
||||
return contractAddress, sdkerrors.Wrap(types.ErrInstantiateFailed, err.Error())
|
||||
@@ -278,7 +280,7 @@ func (k Keeper) Execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller
|
||||
}
|
||||
|
||||
gas := gasForContract(ctx)
|
||||
res, gasUsed, execErr := k.wasmer.Execute(codeInfo.CodeHash, params, msg, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas)
|
||||
res, gasUsed, execErr := k.wasmer.Execute(codeInfo.CodeHash, params, msg, prefixStore, cosmwasmAPI, querier, gasMeter(ctx), gas)
|
||||
consumeGas(ctx, gasUsed)
|
||||
if execErr != nil {
|
||||
return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
|
||||
@@ -331,7 +333,7 @@ func (k Keeper) migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller
|
||||
prefixStoreKey := types.GetContractStorePrefixKey(contractAddress)
|
||||
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), prefixStoreKey)
|
||||
gas := gasForContract(ctx)
|
||||
res, gasUsed, err := k.wasmer.Migrate(newCodeInfo.CodeHash, params, msg, &prefixStore, cosmwasmAPI, &querier, ctx.GasMeter(), gas)
|
||||
res, gasUsed, err := k.wasmer.Migrate(newCodeInfo.CodeHash, params, msg, &prefixStore, cosmwasmAPI, &querier, gasMeter(ctx), gas)
|
||||
consumeGas(ctx, gasUsed)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(types.ErrMigrationFailed, err.Error())
|
||||
@@ -408,7 +410,7 @@ func (k Keeper) QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []b
|
||||
Ctx: ctx,
|
||||
Plugins: k.queryPlugins,
|
||||
}
|
||||
queryResult, gasUsed, qErr := k.wasmer.Query(codeInfo.CodeHash, req, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gasForContract(ctx))
|
||||
queryResult, gasUsed, qErr := k.wasmer.Query(codeInfo.CodeHash, req, prefixStore, cosmwasmAPI, querier, gasMeter(ctx), gasForContract(ctx))
|
||||
consumeGas(ctx, gasUsed)
|
||||
if qErr != nil {
|
||||
return nil, sdkerrors.Wrap(types.ErrQueryFailed, qErr.Error())
|
||||
@@ -571,6 +573,10 @@ func gasForContract(ctx sdk.Context) uint64 {
|
||||
func consumeGas(ctx sdk.Context, gas uint64) {
|
||||
consumed := gas / GasMultiplier
|
||||
ctx.GasMeter().ConsumeGas(consumed, "wasm contract")
|
||||
// throw OutOfGas error if we ran out (got exactly to zero due to better limit enforcing)
|
||||
if ctx.GasMeter().IsOutOfGas() {
|
||||
panic(sdk.ErrorOutOfGas{"Wasmer function execution"})
|
||||
}
|
||||
}
|
||||
|
||||
// generates a contract address from codeID + instanceID
|
||||
@@ -650,3 +656,20 @@ func addrFromUint64(id uint64) sdk.AccAddress {
|
||||
binary.PutUvarint(addr[1:], id)
|
||||
return sdk.AccAddress(crypto.AddressHash(addr))
|
||||
}
|
||||
|
||||
// MultipliedGasMeter wraps the GasMeter from context and multiplies all reads by out defined multiplier
|
||||
type MultipiedGasMeter struct {
|
||||
originalMeter sdk.GasMeter
|
||||
}
|
||||
|
||||
var _ wasm.GasMeter = MultipiedGasMeter{}
|
||||
|
||||
func (m MultipiedGasMeter) GasConsumed() sdk.Gas {
|
||||
return m.originalMeter.GasConsumed() * GasMultiplier
|
||||
}
|
||||
|
||||
func gasMeter(ctx sdk.Context) MultipiedGasMeter {
|
||||
return MultipiedGasMeter{
|
||||
originalMeter: ctx.GasMeter(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,7 +306,7 @@ func TestInstantiate(t *testing.T) {
|
||||
require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", contractAddr.String())
|
||||
|
||||
gasAfter := ctx.GasMeter().GasConsumed()
|
||||
require.Equal(t, uint64(0x12313), gasAfter-gasBefore)
|
||||
require.Equal(t, uint64(0x10c43), gasAfter-gasBefore)
|
||||
|
||||
// ensure it is stored properly
|
||||
info := keeper.GetContractInfo(ctx, contractAddr)
|
||||
@@ -534,7 +534,7 @@ func TestExecute(t *testing.T) {
|
||||
|
||||
// make sure gas is properly deducted from ctx
|
||||
gasAfter := ctx.GasMeter().GasConsumed()
|
||||
require.Equal(t, uint64(0x11aa2), gasAfter-gasBefore)
|
||||
require.Equal(t, uint64(0x11617), gasAfter-gasBefore)
|
||||
|
||||
// ensure bob now exists and got both payments released
|
||||
bobAcct = accKeeper.GetAccount(ctx, bob)
|
||||
@@ -710,11 +710,18 @@ func TestExecuteWithCpuLoop(t *testing.T) {
|
||||
ctx = ctx.WithGasMeter(sdk.NewGasMeter(gasLimit))
|
||||
require.Equal(t, uint64(0), ctx.GasMeter().GasConsumed())
|
||||
|
||||
// this must fail
|
||||
// ensure we get an out of gas panic
|
||||
defer func() {
|
||||
r := recover()
|
||||
require.NotNil(t, r)
|
||||
_, ok := r.(sdk.ErrorOutOfGas)
|
||||
require.True(t, ok, "%v", r)
|
||||
}()
|
||||
|
||||
// this should throw out of gas exception (panic)
|
||||
_, err = keeper.Execute(ctx, addr, fred, []byte(`{"cpu_loop":{}}`), nil)
|
||||
assert.Error(t, err)
|
||||
// make sure gas ran out
|
||||
require.Equal(t, gasLimit, ctx.GasMeter().GasConsumed())
|
||||
require.True(t, false, "We must panic before this line")
|
||||
|
||||
}
|
||||
|
||||
func TestExecuteWithStorageLoop(t *testing.T) {
|
||||
@@ -747,7 +754,7 @@ func TestExecuteWithStorageLoop(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// make sure we set a limit before calling
|
||||
var gasLimit uint64 = 400_000
|
||||
var gasLimit uint64 = 400_002
|
||||
ctx = ctx.WithGasMeter(sdk.NewGasMeter(gasLimit))
|
||||
require.Equal(t, uint64(0), ctx.GasMeter().GasConsumed())
|
||||
|
||||
@@ -755,7 +762,6 @@ func TestExecuteWithStorageLoop(t *testing.T) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
require.NotNil(t, r)
|
||||
// TODO: ensure it is out of gas error
|
||||
_, ok := r.(sdk.ErrorOutOfGas)
|
||||
require.True(t, ok, "%v", r)
|
||||
}()
|
||||
|
||||
BIN
x/wasm/internal/keeper/testdata/burner.wasm
vendored
BIN
x/wasm/internal/keeper/testdata/burner.wasm
vendored
Binary file not shown.
BIN
x/wasm/internal/keeper/testdata/contract.wasm
vendored
BIN
x/wasm/internal/keeper/testdata/contract.wasm
vendored
Binary file not shown.
BIN
x/wasm/internal/keeper/testdata/contract.wasm.gzip
vendored
BIN
x/wasm/internal/keeper/testdata/contract.wasm.gzip
vendored
Binary file not shown.
BIN
x/wasm/internal/keeper/testdata/reflect.wasm
vendored
BIN
x/wasm/internal/keeper/testdata/reflect.wasm
vendored
Binary file not shown.
BIN
x/wasm/internal/keeper/testdata/staking.wasm
vendored
BIN
x/wasm/internal/keeper/testdata/staking.wasm
vendored
Binary file not shown.
@@ -203,11 +203,11 @@ func NewEnv(ctx sdk.Context, creator sdk.AccAddress, deposit sdk.Coins, contract
|
||||
ChainID: ctx.ChainID(),
|
||||
},
|
||||
Message: wasmTypes.MessageInfo{
|
||||
Sender: wasmTypes.CanonicalAddress(creator),
|
||||
Sender: creator.String(),
|
||||
SentFunds: NewWasmCoins(deposit),
|
||||
},
|
||||
Contract: wasmTypes.ContractInfo{
|
||||
Address: wasmTypes.CanonicalAddress(contractAddr),
|
||||
Address: contractAddr.String(),
|
||||
},
|
||||
}
|
||||
return env
|
||||
|
||||
Reference in New Issue
Block a user