Skip to content
This repository was archived by the owner on Nov 24, 2025. It is now read-only.

Commit f6e6101

Browse files
authored
Merge branch 'master' into LG/readme-links-to-docs-and-resources
2 parents cb8a111 + f864fa1 commit f6e6101

File tree

1 file changed

+89
-73
lines changed

1 file changed

+89
-73
lines changed

src/Chainweb/Mempool/InMem.hs

Lines changed: 89 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
{-# LANGUAGE ExistentialQuantification #-}
55
{-# LANGUAGE FlexibleContexts #-}
66
{-# LANGUAGE ImportQualifiedPost #-}
7+
{-# LANGUAGE LambdaCase #-}
78
{-# LANGUAGE NumericUnderscores #-}
89
{-# LANGUAGE OverloadedStrings #-}
910
{-# LANGUAGE RankNTypes #-}
@@ -26,65 +27,57 @@ module Chainweb.Mempool.InMem
2627
, txTTLCheck
2728
) where
2829

29-
------------------------------------------------------------------------------
30+
#if MIN_VERSION_base(4,20,0)
31+
import Data.Foldable (foldlM)
32+
#else
33+
import Data.Foldable (foldl', foldlM)
34+
#endif
3035

31-
import Data.List qualified as List
36+
import Chainweb.BlockHash
37+
import Chainweb.BlockHeight
38+
import Chainweb.Logger
39+
import Chainweb.Mempool.CurrentTxs
40+
import Chainweb.Mempool.InMemTypes
41+
import Chainweb.Mempool.Mempool
42+
import Chainweb.Pact4.Validations (defaultMaxTTL, defaultMaxCoinDecimalPlaces)
43+
import Chainweb.Time
44+
import Chainweb.Utils
45+
import Chainweb.Version (ChainwebVersion)
3246
import Control.Applicative ((<|>))
3347
import Control.Concurrent.Async
3448
import Control.Concurrent.MVar
3549
import Control.DeepSeq
3650
import Control.Error.Util (hush)
3751
import Control.Exception (evaluate, mask_, throw)
52+
import Control.Lens
3853
import Control.Monad
39-
40-
import qualified Data.ByteString.Short as SB
54+
import Control.Monad.IO.Class (liftIO)
55+
import Control.Monad.Except (runExceptT, throwError)
56+
import Data.ByteString (ByteString)
57+
import Data.ByteString qualified as BS
58+
import Data.ByteString.Short qualified as SB
4159
import Data.Decimal
42-
#if MIN_VERSION_base(4,20,0)
43-
import Data.Foldable (foldlM)
44-
#else
45-
import Data.Foldable (foldl', foldlM)
46-
#endif
60+
import Data.Either (partitionEithers)
4761
import Data.Function (on)
4862
import Data.HashMap.Strict (HashMap)
49-
import qualified Data.HashMap.Strict as HashMap
63+
import Data.HashMap.Strict qualified as HashMap
5064
import Data.IORef (modifyIORef', newIORef, readIORef, writeIORef)
65+
import Data.List qualified as List
5166
import Data.Maybe
5267
import Data.Ord
53-
import qualified Data.Set as S
54-
import qualified Data.Text as T
55-
import qualified Data.Text.Encoding as T
56-
import Data.Traversable (for)
68+
import Data.Set qualified as S
69+
import Data.Text qualified as T
70+
import Data.Text.Encoding qualified as T
5771
import Data.Vector (Vector)
58-
import qualified Data.Vector as V
59-
import qualified Data.Vector.Algorithms.Tim as TimSort
60-
72+
import Data.Vector qualified as V
73+
import Data.Vector.Algorithms.Tim qualified as TimSort
74+
import Numeric.AffineSpace
6175
import Pact.Parse
62-
76+
import Pact.Types.ChainMeta qualified as P
6377
import Prelude hiding (init, lookup, pred)
64-
6578
import System.LogLevel
6679
import System.Random
6780

68-
-- internal imports
69-
70-
import Chainweb.BlockHash
71-
import Chainweb.BlockHeight
72-
import Chainweb.Logger
73-
import Chainweb.Mempool.CurrentTxs
74-
import Chainweb.Mempool.InMemTypes
75-
import Chainweb.Mempool.Mempool
76-
import Chainweb.Pact4.Validations (defaultMaxTTL, defaultMaxCoinDecimalPlaces)
77-
import Chainweb.Time
78-
import Chainweb.Utils
79-
import Chainweb.Version (ChainwebVersion)
80-
81-
import qualified Pact.Types.ChainMeta as P
82-
83-
import Numeric.AffineSpace
84-
import Data.ByteString (ByteString)
85-
import Data.Either (partitionEithers)
86-
import Control.Lens
87-
8881
------------------------------------------------------------------------------
8982
compareOnGasPrice :: TransactionConfig t -> t -> t -> Ordering
9083
compareOnGasPrice txcfg a b = compare aa bb
@@ -102,16 +95,15 @@ makeInMemPool cfg = mask_ $ do
10295
dataLock <- newInMemMempoolData >>= newMVar
10396
return $! InMemoryMempool cfg dataLock nonce
10497

105-
10698
------------------------------------------------------------------------------
99+
107100
newInMemMempoolData :: IO (InMemoryMempoolData t)
108101
newInMemMempoolData =
109102
InMemoryMempoolData <$!> newIORef mempty
110103
<*> newIORef emptyRecentLog
111104
<*> newIORef mempty
112105
<*> newIORef newCurrentTxs
113106

114-
115107
------------------------------------------------------------------------------
116108
toMempoolBackend
117109
:: forall t logger
@@ -127,8 +119,8 @@ toMempoolBackend logger mempool = do
127119
, mempoolLookup = lookupInMem tcfg lockMVar
128120
, mempoolLookupEncoded = lookupEncodedInMem lockMVar
129121
, mempoolInsert = insertInMem logger cfg lockMVar
130-
, mempoolInsertCheck = insertCheckInMem cfg lockMVar
131-
, mempoolInsertCheckVerbose = insertCheckVerboseInMem cfg lockMVar
122+
, mempoolInsertCheck = insertCheckInMem logger cfg lockMVar
123+
, mempoolInsertCheckVerbose = insertCheckVerboseInMem logger cfg lockMVar
132124
, mempoolMarkValidated = markValidatedInMem logger tcfg lockMVar
133125
, mempoolAddToBadList = addToBadListInMem lockMVar
134126
, mempoolCheckBadList = checkBadListInMem lockMVar
@@ -306,13 +298,13 @@ maxNumPending = 10000
306298
-- the latter case.
307299
--
308300
insertCheckInMem
309-
:: forall t
310-
. NFData t
311-
=> InMemConfig t -- ^ in-memory config
301+
:: forall logger t. (NFData t, Logger logger)
302+
=> logger
303+
-> InMemConfig t -- ^ in-memory config
312304
-> MVar (InMemoryMempoolData t) -- ^ in-memory state
313305
-> Vector t -- ^ new transactions
314306
-> IO (Either (T2 TransactionHash InsertError) ())
315-
insertCheckInMem cfg lock txs
307+
insertCheckInMem logger cfg lock txs
316308
| V.null txs = pure $ Right ()
317309
| otherwise = do
318310
now <- getCurrentTimeIntegral
@@ -321,10 +313,14 @@ insertCheckInMem cfg lock txs
321313

322314
-- We hash the tx here and pass it around around to avoid needing to repeat
323315
-- the hashing effort.
324-
let withHashes :: Either (T2 TransactionHash InsertError) (Vector (T2 TransactionHash t))
325-
withHashes = for txs $ \tx ->
326-
let !h = hasher tx
327-
in bimap (T2 h) (T2 h) $ validateOne cfg badmap curTxIdx now tx h
316+
withHashes :: Either (T2 TransactionHash InsertError) (Vector (T2 TransactionHash t)) <- runExceptT $ do
317+
forM txs $ \tx -> do
318+
let !h = hasher tx
319+
case validateOne cfg badmap curTxIdx now tx h of
320+
Right t -> pure (T2 h t)
321+
Left insertErr -> do
322+
liftIO $ logValidateOneFailure logger "insertCheckInMem" h insertErr
323+
throwError (T2 h insertErr)
328324

329325
case withHashes of
330326
Left _ -> pure $! void withHashes
@@ -340,27 +336,33 @@ insertCheckInMem cfg lock txs
340336
-- and the creation time of the parent header in the latter case (new block creation).
341337
--
342338
insertCheckVerboseInMem
343-
:: forall t
344-
. NFData t
345-
=> InMemConfig t -- ^ in-memory config
339+
:: forall t logger. (NFData t, Logger logger)
340+
=> logger
341+
-> InMemConfig t -- ^ in-memory config
346342
-> MVar (InMemoryMempoolData t) -- ^ in-memory state
347343
-> Vector t -- ^ new transactions
348344
-> IO (Vector (T2 TransactionHash (Either InsertError t)))
349-
insertCheckVerboseInMem cfg lock txs
345+
insertCheckVerboseInMem logger cfg lock txs
350346
| V.null txs = return V.empty
351347
| otherwise = do
352348
now <- getCurrentTimeIntegral
353349
badmap <- withMVarMasked lock $ readIORef . _inmemBadMap
354350
curTxIdx <- withMVarMasked lock $ readIORef . _inmemCurrentTxs
355-
356-
let withHashesAndPositions :: (HashMap TransactionHash (Int, InsertError), HashMap TransactionHash (Int, t))
357-
withHashesAndPositions =
358-
over _1 (HashMap.fromList . V.toList)
359-
$ over _2 (HashMap.fromList . V.toList)
360-
$ V.partitionWith (\(i, h, e) -> bimap (\err -> (h, (i, err))) (\err -> (h, (i, err))) e)
361-
$ flip V.imap txs $ \i tx ->
362-
let !h = hasher tx
363-
in (i, h,) $! validateOne cfg badmap curTxIdx now tx h
351+
352+
withHashesAndPositions :: (HashMap TransactionHash (Int, InsertError), HashMap TransactionHash (Int, t)) <- do
353+
pos <- flip V.imapM txs $ \i tx -> do
354+
let !h = hasher tx
355+
case validateOne cfg badmap curTxIdx now tx h of
356+
Right t -> pure (i, h, Right t)
357+
Left insertErr -> do
358+
logValidateOneFailure logger "insertCheckVerboseInMem" h insertErr
359+
pure (i, h, Left insertErr)
360+
361+
pure
362+
$ over _1 (HashMap.fromList . V.toList)
363+
$ over _2 (HashMap.fromList . V.toList)
364+
$ V.partitionWith (\(i, h, e) -> bimap (\err -> (h, (i, err))) (\err -> (h, (i, err))) e)
365+
$ pos
364366

365367
let (prevFailures, prevSuccesses) = withHashesAndPositions
366368

@@ -496,23 +498,27 @@ txTTLCheck txcfg now t = do
496498
-- the latter case.
497499
--
498500
insertCheckInMem'
499-
:: forall t
500-
. NFData t
501-
=> InMemConfig t -- ^ in-memory config
501+
:: forall t logger. (NFData t, Logger logger)
502+
=> logger
503+
-> InMemConfig t -- ^ in-memory config
502504
-> MVar (InMemoryMempoolData t) -- ^ in-memory state
503505
-> Vector t -- ^ new transactions
504506
-> IO (Vector (T2 TransactionHash t))
505-
insertCheckInMem' cfg lock txs
507+
insertCheckInMem' logger cfg lock txs
506508
| V.null txs = pure V.empty
507509
| otherwise = do
508510
now <- getCurrentTimeIntegral
509511
badmap <- withMVarMasked lock $ readIORef . _inmemBadMap
510512
curTxIdx <- withMVarMasked lock $ readIORef . _inmemCurrentTxs
511513

512-
let withHashes :: Vector (T2 TransactionHash t)
513-
withHashes = flip V.mapMaybe txs $ \tx ->
514-
let !h = hasher tx
515-
in (T2 h) <$> hush (validateOne cfg badmap curTxIdx now tx h)
514+
withHashes :: Vector (T2 TransactionHash t) <- do
515+
flip V.mapMaybeM txs $ \tx -> do
516+
let !h = hasher tx
517+
case validateOne cfg badmap curTxIdx now tx h of
518+
Right t -> pure (Just (T2 h t))
519+
Left insertErr -> do
520+
logValidateOneFailure logger "insertCheckInMem'" h insertErr
521+
pure Nothing
516522

517523
V.mapMaybe hush <$!> _inmemPreInsertBatchChecks cfg withHashes
518524
where
@@ -544,7 +550,7 @@ insertInMem logger cfg lock runCheck txs0 = do
544550
where
545551
insertCheck :: IO (Vector (T2 TransactionHash t))
546552
insertCheck = case runCheck of
547-
CheckedInsert -> insertCheckInMem' cfg lock txs0
553+
CheckedInsert -> insertCheckInMem' logger cfg lock txs0
548554
UncheckedInsert -> return $! V.map (\tx -> T2 (hasher tx) tx) txs0
549555

550556
txcfg = _inmemTxCfg cfg
@@ -867,3 +873,13 @@ pruneInternal logger mdata now = do
867873
-- keep transactions that expire in the future.
868874
flt pe = _inmemPeExpires pe > now
869875
pruneBadMap = HashMap.filter (> now)
876+
877+
logValidateOneFailure :: (Logger logger)
878+
=> logger
879+
-> T.Text -- ^ location
880+
-> TransactionHash
881+
-> InsertError
882+
-> IO ()
883+
logValidateOneFailure logger loc (TransactionHash hsb) insertErr = do
884+
let abbrevReqKey = T.decodeUtf8 (BS.take 6 (SB.fromShort hsb))
885+
logFunctionText logger Info $ loc <> ": " <> abbrevReqKey <> "... failed mempool check. " <> sshow insertErr

0 commit comments

Comments
 (0)