{-# LANGUAGE GeneralisedNewtypeDeriving #-}

module Bcc.CLI.Cole.Key
  ( -- * Keys
    ColeKeyFailure(..)
  , NewSigningKeyFile(..)
  , NewVerificationKeyFile(..)
  , VerificationKeyFile(..)
  , prettyPublicKey
  , readColeSigningKey
  , readPaymentVerificationKey
  , renderColeKeyFailure
  , coleWitnessToVerKey
  )
where

import           Bcc.Prelude hiding (option, show, trace, (%))
import           Prelude (show)

import           Control.Monad.Trans.Except.Extra (firstExceptT, handleIOExceptT, hoistEither, left,
                     right)
import qualified Data.ByteString as SB
import qualified Data.ByteString.UTF8 as UTF8
import           Data.String (fromString)
import qualified Data.Text as T
import           Formatting (build, sformat, (%))

import           Bcc.Api.Cole

import qualified Bcc.Chain.Common as Common
import           Bcc.CLI.Helpers (textShow)
import           Bcc.CLI.Sophie.Commands (ColeKeyFormat (..))
import           Bcc.CLI.Types
import qualified Bcc.Crypto.Signing as Crypto


data ColeKeyFailure
  = ReadSigningKeyFailure !FilePath !Text
  | ReadVerificationKeyFailure !FilePath !Text
  | LegacySigningKeyDeserialisationFailed !FilePath
  | SigningKeyDeserialisationFailed !FilePath
  | VerificationKeyDeserialisationFailed !FilePath !Text
  | CannotMigrateFromNonLegacySigningKey !FilePath
  deriving Int -> ColeKeyFailure -> ShowS
[ColeKeyFailure] -> ShowS
ColeKeyFailure -> String
(Int -> ColeKeyFailure -> ShowS)
-> (ColeKeyFailure -> String)
-> ([ColeKeyFailure] -> ShowS)
-> Show ColeKeyFailure
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ColeKeyFailure] -> ShowS
$cshowList :: [ColeKeyFailure] -> ShowS
show :: ColeKeyFailure -> String
$cshow :: ColeKeyFailure -> String
showsPrec :: Int -> ColeKeyFailure -> ShowS
$cshowsPrec :: Int -> ColeKeyFailure -> ShowS
Show

renderColeKeyFailure :: ColeKeyFailure -> Text
renderColeKeyFailure :: ColeKeyFailure -> Text
renderColeKeyFailure ColeKeyFailure
err =
  case ColeKeyFailure
err of
    CannotMigrateFromNonLegacySigningKey String
fp ->
      Text
"Migrate from non-legacy Cole key unnecessary: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
fp
    ReadSigningKeyFailure String
sKeyFp Text
readErr ->
      Text
"Error reading signing key at: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
sKeyFp Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" Error: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
forall a. Show a => a -> Text
textShow Text
readErr
    ReadVerificationKeyFailure String
vKeyFp Text
readErr ->
      Text
"Error reading verification key at: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
vKeyFp Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" Error: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
forall a. Show a => a -> Text
textShow Text
readErr
    LegacySigningKeyDeserialisationFailed String
fp ->
      Text
"Error attempting to deserialise a legacy signing key at: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
fp
    SigningKeyDeserialisationFailed String
sKeyFp  ->
      Text
"Error deserialising signing key at: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
sKeyFp
    VerificationKeyDeserialisationFailed String
vKeyFp Text
deSerError ->
      Text
"Error deserialising verification key at: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. Show a => a -> Text
textShow String
vKeyFp Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" Error: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
forall a. Show a => a -> Text
textShow Text
deSerError

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

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

-- | Print some invariant properties of a public key:
--   its hash and formatted view.
prettyPublicKey :: VerificationKey ColeKey-> Text
prettyPublicKey :: VerificationKey ColeKey -> Text
prettyPublicKey (ColeVerificationKey vk) =
  Format
  Text
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
-> AddressHash VerificationKey
-> VerificationKey
-> VerificationKey
-> Text
forall a. Format Text a -> a
sformat (  Format
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
"    public key hash: "Format
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
-> Format
     Text
     (AddressHash VerificationKey
      -> VerificationKey -> VerificationKey -> Text)
-> Format
     Text
     (AddressHash VerificationKey
      -> VerificationKey -> VerificationKey -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format
  (VerificationKey -> VerificationKey -> Text)
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
forall a r. Buildable a => Format r (a -> r)
build Format
  (VerificationKey -> VerificationKey -> Text)
  (AddressHash VerificationKey
   -> VerificationKey -> VerificationKey -> Text)
-> Format Text (VerificationKey -> VerificationKey -> Text)
-> Format
     Text
     (AddressHash VerificationKey
      -> VerificationKey -> VerificationKey -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
%
           Format
  (VerificationKey -> VerificationKey -> Text)
  (VerificationKey -> VerificationKey -> Text)
"\npublic key (base64): "Format
  (VerificationKey -> VerificationKey -> Text)
  (VerificationKey -> VerificationKey -> Text)
-> Format Text (VerificationKey -> VerificationKey -> Text)
-> Format Text (VerificationKey -> VerificationKey -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format
  (VerificationKey -> Text)
  (VerificationKey -> VerificationKey -> Text)
forall r. Format r (VerificationKey -> r)
Crypto.fullVerificationKeyF Format
  (VerificationKey -> Text)
  (VerificationKey -> VerificationKey -> Text)
-> Format Text (VerificationKey -> Text)
-> Format Text (VerificationKey -> VerificationKey -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
%
           Format (VerificationKey -> Text) (VerificationKey -> Text)
"\n   public key (hex): "Format (VerificationKey -> Text) (VerificationKey -> Text)
-> Format Text (VerificationKey -> Text)
-> Format Text (VerificationKey -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format Text (VerificationKey -> Text)
forall r. Format r (VerificationKey -> r)
Crypto.fullVerificationKeyHexF)
    (VerificationKey -> AddressHash VerificationKey
forall a. ToCBOR a => a -> AddressHash a
Common.addressHash VerificationKey
vk) VerificationKey
vk VerificationKey
vk

coleWitnessToVerKey :: SomeColeSigningKey -> VerificationKey ColeKey
coleWitnessToVerKey :: SomeColeSigningKey -> VerificationKey ColeKey
coleWitnessToVerKey (AColeSigningKeyLegacy SigningKey ColeKeyLegacy
sKeyLeg) = VerificationKey ColeKeyLegacy -> VerificationKey ColeKey
forall keyroleA keyroleB.
CastVerificationKeyRole keyroleA keyroleB =>
VerificationKey keyroleA -> VerificationKey keyroleB
castVerificationKey (VerificationKey ColeKeyLegacy -> VerificationKey ColeKey)
-> VerificationKey ColeKeyLegacy -> VerificationKey ColeKey
forall a b. (a -> b) -> a -> b
$ SigningKey ColeKeyLegacy -> VerificationKey ColeKeyLegacy
forall keyrole.
Key keyrole =>
SigningKey keyrole -> VerificationKey keyrole
getVerificationKey SigningKey ColeKeyLegacy
sKeyLeg
coleWitnessToVerKey (AColeSigningKey SigningKey ColeKey
sKeyNonLeg) = SigningKey ColeKey -> VerificationKey ColeKey
forall keyrole.
Key keyrole =>
SigningKey keyrole -> VerificationKey keyrole
getVerificationKey SigningKey ColeKey
sKeyNonLeg

-- TODO:  we need to support password-protected secrets.
-- | Read signing key from a file.
readColeSigningKey :: ColeKeyFormat -> SigningKeyFile -> ExceptT ColeKeyFailure IO SomeColeSigningKey
readColeSigningKey :: ColeKeyFormat
-> SigningKeyFile -> ExceptT ColeKeyFailure IO SomeColeSigningKey
readColeSigningKey ColeKeyFormat
bKeyFormat (SigningKeyFile String
fp) = do
  ByteString
sK <- (IOException -> ColeKeyFailure)
-> IO ByteString -> ExceptT ColeKeyFailure IO ByteString
forall (m :: * -> *) x a.
MonadIO m =>
(IOException -> x) -> IO a -> ExceptT x m a
handleIOExceptT (String -> Text -> ColeKeyFailure
ReadSigningKeyFailure String
fp (Text -> ColeKeyFailure)
-> (IOException -> Text) -> IOException -> ColeKeyFailure
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Text
T.pack (String -> Text) -> (IOException -> String) -> IOException -> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IOException -> String
forall e. Exception e => e -> String
displayException) (IO ByteString -> ExceptT ColeKeyFailure IO ByteString)
-> IO ByteString -> ExceptT ColeKeyFailure IO ByteString
forall a b. (a -> b) -> a -> b
$ String -> IO ByteString
SB.readFile String
fp
  case ColeKeyFormat
bKeyFormat of
    ColeKeyFormat
LegacyColeKeyFormat ->
      case AsType (SigningKey ColeKeyLegacy)
-> ByteString -> Maybe (SigningKey ColeKeyLegacy)
forall a.
SerialiseAsRawBytes a =>
AsType a -> ByteString -> Maybe a
deserialiseFromRawBytes (AsType ColeKeyLegacy -> AsType (SigningKey ColeKeyLegacy)
forall a. AsType a -> AsType (SigningKey a)
AsSigningKey AsType ColeKeyLegacy
AsColeKeyLegacy) ByteString
sK of
        Just SigningKey ColeKeyLegacy
legKey -> SomeColeSigningKey -> ExceptT ColeKeyFailure IO SomeColeSigningKey
forall (m :: * -> *) a x. Monad m => a -> ExceptT x m a
right (SomeColeSigningKey
 -> ExceptT ColeKeyFailure IO SomeColeSigningKey)
-> SomeColeSigningKey
-> ExceptT ColeKeyFailure IO SomeColeSigningKey
forall a b. (a -> b) -> a -> b
$ SigningKey ColeKeyLegacy -> SomeColeSigningKey
AColeSigningKeyLegacy SigningKey ColeKeyLegacy
legKey
        Maybe (SigningKey ColeKeyLegacy)
Nothing -> ColeKeyFailure -> ExceptT ColeKeyFailure IO SomeColeSigningKey
forall (m :: * -> *) x a. Monad m => x -> ExceptT x m a
left (ColeKeyFailure -> ExceptT ColeKeyFailure IO SomeColeSigningKey)
-> ColeKeyFailure -> ExceptT ColeKeyFailure IO SomeColeSigningKey
forall a b. (a -> b) -> a -> b
$ String -> ColeKeyFailure
LegacySigningKeyDeserialisationFailed String
fp
    ColeKeyFormat
NonLegacyColeKeyFormat ->
      case AsType (SigningKey ColeKey)
-> ByteString -> Maybe (SigningKey ColeKey)
forall a.
SerialiseAsRawBytes a =>
AsType a -> ByteString -> Maybe a
deserialiseFromRawBytes (AsType ColeKey -> AsType (SigningKey ColeKey)
forall a. AsType a -> AsType (SigningKey a)
AsSigningKey AsType ColeKey
AsColeKey) ByteString
sK of
        Just SigningKey ColeKey
nonLegSKey -> SomeColeSigningKey -> ExceptT ColeKeyFailure IO SomeColeSigningKey
forall (m :: * -> *) a x. Monad m => a -> ExceptT x m a
right (SomeColeSigningKey
 -> ExceptT ColeKeyFailure IO SomeColeSigningKey)
-> SomeColeSigningKey
-> ExceptT ColeKeyFailure IO SomeColeSigningKey
forall a b. (a -> b) -> a -> b
$ SigningKey ColeKey -> SomeColeSigningKey
AColeSigningKey SigningKey ColeKey
nonLegSKey
        Maybe (SigningKey ColeKey)
Nothing -> ColeKeyFailure -> ExceptT ColeKeyFailure IO SomeColeSigningKey
forall (m :: * -> *) x a. Monad m => x -> ExceptT x m a
left (ColeKeyFailure -> ExceptT ColeKeyFailure IO SomeColeSigningKey)
-> ColeKeyFailure -> ExceptT ColeKeyFailure IO SomeColeSigningKey
forall a b. (a -> b) -> a -> b
$ String -> ColeKeyFailure
SigningKeyDeserialisationFailed String
fp

-- | Read verification key from a file.  Throw an error if the file can't be read
-- or the key fails to deserialise.
readPaymentVerificationKey :: VerificationKeyFile -> ExceptT ColeKeyFailure IO Crypto.VerificationKey
readPaymentVerificationKey :: VerificationKeyFile -> ExceptT ColeKeyFailure IO VerificationKey
readPaymentVerificationKey (VerificationKeyFile String
fp) = do
  ByteString
vkB <- (IOException -> ColeKeyFailure)
-> IO ByteString -> ExceptT ColeKeyFailure IO ByteString
forall (m :: * -> *) x a.
MonadIO m =>
(IOException -> x) -> IO a -> ExceptT x m a
handleIOExceptT (String -> Text -> ColeKeyFailure
ReadVerificationKeyFailure String
fp (Text -> ColeKeyFailure)
-> (IOException -> Text) -> IOException -> ColeKeyFailure
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Text
T.pack (String -> Text) -> (IOException -> String) -> IOException -> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IOException -> String
forall e. Exception e => e -> String
displayException) (String -> IO ByteString
SB.readFile String
fp)
  -- Verification Key
  let eVk :: ExceptT VerificationKeyParseError IO VerificationKey
eVk = Either VerificationKeyParseError VerificationKey
-> ExceptT VerificationKeyParseError IO VerificationKey
forall (m :: * -> *) x a. Monad m => Either x a -> ExceptT x m a
hoistEither (Either VerificationKeyParseError VerificationKey
 -> ExceptT VerificationKeyParseError IO VerificationKey)
-> (String -> Either VerificationKeyParseError VerificationKey)
-> String
-> ExceptT VerificationKeyParseError IO VerificationKey
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> Either VerificationKeyParseError VerificationKey
Crypto.parseFullVerificationKey (Text -> Either VerificationKeyParseError VerificationKey)
-> (String -> Text)
-> String
-> Either VerificationKeyParseError VerificationKey
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. IsString a => String -> a
fromString (String -> ExceptT VerificationKeyParseError IO VerificationKey)
-> String -> ExceptT VerificationKeyParseError IO VerificationKey
forall a b. (a -> b) -> a -> b
$ ByteString -> String
UTF8.toString ByteString
vkB
  -- Convert error to 'CliError'
  (VerificationKeyParseError -> ColeKeyFailure)
-> ExceptT VerificationKeyParseError IO VerificationKey
-> ExceptT ColeKeyFailure IO VerificationKey
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT (String -> Text -> ColeKeyFailure
VerificationKeyDeserialisationFailed String
fp (Text -> ColeKeyFailure)
-> (VerificationKeyParseError -> Text)
-> VerificationKeyParseError
-> ColeKeyFailure
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Text
T.pack (String -> Text)
-> (VerificationKeyParseError -> String)
-> VerificationKeyParseError
-> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. VerificationKeyParseError -> String
forall a. Show a => a -> String
show) ExceptT VerificationKeyParseError IO VerificationKey
eVk