Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>
This commit is contained in:
parent
6b395f61d9
commit
bee95b19b5
@ -41,6 +41,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
### Features
|
||||
|
||||
* (x/bank) [#16795](https://github.com/cosmos/cosmos-sdk/pull/16852) Add `DenomMetadataByQueryString` query in bank module to support metadata query by query string.
|
||||
* (baseapp) [#16239](https://github.com/cosmos/cosmos-sdk/pull/16239) Add Gas Limits to allow node operators to resource bound queries.
|
||||
|
||||
### Improvements
|
||||
|
||||
|
||||
@ -1116,7 +1116,8 @@ func (app *BaseApp) CreateQueryContext(height int64, prove bool) (sdk.Context, e
|
||||
// branch the commit multi-store for safety
|
||||
ctx := sdk.NewContext(cacheMS, app.checkState.ctx.BlockHeader(), true, app.logger).
|
||||
WithMinGasPrices(app.minGasPrices).
|
||||
WithBlockHeight(height)
|
||||
WithBlockHeight(height).
|
||||
WithGasMeter(storetypes.NewGasMeter(app.queryGasLimit))
|
||||
|
||||
if height != lastBlockHeight {
|
||||
rms, ok := app.cms.(*rootmulti.Store)
|
||||
|
||||
@ -3,6 +3,7 @@ package baseapp
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
@ -123,6 +124,9 @@ type BaseApp struct {
|
||||
// application parameter store.
|
||||
paramStore ParamStore
|
||||
|
||||
// queryGasLimit defines the maximum gas for queries; unbounded if 0.
|
||||
queryGasLimit uint64
|
||||
|
||||
// The minimum gas prices a validator is willing to accept for processing a
|
||||
// transaction. This is mainly used for DoS and spam prevention.
|
||||
minGasPrices sdk.DecCoins
|
||||
@ -192,6 +196,7 @@ func NewBaseApp(
|
||||
msgServiceRouter: NewMsgServiceRouter(),
|
||||
txDecoder: txDecoder,
|
||||
fauxMerkleMode: false,
|
||||
queryGasLimit: math.MaxUint64,
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
|
||||
@ -85,6 +85,26 @@ func NewBaseAppSuite(t *testing.T, opts ...func(*baseapp.BaseApp)) *BaseAppSuite
|
||||
}
|
||||
}
|
||||
|
||||
func getQueryBaseapp(t *testing.T) *baseapp.BaseApp {
|
||||
t.Helper()
|
||||
|
||||
db := dbm.NewMemDB()
|
||||
name := t.Name()
|
||||
app := baseapp.NewBaseApp(name, log.NewTestLogger(t), db, nil)
|
||||
|
||||
_, err := app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
|
||||
require.NoError(t, err)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 2})
|
||||
require.NoError(t, err)
|
||||
_, err = app.Commit()
|
||||
require.NoError(t, err)
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
func NewBaseAppSuiteWithSnapshots(t *testing.T, cfg SnapshotsConfig, opts ...func(*baseapp.BaseApp)) *BaseAppSuite {
|
||||
snapshotTimeout := 1 * time.Minute
|
||||
snapshotStore, err := snapshots.NewStore(dbm.NewMemDB(), testutil.GetTempDir(t))
|
||||
@ -614,6 +634,60 @@ func TestSetMinGasPrices(t *testing.T) {
|
||||
require.Equal(t, minGasPrices, ctx.MinGasPrices())
|
||||
}
|
||||
|
||||
type ctxType string
|
||||
|
||||
const (
|
||||
QueryCtx ctxType = "query"
|
||||
CheckTxCtx ctxType = "checkTx"
|
||||
)
|
||||
|
||||
var ctxTypes = []ctxType{QueryCtx, CheckTxCtx}
|
||||
|
||||
func (c ctxType) GetCtx(t *testing.T, bapp *baseapp.BaseApp) sdk.Context {
|
||||
t.Helper()
|
||||
if c == QueryCtx {
|
||||
ctx, err := bapp.CreateQueryContext(1, false)
|
||||
require.NoError(t, err)
|
||||
return ctx
|
||||
} else if c == CheckTxCtx {
|
||||
return getCheckStateCtx(bapp)
|
||||
}
|
||||
// TODO: Not supported yet
|
||||
return getFinalizeBlockStateCtx(bapp)
|
||||
}
|
||||
|
||||
func TestQueryGasLimit(t *testing.T) {
|
||||
testCases := []struct {
|
||||
queryGasLimit uint64
|
||||
gasActuallyUsed uint64
|
||||
shouldQueryErr bool
|
||||
}{
|
||||
{queryGasLimit: 100, gasActuallyUsed: 50, shouldQueryErr: false}, // Valid case
|
||||
{queryGasLimit: 100, gasActuallyUsed: 150, shouldQueryErr: true}, // gasActuallyUsed > queryGasLimit
|
||||
{queryGasLimit: 0, gasActuallyUsed: 50, shouldQueryErr: false}, // fuzzing with queryGasLimit = 0
|
||||
{queryGasLimit: 0, gasActuallyUsed: 0, shouldQueryErr: false}, // both queryGasLimit and gasActuallyUsed are 0
|
||||
{queryGasLimit: 200, gasActuallyUsed: 200, shouldQueryErr: false}, // gasActuallyUsed == queryGasLimit
|
||||
{queryGasLimit: 100, gasActuallyUsed: 1000, shouldQueryErr: true}, // gasActuallyUsed > queryGasLimit
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
for _, ctxType := range ctxTypes {
|
||||
t.Run(fmt.Sprintf("%s: %d - %d", ctxType, tc.queryGasLimit, tc.gasActuallyUsed), func(t *testing.T) {
|
||||
app := getQueryBaseapp(t)
|
||||
baseapp.SetQueryGasLimit(tc.queryGasLimit)(app)
|
||||
ctx := ctxType.GetCtx(t, app)
|
||||
|
||||
// query gas limit should have no effect when CtxType != QueryCtx
|
||||
if tc.shouldQueryErr && ctxType == QueryCtx {
|
||||
require.Panics(t, func() { ctx.GasMeter().ConsumeGas(tc.gasActuallyUsed, "test") })
|
||||
} else {
|
||||
require.NotPanics(t, func() { ctx.GasMeter().ConsumeGas(tc.gasActuallyUsed, "test") })
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMaximumBlockGas(t *testing.T) {
|
||||
suite := NewBaseAppSuite(t)
|
||||
_, err := suite.baseApp.InitChain(&abci.RequestInitChain{})
|
||||
|
||||
@ -3,6 +3,7 @@ package baseapp
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
|
||||
dbm "github.com/cosmos/cosmos-db"
|
||||
|
||||
@ -36,6 +37,15 @@ func SetMinGasPrices(gasPricesStr string) func(*BaseApp) {
|
||||
return func(bapp *BaseApp) { bapp.setMinGasPrices(gasPrices) }
|
||||
}
|
||||
|
||||
// SetQueryGasLimit returns an option that sets a gas limit for queries.
|
||||
func SetQueryGasLimit(queryGasLimit uint64) func(*BaseApp) {
|
||||
if queryGasLimit == 0 {
|
||||
queryGasLimit = math.MaxUint64
|
||||
}
|
||||
|
||||
return func(bapp *BaseApp) { bapp.queryGasLimit = queryGasLimit }
|
||||
}
|
||||
|
||||
// SetHaltHeight returns a BaseApp option function that sets the halt block height.
|
||||
func SetHaltHeight(blockHeight uint64) func(*BaseApp) {
|
||||
return func(bapp *BaseApp) { bapp.setHaltHeight(blockHeight) }
|
||||
|
||||
@ -39,6 +39,10 @@ type BaseConfig struct {
|
||||
// specified in this config (e.g. 0.25token1;0.0001token2).
|
||||
MinGasPrices string `mapstructure:"minimum-gas-prices"`
|
||||
|
||||
// The maximum amount of gas a grpc/Rest query may consume.
|
||||
// If set to 0, it is unbounded.
|
||||
QueryGasLimit uint64 `mapstructure:"query-gas-limit"`
|
||||
|
||||
Pruning string `mapstructure:"pruning"`
|
||||
PruningKeepRecent string `mapstructure:"pruning-keep-recent"`
|
||||
PruningInterval string `mapstructure:"pruning-interval"`
|
||||
@ -225,6 +229,7 @@ func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
BaseConfig: BaseConfig{
|
||||
MinGasPrices: defaultMinGasPrices,
|
||||
QueryGasLimit: 0,
|
||||
InterBlockCache: true,
|
||||
Pruning: pruningtypes.PruningOptionDefault,
|
||||
PruningKeepRecent: "0",
|
||||
|
||||
@ -21,6 +21,10 @@ const DefaultConfigTemplate = `# This is a TOML config file.
|
||||
# specified in this config (e.g. 0.25token1;0.0001token2).
|
||||
minimum-gas-prices = "{{ .BaseConfig.MinGasPrices }}"
|
||||
|
||||
# The maximum gas a query coming over rest/grpc may consume.
|
||||
# If this is set to zero, the query can consume an unbounded amount of gas.
|
||||
query-gas-limit = "{{ .BaseConfig.QueryGasLimit }}"
|
||||
|
||||
# default: the last 362880 states are kept, pruning at 10 block intervals
|
||||
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
|
||||
# everything: 2 latest states will be kept; pruning at 10 block intervals.
|
||||
|
||||
@ -50,6 +50,7 @@ const (
|
||||
flagTraceStore = "trace-store"
|
||||
flagCPUProfile = "cpu-profile"
|
||||
FlagMinGasPrices = "minimum-gas-prices"
|
||||
FlagQueryGasLimit = "query-gas-limit"
|
||||
FlagHaltHeight = "halt-height"
|
||||
FlagHaltTime = "halt-time"
|
||||
FlagInterBlockCache = "inter-block-cache"
|
||||
@ -180,6 +181,7 @@ is performed. Note, when enabled, gRPC will also be automatically enabled.
|
||||
cmd.Flags().String(flagTransport, "socket", "Transport protocol: socket, grpc")
|
||||
cmd.Flags().String(flagTraceStore, "", "Enable KVStore tracing to an output file")
|
||||
cmd.Flags().String(FlagMinGasPrices, "", "Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photino;0.0001stake)")
|
||||
cmd.Flags().Uint64(FlagQueryGasLimit, 0, "Maximum gas a Rest/Grpc query can consume. Blank and 0 imply unbounded.")
|
||||
cmd.Flags().IntSlice(FlagUnsafeSkipUpgrades, []int{}, "Skip a set of upgrade heights to continue the old binary")
|
||||
cmd.Flags().Uint64(FlagHaltHeight, 0, "Block height at which to gracefully halt the chain and shutdown the node")
|
||||
cmd.Flags().Uint64(FlagHaltTime, 0, "Minimum block time (in Unix seconds) at which to gracefully halt the chain and shutdown the node")
|
||||
|
||||
@ -516,6 +516,7 @@ func DefaultBaseappOptions(appOpts types.AppOptions) []func(*baseapp.BaseApp) {
|
||||
baseapp.SetIAVLDisableFastNode(cast.ToBool(appOpts.Get(FlagDisableIAVLFastNode))),
|
||||
defaultMempool,
|
||||
baseapp.SetChainID(chainID),
|
||||
baseapp.SetQueryGasLimit(cast.ToUint64(appOpts.Get(FlagQueryGasLimit))),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,10 @@
|
||||
# specified in this config (e.g. 0.25token1;0.0001token2).
|
||||
minimum-gas-prices = "0stake"
|
||||
|
||||
# The maximum gas a query coming over rest/grpc may consume.
|
||||
# If this is set to zero, the query can consume an unbounded amount of gas.
|
||||
query-gas-limit = "0"
|
||||
|
||||
# default: the last 362880 states are kept, pruning at 10 block intervals
|
||||
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
|
||||
# everything: 2 latest states will be kept; pruning at 10 block intervals.
|
||||
@ -226,4 +230,4 @@ max-txs = "5000"
|
||||
query_gas_limit = 300000
|
||||
# This is the number of wasm vm instances we keep cached in memory for speed-up
|
||||
# Warning: this is currently unstable and may lead to crashes, best to keep for 0 unless testing locally
|
||||
lru_size = 0
|
||||
lru_size = 0
|
||||
|
||||
Loading…
Reference in New Issue
Block a user