diff --git a/Dockerfile b/Dockerfile index 9275a0de72..98463bc9b9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,10 +17,10 @@ RUN apk add git WORKDIR /code COPY . /code/ # See https://github.com/CosmWasm/wasmvm/releases -ADD https://github.com/CosmWasm/wasmvm/releases/download/v2.1.2/libwasmvm_muslc.aarch64.a /lib/libwasmvm_muslc.aarch64.a -ADD https://github.com/CosmWasm/wasmvm/releases/download/v2.1.2/libwasmvm_muslc.x86_64.a /lib/libwasmvm_muslc.x86_64.a -RUN sha256sum /lib/libwasmvm_muslc.aarch64.a | grep 0881c5b463e89e229b06370e9e2961aec0a5c636772d5142c68d351564464a66 -RUN sha256sum /lib/libwasmvm_muslc.x86_64.a | grep 58e1f6bfa89ee390cb9abc69a5bc126029a497fe09dd399f38a82d0d86fe95ef +ADD https://github.com/CosmWasm/wasmvm/releases/download/v2.1.4/libwasmvm_muslc.aarch64.a /lib/libwasmvm_muslc.aarch64.a +ADD https://github.com/CosmWasm/wasmvm/releases/download/v2.1.4/libwasmvm_muslc.x86_64.a /lib/libwasmvm_muslc.x86_64.a +RUN sha256sum /lib/libwasmvm_muslc.aarch64.a | grep 090b97641157fae1ae45e7ed368a1a8c091f3fef67958d3bc7c2fa7e7c54b6b4 +RUN sha256sum /lib/libwasmvm_muslc.x86_64.a | grep a4a3d09b36fabb65b119d5ba23442c23694401fcbee4451fe6b7e22e325a4bac # force it to use static lib (from above) not standard libgo_cosmwasm.so file RUN LEDGER_ENABLED=false BUILD_TAGS=muslc LINK_STATICALLY=true make build diff --git a/go.mod b/go.mod index 8b4cb9054d..26ecca678d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/CosmWasm/wasmd go 1.21 require ( - github.com/CosmWasm/wasmvm/v2 v2.1.2 + github.com/CosmWasm/wasmvm/v2 v2.1.4 github.com/cosmos/cosmos-proto v1.0.0-beta.5 github.com/cosmos/cosmos-sdk v0.50.9 github.com/cosmos/gogogateway v1.2.0 // indirect diff --git a/go.sum b/go.sum index 54068d14af..49f17d0b71 100644 --- a/go.sum +++ b/go.sum @@ -223,8 +223,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25 github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CosmWasm/wasmvm/v2 v2.1.2 h1:GkJ5bAsRlLHfIQVg/FY1VHwLyBwlCjAhDea0B8L+e20= -github.com/CosmWasm/wasmvm/v2 v2.1.2/go.mod h1:bMhLQL4Yp9CzJi9A83aR7VO9wockOsSlZbT4ztOl6bg= +github.com/CosmWasm/wasmvm/v2 v2.1.4 h1:7EUVQjBxXHkVjL2AqqXD7hMEe0dmoNn2li9E4PWRAnA= +github.com/CosmWasm/wasmvm/v2 v2.1.4/go.mod h1:bMhLQL4Yp9CzJi9A83aR7VO9wockOsSlZbT4ztOl6bg= github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index 0e445055c6..0fe1b51b04 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -171,7 +171,13 @@ func (k Keeper) create(ctx context.Context, creator sdk.AccAddress, wasmCode []b } gasLeft := k.runtimeGasForContract(sdkCtx) - checksum, gasUsed, err := k.wasmVM.StoreCode(wasmCode, gasLeft) + var gasUsed uint64 + if sdkCtx.ExecMode() == sdk.ExecModeSimulate { + // only simulate storing the code, no files are written + checksum, gasUsed, err = k.wasmVM.SimulateStoreCode(wasmCode, gasLeft) + } else { + checksum, gasUsed, err = k.wasmVM.StoreCode(wasmCode, gasLeft) + } k.consumeRuntimeGas(sdkCtx, gasUsed) if err != nil { return 0, checksum, errorsmod.Wrap(types.ErrCreateFailed, err.Error()) diff --git a/x/wasm/keeper/keeper_test.go b/x/wasm/keeper/keeper_test.go index a49d31a9b3..bc90835a90 100644 --- a/x/wasm/keeper/keeper_test.go +++ b/x/wasm/keeper/keeper_test.go @@ -422,7 +422,7 @@ func TestInstantiate(t *testing.T) { gasAfter := ctx.GasMeter().GasConsumed() if types.EnableGasVerification { - require.Equal(t, uint64(0x1bc8f), gasAfter-gasBefore) + require.Equal(t, uint64(0x1bca5), gasAfter-gasBefore) } // ensure it is stored properly @@ -959,7 +959,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(0x1acb4), gasAfter-gasBefore) + require.Equal(t, uint64(0x1acdb), gasAfter-gasBefore) } // ensure bob now exists and got both payments released bobAcct = accKeeper.GetAccount(ctx, bob) diff --git a/x/wasm/keeper/recurse_test.go b/x/wasm/keeper/recurse_test.go index 9cc93ebef5..e9c0540e08 100644 --- a/x/wasm/keeper/recurse_test.go +++ b/x/wasm/keeper/recurse_test.go @@ -56,12 +56,12 @@ func initRecurseContract(t *testing.T) (contract sdk.AccAddress, ctx sdk.Context func TestGasCostOnQuery(t *testing.T) { const ( - GasNoWork uint64 = 63_983 + GasNoWork uint64 = 0xfa02 // Note: about 100 SDK gas (10k CosmWasm gas) for each round of sha256 - GasWork50 uint64 = 64_222 // this is a little shy of 50k gas - to keep an eye on the limit + GasWork50 uint64 = 0xfaf9 - GasReturnUnhashed uint64 = 55 - GasReturnHashed uint64 = 46 + GasReturnUnhashed uint64 = 70 + GasReturnHashed uint64 = 59 ) cases := map[string]struct { @@ -211,9 +211,9 @@ func TestLimitRecursiveQueryGas(t *testing.T) { const ( // Note: about 100 SDK gas (10k CosmWasm gas) for each round of sha256 - GasWork2k uint64 = 76_279 // = SetupContractCost + x // we have 6x gas used in cpu than in the instance + GasWork2k uint64 = 0x12c20 // = SetupContractCost + x // we have 6x gas used in cpu than in the instance // This is overhead for calling into a sub-contract - GasReturnHashed uint64 = 48 + GasReturnHashed uint64 = 0x3B ) cases := map[string]struct { @@ -263,7 +263,7 @@ func TestLimitRecursiveQueryGas(t *testing.T) { expectQueriesFromContract: 10, expectOutOfGas: false, expectError: "query wasm contract failed", // Error we get from the contract instance doing the failing query, not wasmd - expectedGas: 10*(GasWork2k+GasReturnHashed) + 3279, // lots of additional gas for long error message + expectedGas: 10*(GasWork2k+GasReturnHashed) + 3400, // lots of additional gas for long error message }, } diff --git a/x/wasm/keeper/wasmtesting/mock_engine.go b/x/wasm/keeper/wasmtesting/mock_engine.go index 14a3976d1a..886a27aef1 100644 --- a/x/wasm/keeper/wasmtesting/mock_engine.go +++ b/x/wasm/keeper/wasmtesting/mock_engine.go @@ -24,6 +24,7 @@ var _ types.WasmEngine = &MockWasmEngine{} type MockWasmEngine struct { StoreCodeFn func(codeID wasmvm.WasmCode, gasLimit uint64) (wasmvm.Checksum, uint64, error) StoreCodeUncheckedFn func(codeID wasmvm.WasmCode) (wasmvm.Checksum, error) + SimulateStoreCodeFn func(codeID wasmvm.WasmCode, gasLimit uint64) (wasmvm.Checksum, uint64, 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, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.ContractResult, 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.ContractResult, uint64, error) @@ -117,6 +118,13 @@ func (m *MockWasmEngine) StoreCodeUnchecked(codeID wasmvm.WasmCode) (wasmvm.Chec return m.StoreCodeUncheckedFn(codeID) } +func (m *MockWasmEngine) SimulateStoreCode(codeID wasmvm.WasmCode, gasLimit uint64) (wasmvm.Checksum, uint64, error) { + if m.SimulateStoreCodeFn == nil { + panic("not supposed to be called!") + } + return m.SimulateStoreCodeFn(codeID, gasLimit) +} + func (m *MockWasmEngine) AnalyzeCode(codeID wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error) { if m.AnalyzeCodeFn == nil { panic("not supposed to be called!") diff --git a/x/wasm/types/wasmer_engine.go b/x/wasm/types/wasmer_engine.go index ce1a56ffc4..9a0c20b28a 100644 --- a/x/wasm/types/wasmer_engine.go +++ b/x/wasm/types/wasmer_engine.go @@ -30,6 +30,11 @@ type WasmEngine interface { // Use this for adding code that was checked before, particularly in the case of state sync. StoreCodeUnchecked(code wasmvm.WasmCode) (wasmvm.Checksum, error) + // SimulateStoreCode works like StoreCode, but does not actually store the code. + // Instead, it just does all the validation and compilation steps without storing the result on disk. + // Returns both the checksum, as well as the gas cost of compilation (in CosmWasm Gas) or an error. + SimulateStoreCode(code wasmvm.WasmCode, gasLimit uint64) (wasmvm.Checksum, uint64, error) + // AnalyzeCode will statically analyze the code. // Currently just reports if it exposes all IBC entry points. AnalyzeCode(checksum wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error)