Skip to content

Commit

Permalink
Optimize OffsetSubaccountPerpetualPosition subaccount iteration (#906)
Browse files Browse the repository at this point in the history
* Optimize  subaccount iteration

* fix test

* only get relevant subaccounts for final settlement

* start from a random subaccount

* fix test

* fix test
  • Loading branch information
jayy04 committed Dec 22, 2023
1 parent 538fe2b commit cc235f0
Show file tree
Hide file tree
Showing 18 changed files with 260 additions and 336 deletions.
5 changes: 4 additions & 1 deletion protocol/app/ante_whitebox_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package app

import (
"github.com/dydxprotocol/v4-chain/protocol/lib"
"reflect"
"testing"

"github.com/dydxprotocol/v4-chain/protocol/lib"

delaymsgmoduletypes "github.com/dydxprotocol/v4-chain/protocol/x/delaymsg/types"

"github.com/dydxprotocol/v4-chain/protocol/x/clob/rate_limit"
Expand All @@ -15,6 +16,7 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper"
liquidationtypes "github.com/dydxprotocol/v4-chain/protocol/daemons/server/types/liquidations"
libante "github.com/dydxprotocol/v4-chain/protocol/lib/ante"
clobante "github.com/dydxprotocol/v4-chain/protocol/x/clob/ante"
"github.com/dydxprotocol/v4-chain/protocol/x/clob/flags"
Expand Down Expand Up @@ -72,6 +74,7 @@ func newTestHandlerOptions() HandlerOptions {
flags.GetDefaultClobFlags(),
rate_limit.NewNoOpRateLimiter[*types.MsgPlaceOrder](),
rate_limit.NewNoOpRateLimiter[*types.MsgCancelOrder](),
liquidationtypes.NewDaemonLiquidationInfo(),
)
return HandlerOptions{
HandlerOptions: ante.HandlerOptions{
Expand Down
2 changes: 1 addition & 1 deletion protocol/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -903,14 +903,14 @@ func New(
clobFlags,
rate_limit.NewPanicRateLimiter[*clobmoduletypes.MsgPlaceOrder](),
rate_limit.NewPanicRateLimiter[*clobmoduletypes.MsgCancelOrder](),
daemonLiquidationInfo,
)
clobModule := clobmodule.NewAppModule(
appCodec,
app.ClobKeeper,
app.AccountKeeper,
app.BankKeeper,
app.SubaccountsKeeper,
daemonLiquidationInfo,
)
app.PerpetualsKeeper.SetClobKeeper(app.ClobKeeper)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,37 @@ func (ls *DaemonLiquidationInfo) UpdateSubaccountsWithPositions(
}
}

// GetSubaccountsWithPositions returns the list of subaccount ids with open positions.
func (ls *DaemonLiquidationInfo) GetSubaccountsWithPositions() map[uint32]*clobtypes.SubaccountOpenPositionInfo {
// GetSubaccountsWithOpenPositions returns the list of subaccount ids with open positions for a perpetual.
func (ls *DaemonLiquidationInfo) GetSubaccountsWithOpenPositions(
perpetualId uint32,
) []satypes.SubaccountId {
ls.Lock()
defer ls.Unlock()

result := make(map[uint32]*clobtypes.SubaccountOpenPositionInfo)
for perpetualId, info := range ls.subaccountsWithPositions {
clone := &clobtypes.SubaccountOpenPositionInfo{
PerpetualId: perpetualId,
SubaccountsWithLongPosition: make([]satypes.SubaccountId, len(info.SubaccountsWithLongPosition)),
SubaccountsWithShortPosition: make([]satypes.SubaccountId, len(info.SubaccountsWithShortPosition)),
result := make([]satypes.SubaccountId, 0)
if info, ok := ls.subaccountsWithPositions[perpetualId]; ok {
result = append(result, info.SubaccountsWithLongPosition...)
result = append(result, info.SubaccountsWithShortPosition...)
}
return result
}

// GetSubaccountsWithOpenPositionsOnSide returns the list of subaccount ids with open positions
// on a specific side for a perpetual.
func (ls *DaemonLiquidationInfo) GetSubaccountsWithOpenPositionsOnSide(
perpetualId uint32,
isLong bool,
) []satypes.SubaccountId {
ls.Lock()
defer ls.Unlock()

result := make([]satypes.SubaccountId, 0)
if info, ok := ls.subaccountsWithPositions[perpetualId]; ok {
if isLong {
result = append(result, info.SubaccountsWithLongPosition...)
} else {
result = append(result, info.SubaccountsWithShortPosition...)
}
copy(clone.SubaccountsWithLongPosition, info.SubaccountsWithLongPosition)
copy(clone.SubaccountsWithShortPosition, info.SubaccountsWithShortPosition)
result[perpetualId] = clone
}
return result
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func TestNewDaemonLiquidationInfo(t *testing.T) {
ls := liquidationstypes.NewDaemonLiquidationInfo()
require.Empty(t, ls.GetLiquidatableSubaccountIds())
require.Empty(t, ls.GetNegativeTncSubaccountIds())
require.Empty(t, ls.GetSubaccountsWithPositions())
require.Empty(t, ls.GetSubaccountsWithOpenPositions(0))
}

func TestLiquidatableSubaccountIds_Multiple_Reads(t *testing.T) {
Expand Down Expand Up @@ -62,12 +62,13 @@ func TestSubaccountsWithOpenPositions_Multiple_Reads(t *testing.T) {
input := []clobtypes.SubaccountOpenPositionInfo{info}
ls.UpdateSubaccountsWithPositions(input)

expected := map[uint32]*clobtypes.SubaccountOpenPositionInfo{
0: &info,
expected := []satypes.SubaccountId{
constants.Alice_Num1,
constants.Bob_Num0,
}
require.Equal(t, expected, ls.GetSubaccountsWithPositions())
require.Equal(t, expected, ls.GetSubaccountsWithPositions())
require.Equal(t, expected, ls.GetSubaccountsWithPositions())
require.Equal(t, expected, ls.GetSubaccountsWithOpenPositions(0))
require.Equal(t, expected, ls.GetSubaccountsWithOpenPositions(0))
require.Equal(t, expected, ls.GetSubaccountsWithOpenPositions(0))
}

func TestLiquidatableSubaccountIds_Multiple_Writes(t *testing.T) {
Expand Down Expand Up @@ -118,7 +119,7 @@ func TestNegativeTncSubaccounts_Multiple_Writes(t *testing.T) {

func TestSubaccountsWithOpenPositions_Multiple_Writes(t *testing.T) {
ls := liquidationstypes.NewDaemonLiquidationInfo()
require.Empty(t, ls.GetSubaccountsWithPositions())
require.Empty(t, ls.GetSubaccountsWithOpenPositions(0))

info := clobtypes.SubaccountOpenPositionInfo{
PerpetualId: 0,
Expand All @@ -132,10 +133,11 @@ func TestSubaccountsWithOpenPositions_Multiple_Writes(t *testing.T) {

input := []clobtypes.SubaccountOpenPositionInfo{info}
ls.UpdateSubaccountsWithPositions(input)
expected := map[uint32]*clobtypes.SubaccountOpenPositionInfo{
0: &info,
expected := []satypes.SubaccountId{
constants.Alice_Num1,
constants.Bob_Num0,
}
require.Equal(t, expected, ls.GetSubaccountsWithPositions())
require.Equal(t, expected, ls.GetSubaccountsWithOpenPositions(0))

info2 := clobtypes.SubaccountOpenPositionInfo{
PerpetualId: 0,
Expand All @@ -149,10 +151,11 @@ func TestSubaccountsWithOpenPositions_Multiple_Writes(t *testing.T) {

input2 := []clobtypes.SubaccountOpenPositionInfo{info2}
ls.UpdateSubaccountsWithPositions(input2)
expected = map[uint32]*clobtypes.SubaccountOpenPositionInfo{
0: &info2,
expected = []satypes.SubaccountId{
constants.Carl_Num0,
constants.Dave_Num0,
}
require.Equal(t, expected, ls.GetSubaccountsWithPositions())
require.Equal(t, expected, ls.GetSubaccountsWithOpenPositions(0))

info3 := clobtypes.SubaccountOpenPositionInfo{
PerpetualId: 0,
Expand All @@ -166,10 +169,11 @@ func TestSubaccountsWithOpenPositions_Multiple_Writes(t *testing.T) {

input3 := []clobtypes.SubaccountOpenPositionInfo{info3}
ls.UpdateSubaccountsWithPositions(input3)
expected = map[uint32]*clobtypes.SubaccountOpenPositionInfo{
0: &info3,
expected = []satypes.SubaccountId{
constants.Dave_Num1,
constants.Alice_Num1,
}
require.Equal(t, expected, ls.GetSubaccountsWithPositions())
require.Equal(t, expected, ls.GetSubaccountsWithOpenPositions(0))
}

func TestLiquidatableSubaccountIds_Empty_Update(t *testing.T) {
Expand Down Expand Up @@ -204,7 +208,7 @@ func TestNegativeTnc_Empty_Update(t *testing.T) {

func TestSubaccountsWithOpenPosition_Empty_Update(t *testing.T) {
ls := liquidationstypes.NewDaemonLiquidationInfo()
require.Empty(t, ls.GetSubaccountsWithPositions())
require.Empty(t, ls.GetSubaccountsWithOpenPositions(0))

info := clobtypes.SubaccountOpenPositionInfo{
PerpetualId: 0,
Expand All @@ -217,12 +221,13 @@ func TestSubaccountsWithOpenPosition_Empty_Update(t *testing.T) {
}
input := []clobtypes.SubaccountOpenPositionInfo{info}
ls.UpdateSubaccountsWithPositions(input)
expected := map[uint32]*clobtypes.SubaccountOpenPositionInfo{
0: &info,
expected := []satypes.SubaccountId{
constants.Alice_Num1,
constants.Bob_Num0,
}
require.Equal(t, expected, ls.GetSubaccountsWithPositions())
require.Equal(t, expected, ls.GetSubaccountsWithOpenPositions(0))

input2 := []clobtypes.SubaccountOpenPositionInfo{}
ls.UpdateSubaccountsWithPositions(input2)
require.Empty(t, ls.GetSubaccountsWithPositions())
require.Empty(t, ls.GetSubaccountsWithOpenPositions(0))
}
42 changes: 42 additions & 0 deletions protocol/testutil/clob/open_positions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package clob

import (
clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types"
satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types"
)

func GetOpenPositionsFromSubaccounts(
subaccounts []satypes.Subaccount,
) []clobtypes.SubaccountOpenPositionInfo {
positionMap := make(map[uint32]*clobtypes.SubaccountOpenPositionInfo)
for _, subaccount := range subaccounts {
for _, position := range subaccount.PerpetualPositions {
info, ok := positionMap[position.PerpetualId]
if !ok {
info = &clobtypes.SubaccountOpenPositionInfo{
PerpetualId: position.PerpetualId,
SubaccountsWithLongPosition: make([]satypes.SubaccountId, 0),
SubaccountsWithShortPosition: make([]satypes.SubaccountId, 0),
}
positionMap[position.PerpetualId] = info
}
if position.GetIsLong() {
info.SubaccountsWithLongPosition = append(
info.SubaccountsWithLongPosition,
*subaccount.Id,
)
} else {
info.SubaccountsWithShortPosition = append(
info.SubaccountsWithShortPosition,
*subaccount.Id,
)
}
}
}

positionSlice := make([]clobtypes.SubaccountOpenPositionInfo, 0)
for _, info := range positionMap {
positionSlice = append(positionSlice, *info)
}
return positionSlice
}
2 changes: 2 additions & 0 deletions protocol/testutil/keeper/clob.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
liquidationtypes "github.com/dydxprotocol/v4-chain/protocol/daemons/server/types/liquidations"
asskeeper "github.com/dydxprotocol/v4-chain/protocol/x/assets/keeper"
blocktimekeeper "github.com/dydxprotocol/v4-chain/protocol/x/blocktime/keeper"
"github.com/dydxprotocol/v4-chain/protocol/x/clob/keeper"
Expand Down Expand Up @@ -217,6 +218,7 @@ func createClobKeeper(
flags.GetDefaultClobFlags(),
rate_limit.NewNoOpRateLimiter[*types.MsgPlaceOrder](),
rate_limit.NewNoOpRateLimiter[*types.MsgCancelOrder](),
liquidationtypes.NewDaemonLiquidationInfo(),
)
k.SetAnteHandler(constants.EmptyAnteHandler)

Expand Down
10 changes: 2 additions & 8 deletions protocol/x/clob/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
liquidationtypes "github.com/dydxprotocol/v4-chain/protocol/daemons/server/types/liquidations"
indexerevents "github.com/dydxprotocol/v4-chain/protocol/indexer/events"
"github.com/dydxprotocol/v4-chain/protocol/indexer/indexer_manager"
indexershared "github.com/dydxprotocol/v4-chain/protocol/indexer/shared"
Expand Down Expand Up @@ -117,7 +116,6 @@ func EndBlocker(
func PrepareCheckState(
ctx sdk.Context,
keeper *keeper.Keeper,
daemonLiquidationInfo *liquidationtypes.DaemonLiquidationInfo,
) {
// Get the events generated from processing the matches in the latest block.
processProposerMatchesEvents := keeper.GetProcessProposerMatchesEvents(ctx)
Expand Down Expand Up @@ -197,20 +195,16 @@ func PrepareCheckState(
}

// 6. Get all potentially liquidatable subaccount IDs and attempt to liquidate them.
liquidatableSubaccountIds := daemonLiquidationInfo.GetLiquidatableSubaccountIds()
liquidatableSubaccountIds := keeper.DaemonLiquidationInfo.GetLiquidatableSubaccountIds()
subaccountsToDeleverage, err := keeper.LiquidateSubaccountsAgainstOrderbook(ctx, liquidatableSubaccountIds)
if err != nil {
panic(err)
}
subaccountPositionInfo := daemonLiquidationInfo.GetSubaccountsWithPositions()
// Add subaccounts with open positions in final settlement markets to the slice of subaccounts/perps
// to be deleveraged.
subaccountsToDeleverage = append(
subaccountsToDeleverage,
keeper.GetSubaccountsWithPositionsInFinalSettlementMarkets(
ctx,
subaccountPositionInfo,
)...,
keeper.GetSubaccountsWithPositionsInFinalSettlementMarkets(ctx)...,
)

// 7. Deleverage subaccounts.
Expand Down
7 changes: 1 addition & 6 deletions protocol/x/clob/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/cosmos/cosmos-sdk/store/prefix"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
liquidationtypes "github.com/dydxprotocol/v4-chain/protocol/daemons/server/types/liquidations"
"github.com/dydxprotocol/v4-chain/protocol/mocks"
keepertest "github.com/dydxprotocol/v4-chain/protocol/testutil/keeper"
blocktimetypes "github.com/dydxprotocol/v4-chain/protocol/x/blocktime/types"
Expand Down Expand Up @@ -1099,7 +1098,6 @@ func TestPrepareCheckState_WithProcessProposerMatchesEventsWithBadBlockHeight(t
clob.PrepareCheckState(
ks.Ctx.WithBlockHeight(int64(blockHeight+1)),
ks.ClobKeeper,
liquidationtypes.NewDaemonLiquidationInfo(),
)
})
}
Expand All @@ -1126,7 +1124,6 @@ func TestCommitBlocker_WithProcessProposerMatchesEventsWithBadBlockHeight(t *tes
clob.PrepareCheckState(
ks.Ctx.WithBlockHeight(int64(blockHeight+1)),
ks.ClobKeeper,
liquidationtypes.NewDaemonLiquidationInfo(),
)
})
}
Expand Down Expand Up @@ -1475,14 +1472,12 @@ func TestPrepareCheckState(t *testing.T) {
}

// Set the liquidatable subaccount IDs.
liquidatableSubaccountIds := liquidationtypes.NewDaemonLiquidationInfo()
liquidatableSubaccountIds.UpdateLiquidatableSubaccountIds(tc.liquidatableSubaccounts)
ks.ClobKeeper.DaemonLiquidationInfo.UpdateLiquidatableSubaccountIds(tc.liquidatableSubaccounts)

// Run the test.
clob.PrepareCheckState(
ctx,
ks.ClobKeeper,
liquidatableSubaccountIds,
)

// Verify test expectations.
Expand Down

0 comments on commit cc235f0

Please sign in to comment.