-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Implementation of a Bitoin node. -- -- haskoin-node provides an implementation of the Bitcoin network -- protocol that allows you to synchronize headers (with SPV validation) -- and download merkle blocks and full blocks. This package can be used -- to implement wallets or other Bitcoin components that require talking -- to the Bitcoin network. It provides the following features: -- -- -- -- A wallet implementation using this package is available in -- haskoin-wallet. @package haskoin-node @version 0.4.2 module Network.Haskoin.Node.Checkpoints -- | Checkpoints from bitcoind reference implementation -- srccheckpoints.cpp presented as an IntMap. checkpointMap :: IntMap BlockHash -- | Checkpoints from bitcoind reference implementation -- srccheckpoints.cpp presented as a list. checkpointList :: [(Int, BlockHash)] -- | Verify that a block hash at a given height either matches an existing -- checkpoint or is not a checkpoint. verifyCheckpoint :: Int -> BlockHash -> Bool module Network.Haskoin.Node.HeaderTree data BlockChainAction BestChain :: ![NodeBlock] -> BlockChainAction [actionNodes] :: BlockChainAction -> ![NodeBlock] ChainReorg :: !NodeBlock -> ![NodeBlock] -> ![NodeBlock] -> BlockChainAction [actionSplitNode] :: BlockChainAction -> !NodeBlock [actionOldNodes] :: BlockChainAction -> ![NodeBlock] [actionNodes] :: BlockChainAction -> ![NodeBlock] SideChain :: ![NodeBlock] -> BlockChainAction [actionNodes] :: BlockChainAction -> ![NodeBlock] KnownChain :: ![NodeBlock] -> BlockChainAction [actionNodes] :: BlockChainAction -> ![NodeBlock] type BlockHeight = Word32 data NodeBlock type Timestamp = Word32 -- | Initialize the block header chain by inserting the genesis block if it -- doesn't already exist. initHeaderTree :: MonadIO m => SqlPersistT m () migrateHeaderTree :: Migration getBestBlock :: MonadIO m => SqlPersistT m NodeBlock getHeads :: MonadIO m => SqlPersistT m [NodeBlock] getBlockByHash :: MonadIO m => BlockHash -> SqlPersistT m (Maybe NodeBlock) -- | Finds the parent of a block. getParentBlock :: MonadIO m => NodeBlock -> SqlPersistT m (Maybe NodeBlock) -- | Return blockchain action to connect given block with best block. Count -- will limit the amount of blocks building up from split point towards -- the best block. getBlockWindow :: MonadIO m => NodeBlock -> NodeBlock -> Word32 -> SqlPersistT m BlockChainAction -- | Get node immediately at or after timestamp in main chain. getBlockAfterTime :: MonadIO m => Timestamp -> SqlPersistT m (Maybe NodeBlock) -- | Get all children for a block getChildBlocks :: MonadIO m => BlockHash -> SqlPersistT m [NodeBlock] -- | Get ancestor of specified block at given height. getBlockByHeight :: MonadIO m => NodeBlock -> BlockHeight -> SqlPersistT m (Maybe NodeBlock) -- | Get ancestors for specified block at given heights. getBlocksByHeight :: MonadIO m => NodeBlock -> [BlockHeight] -> SqlPersistT m [NodeBlock] -- | Get a range of block headers building up to specified block. If -- specified height is too large, an empty list will be returned. getBlocksFromHeight :: MonadIO m => NodeBlock -> Word32 -> BlockHeight -> SqlPersistT m [NodeBlock] -- | Get blocks at specified height in all chains. getBlocksAtHeight :: MonadIO m => BlockHeight -> SqlPersistT m [NodeBlock] -- | Put single block in database. putBlock :: MonadIO m => NodeBlock -> SqlPersistT m () -- | Put multiple blocks in database. putBlocks :: MonadIO m => [NodeBlock] -> SqlPersistT m () -- | Genesis block. genesisBlock :: NodeBlock -- | Get node height and chain common to both given. splitBlock :: MonadIO m => NodeBlock -> NodeBlock -> SqlPersistT m NodeBlock -- | Find the split point between two nodes. It also returns the two -- partial chains leading from the split point to the respective nodes. -- Tuples must contain a block node and the count of nodes that should be -- returned from the split towards that block. 0 means all. splitChains :: MonadIO m => (NodeBlock, Word32) -> (NodeBlock, Word32) -> SqlPersistT m (NodeBlock, [NodeBlock], [NodeBlock]) -- | Create a block node data structure from a block header. nodeBlock :: NodeBlock -> Word32 -> BlockHeader -> NodeBlock nodeBlockHeight :: NodeBlock -> BlockHeight nodeHash :: NodeBlock -> BlockHash nodeHeader :: NodeBlock -> BlockHeader nodePrev :: NodeBlock -> BlockHash nodeTimestamp :: NodeBlock -> Timestamp nodeWork :: NodeBlock -> Work nodeHeight :: NodeBlock -> BlockHeight nodeChain :: NodeBlock -> Word32 -- | Returns True if the action is a best chain. isBestChain :: BlockChainAction -> Bool -- | Returns True if the action is a chain reorg. isChainReorg :: BlockChainAction -> Bool -- | Returns True if the action is a side chain. isSideChain :: BlockChainAction -> Bool -- | Returns True if the action is a known chain. isKnownChain :: BlockChainAction -> Bool -- | Connect a block header to this block header chain. Corresponds to -- bitcoind function ProcessBlockHeader and AcceptBlockHeader in -- main.cpp. connectHeader :: MonadIO m => NodeBlock -> BlockHeader -> Timestamp -> SqlPersistT m (Either String BlockChainAction) -- | A more efficient way of connecting a list of block headers than -- connecting them individually. The list of block headers have must form -- a valid chain. connectHeaders :: MonadIO m => NodeBlock -> [BlockHeader] -> Timestamp -> SqlPersistT m (Either String BlockChainAction) -- | Returns a BlockLocator object for a given block hash. blockLocator :: MonadIO m => NodeBlock -> SqlPersistT m BlockLocator -- | Remove all other chains from database and return updated best block -- node. pruneChain :: MonadIO m => NodeBlock -> SqlPersistT m NodeBlock instance GHC.Classes.Eq Network.Haskoin.Node.HeaderTree.BlockChainAction instance GHC.Show.Show Network.Haskoin.Node.HeaderTree.BlockChainAction module Network.Haskoin.Node.STM type MerkleTxs = [TxHash] type NodeT = ReaderT SharedNodeState type PeerId = Unique type PeerHostScore = Word32 newtype ShowPeerId ShowPeerId :: PeerId -> ShowPeerId [getShowPeerId] :: ShowPeerId -> PeerId runSql :: (MonadBaseControl IO m) => SqlPersistT m a -> Either SqlBackend ConnectionPool -> m a runSqlNodeT :: (MonadBaseControl IO m) => SqlPersistT m a -> NodeT m a getNodeState :: (MonadLoggerIO m, MonadBaseControl IO m) => Either SqlBackend ConnectionPool -> m SharedNodeState runNodeT :: Monad m => NodeT m a -> SharedNodeState -> m a withNodeT :: (MonadLoggerIO m, MonadBaseControl IO m) => NodeT m a -> Either SqlBackend ConnectionPool -> m a atomicallyNodeT :: MonadIO m => NodeT STM a -> NodeT m a data PeerHostSession PeerHostSession :: !PeerHostScore -> !Int -> ![String] -> PeerHostSession [peerHostSessionScore] :: PeerHostSession -> !PeerHostScore [peerHostSessionReconnect] :: PeerHostSession -> !Int -- | Important host log messages that should appear in status command [peerHostSessionLog] :: PeerHostSession -> ![String] data SharedNodeState SharedNodeState :: !(TVar (Map PeerId (TVar PeerSession))) -> !(TVar (Map PeerHost (TVar PeerHostSession))) -> !(TVar BlockHeight) -> !(TMVar (PeerId, Headers)) -> !(TVar (Maybe PeerId)) -> !(TVar (Maybe PeerId)) -> !Lock -> !(TVar NodeBlock) -> !(TVar NodeBlock) -> !(TVar (Map TxHash [(PeerId, PeerHost)])) -> !(TVar (Maybe (BloomFilter, Int))) -> !(TBMChan (PeerId, PeerHost, BlockHash)) -> !(TBMChan (PeerId, PeerHost, Tx)) -> !(TMVar (Either Timestamp BlockHeight)) -> !(TVar Bool) -> !(Either SqlBackend ConnectionPool) -> SharedNodeState -- | Map of all active peers and their sessions [sharedPeerMap] :: SharedNodeState -> !(TVar (Map PeerId (TVar PeerSession))) -- | The peer that is currently syncing the block headers [sharedHostMap] :: SharedNodeState -> !(TVar (Map PeerHost (TVar PeerHostSession))) -- | The current height of the network [sharedNetworkHeight] :: SharedNodeState -> !(TVar BlockHeight) -- | Block headers sent from a peer [sharedHeaders] :: SharedNodeState -> !(TMVar (PeerId, Headers)) -- | Peer currently syncing headers [sharedHeaderPeer] :: SharedNodeState -> !(TVar (Maybe PeerId)) -- | Peer currently downloading merkle blocks [sharedMerklePeer] :: SharedNodeState -> !(TVar (Maybe PeerId)) -- | Lock on the header syncing process [sharedSyncLock] :: SharedNodeState -> !Lock -- | Our best block header [sharedBestHeader] :: SharedNodeState -> !(TVar NodeBlock) -- | Our best merkle block's height [sharedBestBlock] :: SharedNodeState -> !(TVar NodeBlock) -- | List of Tx GetData requests [sharedTxGetData] :: SharedNodeState -> !(TVar (Map TxHash [(PeerId, PeerHost)])) -- | Bloom filter [sharedBloomFilter] :: SharedNodeState -> !(TVar (Maybe (BloomFilter, Int))) -- | Channel containing all the block tickles received from peers [sharedTickleChan] :: SharedNodeState -> !(TBMChan (PeerId, PeerHost, BlockHash)) -- | Transaction channel [sharedTxChan] :: SharedNodeState -> !(TBMChan (PeerId, PeerHost, Tx)) -- | Rescan requests from a timestamp or from a block height [sharedRescan] :: SharedNodeState -> !(TMVar (Either Timestamp BlockHeight)) -- | Did we do a Mempool sync ? [sharedMempool] :: SharedNodeState -> !(TVar Bool) [sharedSqlBackend] :: SharedNodeState -> !(Either SqlBackend ConnectionPool) type PingNonce = Word64 data PeerSession PeerSession :: !Bool -> !(Maybe Version) -> !BlockHeight -> !(TBMChan Message) -> !PeerHost -> !ThreadId -> !(TBMChan (Either (MerkleBlock, MerkleTxs) Tx)) -> !(TVar [PingNonce]) -> !(Maybe NominalDiffTime) -> PeerSession -- | True if the peer is connected (completed the handshake) [peerSessionConnected] :: PeerSession -> !Bool -- | Contains the version message that we received from the peer [peerSessionVersion] :: PeerSession -> !(Maybe Version) -- | Current known height of the peer [peerSessionHeight] :: PeerSession -> !BlockHeight -- | Message channel to send messages to the peer [peerSessionChan] :: PeerSession -> !(TBMChan Message) -- | Host to which this peer is connected [peerSessionHost] :: PeerSession -> !PeerHost -- | Peer ThreadId [peerSessionThreadId] :: PeerSession -> !ThreadId -- | Merkle block/Merkle transaction channel [peerSessionMerkleChan] :: PeerSession -> !(TBMChan (Either (MerkleBlock, MerkleTxs) Tx)) -- | Time at which we requested pings [peerSessionPings] :: PeerSession -> !(TVar [PingNonce]) -- | Ping scores for this peer (round trip times) [peerSessionScore] :: PeerSession -> !(Maybe NominalDiffTime) data PeerHost PeerHost :: !String -> !Int -> PeerHost [peerHost] :: PeerHost -> !String [peerPort] :: PeerHost -> !Int peerHostString :: PeerHost -> String data PeerStatus PeerStatus :: !Int -> !PeerHost -> !Bool -> !BlockHeight -> !(Maybe Word32) -> !(Maybe String) -> !(Maybe String) -> !(Maybe PeerHostScore) -> !Bool -> !Bool -> ![PingNonce] -> !(Maybe Int) -> !(Maybe [String]) -> PeerStatus [peerStatusPeerId] :: PeerStatus -> !Int [peerStatusHost] :: PeerStatus -> !PeerHost [peerStatusConnected] :: PeerStatus -> !Bool [peerStatusHeight] :: PeerStatus -> !BlockHeight [peerStatusProtocol] :: PeerStatus -> !(Maybe Word32) [peerStatusUserAgent] :: PeerStatus -> !(Maybe String) [peerStatusPing] :: PeerStatus -> !(Maybe String) [peerStatusDoSScore] :: PeerStatus -> !(Maybe PeerHostScore) [peerStatusHaveMerkles] :: PeerStatus -> !Bool [peerStatusHaveMessage] :: PeerStatus -> !Bool [peerStatusPingNonces] :: PeerStatus -> ![PingNonce] [peerStatusReconnectTimer] :: PeerStatus -> !(Maybe Int) [peerStatusLog] :: PeerStatus -> !(Maybe [String]) data NodeStatus NodeStatus :: ![PeerStatus] -> !BlockHeight -> !BlockHash -> !BlockHeight -> !BlockHash -> !BlockHeight -> !Int -> !(Maybe Int) -> !(Maybe Int) -> !Bool -> !Bool -> !Bool -> ![TxHash] -> !(Maybe (Either Timestamp BlockHeight)) -> !Bool -> !Bool -> NodeStatus [nodeStatusPeers] :: NodeStatus -> ![PeerStatus] [nodeStatusNetworkHeight] :: NodeStatus -> !BlockHeight [nodeStatusBestHeader] :: NodeStatus -> !BlockHash [nodeStatusBestHeaderHeight] :: NodeStatus -> !BlockHeight [nodeStatusBestBlock] :: NodeStatus -> !BlockHash [nodeStatusBestBlockHeight] :: NodeStatus -> !BlockHeight [nodeStatusBloomSize] :: NodeStatus -> !Int [nodeStatusHeaderPeer] :: NodeStatus -> !(Maybe Int) [nodeStatusMerklePeer] :: NodeStatus -> !(Maybe Int) [nodeStatusHaveHeaders] :: NodeStatus -> !Bool [nodeStatusHaveTickles] :: NodeStatus -> !Bool [nodeStatusHaveTxs] :: NodeStatus -> !Bool [nodeStatusGetData] :: NodeStatus -> ![TxHash] [nodeStatusRescan] :: NodeStatus -> !(Maybe (Either Timestamp BlockHeight)) [nodeStatusMempool] :: NodeStatus -> !Bool [nodeStatusSyncLock] :: NodeStatus -> !Bool tryGetPeerSession :: PeerId -> NodeT STM (Maybe PeerSession) getPeerSession :: PeerId -> NodeT STM PeerSession newPeerSession :: PeerId -> PeerSession -> NodeT STM () modifyPeerSession :: PeerId -> (PeerSession -> PeerSession) -> NodeT STM () removePeerSession :: PeerId -> NodeT STM (Maybe PeerSession) getHostSession :: PeerHost -> NodeT STM (Maybe PeerHostSession) modifyHostSession :: PeerHost -> (PeerHostSession -> PeerHostSession) -> NodeT STM () newHostSession :: PeerHost -> PeerHostSession -> NodeT STM () bannedScore :: PeerHostScore minorDoS :: PeerHostScore -> PeerHostScore moderateDoS :: PeerHostScore -> PeerHostScore severeDoS :: PeerHostScore -> PeerHostScore isHostScoreBanned :: PeerHostScore -> Bool orElseNodeT :: NodeT STM a -> NodeT STM a -> NodeT STM a readTVarS :: (SharedNodeState -> TVar a) -> NodeT STM a writeTVarS :: (SharedNodeState -> TVar a) -> a -> NodeT STM () takeTMVarS :: (SharedNodeState -> TMVar a) -> NodeT STM a readTMVarS :: (SharedNodeState -> TMVar a) -> NodeT STM a tryReadTMVarS :: (SharedNodeState -> TMVar a) -> NodeT STM (Maybe a) putTMVarS :: (SharedNodeState -> TMVar a) -> a -> NodeT STM () tryPutTMVarS :: (SharedNodeState -> TMVar a) -> a -> NodeT STM Bool swapTMVarS :: (SharedNodeState -> TMVar a) -> a -> NodeT STM () isEmptyTMVarS :: (SharedNodeState -> TMVar a) -> NodeT STM Bool data NodeException NodeExceptionBanned :: NodeException NodeExceptionConnected :: NodeException NodeExceptionInvalidPeer :: !ShowPeerId -> NodeException NodeExceptionPeerNotConnected :: !ShowPeerId -> NodeException NodeException :: !String -> NodeException isNodeException :: SomeException -> Bool catchAny :: MonadBaseControl IO m => m a -> (SomeException -> m a) -> m a catchAny_ :: MonadBaseControl IO m => m () -> m () instance GHC.Show.Show Network.Haskoin.Node.STM.NodeException instance Data.Aeson.Types.ToJSON.ToJSON Network.Haskoin.Node.STM.NodeStatus instance Data.Aeson.Types.FromJSON.FromJSON Network.Haskoin.Node.STM.NodeStatus instance GHC.Exception.Exception Network.Haskoin.Node.STM.NodeException instance Data.Aeson.Types.ToJSON.ToJSON Network.Haskoin.Node.STM.PeerStatus instance Data.Aeson.Types.FromJSON.FromJSON Network.Haskoin.Node.STM.PeerStatus instance Data.Aeson.Types.ToJSON.ToJSON Network.Haskoin.Node.STM.PeerHost instance Data.Aeson.Types.FromJSON.FromJSON Network.Haskoin.Node.STM.PeerHost instance Control.DeepSeq.NFData Network.Haskoin.Node.STM.PeerHost instance GHC.Classes.Ord Network.Haskoin.Node.STM.PeerHost instance GHC.Classes.Eq Network.Haskoin.Node.STM.PeerHost instance GHC.Classes.Eq Network.Haskoin.Node.STM.ShowPeerId instance GHC.Show.Show Network.Haskoin.Node.STM.ShowPeerId instance Control.DeepSeq.NFData Network.Haskoin.Node.STM.PeerHostSession instance Control.DeepSeq.NFData Network.Haskoin.Node.STM.PeerSession module Network.Haskoin.Node.Peer minProtocolVersion :: Word32 startPeer :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerHost -> NodeT m () startReconnectPeer :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerHost -> NodeT m () startPeerPid :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerId -> PeerHost -> NodeT m () isPeerHostBanned :: PeerHost -> NodeT STM Bool isPeerHostConnected :: PeerHost -> NodeT STM Bool -- | Decode messages sent from the remote host and send them to the peers -- main message queue for processing. If we receive invalid messages, -- this function will also notify the PeerManager about a misbehaving -- remote host. decodeMessage :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerId -> PeerHost -> Sink ByteString (StateT (Maybe (MerkleBlock, MerkleTxs)) (NodeT m)) () processMessage :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerId -> PeerHost -> Message -> StateT (Maybe (MerkleBlock, MerkleTxs)) (NodeT m) () processInvMessage :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerId -> PeerHost -> Inv -> NodeT m () -- | Encode message that are being sent to the remote host. encodeMessage :: MonadLoggerIO m => Conduit Message (NodeT m) ByteString peerPing :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerId -> PeerHost -> NodeT m () isBloomDisabled :: Version -> Bool peerHandshake :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerId -> PeerHost -> TBMChan Message -> NodeT m () waitPeerVersion :: PeerId -> NodeT STM Version disconnectPeer :: (MonadLoggerIO m) => PeerId -> PeerHost -> NodeT m () waitPeerAvailable :: PeerId -> NodeT STM () waitBloomFilter :: NodeT STM BloomFilter sendBloomFilter :: BloomFilter -> Int -> NodeT STM () getMedianHeight :: NodeT STM BlockHeight updateNetworkHeight :: NodeT STM () getPeers :: NodeT STM [(PeerId, PeerSession)] getConnectedPeers :: NodeT STM [(PeerId, PeerSession)] getPeersAtNetHeight :: NodeT STM [(PeerId, PeerSession)] getPeersAtHeight :: (BlockHeight -> Bool) -> NodeT STM [(PeerId, PeerSession)] trySendMessage :: PeerId -> Message -> NodeT STM Bool sendMessage :: PeerId -> Message -> NodeT STM () sendMessageAll :: Message -> NodeT STM () getNetworkHeight :: NodeT STM BlockHeight misbehaving :: (MonadLoggerIO m) => PeerId -> PeerHost -> (PeerHostScore -> PeerHostScore) -> String -> NodeT m () raceTimeout :: (MonadIO m, MonadBaseControl IO m) => Int -> m a -> m b -> m (Either a b) formatPid :: PeerId -> PeerHost -> String -> Text module Network.Haskoin.Node.BlockChain startSPVNode :: (MonadLoggerIO m, MonadBaseControl IO m) => [PeerHost] -> BloomFilter -> Int -> NodeT m () txSource :: (MonadLoggerIO m, MonadBaseControl IO m) => Source (NodeT m) Tx handleGetData :: (MonadLoggerIO m, MonadBaseControl IO m) => (TxHash -> m (Maybe Tx)) -> NodeT m () broadcastTxs :: (MonadLoggerIO m, MonadBaseControl IO m) => [TxHash] -> NodeT m () rescanTs :: Timestamp -> NodeT STM () rescanHeight :: BlockHeight -> NodeT STM () merkleDownload :: (MonadLoggerIO m, MonadBaseControl IO m) => BlockHash -> Word32 -> NodeT m (BlockChainAction, Source (NodeT m) (Either (MerkleBlock, MerkleTxs) Tx)) -- | Perform some actions only when headers have been synced. merkleSyncedActions :: (MonadLoggerIO m, MonadBaseControl IO m) => BlockHash -> NodeT m () waitHeight :: BlockHeight -> NodeT STM () waitFastCatchup :: Timestamp -> NodeT STM () waitNewBlock :: BlockHash -> NodeT STM () tryMerkleDwnHeight :: (MonadLoggerIO m, MonadBaseControl IO m) => NodeBlock -> Word32 -> NodeT m (Maybe (BlockChainAction, Source (NodeT m) (Either (MerkleBlock, MerkleTxs) Tx))) tryMerkleDwnTimestamp :: (MonadLoggerIO m, MonadBaseControl IO m) => Timestamp -> Word32 -> NodeT m (Maybe (BlockChainAction, Source (NodeT m) (Either (MerkleBlock, MerkleTxs) Tx))) tryMerkleDwnBlock :: (MonadLoggerIO m, MonadBaseControl IO m) => NodeBlock -> Word32 -> NodeT m (Maybe (BlockChainAction, Source (NodeT m) (Either (MerkleBlock, MerkleTxs) Tx))) peerMerkleDownload :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerId -> PeerHost -> BlockChainAction -> Source (NodeT m) (Either (MerkleBlock, MerkleTxs) Tx) processTickles :: (MonadLoggerIO m, MonadBaseControl IO m) => NodeT m () waitTickle :: NodeT STM (PeerId, PeerHost, BlockHash) syncedHeight :: MonadIO m => NodeT m (Bool, Word32) headerSync :: (MonadLoggerIO m, MonadBaseControl IO m) => NodeT m () peerHeaderSyncLimit :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerId -> PeerHost -> Int -> NodeT m Bool peerHeaderSyncFull :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerId -> PeerHost -> NodeT m () areBlocksSynced :: BlockHash -> NodeT STM Bool areHeadersSynced :: NodeT STM Bool -- | Sync one batch of headers from the given peer. Accept the result of a -- previous peerHeaderSync to correctly compute block locators in the -- presence of side chains. peerHeaderSync :: (MonadLoggerIO m, MonadBaseControl IO m) => PeerId -> PeerHost -> Maybe BlockChainAction -> NodeT m (Maybe BlockChainAction) nodeStatus :: NodeT STM NodeStatus peerStatus :: (PeerId, PeerSession) -> NodeT STM PeerStatus