Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit 575c6e8

Browse files
committed
Merge branch 'feature/dae111-txhistory-cache' into cardano-sl-0.2
2 parents 76e35a9 + b10ede9 commit 575c6e8

File tree

6 files changed

+100
-34
lines changed

6 files changed

+100
-34
lines changed

src/Pos/Wallet/WalletMode.hs

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
module Pos.Wallet.WalletMode
1010
( MonadBalances (..)
1111
, MonadTxHistory (..)
12+
, TxHistoryAnswer (..)
1213
, MonadBlockchainInfo (..)
1314
, MonadUpdates (..)
1415
, TxMode
@@ -48,7 +49,7 @@ import Pos.Txp.Class (getMemPool, getUtxoView)
4849
import qualified Pos.Txp.Holder as Modern
4950
import Pos.Txp.Logic (processTx)
5051
import Pos.Txp.Types (UtxoView (..), localTxs)
51-
import Pos.Types (Address, BlockHeader, ChainDifficulty, Coin,
52+
import Pos.Types (Address, BlockHeader, ChainDifficulty, Coin, HeaderHash,
5253
TxAux, TxId, Utxo, difficultyL,
5354
evalUtxoStateT, flattenEpochOrSlot,
5455
flattenSlotId, prevBlockL, runUtxoStateT,
@@ -64,7 +65,7 @@ import Pos.Wallet.Context (ContextHolder, WithWalletContext)
6465
import Pos.Wallet.KeyStorage (KeyStorage, MonadKeys)
6566
import Pos.Wallet.State (WalletDB)
6667
import qualified Pos.Wallet.State as WS
67-
import Pos.Wallet.Tx.Pure (TxHistoryEntry, deriveAddrHistory,
68+
import Pos.Wallet.Tx.Pure (TxHistoryEntry, deriveAddrHistory, thDifficulty,
6869
deriveAddrHistoryPartial, getRelatedTxs)
6970
import Pos.Wallet.Web.State (WalletWebDB (..))
7071

@@ -109,13 +110,23 @@ instance (MonadDB ssc m, MonadMask m) => MonadBalances (Modern.TxpLDHolder ssc m
109110

110111
--deriving instance MonadBalances m => MonadBalances (Modern.TxpLDHolder m)
111112

113+
data TxHistoryAnswer = TxHistoryAnswer
114+
{ taLastCachedHash :: HeaderHash
115+
, taCachedNum :: Int
116+
, taCachedUtxo :: Utxo
117+
, taHistory :: [TxHistoryEntry]
118+
} deriving (Show)
119+
112120
-- | A class which have methods to get transaction history
113121
class Monad m => MonadTxHistory m where
114-
getTxHistory :: Address -> m [TxHistoryEntry]
122+
getTxHistory
123+
:: Address -> Maybe (HeaderHash, Utxo) -> m TxHistoryAnswer
115124
saveTx :: (TxId, TxAux) -> m ()
116125

117-
default getTxHistory :: (MonadTrans t, MonadTxHistory m', t m' ~ m) => Address -> m [TxHistoryEntry]
118-
getTxHistory = lift . getTxHistory
126+
default getTxHistory
127+
:: (MonadTrans t, MonadTxHistory m', t m' ~ m)
128+
=> Address -> Maybe (HeaderHash, Utxo) -> m TxHistoryAnswer
129+
getTxHistory addr = lift . getTxHistory addr
119130

120131
default saveTx :: (MonadTrans t, MonadTxHistory m', t m' ~ m) => (TxId, TxAux) -> m ()
121132
saveTx = lift . saveTx
@@ -138,20 +149,22 @@ deriving instance MonadTxHistory m => MonadTxHistory (WalletWebDB m)
138149

139150
-- | Get tx history for Address
140151
instance MonadIO m => MonadTxHistory (WalletDB m) where
141-
getTxHistory addr = do
152+
getTxHistory addr _ = do
142153
chain <- WS.getBestChain
143154
utxo <- WS.getOldestUtxo
144-
fmap (fst . fromMaybe (panic "deriveAddrHistory: Nothing")) $
155+
res <- fmap (fst . fromMaybe (panic "deriveAddrHistory: Nothing")) $
145156
runMaybeT $ flip runUtxoStateT utxo $
146157
deriveAddrHistory addr chain
158+
pure undefined
147159
saveTx _ = pure ()
148160

149-
instance (SscHelpersClass ssc, MonadDB ssc m, MonadThrow m, WithLogger m)
161+
instance (SscHelpersClass ssc, MonadDB ssc m, MonadThrow m, WithLogger m, PC.WithNodeContext ssc m)
150162
=> MonadTxHistory (Modern.TxpLDHolder ssc m) where
151-
getTxHistory addr = do
152-
bot <- GS.getBot
163+
getTxHistory addr mInit = do
153164
tip <- GS.getTip
154-
genUtxo <- GS.getFilteredGenUtxo addr
165+
166+
let getGenUtxo = filterUtxoByAddr addr . PC.ncGenesisUtxo <$> PC.getNodeContext
167+
(bot, genUtxo) <- maybe ((,) <$> GS.getBot <*> getGenUtxo) pure mInit
155168

156169
-- Getting list of all hashes in main blockchain (excluding bottom block - it's genesis anyway)
157170
hashList <- flip unfoldrM tip $ \h ->
@@ -163,6 +176,10 @@ instance (SscHelpersClass ssc, MonadDB ssc m, MonadThrow m, WithLogger m)
163176
let prev = header ^. prevBlockL
164177
return $ Just (h, prev)
165178

179+
-- Determine last block which txs should be cached
180+
let cachedHashes = drop blkSecurityParam hashList
181+
nonCachedHashes = take blkSecurityParam hashList
182+
166183
let blockFetcher h txs = do
167184
blk <- lift . lift $ DB.getBlock h >>=
168185
maybeThrow (DBMalformed "A block mysteriously disappeared!")
@@ -173,9 +190,18 @@ instance (SscHelpersClass ssc, MonadDB ssc m, MonadThrow m, WithLogger m)
173190
txs <- getRelatedTxs addr $ map mp ltxs
174191
return $ txs ++ blkTxs
175192

176-
result <- runMaybeT $
177-
evalUtxoStateT (foldrM blockFetcher [] hashList >>= localFetcher) genUtxo
178-
maybe (panic "deriveAddrHistory: Nothing") return result
193+
mres <- runMaybeT $ do
194+
(cachedTxs, cachedUtxo) <- runUtxoStateT
195+
(foldrM blockFetcher [] cachedHashes) genUtxo
196+
197+
result <- evalUtxoStateT
198+
(foldrM blockFetcher cachedTxs nonCachedHashes >>= localFetcher)
199+
cachedUtxo
200+
201+
let lastCachedHash = maybe bot identity $ head cachedHashes
202+
return $ TxHistoryAnswer lastCachedHash (length cachedTxs) cachedUtxo result
203+
204+
maybe (panic "deriveAddrHistory: Nothing") pure mres
179205

180206
saveTx txw = () <$ processTx txw
181207

src/Pos/Wallet/Web/Server/Methods.hs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ import Pos.Wallet.KeyStorage (KeyError (..), MonadKeys (..),
4949
addSecretKey)
5050
import Pos.Wallet.Tx (sendTxOuts, submitTx)
5151
import Pos.Wallet.Tx.Pure (TxHistoryEntry (..))
52-
import Pos.Wallet.WalletMode (WalletMode, applyLastUpdate,
53-
blockchainSlotDuration, connectedPeers,
54-
getBalance, getTxHistory,
52+
import Pos.Wallet.WalletMode (TxHistoryAnswer (..), WalletMode,
53+
applyLastUpdate, blockchainSlotDuration,
54+
connectedPeers, getBalance, getTxHistory,
5555
localChainDifficulty,
5656
networkChainDifficulty, waitForUpdate)
5757
import Pos.Wallet.Web.Api (WalletApi, walletApi)
@@ -71,11 +71,13 @@ import Pos.Wallet.Web.Server.Sockets (MonadWalletWebSockets (..),
7171
notify, runWalletWS, upgradeApplicationWS)
7272
import Pos.Wallet.Web.State (MonadWalletWebDB (..), WalletWebDB,
7373
addOnlyNewTxMeta, addUpdate, closeState,
74-
createWallet, getNextUpdate, getProfile,
75-
getTxMeta, getWalletMeta, getWalletState,
76-
openState, removeNextUpdate, removeWallet,
74+
createWallet, getHistoryCache,
75+
getNextUpdate, getProfile, getTxMeta,
76+
getWalletMeta, getWalletState, openState,
77+
removeNextUpdate, removeWallet,
7778
runWalletWebDB, setProfile, setWalletMeta,
78-
setWalletTransactionMeta)
79+
setWalletTransactionMeta,
80+
updateHistoryCache)
7981
import Pos.Web.Server (serveImpl)
8082

8183
----------------------------------------------------------------------------
@@ -294,7 +296,7 @@ decodeCAddressOrFail = either wrongAddress pure . cAddressToAddress
294296
getWallets :: WalletWebMode ssc m => m [CWallet]
295297
getWallets = join $ mapM getWallet <$> myCAddresses
296298

297-
send :: WalletWebMode ssc m => SendActions m -> CAddress -> CAddress -> Coin -> m CTx
299+
send :: WalletWebMode ssc m => SendActions m -> CAddress -> CAddress -> Coin -> m CTx
298300
send sendActions srcCAddr dstCAddr c =
299301
sendExtended sendActions srcCAddr dstCAddr c ADA mempty mempty
300302

@@ -320,11 +322,23 @@ sendExtended sendActions srcCAddr dstCAddr c curr title desc = do
320322

321323
getHistory :: WalletWebMode ssc m => CAddress -> Word -> Word -> m ([CTx], Word)
322324
getHistory cAddr skip limit = do
323-
history <- getTxHistory =<< decodeCAddressOrFail cAddr
324-
cHistory <- mapM (addHistoryTx cAddr ADA mempty mempty) history
325-
pure (paginate cHistory, fromIntegral $ length cHistory)
325+
(minit, cachedTxs) <- transCache <$> getHistoryCache cAddr
326+
327+
TxHistoryAnswer {..} <- flip getTxHistory minit
328+
=<< decodeCAddressOrFail cAddr
329+
cHistory <- mapM (addHistoryTx cAddr ADA mempty mempty) taHistory
330+
331+
-- Add allowed portion of result to cache
332+
let fullHistory = cHistory <> cachedTxs
333+
lenHistory = length cHistory
334+
cached = drop (lenHistory - taCachedNum) cHistory
335+
updateHistoryCache cAddr taLastCachedHash taCachedUtxo cached
336+
337+
pure (paginate fullHistory, fromIntegral $ length fullHistory)
326338
where
327339
paginate = take (fromIntegral limit) . drop (fromIntegral skip)
340+
transCache Nothing = (Nothing, [])
341+
transCache (Just (hh, utxo, txs)) = (Just (hh, utxo), txs)
328342

329343
-- FIXME: is Word enough for length here?
330344
searchHistory :: WalletWebMode ssc m => CAddress -> Text -> Word -> Word -> m ([CTx], Word)

src/Pos/Wallet/Web/State/Acidic.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module Pos.Wallet.Web.State.Acidic
1818
, GetTxMeta (..)
1919
, GetUpdates (..)
2020
, GetNextUpdate (..)
21+
, GetHistoryCache (..)
2122
, CreateWallet (..)
2223
, SetProfile (..)
2324
, SetWalletMeta (..)
@@ -28,6 +29,7 @@ module Pos.Wallet.Web.State.Acidic
2829
, RemoveWallet (..)
2930
, AddUpdate (..)
3031
, RemoveNextUpdate (..)
32+
, UpdateHistoryCache (..)
3133
) where
3234

3335
import Universum
@@ -74,6 +76,7 @@ makeAcidic ''WalletStorage
7476
, 'WS.getTxMeta
7577
, 'WS.getUpdates
7678
, 'WS.getNextUpdate
79+
, 'WS.getHistoryCache
7780
, 'WS.createWallet
7881
, 'WS.setProfile
7982
, 'WS.setWalletMeta
@@ -84,4 +87,5 @@ makeAcidic ''WalletStorage
8487
, 'WS.removeWallet
8588
, 'WS.addUpdate
8689
, 'WS.removeNextUpdate
90+
, 'WS.updateHistoryCache
8791
]

src/Pos/Wallet/Web/State/State.hs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ module Pos.Wallet.Web.State.State
1717
, getWalletHistory
1818
, getUpdates
1919
, getNextUpdate
20+
, getHistoryCache
2021

2122
-- * Setters
2223
, createWallet
@@ -28,6 +29,7 @@ module Pos.Wallet.Web.State.State
2829
, removeWallet
2930
, addUpdate
3031
, removeNextUpdate
32+
, updateHistoryCache
3133
) where
3234

3335
import Data.Acid (EventResult, EventState, QueryEvent,
@@ -36,8 +38,9 @@ import Mockable (MonadMockable)
3638
import Universum
3739

3840
import Pos.Slotting (NtpSlotting)
39-
import Pos.Wallet.Web.ClientTypes (CAddress, CProfile, CTxId, CTxMeta,
40-
CUpdateInfo, CWalletMeta)
41+
import Pos.Types (HeaderHash, Utxo)
42+
import Pos.Wallet.Web.ClientTypes (CAddress, CHash, CProfile, CTx, CTxId,
43+
CTxMeta, CUpdateInfo, CWalletMeta)
4144
import Pos.Wallet.Web.State.Acidic (WalletState, closeState, openMemState,
4245
openState)
4346
import Pos.Wallet.Web.State.Acidic as A
@@ -91,6 +94,9 @@ getUpdates = queryDisk A.GetUpdates
9194
getNextUpdate :: WebWalletModeDB m => m (Maybe CUpdateInfo)
9295
getNextUpdate = queryDisk A.GetNextUpdate
9396

97+
getHistoryCache :: WebWalletModeDB m => CAddress -> m (Maybe (HeaderHash, Utxo, [CTx]))
98+
getHistoryCache = queryDisk . A.GetHistoryCache
99+
94100
createWallet :: WebWalletModeDB m => CAddress -> CWalletMeta -> m ()
95101
createWallet addr = updateDisk . A.CreateWallet addr
96102

@@ -117,3 +123,6 @@ addUpdate = updateDisk . A.AddUpdate
117123

118124
removeNextUpdate :: WebWalletModeDB m => m ()
119125
removeNextUpdate = updateDisk A.RemoveNextUpdate
126+
127+
updateHistoryCache :: WebWalletModeDB m => CAddress -> HeaderHash -> Utxo -> [CTx] -> m ()
128+
updateHistoryCache cAddr h utxo = updateDisk . A.UpdateHistoryCache cAddr h utxo

src/Pos/Wallet/Web/State/Storage.hs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module Pos.Wallet.Web.State.Storage
1414
, getTxMeta
1515
, getUpdates
1616
, getNextUpdate
17+
, getHistoryCache
1718
, createWallet
1819
, setWalletMeta
1920
, setWalletHistory
@@ -23,14 +24,16 @@ module Pos.Wallet.Web.State.Storage
2324
, removeWallet
2425
, addUpdate
2526
, removeNextUpdate
27+
, updateHistoryCache
2628
) where
2729

2830
import Control.Lens (at, ix, makeClassy, (%=), (.=), _Just, _head)
2931
import Data.Default (Default, def)
3032
import Data.SafeCopy (base, deriveSafeCopySimple)
31-
import Pos.Wallet.Web.ClientTypes (CAddress, CCurrency, CHash, CProfile, CTxId,
32-
CTxMeta, CUpdateInfo, CWalletMeta,
33-
CWalletType)
33+
import Pos.Types (HeaderHash, Utxo)
34+
import Pos.Wallet.Web.ClientTypes (CAddress, CCurrency, CHash, CProfile, CTType,
35+
CTx, CTxId, CTxMeta, CUpdateInfo,
36+
CWalletMeta, CWalletType)
3437
import Universum
3538

3639
type TransactionHistory = HashMap CTxId CTxMeta
@@ -40,6 +43,7 @@ data WalletStorage = WalletStorage
4043
_wsWalletMetas :: !(HashMap CAddress (CWalletMeta, TransactionHistory))
4144
, _wsProfile :: !(Maybe CProfile)
4245
, _wsReadyUpdates :: [CUpdateInfo]
46+
, _wsHistoryCache :: !(HashMap CAddress (HeaderHash, Utxo, [CTx]))
4347
}
4448

4549
makeClassy ''WalletStorage
@@ -51,6 +55,7 @@ instance Default WalletStorage where
5155
_wsWalletMetas = mempty
5256
, _wsProfile = mzero
5357
, _wsReadyUpdates = mempty
58+
, _wsHistoryCache = mempty
5459
}
5560

5661
type Query a = forall m. (MonadReader WalletStorage m) => m a
@@ -80,6 +85,9 @@ getUpdates = view wsReadyUpdates
8085
getNextUpdate :: Query (Maybe CUpdateInfo)
8186
getNextUpdate = preview (wsReadyUpdates . _head)
8287

88+
getHistoryCache :: CAddress -> Query (Maybe (HeaderHash, Utxo, [CTx]))
89+
getHistoryCache cAddr = view $ wsHistoryCache . at cAddr
90+
8391
createWallet :: CAddress -> CWalletMeta -> Update ()
8492
createWallet cAddr wMeta = wsWalletMetas . at cAddr .= Just (wMeta, mempty)
8593

@@ -107,9 +115,12 @@ addUpdate :: CUpdateInfo -> Update ()
107115
addUpdate ui = wsReadyUpdates %= (++ [ui])
108116

109117
removeNextUpdate :: Update ()
110-
removeNextUpdate = wsReadyUpdates %= \case
111-
[] -> []
112-
(_:as) -> as
118+
removeNextUpdate = wsReadyUpdates %= drop 1
119+
120+
updateHistoryCache :: CAddress -> HeaderHash -> Utxo -> [CTx] -> Update ()
121+
updateHistoryCache cAddr cHash utxo cTxs = do
122+
oldTxs <- use $ wsHistoryCache . at cAddr . _Just . _3
123+
wsHistoryCache . at cAddr .= Just (cHash, utxo, cTxs <> oldTxs)
113124

114125
deriveSafeCopySimple 0 'base ''CProfile
115126
deriveSafeCopySimple 0 'base ''CHash
@@ -118,6 +129,8 @@ deriveSafeCopySimple 0 'base ''CCurrency
118129
deriveSafeCopySimple 0 'base ''CWalletType
119130
deriveSafeCopySimple 0 'base ''CWalletMeta
120131
deriveSafeCopySimple 0 'base ''CTxId
132+
deriveSafeCopySimple 0 'base ''CTType
133+
deriveSafeCopySimple 0 'base ''CTx
121134
deriveSafeCopySimple 0 'base ''CTxMeta
122135
deriveSafeCopySimple 0 'base ''CUpdateInfo
123136
deriveSafeCopySimple 0 'base ''WalletStorage

util-scripts/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ do
4747
done
4848

4949
# TODO: how can --ghc-options be moved into commonargs?
50-
commonargs='--test --no-haddock-deps --bench --jobs=4'
50+
commonargs='--no-haddock-deps --bench --jobs=4'
5151
norun='--no-run-tests --no-run-benchmarks'
5252
webwallet='--flag cardano-sl:with-web --flag cardano-sl:with-wallet'
5353

0 commit comments

Comments
 (0)