Skip to content

Commit 226dea8

Browse files
Julian OspaldjonathanknowlesKtorZ
committed
Garbage collect delisted Pools from SMASH
X-JIRA-Ticket: ADP-478 Co-authored-by: Jonathan Knowles <jonathan.knowles@iohk.io> Co-authored-by: KtorZ <matthias.benkort@gmail.com>
1 parent 1ee823d commit 226dea8

File tree

33 files changed

+5287
-260
lines changed

33 files changed

+5287
-260
lines changed

lib/core/cardano-wallet-core.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ library
9494
, statistics
9595
, stm
9696
, streaming-commons
97-
, string-qq
97+
, string-interpolate
9898
, template-haskell
9999
, text
100100
, text-class

lib/core/src/Cardano/Pool/DB.hs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ import Data.Map.Strict
4949
( Map )
5050
import Data.Quantity
5151
( Quantity (..) )
52+
import Data.Time.Clock.POSIX
53+
( POSIXTime )
5254
import Data.Word
5355
( Word64 )
5456
import System.Random
@@ -211,6 +213,16 @@ data DBLayer m = forall stm. (MonadFail stm, MonadIO stm) => DBLayer
211213
-> stm ()
212214
-- ^ Remove all entries of slot ids newer than the argument
213215

216+
, putDelistedPools
217+
:: [PoolId]
218+
-> stm ()
219+
-- ^ Overwrite the set of delisted pools with a completely new set.
220+
-- Pools may be delisted for reasons such as non-compliance.
221+
222+
, readDelistedPools
223+
:: stm [PoolId]
224+
-- ^ Fetch the set of delisted pools.
225+
214226
, removePools
215227
:: [PoolId]
216228
-> stm ()
@@ -249,6 +261,15 @@ data DBLayer m = forall stm. (MonadFail stm, MonadIO stm) => DBLayer
249261
-> stm ()
250262
-- ^ Modify the settings.
251263

264+
, readLastMetadataGC
265+
:: stm (Maybe POSIXTime)
266+
-- ^ Get the last metadata GC time.
267+
268+
, putLastMetadataGC
269+
:: POSIXTime
270+
-> stm ()
271+
-- ^ Set the last metadata GC time.
272+
--
252273
, cleanDB
253274
:: stm ()
254275
-- ^ Clean a database

lib/core/src/Cardano/Pool/DB/MVar.hs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,19 @@ import Cardano.Pool.DB.Model
3030
, mListPoolLifeCycleData
3131
, mListRegisteredPools
3232
, mListRetiredPools
33+
, mPutDelistedPools
3334
, mPutFetchAttempt
3435
, mPutHeader
36+
, mPutLastMetadataGC
3537
, mPutPoolMetadata
3638
, mPutPoolProduction
3739
, mPutPoolRegistration
3840
, mPutPoolRetirement
3941
, mPutSettings
4042
, mPutStakeDistribution
4143
, mReadCursor
44+
, mReadDelistedPools
45+
, mReadLastMetadataGC
4246
, mReadPoolLifeCycleStatus
4347
, mReadPoolMetadata
4448
, mReadPoolProduction
@@ -146,6 +150,12 @@ newDBLayer timeInterpreter = do
146150
rollbackTo =
147151
void . alterPoolDB (const Nothing) db . mRollbackTo timeInterpreter
148152

153+
putDelistedPools =
154+
void . alterPoolDB (const Nothing) db . mPutDelistedPools
155+
156+
readDelistedPools =
157+
readPoolDB db mReadDelistedPools
158+
149159
removePools =
150160
void . alterPoolDB (const Nothing) db . mRemovePools
151161

@@ -165,6 +175,11 @@ newDBLayer timeInterpreter = do
165175
putSettings =
166176
void . alterPoolDB (const Nothing) db . mPutSettings
167177

178+
readLastMetadataGC = readPoolDB db mReadLastMetadataGC
179+
180+
putLastMetadataGC =
181+
void . alterPoolDB (const Nothing) db . mPutLastMetadataGC
182+
168183
cleanDB =
169184
void $ alterPoolDB (const Nothing) db mCleanDatabase
170185

lib/core/src/Cardano/Pool/DB/Model.hs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
{-# LANGUAGE ScopedTypeVariables #-}
1717
{-# LANGUAGE UndecidableInstances #-}
1818

19+
1920
-- |
2021
-- Copyright: © 2018-2020 IOHK
2122
-- License: Apache-2.0
@@ -50,6 +51,7 @@ module Cardano.Pool.DB.Model
5051
, mPutPoolRetirement
5152
, mReadPoolRetirement
5253
, mUnfetchedPoolMetadataRefs
54+
, mPutDelistedPools
5355
, mPutFetchAttempt
5456
, mPutPoolMetadata
5557
, mListPoolLifeCycleData
@@ -60,9 +62,12 @@ module Cardano.Pool.DB.Model
6062
, mRollbackTo
6163
, mReadCursor
6264
, mRemovePools
65+
, mReadDelistedPools
6366
, mRemoveRetiredPools
6467
, mReadSettings
6568
, mPutSettings
69+
, mPutLastMetadataGC
70+
, mReadLastMetadataGC
6671
) where
6772

6873
import Prelude
@@ -75,16 +80,18 @@ import Cardano.Wallet.Primitive.Types
7580
( BlockHeader (..)
7681
, CertificatePublicationTime
7782
, EpochNo (..)
83+
, InternalState (..)
7884
, PoolId
7985
, PoolLifeCycleStatus (..)
8086
, PoolOwner (..)
8187
, PoolRegistrationCertificate (..)
8288
, PoolRetirementCertificate (..)
8389
, Settings
8490
, SlotNo (..)
85-
, StakePoolMetadata
91+
, StakePoolMetadata (..)
8692
, StakePoolMetadataHash
8793
, StakePoolMetadataUrl
94+
, defaultInternalState
8895
, defaultSettings
8996
)
9097
import Control.Monad.Trans.Class
@@ -109,6 +116,10 @@ import Data.Ord
109116
( Down (..) )
110117
import Data.Quantity
111118
( Quantity (..) )
119+
import Data.Set
120+
( Set )
121+
import Data.Time.Clock.POSIX
122+
( POSIXTime )
112123
import Data.Word
113124
( Word64 )
114125
import GHC.Generics
@@ -143,6 +154,8 @@ data PoolDatabase = PoolDatabase
143154
!(Map (CertificatePublicationTime, PoolId) PoolRetirementCertificate)
144155
-- ^ On-chain retirements associated with pools
145156

157+
, delisted :: !(Set PoolId)
158+
146159
, metadata :: !(Map StakePoolMetadataHash StakePoolMetadata)
147160
-- ^ Off-chain metadata cached in database
148161

@@ -156,6 +169,10 @@ data PoolDatabase = PoolDatabase
156169
-- ^ Store headers during syncing
157170

158171
, settings :: Settings
172+
173+
, internalState :: InternalState
174+
-- ^ Various internal states that need to persist across
175+
-- wallet restarts.
159176
} deriving (Generic, Show, Eq)
160177

161178
data SystemSeed
@@ -171,9 +188,9 @@ instance Eq SystemSeed where
171188

172189
-- | Produces an empty model pool production database.
173190
emptyPoolDatabase :: PoolDatabase
174-
emptyPoolDatabase =
175-
PoolDatabase mempty mempty mempty mempty mempty mempty mempty NotSeededYet
176-
mempty defaultSettings
191+
emptyPoolDatabase = PoolDatabase
192+
mempty mempty mempty mempty mempty mempty mempty mempty NotSeededYet
193+
mempty defaultSettings defaultInternalState
177194

178195
{-------------------------------------------------------------------------------
179196
Model Operation Types
@@ -414,6 +431,12 @@ mRollbackTo ti point = do
414431
| point' <= getPoint point = Just v
415432
| otherwise = Nothing
416433

434+
mPutDelistedPools :: [PoolId] -> ModelOp ()
435+
mPutDelistedPools = modify #delisted . const . Set.fromList
436+
437+
mReadDelistedPools :: ModelOp [PoolId]
438+
mReadDelistedPools = Set.toList <$> get #delisted
439+
417440
mRemovePools :: [PoolId] -> ModelOp ()
418441
mRemovePools poolsToRemove = do
419442
modify #distributions
@@ -453,6 +476,15 @@ mPutSettings
453476
-> ModelOp ()
454477
mPutSettings s = modify #settings (\_ -> s)
455478

479+
mReadLastMetadataGC
480+
:: ModelOp (Maybe POSIXTime)
481+
mReadLastMetadataGC = get (#internalState . #lastMetadataGC)
482+
483+
mPutLastMetadataGC
484+
:: POSIXTime
485+
-> ModelOp ()
486+
mPutLastMetadataGC t = modify (#internalState . #lastMetadataGC) (\_ -> Just t)
487+
456488
--------------------------------------------------------------------------------
457489
-- Utilities
458490
--------------------------------------------------------------------------------

lib/core/src/Cardano/Pool/DB/Sqlite.hs

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ import Cardano.Pool.DB
5050
( DBLayer (..), ErrPointAlreadyExists (..), determinePoolLifeCycleStatus )
5151
import Cardano.Pool.DB.Log
5252
( ParseFailure (..), PoolDbLog (..) )
53+
import Cardano.Pool.DB.Sqlite.TH hiding
54+
( BlockHeader, blockHeight )
5355
import Cardano.Wallet.DB.Sqlite.Types
5456
( BlockId (..) )
5557
import Cardano.Wallet.Logging
@@ -60,7 +62,7 @@ import Cardano.Wallet.Primitive.Types
6062
( BlockHeader (..)
6163
, CertificatePublicationTime (..)
6264
, EpochNo (..)
63-
, PoolId
65+
, PoolId (..)
6466
, PoolLifeCycleStatus (..)
6567
, PoolRegistrationCertificate (..)
6668
, PoolRetirementCertificate (..)
@@ -96,8 +98,8 @@ import Data.Quantity
9698
( Percentage (..), Quantity (..) )
9799
import Data.Ratio
98100
( denominator, numerator, (%) )
99-
import Data.String.QQ
100-
( s )
101+
import Data.String.Interpolate
102+
( i )
101103
import Data.Text
102104
( Text )
103105
import Data.Time.Clock
@@ -120,7 +122,9 @@ import Database.Persist.Sql
120122
, selectFirst
121123
, selectList
122124
, toPersistValue
125+
, update
123126
, (<.)
127+
, (=.)
124128
, (==.)
125129
, (>.)
126130
, (>=.)
@@ -134,9 +138,6 @@ import System.FilePath
134138
import System.Random
135139
( newStdGen )
136140

137-
import Cardano.Pool.DB.Sqlite.TH hiding
138-
( BlockHeader, blockHeight )
139-
140141
import qualified Cardano.Pool.DB.Sqlite.TH as TH
141142
import qualified Cardano.Wallet.Primitive.Types as W
142143
import qualified Data.Map.Strict as Map
@@ -393,7 +394,8 @@ newDBLayer trace fp timeInterpreter = do
393394
(PoolMetadataFetchAttempts hash url retryAfter $ retryCount + 1)
394395

395396
putPoolMetadata hash metadata = do
396-
let StakePoolMetadata{ticker,name,description,homepage} = metadata
397+
let StakePoolMetadata
398+
{ticker, name, description, homepage} = metadata
397399
repsert
398400
(PoolMetadataKey hash)
399401
(PoolMetadata hash name ticker description homepage)
@@ -489,6 +491,13 @@ newDBLayer trace fp timeInterpreter = do
489491
deleteWhere [ BlockSlot >. point ]
490492
-- TODO: remove dangling metadata no longer attached to a pool
491493

494+
putDelistedPools pools = do
495+
deleteWhere ([] :: [Filter PoolDelistment])
496+
insertMany_ $ fmap PoolDelistment pools
497+
498+
readDelistedPools =
499+
fmap (delistedPoolId . entityVal) <$> selectList [] []
500+
492501
removePools = mapM_ $ \pool -> do
493502
liftIO $ traceWith trace $ MsgRemovingPool pool
494503
deleteWhere [ PoolProductionPoolId ==. pool ]
@@ -541,16 +550,33 @@ newDBLayer trace fp timeInterpreter = do
541550
(SettingsKey 1)
542551
. toSettings
543552

553+
readLastMetadataGC = do
554+
-- only ever read the first row
555+
result <- selectFirst
556+
[]
557+
[Asc InternalStateId, LimitTo 1]
558+
pure $ (W.lastMetadataGC . fromInternalState . entityVal) =<< result
559+
560+
putLastMetadataGC utc = do
561+
result <- selectFirst
562+
[ InternalStateId ==. (InternalStateKey 1) ]
563+
[ ]
564+
case result of
565+
Just _ -> update (InternalStateKey 1) [ LastGCMetadata =. Just utc ]
566+
Nothing -> insert_ (InternalState $ Just utc)
567+
544568
cleanDB = do
545569
deleteWhere ([] :: [Filter PoolProduction])
546570
deleteWhere ([] :: [Filter PoolOwner])
547571
deleteWhere ([] :: [Filter PoolRegistration])
548572
deleteWhere ([] :: [Filter PoolRetirement])
573+
deleteWhere ([] :: [Filter PoolDelistment])
549574
deleteWhere ([] :: [Filter StakeDistribution])
550575
deleteWhere ([] :: [Filter PoolMetadata])
551576
deleteWhere ([] :: [Filter PoolMetadataFetchAttempts])
552577
deleteWhere ([] :: [Filter TH.BlockHeader])
553578
deleteWhere ([] :: [Filter Settings])
579+
deleteWhere ([] :: [Filter InternalState])
554580

555581
atomically :: forall a. (SqlPersistT IO a -> IO a)
556582
atomically = runQuery
@@ -706,7 +732,7 @@ createView conn (DatabaseView name definition) = do
706732
-- This view does NOT exclude pools that have retired.
707733
--
708734
activePoolLifeCycleData :: DatabaseView
709-
activePoolLifeCycleData = DatabaseView "active_pool_lifecycle_data" [s|
735+
activePoolLifeCycleData = DatabaseView "active_pool_lifecycle_data" [i|
710736
SELECT
711737
active_pool_registrations.pool_id as pool_id,
712738
active_pool_retirements.retirement_epoch as retirement_epoch,
@@ -735,7 +761,7 @@ activePoolLifeCycleData = DatabaseView "active_pool_lifecycle_data" [s|
735761
-- This view does NOT exclude pools that have retired.
736762
--
737763
activePoolOwners :: DatabaseView
738-
activePoolOwners = DatabaseView "active_pool_owners" [s|
764+
activePoolOwners = DatabaseView "active_pool_owners" [i|
739765
SELECT pool_id, pool_owners FROM (
740766
SELECT row_number() OVER w AS r, *
741767
FROM (
@@ -763,7 +789,7 @@ activePoolOwners = DatabaseView "active_pool_owners" [s|
763789
-- This view does NOT exclude pools that have retired.
764790
--
765791
activePoolRegistrations :: DatabaseView
766-
activePoolRegistrations = DatabaseView "active_pool_registrations" [s|
792+
activePoolRegistrations = DatabaseView "active_pool_registrations" [i|
767793
SELECT
768794
pool_id,
769795
cost,
@@ -793,7 +819,7 @@ activePoolRegistrations = DatabaseView "active_pool_registrations" [s|
793819
-- certificates revoked by subsequent re-registration certificates.
794820
--
795821
activePoolRetirements :: DatabaseView
796-
activePoolRetirements = DatabaseView "active_pool_retirements" [s|
822+
activePoolRetirements = DatabaseView "active_pool_retirements" [i|
797823
SELECT * FROM (
798824
SELECT
799825
pool_id,
@@ -973,3 +999,7 @@ toSettings
973999
-> Settings
9741000
toSettings (W.Settings pms) = Settings pms
9751001

1002+
fromInternalState
1003+
:: InternalState
1004+
-> W.InternalState
1005+
fromInternalState (InternalState utc) = W.InternalState utc

0 commit comments

Comments
 (0)