packages feed

haskoin-node 1.3.0 → 1.3.1

raw patch · 3 files changed

+47/−31 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Haskoin.Node: runChainT :: ChainT m a -> Chain -> m a
+ Haskoin.Node: type ChainT (m :: Type -> Type) = ReaderT Chain m

Files

CHANGELOG.md view
@@ -4,6 +4,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.3.1] - 2026-08-12++### Added++- Add monad transformers to support haskoin-store.+ ## [1.3.0] - 2026-08-12  ### Changed
haskoin-node.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           haskoin-node-version:        1.3.0+version:        1.3.1 synopsis:       P2P library for Bitcoin and Bitcoin Cash description:    Please see the README on GitHub at <https://github.com/jprupp/haskoin-node#readme> category:       Bitcoin, Finance, Network
src/Haskoin/Node/Chain.hs view
@@ -20,6 +20,8 @@   ( ChainConfig (..),     ChainEvent (..),     Chain,+    ChainT,+    runChainT,     withChain,     chainGetBlock,     chainGetBest,@@ -39,6 +41,7 @@ import Control.Concurrent.STM import Control.Logging import Control.Monad (forM_, forever, guard, when)+import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Trans.Reader import Data.ByteString qualified as B import Data.Function (on)@@ -150,29 +153,29 @@     return BestBlockKey   put BestBlockKey = putWord8 0x91 -type ChainM = ReaderT ChainConfig IO+type ChainT m = ReaderT Chain m -chainM :: ChainConfig -> ChainM a -> IO a-chainM cfg m = runReaderT m cfg+runChainT :: ChainT m a -> Chain -> m a+runChainT = runReaderT -instance BlockHeaders ChainM where-  addBlockHeader bn = ReaderT $ \ChainConfig {db, cf} -> do+instance MonadIO m => BlockHeaders (ReaderT ChainConfig m) where+  addBlockHeader bn = ReaderT $ \ChainConfig {db, cf} -> liftIO $ do     case cf of       Nothing -> insert db (BlockHeaderKey h) bn       Just cf' -> insertCF db cf' (BlockHeaderKey h) bn     where       h = headerHash bn.header-  getBlockHeader bh = ReaderT $ \ChainConfig {db, cf} -> do+  getBlockHeader bh = ReaderT $ \ChainConfig {db, cf} -> liftIO $ do     retrieveCommon db cf (BlockHeaderKey bh)-  getBestBlockHeader = ReaderT $ \ChainConfig {db, cf} -> do+  getBestBlockHeader = ReaderT $ \ChainConfig {db, cf} -> liftIO $ do     retrieveCommon db cf BestBlockKey >>= \case       Nothing -> error "Could not get best block from database"       Just b -> return b-  setBestBlockHeader bn = ReaderT $ \ChainConfig {db, cf} -> do+  setBestBlockHeader bn = ReaderT $ \ChainConfig {db, cf} -> liftIO $ do     case cf of       Nothing -> insert db BestBlockKey bn       Just cf' -> insertCF db cf' BestBlockKey bn-  addBlockHeaders bns = ReaderT $ \ChainConfig {db, cf} -> do+  addBlockHeaders bns = ReaderT $ \ChainConfig {db, cf} -> liftIO $ do     writeBatch db (map (f cf) bns)     where       h bn = headerHash bn.header@@ -180,6 +183,13 @@         Nothing -> insertOp (BlockHeaderKey (h bn)) bn         Just cf' -> insertOpCF cf' (BlockHeaderKey (h bn)) bn +instance MonadIO m => BlockHeaders (ChainT m) where+  addBlockHeader bn = withReaderT (.config) (addBlockHeader bn)+  getBlockHeader bh = withReaderT (.config) (getBlockHeader bh)+  getBestBlockHeader = withReaderT (.config) getBestBlockHeader+  setBestBlockHeader bn = withReaderT (.config) (setBestBlockHeader bn)+  addBlockHeaders bns = withReaderT (.config) (addBlockHeaders bns)+ withChain :: ChainConfig -> (Chain -> IO a) -> IO a withChain cfg action = do   (inbox, mailbox) <- newMailbox@@ -199,12 +209,12 @@     main_loop ch inbox =       withSyncLoop ch.mailbox (run ch inbox)     run ch inbox = do-      chainM cfg getBestBlockHeader+      runReaderT getBestBlockHeader cfg         >>= chainEvent cfg.pub . ChainBestBlock       forever $ do         debugS "Chain" "Awaiting event..."         msg <- receive inbox-        chainMessage ch msg+        chainConfigMessage ch msg  chainEvent :: Publisher ChainEvent -> ChainEvent -> IO () chainEvent pub e = do@@ -223,14 +233,14 @@     ("Processing " <> cs (show len) <> " headers from peer: " <> p.label)   let net = ch.config.net   now <- getCurrentTime-  pbest <- chainM ch.config getBestBlockHeader+  pbest <- runReaderT getBestBlockHeader ch.config   importHeaders ch now hs >>= \case     Nothing -> do       warnS "Chain" ("Could not connect headers from peer: " <> p.label)       killPeer p     Just done -> do       setLastReceived ch.state-      best <- chainM ch.config getBestBlockHeader+      best <- runReaderT getBestBlockHeader ch.config       when (pbest.header /= best.header) $         chainEvent ch.config.pub (ChainBestBlock best)       if done@@ -257,7 +267,7 @@   notifySynced ch >>= \case     False -> return ()     True ->-      chainM ch.config getBestBlockHeader+      runReaderT getBestBlockHeader ch.config         >>= chainEvent ch.config.pub . ChainSynced  syncPeer :: Chain -> Peer -> IO ()@@ -280,26 +290,26 @@         False -> return Nothing         True -> do           debugS "Chain" ("Locked peer: " <> p.label)-          h <- chainM ch.config getBestBlockHeader+          h <- runReaderT getBestBlockHeader ch.config           Just <$> syncHeaders ch t h p     syncing_me t m = do       h <- case m of-        Nothing -> chainM ch.config getBestBlockHeader+        Nothing -> runReaderT getBestBlockHeader ch.config         Just h -> return h       Just <$> syncHeaders ch t h p -chainMessage :: Chain -> ChainMessage -> IO ()-chainMessage ch (ChainHeaders p hs) =+chainConfigMessage :: Chain -> ChainMessage -> IO ()+chainConfigMessage ch (ChainHeaders p hs) =   processHeaders ch p hs-chainMessage ch (ChainPeerConnected p) = do+chainConfigMessage ch (ChainPeerConnected p) = do   debugS "Chain" ("Peer connected: " <> p.label)   addPeer ch.state p   syncNewPeer ch-chainMessage ch (ChainPeerDisconnected p) = do+chainConfigMessage ch (ChainPeerDisconnected p) = do   debugS "Chain" ("Peer disconnected: " <> p.label)   finishPeer ch.state p   syncNewPeer ch-chainMessage ch ChainPing = do+chainConfigMessage ch ChainPing = do   debugS "Chain" "Internal clock event"   let to = ch.config.timeout   now <- getCurrentTime@@ -337,7 +347,7 @@     Nothing -> insert db ChainDataVersionKey dataVersion     Just cf' -> insertCF db cf' ChainDataVersionKey dataVersion   retrieveCommon db cf BestBlockKey >>= \b ->-    when (isNothing (b :: Maybe BlockNode)) . chainM cfg $ do+    when (isNothing (b :: Maybe BlockNode)) . flip runReaderT cfg $ do       addBlockHeader (genesisNode net)       setBestBlockHeader (genesisNode net) @@ -380,8 +390,8 @@   where     set_best bb ChainSync {..} = ChainSync {best = bb, ..}     timestamp = floor (utcTimeToPOSIXSeconds now)-    connect = chainM ch.config (connectBlocks ch.config.net timestamp hs)-    get_last = chainM ch.config $ getBlockHeader (headerHash (last hs))+    connect = runReaderT (connectBlocks ch.config.net timestamp hs) ch.config+    get_last = runReaderT (getBlockHeader (headerHash (last hs))) ch.config  -- | Check if best block header is in sync with the rest of the block chain by -- comparing the best block with the current time, verifying that there are no@@ -392,7 +402,7 @@ -- 'True'. notifySynced :: Chain -> IO Bool notifySynced ch = do-  bb <- chainM ch.config getBestBlockHeader+  bb <- runReaderT getBestBlockHeader ch.config   df <- (`diffUTCTime` block_time bb) <$> getCurrentTime   atomically $ do     s <- readTVar ch.state@@ -434,7 +444,7 @@                 },           peers = delete p s.peers         }-  loc <- chainM ch.config (blockLocator bb)+  loc <- runReaderT (blockLocator bb) ch.config   return     GetHeaders       { version = myVersion,@@ -528,15 +538,15 @@  -- | Get a block header from the block chain. chainGetBlock :: Chain -> BlockHash -> IO (Maybe BlockNode)-chainGetBlock ch bh = chainM ch.config (getBlockHeader bh)+chainGetBlock ch bh = runReaderT (getBlockHeader bh) ch.config  -- | Get best block header from chain process. chainGetBest :: Chain -> IO BlockNode-chainGetBest ch = chainM ch.config getBestBlockHeader+chainGetBest ch = runReaderT getBestBlockHeader ch.config  -- | Get ancestor of 'BlockNode' at 'BlockHeight' from chain process. chainGetAncestor :: Chain -> BlockHeight -> BlockNode -> IO (Maybe BlockNode)-chainGetAncestor ch h bn = chainM ch.config (getAncestor h bn)+chainGetAncestor ch h bn = runReaderT (getAncestor h bn) ch.config  -- | Get parents of 'BlockNode' starting at 'BlockHeight' from chain process. chainGetParents :: Chain -> BlockHeight -> BlockNode -> IO [BlockNode]@@ -553,7 +563,7 @@  -- | Get last common block from chain process. chainGetSplitBlock :: Chain -> BlockNode -> BlockNode -> IO BlockNode-chainGetSplitBlock ch l r = chainM ch.config (splitPoint l r)+chainGetSplitBlock ch l r = runReaderT (splitPoint l r) ch.config  -- | Notify chain that a new peer is connected. chainPeerConnected :: Chain -> Peer -> IO ()