module Hydra.Utils where import Hydra.Prelude import Crypto.Random (getRandomBytes) import Data.Aeson qualified as Aeson import Data.Aeson.Types qualified as Aeson import GHC.IO.Exception (userError) import Hydra.Cardano.Api (File (..), FileError (FileIOError), writeFileTextEnvelope) import Hydra.Options (GenerateKeyPair (..)) import Hydra.Tx.Crypto (HydraKey, SigningKey, generateSigningKey, getVerificationKey) import Hydra.Tx.Secret (Secret, withSecret) import System.Directory (doesFileExist) import System.FilePath ((<.>)) genHydraKeys :: GenerateKeyPair -> IO (Either (FileError ()) ()) genHydraKeys :: GenerateKeyPair -> IO (Either (FileError ()) ()) genHydraKeys GenerateKeyPair{FilePath outputFile :: FilePath $sel:outputFile:GenerateKeyPair :: GenerateKeyPair -> FilePath outputFile} = do Bool fileExists <- FilePath -> IO Bool doesFileExist FilePath outputFile if Bool fileExists then Either (FileError ()) () -> IO (Either (FileError ()) ()) forall a. a -> IO a forall (f :: * -> *) a. Applicative f => a -> f a pure (Either (FileError ()) () -> IO (Either (FileError ()) ())) -> Either (FileError ()) () -> IO (Either (FileError ()) ()) forall a b. (a -> b) -> a -> b $ FileError () -> Either (FileError ()) () forall a b. a -> Either a b Left (FileError () -> Either (FileError ()) ()) -> FileError () -> Either (FileError ()) () forall a b. (a -> b) -> a -> b $ FilePath -> IOException -> FileError () forall e. FilePath -> IOException -> FileError e FileIOError FilePath outputFile (FilePath -> IOException userError FilePath "File already exists! Please remove it in order to generate new hydra keys.") else do Secret (SigningKey HydraKey) sk :: Secret (SigningKey HydraKey) <- ByteString -> Secret (SigningKey HydraKey) generateSigningKey (ByteString -> Secret (SigningKey HydraKey)) -> IO ByteString -> IO (Secret (SigningKey HydraKey)) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Int -> IO ByteString forall byteArray. ByteArray byteArray => Int -> IO byteArray forall (m :: * -> *) byteArray. (MonadRandom m, ByteArray byteArray) => Int -> m byteArray getRandomBytes Int 16 ExceptT (FileError ()) IO () -> IO (Either (FileError ()) ()) forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a) runExceptT (ExceptT (FileError ()) IO () -> IO (Either (FileError ()) ())) -> ExceptT (FileError ()) IO () -> IO (Either (FileError ()) ()) forall a b. (a -> b) -> a -> b $ do IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO () forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a ExceptT (IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ()) -> IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO () forall a b. (a -> b) -> a -> b $ Secret (SigningKey HydraKey) -> (SigningKey HydraKey -> IO (Either (FileError ()) ())) -> IO (Either (FileError ()) ()) forall a r. Secret a -> (a -> r) -> r withSecret Secret (SigningKey HydraKey) sk (File Any 'Out -> Maybe TextEnvelopeDescr -> SigningKey HydraKey -> IO (Either (FileError ()) ()) forall a content. HasTextEnvelope a => File content 'Out -> Maybe TextEnvelopeDescr -> a -> IO (Either (FileError ()) ()) writeFileTextEnvelope (FilePath -> File Any 'Out forall content (direction :: FileDirection). FilePath -> File content direction File (FilePath outputFile FilePath -> FilePath -> FilePath <.> FilePath "sk")) Maybe TextEnvelopeDescr forall a. Maybe a Nothing) IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO () forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a ExceptT (IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ()) -> IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO () forall a b. (a -> b) -> a -> b $ File Any 'Out -> Maybe TextEnvelopeDescr -> VerificationKey HydraKey -> IO (Either (FileError ()) ()) forall a content. HasTextEnvelope a => File content 'Out -> Maybe TextEnvelopeDescr -> a -> IO (Either (FileError ()) ()) writeFileTextEnvelope (FilePath -> File Any 'Out forall content (direction :: FileDirection). FilePath -> File content direction File (FilePath outputFile FilePath -> FilePath -> FilePath <.> FilePath "vk")) Maybe TextEnvelopeDescr forall a. Maybe a Nothing (Secret (SigningKey HydraKey) -> VerificationKey HydraKey forall s k. HasVerificationKey s k => s -> VerificationKey k getVerificationKey Secret (SigningKey HydraKey) sk) readJsonFileThrow :: (Aeson.Value -> Aeson.Parser a) -> FilePath -> IO a readJsonFileThrow :: forall a. (Value -> Parser a) -> FilePath -> IO a readJsonFileThrow Value -> Parser a parser FilePath filepath = do Value value <- FilePath -> IO (Either FilePath Value) forall a. FromJSON a => FilePath -> IO (Either FilePath a) Aeson.eitherDecodeFileStrict FilePath filepath IO (Either FilePath Value) -> (Either FilePath Value -> IO Value) -> IO Value forall a b. IO a -> (a -> IO b) -> IO b forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= (FilePath -> IO Value) -> (Value -> IO Value) -> Either FilePath Value -> IO Value forall a c b. (a -> c) -> (b -> c) -> Either a b -> c either FilePath -> IO Value forall a. FilePath -> IO a forall (m :: * -> *) a. MonadFail m => FilePath -> m a fail Value -> IO Value forall a. a -> IO a forall (f :: * -> *) a. Applicative f => a -> f a pure case (Value -> Parser a) -> Value -> Either FilePath a forall a b. (a -> Parser b) -> a -> Either FilePath b Aeson.parseEither Value -> Parser a parser Value value of Left FilePath e -> FilePath -> IO a forall a. FilePath -> IO a forall (m :: * -> *) a. MonadFail m => FilePath -> m a fail FilePath e Right a a -> a -> IO a forall a. a -> IO a forall (f :: * -> *) a. Applicative f => a -> f a pure a a