{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

-- | Interface to the ledger layer
--
-- This module defines how to apply blocks to a ledger state, and re-exports
-- (from "Ouroboros.Consensus.Ledger.Basics") how to tick ledger states. These
-- are the two main operations we can do with a 'LedgerState'.
module Ouroboros.Consensus.Ledger.Abstract (
    -- * Type-level validation marker
    Validated
    -- * Apply block
  , ApplyBlock (..)
  , ComputeLedgerEvents (..)
  , UpdateLedger
  , defaultApplyBlockLedgerResult
  , defaultReapplyBlockLedgerResult
    -- * Derived
  , applyLedgerBlock
  , foldLedger
  , reapplyLedgerBlock
  , refoldLedger
  , tickThenApply
  , tickThenApplyLedgerResult
  , tickThenReapply
  , tickThenReapplyLedgerResult
    -- ** Short-hand
  , ledgerTipHash
  , ledgerTipPoint
  , ledgerTipSlot
    -- * Re-exports
  , module Ouroboros.Consensus.Ledger.Basics
  ) where

import           Control.Monad.Except
import qualified Control.State.Transition.Extended as STS
import           Data.Kind (Type)
import           GHC.Stack (HasCallStack)
import           Ouroboros.Consensus.Block.Abstract
import           Ouroboros.Consensus.Ledger.Basics
import           Ouroboros.Consensus.Ticked
import           Ouroboros.Consensus.Util

-- | " Validated " transaction or block
--
-- The ledger defines how to validate transactions and blocks. It's possible the
-- type before and after validation may be distinct (eg Alonzo transactions),
-- which originally motivated this family.
--
-- We also gain the related benefit that certain interface functions, such as
-- those that /reapply/ blocks, can have a more precise type now. TODO
--
-- Similarly, the Node-to-Client mini protocols can explicitly indicate that the
-- client trusts the blocks from the local server, by having the server send
-- 'Validated' blocks to the client. TODO
--
-- Note that validation has different implications for a transaction than for a
-- block. In particular, a validated transaction can be " reapplied " to
-- different ledger states, whereas a validated block must only be " reapplied "
-- to the exact same ledger state (eg as part of rebuilding from an on-disk
-- ledger snapshot).
--
-- Since the ledger defines validation, see the ledger details for concrete
-- examples of what determines the validity (wrt to a 'LedgerState') of a
-- transaction and/or block. Example properties include: a transaction's claimed
-- inputs exist and are still unspent, a block carries a sufficient
-- cryptographic signature, etc.
data family Validated x :: Type

{-------------------------------------------------------------------------------
  Apply block to ledger state
-------------------------------------------------------------------------------}

class ( IsLedger l
      , HeaderHash l ~ HeaderHash blk
      , HasHeader blk
      , HasHeader (Header blk)
      ) => ApplyBlock l blk where

  -- | Apply a block to the ledger state.
  --
  -- This is passed the ledger state ticked to the slot of the given block, so
  -- 'applyChainTickLedgerResult' has already been called.
  --
  -- Users of this function can set any validation level allowed by the
  -- @small-steps@ package. See "Control.State.Transition.Extended".
  applyBlockLedgerResultWithValidation ::
       HasCallStack
    => STS.ValidationPolicy
    -> ComputeLedgerEvents
    -> LedgerCfg l
    -> blk
    -> Ticked l
    -> Except (LedgerErr l) (LedgerResult l l)

  -- | Apply a block to the ledger state.
  --
  -- This is passed the ledger state ticked to the slot of the given block, so
  -- 'applyChainTickLedgerResult' has already been called.
  --
  -- This function will use 'ValidateAll' policy for calling the ledger rules.
  applyBlockLedgerResult ::
       HasCallStack
    => ComputeLedgerEvents
    -> LedgerCfg l
    -> blk
    -> Ticked l
    -> Except (LedgerErr l) (LedgerResult l l)

  -- | Re-apply a block to the very same ledger state it was applied in before.
  --
  -- Since a block can only be applied to a single, specific, ledger state,
  -- if we apply a previously applied block again it will be applied in the
  -- very same ledger state, and therefore can't possibly fail.
  --
  -- It is worth noting that since we already know that the block is valid in
  -- the provided ledger state, the ledger layer should not perform /any/
  -- validation checks. Thus this function will call the ledger rules with
  -- 'ValidateNone' policy.
  reapplyBlockLedgerResult ::
       HasCallStack
    => ComputeLedgerEvents
    -> LedgerCfg l
    -> blk
    -> Ticked l
    -> LedgerResult l l

defaultApplyBlockLedgerResult ::
     (HasCallStack, ApplyBlock l blk)
  => ComputeLedgerEvents
  -> LedgerCfg l
  -> blk
  -> Ticked l
  -> Except (LedgerErr l) (LedgerResult l l)
defaultApplyBlockLedgerResult :: forall l blk.
(HasCallStack, ApplyBlock l blk) =>
ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> Except (LedgerErr l) (LedgerResult l l)
defaultApplyBlockLedgerResult =
  ValidationPolicy
-> ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> ExceptT (LedgerErr l) Identity (LedgerResult l l)
forall l blk.
(ApplyBlock l blk, HasCallStack) =>
ValidationPolicy
-> ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> Except (LedgerErr l) (LedgerResult l l)
applyBlockLedgerResultWithValidation ValidationPolicy
STS.ValidateAll

defaultReapplyBlockLedgerResult ::
     (HasCallStack, ApplyBlock l blk)
  => (LedgerErr l -> LedgerResult l l)
  -> ComputeLedgerEvents
  -> LedgerCfg l
  -> blk
  -> Ticked l
  -> LedgerResult l l
defaultReapplyBlockLedgerResult :: forall l blk.
(HasCallStack, ApplyBlock l blk) =>
(LedgerErr l -> LedgerResult l l)
-> ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> LedgerResult l l
defaultReapplyBlockLedgerResult LedgerErr l -> LedgerResult l l
throwReapplyError =
       ((LedgerErr l -> LedgerResult l l)
-> (LedgerResult l l -> LedgerResult l l)
-> Either (LedgerErr l) (LedgerResult l l)
-> LedgerResult l l
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either LedgerErr l -> LedgerResult l l
throwReapplyError LedgerResult l l -> LedgerResult l l
forall a. a -> a
id (Either (LedgerErr l) (LedgerResult l l) -> LedgerResult l l)
-> (Except (LedgerErr l) (LedgerResult l l)
    -> Either (LedgerErr l) (LedgerResult l l))
-> Except (LedgerErr l) (LedgerResult l l)
-> LedgerResult l l
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Except (LedgerErr l) (LedgerResult l l)
-> Either (LedgerErr l) (LedgerResult l l)
forall e a. Except e a -> Either e a
runExcept)
  (Except (LedgerErr l) (LedgerResult l l) -> LedgerResult l l)
-> (ComputeLedgerEvents
    -> LedgerCfg l
    -> blk
    -> Ticked l
    -> Except (LedgerErr l) (LedgerResult l l))
-> ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> LedgerResult l l
forall y z x0 x1 x2 x3.
(y -> z)
-> (x0 -> x1 -> x2 -> x3 -> y) -> x0 -> x1 -> x2 -> x3 -> z
...: ValidationPolicy
-> ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> Except (LedgerErr l) (LedgerResult l l)
forall l blk.
(ApplyBlock l blk, HasCallStack) =>
ValidationPolicy
-> ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> Except (LedgerErr l) (LedgerResult l l)
applyBlockLedgerResultWithValidation ValidationPolicy
STS.ValidateNone

-- | Interaction with the ledger layer
class ApplyBlock (LedgerState blk) blk => UpdateLedger blk

{-------------------------------------------------------------------------------
  Derived functionality
-------------------------------------------------------------------------------}

-- | 'lrResult' after 'applyBlockLedgerResult'
applyLedgerBlock ::
     forall l blk.
     (ApplyBlock l blk, HasCallStack)
  => ComputeLedgerEvents
  -> LedgerCfg l
  -> blk
  -> Ticked l
  -> Except (LedgerErr l) l
applyLedgerBlock :: forall l blk.
(ApplyBlock l blk, HasCallStack) =>
ComputeLedgerEvents
-> LedgerCfg l -> blk -> Ticked l -> Except (LedgerErr l) l
applyLedgerBlock = (LedgerResult l l -> l)
-> ExceptT (LedgerErr l) Identity (LedgerResult l l)
-> ExceptT (LedgerErr l) Identity l
forall a b.
(a -> b)
-> ExceptT (LedgerErr l) Identity a
-> ExceptT (LedgerErr l) Identity b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap LedgerResult l l -> l
forall l a. LedgerResult l a -> a
lrResult (ExceptT (LedgerErr l) Identity (LedgerResult l l)
 -> ExceptT (LedgerErr l) Identity l)
-> (ComputeLedgerEvents
    -> LedgerCfg l
    -> blk
    -> Ticked l
    -> ExceptT (LedgerErr l) Identity (LedgerResult l l))
-> ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> ExceptT (LedgerErr l) Identity l
forall y z x0 x1 x2 x3.
(y -> z)
-> (x0 -> x1 -> x2 -> x3 -> y) -> x0 -> x1 -> x2 -> x3 -> z
...: ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> ExceptT (LedgerErr l) Identity (LedgerResult l l)
forall l blk.
(ApplyBlock l blk, HasCallStack) =>
ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> Except (LedgerErr l) (LedgerResult l l)
applyBlockLedgerResult

-- | 'lrResult' after 'reapplyBlockLedgerResult'
reapplyLedgerBlock ::
     forall l blk.
     (ApplyBlock l blk, HasCallStack)
  => ComputeLedgerEvents
  -> LedgerCfg l
  -> blk
  -> Ticked l
  -> l
reapplyLedgerBlock :: forall l blk.
(ApplyBlock l blk, HasCallStack) =>
ComputeLedgerEvents -> LedgerCfg l -> blk -> Ticked l -> l
reapplyLedgerBlock =
  LedgerResult l l -> l
forall l a. LedgerResult l a -> a
lrResult (LedgerResult l l -> l)
-> (ComputeLedgerEvents
    -> LedgerCfg l -> blk -> Ticked l -> LedgerResult l l)
-> ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> l
forall y z x0 x1 x2 x3.
(y -> z)
-> (x0 -> x1 -> x2 -> x3 -> y) -> x0 -> x1 -> x2 -> x3 -> z
...: ComputeLedgerEvents
-> LedgerCfg l -> blk -> Ticked l -> LedgerResult l l
forall l blk.
(ApplyBlock l blk, HasCallStack) =>
ComputeLedgerEvents
-> LedgerCfg l -> blk -> Ticked l -> LedgerResult l l
reapplyBlockLedgerResult

tickThenApplyLedgerResult ::
     ApplyBlock l blk
  => ComputeLedgerEvents
  -> LedgerCfg l
  -> blk
  -> l
  -> Except (LedgerErr l) (LedgerResult l l)
tickThenApplyLedgerResult :: forall l blk.
ApplyBlock l blk =>
ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> l
-> Except (LedgerErr l) (LedgerResult l l)
tickThenApplyLedgerResult ComputeLedgerEvents
opts LedgerCfg l
cfg blk
blk l
l = do
  let lrTick :: LedgerResult l (Ticked l)
lrTick = ComputeLedgerEvents
-> LedgerCfg l -> SlotNo -> l -> LedgerResult l (Ticked l)
forall l.
IsLedger l =>
ComputeLedgerEvents
-> LedgerCfg l -> SlotNo -> l -> LedgerResult l (Ticked l)
applyChainTickLedgerResult ComputeLedgerEvents
opts LedgerCfg l
cfg (blk -> SlotNo
forall b. HasHeader b => b -> SlotNo
blockSlot blk
blk) l
l
  LedgerResult l l
lrBlock <-   ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> Except (LedgerErr l) (LedgerResult l l)
forall l blk.
(ApplyBlock l blk, HasCallStack) =>
ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> Ticked l
-> Except (LedgerErr l) (LedgerResult l l)
applyBlockLedgerResult     ComputeLedgerEvents
opts LedgerCfg l
cfg            blk
blk  (LedgerResult l (Ticked l) -> Ticked l
forall l a. LedgerResult l a -> a
lrResult LedgerResult l (Ticked l)
lrTick)
  LedgerResult l l -> Except (LedgerErr l) (LedgerResult l l)
forall a. a -> ExceptT (LedgerErr l) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure LedgerResult {
      lrEvents :: [AuxLedgerEvent l]
lrEvents = LedgerResult l (Ticked l) -> [AuxLedgerEvent l]
forall l a. LedgerResult l a -> [AuxLedgerEvent l]
lrEvents LedgerResult l (Ticked l)
lrTick [AuxLedgerEvent l] -> [AuxLedgerEvent l] -> [AuxLedgerEvent l]
forall a. Semigroup a => a -> a -> a
<> LedgerResult l l -> [AuxLedgerEvent l]
forall l a. LedgerResult l a -> [AuxLedgerEvent l]
lrEvents LedgerResult l l
lrBlock
    , lrResult :: l
lrResult = LedgerResult l l -> l
forall l a. LedgerResult l a -> a
lrResult LedgerResult l l
lrBlock
    }

tickThenReapplyLedgerResult ::
     forall l blk.
     ApplyBlock l blk
  => ComputeLedgerEvents
  -> LedgerCfg l
  -> blk
  -> l
  -> LedgerResult l l
tickThenReapplyLedgerResult :: forall l blk.
ApplyBlock l blk =>
ComputeLedgerEvents -> LedgerCfg l -> blk -> l -> LedgerResult l l
tickThenReapplyLedgerResult ComputeLedgerEvents
evs LedgerCfg l
cfg blk
blk l
l =
  let lrTick :: LedgerResult l (Ticked l)
lrTick  = ComputeLedgerEvents
-> LedgerCfg l -> SlotNo -> l -> LedgerResult l (Ticked l)
forall l.
IsLedger l =>
ComputeLedgerEvents
-> LedgerCfg l -> SlotNo -> l -> LedgerResult l (Ticked l)
applyChainTickLedgerResult ComputeLedgerEvents
evs LedgerCfg l
cfg (blk -> SlotNo
forall b. HasHeader b => b -> SlotNo
blockSlot blk
blk) l
l
      lrBlock :: LedgerResult l l
lrBlock = ComputeLedgerEvents
-> LedgerCfg l -> blk -> Ticked l -> LedgerResult l l
forall l blk.
(ApplyBlock l blk, HasCallStack) =>
ComputeLedgerEvents
-> LedgerCfg l -> blk -> Ticked l -> LedgerResult l l
reapplyBlockLedgerResult   ComputeLedgerEvents
evs LedgerCfg l
cfg            blk
blk (LedgerResult l (Ticked l) -> Ticked l
forall l a. LedgerResult l a -> a
lrResult LedgerResult l (Ticked l)
lrTick)
  in LedgerResult {
      lrEvents :: [AuxLedgerEvent l]
lrEvents = LedgerResult l (Ticked l) -> [AuxLedgerEvent l]
forall l a. LedgerResult l a -> [AuxLedgerEvent l]
lrEvents LedgerResult l (Ticked l)
lrTick [AuxLedgerEvent l] -> [AuxLedgerEvent l] -> [AuxLedgerEvent l]
forall a. Semigroup a => a -> a -> a
<> LedgerResult l l -> [AuxLedgerEvent l]
forall l a. LedgerResult l a -> [AuxLedgerEvent l]
lrEvents LedgerResult l l
lrBlock
    , lrResult :: l
lrResult = LedgerResult l l -> l
forall l a. LedgerResult l a -> a
lrResult LedgerResult l l
lrBlock
    }

tickThenApply ::
     forall l blk.
     ApplyBlock l blk
  => ComputeLedgerEvents
  -> LedgerCfg l
  -> blk
  -> l
  -> Except (LedgerErr l) l
tickThenApply :: forall l blk.
ApplyBlock l blk =>
ComputeLedgerEvents
-> LedgerCfg l -> blk -> l -> Except (LedgerErr l) l
tickThenApply = (LedgerResult l l -> l)
-> ExceptT (LedgerErr l) Identity (LedgerResult l l)
-> ExceptT (LedgerErr l) Identity l
forall a b.
(a -> b)
-> ExceptT (LedgerErr l) Identity a
-> ExceptT (LedgerErr l) Identity b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap LedgerResult l l -> l
forall l a. LedgerResult l a -> a
lrResult (ExceptT (LedgerErr l) Identity (LedgerResult l l)
 -> ExceptT (LedgerErr l) Identity l)
-> (ComputeLedgerEvents
    -> LedgerCfg l
    -> blk
    -> l
    -> ExceptT (LedgerErr l) Identity (LedgerResult l l))
-> ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> l
-> ExceptT (LedgerErr l) Identity l
forall y z x0 x1 x2 x3.
(y -> z)
-> (x0 -> x1 -> x2 -> x3 -> y) -> x0 -> x1 -> x2 -> x3 -> z
...: ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> l
-> ExceptT (LedgerErr l) Identity (LedgerResult l l)
forall l blk.
ApplyBlock l blk =>
ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> l
-> Except (LedgerErr l) (LedgerResult l l)
tickThenApplyLedgerResult

tickThenReapply ::
     forall l blk.
     ApplyBlock l blk
  => ComputeLedgerEvents
  -> LedgerCfg l
  -> blk
  -> l
  -> l
tickThenReapply :: forall l blk.
ApplyBlock l blk =>
ComputeLedgerEvents -> LedgerCfg l -> blk -> l -> l
tickThenReapply = LedgerResult l l -> l
forall l a. LedgerResult l a -> a
lrResult (LedgerResult l l -> l)
-> (ComputeLedgerEvents
    -> LedgerCfg l -> blk -> l -> LedgerResult l l)
-> ComputeLedgerEvents
-> LedgerCfg l
-> blk
-> l
-> l
forall y z x0 x1 x2 x3.
(y -> z)
-> (x0 -> x1 -> x2 -> x3 -> y) -> x0 -> x1 -> x2 -> x3 -> z
...: ComputeLedgerEvents -> LedgerCfg l -> blk -> l -> LedgerResult l l
forall l blk.
ApplyBlock l blk =>
ComputeLedgerEvents -> LedgerCfg l -> blk -> l -> LedgerResult l l
tickThenReapplyLedgerResult

foldLedger ::
     ApplyBlock l blk
  => ComputeLedgerEvents -> LedgerCfg l -> [blk] -> l -> Except (LedgerErr l) l
foldLedger :: forall l blk.
ApplyBlock l blk =>
ComputeLedgerEvents
-> LedgerCfg l -> [blk] -> l -> Except (LedgerErr l) l
foldLedger = (blk -> l -> ExceptT (LedgerErr l) Identity l)
-> [blk] -> l -> ExceptT (LedgerErr l) Identity l
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> m b) -> [a] -> b -> m b
repeatedlyM ((blk -> l -> ExceptT (LedgerErr l) Identity l)
 -> [blk] -> l -> ExceptT (LedgerErr l) Identity l)
-> (ComputeLedgerEvents
    -> LedgerCfg l -> blk -> l -> ExceptT (LedgerErr l) Identity l)
-> ComputeLedgerEvents
-> LedgerCfg l
-> [blk]
-> l
-> ExceptT (LedgerErr l) Identity l
forall y z x0 x1. (y -> z) -> (x0 -> x1 -> y) -> x0 -> x1 -> z
.: ComputeLedgerEvents
-> LedgerCfg l -> blk -> l -> ExceptT (LedgerErr l) Identity l
forall l blk.
ApplyBlock l blk =>
ComputeLedgerEvents
-> LedgerCfg l -> blk -> l -> Except (LedgerErr l) l
tickThenApply

refoldLedger ::
     ApplyBlock l blk
  => ComputeLedgerEvents -> LedgerCfg l -> [blk] -> l -> l
refoldLedger :: forall l blk.
ApplyBlock l blk =>
ComputeLedgerEvents -> LedgerCfg l -> [blk] -> l -> l
refoldLedger = (blk -> l -> l) -> [blk] -> l -> l
forall a b. (a -> b -> b) -> [a] -> b -> b
repeatedly ((blk -> l -> l) -> [blk] -> l -> l)
-> (ComputeLedgerEvents -> LedgerCfg l -> blk -> l -> l)
-> ComputeLedgerEvents
-> LedgerCfg l
-> [blk]
-> l
-> l
forall y z x0 x1. (y -> z) -> (x0 -> x1 -> y) -> x0 -> x1 -> z
.: ComputeLedgerEvents -> LedgerCfg l -> blk -> l -> l
forall l blk.
ApplyBlock l blk =>
ComputeLedgerEvents -> LedgerCfg l -> blk -> l -> l
tickThenReapply

{-------------------------------------------------------------------------------
  Short-hand
-------------------------------------------------------------------------------}

ledgerTipPoint ::
     UpdateLedger blk
  => LedgerState blk -> Point blk
ledgerTipPoint :: forall blk. UpdateLedger blk => LedgerState blk -> Point blk
ledgerTipPoint = Point (LedgerState blk) -> Point blk
forall {k1} {k2} (b :: k1) (b' :: k2).
Coercible (HeaderHash b) (HeaderHash b') =>
Point b -> Point b'
castPoint (Point (LedgerState blk) -> Point blk)
-> (LedgerState blk -> Point (LedgerState blk))
-> LedgerState blk
-> Point blk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LedgerState blk -> Point (LedgerState blk)
forall l. GetTip l => l -> Point l
getTip

ledgerTipHash ::
     UpdateLedger blk
  => LedgerState blk -> ChainHash blk
ledgerTipHash :: forall blk. UpdateLedger blk => LedgerState blk -> ChainHash blk
ledgerTipHash = Point blk -> ChainHash blk
forall {k} (block :: k). Point block -> ChainHash block
pointHash (Point blk -> ChainHash blk)
-> (LedgerState blk -> Point blk)
-> LedgerState blk
-> ChainHash blk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LedgerState blk -> Point blk
forall blk. UpdateLedger blk => LedgerState blk -> Point blk
ledgerTipPoint

ledgerTipSlot ::
     UpdateLedger blk
  => LedgerState blk -> WithOrigin SlotNo
ledgerTipSlot :: forall blk.
UpdateLedger blk =>
LedgerState blk -> WithOrigin SlotNo
ledgerTipSlot = Point blk -> WithOrigin SlotNo
forall {k} (block :: k). Point block -> WithOrigin SlotNo
pointSlot (Point blk -> WithOrigin SlotNo)
-> (LedgerState blk -> Point blk)
-> LedgerState blk
-> WithOrigin SlotNo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LedgerState blk -> Point blk
forall blk. UpdateLedger blk => LedgerState blk -> Point blk
ledgerTipPoint