never executed always true always false
    1 {-# LANGUAGE FlexibleContexts #-}
    2 {-# LANGUAGE NamedFieldPuns #-}
    3 
    4 {-# OPTIONS_HADDOCK hide #-}
    5 {-# OPTIONS_GHC -fno-warn-deprecations #-}
    6 
    7 module Command.Address.Bootstrap
    8     ( Cmd
    9     , mod
   10     , run
   11     ) where
   12 
   13 import Prelude hiding
   14     ( mod )
   15 
   16 import Cardano.Address
   17     ( AddressDiscrimination (..), NetworkDiscriminant, base58 )
   18 import Cardano.Address.Derivation
   19     ( XPub, coerceWholeDomainIndex )
   20 import Cardano.Address.Style.Byron
   21     ( Byron )
   22 import Options.Applicative
   23     ( CommandFields
   24     , Mod
   25     , command
   26     , footerDoc
   27     , header
   28     , helper
   29     , info
   30     , optional
   31     , progDesc
   32     )
   33 import Options.Applicative.Derivation
   34     ( DerivationPath, castDerivationPath, derivationPathArg, xpubOpt )
   35 import Options.Applicative.Discrimination
   36     ( NetworkTag (..), networkTagOpt )
   37 import Options.Applicative.Help.Pretty
   38     ( bold, indent, string, vsep )
   39 import Options.Applicative.Style
   40     ( Style (..) )
   41 import System.IO
   42     ( stdin, stdout )
   43 import System.IO.Extra
   44     ( hGetXPub, progName )
   45 
   46 import qualified Cardano.Address.Style.Byron as Byron
   47 import qualified Cardano.Address.Style.Icarus as Icarus
   48 import qualified Cardano.Codec.Bech32.Prefixes as CIP5
   49 import qualified Data.ByteString.Char8 as B8
   50 import qualified Data.Text.Encoding as T
   51 
   52 data Cmd = Cmd
   53     { rootXPub :: Maybe XPub
   54     , networkTag :: NetworkTag
   55     , derivationPath :: Maybe DerivationPath
   56     } deriving (Show)
   57 
   58 mod :: (Cmd -> parent) -> Mod CommandFields parent
   59 mod liftCmd = command "bootstrap" $
   60     info (helper <*> fmap liftCmd parser) $ mempty
   61         <> progDesc "Create a bootstrap address"
   62         <> header "Those addresses, now deprecated, were used during the Byron era."
   63         <> footerDoc (Just $ vsep
   64             [ string "Example:"
   65             , indent 2 $ bold $ string $ "$ "<>progName<>" recovery-phrase generate --size 12 \\"
   66             , indent 4 $ bold $ string $ "| "<>progName<>" key from-recovery-phrase Byron > root.prv"
   67             , indent 2 $ string ""
   68             , indent 2 $ bold $ string "$ cat root.prv \\"
   69             , indent 4 $ bold $ string $ "| "<>progName<>" key child 14H/42H | tee addr.prv \\"
   70             , indent 4 $ bold $ string $ "| "<>progName<>" key public --with-chain-code \\"
   71             , indent 4 $ bold $ string $ "| "<>progName<>" address bootstrap --root $(cat root.prv | "<>progName<>" key public --with-chain-code) \\"
   72             , indent 8 $ bold $ string "--network-tag preview 14H/42H"
   73             , indent 2 $ string "KjgoiXJS2coBYYTM69pafiau6bbGqKrzbFiRzahpWsPvit48YNiHocPpB7VJ..."
   74             ])
   75   where
   76     parser = Cmd
   77         <$> optional (xpubOpt [CIP5.root_xvk] "root" "A root public key. Needed for Byron addresses only.")
   78         <*> networkTagOpt Byron
   79         <*> optional derivationPathArg
   80 
   81 run :: Cmd -> IO ()
   82 run Cmd{networkTag,rootXPub,derivationPath} = do
   83     (_hrp, xpub) <- hGetXPub stdin [CIP5.addr_xvk]
   84     addr <- case derivationPath of
   85         Nothing ->
   86             pure $ Icarus.paymentAddress discriminant (Icarus.liftXPub xpub)
   87         Just untypedPath -> do
   88             root <- maybe
   89                 (fail "A root public key must be provided when --path is provided") pure rootXPub
   90             case castDerivationPath untypedPath of
   91                 [acctIx, addrIx] -> do
   92                     let path = (acctIx, coerceWholeDomainIndex addrIx)
   93                         xkey = Byron.liftXPub root path xpub
   94                     pure $ Byron.paymentAddress discriminant xkey
   95                 _ -> do
   96                     fail "Byron derivation path must describe 2 levels (e.g. 0H/0H)"
   97     B8.hPutStr stdout $ T.encodeUtf8 $ base58 addr
   98   where
   99     discriminant :: NetworkDiscriminant Byron -- Or Icarus, same.
  100     discriminant
  101         | networkTag == snd Byron.byronMainnet =
  102             Byron.byronMainnet
  103         | otherwise =
  104             (RequiresNetworkTag, networkTag)