Skip to content

Commit

Permalink
[CT-515] Combine place, cancel, batch cancel rate limiters (#1165)
Browse files Browse the repository at this point in the history
* combine place and cancel rate limiters, add batch cancel

* fixups

* remove cancel rate limit genesis

* fix json files for genesis

* update sample pregenesis

* get tests to work

* update protos to deprecate instead of remove

* lint fix

* empty commit

* fix tests

* lint

* basic tests with only batch cancel orders submitted

* fix cli rate limit test

* e2e tests

* rate limit 2 -> 3

* more explicit replay test

* todo comment

* linty lint

* constants for the tests

* rate limit proto deprecate => reserved

* sample pregenesis update

* indexer proto regen

* fix tests

* fix test

* upgrade handler for batch cancel configs

* upgrade handler

* proto swap reserved back to deprecated

* more test fix

* try upgrade

* fix test

* regen indexer protos

* proto lint

* test fix

* upgrade file comment
  • Loading branch information
jonfung-dydx authored Mar 19, 2024
1 parent d7333d4 commit be4ba54
Show file tree
Hide file tree
Showing 33 changed files with 786 additions and 376 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ export interface BlockRateLimitConfiguration {
* configurations.
*
* Specifying 0 values disables this rate limit.
* Deprecated in favor of `max_short_term_orders_and_cancels_per_n_blocks`
* for v5.x onwards.
*/

/** @deprecated */
maxShortTermOrdersPerNBlocks: MaxPerNBlocksRateLimit[];
/**
* How many stateful order attempts (successful and failed) are allowed for
Expand All @@ -22,7 +26,10 @@ export interface BlockRateLimitConfiguration {
*/

maxStatefulOrdersPerNBlocks: MaxPerNBlocksRateLimit[];
/** @deprecated */

maxShortTermOrderCancellationsPerNBlocks: MaxPerNBlocksRateLimit[];
maxShortTermOrdersAndCancelsPerNBlocks: MaxPerNBlocksRateLimit[];
}
/** Defines the block rate limits for CLOB specific operations. */

Expand All @@ -34,7 +41,11 @@ export interface BlockRateLimitConfigurationSDKType {
* configurations.
*
* Specifying 0 values disables this rate limit.
* Deprecated in favor of `max_short_term_orders_and_cancels_per_n_blocks`
* for v5.x onwards.
*/

/** @deprecated */
max_short_term_orders_per_n_blocks: MaxPerNBlocksRateLimitSDKType[];
/**
* How many stateful order attempts (successful and failed) are allowed for
Expand All @@ -46,7 +57,10 @@ export interface BlockRateLimitConfigurationSDKType {
*/

max_stateful_orders_per_n_blocks: MaxPerNBlocksRateLimitSDKType[];
/** @deprecated */

max_short_term_order_cancellations_per_n_blocks: MaxPerNBlocksRateLimitSDKType[];
max_short_term_orders_and_cancels_per_n_blocks: MaxPerNBlocksRateLimitSDKType[];
}
/** Defines a rate limit over a specific number of blocks. */

Expand Down Expand Up @@ -83,7 +97,8 @@ function createBaseBlockRateLimitConfiguration(): BlockRateLimitConfiguration {
return {
maxShortTermOrdersPerNBlocks: [],
maxStatefulOrdersPerNBlocks: [],
maxShortTermOrderCancellationsPerNBlocks: []
maxShortTermOrderCancellationsPerNBlocks: [],
maxShortTermOrdersAndCancelsPerNBlocks: []
};
}

Expand All @@ -101,6 +116,10 @@ export const BlockRateLimitConfiguration = {
MaxPerNBlocksRateLimit.encode(v!, writer.uint32(26).fork()).ldelim();
}

for (const v of message.maxShortTermOrdersAndCancelsPerNBlocks) {
MaxPerNBlocksRateLimit.encode(v!, writer.uint32(34).fork()).ldelim();
}

return writer;
},

Expand All @@ -125,6 +144,10 @@ export const BlockRateLimitConfiguration = {
message.maxShortTermOrderCancellationsPerNBlocks.push(MaxPerNBlocksRateLimit.decode(reader, reader.uint32()));
break;

case 4:
message.maxShortTermOrdersAndCancelsPerNBlocks.push(MaxPerNBlocksRateLimit.decode(reader, reader.uint32()));
break;

default:
reader.skipType(tag & 7);
break;
Expand All @@ -139,6 +162,7 @@ export const BlockRateLimitConfiguration = {
message.maxShortTermOrdersPerNBlocks = object.maxShortTermOrdersPerNBlocks?.map(e => MaxPerNBlocksRateLimit.fromPartial(e)) || [];
message.maxStatefulOrdersPerNBlocks = object.maxStatefulOrdersPerNBlocks?.map(e => MaxPerNBlocksRateLimit.fromPartial(e)) || [];
message.maxShortTermOrderCancellationsPerNBlocks = object.maxShortTermOrderCancellationsPerNBlocks?.map(e => MaxPerNBlocksRateLimit.fromPartial(e)) || [];
message.maxShortTermOrdersAndCancelsPerNBlocks = object.maxShortTermOrdersAndCancelsPerNBlocks?.map(e => MaxPerNBlocksRateLimit.fromPartial(e)) || [];
return message;
}

Expand Down
16 changes: 15 additions & 1 deletion proto/dydxprotocol/clob/block_rate_limit_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ message BlockRateLimitConfiguration {
// configurations.
//
// Specifying 0 values disables this rate limit.
// Deprecated in favor of `max_short_term_orders_and_cancels_per_n_blocks`
// for v5.x onwards.
repeated MaxPerNBlocksRateLimit max_short_term_orders_per_n_blocks = 1
[ (gogoproto.nullable) = false ];
[ (gogoproto.nullable) = false, deprecated = true ];

// How many stateful order attempts (successful and failed) are allowed for
// an account per N blocks. Note that the rate limits are applied
Expand All @@ -31,8 +33,20 @@ message BlockRateLimitConfiguration {
// rate limit configurations.
//
// Specifying 0 values disables this rate limit.
// Deprecated in favor of `max_short_term_orders_and_cancels_per_n_blocks`
// for v5.x onwards.
repeated MaxPerNBlocksRateLimit
max_short_term_order_cancellations_per_n_blocks = 3
[ (gogoproto.nullable) = false, deprecated = true ];

// How many short term order place and cancel attempts (successful and failed)
// are allowed for an account per N blocks. Note that the rate limits are
// applied in an AND fashion such that an order placement must pass all rate
// limit configurations.
//
// Specifying 0 values disables this rate limit.
repeated MaxPerNBlocksRateLimit
max_short_term_orders_and_cancels_per_n_blocks = 4
[ (gogoproto.nullable) = false ];
}

Expand Down
3 changes: 1 addition & 2 deletions protocol/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -1022,8 +1022,7 @@ func New(
app.GrpcStreamingManager,
txConfig.TxDecoder(),
clobFlags,
rate_limit.NewPanicRateLimiter[*clobmoduletypes.MsgPlaceOrder](),
rate_limit.NewPanicRateLimiter[*clobmoduletypes.MsgCancelOrder](),
rate_limit.NewPanicRateLimiter[sdk.Msg](),
daemonLiquidationInfo,
)
clobModule := clobmodule.NewAppModule(
Expand Down
5 changes: 3 additions & 2 deletions protocol/app/testdata/default_genesis_state.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@
}
},
"block_rate_limit_config": {
"max_short_term_order_cancellations_per_n_blocks": [],
"max_short_term_orders_per_n_blocks": [],
"max_stateful_orders_per_n_blocks": [],
"max_short_term_order_cancellations_per_n_blocks": []
"max_short_term_orders_and_cancels_per_n_blocks": [],
"max_stateful_orders_per_n_blocks": []
},
"equity_tier_limit_config": {
"short_term_order_equity_tiers": [],
Expand Down
1 change: 1 addition & 0 deletions protocol/app/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func (app *App) setupUpgradeHandlers() {
app.ModuleManager,
app.configurator,
app.PerpetualsKeeper,
app.ClobKeeper,
),
)
}
Expand Down
57 changes: 57 additions & 0 deletions protocol/app/upgrades/v5.0.0/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"

clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types"
perptypes "github.com/dydxprotocol/v4-chain/protocol/x/perpetuals/types"

upgradetypes "cosmossdk.io/x/upgrade/types"
Expand All @@ -30,10 +31,63 @@ func perpetualsUpgrade(
}
}

// blockRateLimitConfigUpdate upgrades the block rate limit. It searches for the
// 1-block window limit for short term and cancellations, sums them, and creates a new
// combined rate limit.
func blockRateLimitConfigUpdate(
ctx sdk.Context,
clobKeeper clobtypes.ClobKeeper,
) {
oldBlockRateLimitConfig := clobKeeper.GetBlockRateLimitConfiguration(ctx)
numAllowedShortTermOrderPlacementsInOneBlock := 0
numAllowedShortTermOrderCancellationsInOneBlock := 0
oldShortTermOrderRateLimits := oldBlockRateLimitConfig.MaxShortTermOrdersPerNBlocks
for _, limit := range oldShortTermOrderRateLimits {
if limit.NumBlocks == 1 {
numAllowedShortTermOrderPlacementsInOneBlock += int(limit.NumBlocks)
break
}
}
if numAllowedShortTermOrderPlacementsInOneBlock == 0 {
panic("Failed to find MaxShortTermOrdersPerNBlocks with window 1.")
}

oldShortTermOrderCancellationRateLimits := oldBlockRateLimitConfig.MaxShortTermOrderCancellationsPerNBlocks
for _, limit := range oldShortTermOrderCancellationRateLimits {
if limit.NumBlocks == 1 {
numAllowedShortTermOrderCancellationsInOneBlock += int(limit.NumBlocks)
break
}
}
if numAllowedShortTermOrderCancellationsInOneBlock == 0 {
panic("Failed to find MaxShortTermOrdersPerNBlocks with window 1.")
}

allowedNumShortTermPlaceAndCancelInFiveBlocks :=
(numAllowedShortTermOrderPlacementsInOneBlock + numAllowedShortTermOrderCancellationsInOneBlock) * 5

blockRateLimitConfig := clobtypes.BlockRateLimitConfiguration{
// Kept the same
MaxStatefulOrdersPerNBlocks: oldBlockRateLimitConfig.MaxStatefulOrdersPerNBlocks,
// Combine place and cancel, gate over 5 blocks to allow burst
MaxShortTermOrdersAndCancelsPerNBlocks: []clobtypes.MaxPerNBlocksRateLimit{
{
NumBlocks: 5,
Limit: uint32(allowedNumShortTermPlaceAndCancelInFiveBlocks),
},
},
}

if err := clobKeeper.InitializeBlockRateLimit(ctx, blockRateLimitConfig); err != nil {
panic(fmt.Sprintf("failed to update the block rate limit configuration: %s", err))
}
}

func CreateUpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
perpetualsKeeper perptypes.PerpetualsKeeper,
clobKeeper clobtypes.ClobKeeper,
) upgradetypes.UpgradeHandler {
return func(ctx context.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
sdkCtx := lib.UnwrapSDKContext(ctx, "app/upgrades")
Expand All @@ -42,6 +96,9 @@ func CreateUpgradeHandler(
// Set all perpetuals to cross market type
perpetualsUpgrade(sdkCtx, perpetualsKeeper)

// Set block rate limit configuration
blockRateLimitConfigUpdate(sdkCtx, clobKeeper)

// TODO(TRA-93): Initialize `x/vault` module.

return mm.RunMigrations(ctx, configurator, vm)
Expand Down
1 change: 1 addition & 0 deletions protocol/lib/metrics/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ const (
// CLOB.
AddPerpetualFillAmount = "add_perpetual_fill_amount"
BaseQuantums = "base_quantums"
BatchCancel = "batch_cancel"
BestAsk = "best_ask"
BestAskClobPair = "best_ask_clob_pair"
BestBid = "best_bid"
Expand Down
36 changes: 36 additions & 0 deletions protocol/mocks/ClobKeeper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 5 additions & 9 deletions protocol/scripts/genesis/sample_pregenesis.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,18 +100,14 @@
},
"clob": {
"block_rate_limit_config": {
"max_short_term_order_cancellations_per_n_blocks": [
"max_short_term_order_cancellations_per_n_blocks": [],
"max_short_term_orders_and_cancels_per_n_blocks": [
{
"limit": 200,
"num_blocks": 1
}
],
"max_short_term_orders_per_n_blocks": [
{
"limit": 200,
"limit": 400,
"num_blocks": 1
}
],
"max_short_term_orders_per_n_blocks": [],
"max_stateful_orders_per_n_blocks": [
{
"limit": 2,
Expand Down Expand Up @@ -1830,7 +1826,7 @@
]
}
},
"app_version": "4.0.0-dev0-101-g18028fd0",
"app_version": "4.0.0-dev0-134-gc65a2bfe",
"chain_id": "dydx-sample-1",
"consensus": {
"params": {
Expand Down
12 changes: 4 additions & 8 deletions protocol/testing/genesis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1404,14 +1404,10 @@ function edit_genesis() {
dasel put -t int -f "$GENESIS" '.app_state.clob.liquidations_config.fillable_price_config.spread_to_maintenance_margin_ratio_ppm' -v '1500000' # 150%

# Block Rate Limit
# Max 50 short term orders per block
dasel put -t json -f "$GENESIS" '.app_state.clob.block_rate_limit_config.max_short_term_orders_per_n_blocks.[]' -v "{}"
dasel put -t int -f "$GENESIS" '.app_state.clob.block_rate_limit_config.max_short_term_orders_per_n_blocks.[0].limit' -v '200'
dasel put -t int -f "$GENESIS" '.app_state.clob.block_rate_limit_config.max_short_term_orders_per_n_blocks.[0].num_blocks' -v '1'
# Max 50 short term order cancellations per block
dasel put -t json -f "$GENESIS" '.app_state.clob.block_rate_limit_config.max_short_term_order_cancellations_per_n_blocks.[]' -v "{}"
dasel put -t int -f "$GENESIS" '.app_state.clob.block_rate_limit_config.max_short_term_order_cancellations_per_n_blocks.[0].limit' -v '200'
dasel put -t int -f "$GENESIS" '.app_state.clob.block_rate_limit_config.max_short_term_order_cancellations_per_n_blocks.[0].num_blocks' -v '1'
# Max 400 short term orders/cancels per block
dasel put -t json -f "$GENESIS" '.app_state.clob.block_rate_limit_config.max_short_term_orders_and_cancels_per_n_blocks.[]' -v "{}"
dasel put -t int -f "$GENESIS" '.app_state.clob.block_rate_limit_config.max_short_term_orders_and_cancels_per_n_blocks.[0].limit' -v '400'
dasel put -t int -f "$GENESIS" '.app_state.clob.block_rate_limit_config.max_short_term_orders_and_cancels_per_n_blocks.[0].num_blocks' -v '1'
# Max 2 stateful orders per block
dasel put -t json -f "$GENESIS" '.app_state.clob.block_rate_limit_config.max_stateful_orders_per_n_blocks.[]' -v "{}"
dasel put -t int -f "$GENESIS" '.app_state.clob.block_rate_limit_config.max_stateful_orders_per_n_blocks.[0].limit' -v '2'
Expand Down
10 changes: 2 additions & 8 deletions protocol/testutil/constants/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,10 @@ const GenesisState = `{
},
"clob": {
"block_rate_limit_config": {
"max_short_term_orders_per_n_blocks": [
"max_short_term_orders_and_cancels_per_n_blocks": [
{
"num_blocks": 1,
"limit": 200
"limit": 400
}
],
"max_stateful_orders_per_n_blocks": [
Expand All @@ -233,12 +233,6 @@ const GenesisState = `{
"num_blocks": 100,
"limit": 20
}
],
"max_short_term_order_cancellations_per_n_blocks": [
{
"num_blocks": 1,
"limit": 200
}
]
},
"clob_pairs": [
Expand Down
3 changes: 1 addition & 2 deletions protocol/testutil/keeper/clob.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,7 @@ func createClobKeeper(
streaming.NewNoopGrpcStreamingManager(),
constants.TestEncodingCfg.TxConfig.TxDecoder(),
flags.GetDefaultClobFlags(),
rate_limit.NewNoOpRateLimiter[*types.MsgPlaceOrder](),
rate_limit.NewNoOpRateLimiter[*types.MsgCancelOrder](),
rate_limit.NewNoOpRateLimiter[sdk.Msg](),
liquidationtypes.NewDaemonLiquidationInfo(),
)
k.SetAnteHandler(constants.EmptyAnteHandler)
Expand Down
Loading

0 comments on commit be4ba54

Please sign in to comment.