Skip to content

Commit

Permalink
[ADP-3212] Restructure delegation datatypes to match Conway specs (#4437
Browse files Browse the repository at this point in the history
)

Follow up on #4433. As ledger Conway specs regarding Certificates has
changed we try to follow their data model in our Store

- [x] Update delegations Operations
- [x] Update delegations Status 

A follow up to this PR will update the lean specifications

ADP-3212
  • Loading branch information
paolino authored Feb 8, 2024
2 parents ebf229f + 17e2715 commit b6d991b
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 215 deletions.
2 changes: 1 addition & 1 deletion lib/wallet/src/Cardano/Wallet/DB/Layer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ mkDBLayerCollection ti wid atomically_ walletState =
, UpdateSubmissions
$ rollBackSubmissions nearestSlotNo
, UpdateDelegations
[Dlgs.Rollback nearestSlotNo]
$ Dlgs.Rollback nearestSlotNo
]
, case Map.lookup nearestPoint
(wal ^. #checkpoints . #checkpoints) of
Expand Down
21 changes: 11 additions & 10 deletions lib/wallet/src/Cardano/Wallet/DB/Store/Delegations/Layer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ import Cardano.Wallet.Primitive.Types
, WalletDelegationNext (..)
, WalletDelegationStatus (..)
)
import Cardano.Wallet.Primitive.Types.DRep
( DRep
)
import Data.Foldable
( find
)
Expand Down Expand Up @@ -66,8 +69,7 @@ isVoting :: Delegations -> Bool
isVoting m = fromMaybe False $ do
(_, v) <- lookupMax m
let votedAlready = \case
ActiveAndVoted _ _ -> True
Voted _ -> True
Active (Just _) _ -> True
_ -> False
pure $ votedAlready v

Expand All @@ -85,9 +87,8 @@ putDelegationCertificate
-> SlotNo
-> DeltaDelegations
putDelegationCertificate cert sl = case cert of
CertDelegateNone _ -> [Deregister sl]
CertVoteAndDelegate _ (Just pool) _ -> [Delegate pool sl, Register sl]
CertVoteAndDelegate _ Nothing _ -> [Register sl]
CertDelegateNone _ -> Deregister sl
CertVoteAndDelegate _ pool drep -> VoteAndDelegate drep pool sl

-- | Arguments to 'readDelegation'.
data CurrentEpochSlotting = CurrentEpochSlotting
Expand Down Expand Up @@ -135,13 +136,13 @@ readDelegation CurrentEpochSlotting{..} history =
readDelegationStatus cond =
(walletDelegationStatus . snd <$>) . find (cond . fst) . Map.toDescList

walletDelegationStatus :: Status PoolId -> WalletDelegationStatus
walletDelegationStatus :: Status DRep PoolId -> WalletDelegationStatus
walletDelegationStatus = \case
Inactive -> NotDelegating
Registered -> NotDelegating
Active pid -> Delegating pid
ActiveAndVoted pid vote -> DelegatingVoting pid vote
Voted vote -> Voting vote
Active Nothing Nothing -> NotDelegating
Active Nothing (Just pid) -> Delegating pid
Active (Just vote) Nothing -> Voting vote
Active (Just vote) (Just pid) -> DelegatingVoting pid vote

-- | Construct 'CurrentEpochSlotting' from an 'EpochNo' using a 'TimeInterpreter'
-- .
Expand Down
19 changes: 9 additions & 10 deletions lib/wallet/src/Cardano/Wallet/DB/Store/Delegations/Model.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,24 @@ import Cardano.Wallet.Delegation.Model
import Cardano.Wallet.Primitive.Types
( SlotNo
)
import Cardano.Wallet.Primitive.Types.DRep
( DRep
)
import Fmt
( Buildable (..)
, listF'
)

-- | Wallet delegation history
type Delegations = History SlotNo PoolId
type Delegations = History SlotNo DRep PoolId

-- | Delta of wallet delegation history. As always with deltas, the
-- order of the operations matters and it's reversed! (ask the architects)
type DeltaDelegations = [Operation SlotNo PoolId]
type DeltaDelegations = Operation SlotNo DRep PoolId

instance Buildable DeltaDelegations where
build = listF' build1
where
build1 = \case
Register slot -> "Register " <> build slot
build = \case
Deregister slot -> "Deregister " <> build slot
Delegate pool slot -> "Delegate " <> build pool <> " " <> build slot
DelegateAndVote pool vote slot -> "Delegate " <> build pool <> " and vote "<> build vote <> " " <> build slot
Vote vote slot -> "Vote " <> build vote <> " " <> build slot
VoteAndDelegate vote pool slot ->
"Delegate " <> build pool
<> " and vote "<> build vote <> " " <> build slot
Rollback slot -> "Rollback " <> build slot
33 changes: 18 additions & 15 deletions lib/wallet/src/Cardano/Wallet/DB/Store/Delegations/Store.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ import Cardano.Wallet.Delegation.Model
, Status (..)
, slotOf
)
import Cardano.Wallet.Primitive.Types.DRep
( DRep
)
import Control.Exception
( Exception
, SomeException (SomeException)
Expand Down Expand Up @@ -71,11 +74,11 @@ import Database.Persist.Sql

import qualified Data.Map.Strict as Map

mkStoreDelegations :: UpdateStore (SqlPersistT IO) (Operation SlotNo PoolId)
mkStoreDelegations :: UpdateStore (SqlPersistT IO) (Operation SlotNo DRep PoolId)
mkStoreDelegations = mkUpdateStore loadS' writeS' updateS'

loadS'
:: SqlPersistT IO (Either SomeException (History SlotNo PoolId))
:: SqlPersistT IO (Either SomeException (History SlotNo DRep PoolId))
loadS' = do
xs <- selectList [] []
pure $ Map.fromList <$> sequence [decodeStatus x | Entity _ x <- xs]
Expand All @@ -89,25 +92,25 @@ data DecodeDelegationError
| ActiveVotingWithoutPoolAndDRep
deriving (Show, Eq, Exception)

decodeStatus :: Delegations -> (Either SomeException (SlotNo, Status PoolId))
decodeStatus :: Delegations -> (Either SomeException (SlotNo, Status DRep PoolId))
decodeStatus (Delegations sn n m_pi m_v) = case n of
InactiveE -> Right (sn, Inactive)
RegisteredE -> Right (sn, Registered)
RegisteredE -> Right (sn, Active Nothing Nothing)
ActiveE -> case m_pi of
Nothing -> Left $ SomeException ActiveDelegationWithoutAPool
Just pi' -> Right (sn, Active pi')
Just pi' -> Right (sn, Active Nothing (Just pi'))
VotedE -> case m_v of
Nothing -> Left $ SomeException VotingWithoutADRep
Just v' -> Right (sn, Voted v')
Just v' -> Right (sn, Active (Just v') Nothing)
ActiveAndVotedE -> case (m_pi, m_v) of
(Just _, Nothing) -> Left $ SomeException ActiveVotingWithoutADRep
(Nothing, Just _) -> Left $ SomeException ActiveVotingWithoutAPool
(Nothing, Nothing) -> Left $ SomeException ActiveVotingWithoutPoolAndDRep
(Just pi', Just v') -> Right (sn, ActiveAndVoted pi' v')
(Just pi', Just v') -> Right (sn, Active (Just v') (Just pi'))

updateS'
:: Maybe (History SlotNo PoolId)
-> Operation SlotNo PoolId
:: Maybe (History SlotNo DRep PoolId)
-> Operation SlotNo DRep PoolId
-> SqlPersistT IO ()
updateS' = updateLoad loadS' throwIO $ \h op -> do
let slot = slotOf op
Expand All @@ -124,15 +127,15 @@ updateS' = updateLoad loadS' throwIO $ \h op -> do
repsert (DelegationsKey slot)
$ encodeStatus slot w

encodeStatus :: SlotNo -> Status PoolId -> Delegations
encodeStatus :: SlotNo -> Status DRep PoolId -> Delegations
encodeStatus slot = \case
Inactive -> Delegations slot InactiveE Nothing Nothing
Registered -> Delegations slot RegisteredE Nothing Nothing
Active pi' -> Delegations slot ActiveE (Just pi') Nothing
Voted v' -> Delegations slot VotedE Nothing (Just v')
ActiveAndVoted pi' v' -> Delegations slot ActiveAndVotedE (Just pi') (Just v')
Active Nothing Nothing -> Delegations slot RegisteredE Nothing Nothing
Active Nothing (Just pi') -> Delegations slot ActiveE (Just pi') Nothing
Active (Just v') Nothing -> Delegations slot VotedE Nothing (Just v')
Active v' pi' -> Delegations slot ActiveAndVotedE pi' v'

writeS' :: History SlotNo PoolId -> SqlPersistT IO ()
writeS' :: History SlotNo DRep PoolId -> SqlPersistT IO ()
writeS' h = do
resetDelegationTable
insertMany_ [encodeStatus slot x | (slot, x) <- Map.assocs h]
7 changes: 2 additions & 5 deletions lib/wallet/src/Cardano/Wallet/DB/Store/WalletState/Store.hs
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,6 @@ mkStoreWallet wF wid = mkUpdateStore load write update
update1 _ (UpdateInfo delta) = updateS infoStore Nothing delta
update1 _ (UpdateCredentials delta) = do
updateS pkStore Nothing delta
update1 s (UpdateDelegations deltas) = do
updateSequence
(updateS delegationsStore . Just)
(delegations s)
deltas
update1 s (UpdateDelegations delta) = do
updateS delegationsStore (Just $ delegations s) delta
update1 _ (UpdateRewards delta) = updateS rewardsStore Nothing delta
60 changes: 22 additions & 38 deletions lib/wallet/src/Cardano/Wallet/Delegation/Model.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ module Cardano.Wallet.Delegation.Model

import Prelude

import Cardano.Wallet.Primitive.Types.DRep
( DRep
)
import Data.Delta
( Delta (..)
)
Expand All @@ -31,67 +28,54 @@ import Data.Map.Strict
import qualified Data.Map.Strict as Map

-- | Delta type for the delegation 'History'.
data Operation slot pool
= Register slot
data Operation slot drep pool
= VoteAndDelegate (Maybe drep) (Maybe pool) slot
| Deregister slot
| Delegate pool slot
| DelegateAndVote pool DRep slot
| Vote DRep slot
| Rollback slot
deriving (Show)

-- | Target slot of each 'Operation'.
slotOf :: Operation slot pool -> slot
slotOf (Register x) = x
slotOf :: Operation slot drep pool -> slot
slotOf (Deregister x) = x
slotOf (Delegate _ x) = x
slotOf (DelegateAndVote _ _ x) = x
slotOf (Vote _ x) = x
slotOf (Rollback x) = x
slotOf (VoteAndDelegate _ _ x) = x

-- | Valid state for the delegations, independent of time.
data Status pool
data Status drep pool
= Inactive
| Registered
| Active pool
| ActiveAndVoted pool DRep
| Voted DRep
| Active (Maybe drep) (Maybe pool)
deriving (Show, Eq)

-- | Delegation history implementation.
type History slot pool = Map slot (Status pool)
type History slot drep pool = Map slot (Status drep pool)

instance (Ord slot, Eq pool) => Delta (Operation slot pool) where
type Base (Operation slot pool) = History slot pool
instance (Ord slot, Eq pool, Eq drep) => Delta (Operation slot drep pool) where
type Base (Operation slot drep pool) = History slot drep pool
apply r hist = hist' & if miss == wanted then id else Map.insert slot wanted
where
slot = slotOf r
hist' = cut (< slot) hist
miss = status slot hist'
wanted = transition r $ status slot hist

transition :: Operation slot pool -> Status pool -> Status pool
transition (Register _) Inactive = Registered
transition (Delegate p _) Registered = Active p
transition (Delegate p _) (Active _) = Active p
transition (Vote v _) Registered = Voted v
transition (DelegateAndVote p v _) Registered = ActiveAndVoted p v
transition (Vote v _) (Voted _) = Voted v
transition (Delegate p _) (Voted v) = ActiveAndVoted p v
transition (DelegateAndVote p v _) (Voted _) = ActiveAndVoted p v
transition (Vote v _) (Active p) = ActiveAndVoted p v
transition (DelegateAndVote p v _) (Active _) = ActiveAndVoted p v
transition (DelegateAndVote p v _) (ActiveAndVoted _ _) = ActiveAndVoted p v
transition (Delegate p _) (ActiveAndVoted _ v) = ActiveAndVoted p v
transition (Vote v _) (ActiveAndVoted p _) = ActiveAndVoted p v
transition :: Operation slot drep pool -> Status drep pool -> Status drep pool
transition (Deregister _) _ = Inactive
transition (VoteAndDelegate d p _) (Active d' p') = Active d'' p''
where
d'' = insertIfJust d d'
p'' = insertIfJust p p'
transition (VoteAndDelegate d p _) _ = Active d p
transition _ s = s

type Change slot pool = History slot pool -> History slot pool
insertIfJust :: Maybe a -> Maybe a -> Maybe a
insertIfJust (Just y) _ = Just y
insertIfJust Nothing x = x

type Change slot drep pool = History slot drep pool -> History slot drep pool

cut :: (slot -> Bool) -> Change slot pool
cut :: (slot -> Bool) -> Change slot drep pool
cut op = fst . Map.spanAntitone op

-- | Status of the delegation at a given slot.
status :: Ord slot => slot -> History slot pool -> Status pool
status :: Ord slot => slot -> Map slot (Status drep pool) -> Status drep pool
status x = maybe Inactive snd . Map.lookupMax . cut (<= x)
Loading

0 comments on commit b6d991b

Please sign in to comment.