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

Add customizable WasmLimits #1989

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions app/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type HandlerOptions struct {
ante.HandlerOptions

IBCKeeper *keeper.Keeper
WasmConfig *wasmTypes.WasmConfig
NodeConfig *wasmTypes.NodeConfig
WasmKeeper *wasmkeeper.Keeper
TXCounterStoreService corestoretypes.KVStoreService
CircuitKeeper *circuitkeeper.Keeper
Expand All @@ -40,7 +40,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
if options.SignModeHandler == nil {
return nil, errors.New("sign mode handler is required for ante builder")
}
if options.WasmConfig == nil {
if options.NodeConfig == nil {
return nil, errors.New("wasm config is required for ante builder")
}
if options.TXCounterStoreService == nil {
Expand All @@ -52,7 +52,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {

anteDecorators := []sdk.AnteDecorator{
ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
wasmkeeper.NewLimitSimulationGasDecorator(options.WasmConfig.SimulationGasLimit), // after setup context to enforce limits early
wasmkeeper.NewLimitSimulationGasDecorator(options.NodeConfig.SimulationGasLimit), // after setup context to enforce limits early
wasmkeeper.NewCountTXDecorator(options.TXCounterStoreService),
wasmkeeper.NewGasRegisterDecorator(options.WasmKeeper.GetGasRegister()),
wasmkeeper.NewTxContractsDecorator(),
Expand Down
11 changes: 6 additions & 5 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ func NewWasmApp(
)

wasmDir := filepath.Join(homePath, "wasm")
wasmConfig, err := wasm.ReadWasmConfig(appOpts)
nodeConfig, err := wasm.ReadNodeConfig(appOpts)
if err != nil {
panic(fmt.Sprintf("error while reading wasm config: %s", err))
}
Expand All @@ -645,7 +645,8 @@ func NewWasmApp(
app.MsgServiceRouter(),
app.GRPCQueryRouter(),
wasmDir,
wasmConfig,
nodeConfig,
wasmtypes.VMConfig{},
wasmkeeper.BuiltInCapabilities(),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
wasmOpts...,
Expand Down Expand Up @@ -871,7 +872,7 @@ func NewWasmApp(
app.SetPreBlocker(app.PreBlocker)
app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)
app.setAnteHandler(txConfig, wasmConfig, keys[wasmtypes.StoreKey])
app.setAnteHandler(txConfig, nodeConfig, keys[wasmtypes.StoreKey])

// must be before Loading version
// requires the snapshot store to be created and registered as a BaseAppOption
Expand Down Expand Up @@ -934,7 +935,7 @@ func NewWasmApp(
return app
}

func (app *WasmApp) setAnteHandler(txConfig client.TxConfig, wasmConfig wasmtypes.WasmConfig, txCounterStoreKey *storetypes.KVStoreKey) {
func (app *WasmApp) setAnteHandler(txConfig client.TxConfig, nodeConfig wasmtypes.NodeConfig, txCounterStoreKey *storetypes.KVStoreKey) {
anteHandler, err := NewAnteHandler(
HandlerOptions{
HandlerOptions: ante.HandlerOptions{
Expand All @@ -945,7 +946,7 @@ func (app *WasmApp) setAnteHandler(txConfig client.TxConfig, wasmConfig wasmtype
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
IBCKeeper: app.IBCKeeper,
WasmConfig: &wasmConfig,
NodeConfig: &nodeConfig,
WasmKeeper: &app.WasmKeeper,
TXCounterStoreService: runtime.NewKVStoreService(txCounterStoreKey),
CircuitKeeper: &app.CircuitKeeper,
Expand Down
4 changes: 2 additions & 2 deletions cmd/wasmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func initAppConfig() (string, interface{}) {
type CustomAppConfig struct {
serverconfig.Config

Wasm wasmtypes.WasmConfig `mapstructure:"wasm"`
Wasm wasmtypes.NodeConfig `mapstructure:"wasm"`
}

// Optionally allow the chain developer to overwrite the SDK's default
Expand All @@ -84,7 +84,7 @@ func initAppConfig() (string, interface{}) {

customAppConfig := CustomAppConfig{
Config: *srvCfg,
Wasm: wasmtypes.DefaultWasmConfig(),
Wasm: wasmtypes.DefaultNodeConfig(),
}

customAppTemplate := serverconfig.DefaultConfigTemplate +
Expand Down
31 changes: 31 additions & 0 deletions docs/proto/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
- [QueryRawContractStateResponse](#cosmwasm.wasm.v1.QueryRawContractStateResponse)
- [QuerySmartContractStateRequest](#cosmwasm.wasm.v1.QuerySmartContractStateRequest)
- [QuerySmartContractStateResponse](#cosmwasm.wasm.v1.QuerySmartContractStateResponse)
- [QueryWasmLimitsConfigRequest](#cosmwasm.wasm.v1.QueryWasmLimitsConfigRequest)
- [QueryWasmLimitsConfigResponse](#cosmwasm.wasm.v1.QueryWasmLimitsConfigResponse)

- [Query](#cosmwasm.wasm.v1.Query)

Expand Down Expand Up @@ -1421,6 +1423,34 @@ Query/SmartContractState RPC method




<a name="cosmwasm.wasm.v1.QueryWasmLimitsConfigRequest"></a>

### QueryWasmLimitsConfigRequest
QueryWasmLimitsConfigRequest is the request type for the
Query/WasmLimitsConfig RPC method.






<a name="cosmwasm.wasm.v1.QueryWasmLimitsConfigResponse"></a>

### QueryWasmLimitsConfigResponse
QueryWasmLimitsConfigResponse is the response type for the
Query/WasmLimitsConfig RPC method. It contains the JSON encoded limits for
static validation of Wasm files.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `config` | [string](#string) | | |





<!-- end messages -->

<!-- end enums -->
Expand All @@ -1447,6 +1477,7 @@ Query provides defines the gRPC querier service
| `PinnedCodes` | [QueryPinnedCodesRequest](#cosmwasm.wasm.v1.QueryPinnedCodesRequest) | [QueryPinnedCodesResponse](#cosmwasm.wasm.v1.QueryPinnedCodesResponse) | PinnedCodes gets the pinned code ids | GET|/cosmwasm/wasm/v1/codes/pinned|
| `Params` | [QueryParamsRequest](#cosmwasm.wasm.v1.QueryParamsRequest) | [QueryParamsResponse](#cosmwasm.wasm.v1.QueryParamsResponse) | Params gets the module params | GET|/cosmwasm/wasm/v1/codes/params|
| `ContractsByCreator` | [QueryContractsByCreatorRequest](#cosmwasm.wasm.v1.QueryContractsByCreatorRequest) | [QueryContractsByCreatorResponse](#cosmwasm.wasm.v1.QueryContractsByCreatorResponse) | ContractsByCreator gets the contracts by creator | GET|/cosmwasm/wasm/v1/contracts/creator/{creator_address}|
| `WasmLimitsConfig` | [QueryWasmLimitsConfigRequest](#cosmwasm.wasm.v1.QueryWasmLimitsConfigRequest) | [QueryWasmLimitsConfigResponse](#cosmwasm.wasm.v1.QueryWasmLimitsConfigResponse) | WasmLimitsConfig gets the configured limits for static validation of Wasm files, encoded in JSON. | GET|/cosmwasm/wasm/v1/wasm-limits-config|
| `BuildAddress` | [QueryBuildAddressRequest](#cosmwasm.wasm.v1.QueryBuildAddressRequest) | [QueryBuildAddressResponse](#cosmwasm.wasm.v1.QueryBuildAddressResponse) | BuildAddress builds a contract address | GET|/cosmwasm/wasm/v1/contract/build_address|

<!-- end services -->
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ replace (
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
)

// local wasmvm
replace github.com/CosmWasm/wasmvm/v2 => ../wasmvm

retract (
// see https://github.com/CosmWasm/wasmd/issues/1713
v0.44.0
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,6 @@ 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/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=
Expand Down
16 changes: 16 additions & 0 deletions proto/cosmwasm/wasm/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ service Query {
"/cosmwasm/wasm/v1/contracts/creator/{creator_address}";
}

// WasmLimitsConfig gets the configured limits for static validation of Wasm
// files, encoded in JSON.
rpc WasmLimitsConfig(QueryWasmLimitsConfigRequest)
returns (QueryWasmLimitsConfigResponse) {
option (google.api.http).get = "/cosmwasm/wasm/v1/wasm-limits-config";
}

// BuildAddress builds a contract address
rpc BuildAddress(QueryBuildAddressRequest)
returns (QueryBuildAddressResponse) {
Expand Down Expand Up @@ -317,6 +324,15 @@ message QueryContractsByCreatorResponse {
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QueryWasmLimitsConfigRequest is the request type for the
// Query/WasmLimitsConfig RPC method.
message QueryWasmLimitsConfigRequest {}

// QueryWasmLimitsConfigResponse is the response type for the
// Query/WasmLimitsConfig RPC method. It contains the JSON encoded limits for
// static validation of Wasm files.
message QueryWasmLimitsConfigResponse { string config = 1; }
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have a specific struct that we can define for config or we want to keep it flexible?
In that case, we could evaluate using bytes instead of string. WDYT?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

As mentioned in our chat, I want to keep it flexible. The reason for string instead of bytes is that I want to make it easy for contract devs to copy and paste the limits. They need pass them into cosmwasm-check. See here: https://github.com/CosmWasm/cosmwasm/blob/cf413c5ad6a58a87e0be894584f01506f3b2e0af/packages/check/src/main.rs#L41-L50


// QueryBuildAddressRequest is the request type for the Query/BuildAddress RPC
// method.
message QueryBuildAddressRequest {
Expand Down
18 changes: 9 additions & 9 deletions tests/integration/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,25 +446,25 @@ func TestHandleExecuteEscrow(t *testing.T) {
assert.Equal(t, sdk.Coins{}, data.bankKeeper.GetAllBalances(data.ctx, contractAcct.GetAddress()))
}

func TestReadWasmConfig(t *testing.T) {
func TestReadNodeConfig(t *testing.T) {
withViper := func(s string) *viper.Viper {
v := viper.New()
v.SetConfigType("toml")
require.NoError(t, v.ReadConfig(strings.NewReader(s)))
return v
}
var one uint64 = 1
defaults := types.DefaultWasmConfig()
defaults := types.DefaultNodeConfig()

specs := map[string]struct {
src servertypes.AppOptions
exp types.WasmConfig
exp types.NodeConfig
}{
"set query gas limit via opts": {
src: AppOptionsMock{
"wasm.query_gas_limit": 1,
},
exp: types.WasmConfig{
exp: types.NodeConfig{
SmartQueryGasLimit: 1,
MemoryCacheSize: defaults.MemoryCacheSize,
},
Expand All @@ -473,7 +473,7 @@ func TestReadWasmConfig(t *testing.T) {
src: AppOptionsMock{
"wasm.memory_cache_size": 2,
},
exp: types.WasmConfig{
exp: types.NodeConfig{
MemoryCacheSize: 2,
SmartQueryGasLimit: defaults.SmartQueryGasLimit,
},
Expand All @@ -482,7 +482,7 @@ func TestReadWasmConfig(t *testing.T) {
src: AppOptionsMock{
"trace": true,
},
exp: types.WasmConfig{
exp: types.NodeConfig{
SmartQueryGasLimit: defaults.SmartQueryGasLimit,
MemoryCacheSize: defaults.MemoryCacheSize,
ContractDebugMode: true,
Expand All @@ -497,12 +497,12 @@ func TestReadWasmConfig(t *testing.T) {
exp: defaults,
},
"custom config template values": {
src: withViper(types.ConfigTemplate(types.WasmConfig{
src: withViper(types.ConfigTemplate(types.NodeConfig{
SimulationGasLimit: &one,
SmartQueryGasLimit: 2,
MemoryCacheSize: 3,
})),
exp: types.WasmConfig{
exp: types.NodeConfig{
SimulationGasLimit: &one,
SmartQueryGasLimit: 2,
MemoryCacheSize: 3,
Expand All @@ -512,7 +512,7 @@ func TestReadWasmConfig(t *testing.T) {
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
got, err := wasm.ReadWasmConfig(spec.src)
got, err := wasm.ReadNodeConfig(spec.src)
require.NoError(t, err)
assert.Equal(t, spec.exp, got)
})
Expand Down
4 changes: 2 additions & 2 deletions x/wasm/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ var (
// Deprecated: Do not use.
NewWasmCoins = types.NewWasmCoins
// Deprecated: Do not use.
DefaultWasmConfig = types.DefaultWasmConfig
DefaultNodeConfig = types.DefaultNodeConfig
// Deprecated: Do not use.
DefaultParams = types.DefaultParams
// Deprecated: Do not use.
Expand Down Expand Up @@ -174,7 +174,7 @@ type (
// Deprecated: Do not use.
CreatedAt = types.AbsoluteTxPosition
// Deprecated: Do not use.
Config = types.WasmConfig
Config = types.NodeConfig
// Deprecated: Do not use.
CodeInfoResponse = types.CodeInfoResponse
// Deprecated: Do not use.
Expand Down
8 changes: 4 additions & 4 deletions x/wasm/keeper/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ func BenchmarkInstantiationOverhead(b *testing.B) {
}
for name, spec := range specs {
b.Run(name, func(b *testing.B) {
wasmConfig := types.WasmConfig{MemoryCacheSize: 0}
ctx, keepers := createTestInput(b, false, AvailableCapabilities, wasmConfig, spec.db())
nodeConfig := types.NodeConfig{MemoryCacheSize: 0}
ctx, keepers := createTestInput(b, false, AvailableCapabilities, nodeConfig, types.VMConfig{}, spec.db())
example := InstantiateHackatomExampleContract(b, ctx, keepers)
if spec.pinned {
require.NoError(b, keepers.ContractKeeper.PinCode(ctx, example.CodeID))
Expand Down Expand Up @@ -85,9 +85,9 @@ func BenchmarkCompilation(b *testing.B) {

for name, spec := range specs {
b.Run(name, func(b *testing.B) {
wasmConfig := types.WasmConfig{MemoryCacheSize: 0}
nodeConfig := types.NodeConfig{MemoryCacheSize: 0}
db := dbm.NewMemDB()
ctx, keepers := createTestInput(b, false, AvailableCapabilities, wasmConfig, db)
ctx, keepers := createTestInput(b, false, AvailableCapabilities, nodeConfig, types.VMConfig{}, db)

// print out code size for comparisons
code, err := os.ReadFile(spec.wasmFile)
Expand Down
6 changes: 4 additions & 2 deletions x/wasm/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"

"github.com/CosmWasm/wasmd/x/wasm/types"
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
)

func TestGenesisExportImport(t *testing.T) {
Expand Down Expand Up @@ -680,7 +681,7 @@ func setupKeeper(t *testing.T) (*Keeper, sdk.Context) {
// also registering gov interfaces for nested Any type
v1beta1.RegisterInterfaces(encodingConfig.InterfaceRegistry)

wasmConfig := types.DefaultWasmConfig()
nodeConfig := types.DefaultNodeConfig()

srcKeeper := NewKeeper(
encodingConfig.Codec,
Expand All @@ -697,7 +698,8 @@ func setupKeeper(t *testing.T) (*Keeper, sdk.Context) {
nil,
nil,
tempDir,
wasmConfig,
nodeConfig,
wasmtypes.VMConfig{},
AvailableCapabilities,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
Expand Down
7 changes: 7 additions & 0 deletions x/wasm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ type Keeper struct {
// the address capable of executing a MsgUpdateParams message. Typically, this
// should be the x/gov module account.
authority string

// wasmLimits contains the limits sent to wasmvm on init
wasmLimits wasmvmtypes.WasmLimits
}

func (k Keeper) getUploadAccessConfig(ctx context.Context) types.AccessConfig {
Expand All @@ -119,6 +122,10 @@ func (k Keeper) getInstantiateAccessConfig(ctx context.Context) types.AccessType
return k.GetParams(ctx).InstantiateDefaultPermission
}

func (k Keeper) GetWasmLimits() wasmvmtypes.WasmLimits {
return k.wasmLimits
}

// GetParams returns the total set of wasm parameters.
func (k Keeper) GetParams(ctx context.Context) types.Params {
p, err := k.params.Get(ctx)
Expand Down
Loading