From a1a45c8f6198d0c9994f85c9c349912972fa711c Mon Sep 17 00:00:00 2001 From: Teddy Ding Date: Mon, 1 Jul 2024 20:00:13 -0400 Subject: [PATCH] wip: deprecate in-memory UCO --- protocol/x/clob/abci.go | 30 ++-- protocol/x/clob/abci_test.go | 108 ++++++------- protocol/x/clob/keeper/clob_pair_test.go | 13 +- protocol/x/clob/keeper/final_settlement.go | 4 +- protocol/x/clob/keeper/keeper.go | 50 +++--- protocol/x/clob/keeper/orders.go | 53 +++---- protocol/x/clob/keeper/orders_test.go | 6 +- .../keeper/untriggered_conditional_orders.go | 147 ++++++++---------- .../untriggered_conditional_orders_test.go | 7 +- 9 files changed, 199 insertions(+), 219 deletions(-) diff --git a/protocol/x/clob/abci.go b/protocol/x/clob/abci.go index 8efbfc71e1..69fbd20191 100644 --- a/protocol/x/clob/abci.go +++ b/protocol/x/clob/abci.go @@ -89,26 +89,26 @@ func EndBlocker( } // Prune expired untriggered conditional orders from the in-memory UntriggeredConditionalOrders struct. - keeper.PruneUntriggeredConditionalOrders( - expiredStatefulOrderIds, - processProposerMatchesEvents.PlacedStatefulCancellationOrderIds, - ) + // keeper.PruneUntriggeredConditionalOrders( + // expiredStatefulOrderIds, + // processProposerMatchesEvents.PlacedStatefulCancellationOrderIds, + // ) // Update the memstore with expired order ids. // These expired stateful order ids will be purged from the memclob in `Commit`. processProposerMatchesEvents.ExpiredStatefulOrderIds = expiredStatefulOrderIds - // Before triggering conditional orders, add newly-placed conditional orders to the clob keeper's - // in-memory UntriggeredConditionalOrders data structure to allow conditional orders to - // trigger in the same block they are placed. Skip triggering orders which have been cancelled - // or expired. - // TODO(CLOB-773) Support conditional order replacements. Ensure replacements are de-duplicated. - keeper.AddUntriggeredConditionalOrders( - ctx, - processProposerMatchesEvents.PlacedConditionalOrderIds, - lib.UniqueSliceToSet(processProposerMatchesEvents.GetPlacedStatefulCancellationOrderIds()), - lib.UniqueSliceToSet(expiredStatefulOrderIds), - ) + // // Before triggering conditional orders, add newly-placed conditional orders to the clob keeper's + // // in-memory UntriggeredConditionalOrders data structure to allow conditional orders to + // // trigger in the same block they are placed. Skip triggering orders which have been cancelled + // // or expired. + // // TODO(CLOB-773) Support conditional order replacements. Ensure replacements are de-duplicated. + // keeper.AddUntriggeredConditionalOrders( + // ctx, + // processProposerMatchesEvents.PlacedConditionalOrderIds, + // lib.UniqueSliceToSet(processProposerMatchesEvents.GetPlacedStatefulCancellationOrderIds()), + // lib.UniqueSliceToSet(expiredStatefulOrderIds), + // ) // Poll out all triggered conditional orders from `UntriggeredConditionalOrders` and update state. triggeredConditionalOrderIds := keeper.MaybeTriggerConditionalOrders(ctx) diff --git a/protocol/x/clob/abci_test.go b/protocol/x/clob/abci_test.go index 466489338a..300052d28a 100644 --- a/protocol/x/clob/abci_test.go +++ b/protocol/x/clob/abci_test.go @@ -247,16 +247,16 @@ func TestEndBlocker_Success(t *testing.T) { ) } - ks.ClobKeeper.UntriggeredConditionalOrders = map[types.ClobPairId]*keeper.UntriggeredConditionalOrders{ - constants.ClobPair_Btc.GetClobPairId(): { - OrdersToTriggerWhenOraclePriceLTETriggerPrice: []types.Order{orderToPrune1, orderToPrune2, orderToPrune4}, - OrdersToTriggerWhenOraclePriceGTETriggerPrice: []types.Order{}, - }, - constants.ClobPair_Eth.GetClobPairId(): { - OrdersToTriggerWhenOraclePriceLTETriggerPrice: []types.Order{}, - OrdersToTriggerWhenOraclePriceGTETriggerPrice: []types.Order{orderToPrune3}, - }, - } + // ks.ClobKeeper.UntriggeredConditionalOrders = map[types.ClobPairId]*keeper.UntriggeredConditionalOrders{ + // constants.ClobPair_Btc.GetClobPairId(): { + // OrdersToTriggerWhenOraclePriceLTETriggerPrice: []types.Order{orderToPrune1, orderToPrune2, orderToPrune4}, + // OrdersToTriggerWhenOraclePriceGTETriggerPrice: []types.Order{}, + // }, + // constants.ClobPair_Eth.GetClobPairId(): { + // OrdersToTriggerWhenOraclePriceLTETriggerPrice: []types.Order{}, + // OrdersToTriggerWhenOraclePriceGTETriggerPrice: []types.Order{orderToPrune3}, + // }, + // } ks.ClobKeeper.MustSetProcessProposerMatchesEvents( ctx, @@ -366,43 +366,43 @@ func TestEndBlocker_Success(t *testing.T) { }) require.NoError(t, err) - ks.ClobKeeper.UntriggeredConditionalOrders = map[types.ClobPairId]*keeper.UntriggeredConditionalOrders{ - constants.ClobPair_Btc.GetClobPairId(): { - // 10 oracle price subticks triggers 3 orders here. - OrdersToTriggerWhenOraclePriceLTETriggerPrice: []types.Order{ - constants.ConditionalOrder_Alice_Num0_Id0_Clob0_Buy5_Price10_GTBT15_TakeProfit10, - constants.ConditionalOrder_Alice_Num0_Id1_Clob0_Buy15_Price10_GTBT15_TakeProfit5, - constants.ConditionalOrder_Alice_Num0_Id2_Clob0_Buy20_Price10_GTBT15_TakeProfit10, - constants.ConditionalOrder_Alice_Num0_Id3_Clob0_Sell25_Price10_GTBT15_StopLoss10, - }, - // 10 oracle price subticks triggers no orders here. - OrdersToTriggerWhenOraclePriceGTETriggerPrice: []types.Order{ - constants.ConditionalOrder_Alice_Num0_Id0_Clob0_Buy5_Price20_GTBT15_StopLoss20, - constants.ConditionalOrder_Alice_Num0_Id1_Clob0_Buy15_Price25_GTBT15_StopLoss25, - constants.ConditionalOrder_Alice_Num0_Id2_Clob0_Sell20_Price20_GTBT15_TakeProfit20, - constants.ConditionalOrder_Alice_Num0_Id3_Clob0_Buy25_Price25_GTBT15_StopLoss25, - }, - }, - constants.ClobPair_Eth.GetClobPairId(): { - // 35 oracle price subticks triggers no orders here. - OrdersToTriggerWhenOraclePriceLTETriggerPrice: []types.Order{ - constants.ConditionalOrder_Alice_Num0_Id0_Clob1_Buy5_Price10_GTBT15_TakeProfit30, - }, - // 35 oracle price subticks triggers one order here. - OrdersToTriggerWhenOraclePriceGTETriggerPrice: []types.Order{ - constants.ConditionalOrder_Alice_Num0_Id3_Clob1_Buy25_Price10_GTBT15_StopLoss20, - }, - }, - } - - for _, untrigCondOrders := range ks.ClobKeeper.UntriggeredConditionalOrders { - for _, conditionalOrder := range untrigCondOrders.OrdersToTriggerWhenOraclePriceGTETriggerPrice { - ks.ClobKeeper.SetLongTermOrderPlacement(ctx, conditionalOrder, blockHeight) - } - for _, conditionalOrder := range untrigCondOrders.OrdersToTriggerWhenOraclePriceLTETriggerPrice { - ks.ClobKeeper.SetLongTermOrderPlacement(ctx, conditionalOrder, blockHeight) - } - } + // ks.ClobKeeper.UntriggeredConditionalOrders = map[types.ClobPairId]*keeper.UntriggeredConditionalOrders{ + // constants.ClobPair_Btc.GetClobPairId(): { + // // 10 oracle price subticks triggers 3 orders here. + // OrdersToTriggerWhenOraclePriceLTETriggerPrice: []types.Order{ + // constants.ConditionalOrder_Alice_Num0_Id0_Clob0_Buy5_Price10_GTBT15_TakeProfit10, + // constants.ConditionalOrder_Alice_Num0_Id1_Clob0_Buy15_Price10_GTBT15_TakeProfit5, + // constants.ConditionalOrder_Alice_Num0_Id2_Clob0_Buy20_Price10_GTBT15_TakeProfit10, + // constants.ConditionalOrder_Alice_Num0_Id3_Clob0_Sell25_Price10_GTBT15_StopLoss10, + // }, + // // 10 oracle price subticks triggers no orders here. + // OrdersToTriggerWhenOraclePriceGTETriggerPrice: []types.Order{ + // constants.ConditionalOrder_Alice_Num0_Id0_Clob0_Buy5_Price20_GTBT15_StopLoss20, + // constants.ConditionalOrder_Alice_Num0_Id1_Clob0_Buy15_Price25_GTBT15_StopLoss25, + // constants.ConditionalOrder_Alice_Num0_Id2_Clob0_Sell20_Price20_GTBT15_TakeProfit20, + // constants.ConditionalOrder_Alice_Num0_Id3_Clob0_Buy25_Price25_GTBT15_StopLoss25, + // }, + // }, + // constants.ClobPair_Eth.GetClobPairId(): { + // // 35 oracle price subticks triggers no orders here. + // OrdersToTriggerWhenOraclePriceLTETriggerPrice: []types.Order{ + // constants.ConditionalOrder_Alice_Num0_Id0_Clob1_Buy5_Price10_GTBT15_TakeProfit30, + // }, + // // 35 oracle price subticks triggers one order here. + // OrdersToTriggerWhenOraclePriceGTETriggerPrice: []types.Order{ + // constants.ConditionalOrder_Alice_Num0_Id3_Clob1_Buy25_Price10_GTBT15_StopLoss20, + // }, + // }, + // } + + // for _, untrigCondOrders := range ks.ClobKeeper.UntriggeredConditionalOrders { + // for _, conditionalOrder := range untrigCondOrders.OrdersToTriggerWhenOraclePriceGTETriggerPrice { + // ks.ClobKeeper.SetLongTermOrderPlacement(ctx, conditionalOrder, blockHeight) + // } + // for _, conditionalOrder := range untrigCondOrders.OrdersToTriggerWhenOraclePriceLTETriggerPrice { + // ks.ClobKeeper.SetLongTermOrderPlacement(ctx, conditionalOrder, blockHeight) + // } + // } ks.ClobKeeper.MustSetProcessProposerMatchesEvents( ctx, @@ -815,13 +815,13 @@ func TestEndBlocker_Success(t *testing.T) { require.False(t, exists) } - if tc.expectedUntriggeredConditionalOrders != nil { - require.Equal( - t, - tc.expectedUntriggeredConditionalOrders, - ks.ClobKeeper.UntriggeredConditionalOrders, - ) - } + // if tc.expectedUntriggeredConditionalOrders != nil { + // require.Equal( + // t, + // tc.expectedUntriggeredConditionalOrders, + // ks.ClobKeeper.UntriggeredConditionalOrders, + // ) + // } // Assert that the necessary off-chain indexer events have been added. mockIndexerEventManager.AssertExpectations(t) diff --git a/protocol/x/clob/keeper/clob_pair_test.go b/protocol/x/clob/keeper/clob_pair_test.go index 4ae6fb3e14..7c89c2df37 100644 --- a/protocol/x/clob/keeper/clob_pair_test.go +++ b/protocol/x/clob/keeper/clob_pair_test.go @@ -21,7 +21,6 @@ import ( "github.com/dydxprotocol/v4-chain/protocol/testutil/nullify" perptest "github.com/dydxprotocol/v4-chain/protocol/testutil/perpetuals" pricestest "github.com/dydxprotocol/v4-chain/protocol/testutil/prices" - "github.com/dydxprotocol/v4-chain/protocol/x/clob/keeper" "github.com/dydxprotocol/v4-chain/protocol/x/clob/memclob" "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" "github.com/dydxprotocol/v4-chain/protocol/x/perpetuals" @@ -684,9 +683,9 @@ func TestUpdateClobPair_FinalSettlement(t *testing.T) { } } - ks.ClobKeeper.UntriggeredConditionalOrders = map[types.ClobPairId]*keeper.UntriggeredConditionalOrders{ - 0: {}, // leaving blank, orders here don't matter in particular since we clear the whole key - } + // ks.ClobKeeper.UntriggeredConditionalOrders = map[types.ClobPairId]*keeper.UntriggeredConditionalOrders{ + // 0: {}, // leaving blank, orders here don't matter in particular since we clear the whole key + // } clobPair.Status = types.ClobPair_STATUS_FINAL_SETTLEMENT err = ks.ClobKeeper.UpdateClobPair(ks.Ctx, clobPair) @@ -712,9 +711,9 @@ func TestUpdateClobPair_FinalSettlement(t *testing.T) { ppme.RemovedStatefulOrderIds, ) - // Verify UntriggeredConditionalOrders is cleared. - _, found := ks.ClobKeeper.UntriggeredConditionalOrders[0] - require.False(t, found) + // // Verify UntriggeredConditionalOrders is cleared. + // _, found := ks.ClobKeeper.UntriggeredConditionalOrders[0] + // require.False(t, found) } func TestUpdateClobPair(t *testing.T) { diff --git a/protocol/x/clob/keeper/final_settlement.go b/protocol/x/clob/keeper/final_settlement.go index a553985cac..9bc0a2f876 100644 --- a/protocol/x/clob/keeper/final_settlement.go +++ b/protocol/x/clob/keeper/final_settlement.go @@ -15,8 +15,8 @@ func (k Keeper) mustTransitionToFinalSettlement(ctx sdk.Context, clobPairId type // Forcefully cancel all stateful orders from state for this clob pair. k.mustCancelStatefulOrdersForFinalSettlement(ctx, clobPairId) - // Delete untriggered conditional orders for this clob pair from memory. - delete(k.UntriggeredConditionalOrders, clobPairId) + // // Delete untriggered conditional orders for this clob pair from memory. + // delete(k.UntriggeredConditionalOrders, clobPairId) } // mustCancelStatefulOrdersForFinalSettlement forcefully cancels all stateful orders diff --git a/protocol/x/clob/keeper/keeper.go b/protocol/x/clob/keeper/keeper.go index 043c2f3d7f..0ae7316c57 100644 --- a/protocol/x/clob/keeper/keeper.go +++ b/protocol/x/clob/keeper/keeper.go @@ -28,9 +28,8 @@ type ( transientStoreKey storetypes.StoreKey authorities map[string]struct{} - MemClob types.MemClob - UntriggeredConditionalOrders map[types.ClobPairId]*UntriggeredConditionalOrders - PerpetualIdToClobPairId map[uint32][]types.ClobPairId + MemClob types.MemClob + PerpetualIdToClobPairId map[uint32][]types.ClobPairId subaccountsKeeper types.SubaccountsKeeper assetsKeeper types.AssetsKeeper @@ -92,28 +91,27 @@ func NewKeeper( daemonLiquidationInfo *liquidationtypes.DaemonLiquidationInfo, ) *Keeper { keeper := &Keeper{ - cdc: cdc, - storeKey: storeKey, - memKey: memKey, - transientStoreKey: liquidationsStoreKey, - authorities: lib.UniqueSliceToSet(authorities), - MemClob: memClob, - UntriggeredConditionalOrders: make(map[types.ClobPairId]*UntriggeredConditionalOrders), - PerpetualIdToClobPairId: make(map[uint32][]types.ClobPairId), - subaccountsKeeper: subaccountsKeeper, - assetsKeeper: assetsKeeper, - blockTimeKeeper: blockTimeKeeper, - bankKeeper: bankKeeper, - feeTiersKeeper: feeTiersKeeper, - perpetualsKeeper: perpetualsKeeper, - pricesKeeper: pricesKeeper, - statsKeeper: statsKeeper, - rewardsKeeper: rewardsKeeper, - indexerEventManager: indexerEventManager, - streamingManager: grpcStreamingManager, - memStoreInitialized: &atomic.Bool{}, // False by default. - initialized: &atomic.Bool{}, // False by default. - txDecoder: txDecoder, + cdc: cdc, + storeKey: storeKey, + memKey: memKey, + transientStoreKey: liquidationsStoreKey, + authorities: lib.UniqueSliceToSet(authorities), + MemClob: memClob, + PerpetualIdToClobPairId: make(map[uint32][]types.ClobPairId), + subaccountsKeeper: subaccountsKeeper, + assetsKeeper: assetsKeeper, + blockTimeKeeper: blockTimeKeeper, + bankKeeper: bankKeeper, + feeTiersKeeper: feeTiersKeeper, + perpetualsKeeper: perpetualsKeeper, + pricesKeeper: pricesKeeper, + statsKeeper: statsKeeper, + rewardsKeeper: rewardsKeeper, + indexerEventManager: indexerEventManager, + streamingManager: grpcStreamingManager, + memStoreInitialized: &atomic.Bool{}, // False by default. + initialized: &atomic.Bool{}, // False by default. + txDecoder: txDecoder, mevTelemetryConfig: MevTelemetryConfig{ Enabled: clobFlags.MevTelemetryEnabled, Hosts: clobFlags.MevTelemetryHosts, @@ -190,7 +188,7 @@ func (k Keeper) Initialize(ctx sdk.Context) { k.HydrateClobPairAndPerpetualMapping(checkCtx) // Initialize the untriggered conditional orders data structure with untriggered // conditional orders in state. - k.HydrateUntriggeredConditionalOrders(checkCtx) + // k.HydrateUntriggeredConditionalOrders(checkCtx) } // InitMemStore initializes the memstore of the `clob` keeper. diff --git a/protocol/x/clob/keeper/orders.go b/protocol/x/clob/keeper/orders.go index 9986580930..684d250ace 100644 --- a/protocol/x/clob/keeper/orders.go +++ b/protocol/x/clob/keeper/orders.go @@ -1243,37 +1243,28 @@ func (k Keeper) InitStatefulOrders( } } -// HydrateUntriggeredConditionalOrders inserts all untriggered conditional orders in state into the -// `UntriggeredConditionalOrders` data structure. Note that all untriggered conditional orders will -// be ordered by time priority. This function should only be called on application startup. -func (k Keeper) HydrateUntriggeredConditionalOrders( - ctx sdk.Context, -) { - defer telemetry.ModuleMeasureSince( - types.ModuleName, - time.Now(), - metrics.ConditionalOrderUntriggered, - metrics.Hydrate, - metrics.Latency, - ) - - // Get all untriggered conditional orders in state, ordered by time priority ascending order, - // and add them to the `UntriggeredConditionalOrders` data structure. - untriggeredConditionalOrders := k.GetAllUntriggeredConditionalOrders(ctx) - k.AddUntriggeredConditionalOrders( - ctx, - lib.MapSlice( - untriggeredConditionalOrders, - func(o types.Order) types.OrderId { - return o.OrderId - }, - ), - // Note both of these arguments are empty slices since the untriggered conditional orders - // shouldn't be expired or canceled. - map[types.OrderId]struct{}{}, - map[types.OrderId]struct{}{}, - ) -} +// // HydrateUntriggeredConditionalOrders inserts all untriggered conditional orders in state into the +// // `UntriggeredConditionalOrders` data structure. Note that all untriggered conditional orders will +// // be ordered by time priority. This function should only be called on application startup. +// func (k Keeper) HydrateUntriggeredConditionalOrders( +// ctx sdk.Context, +// ) { +// defer telemetry.ModuleMeasureSince( +// types.ModuleName, +// time.Now(), +// metrics.ConditionalOrderUntriggered, +// metrics.Hydrate, +// metrics.Latency, +// ) + +// // Get all untriggered conditional orders in state, ordered by time priority ascending order, +// // and add them to the `UntriggeredConditionalOrders` data structure. +// untriggeredConditionalOrders := k.GetAllUntriggeredConditionalOrders(ctx) +// untriggeredConditonals := GetInMemUntriggeredConditionalOrders( +// ctx, +// untriggeredConditionalOrders, +// ) +// } // sendOffchainMessagesWithTxHash sends all the `Message` in the offchainUpdates passed in along with // an additional header for the transaction hash passed in. diff --git a/protocol/x/clob/keeper/orders_test.go b/protocol/x/clob/keeper/orders_test.go index e3b27261f3..dec4f241ec 100644 --- a/protocol/x/clob/keeper/orders_test.go +++ b/protocol/x/clob/keeper/orders_test.go @@ -2171,10 +2171,10 @@ func TestHydrateUntriggeredConditionalOrdersInMemClob(t *testing.T) { untriggeredConditionalOrders.AddUntriggeredConditionalOrder(order) } - // Run the test and verify expectations. - ks.ClobKeeper.HydrateUntriggeredConditionalOrders(ks.Ctx) + // // Run the test and verify expectations. + // ks.ClobKeeper.HydrateUntriggeredConditionalOrders(ks.Ctx) - require.Equal(t, expectedUntriggeredConditionalOrders, ks.ClobKeeper.UntriggeredConditionalOrders) + // require.Equal(t, expectedUntriggeredConditionalOrders, ks.ClobKeeper.UntriggeredConditionalOrders) }) } } diff --git a/protocol/x/clob/keeper/untriggered_conditional_orders.go b/protocol/x/clob/keeper/untriggered_conditional_orders.go index 8ff6e3a52d..d21bd41c12 100644 --- a/protocol/x/clob/keeper/untriggered_conditional_orders.go +++ b/protocol/x/clob/keeper/untriggered_conditional_orders.go @@ -54,38 +54,23 @@ func (untriggeredOrders *UntriggeredConditionalOrders) IsEmpty() bool { // AddUntriggeredConditionalOrders takes in a list of newly-placed conditional order ids and adds them // to the in-memory UntriggeredConditionalOrders struct, filtering out orders that have been cancelled // or expired in the last block. This function is used in EndBlocker and on application startup. -func (k Keeper) AddUntriggeredConditionalOrders( +func GetInMemUntriggeredConditionalOrders( ctx sdk.Context, - placedConditionalOrderIds []types.OrderId, - placedStatefulCancellationOrderIds map[types.OrderId]struct{}, - expiredStatefulOrderIdsSet map[types.OrderId]struct{}, -) { - for _, orderId := range placedConditionalOrderIds { - _, isCancelled := placedStatefulCancellationOrderIds[orderId] - _, isExpired := expiredStatefulOrderIdsSet[orderId] - if isCancelled || isExpired { - continue - } + conditonalOrdersFromState []types.Order, +) map[types.ClobPairId]*UntriggeredConditionalOrders { + ret := make(map[types.ClobPairId]*UntriggeredConditionalOrders) - orderPlacement, exists := k.GetUntriggeredConditionalOrderPlacement(ctx, orderId) + for _, order := range conditonalOrdersFromState { + clobPairId := types.ClobPairId(order.GetClobPairId()) + untriggeredConditionalOrders, exists := ret[clobPairId] if !exists { - panic( - fmt.Sprintf( - "AddUntriggeredConditionalOrders: order placement does not exist in state for untriggered "+ - "conditional order id, OrderId %+v.", - orderId, - ), - ) + untriggeredConditionalOrders = NewUntriggeredConditionalOrders() + ret[clobPairId] = untriggeredConditionalOrders } - - clobPairId := types.ClobPairId(orderId.GetClobPairId()) - untriggeredConditionalOrders, exists := k.UntriggeredConditionalOrders[clobPairId] - if !exists { - untriggeredConditionalOrders = k.NewUntriggeredConditionalOrders() - k.UntriggeredConditionalOrders[clobPairId] = untriggeredConditionalOrders - } - untriggeredConditionalOrders.AddUntriggeredConditionalOrder(orderPlacement.GetOrder()) + untriggeredConditionalOrders.AddUntriggeredConditionalOrder(order) } + + return ret } // AddUntriggeredConditionalOrder adds an untriggered conditional order to the UntriggeredConditionalOrders @@ -126,53 +111,53 @@ func (untriggeredOrders *UntriggeredConditionalOrders) AddUntriggeredConditional // all respective orders from the in-memory `UntriggeredConditionalOrders` data structure. This data structure // stores untriggered orders in a map of ClobPairId -> []Order, so we first group orders by ClobPairId and then // call `UntriggeredConditionalOrders.RemoveExpiredUntriggeredConditionalOrders` on each ClobPairId. -func (k Keeper) PruneUntriggeredConditionalOrders( - expiredStatefulOrderIds []types.OrderId, - cancelledStatefulOrderIds []types.OrderId, -) { - // Merge lists of order ids. - orderIdsToPrune := lib.UniqueSliceToSet(expiredStatefulOrderIds) - for _, orderId := range cancelledStatefulOrderIds { - if _, exists := orderIdsToPrune[orderId]; exists { - panic( - fmt.Sprintf( - "PruneUntriggeredConditionalOrders: duplicate order id %+v in expired and "+ - "cancelled order lists", orderId, - ), - ) - } - orderIdsToPrune[orderId] = struct{}{} - } - - prunableUntriggeredConditionalOrderIdsByClobPair := make(map[types.ClobPairId][]types.OrderId) - for orderId := range orderIdsToPrune { - // If the order id is conditional, add to prunable list of untriggered order ids. - // Triggered conditional orders will be effectively ignored during removal as they are not part of - // UntriggeredConditionalOrders anymore. No need to filter out here, we can avoid memstore reads. - if orderId.IsConditionalOrder() { - clobPairId := types.ClobPairId(orderId.GetClobPairId()) - if _, exists := prunableUntriggeredConditionalOrderIdsByClobPair[clobPairId]; !exists { - prunableUntriggeredConditionalOrderIdsByClobPair[clobPairId] = []types.OrderId{} - } - - prunableUntriggeredConditionalOrderIdsByClobPair[clobPairId] = append( - prunableUntriggeredConditionalOrderIdsByClobPair[clobPairId], - orderId, - ) - } - } - - for clobPairId := range prunableUntriggeredConditionalOrderIdsByClobPair { - if untriggeredConditionalOrders, exists := k.UntriggeredConditionalOrders[clobPairId]; exists { - untriggeredConditionalOrders.RemoveUntriggeredConditionalOrders( - prunableUntriggeredConditionalOrderIdsByClobPair[clobPairId], - ) - if untriggeredConditionalOrders.IsEmpty() { - delete(k.UntriggeredConditionalOrders, clobPairId) - } - } - } -} +// func (k Keeper) PruneUntriggeredConditionalOrders( +// expiredStatefulOrderIds []types.OrderId, +// cancelledStatefulOrderIds []types.OrderId, +// ) { +// // Merge lists of order ids. +// orderIdsToPrune := lib.UniqueSliceToSet(expiredStatefulOrderIds) +// for _, orderId := range cancelledStatefulOrderIds { +// if _, exists := orderIdsToPrune[orderId]; exists { +// panic( +// fmt.Sprintf( +// "PruneUntriggeredConditionalOrders: duplicate order id %+v in expired and "+ +// "cancelled order lists", orderId, +// ), +// ) +// } +// orderIdsToPrune[orderId] = struct{}{} +// } + +// prunableUntriggeredConditionalOrderIdsByClobPair := make(map[types.ClobPairId][]types.OrderId) +// for orderId := range orderIdsToPrune { +// // If the order id is conditional, add to prunable list of untriggered order ids. +// // Triggered conditional orders will be effectively ignored during removal as they are not part of +// // UntriggeredConditionalOrders anymore. No need to filter out here, we can avoid memstore reads. +// if orderId.IsConditionalOrder() { +// clobPairId := types.ClobPairId(orderId.GetClobPairId()) +// if _, exists := prunableUntriggeredConditionalOrderIdsByClobPair[clobPairId]; !exists { +// prunableUntriggeredConditionalOrderIdsByClobPair[clobPairId] = []types.OrderId{} +// } + +// prunableUntriggeredConditionalOrderIdsByClobPair[clobPairId] = append( +// prunableUntriggeredConditionalOrderIdsByClobPair[clobPairId], +// orderId, +// ) +// } +// } + +// for clobPairId := range prunableUntriggeredConditionalOrderIdsByClobPair { +// if untriggeredConditionalOrders, exists := k.UntriggeredConditionalOrders[clobPairId]; exists { +// untriggeredConditionalOrders.RemoveUntriggeredConditionalOrders( +// prunableUntriggeredConditionalOrderIdsByClobPair[clobPairId], +// ) +// if untriggeredConditionalOrders.IsEmpty() { +// delete(k.UntriggeredConditionalOrders, clobPairId) +// } +// } +// } +// } // RemoveUntriggeredConditionalOrders removes a list of order ids from the `UntriggeredConditionalOrders` // data structure. This function will panic if the order ids contained involve more than one ClobPairId. @@ -277,15 +262,21 @@ func (k Keeper) MaybeTriggerConditionalOrders(ctx sdk.Context) (allTriggeredOrde time.Now(), ) + allUntriggerred := k.GetAllUntriggeredConditionalOrders(ctx) + untriggeredConditonals := GetInMemUntriggeredConditionalOrders( + ctx, + allUntriggerred, + ) + // Sort the keys for the untriggered conditional orders struct. We need to trigger // the conditional orders in an ordered way to have deterministic state writes. - sortedKeys := lib.GetSortedKeys[types.SortedClobPairId](k.UntriggeredConditionalOrders) + sortedKeys := lib.GetSortedKeys[types.SortedClobPairId](untriggeredConditonals) allTriggeredOrderIds = make([]types.OrderId, 0) // For all clob pair ids in UntriggeredConditionalOrders, fetch the updated // oracle price and poll out triggered conditional orders. for _, clobPairId := range sortedKeys { - untriggered := k.UntriggeredConditionalOrders[clobPairId] + untriggered := untriggeredConditonals[clobPairId] clobPair, found := k.GetClobPair(ctx, clobPairId) if !found { panic( @@ -319,8 +310,8 @@ func (k Keeper) MaybeTriggerConditionalOrders(ctx sdk.Context) (allTriggeredOrde allTriggeredOrderIds = append(allTriggeredOrderIds, triggered...) } - // Set the modified untriggeredConditionalOrders back on the keeper field. - k.UntriggeredConditionalOrders[clobPairId] = untriggered + // // Set the modified untriggeredConditionalOrders back on the keeper field. + // untriggeredConditonals[clobPairId] = untriggered // Gauge the number of untriggered orders. metrics.SetGaugeWithLabels( diff --git a/protocol/x/clob/keeper/untriggered_conditional_orders_test.go b/protocol/x/clob/keeper/untriggered_conditional_orders_test.go index db84fe6f04..fa23a06435 100644 --- a/protocol/x/clob/keeper/untriggered_conditional_orders_test.go +++ b/protocol/x/clob/keeper/untriggered_conditional_orders_test.go @@ -2,10 +2,11 @@ package keeper_test import ( "fmt" - testApp "github.com/dydxprotocol/v4-chain/protocol/testutil/app" "math/big" "testing" + testApp "github.com/dydxprotocol/v4-chain/protocol/testutil/app" + "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" "github.com/dydxprotocol/v4-chain/protocol/x/clob/keeper" "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" @@ -91,7 +92,7 @@ func TestAddUntriggeredConditionalOrder(t *testing.T) { tApp := testApp.NewTestAppBuilder(t).Build() tApp.InitChain() untriggeredConditionalOrders := tApp.App.ClobKeeper.NewUntriggeredConditionalOrders() - tApp.App.ClobKeeper.UntriggeredConditionalOrders[0] = untriggeredConditionalOrders + // tApp.App.ClobKeeper.UntriggeredConditionalOrders[0] = untriggeredConditionalOrders for _, order := range tc.conditionalOrdersToAdd { untriggeredConditionalOrders.AddUntriggeredConditionalOrder(order) @@ -197,7 +198,7 @@ func TestRemoveUntriggeredConditionalOrders(t *testing.T) { tApp := testApp.NewTestAppBuilder(t).Build() tApp.InitChain() untriggeredConditionalOrders := tApp.App.ClobKeeper.NewUntriggeredConditionalOrders() - tApp.App.ClobKeeper.UntriggeredConditionalOrders[0] = untriggeredConditionalOrders + // tApp.App.ClobKeeper.UntriggeredConditionalOrders[0] = untriggeredConditionalOrders for _, order := range tc.conditionalOrdersToAdd { untriggeredConditionalOrders.AddUntriggeredConditionalOrder(order)