{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}

module Cardano.Chain.Common.ChainDifficulty (
  ChainDifficulty (..),
  dropChainDifficulty,
) where

import Cardano.Ledger.Binary (
  DecCBOR (..),
  Dropper,
  EncCBOR (..),
  FromCBOR (..),
  ToCBOR (..),
  dropWord64,
  encodeListLen,
  enforceSize,
  fromByronCBOR,
  toByronCBOR,
 )
import Cardano.Prelude
import Data.Aeson (ToJSON)
import Formatting.Buildable (Buildable)
import NoThunks.Class (NoThunks (..))

-- | Chain difficulty represents necessary effort to generate a
-- chain. In the simplest case it can be number of blocks in chain.
newtype ChainDifficulty = ChainDifficulty
  { ChainDifficulty -> Word64
unChainDifficulty :: Word64
  }
  deriving (Int -> ChainDifficulty -> ShowS
[ChainDifficulty] -> ShowS
ChainDifficulty -> String
(Int -> ChainDifficulty -> ShowS)
-> (ChainDifficulty -> String)
-> ([ChainDifficulty] -> ShowS)
-> Show ChainDifficulty
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ChainDifficulty -> ShowS
showsPrec :: Int -> ChainDifficulty -> ShowS
$cshow :: ChainDifficulty -> String
show :: ChainDifficulty -> String
$cshowList :: [ChainDifficulty] -> ShowS
showList :: [ChainDifficulty] -> ShowS
Show, ChainDifficulty -> ChainDifficulty -> Bool
(ChainDifficulty -> ChainDifficulty -> Bool)
-> (ChainDifficulty -> ChainDifficulty -> Bool)
-> Eq ChainDifficulty
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ChainDifficulty -> ChainDifficulty -> Bool
== :: ChainDifficulty -> ChainDifficulty -> Bool
$c/= :: ChainDifficulty -> ChainDifficulty -> Bool
/= :: ChainDifficulty -> ChainDifficulty -> Bool
Eq, Eq ChainDifficulty
Eq ChainDifficulty =>
(ChainDifficulty -> ChainDifficulty -> Ordering)
-> (ChainDifficulty -> ChainDifficulty -> Bool)
-> (ChainDifficulty -> ChainDifficulty -> Bool)
-> (ChainDifficulty -> ChainDifficulty -> Bool)
-> (ChainDifficulty -> ChainDifficulty -> Bool)
-> (ChainDifficulty -> ChainDifficulty -> ChainDifficulty)
-> (ChainDifficulty -> ChainDifficulty -> ChainDifficulty)
-> Ord ChainDifficulty
ChainDifficulty -> ChainDifficulty -> Bool
ChainDifficulty -> ChainDifficulty -> Ordering
ChainDifficulty -> ChainDifficulty -> ChainDifficulty
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ChainDifficulty -> ChainDifficulty -> Ordering
compare :: ChainDifficulty -> ChainDifficulty -> Ordering
$c< :: ChainDifficulty -> ChainDifficulty -> Bool
< :: ChainDifficulty -> ChainDifficulty -> Bool
$c<= :: ChainDifficulty -> ChainDifficulty -> Bool
<= :: ChainDifficulty -> ChainDifficulty -> Bool
$c> :: ChainDifficulty -> ChainDifficulty -> Bool
> :: ChainDifficulty -> ChainDifficulty -> Bool
$c>= :: ChainDifficulty -> ChainDifficulty -> Bool
>= :: ChainDifficulty -> ChainDifficulty -> Bool
$cmax :: ChainDifficulty -> ChainDifficulty -> ChainDifficulty
max :: ChainDifficulty -> ChainDifficulty -> ChainDifficulty
$cmin :: ChainDifficulty -> ChainDifficulty -> ChainDifficulty
min :: ChainDifficulty -> ChainDifficulty -> ChainDifficulty
Ord, Int -> ChainDifficulty
ChainDifficulty -> Int
ChainDifficulty -> [ChainDifficulty]
ChainDifficulty -> ChainDifficulty
ChainDifficulty -> ChainDifficulty -> [ChainDifficulty]
ChainDifficulty
-> ChainDifficulty -> ChainDifficulty -> [ChainDifficulty]
(ChainDifficulty -> ChainDifficulty)
-> (ChainDifficulty -> ChainDifficulty)
-> (Int -> ChainDifficulty)
-> (ChainDifficulty -> Int)
-> (ChainDifficulty -> [ChainDifficulty])
-> (ChainDifficulty -> ChainDifficulty -> [ChainDifficulty])
-> (ChainDifficulty -> ChainDifficulty -> [ChainDifficulty])
-> (ChainDifficulty
    -> ChainDifficulty -> ChainDifficulty -> [ChainDifficulty])
-> Enum ChainDifficulty
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: ChainDifficulty -> ChainDifficulty
succ :: ChainDifficulty -> ChainDifficulty
$cpred :: ChainDifficulty -> ChainDifficulty
pred :: ChainDifficulty -> ChainDifficulty
$ctoEnum :: Int -> ChainDifficulty
toEnum :: Int -> ChainDifficulty
$cfromEnum :: ChainDifficulty -> Int
fromEnum :: ChainDifficulty -> Int
$cenumFrom :: ChainDifficulty -> [ChainDifficulty]
enumFrom :: ChainDifficulty -> [ChainDifficulty]
$cenumFromThen :: ChainDifficulty -> ChainDifficulty -> [ChainDifficulty]
enumFromThen :: ChainDifficulty -> ChainDifficulty -> [ChainDifficulty]
$cenumFromTo :: ChainDifficulty -> ChainDifficulty -> [ChainDifficulty]
enumFromTo :: ChainDifficulty -> ChainDifficulty -> [ChainDifficulty]
$cenumFromThenTo :: ChainDifficulty
-> ChainDifficulty -> ChainDifficulty -> [ChainDifficulty]
enumFromThenTo :: ChainDifficulty
-> ChainDifficulty -> ChainDifficulty -> [ChainDifficulty]
Enum, (forall x. ChainDifficulty -> Rep ChainDifficulty x)
-> (forall x. Rep ChainDifficulty x -> ChainDifficulty)
-> Generic ChainDifficulty
forall x. Rep ChainDifficulty x -> ChainDifficulty
forall x. ChainDifficulty -> Rep ChainDifficulty x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ChainDifficulty -> Rep ChainDifficulty x
from :: forall x. ChainDifficulty -> Rep ChainDifficulty x
$cto :: forall x. Rep ChainDifficulty x -> ChainDifficulty
to :: forall x. Rep ChainDifficulty x -> ChainDifficulty
Generic, ChainDifficulty -> Builder
(ChainDifficulty -> Builder) -> Buildable ChainDifficulty
forall p. (p -> Builder) -> Buildable p
$cbuild :: ChainDifficulty -> Builder
build :: ChainDifficulty -> Builder
Buildable, ChainDifficulty -> ()
(ChainDifficulty -> ()) -> NFData ChainDifficulty
forall a. (a -> ()) -> NFData a
$crnf :: ChainDifficulty -> ()
rnf :: ChainDifficulty -> ()
NFData, Context -> ChainDifficulty -> IO (Maybe ThunkInfo)
Proxy ChainDifficulty -> String
(Context -> ChainDifficulty -> IO (Maybe ThunkInfo))
-> (Context -> ChainDifficulty -> IO (Maybe ThunkInfo))
-> (Proxy ChainDifficulty -> String)
-> NoThunks ChainDifficulty
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
$cnoThunks :: Context -> ChainDifficulty -> IO (Maybe ThunkInfo)
noThunks :: Context -> ChainDifficulty -> IO (Maybe ThunkInfo)
$cwNoThunks :: Context -> ChainDifficulty -> IO (Maybe ThunkInfo)
wNoThunks :: Context -> ChainDifficulty -> IO (Maybe ThunkInfo)
$cshowTypeOf :: Proxy ChainDifficulty -> String
showTypeOf :: Proxy ChainDifficulty -> String
NoThunks)

-- Used for debugging purposes only
instance ToJSON ChainDifficulty

instance ToCBOR ChainDifficulty where
  toCBOR :: ChainDifficulty -> Encoding
toCBOR = ChainDifficulty -> Encoding
forall a. EncCBOR a => a -> Encoding
toByronCBOR

instance FromCBOR ChainDifficulty where
  fromCBOR :: forall s. Decoder s ChainDifficulty
fromCBOR = Decoder s ChainDifficulty
forall a s. DecCBOR a => Decoder s a
fromByronCBOR

instance EncCBOR ChainDifficulty where
  encCBOR :: ChainDifficulty -> Encoding
encCBOR ChainDifficulty
cd = Word -> Encoding
encodeListLen Word
1 Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word64 -> Encoding
forall a. EncCBOR a => a -> Encoding
encCBOR (ChainDifficulty -> Word64
unChainDifficulty ChainDifficulty
cd)

  encodedSizeExpr :: (forall t. EncCBOR t => Proxy t -> Size)
-> Proxy ChainDifficulty -> Size
encodedSizeExpr forall t. EncCBOR t => Proxy t -> Size
f Proxy ChainDifficulty
cd = Size
1 Size -> Size -> Size
forall a. Num a => a -> a -> a
+ (forall t. EncCBOR t => Proxy t -> Size) -> Proxy Word64 -> Size
forall a.
EncCBOR a =>
(forall t. EncCBOR t => Proxy t -> Size) -> Proxy a -> Size
encodedSizeExpr Proxy t -> Size
forall t. EncCBOR t => Proxy t -> Size
f (ChainDifficulty -> Word64
unChainDifficulty (ChainDifficulty -> Word64)
-> Proxy ChainDifficulty -> Proxy Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Proxy ChainDifficulty
cd)

instance DecCBOR ChainDifficulty where
  decCBOR :: forall s. Decoder s ChainDifficulty
decCBOR = do
    Text -> Int -> Decoder s ()
forall s. Text -> Int -> Decoder s ()
enforceSize Text
"ChainDifficulty" Int
1
    Word64 -> ChainDifficulty
ChainDifficulty (Word64 -> ChainDifficulty)
-> Decoder s Word64 -> Decoder s ChainDifficulty
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s Word64
forall s. Decoder s Word64
forall a s. DecCBOR a => Decoder s a
decCBOR

dropChainDifficulty :: Dropper s
dropChainDifficulty :: forall s. Dropper s
dropChainDifficulty = do
  Text -> Int -> Dropper s
forall s. Text -> Int -> Decoder s ()
enforceSize Text
"ChainDifficulty" Int
1
  Dropper s
forall s. Dropper s
dropWord64