{-# LANGUAGE CPP #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}

#if !defined(mingw32_HOST_OS)
#define UNIX
#endif

module Cardano.CLI.Byron.Genesis
  ( ByronGenesisError(..)
  , GenesisParameters(..)
  , NewDirectory(..)
  , dumpGenesis
  , mkGenesis
  , readGenesis
  , renderByronGenesisError
  )
where

import           Cardano.Prelude hiding (option, show, trace)
import           Prelude (String, show)

import           Control.Monad.Trans.Except.Extra (firstExceptT, left, right)
import qualified Data.ByteString.Lazy as LB
import qualified Data.Map.Strict as Map
import           Data.Text.Lazy.Builder (toLazyText)
import           Data.Time (UTCTime)
import           Formatting.Buildable
import           Text.Printf (printf)

import           System.Directory (createDirectory, doesPathExist)
import           System.FilePath ((</>))
#ifdef UNIX
import           System.Posix.Files (ownerReadMode, setFileMode)
#else
import           System.Directory (emptyPermissions, readable, setPermissions)
#endif
import           Cardano.Api.Typed (NetworkId, toByronRequiresNetworkMagic)

import qualified Cardano.Chain.Common as Common
import           Cardano.Chain.Delegation hiding (Map, epoch)
import           Cardano.Chain.Genesis (GeneratedSecrets (..))
import qualified Cardano.Chain.Genesis as Genesis
import qualified Cardano.Chain.UTxO as UTxO

import           Cardano.Crypto (SigningKey (..))
import qualified Cardano.Crypto as Crypto

import           Cardano.CLI.Byron.Delegation
import           Cardano.CLI.Byron.Key
import           Cardano.CLI.Helpers (textShow)
import           Cardano.CLI.Types (GenesisFile (..))

data ByronGenesisError
  = ByronDelegationCertSerializationError !ByronDelegationError
  | ByronDelegationKeySerializationError ByronDelegationError
  | ByronGenesisCardanoEraNotSupported !CardanoEra
  | GenesisGenerationError !Genesis.GenesisDataGenerationError
  | GenesisOutputDirAlreadyExists FilePath
  | GenesisReadError !FilePath !Genesis.GenesisDataError
  | GenesisSpecError !Text
  | MakeGenesisDelegationError !Genesis.GenesisDelegationError
  | NoGenesisDelegationForKey !Text
  | ProtocolParametersParseFailed !FilePath !Text
  | PoorKeyFailure !ByronKeyFailure

  deriving Int -> ByronGenesisError -> ShowS
[ByronGenesisError] -> ShowS
ByronGenesisError -> String
(Int -> ByronGenesisError -> ShowS)
-> (ByronGenesisError -> String)
-> ([ByronGenesisError] -> ShowS)
-> Show ByronGenesisError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ByronGenesisError] -> ShowS
$cshowList :: [ByronGenesisError] -> ShowS
show :: ByronGenesisError -> String
$cshow :: ByronGenesisError -> String
showsPrec :: Int -> ByronGenesisError -> ShowS
$cshowsPrec :: Int -> ByronGenesisError -> ShowS
Show

renderByronGenesisError :: ByronGenesisError -> Text
renderByronGenesisError :: ByronGenesisError -> Text
renderByronGenesisError ByronGenesisError
err =
  case ByronGenesisError
err of
    ProtocolParametersParseFailed String
pParamFp Text
parseError ->
      Text
"Protocol parameters parse failed at: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
pParamFp Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" Error: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
parseError
    ByronDelegationCertSerializationError ByronDelegationError
bDelegSerErr ->
      Text
"Error while serializing the delegation certificate: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ByronDelegationError -> Text
forall a. Show a => a -> Text
textShow ByronDelegationError
bDelegSerErr
    ByronDelegationKeySerializationError ByronDelegationError
bKeySerErr ->
      Text
"Error while serializing the delegation key: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ByronDelegationError -> Text
forall a. Show a => a -> Text
textShow ByronDelegationError
bKeySerErr
    PoorKeyFailure ByronKeyFailure
bKeyFailure ->
      Text
"Error creating poor keys: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ByronKeyFailure -> Text
forall a. Show a => a -> Text
textShow ByronKeyFailure
bKeyFailure
    MakeGenesisDelegationError GenesisDelegationError
genDelegError ->
      Text
"Error creating genesis delegation: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> GenesisDelegationError -> Text
forall a. Show a => a -> Text
textShow GenesisDelegationError
genDelegError
    GenesisGenerationError GenesisDataGenerationError
genDataGenError ->
      Text
"Error generating genesis: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> GenesisDataGenerationError -> Text
forall a. Show a => a -> Text
textShow GenesisDataGenerationError
genDataGenError
    ByronGenesisCardanoEraNotSupported CardanoEra
era ->
      Text
"Error while serialising genesis, " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> CardanoEra -> Text
forall a. Show a => a -> Text
textShow CardanoEra
era Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" is not supported."
    GenesisOutputDirAlreadyExists String
genOutDir ->
      Text
"Genesis output directory already exists: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
genOutDir
    GenesisReadError String
genFp GenesisDataError
genDataError ->
      Text
"Error while reading genesis file at: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
genFp Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" Error: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> GenesisDataError -> Text
forall a. Show a => a -> Text
textShow GenesisDataError
genDataError
    GenesisSpecError Text
genSpecError ->
      Text
"Error while creating genesis spec" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
forall a. Show a => a -> Text
textShow Text
genSpecError
    NoGenesisDelegationForKey Text
verKey ->
      Text
"Error while creating genesis, no delegation certificate for this verification key:" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
forall a. Show a => a -> Text
textShow Text
verKey

newtype NewDirectory =
  NewDirectory FilePath
  deriving (NewDirectory -> NewDirectory -> Bool
(NewDirectory -> NewDirectory -> Bool)
-> (NewDirectory -> NewDirectory -> Bool) -> Eq NewDirectory
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NewDirectory -> NewDirectory -> Bool
$c/= :: NewDirectory -> NewDirectory -> Bool
== :: NewDirectory -> NewDirectory -> Bool
$c== :: NewDirectory -> NewDirectory -> Bool
Eq, Eq NewDirectory
Eq NewDirectory
-> (NewDirectory -> NewDirectory -> Ordering)
-> (NewDirectory -> NewDirectory -> Bool)
-> (NewDirectory -> NewDirectory -> Bool)
-> (NewDirectory -> NewDirectory -> Bool)
-> (NewDirectory -> NewDirectory -> Bool)
-> (NewDirectory -> NewDirectory -> NewDirectory)
-> (NewDirectory -> NewDirectory -> NewDirectory)
-> Ord NewDirectory
NewDirectory -> NewDirectory -> Bool
NewDirectory -> NewDirectory -> Ordering
NewDirectory -> NewDirectory -> NewDirectory
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
min :: NewDirectory -> NewDirectory -> NewDirectory
$cmin :: NewDirectory -> NewDirectory -> NewDirectory
max :: NewDirectory -> NewDirectory -> NewDirectory
$cmax :: NewDirectory -> NewDirectory -> NewDirectory
>= :: NewDirectory -> NewDirectory -> Bool
$c>= :: NewDirectory -> NewDirectory -> Bool
> :: NewDirectory -> NewDirectory -> Bool
$c> :: NewDirectory -> NewDirectory -> Bool
<= :: NewDirectory -> NewDirectory -> Bool
$c<= :: NewDirectory -> NewDirectory -> Bool
< :: NewDirectory -> NewDirectory -> Bool
$c< :: NewDirectory -> NewDirectory -> Bool
compare :: NewDirectory -> NewDirectory -> Ordering
$ccompare :: NewDirectory -> NewDirectory -> Ordering
$cp1Ord :: Eq NewDirectory
Ord, Int -> NewDirectory -> ShowS
[NewDirectory] -> ShowS
NewDirectory -> String
(Int -> NewDirectory -> ShowS)
-> (NewDirectory -> String)
-> ([NewDirectory] -> ShowS)
-> Show NewDirectory
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NewDirectory] -> ShowS
$cshowList :: [NewDirectory] -> ShowS
show :: NewDirectory -> String
$cshow :: NewDirectory -> String
showsPrec :: Int -> NewDirectory -> ShowS
$cshowsPrec :: Int -> NewDirectory -> ShowS
Show, String -> NewDirectory
(String -> NewDirectory) -> IsString NewDirectory
forall a. (String -> a) -> IsString a
fromString :: String -> NewDirectory
$cfromString :: String -> NewDirectory
IsString)

-- | Parameters required for generation of new genesis.
data GenesisParameters = GenesisParameters
  { GenesisParameters -> UTCTime
gpStartTime :: !UTCTime
  , GenesisParameters -> String
gpProtocolParamsFile :: !FilePath
  , GenesisParameters -> BlockCount
gpK :: !Common.BlockCount
  , GenesisParameters -> ProtocolMagic
gpProtocolMagic :: !Crypto.ProtocolMagic
  , GenesisParameters -> TestnetBalanceOptions
gpTestnetBalance :: !Genesis.TestnetBalanceOptions
  , GenesisParameters -> FakeAvvmOptions
gpFakeAvvmOptions :: !Genesis.FakeAvvmOptions
  , GenesisParameters -> LovelacePortion
gpAvvmBalanceFactor :: !Common.LovelacePortion
  , GenesisParameters -> Maybe Integer
gpSeed :: !(Maybe Integer)
  } deriving Int -> GenesisParameters -> ShowS
[GenesisParameters] -> ShowS
GenesisParameters -> String
(Int -> GenesisParameters -> ShowS)
-> (GenesisParameters -> String)
-> ([GenesisParameters] -> ShowS)
-> Show GenesisParameters
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [GenesisParameters] -> ShowS
$cshowList :: [GenesisParameters] -> ShowS
show :: GenesisParameters -> String
$cshow :: GenesisParameters -> String
showsPrec :: Int -> GenesisParameters -> ShowS
$cshowsPrec :: Int -> GenesisParameters -> ShowS
Show


mkGenesisSpec :: GenesisParameters -> ExceptT ByronGenesisError IO Genesis.GenesisSpec
mkGenesisSpec :: GenesisParameters -> ExceptT ByronGenesisError IO GenesisSpec
mkGenesisSpec GenesisParameters
gp = do
  ByteString
protoParamsRaw <- IO ByteString -> ExceptT ByronGenesisError IO ByteString
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (IO ByteString -> ExceptT ByronGenesisError IO ByteString)
-> (String -> IO ByteString)
-> String
-> ExceptT ByronGenesisError IO ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> IO ByteString
LB.readFile (String -> ExceptT ByronGenesisError IO ByteString)
-> String -> ExceptT ByronGenesisError IO ByteString
forall a b. (a -> b) -> a -> b
$ GenesisParameters -> String
gpProtocolParamsFile GenesisParameters
gp

  ProtocolParameters
protocolParameters <- (Text -> ByronGenesisError)
-> ExceptT Text IO ProtocolParameters
-> ExceptT ByronGenesisError IO ProtocolParameters
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT
    (String -> Text -> ByronGenesisError
ProtocolParametersParseFailed (GenesisParameters -> String
gpProtocolParamsFile GenesisParameters
gp)) (ExceptT Text IO ProtocolParameters
 -> ExceptT ByronGenesisError IO ProtocolParameters)
-> ExceptT Text IO ProtocolParameters
-> ExceptT ByronGenesisError IO ProtocolParameters
forall a b. (a -> b) -> a -> b
$
    IO (Either Text ProtocolParameters)
-> ExceptT Text IO ProtocolParameters
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (IO (Either Text ProtocolParameters)
 -> ExceptT Text IO ProtocolParameters)
-> (Either Text ProtocolParameters
    -> IO (Either Text ProtocolParameters))
-> Either Text ProtocolParameters
-> ExceptT Text IO ProtocolParameters
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Either Text ProtocolParameters
-> IO (Either Text ProtocolParameters)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either Text ProtocolParameters
 -> ExceptT Text IO ProtocolParameters)
-> Either Text ProtocolParameters
-> ExceptT Text IO ProtocolParameters
forall a b. (a -> b) -> a -> b
$ ByteString -> Either Text ProtocolParameters
forall a.
FromJSON (Either SchemaError) a =>
ByteString -> Either Text a
canonicalDecodePretty ByteString
protoParamsRaw

  -- We're relying on the generator to fake AVVM and delegation.
  GenesisDelegation
genesisDelegation <- (GenesisDelegationError -> ByronGenesisError)
-> ExceptT GenesisDelegationError IO GenesisDelegation
-> ExceptT ByronGenesisError IO GenesisDelegation
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT GenesisDelegationError -> ByronGenesisError
MakeGenesisDelegationError (ExceptT GenesisDelegationError IO GenesisDelegation
 -> ExceptT ByronGenesisError IO GenesisDelegation)
-> ExceptT GenesisDelegationError IO GenesisDelegation
-> ExceptT ByronGenesisError IO GenesisDelegation
forall a b. (a -> b) -> a -> b
$
    [Certificate]
-> ExceptT GenesisDelegationError IO GenesisDelegation
forall (m :: * -> *).
MonadError GenesisDelegationError m =>
[Certificate] -> m GenesisDelegation
Genesis.mkGenesisDelegation []

  (Text -> ByronGenesisError)
-> ExceptT Text IO GenesisSpec
-> ExceptT ByronGenesisError IO GenesisSpec
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT Text -> ByronGenesisError
GenesisSpecError (ExceptT Text IO GenesisSpec
 -> ExceptT ByronGenesisError IO GenesisSpec)
-> ExceptT Text IO GenesisSpec
-> ExceptT ByronGenesisError IO GenesisSpec
forall a b. (a -> b) -> a -> b
$
    IO (Either Text GenesisSpec) -> ExceptT Text IO GenesisSpec
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (IO (Either Text GenesisSpec) -> ExceptT Text IO GenesisSpec)
-> (Either Text GenesisSpec -> IO (Either Text GenesisSpec))
-> Either Text GenesisSpec
-> ExceptT Text IO GenesisSpec
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Either Text GenesisSpec -> IO (Either Text GenesisSpec)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either Text GenesisSpec -> ExceptT Text IO GenesisSpec)
-> Either Text GenesisSpec -> ExceptT Text IO GenesisSpec
forall a b. (a -> b) -> a -> b
$ GenesisAvvmBalances
-> GenesisDelegation
-> ProtocolParameters
-> BlockCount
-> ProtocolMagic
-> GenesisInitializer
-> Either Text GenesisSpec
Genesis.mkGenesisSpec
      (Map CompactRedeemVerificationKey Lovelace -> GenesisAvvmBalances
Genesis.GenesisAvvmBalances Map CompactRedeemVerificationKey Lovelace
forall a. Monoid a => a
mempty)
      GenesisDelegation
genesisDelegation
      ProtocolParameters
protocolParameters
      (GenesisParameters -> BlockCount
gpK GenesisParameters
gp)
      (GenesisParameters -> ProtocolMagic
gpProtocolMagic GenesisParameters
gp)
      (Bool -> GenesisInitializer
mkGenesisInitialiser Bool
True)

  where
    mkGenesisInitialiser :: Bool -> Genesis.GenesisInitializer
    mkGenesisInitialiser :: Bool -> GenesisInitializer
mkGenesisInitialiser Bool
useHeavyDlg =
      TestnetBalanceOptions
-> FakeAvvmOptions -> Rational -> Bool -> GenesisInitializer
Genesis.GenesisInitializer
      (GenesisParameters -> TestnetBalanceOptions
gpTestnetBalance GenesisParameters
gp)
      (GenesisParameters -> FakeAvvmOptions
gpFakeAvvmOptions GenesisParameters
gp)
      (LovelacePortion -> Rational
Common.lovelacePortionToRational (GenesisParameters -> LovelacePortion
gpAvvmBalanceFactor GenesisParameters
gp))
      Bool
useHeavyDlg

-- | Generate a genesis, for given blockchain start time, protocol parameters,
-- security parameter, protocol magic, testnet balance options, fake AVVM options,
-- AVVM balance factor and seed.  Throw an error in the following cases: if the
-- protocol parameters file can't be read or fails parse, if genesis delegation
-- couldn't be generated, if the parameter-derived genesis specification is wrong,
-- or if the genesis fails generation.
mkGenesis
  :: GenesisParameters
  -> ExceptT ByronGenesisError IO (Genesis.GenesisData, Genesis.GeneratedSecrets)
mkGenesis :: GenesisParameters
-> ExceptT ByronGenesisError IO (GenesisData, GeneratedSecrets)
mkGenesis GenesisParameters
gp = do
  GenesisSpec
genesisSpec <- GenesisParameters -> ExceptT ByronGenesisError IO GenesisSpec
mkGenesisSpec GenesisParameters
gp

  (GenesisDataGenerationError -> ByronGenesisError)
-> ExceptT
     GenesisDataGenerationError IO (GenesisData, GeneratedSecrets)
-> ExceptT ByronGenesisError IO (GenesisData, GeneratedSecrets)
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT GenesisDataGenerationError -> ByronGenesisError
GenesisGenerationError (ExceptT
   GenesisDataGenerationError IO (GenesisData, GeneratedSecrets)
 -> ExceptT ByronGenesisError IO (GenesisData, GeneratedSecrets))
-> ExceptT
     GenesisDataGenerationError IO (GenesisData, GeneratedSecrets)
-> ExceptT ByronGenesisError IO (GenesisData, GeneratedSecrets)
forall a b. (a -> b) -> a -> b
$
    UTCTime
-> GenesisSpec
-> ExceptT
     GenesisDataGenerationError IO (GenesisData, GeneratedSecrets)
Genesis.generateGenesisData (GenesisParameters -> UTCTime
gpStartTime GenesisParameters
gp) GenesisSpec
genesisSpec

-- | Read genesis from a file.
readGenesis :: GenesisFile
            -> NetworkId
            -> ExceptT ByronGenesisError IO Genesis.Config
readGenesis :: GenesisFile -> NetworkId -> ExceptT ByronGenesisError IO Config
readGenesis (GenesisFile String
file) NetworkId
nw =
  (GenesisDataError -> ByronGenesisError)
-> ExceptT GenesisDataError IO Config
-> ExceptT ByronGenesisError IO Config
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
firstExceptT (String -> GenesisDataError -> ByronGenesisError
GenesisReadError String
file) (ExceptT GenesisDataError IO Config
 -> ExceptT ByronGenesisError IO Config)
-> ExceptT GenesisDataError IO Config
-> ExceptT ByronGenesisError IO Config
forall a b. (a -> b) -> a -> b
$ do
    (GenesisData
genesisData, GenesisHash
genesisHash) <- String -> ExceptT GenesisDataError IO (GenesisData, GenesisHash)
forall (m :: * -> *).
(MonadError GenesisDataError m, MonadIO m) =>
String -> m (GenesisData, GenesisHash)
Genesis.readGenesisData String
file
    Config -> ExceptT GenesisDataError IO Config
forall (m :: * -> *) a. Monad m => a -> m a
return Config :: GenesisData
-> GenesisHash
-> RequiresNetworkMagic
-> UTxOConfiguration
-> Config
Genesis.Config {
      configGenesisData :: GenesisData
Genesis.configGenesisData       = GenesisData
genesisData,
      configGenesisHash :: GenesisHash
Genesis.configGenesisHash       = GenesisHash
genesisHash,
      configReqNetMagic :: RequiresNetworkMagic
Genesis.configReqNetMagic       = NetworkId -> RequiresNetworkMagic
toByronRequiresNetworkMagic NetworkId
nw,
      configUTxOConfiguration :: UTxOConfiguration
Genesis.configUTxOConfiguration = UTxOConfiguration
UTxO.defaultUTxOConfiguration
    }

--TODO: dumpGenesis needs refactoring.
-- | Write out genesis into a directory that must not yet exist.  An error is
-- thrown if the directory already exists, or the genesis has delegate keys that
-- are not delegated to.
dumpGenesis
  :: CardanoEra
  -> NewDirectory
  -> Genesis.GenesisData
  -> Genesis.GeneratedSecrets
  -> ExceptT ByronGenesisError IO ()
dumpGenesis :: CardanoEra
-> NewDirectory
-> GenesisData
-> GeneratedSecrets
-> ExceptT ByronGenesisError IO ()
dumpGenesis CardanoEra
era (NewDirectory String
outDir) GenesisData
genesisData GeneratedSecrets
gs = do
  Bool
exists <- IO Bool -> ExceptT ByronGenesisError IO Bool
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Bool -> ExceptT ByronGenesisError IO Bool)
-> IO Bool -> ExceptT ByronGenesisError IO Bool
forall a b. (a -> b) -> a -> b
$ String -> IO Bool
doesPathExist String
outDir
  if Bool
exists
  then ByronGenesisError -> ExceptT ByronGenesisError IO ()
forall (m :: * -> *) x a. Monad m => x -> ExceptT x m a
left (ByronGenesisError -> ExceptT ByronGenesisError IO ())
-> ByronGenesisError -> ExceptT ByronGenesisError IO ()
forall a b. (a -> b) -> a -> b
$ String -> ByronGenesisError
GenesisOutputDirAlreadyExists String
outDir
  else IO () -> ExceptT ByronGenesisError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT ByronGenesisError IO ())
-> IO () -> ExceptT ByronGenesisError IO ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
createDirectory String
outDir
  IO () -> ExceptT ByronGenesisError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT ByronGenesisError IO ())
-> IO () -> ExceptT ByronGenesisError IO ()
forall a b. (a -> b) -> a -> b
$ String -> ByteString -> IO ()
LB.writeFile String
genesisJSONFile (GenesisData -> ByteString
serialiseGenesis GenesisData
genesisData)

  [Certificate]
dlgCerts <- (SigningKey -> ExceptT ByronGenesisError IO Certificate)
-> [SigningKey] -> ExceptT ByronGenesisError IO [Certificate]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM SigningKey -> ExceptT ByronGenesisError IO Certificate
findDelegateCert ([SigningKey] -> ExceptT ByronGenesisError IO [Certificate])
-> [SigningKey] -> ExceptT ByronGenesisError IO [Certificate]
forall a b. (a -> b) -> a -> b
$ GeneratedSecrets -> [SigningKey]
gsRichSecrets GeneratedSecrets
gs

  IO () -> ExceptT ByronGenesisError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT ByronGenesisError IO ())
-> IO () -> ExceptT ByronGenesisError IO ()
forall a b. (a -> b) -> a -> b
$ String
-> String
-> (SigningKey -> IO (Either ByronGenesisError ByteString))
-> [SigningKey]
-> IO ()
forall a.
String
-> String
-> (a -> IO (Either ByronGenesisError ByteString))
-> [a]
-> IO ()
wOut String
"genesis-keys" String
"key"
                (Either ByronGenesisError ByteString
-> IO (Either ByronGenesisError ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either ByronGenesisError ByteString
 -> IO (Either ByronGenesisError ByteString))
-> (SigningKey -> Either ByronGenesisError ByteString)
-> SigningKey
-> IO (Either ByronGenesisError ByteString)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (ByronKeyFailure -> ByronGenesisError)
-> Either ByronKeyFailure ByteString
-> Either ByronGenesisError ByteString
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (ByronDelegationError -> ByronGenesisError
ByronDelegationKeySerializationError
                             (ByronDelegationError -> ByronGenesisError)
-> (ByronKeyFailure -> ByronDelegationError)
-> ByronKeyFailure
-> ByronGenesisError
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByronKeyFailure -> ByronDelegationError
ByronDelegationKeyError)
                      (Either ByronKeyFailure ByteString
 -> Either ByronGenesisError ByteString)
-> (SigningKey -> Either ByronKeyFailure ByteString)
-> SigningKey
-> Either ByronGenesisError ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. CardanoEra -> SigningKey -> Either ByronKeyFailure ByteString
serialiseSigningKey CardanoEra
era)
                (GeneratedSecrets -> [SigningKey]
gsDlgIssuersSecrets GeneratedSecrets
gs)
  IO () -> ExceptT ByronGenesisError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT ByronGenesisError IO ())
-> IO () -> ExceptT ByronGenesisError IO ()
forall a b. (a -> b) -> a -> b
$ String
-> String
-> (SigningKey -> IO (Either ByronGenesisError ByteString))
-> [SigningKey]
-> IO ()
forall a.
String
-> String
-> (a -> IO (Either ByronGenesisError ByteString))
-> [a]
-> IO ()
wOut String
"delegate-keys" String
"key"
                (Either ByronGenesisError ByteString
-> IO (Either ByronGenesisError ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either ByronGenesisError ByteString
 -> IO (Either ByronGenesisError ByteString))
-> (SigningKey -> Either ByronGenesisError ByteString)
-> SigningKey
-> IO (Either ByronGenesisError ByteString)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (ByronDelegationError -> ByronGenesisError)
-> Either ByronDelegationError ByteString
-> Either ByronGenesisError ByteString
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first ByronDelegationError -> ByronGenesisError
ByronDelegationKeySerializationError
                      (Either ByronDelegationError ByteString
 -> Either ByronGenesisError ByteString)
-> (SigningKey -> Either ByronDelegationError ByteString)
-> SigningKey
-> Either ByronGenesisError ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. CardanoEra -> SigningKey -> Either ByronDelegationError ByteString
serialiseDelegateKey CardanoEra
era)
                (GeneratedSecrets -> [SigningKey]
gsRichSecrets GeneratedSecrets
gs)
  IO () -> ExceptT ByronGenesisError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT ByronGenesisError IO ())
-> IO () -> ExceptT ByronGenesisError IO ()
forall a b. (a -> b) -> a -> b
$ String
-> String
-> (PoorSecret -> IO (Either ByronGenesisError ByteString))
-> [PoorSecret]
-> IO ()
forall a.
String
-> String
-> (a -> IO (Either ByronGenesisError ByteString))
-> [a]
-> IO ()
wOut String
"poor-keys" String
"key"
                (Either ByronGenesisError ByteString
-> IO (Either ByronGenesisError ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either ByronGenesisError ByteString
 -> IO (Either ByronGenesisError ByteString))
-> (PoorSecret -> Either ByronGenesisError ByteString)
-> PoorSecret
-> IO (Either ByronGenesisError ByteString)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (ByronKeyFailure -> ByronGenesisError)
-> Either ByronKeyFailure ByteString
-> Either ByronGenesisError ByteString
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first ByronKeyFailure -> ByronGenesisError
PoorKeyFailure
                      (Either ByronKeyFailure ByteString
 -> Either ByronGenesisError ByteString)
-> (PoorSecret -> Either ByronKeyFailure ByteString)
-> PoorSecret
-> Either ByronGenesisError ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. CardanoEra -> PoorSecret -> Either ByronKeyFailure ByteString
serialisePoorKey CardanoEra
era)
                (GeneratedSecrets -> [PoorSecret]
gsPoorSecrets GeneratedSecrets
gs)
  IO () -> ExceptT ByronGenesisError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT ByronGenesisError IO ())
-> IO () -> ExceptT ByronGenesisError IO ()
forall a b. (a -> b) -> a -> b
$ String
-> String
-> (Certificate -> IO (Either ByronGenesisError ByteString))
-> [Certificate]
-> IO ()
forall a.
String
-> String
-> (a -> IO (Either ByronGenesisError ByteString))
-> [a]
-> IO ()
wOut String
"delegation-cert" String
"json"
                (Either ByronGenesisError ByteString
-> IO (Either ByronGenesisError ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either ByronGenesisError ByteString
 -> IO (Either ByronGenesisError ByteString))
-> (Certificate -> Either ByronGenesisError ByteString)
-> Certificate
-> IO (Either ByronGenesisError ByteString)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByteString -> Either ByronGenesisError ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Either ByronGenesisError ByteString)
-> (Certificate -> ByteString)
-> Certificate
-> Either ByronGenesisError ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Certificate -> ByteString
serialiseDelegationCert)
                [Certificate]
dlgCerts
  IO () -> ExceptT ByronGenesisError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT ByronGenesisError IO ())
-> IO () -> ExceptT ByronGenesisError IO ()
forall a b. (a -> b) -> a -> b
$ String
-> String
-> (RedeemSigningKey -> IO (Either ByronGenesisError ByteString))
-> [RedeemSigningKey]
-> IO ()
forall a.
String
-> String
-> (a -> IO (Either ByronGenesisError ByteString))
-> [a]
-> IO ()
wOut String
"avvm-secrets" String
"secret"
                (Either ByronGenesisError ByteString
-> IO (Either ByronGenesisError ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either ByronGenesisError ByteString
 -> IO (Either ByronGenesisError ByteString))
-> (RedeemSigningKey -> Either ByronGenesisError ByteString)
-> RedeemSigningKey
-> IO (Either ByronGenesisError ByteString)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. RedeemSigningKey -> Either ByronGenesisError ByteString
printFakeAvvmSecrets)
                (GeneratedSecrets -> [RedeemSigningKey]
gsFakeAvvmSecrets GeneratedSecrets
gs)
 where
  dlgCertMap :: Map Common.KeyHash Certificate
  dlgCertMap :: Map KeyHash Certificate
dlgCertMap = GenesisDelegation -> Map KeyHash Certificate
Genesis.unGenesisDelegation (GenesisDelegation -> Map KeyHash Certificate)
-> GenesisDelegation -> Map KeyHash Certificate
forall a b. (a -> b) -> a -> b
$ GenesisData -> GenesisDelegation
Genesis.gdHeavyDelegation GenesisData
genesisData
  findDelegateCert :: SigningKey -> ExceptT ByronGenesisError IO Certificate
  findDelegateCert :: SigningKey -> ExceptT ByronGenesisError IO Certificate
findDelegateCert SigningKey
sk =
    case ((Certificate -> Bool) -> [Certificate] -> Maybe Certificate)
-> [Certificate] -> (Certificate -> Bool) -> Maybe Certificate
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Certificate -> Bool) -> [Certificate] -> Maybe Certificate
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (Map KeyHash Certificate -> [Certificate]
forall k a. Map k a -> [a]
Map.elems Map KeyHash Certificate
dlgCertMap) ((Certificate -> Bool) -> Maybe Certificate)
-> (SigningKey -> Certificate -> Bool)
-> SigningKey
-> Maybe Certificate
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. SigningKey -> Certificate -> Bool
isCertForSK (SigningKey -> Maybe Certificate)
-> SigningKey -> Maybe Certificate
forall a b. (a -> b) -> a -> b
$ SigningKey
sk of
      Maybe Certificate
Nothing -> ByronGenesisError -> ExceptT ByronGenesisError IO Certificate
forall (m :: * -> *) x a. Monad m => x -> ExceptT x m a
left (ByronGenesisError -> ExceptT ByronGenesisError IO Certificate)
-> (SigningKey -> ByronGenesisError)
-> SigningKey
-> ExceptT ByronGenesisError IO Certificate
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> ByronGenesisError
NoGenesisDelegationForKey
                 (Text -> ByronGenesisError)
-> (SigningKey -> Text) -> SigningKey -> ByronGenesisError
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. VerificationKey -> Text
prettyPublicKey (VerificationKey -> Text)
-> (SigningKey -> VerificationKey) -> SigningKey -> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. SigningKey -> VerificationKey
Crypto.toVerification (SigningKey -> ExceptT ByronGenesisError IO Certificate)
-> SigningKey -> ExceptT ByronGenesisError IO Certificate
forall a b. (a -> b) -> a -> b
$ SigningKey
sk
      Just Certificate
x  -> Certificate -> ExceptT ByronGenesisError IO Certificate
forall (m :: * -> *) a x. Monad m => a -> ExceptT x m a
right Certificate
x
  genesisJSONFile :: FilePath
  genesisJSONFile :: String
genesisJSONFile = String
outDir String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"/genesis.json"

  printFakeAvvmSecrets :: Crypto.RedeemSigningKey -> Either ByronGenesisError LB.ByteString
  printFakeAvvmSecrets :: RedeemSigningKey -> Either ByronGenesisError ByteString
printFakeAvvmSecrets RedeemSigningKey
rskey = ByteString -> Either ByronGenesisError ByteString
forall a b. b -> Either a b
Right (ByteString -> Either ByronGenesisError ByteString)
-> (Builder -> ByteString)
-> Builder
-> Either ByronGenesisError ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByteString -> ByteString
LB.fromStrict (ByteString -> ByteString)
-> (Builder -> ByteString) -> Builder -> ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> ByteString
encodeUtf8 (Text -> ByteString) -> (Builder -> Text) -> Builder -> ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> Text
toStrict (Text -> Text) -> (Builder -> Text) -> Builder -> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Builder -> Text
toLazyText (Builder -> Either ByronGenesisError ByteString)
-> Builder -> Either ByronGenesisError ByteString
forall a b. (a -> b) -> a -> b
$ RedeemSigningKey -> Builder
forall p. Buildable p => p -> Builder
build RedeemSigningKey
rskey

  -- Compare a given 'SigningKey' with a 'Certificate' 'VerificationKey'
  isCertForSK :: SigningKey -> Certificate -> Bool
  isCertForSK :: SigningKey -> Certificate -> Bool
isCertForSK SigningKey
sk Certificate
cert = Certificate -> VerificationKey
forall a. ACertificate a -> VerificationKey
delegateVK Certificate
cert VerificationKey -> VerificationKey -> Bool
forall a. Eq a => a -> a -> Bool
== SigningKey -> VerificationKey
Crypto.toVerification SigningKey
sk
  wOut :: String -> String -> (a -> IO (Either ByronGenesisError LB.ByteString)) -> [a] -> IO ()
  wOut :: String
-> String
-> (a -> IO (Either ByronGenesisError ByteString))
-> [a]
-> IO ()
wOut = String
-> String
-> String
-> (a -> IO (Either ByronGenesisError ByteString))
-> [a]
-> IO ()
forall a.
String
-> String
-> String
-> (a -> IO (Either ByronGenesisError ByteString))
-> [a]
-> IO ()
writeSecrets String
outDir


serialiseGenesis :: Genesis.GenesisData -> LB.ByteString
serialiseGenesis :: GenesisData -> ByteString
serialiseGenesis = GenesisData -> ByteString
forall a. ToJSON Identity a => a -> ByteString
canonicalEncodePretty

writeSecrets :: FilePath -> String -> String -> (a -> IO (Either ByronGenesisError LB.ByteString)) -> [a] -> IO ()
writeSecrets :: String
-> String
-> String
-> (a -> IO (Either ByronGenesisError ByteString))
-> [a]
-> IO ()
writeSecrets String
outDir String
prefix String
suffix a -> IO (Either ByronGenesisError ByteString)
secretOp [a]
xs =
  [(a, Int)] -> ((a, Int) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([a] -> [Int] -> [(a, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [a]
xs [Int
0::Int ..]) (((a, Int) -> IO ()) -> IO ()) -> ((a, Int) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$
  \(a
secret, Int
nr)-> do
    let filename :: String
filename = String
outDir String -> ShowS
</> String
prefix String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"." String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String -> Int -> String
forall r. PrintfType r => String -> r
printf String
"%03d" Int
nr String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"." String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
suffix
    Either ByronGenesisError ByteString
result <- a -> IO (Either ByronGenesisError ByteString)
secretOp a
secret
    case Either ByronGenesisError ByteString
result of
      Left ByronGenesisError
cliError -> Text -> IO ()
forall a. HasCallStack => Text -> a
panic (Text -> IO ()) -> (String -> Text) -> String -> IO ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Text
forall a b. ConvertText a b => a -> b
toS (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ ByronGenesisError -> String
forall a. Show a => a -> String
show ByronGenesisError
cliError
      Right ByteString
bs -> String -> ByteString -> IO ()
LB.writeFile String
filename ByteString
bs
#ifdef UNIX
    String -> FileMode -> IO ()
setFileMode    String
filename FileMode
ownerReadMode
#else
    setPermissions filename (emptyPermissions {readable = True})
#endif