Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mnemonic sentence support #975

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
14 changes: 14 additions & 0 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ index-state:
packages:
cardano-cli

source-repository-package
type: git
location: https://github.com/intersectmbo/cardano-addresses.git
tag: b170724d92549a69fc3074b5f9b3f1871701aaab
subdir: core
--sha256: sha256-ldr7lEdME4XUjtgARPDBMMzeg3i2UojlW03ab3Pv0T0=

source-repository-package
type: git
location: https://github.com/intersectmbo/cardano-api.git
tag: 29ca290f33c8df3d54e68cd566a762fa4aad2693
subdir: cardano-api
--sha256: sha256-LuCEwN4nAiAfDelb7slBTkvfvUqQFQK0mMwaOF1kcHo=

program-options
ghc-options: -Werror

Expand Down
24 changes: 24 additions & 0 deletions cardano-cli/src/Cardano/CLI/Commands/Key.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ module Cardano.CLI.Commands.Key
( KeyCmds (..)
, KeyVerificationKeyCmdArgs (..)
, KeyNonExtendedKeyCmdArgs (..)
, KeyExtendedSigningKeyFromMnemonicArgs (..)
, ExtendedSigningType (..)
, KeyConvertByronKeyCmdArgs (..)
, KeyConvertByronGenesisVKeyCmdArgs (..)
, KeyConvertITNKeyCmdArgs (..)
Expand All @@ -19,12 +21,14 @@ where
import Cardano.Api.Shelley

import Cardano.CLI.Types.Common
import Cardano.Prelude (Word32)

import Data.Text (Text)

data KeyCmds
= KeyVerificationKeyCmd !KeyVerificationKeyCmdArgs
| KeyNonExtendedKeyCmd !KeyNonExtendedKeyCmdArgs
| KeyExtendedSigningKeyFromMnemonicCmd !KeyExtendedSigningKeyFromMnemonicArgs
| KeyConvertByronKeyCmd !KeyConvertByronKeyCmdArgs
| KeyConvertByronGenesisVKeyCmd !KeyConvertByronGenesisVKeyCmdArgs
| KeyConvertITNKeyCmd !KeyConvertITNKeyCmdArgs
Expand Down Expand Up @@ -52,6 +56,24 @@ data KeyNonExtendedKeyCmdArgs = KeyNonExtendedKeyCmdArgs
}
deriving Show

-- | Get a verification key from a mnemonic. This supports all extended key types.
palas marked this conversation as resolved.
Show resolved Hide resolved
data KeyExtendedSigningKeyFromMnemonicArgs = KeyExtendedSigningKeyFromMnemonicArgs
{ keyOutputFormat :: !KeyOutputFormat
, extendedSigningKeyType :: !ExtendedSigningType
palas marked this conversation as resolved.
Show resolved Hide resolved
, derivationAccountNo :: !Word32
, mnemonic :: !Text
, signingKeyFileOut :: !(SigningKeyFile Out)
}
deriving Show

data ExtendedSigningType
palas marked this conversation as resolved.
Show resolved Hide resolved
= ExtendedSigningPaymentKey !Word32
| ExtendedSigningStakeKey !Word32
| ExtendedSigningDRepKey
| ExtendedSigningCCColdKey
| ExtendedSigningCCHotKey
deriving Show

-- | Convert a Byron payment, genesis or genesis delegate key (signing or
-- verification) to a corresponding Shelley-format key.
data KeyConvertByronKeyCmdArgs = KeyConvertByronKeyCmdArgs
Expand Down Expand Up @@ -124,6 +146,8 @@ renderKeyCmds = \case
"key verification-key"
KeyNonExtendedKeyCmd{} ->
"key non-extended-key"
KeyExtendedSigningKeyFromMnemonicCmd{} ->
"key from-mnemonic"
KeyConvertByronKeyCmd{} ->
"key convert-byron-key"
KeyConvertByronGenesisVKeyCmd{} ->
Expand Down
85 changes: 85 additions & 0 deletions cardano-cli/src/Cardano/CLI/Options/Key.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import Cardano.CLI.Types.Common

import Data.Foldable
import Data.Text (Text)
import qualified Data.Text as Text
import GHC.Word (Word32)
import Options.Applicative hiding (help, str)
import qualified Options.Applicative as Opt

Expand All @@ -42,6 +44,12 @@ pKeyCmds =
, "extended verification key. This supports all "
, "extended key types."
]
, subParser "key-from-mnemonic" $
Opt.info pKeyExtendedSigningKeyFromMnemonicCmd $
Opt.progDesc $
mconcat
[ "Derive an extended signing key from a mnemonic."
]
, subParser "convert-byron-key" $
Opt.info pKeyConvertByronKeyCmd $
Opt.progDesc $
Expand Down Expand Up @@ -114,6 +122,83 @@ pKeyNonExtendedKeyCmd =
<$> pExtendedVerificationKeyFileIn
<*> pVerificationKeyFileOut

pKeyExtendedSigningKeyFromMnemonicCmd :: Parser KeyCmds
pKeyExtendedSigningKeyFromMnemonicCmd =
fmap KeyExtendedSigningKeyFromMnemonicCmd $
KeyExtendedSigningKeyFromMnemonicArgs
<$> pKeyOutputFormat
<*> pExtendedSigningKeyType
<*> pAccountNumber
<*> pMnemonicSentence
<*> pSigningKeyFileOut

pExtendedSigningKeyType :: Parser ExtendedSigningType
pExtendedSigningKeyType =
asum
[ ( ExtendedSigningPaymentKey
<$ ( Opt.flag' () $
mconcat
[ Opt.long "payment-key"
, Opt.help "Derive an extended payment key."
]
)
)
<*> pPaymentAddressNumber
, ( ExtendedSigningStakeKey
<$ ( Opt.flag' () $
mconcat
[ Opt.long "stake-key"
, Opt.help "Derive an extended stake key."
]
)
)
<*> pPaymentAddressNumber
, Opt.flag' ExtendedSigningDRepKey $
mconcat
[ Opt.long "drep-key"
, Opt.help "Derive an extended DRep key."
]
, Opt.flag' ExtendedSigningCCColdKey $
mconcat
[ Opt.long "cc-cold-key"
, Opt.help "Derive an extended committee cold key."
]
, Opt.flag' ExtendedSigningCCHotKey $
mconcat
[ Opt.long "cc-hot-key"
, Opt.help "Derive an extended committee hot key."
]
]

pPaymentAddressNumber :: Parser Word32
pPaymentAddressNumber =
Opt.option integralReader $
mconcat
[ Opt.long "payment-address-number"
, Opt.metavar "WORD32"
, Opt.help "Payment address number in the derivation path."
]

pAccountNumber :: Parser Word32
pAccountNumber =
Opt.option integralReader $
mconcat
[ Opt.long "account-number"
, Opt.metavar "WORD32"
, Opt.help "Account number in the derivation path."
]

pMnemonicSentence :: Parser Text
pMnemonicSentence =
fmap Text.pack $
Opt.strOption $
mconcat
[ Opt.long "mnemonic-phrase"
, Opt.metavar "MNEMONIC"
, Opt.help
"Series of words separated by spaces that represent the mnemonic phrase. The number of words must be one of: 12, 15, 18, 21, or 24."
]

pKeyConvertByronKeyCmd :: Parser KeyCmds
pKeyConvertByronKeyCmd =
fmap KeyConvertByronKeyCmd $
Expand Down
70 changes: 70 additions & 0 deletions cardano-cli/src/Cardano/CLI/Run/Key.hs
palas marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Data.Function
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import System.Exit (exitFailure)
Expand Down Expand Up @@ -112,6 +113,8 @@ runKeyCmds = \case
runVerificationKeyCmd cmd
Cmd.KeyNonExtendedKeyCmd cmd ->
runNonExtendedKeyCmd cmd
Cmd.KeyExtendedSigningKeyFromMnemonicCmd cmd ->
runExtendedSigningKeyFromMnemonicCmd cmd
Cmd.KeyConvertByronKeyCmd cmd ->
runConvertByronKeyCmd cmd
Cmd.KeyConvertByronGenesisVKeyCmd cmd ->
Expand Down Expand Up @@ -232,6 +235,73 @@ readExtendedVerificationKeyFile evkfile = do
where
goFail k = left $ KeyCmdExpectedExtendedVerificationKey k

runExtendedSigningKeyFromMnemonicCmd
:: Cmd.KeyExtendedSigningKeyFromMnemonicArgs
-> ExceptT KeyCmdError IO ()
runExtendedSigningKeyFromMnemonicCmd
Cmd.KeyExtendedSigningKeyFromMnemonicArgs
{ keyOutputFormat
, extendedSigningKeyType
, derivationAccountNo
, mnemonic
, signingKeyFileOut
} = do
let writeKeyToFile
:: (HasTextEnvelope (SigningKey a), SerialiseAsBech32 (SigningKey a))
=> SigningKey a -> ExceptT KeyCmdError IO ()
writeKeyToFile = writeSigningKeyFile keyOutputFormat signingKeyFileOut

wrapException :: Either MnemonicToSigningKeyError a -> ExceptT KeyCmdError IO a
wrapException = except . first KeyCmdMnemonicError

mnemonicWords = map T.pack $ words $ T.unpack mnemonic

case extendedSigningKeyType of
Cmd.ExtendedSigningPaymentKey paymentKeyNo ->
writeKeyToFile
=<< wrapException
( signingKeyFromMnemonicWithPaymentKeyIndex
AsPaymentExtendedKey
mnemonicWords
derivationAccountNo
paymentKeyNo
)
Cmd.ExtendedSigningStakeKey paymentKeyNo ->
writeKeyToFile
=<< wrapException
( signingKeyFromMnemonicWithPaymentKeyIndex
AsStakeExtendedKey
mnemonicWords
derivationAccountNo
paymentKeyNo
)
Cmd.ExtendedSigningDRepKey ->
writeKeyToFile
=<< wrapException (signingKeyFromMnemonic AsDRepExtendedKey mnemonicWords derivationAccountNo)
Cmd.ExtendedSigningCCColdKey ->
writeKeyToFile
=<< wrapException
(signingKeyFromMnemonic AsCommitteeColdExtendedKey mnemonicWords derivationAccountNo)
Cmd.ExtendedSigningCCHotKey ->
writeKeyToFile
=<< wrapException
(signingKeyFromMnemonic AsCommitteeHotExtendedKey mnemonicWords derivationAccountNo)
where
writeSigningKeyFile
:: (HasTextEnvelope (SigningKey a), SerialiseAsBech32 (SigningKey a))
=> KeyOutputFormat -> SigningKeyFile Out -> SigningKey a -> ExceptT KeyCmdError IO ()
writeSigningKeyFile fmt sKeyPath skey =
firstExceptT KeyCmdWriteFileError $
case fmt of
KeyOutputFormatTextEnvelope ->
newExceptT $
writeLazyByteStringFile sKeyPath $
textEnvelopeToJSON Nothing skey
KeyOutputFormatBech32 ->
newExceptT $
writeTextFile sKeyPath $
serialiseToBech32 skey

runConvertByronKeyCmd
:: Cmd.KeyConvertByronKeyCmdArgs
-> ExceptT KeyCmdError IO ()
Expand Down
3 changes: 3 additions & 0 deletions cardano-cli/src/Cardano/CLI/Types/Errors/KeyCmdError.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ data KeyCmdError
= KeyCmdReadFileError !(FileError TextEnvelopeError)
| KeyCmdReadKeyFileError !(FileError InputDecodeError)
| KeyCmdWriteFileError !(FileError ())
| KeyCmdMnemonicError MnemonicToSigningKeyError
| KeyCmdByronKeyFailure !Byron.ByronKeyFailure
| -- | Text representation of the parse error. Unfortunately, the actual
-- error type isn't exported.
Expand All @@ -45,6 +46,8 @@ renderKeyCmdError err =
prettyError fileErr
KeyCmdWriteFileError fileErr ->
prettyError fileErr
KeyCmdMnemonicError mnemonicErr ->
"Error converting the mnemonic into a key: " <> prettyError mnemonicErr
KeyCmdByronKeyFailure e ->
Byron.renderByronKeyFailure e
KeyCmdByronKeyParseError errTxt ->
Expand Down
Loading