{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}

-- | Infrastructure required to run a node
--
-- The definitions in this module are independent from any specific protocol.
module Ouroboros.Consensus.Node.Run
  ( -- * SerialiseDisk
    ImmutableDbSerialiseConstraints
  , LedgerDbSerialiseConstraints
  , SerialiseDiskConstraints
  , VolatileDbSerialiseConstraints

    -- * SerialiseNodeToNode
  , SerialiseNodeToNodeConstraints (..)

    -- * SerialiseNodeToClient
  , SerialiseNodeToClientConstraints

    -- * RunNode
  , RunNode
  ) where

import Data.Typeable (Typeable)
import Ouroboros.Consensus.Block
import Ouroboros.Consensus.Config.SupportsNode
import Ouroboros.Consensus.HardFork.Abstract
import Ouroboros.Consensus.Ledger.Abstract
import Ouroboros.Consensus.Ledger.CommonProtocolParams
import Ouroboros.Consensus.Ledger.Inspect
import Ouroboros.Consensus.Ledger.Query
import Ouroboros.Consensus.Ledger.SupportsMempool
import Ouroboros.Consensus.Ledger.SupportsPeerSelection
import Ouroboros.Consensus.Ledger.SupportsProtocol
import Ouroboros.Consensus.Node.InitStorage
import Ouroboros.Consensus.Node.NetworkProtocolVersion
import Ouroboros.Consensus.Node.Serialisation
import Ouroboros.Consensus.Storage.ChainDB
  ( ImmutableDbSerialiseConstraints
  , SerialiseDiskConstraints
  , VolatileDbSerialiseConstraints
  )
import Ouroboros.Consensus.Storage.LedgerDB
import Ouroboros.Consensus.Storage.Serialisation
import Ouroboros.Consensus.Util (ShowProxy)
import Ouroboros.Network.Block (Serialised)

{-------------------------------------------------------------------------------
  RunNode proper
-------------------------------------------------------------------------------}

-- | Serialisation constraints needed by the node-to-node protocols
class
  ( ConvertRawHash blk
  , SerialiseNodeToNode blk blk
  , SerialiseNodeToNode blk (Header blk)
  , SerialiseNodeToNode blk (Serialised blk)
  , SerialiseNodeToNode blk (SerialisedHeader blk)
  , SerialiseNodeToNode blk (GenTx blk)
  , SerialiseNodeToNode blk (GenTxId blk)
  ) =>
  SerialiseNodeToNodeConstraints blk
  where
  -- | An upper bound on the size in bytes of the block corresponding to the
  -- header. This can be an overestimate, but not an underestimate.
  --
  -- The block fetch client uses this to estimate how bytes will be in flight.
  -- This is also used to limit the number of bytes accepted when downloading
  -- a block.
  --
  -- This is part of this class as it depends on the node-to-node serialisation
  -- format used for blocks.
  estimateBlockSize :: Header blk -> SizeInBytes

-- | Serialisation constraints needed by the node-to-client protocols
class
  ( Typeable blk
  , ConvertRawHash blk
  , SerialiseNodeToClient blk blk
  , SerialiseNodeToClient blk (Serialised blk)
  , SerialiseNodeToClient blk (GenTx blk)
  , SerialiseNodeToClient blk (GenTxId blk)
  , SerialiseNodeToClient blk SlotNo
  , SerialiseNodeToClient blk (ApplyTxErr blk)
  , SerialiseNodeToClient blk (SomeBlockQuery (BlockQuery blk))
  , SerialiseNodeToClient blk (LedgerConfig blk)
  , SerialiseBlockQueryResult blk BlockQuery
  ) =>
  SerialiseNodeToClientConstraints blk

class
  ( LedgerSupportsProtocol blk
  , InspectLedger blk
  , HasHardForkHistory blk
  , LedgerSupportsMempool blk
  , HasTxId (GenTx blk)
  , BlockSupportsLedgerQuery blk
  , SupportedNetworkProtocolVersion blk
  , ConfigSupportsNode blk
  , ConvertRawHash blk
  , CommonProtocolParams blk
  , HasBinaryBlockInfo blk
  , SerialiseDiskConstraints blk
  , SerialiseNodeToNodeConstraints blk
  , SerialiseNodeToClientConstraints blk
  , LedgerSupportsPeerSelection blk
  , NodeInitStorage blk
  , BlockSupportsMetrics blk
  , BlockSupportsDiffusionPipelining blk
  , BlockSupportsSanityCheck blk
  , Show (CannotForge blk)
  , Show (ForgeStateInfo blk)
  , Show (ForgeStateUpdateError blk)
  , ShowProxy blk
  , ShowProxy (ApplyTxErr blk)
  , ShowProxy (GenTx blk)
  , ShowProxy (Header blk)
  , ShowProxy (BlockQuery blk)
  , ShowProxy (TxId (GenTx blk))
  , (forall fp. ShowQuery (BlockQuery blk fp))
  , LedgerSupportsLedgerDB blk
  ) =>
  RunNode blk

-- This class is intentionally empty. It is not necessarily compositional - ie
-- the instance for 'HardForkBlock' might do more than merely delegate to the
-- instance for each era - but we want as many of its super classes as
-- possible to rely on compositional instances when possible. Not putting any
-- methods here helps encourage that.