From 9b00f07ce156e4632ba0d3470f42a43b208da069 Mon Sep 17 00:00:00 2001 From: dylanhuang Date: Mon, 24 Jul 2023 11:44:02 +0800 Subject: [PATCH 1/6] fix: limit pagination to protect the node would not be Query DoS (#252) * fix: limit pagination to protect the node would not be Query DoS * chore: fix lint * chore: fix testcase --- types/query/pagination.go | 6 +++++- types/query/pagination_test.go | 13 +++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/types/query/pagination.go b/types/query/pagination.go index 0c670b50e6..730741afc5 100644 --- a/types/query/pagination.go +++ b/types/query/pagination.go @@ -38,7 +38,8 @@ func ParsePagination(pageReq *PageRequest) (page, limit int, err error) { if limit < 0 { return 1, 0, status.Error(codes.InvalidArgument, "limit must greater than 0") - } else if limit == 0 { + } else if limit > DefaultLimit || limit == 0 { + // limit to protect the node would not be Query DoS limit = DefaultLimit } @@ -74,6 +75,9 @@ func Paginate( // count total results when the limit is zero/not supplied countTotal = true + } else if limit > DefaultLimit { + // limit to protect the node would not be Query DoS + limit = DefaultLimit } if len(key) != 0 { diff --git a/types/query/pagination_test.go b/types/query/pagination_test.go index 49a09619a4..4228b0cde9 100644 --- a/types/query/pagination_test.go +++ b/types/query/pagination_test.go @@ -234,11 +234,20 @@ func (s *paginationTestSuite) TestReversePagination() { s.Require().NotNil(res1.Pagination.NextKey) s.T().Log("verify paginate with custom limit and countTotal, Reverse false") - pageReq = &query.PageRequest{Limit: 150} + pageReq = &query.PageRequest{Limit: 100} request = types.NewQueryAllBalancesRequest(addr1, pageReq) res1, err = queryClient.AllBalances(gocontext.Background(), request) s.Require().NoError(err) - s.Require().Equal(res1.Balances.Len(), 150) + s.Require().Equal(res1.Balances.Len(), 100) + s.Require().NotNil(res1.Pagination.NextKey) + s.Require().Equal(res1.Pagination.Total, uint64(0)) + + s.T().Log("verify paginate with custom limit and countTotal, Reverse false") + pageReq = &query.PageRequest{Limit: 50, Offset: 100} + request = types.NewQueryAllBalancesRequest(addr1, pageReq) + res1, err = queryClient.AllBalances(gocontext.Background(), request) + s.Require().NoError(err) + s.Require().Equal(res1.Balances.Len(), 50) s.Require().NotNil(res1.Pagination.NextKey) s.Require().Equal(res1.Pagination.Total, uint64(0)) From c2834e8978a5d09900e970b70c5b8f27cb02be88 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Mon, 24 Jul 2023 13:46:22 +0800 Subject: [PATCH 2/6] feat: add option for disabling event emit --- baseapp/options.go | 5 +++++ server/config/config.go | 3 +++ server/config/toml.go | 4 ++++ server/start.go | 3 +++ server/util.go | 1 + types/events.go | 39 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 55 insertions(+) diff --git a/baseapp/options.go b/baseapp/options.go index 36ca4d1a0c..e57bee6a25 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -24,6 +24,11 @@ func SetPruning(opts pruningtypes.PruningOptions) func(*BaseApp) { return func(bapp *BaseApp) { bapp.cms.SetPruning(opts) } } +// SetEventing sets an eventing option on the event manager with the app +func SetEventing(eventingStr string) func(*BaseApp) { + return func(bapp *BaseApp) { sdk.SetEventingOption(eventingStr) } +} + // SetMinGasPrices returns an option that sets the minimum gas prices on the app. func SetMinGasPrices(gasPricesStr string) func(*BaseApp) { gasPrices, err := sdk.ParseDecCoins(gasPricesStr) diff --git a/server/config/config.go b/server/config/config.go index 28a7d4f4b1..d356899641 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -48,6 +48,8 @@ type BaseConfig struct { PruningKeepRecent string `mapstructure:"pruning-keep-recent"` PruningInterval string `mapstructure:"pruning-interval"` + Eventing string `mapstructure:"eventing"` + // HaltHeight contains a non-zero block height at which a node will gracefully // halt and shutdown that can be used to assist upgrades and testing. // @@ -270,6 +272,7 @@ func DefaultConfig() *Config { Pruning: pruningtypes.PruningOptionDefault, PruningKeepRecent: "0", PruningInterval: "0", + Eventing: sdk.EventingOptionNothing, MinRetainBlocks: 0, IndexEvents: make([]string, 0), IAVLCacheSize: 781250, diff --git a/server/config/toml.go b/server/config/toml.go index 728d8a735a..6c710e04af 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -27,6 +27,10 @@ minimum-gas-prices = "{{ .BaseConfig.MinGasPrices }}" # custom: allow pruning options to be manually specified through 'pruning-keep-recent', and 'pruning-interval' pruning = "{{ .BaseConfig.Pruning }}" +# everything: all events will be emitted +# nothing: no events will be emitted. +eventing = "{{ .BaseConfig.Eventing }}" + # These are applied if and only if the pruning strategy is custom. pruning-keep-recent = "{{ .BaseConfig.PruningKeepRecent }}" pruning-interval = "{{ .BaseConfig.PruningInterval }}" diff --git a/server/start.go b/server/start.go index 81d5f86ccd..2d387ba92e 100644 --- a/server/start.go +++ b/server/start.go @@ -32,6 +32,7 @@ import ( "github.com/cosmos/cosmos-sdk/server/types" pruningtypes "github.com/cosmos/cosmos-sdk/store/pruning/types" "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/mempool" ) @@ -52,6 +53,7 @@ const ( FlagPruning = "pruning" FlagPruningKeepRecent = "pruning-keep-recent" FlagPruningInterval = "pruning-interval" + FlagEventing = "eventing" FlagIndexEvents = "index-events" FlagMinRetainBlocks = "min-retain-blocks" FlagIAVLCacheSize = "iavl-cache-size" @@ -183,6 +185,7 @@ is performed. Note, when enabled, gRPC will also be automatically enabled. cmd.Flags().Uint64(FlagPruningInterval, 0, "Height interval at which pruned heights are removed from disk (ignored if pruning is not 'custom')") cmd.Flags().Uint(FlagInvCheckPeriod, 0, "Assert registered invariants every N blocks") cmd.Flags().Uint64(FlagMinRetainBlocks, 0, "Minimum block height offset during ABCI commit to prune Tendermint blocks") + cmd.Flags().String(FlagEventing, sdk.EventingOptionEverything, "Eventing strategy (everything|nothing)") cmd.Flags().Bool(FlagAPIEnable, false, "Define if the API server should be enabled") cmd.Flags().Bool(FlagAPISwagger, false, "Define if swagger documentation should automatically be registered (Note: the API must also be enabled)") diff --git a/server/util.go b/server/util.go index 7237b27dc1..ed37b5784e 100644 --- a/server/util.go +++ b/server/util.go @@ -480,6 +480,7 @@ func DefaultBaseappOptions(appOpts types.AppOptions) []func(*baseapp.BaseApp) { return []func(*baseapp.BaseApp){ baseapp.SetPruning(pruningOpts), + baseapp.SetEventing(cast.ToString(appOpts.Get(FlagEventing))), baseapp.SetMinGasPrices(cast.ToString(appOpts.Get(FlagMinGasPrices))), baseapp.SetHaltHeight(cast.ToUint64(appOpts.Get(FlagHaltHeight))), baseapp.SetHaltTime(cast.ToUint64(appOpts.Get(FlagHaltTime))), diff --git a/types/events.go b/types/events.go index b74f3913c3..dc73c1ecca 100644 --- a/types/events.go +++ b/types/events.go @@ -16,6 +16,33 @@ import ( "github.com/cosmos/cosmos-sdk/codec" ) +// EventingOptionEverything will allow to emit all events. +const EventingOptionEverything = "everything" + +// EventingOptionNothing will emit none events. +const EventingOptionNothing = "nothing" + +type emittingStrategy int + +const ( + // emittingEverything strategy will emit everything. + emittingEverything emittingStrategy = iota + // emittingNothing strategy will emit nothing. + emittingNothing +) + +var strategy emittingStrategy + +func SetEventingOption(option string) { + if option == "" || option == EventingOptionEverything { + strategy = emittingEverything + } else if option == EventingOptionNothing { + strategy = emittingNothing + } else { + panic("invalid eventing option") + } +} + // ---------------------------------------------------------------------------- // Event Manager // ---------------------------------------------------------------------------- @@ -35,12 +62,18 @@ func (em *EventManager) Events() Events { return em.events } // EmitEvent stores a single Event object. // Deprecated: Use EmitTypedEvent func (em *EventManager) EmitEvent(event Event) { + if strategy == emittingNothing { + return + } em.events = em.events.AppendEvent(event) } // EmitEvents stores a series of Event objects. // Deprecated: Use EmitTypedEvents func (em *EventManager) EmitEvents(events Events) { + if strategy == emittingNothing { + return + } em.events = em.events.AppendEvents(events) } @@ -51,6 +84,9 @@ func (em EventManager) ABCIEvents() []abci.Event { // EmitTypedEvent takes typed event and emits converting it into Event func (em *EventManager) EmitTypedEvent(tev proto.Message) error { + if strategy == emittingNothing { + return nil + } event, err := TypedEventToEvent(tev) if err != nil { return err @@ -62,6 +98,9 @@ func (em *EventManager) EmitTypedEvent(tev proto.Message) error { // EmitTypedEvents takes series of typed events and emit func (em *EventManager) EmitTypedEvents(tevs ...proto.Message) error { + if strategy == emittingNothing { + return nil + } events := make(Events, len(tevs)) for i, tev := range tevs { res, err := TypedEventToEvent(tev) From 892bd1bd205742eb887d1c84e7f7c107ef0f39f2 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Mon, 24 Jul 2023 13:48:13 +0800 Subject: [PATCH 3/6] update toml --- server/config/toml.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/config/toml.go b/server/config/toml.go index 6c710e04af..7636434c0b 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -27,14 +27,14 @@ minimum-gas-prices = "{{ .BaseConfig.MinGasPrices }}" # custom: allow pruning options to be manually specified through 'pruning-keep-recent', and 'pruning-interval' pruning = "{{ .BaseConfig.Pruning }}" -# everything: all events will be emitted -# nothing: no events will be emitted. -eventing = "{{ .BaseConfig.Eventing }}" - # These are applied if and only if the pruning strategy is custom. pruning-keep-recent = "{{ .BaseConfig.PruningKeepRecent }}" pruning-interval = "{{ .BaseConfig.PruningInterval }}" +# everything: all events will be emitted +# nothing: no events will be emitted. +eventing = "{{ .BaseConfig.Eventing }}" + # HaltHeight contains a non-zero block height at which a node will gracefully # halt and shutdown that can be used to assist upgrades and testing. # From 1c0bc00b9e17d40a60575f7756eed75828820fb1 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Mon, 24 Jul 2023 13:58:07 +0800 Subject: [PATCH 4/6] fix lint issue --- types/events.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/types/events.go b/types/events.go index dc73c1ecca..8a03c58192 100644 --- a/types/events.go +++ b/types/events.go @@ -34,11 +34,14 @@ const ( var strategy emittingStrategy func SetEventingOption(option string) { - if option == "" || option == EventingOptionEverything { + switch option { + case "": strategy = emittingEverything - } else if option == EventingOptionNothing { + case EventingOptionEverything: + strategy = emittingEverything + case EventingOptionNothing: strategy = emittingNothing - } else { + default: panic("invalid eventing option") } } From 0f3016c6ef9879dd62ed798e5819b7f78d3e3601 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Mon, 24 Jul 2023 16:01:50 +0800 Subject: [PATCH 5/6] update the default config --- server/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/config/config.go b/server/config/config.go index d356899641..732d785ec0 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -272,7 +272,7 @@ func DefaultConfig() *Config { Pruning: pruningtypes.PruningOptionDefault, PruningKeepRecent: "0", PruningInterval: "0", - Eventing: sdk.EventingOptionNothing, + Eventing: sdk.EventingOptionEverything, MinRetainBlocks: 0, IndexEvents: make([]string, 0), IAVLCacheSize: 781250, From 05d01e9a5be596fa2dea67ddfa22c9ef21550ce1 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Tue, 25 Jul 2023 16:01:16 +0800 Subject: [PATCH 6/6] release: draft release for v0.2.3-alpha.5 (#254) --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d0f598591..59d1d02a30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## v0.2.3-alpha.5 +This is a maintenance release. + +Features: +* [#253](https://github.com/bnb-chain/greenfield-cosmos-sdk/pull/253) feat: add option for disabling event emit + +Fix: +* [#252](https://github.com/bnb-chain/greenfield-cosmos-sdk/pull/252) fix: limit pagination to protect the node would not be Query DoS + ## v0.2.3-alpha.4 This is a maintenance release.