From 1c35383e693fbd3372a54ca5ccf20171dc9d157b Mon Sep 17 00:00:00 2001 From: Jay Yu <103467857+jayy04@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:59:05 -0500 Subject: [PATCH 1/3] Move mem store hydration initialized flag to memstore --- protocol/x/clob/keeper/keeper.go | 33 +++++++++++++++++++++++--------- protocol/x/clob/types/keys.go | 3 +++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/protocol/x/clob/keeper/keeper.go b/protocol/x/clob/keeper/keeper.go index 4d2303bb0d5..c850726eaab 100644 --- a/protocol/x/clob/keeper/keeper.go +++ b/protocol/x/clob/keeper/keeper.go @@ -1,7 +1,6 @@ package keeper import ( - "errors" "fmt" "math/big" "sync/atomic" @@ -54,8 +53,7 @@ type ( streamingManager streamingtypes.FullNodeStreamingManager finalizeBlockEventStager finalizeblock.EventStager[*types.ClobStagedFinalizeBlockEvent] - initialized *atomic.Bool - memStoreInitialized *atomic.Bool + initialized *atomic.Bool Flags flags.ClobFlags @@ -124,7 +122,6 @@ func NewKeeper( accountPlusKeeper: accountPlusKeeper, indexerEventManager: indexerEventManager, streamingManager: streamingManager, - memStoreInitialized: &atomic.Bool{}, // False by default. initialized: &atomic.Bool{}, // False by default. txDecoder: txDecoder, mevTelemetryConfig: MevTelemetryConfig{ @@ -187,14 +184,16 @@ func (k Keeper) IsInitialized() bool { // Initialize hydrates the clob keeper with the necessary in memory data structures. func (k Keeper) Initialize(ctx sdk.Context) { + // Initialize memstore in clobKeeper with order fill amounts and stateful orders. + k.InitMemStore(ctx) + + // Code below hydrates the in memory data structures and is not rolled back even if + // the block execution is discarded by OE. Therefore, they are only called once. alreadyInitialized := k.initialized.Swap(true) if alreadyInitialized { return } - // Initialize memstore in clobKeeper with order fill amounts and stateful orders. - k.InitMemStore(ctx) - // Branch the context for hydration. // This means that new order matches from hydration will get added to the operations // queue but the corresponding state changes will be discarded. @@ -254,11 +253,14 @@ func (k Keeper) ProcessStagedFinalizeBlockEvents(ctx sdk.Context) { // InitMemStore initializes the memstore of the `clob` keeper. // This is called during app initialization in `app.go`, before any ABCI calls are received. func (k Keeper) InitMemStore(ctx sdk.Context) { - alreadyInitialized := k.memStoreInitialized.Swap(true) + alreadyInitialized := k.GetMemstoreInitialized(ctx) if alreadyInitialized { - panic(errors.New("Memory store already initialized and is not intended to be invoked more then once.")) + return } + // Set memstore initialized flag. + k.SetMemstoreInitialized(ctx) + memStore := ctx.KVStore(k.memKey) memStoreType := memStore.GetStoreType() if memStoreType != storetypes.StoreTypeMemory { @@ -307,6 +309,19 @@ func (k Keeper) InitMemStore(ctx sdk.Context) { } } +func (k Keeper) GetMemstoreInitialized(ctx sdk.Context) bool { + store := ctx.KVStore(k.memKey) + return store.Has([]byte(types.KeyMemstoreInitialized)) +} + +func (k Keeper) SetMemstoreInitialized(ctx sdk.Context) { + store := ctx.KVStore(k.memKey) + store.Set( + []byte(types.KeyMemstoreInitialized), + []byte{1}, + ) +} + // Sets the ante handler after it has been constructed. This breaks a cycle between // when the ante handler is constructed and when the clob keeper is constructed. func (k *Keeper) SetAnteHandler(anteHandler sdk.AnteHandler) { diff --git a/protocol/x/clob/types/keys.go b/protocol/x/clob/types/keys.go index a78fbea45ea..a5ccc8bb1c4 100644 --- a/protocol/x/clob/types/keys.go +++ b/protocol/x/clob/types/keys.go @@ -79,6 +79,9 @@ const ( // Memstore const ( + // KeyMemstoreInitialized is the key to check if the memstore has been initialized. + KeyMemstoreInitialized = "MemstoreInit" + // ProcessProposerMatchesEventsKey is the key to retrieve information about how to update // memclob state based on the latest block. ProcessProposerMatchesEventsKey = "ProposerEvents" From 6dcdcaedee96faeea32edc7396b01233ec096efe Mon Sep 17 00:00:00 2001 From: Jay Yu <103467857+jayy04@users.noreply.github.com> Date: Fri, 10 Jan 2025 20:43:21 -0500 Subject: [PATCH 2/3] fix test --- protocol/x/clob/keeper/keeper_test.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/protocol/x/clob/keeper/keeper_test.go b/protocol/x/clob/keeper/keeper_test.go index f92d00bc7bb..1c594dc323b 100644 --- a/protocol/x/clob/keeper/keeper_test.go +++ b/protocol/x/clob/keeper/keeper_test.go @@ -31,10 +31,7 @@ func TestInitMemStore_OnlyAllowedOnce(t *testing.T) { ks.ClobKeeper.InitMemStore(ks.Ctx) - // Initializing a second time causes a panic - require.Panics(t, func() { - ks.ClobKeeper.InitMemStore(ks.Ctx) - }) + require.True(t, ks.ClobKeeper.GetMemstoreInitialized(ks.Ctx)) } func TestInitMemStore_StatefulOrderCount(t *testing.T) { From b4629a913d30982c7588b8a548815b3d5f82f12c Mon Sep 17 00:00:00 2001 From: Jay Yu <103467857+jayy04@users.noreply.github.com> Date: Sat, 11 Jan 2025 08:55:53 -0500 Subject: [PATCH 3/3] comments --- protocol/mocks/ClobKeeper.go | 10 +++--- protocol/x/clob/ante/clob.go | 2 +- protocol/x/clob/ante/clob_test.go | 2 +- protocol/x/clob/keeper/keeper.go | 54 ++++++++++++++-------------- protocol/x/clob/types/clob_keeper.go | 2 +- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/protocol/mocks/ClobKeeper.go b/protocol/mocks/ClobKeeper.go index 84dd25c4545..efb28a25298 100644 --- a/protocol/mocks/ClobKeeper.go +++ b/protocol/mocks/ClobKeeper.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.46.0. DO NOT EDIT. +// Code generated by mockery v2.50.0. DO NOT EDIT. package mocks @@ -312,7 +312,7 @@ func (_m *ClobKeeper) GetFillablePrice(ctx types.Context, subaccountId subaccoun return r0, r1 } -// GetIndexerEventManager provides a mock function with given fields: +// GetIndexerEventManager provides a mock function with no fields func (_m *ClobKeeper) GetIndexerEventManager() indexer_manager.IndexerEventManager { ret := _m.Called() @@ -691,12 +691,12 @@ func (_m *ClobKeeper) InitializeNewStreams(ctx types.Context, subaccountSnapshot _m.Called(ctx, subaccountSnapshots) } -// IsInitialized provides a mock function with given fields: -func (_m *ClobKeeper) IsInitialized() bool { +// IsInMemStructuresInitialized provides a mock function with no fields +func (_m *ClobKeeper) IsInMemStructuresInitialized() bool { ret := _m.Called() if len(ret) == 0 { - panic("no return value specified for IsInitialized") + panic("no return value specified for IsInMemStructuresInitialized") } var r0 bool diff --git a/protocol/x/clob/ante/clob.go b/protocol/x/clob/ante/clob.go index dd678ba48b5..913faacbc43 100644 --- a/protocol/x/clob/ante/clob.go +++ b/protocol/x/clob/ante/clob.go @@ -65,7 +65,7 @@ func (cd ClobDecorator) AnteHandle( } // Disable order placement and cancelation processing if the clob keeper is not initialized. - if !cd.clobKeeper.IsInitialized() { + if !cd.clobKeeper.IsInMemStructuresInitialized() { return ctx, errorsmod.Wrap( types.ErrClobNotInitialized, "clob keeper is not initialized. Please wait for the next block.", diff --git a/protocol/x/clob/ante/clob_test.go b/protocol/x/clob/ante/clob_test.go index 60a0f8c39d5..f0123d147f9 100644 --- a/protocol/x/clob/ante/clob_test.go +++ b/protocol/x/clob/ante/clob_test.go @@ -53,7 +53,7 @@ func runTestCase(t *testing.T, tc TestCase) { // Setup AnteHandler. mockClobKeeper := &mocks.ClobKeeper{} mockClobKeeper.On("Logger", mock.Anything).Return(log.NewNopLogger()).Maybe() - mockClobKeeper.On("IsInitialized").Return(true).Maybe() + mockClobKeeper.On("IsInMemStructuresInitialized").Return(true).Maybe() cd := ante.NewClobDecorator(mockClobKeeper) antehandler := sdk.ChainAnteDecorators(cd) if tc.setupMocks != nil { diff --git a/protocol/x/clob/keeper/keeper.go b/protocol/x/clob/keeper/keeper.go index c850726eaab..fae1a3b4db3 100644 --- a/protocol/x/clob/keeper/keeper.go +++ b/protocol/x/clob/keeper/keeper.go @@ -53,7 +53,7 @@ type ( streamingManager streamingtypes.FullNodeStreamingManager finalizeBlockEventStager finalizeblock.EventStager[*types.ClobStagedFinalizeBlockEvent] - initialized *atomic.Bool + inMemStructuresInitialized *atomic.Bool Flags flags.ClobFlags @@ -102,28 +102,28 @@ func NewKeeper( revshareKeeper types.RevShareKeeper, ) *Keeper { keeper := &Keeper{ - cdc: cdc, - storeKey: storeKey, - memKey: memKey, - transientStoreKey: transientStoreKey, - 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, - affiliatesKeeper: affiliatesKeeper, - accountPlusKeeper: accountPlusKeeper, - indexerEventManager: indexerEventManager, - streamingManager: streamingManager, - initialized: &atomic.Bool{}, // False by default. - txDecoder: txDecoder, + cdc: cdc, + storeKey: storeKey, + memKey: memKey, + transientStoreKey: transientStoreKey, + 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, + affiliatesKeeper: affiliatesKeeper, + accountPlusKeeper: accountPlusKeeper, + indexerEventManager: indexerEventManager, + streamingManager: streamingManager, + inMemStructuresInitialized: &atomic.Bool{}, // False by default. + txDecoder: txDecoder, mevTelemetryConfig: MevTelemetryConfig{ Enabled: clobFlags.MevTelemetryEnabled, Hosts: clobFlags.MevTelemetryHosts, @@ -177,9 +177,9 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { func (k Keeper) InitializeForGenesis(ctx sdk.Context) { } -// IsInitialized returns whether the clob keeper has been hydrated. -func (k Keeper) IsInitialized() bool { - return k.initialized.Load() +// IsInMemStructuresInitialized returns whether the clob keeper has been hydrated. +func (k Keeper) IsInMemStructuresInitialized() bool { + return k.inMemStructuresInitialized.Load() } // Initialize hydrates the clob keeper with the necessary in memory data structures. @@ -189,7 +189,7 @@ func (k Keeper) Initialize(ctx sdk.Context) { // Code below hydrates the in memory data structures and is not rolled back even if // the block execution is discarded by OE. Therefore, they are only called once. - alreadyInitialized := k.initialized.Swap(true) + alreadyInitialized := k.inMemStructuresInitialized.Swap(true) if alreadyInitialized { return } diff --git a/protocol/x/clob/types/clob_keeper.go b/protocol/x/clob/types/clob_keeper.go index 770eaf491f5..f9ab736012e 100644 --- a/protocol/x/clob/types/clob_keeper.go +++ b/protocol/x/clob/types/clob_keeper.go @@ -13,7 +13,7 @@ type ClobKeeper interface { LiquidationsKeeper LiquidationsConfigKeeper - IsInitialized() bool + IsInMemStructuresInitialized() bool Initialize(ctx sdk.Context) AddOrderToOrderbookSubaccountUpdatesCheck(