Skip to content

Commit

Permalink
Merge pull request #4032 from cardano-foundation/paolino/ADP-3071/sto…
Browse files Browse the repository at this point in the history
…re-for-delegation-reward-balance

[ADP-3071] Store for delegation reward balance
  • Loading branch information
paolino authored Jul 11, 2023
2 parents ef0d12b + 4d9d791 commit ae68839
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 104 deletions.
2 changes: 2 additions & 0 deletions lib/wallet/cardano-wallet.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ library
Cardano.Wallet.DB.Store.Meta.Model
Cardano.Wallet.DB.Store.Meta.Store
Cardano.Wallet.DB.Store.PrivateKey.Store
Cardano.Wallet.DB.Store.Rewards.Store
Cardano.Wallet.DB.Store.Submissions.Layer
Cardano.Wallet.DB.Store.Submissions.Operations
Cardano.Wallet.DB.Store.Transactions.Decoration
Expand Down Expand Up @@ -939,6 +940,7 @@ test-suite unit
Cardano.Wallet.DB.Store.Meta.ModelSpec
Cardano.Wallet.DB.Store.Meta.StoreSpec
Cardano.Wallet.DB.Store.PrivateKey.StoreSpec
Cardano.Wallet.DB.Store.Rewards.StoreSpec
Cardano.Wallet.DB.Store.Submissions.StoreSpec
Cardano.Wallet.DB.Store.Transactions.StoreSpec
Cardano.Wallet.DB.Store.UTxOHistory.ModelSpec
Expand Down
22 changes: 20 additions & 2 deletions lib/wallet/src/Cardano/Wallet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1256,9 +1256,17 @@ putDelegationCertificate walletState cert slot
= onDBVar walletState $ update $ \_ ->
[UpdateDelegations $ Dlgs.putDelegationCertificate cert slot]

readDelegationRewardBalance
:: Monad stm
=> DBVar stm (DeltaWalletState s)
-> stm Coin
readDelegationRewardBalance walletState =
view #rewards <$> readDBVar walletState

-- | Fetch the cached reward balance of a given wallet from the database.
fetchRewardBalance :: forall s . DBLayer IO s -> IO Coin
fetchRewardBalance DBLayer{..} = atomically readDelegationRewardBalance
fetchRewardBalance DBLayer{..} = atomically
$ readDelegationRewardBalance walletState

mkExternalWithdrawal
:: NetworkLayer IO block
Expand Down Expand Up @@ -1453,6 +1461,7 @@ manageRewardBalance tr' netLayer db = do
where
tr = contramap MsgWallet tr'


handleRewardAccountQuery
:: Monad m
=> Tracer m WalletLog
Expand All @@ -1462,7 +1471,7 @@ handleRewardAccountQuery
handleRewardAccountQuery tr DBLayer{..} query = do
traceWith tr $ MsgRewardBalanceResult query
case query of
Right amt -> atomically $ putDelegationRewardBalance amt
Right amt -> atomically $ putDelegationRewardBalance walletState amt
-- It can happen that the wallet doesn't exist _yet_, whereas we
-- already have a reward balance. If that's the case, we log and
-- move on.
Expand All @@ -1471,6 +1480,15 @@ handleRewardAccountQuery tr DBLayer{..} query = do
-- just update the balance next time the tip changes.
pure ()

putDelegationRewardBalance
:: (Monad stm)
=> DBVar stm (DeltaWalletState s)
-> Coin
-> stm ()
putDelegationRewardBalance walletState amt =
onDBVar walletState $ update $ \_ ->
[UpdateRewards $ Replace amt]

manageSharedRewardBalance
:: forall n block
. Tracer IO WalletWorkerLog
Expand Down
38 changes: 0 additions & 38 deletions lib/wallet/src/Cardano/Wallet/DB.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ module Cardano.Wallet.DB
-- * DBLayer building blocks
, DBLayerCollection (..)
, DBCheckpoints (..)
, DBDelegation (..)
, DBTxHistory (..)
, mkDBLayerFromParts

Expand Down Expand Up @@ -216,20 +215,6 @@ data DBLayer m s = forall stm. (MonadIO stm, MonadFail stm) => DBLayer
-- ^ List all known checkpoint tips, ordered by slot ids from the oldest
-- to the newest.

, putDelegationRewardBalance :: Coin -> stm ()
-- ^ Store the latest known reward account balance.
--
-- This is separate from checkpoints because the data corresponds to the
-- node tip.
-- This is separate from putWalletMeta because it's not meta data

, readDelegationRewardBalance
:: stm Coin
-- ^ Get the reward account balance.
--
-- Returns zero if the wallet isn't found or if wallet hasn't delegated
-- stake.

, putTxHistory :: [(Tx, TxMeta)] -> stm ()
-- ^ Augments the transaction history for a known wallet.
--
Expand Down Expand Up @@ -348,7 +333,6 @@ to delete them wholesale rather than maintaining them.
-}
data DBLayerCollection stm m s = DBLayerCollection
{ dbCheckpoints :: DBCheckpoints stm s
, dbDelegation :: DBDelegation stm
, dbTxHistory :: DBTxHistory stm

-- The following two functions will need to be split up
Expand Down Expand Up @@ -376,8 +360,6 @@ mkDBLayerFromParts ti wid_ DBLayerCollection{..} = DBLayer
, transactionsStore = transactionsStore_
, readCheckpoint = readCheckpoint'
, listCheckpoints = listCheckpoints_ dbCheckpoints
, putDelegationRewardBalance = putDelegationRewardBalance_ dbDelegation
, readDelegationRewardBalance = readDelegationRewardBalance_ dbDelegation
, putTxHistory = putTxHistory_ dbTxHistory
, readTransactions = \minWithdrawal order range status limit ->
readCurrentTip >>= \tip -> do
Expand Down Expand Up @@ -468,26 +450,6 @@ data DBCheckpoints stm s = DBCheckpoints
-- ^ Read the *Byron* genesis parameters.
}

-- | A database layer for storing delegation certificates
-- and the reward balance.
data DBDelegation stm = DBDelegation
{ putDelegationRewardBalance_
:: Coin
-> stm ()
-- ^ Store the latest known reward account balance.
--
-- This is separate from checkpoints because the data corresponds to the
-- node tip.
-- This is separate from putWalletMeta because it's not meta data

, readDelegationRewardBalance_
:: stm Coin
-- ^ Get the reward account balance.
--
-- Returns zero if the wallet hasn't delegated stake.

}

-- | A database layer that stores the transaction history.
data DBTxHistory stm = DBTxHistory
{ putTxHistory_
Expand Down
30 changes: 0 additions & 30 deletions lib/wallet/src/Cardano/Wallet/DB/Layer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ import Cardano.Wallet.Checkpoints
( DeltaCheckpoints (..) )
import Cardano.Wallet.DB
( DBCheckpoints (..)
, DBDelegation (..)
, DBFactory (..)
, DBFresh (..)
, DBLayer (..)
Expand All @@ -88,7 +87,6 @@ import Cardano.Wallet.DB.Sqlite.Migration.Old
( DefaultFieldValues (..), migrateManually )
import Cardano.Wallet.DB.Sqlite.Schema
( CBOR (..)
, DelegationReward (..)
, EntityField (..)
, Key (..)
, TxMeta (..)
Expand Down Expand Up @@ -176,7 +174,6 @@ import Data.Word
import Database.Persist.Sql
( Entity (..)
, SelectOpt (..)
, repsert
, selectFirst
, selectKeysList
, selectList
Expand All @@ -200,7 +197,6 @@ import UnliftIO.MVar
import qualified Cardano.Wallet.Delegation.Model as Dlgs
import qualified Cardano.Wallet.Primitive.Model as W
import qualified Cardano.Wallet.Primitive.Types as W
import qualified Cardano.Wallet.Primitive.Types.Coin as Coin
import qualified Cardano.Wallet.Primitive.Types.Hash as W
import qualified Cardano.Wallet.Primitive.Types.Tx.TransactionInfo as W
import qualified Cardano.Wallet.Primitive.Types.Tx.TxOut as W
Expand Down Expand Up @@ -606,8 +602,6 @@ newDBFreshFromDBOpen wF ti wid_ DBOpen{atomically=atomically_} =
, mkDecorator_ = mkDecorator transactionsQS
}

dbDelegation = mkDBDelegation wid_


mkDBFreshFromParts
:: forall stm m s
Expand Down Expand Up @@ -670,30 +664,6 @@ mkDecorator transactionsQS =
where
lookupTxOut = queryS transactionsQS . GetTxOut

{-----------------------------------------------------------------------
Wallet Delegation
-----------------------------------------------------------------------}

mkDBDelegation :: W.WalletId -> DBDelegation (SqlPersistT IO)
mkDBDelegation wid =
DBDelegation
{ putDelegationRewardBalance_
, readDelegationRewardBalance_
}
where

putDelegationRewardBalance_ :: Coin.Coin -> SqlPersistT IO ()
putDelegationRewardBalance_ amount =
repsert
(DelegationRewardKey wid)
(DelegationReward wid (Coin.unsafeToWord64 amount))

readDelegationRewardBalance_ :: SqlPersistT IO Coin.Coin
readDelegationRewardBalance_ =
Coin.fromWord64 . maybe 0 (rewardAccountBalance . entityVal) <$>
selectFirst [RewardWalletId ==. wid] []


{-------------------------------------------------------------------------------
Conversion between types
from the `persistent` database (Cardano.Wallet.DB.Sqlite.Schema)
Expand Down
13 changes: 0 additions & 13 deletions lib/wallet/src/Cardano/Wallet/DB/Pure/Layer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@ import Cardano.Wallet.DB.Pure.Implementation
, ModelOp
, mInitializeWallet
, mListCheckpoints
, mPutDelegationRewardBalance
, mPutTxHistory
, mReadCheckpoint
, mReadDelegationRewardBalance
, mReadGenesisParameters
, mReadTxHistory
, mRollbackTo
Expand All @@ -41,8 +39,6 @@ import Cardano.Wallet.Primitive.Slotting
( TimeInterpreter )
import Cardano.Wallet.Primitive.Types
( SortOrder (..), WalletId, wholeRange )
import Cardano.Wallet.Primitive.Types.Coin
( Coin (..) )
import Cardano.Wallet.Primitive.Types.Tx
( TransactionInfo (..) )
import Control.Monad
Expand Down Expand Up @@ -162,15 +158,6 @@ newDBFresh timeInterpreter wid = do

, readGenesisParameters = join <$> readDBMaybe db mReadGenesisParameters

{-----------------------------------------------------------------------
Delegation Rewards
-----------------------------------------------------------------------}

, putDelegationRewardBalance = noErrorAlterDB db
. mPutDelegationRewardBalance

, readDelegationRewardBalance = fromMaybe (Coin 0)
<$> readDBMaybe db mReadDelegationRewardBalance

{-----------------------------------------------------------------------
Execution
Expand Down
49 changes: 49 additions & 0 deletions lib/wallet/src/Cardano/Wallet/DB/Store/Rewards/Store.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}

-- |
-- Copyright: © 2022–2023 IOHK
-- License: Apache-2.0
--
-- Rewards-history store and migration from old db tables.
module Cardano.Wallet.DB.Store.Rewards.Store (
mkStoreRewards,
) where

import Prelude

import Cardano.Wallet.DB.Sqlite.Schema
( DelegationReward (..) )
import Control.Exception
( SomeException (SomeException) )
import Data.Delta
( Replace )
import Data.Store
( UpdateStore, mkSimpleStore )
import Database.Persist.Sql
( Entity (..), Filter, SqlPersistT, deleteWhere, insert_, selectList )

import qualified Cardano.Wallet.Primitive.Types as W
import qualified Cardano.Wallet.Primitive.Types.Coin as W

mkStoreRewards :: W.WalletId -> UpdateStore (SqlPersistT IO) (Replace W.Coin)
mkStoreRewards wid = mkSimpleStore loadS' (writeS' wid)

writeS' :: W.WalletId -> W.Coin -> SqlPersistT IO ()
writeS' wid x = do
deleteWhere ([] :: [Filter DelegationReward])
insert_ $ DelegationReward wid $ W.unsafeToWord64 x

loadS' :: SqlPersistT IO (Either SomeException W.Coin)
loadS' = do
xs <- selectList [] []
case xs of
[Entity _ (DelegationReward _ y)] -> pure $ Right $ W.fromWord64 y
[] -> pure $ Right $ W.Coin 0
_multiple ->
pure
$ Left
$ SomeException
$ userError "Multiple rewards found"
15 changes: 9 additions & 6 deletions lib/wallet/src/Cardano/Wallet/DB/Store/WalletState/Store.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import Cardano.Wallet.DB.Store.Info.Store
( mkStoreInfo )
import Cardano.Wallet.DB.Store.PrivateKey.Store
( mkStorePrivateKey )
import Cardano.Wallet.DB.Store.Rewards.Store
( mkStoreRewards )
import Cardano.Wallet.DB.Store.Submissions.Operations
( mkStoreSubmissions )
import Cardano.Wallet.DB.WalletState
Expand All @@ -42,12 +44,9 @@ import UnliftIO.Exception

import qualified Cardano.Wallet.Primitive.Types as W

{-------------------------------------------------------------------------------
WalletState Store
-------------------------------------------------------------------------------}


-- | Store for 'WalletState' of a single wallet.
-- | Store for 'WalletState' of a single wallet. This is a composite store
-- which stores all the sub-stores for the various components of the wallet.
-- TODO: Remove the WalletId parameter as we are storing on a per-wallet basis.
mkStoreWallet
:: PersistAddressBook s
=> WalletFlavorS s
Expand All @@ -60,6 +59,7 @@ mkStoreWallet wF wid = mkUpdateStore load write update
infoStore = mkStoreInfo
pkStore = mkStorePrivateKey (keyOfWallet wF) wid
delegationsStore = mkStoreDelegations
rewardsStore = mkStoreRewards wid

load = do
eprologue <-
Expand All @@ -70,6 +70,7 @@ mkStoreWallet wF wid = mkUpdateStore load write update
einfo <- loadS infoStore
ecredentials <- loadS pkStore
edelegations <- loadS delegationsStore
erewards <- loadS rewardsStore
pure
$ WalletState
<$> eprologue
Expand All @@ -78,6 +79,7 @@ mkStoreWallet wF wid = mkUpdateStore load write update
<*> einfo
<*> ecredentials
<*> edelegations
<*> erewards

write wallet = do
writeS infoStore (wallet ^. #info)
Expand Down Expand Up @@ -105,3 +107,4 @@ mkStoreWallet wF wid = mkUpdateStore load write update
(updateS delegationsStore . Just)
(delegations s)
deltas
update1 _ (UpdateRewards delta) = updateS rewardsStore Nothing delta
Loading

0 comments on commit ae68839

Please sign in to comment.