Skip to content

Commit

Permalink
Merge #3374
Browse files Browse the repository at this point in the history
3374: [ADP-1983] implement local tx submission store r=paolino a=paolino



- [x] implement store expansion 
- [x] implement store pruning
- [x] implement store querying
- [x] couple this store with meta transactions store 
- [x] change the db layer implementation 

### Comments

DB properties/specs seems only covered in the state machine tests

### Issue Number

ADP-1983


Co-authored-by: paolo veronelli <paolo.veronelli@gmail.com>
  • Loading branch information
iohk-bors[bot] and paolino committed Aug 12, 2022
2 parents 9c869db + f9780f9 commit 4a6cd4b
Show file tree
Hide file tree
Showing 10 changed files with 469 additions and 116 deletions.
4 changes: 4 additions & 0 deletions lib/core/cardano-wallet-core.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ library
Cardano.Wallet.DB.Store.Checkpoints
Cardano.Wallet.DB.Store.Meta.Model
Cardano.Wallet.DB.Store.Meta.Store
Cardano.Wallet.DB.Store.Submissions.Model
Cardano.Wallet.DB.Store.Submissions.Store
Cardano.Wallet.DB.Store.Transactions.Model
Cardano.Wallet.DB.Store.Transactions.Store
Cardano.Wallet.DB.Store.Wallets.Model
Expand Down Expand Up @@ -482,6 +484,8 @@ test-suite unit
Cardano.Wallet.DB.StateMachine
Cardano.Wallet.DB.Store.Meta.ModelSpec
Cardano.Wallet.DB.Store.Meta.StoreSpec
Cardano.Wallet.DB.Store.Submissions.ModelSpec
Cardano.Wallet.DB.Store.Submissions.StoreSpec
Cardano.Wallet.DB.Store.Transactions.StoreSpec
Cardano.Wallet.DB.Store.Wallets.StoreSpec
Cardano.Wallet.DummyTarget.Primitive.Types
Expand Down
52 changes: 41 additions & 11 deletions lib/core/src/Cardano/Wallet/DB/Layer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,19 @@ import Cardano.Wallet.DB.Sqlite.Types
import Cardano.Wallet.DB.Store.Checkpoints
( PersistAddressBook (..), blockHeaderFromEntity, mkStoreWallets )
import Cardano.Wallet.DB.Store.Meta.Model
( ManipulateTxMetaHistory (..), TxMetaHistory (..) )
( DeltaTxMetaHistory (..)
, ManipulateTxMetaHistory (..)
, TxMetaHistory (..)
)
import Cardano.Wallet.DB.Store.Submissions.Model
( TxLocalSubmissionHistory (..) )
import Cardano.Wallet.DB.Store.Transactions.Model
( TxHistoryF (..), decorateWithTxOuts, withdrawals )
import Cardano.Wallet.DB.Store.Wallets.Model
( TxWalletsHistory, mkTransactionInfo )
( DeltaWalletsMetaWithSubmissions (..)
, TxWalletsHistory
, mkTransactionInfo
)
import Cardano.Wallet.DB.Store.Wallets.Store
( DeltaTxWalletsHistory (..), mkStoreTxWalletsHistory )
import Cardano.Wallet.DB.WalletState
Expand Down Expand Up @@ -177,7 +185,6 @@ import Database.Persist.Sql
, selectKeysList
, selectList
, updateWhere
, upsert
, (<.)
, (=.)
, (==.)
Expand All @@ -200,6 +207,7 @@ import UnliftIO.MVar
( modifyMVar, modifyMVar_, newMVar, readMVar, withMVar )

import qualified Cardano.Wallet.DB.Sqlite.Schema as DB
import qualified Cardano.Wallet.DB.Store.Submissions.Model as TxSubmissions
import qualified Cardano.Wallet.Primitive.Model as W
import qualified Cardano.Wallet.Primitive.Passphrase as W
import qualified Cardano.Wallet.Primitive.Types as W
Expand Down Expand Up @@ -637,6 +645,8 @@ newDBLayerWith _cacheBehavior _tr ti SqliteContext{runQuery} = do
let
delta = Just
$ ChangeTxMetaWalletsHistory wid
$ ChangeMeta
$ Manipulate
$ RollBackTxMetaHistory nearestPoint
in (delta, Right ())
pure
Expand Down Expand Up @@ -731,17 +741,33 @@ newDBLayerWith _cacheBehavior _tr ti SqliteContext{runQuery} = do
lift $ selectTxHistory cp ti wid minWithdrawal
order filtering txHistory

, putLocalTxSubmission = \wid txid tx sl -> ExceptT $ do
, putLocalTxSubmission = \wid txid tx sl -> do
let errNoSuchWallet = ErrPutLocalTxSubmissionNoSuchWallet $
ErrNoSuchWallet wid
let errNoSuchTx = ErrPutLocalTxSubmissionNoSuchTransaction $
ErrNoSuchTransaction wid txid
ExceptT $ modifyDBMaybe transactionsDBVar
$ \(_txsOld, ws) -> do
case Map.lookup wid ws of
Nothing -> (Nothing, Left errNoSuchWallet)
Just (TxMetaHistory metas, _) -> case
Map.lookup (TxId txid) metas of
Nothing -> (Nothing, Left errNoSuchTx)
Just _ ->
let
delta = Just
$ ChangeTxMetaWalletsHistory wid
$ ChangeSubmissions
$ TxSubmissions.Expand
$ TxLocalSubmissionHistory
$ Map.fromList [
( TxId txid
, LocalTxSubmission (TxId txid)
wid sl tx
)
]
in (delta, Right ())

selectWallet wid >>= \case
Nothing -> pure $ Left errNoSuchWallet
Just _ -> handleConstraint errNoSuchTx $ do
let record = LocalTxSubmission (TxId txid) wid sl tx
void $ upsert record [ LocalTxSubmissionLastSlot =. sl ]

, readLocalTxSubmissionPending =
fmap (map localTxSubmissionFromEntity)
Expand All @@ -754,6 +780,8 @@ newDBLayerWith _cacheBehavior _tr ti SqliteContext{runQuery} = do
let
delta = Just
$ ChangeTxMetaWalletsHistory wid
$ ChangeMeta
$ Manipulate
$ AgeTxMetaHistory tip
in (delta, Right ())

Expand All @@ -770,7 +798,7 @@ newDBLayerWith _cacheBehavior _tr ti SqliteContext{runQuery} = do
$ ErrNoSuchWallet wid
Just _ -> modifyDBMaybe transactionsDBVar
$ \(TxHistoryF _txsOld, ws) -> fromMaybe noTx $ do
TxMetaHistory metas <- Map.lookup wid ws
(TxMetaHistory metas, _) <- Map.lookup wid ws
DB.TxMeta{..} <- Map.lookup (TxId txId) metas
pure $
if txMetaStatus == W.InLedger
Expand All @@ -779,6 +807,8 @@ newDBLayerWith _cacheBehavior _tr ti SqliteContext{runQuery} = do
else
let delta = Just
$ ChangeTxMetaWalletsHistory wid
$ ChangeMeta
$ Manipulate
$ PruneTxMetaHistory $ TxId txId
in (delta, Right ())

Expand Down Expand Up @@ -1004,7 +1034,7 @@ selectTxHistory
selectTxHistory cp ti wid minWithdrawal order whichMeta
(txHistory, wmetas) = do
tinfos <- mapM (uncurry $ mkTransactionInfo ti (W.currentTip cp)) $ do
TxMetaHistory metas <- maybeToList $ Map.lookup wid wmetas
(TxMetaHistory metas, _) <- maybeToList $ Map.lookup wid wmetas
meta <- toList metas
guard $ whichMeta meta
transaction <- maybeToList $ Map.lookup (txMetaTxId meta) txs
Expand Down
2 changes: 1 addition & 1 deletion lib/core/src/Cardano/Wallet/DB/Sqlite/Schema.hs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ LocalTxSubmission
UniqueLocalTxSubmission localTxSubmissionTxId localTxSubmissionWalletId
Primary localTxSubmissionTxId localTxSubmissionWalletId
Foreign TxMeta OnDeleteCascade fk_tx_meta localTxSubmissionTxId localTxSubmissionWalletId
deriving Show Generic
deriving Show Generic Eq

-- A checkpoint for a given wallet is referred to by (wallet_id, slot).
-- Volatile checkpoint data such as AD state will refer to this table.
Expand Down
60 changes: 60 additions & 0 deletions lib/core/src/Cardano/Wallet/DB/Store/Submissions/Model.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}

{- |
Copyright: © 2022 IOHK
License: Apache-2.0
Data type 'TxLocalSubmissionHistory' for storing a set of submitted transactions.
Transactions are encoded "as" expressed in DB tables.
-}
module Cardano.Wallet.DB.Store.Submissions.Model
( TxLocalSubmissionHistory (..)
, DeltaTxLocalSubmission (..)
) where

import Prelude

import Cardano.Wallet.DB.Sqlite.Schema
( LocalTxSubmission (..) )
import Cardano.Wallet.DB.Sqlite.Types
( TxId )
import Data.Delta
( Delta (..) )
import Data.Map.Strict
( Map )
import Fmt
( Buildable (..) )
import GHC.Generics
( Generic )

import qualified Data.Map.Strict as Map
import qualified Data.Set as Set

-- | All transactions that the wallet has submitted to a node,
-- indexed by transaction id.
--
-- Typically, transactions are submitted through the
-- LocalTxSubmission mini-protocol, hence the name of this type.
newtype TxLocalSubmissionHistory =
TxLocalSubmissionHistory {relations :: Map TxId LocalTxSubmission}
deriving ( Eq, Show, Generic, Monoid, Semigroup )

data DeltaTxLocalSubmission
= Expand TxLocalSubmissionHistory
-- ^ Add or overwrite (by id) local-submission-transactions.
| Prune [TxId]
-- ^ Remove submissions by id.
deriving ( Eq, Show, Generic )

instance Buildable DeltaTxLocalSubmission where
build = build . show

instance Delta DeltaTxLocalSubmission where
type Base DeltaTxLocalSubmission = TxLocalSubmissionHistory
apply (Expand addendum) x = addendum <> x
apply (Prune tids) (TxLocalSubmissionHistory m) = TxLocalSubmissionHistory
$ Map.withoutKeys m (Set.fromList tids)
71 changes: 71 additions & 0 deletions lib/core/src/Cardano/Wallet/DB/Store/Submissions/Store.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}

{- |
Copyright: 2022 IOHK
License: Apache-2.0
Implementation of a 'Store' for 'TxLocalSubmissionHistory'.
-}

module Cardano.Wallet.DB.Store.Submissions.Store ( mkStoreSubmissions ) where

import Prelude

import Cardano.Wallet.DB.Sqlite.Schema
( EntityField (..), LocalTxSubmission (..) )
import Cardano.Wallet.DB.Store.Submissions.Model
( DeltaTxLocalSubmission (..), TxLocalSubmissionHistory (..) )
import Cardano.Wallet.Primitive.Types
( WalletId )
import Control.Arrow
( (&&&) )
import Control.Monad
( forM_ )
import Data.DBVar
( Store (..) )
import Data.Foldable
( toList )
import Data.Maybe
( fromJust )
import Database.Persist
( PersistEntity (keyFromRecordM)
, PersistQueryWrite (deleteWhere)
, PersistStoreWrite (repsertMany)
, entityVal
, selectList
, (==.)
)
import Database.Persist.Sql
( SqlPersistT )

import qualified Data.Map.Strict as Map

repsertLocalSubmissions :: TxLocalSubmissionHistory -> SqlPersistT IO ()
repsertLocalSubmissions
(TxLocalSubmissionHistory txs) =
repsertMany [(fromJust keyFromRecordM x, x) | x <- toList txs ]

mkStoreSubmissions :: WalletId
-> Store (SqlPersistT IO) DeltaTxLocalSubmission
mkStoreSubmissions wid =
Store
{ loadS = Right
. TxLocalSubmissionHistory
. Map.fromList
. fmap ((localTxSubmissionTxId &&& id) . entityVal)
<$> selectList [LocalTxSubmissionWalletId ==. wid ] []
, writeS = \txs -> do
deleteWhere [LocalTxSubmissionWalletId ==. wid ]
repsertLocalSubmissions txs
, updateS = \_ -> \case
Expand addendum -> repsertLocalSubmissions addendum
Prune tids -> forM_ tids $ \tid -> deleteWhere
[ LocalTxSubmissionWalletId ==. wid
, LocalTxSubmissionTxId ==. tid
]
}

0 comments on commit 4a6cd4b

Please sign in to comment.