{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}

module Cardano.CLI.EraBased.Run.Genesis.Byron where

import           Cardano.Api.Byron (rationalToLovelacePortion)
import qualified Cardano.Api.Byron as Byron hiding (GenesisParameters)
import qualified Cardano.Api.Ledger as L
import qualified Cardano.Api.Shelley as Shelley

import qualified Cardano.CLI.Byron.Genesis as Byron
import qualified Cardano.Crypto.ProtocolMagic as Crypto

import           Data.Aeson (toJSON, (.=))
import qualified Data.Aeson as Aeson
import           Data.Maybe (fromJust)
import           Data.Ratio ((%))
import           GHC.Word (Word32)

-- | We need to pass these values to create the Byron genesis file.
-- The values here don't matter as the testnet conditions are ultimately determined
-- by the Shelley genesis.
defaultProtocolParamsJsonValue :: Aeson.Value
defaultProtocolParamsJsonValue :: Value
defaultProtocolParamsJsonValue =
  [Pair] -> Value
Aeson.object
    [ Key
"heavyDelThd" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"300000000000"
    , Key
"maxBlockSize" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"2000000"
    , Key
"maxTxSize" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"4096"
    , Key
"maxHeaderSize" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"2000000"
    , Key
"maxProposalSize" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"700"
    , Key
"mpcThd" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"20000000000000"
    , Key
"scriptVersion" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @Int Int
0
    , Key
"slotDuration" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"1000"
    , Key
"softforkRule"
        Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [Pair] -> Value
Aeson.object
          [ Key
"initThd" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"900000000000000"
          , Key
"minThd" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"600000000000000"
          , Key
"thdDecrement" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"50000000000000"
          ]
    , Key
"txFeePolicy"
        Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [Pair] -> Value
Aeson.object
          [ Key
"multiplier" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"43946000000"
          , Key
"summand" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"155381000000000"
          ]
    , Key
"unlockStakeEpoch" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"18446744073709551615"
    , Key
"updateImplicit" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"10000"
    , Key
"updateProposalThd" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"100000000000000"
    , Key
"updateVoteThd" Key -> Value -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON @String String
"1000000000000"
    ]

mkGenesisParameters
  :: Word -> Word32 -> FilePath -> Shelley.ShelleyGenesis c -> Byron.GenesisParameters
mkGenesisParameters :: forall c.
Word -> Word32 -> String -> ShelleyGenesis c -> GenesisParameters
mkGenesisParameters Word
numPools Word32
actualNetworkWord32 String
byronGenesisFp ShelleyGenesis c
shelleyGenesis =
  Byron.GenesisParameters{String
Maybe Integer
UTCTime
BlockCount
LovelacePortion
FakeAvvmOptions
TestnetBalanceOptions
ProtocolMagic
forall {a}. Maybe a
gpStartTime :: UTCTime
gpProtocolParamsFile :: String
gpK :: BlockCount
gpProtocolMagic :: ProtocolMagic
gpTestnetBalance :: TestnetBalanceOptions
gpFakeAvvmOptions :: FakeAvvmOptions
gpAvvmBalanceFactor :: LovelacePortion
gpSeed :: forall {a}. Maybe a
gpSeed :: Maybe Integer
gpAvvmBalanceFactor :: LovelacePortion
gpFakeAvvmOptions :: FakeAvvmOptions
gpTestnetBalance :: TestnetBalanceOptions
gpProtocolMagic :: ProtocolMagic
gpK :: BlockCount
gpProtocolParamsFile :: String
gpStartTime :: UTCTime
..}
 where
  -- All arbitrary values come from cardano-testnet
  byronPoolNumber :: Word
byronPoolNumber = Word -> Word -> Word
forall a. Ord a => a -> a -> a
max Word
1 Word
numPools -- byron genesis creation needs a >= 1 number of pools
  gpStartTime :: UTCTime
gpStartTime = ShelleyGenesis c -> UTCTime
forall c. ShelleyGenesis c -> UTCTime
Shelley.sgSystemStart ShelleyGenesis c
shelleyGenesis
  gpProtocolParamsFile :: String
gpProtocolParamsFile = String
byronGenesisFp
  gpK :: BlockCount
gpK = Word64 -> BlockCount
Byron.BlockCount Word64
10
  protocolMagicId :: ProtocolMagicId
protocolMagicId = Word32 -> ProtocolMagicId
Crypto.ProtocolMagicId Word32
actualNetworkWord32
  gpProtocolMagic :: ProtocolMagic
gpProtocolMagic = Annotated ProtocolMagicId ()
-> RequiresNetworkMagic -> ProtocolMagic
forall a.
Annotated ProtocolMagicId a
-> RequiresNetworkMagic -> AProtocolMagic a
Crypto.AProtocolMagic (ProtocolMagicId -> () -> Annotated ProtocolMagicId ()
forall b a. b -> a -> Annotated b a
L.Annotated ProtocolMagicId
protocolMagicId ()) RequiresNetworkMagic
Crypto.RequiresMagic
  gpTestnetBalance :: TestnetBalanceOptions
gpTestnetBalance =
    Word -> Word -> Lovelace -> Rational -> TestnetBalanceOptions
Byron.TestnetBalanceOptions
      Word
0 -- poor adresses
      Word
byronPoolNumber -- delegate addresses (BFT nodes)
      (Maybe Lovelace -> Lovelace
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Lovelace -> Lovelace) -> Maybe Lovelace -> Lovelace
forall a b. (a -> b) -> a -> b
$ Lovelace -> Maybe Lovelace
Byron.toByronLovelace (Lovelace -> Maybe Lovelace) -> Lovelace -> Maybe Lovelace
forall a b. (a -> b) -> a -> b
$ Integer -> Lovelace
L.Coin (Integer -> Lovelace) -> Integer -> Lovelace
forall a b. (a -> b) -> a -> b
$ Integer
3_000_000_000 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Word -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
byronPoolNumber)
      Rational
1
  gpFakeAvvmOptions :: FakeAvvmOptions
gpFakeAvvmOptions =
    Word -> Lovelace -> FakeAvvmOptions
Byron.FakeAvvmOptions
      Word
0 -- avvm entry count
      (Maybe Lovelace -> Lovelace
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Lovelace -> Lovelace) -> Maybe Lovelace -> Lovelace
forall a b. (a -> b) -> a -> b
$ Lovelace -> Maybe Lovelace
Byron.toByronLovelace (Lovelace -> Maybe Lovelace) -> Lovelace -> Maybe Lovelace
forall a b. (a -> b) -> a -> b
$ Integer -> Lovelace
L.Coin Integer
0) -- avvm entry balance
  gpAvvmBalanceFactor :: LovelacePortion
gpAvvmBalanceFactor = Rational -> LovelacePortion
rationalToLovelacePortion (Rational -> LovelacePortion) -> Rational -> LovelacePortion
forall a b. (a -> b) -> a -> b
$ Integer
1 Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer
1
  gpSeed :: Maybe a
gpSeed = Maybe a
forall {a}. Maybe a
Nothing