Skip to content

Commit

Permalink
Merge #1447
Browse files Browse the repository at this point in the history
1447: Extend Shelley transaction CLI to make use of separate witnesses r=intricate a=intricate



Co-authored-by: Jordan Millar <[email protected]>
Co-authored-by: Luke Nadur <[email protected]>
  • Loading branch information
3 people authored Jul 14, 2020
2 parents d283f3c + 6c657f6 commit f72ff6a
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 42 deletions.
4 changes: 2 additions & 2 deletions cardano-api/src/Cardano/Api/Typed.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1191,10 +1191,10 @@ instance SerialiseAsCBOR (Witness Shelley) where
"Shelley Witness" (fromIntegral t)

instance HasTextEnvelope (Witness Byron) where
textEnvelopeType _ = "TxWinessByron"
textEnvelopeType _ = "TxWitnessByron"

instance HasTextEnvelope (Witness Shelley) where
textEnvelopeType _ = "TxWinessShelley"
textEnvelopeType _ = "TxWitnessShelley"


getTxBody :: Tx era -> TxBody era
Expand Down
25 changes: 15 additions & 10 deletions cardano-cli/src/Cardano/CLI/Shelley/Commands.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ module Cardano.CLI.Shelley.Commands
, GenesisDir (..)
, TxInCount (..)
, TxOutCount (..)
, TxShelleyWinessCount (..)
, TxByronWinessCount (..)
, TxShelleyWitnessCount (..)
, TxByronWitnessCount (..)
, ITNKeyFile (..)
, OpCertCounterFile (..)
, OutputFile (..)
, ProtocolParamsFile (..)
, SigningKeyFile (..)
, WitnessFile (..)
, TxBodyFile (..)
, TxFile (..)
, VerificationKeyFile (..)
Expand Down Expand Up @@ -110,8 +111,8 @@ data TransactionCmd
(Maybe UpdateProposalFile)
TxBodyFile
| TxSign TxBodyFile [SigningKeyFile] (Maybe NetworkId) TxFile
| TxWitness -- { transaction :: Transaction, key :: PrivKeyFile, nodeAddr :: NodeAddress }
| TxSignWitness -- { transaction :: Transaction, witnesses :: [Witness], nodeAddr :: NodeAddress }
| TxWitness TxBodyFile SigningKeyFile (Maybe NetworkId) OutputFile
| TxSignWitness TxBodyFile [WitnessFile] OutputFile
| TxCheck -- { transaction :: Transaction, nodeAddr :: NodeAddress }
| TxSubmit Protocol NetworkId FilePath
| TxCalculateMinFee
Expand All @@ -120,8 +121,8 @@ data TransactionCmd
ProtocolParamsFile
TxInCount
TxOutCount
TxShelleyWinessCount
TxByronWinessCount
TxShelleyWitnessCount
TxByronWitnessCount
| TxGetTxId TxBodyFile
deriving (Eq, Show)

Expand Down Expand Up @@ -236,12 +237,12 @@ newtype TxOutCount
= TxOutCount Int
deriving (Eq, Show)

newtype TxShelleyWinessCount
= TxShelleyWinessCount Int
newtype TxShelleyWitnessCount
= TxShelleyWitnessCount Int
deriving (Eq, Show)

newtype TxByronWinessCount
= TxByronWinessCount Int
newtype TxByronWitnessCount
= TxByronWitnessCount Int
deriving (Eq, Show)

newtype BlockId
Expand Down Expand Up @@ -296,6 +297,10 @@ newtype PrivKeyFile
= PrivKeyFile FilePath
deriving (Eq, Show)

newtype WitnessFile
= WitnessFile FilePath
deriving (Eq, Show)

newtype TxBodyFile
= TxBodyFile FilePath
deriving (Eq, Show)
Expand Down
46 changes: 36 additions & 10 deletions cardano-cli/src/Cardano/CLI/Shelley/Parsers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,15 @@ pTransaction =
<*> pTxFile Output

pTransactionWitness :: Parser TransactionCmd
pTransactionWitness = pure TxWitness
pTransactionWitness = TxWitness <$> pTxBodyFile Input
<*> pWitnessSigningKeyFile
<*> optional pNetworkId
<*> pOutputFile

pTransactionSignWit :: Parser TransactionCmd
pTransactionSignWit = pure TxSignWitness
pTransactionSignWit = TxSignWitness <$> pTxBodyFile Input
<*> some pWitnessFile
<*> pOutputFile

pTransactionCheck :: Parser TransactionCmd
pTransactionCheck = pure TxCheck
Expand All @@ -331,8 +336,8 @@ pTransaction =
<*> pProtocolParamsFile
<*> pTxInCount
<*> pTxOutCount
<*> pTxShelleyWinessCount
<*> pTxByronWinessCount
<*> pTxShelleyWitnessCount
<*> pTxByronWitnessCount

pTransactionId :: Parser TransactionCmd
pTransactionId = TxGetTxId <$> pTxBodyFile Input
Expand Down Expand Up @@ -890,6 +895,17 @@ pByronKeyFile fdir =
<> Opt.completer (Opt.bashCompleter "file")
)

pWitnessSigningKeyFile :: Parser SigningKeyFile
pWitnessSigningKeyFile =
SigningKeyFile <$>
( Opt.strOption
( Opt.long "witness-signing-key-file"
<> Opt.metavar "FILE"
<> Opt.help "Filepath of the witness signing key."
<> Opt.completer (Opt.bashCompleter "file")
)
)

pBlockId :: Parser BlockId
pBlockId =
BlockId <$>
Expand Down Expand Up @@ -1155,6 +1171,16 @@ pTxFee =
<> Opt.help "The fee amount in Lovelace."
)

pWitnessFile :: Parser WitnessFile
pWitnessFile =
WitnessFile <$>
Opt.strOption
( Opt.long "witness-file"
<> Opt.metavar "FILE"
<> Opt.help ("Filepath of the witness.")
<> Opt.completer (Opt.bashCompleter "file")
)

pTxBodyFile :: FileDirection -> Parser TxBodyFile
pTxBodyFile fdir =
TxBodyFile <$>
Expand Down Expand Up @@ -1216,18 +1242,18 @@ pTxOutCount =
<> Opt.help "The number of transaction outputs."
)

pTxShelleyWinessCount :: Parser TxShelleyWinessCount
pTxShelleyWinessCount =
TxShelleyWinessCount <$>
pTxShelleyWitnessCount :: Parser TxShelleyWitnessCount
pTxShelleyWitnessCount =
TxShelleyWitnessCount <$>
Opt.option Opt.auto
( Opt.long "witness-count"
<> Opt.metavar "NATURAL"
<> Opt.help "The number of Shelley key witnesses."
)

pTxByronWinessCount :: Parser TxByronWinessCount
pTxByronWinessCount =
TxByronWinessCount <$>
pTxByronWitnessCount :: Parser TxByronWitnessCount
pTxByronWitnessCount =
TxByronWitnessCount <$>
Opt.option Opt.auto
( Opt.long "byron-witness-count"
<> Opt.metavar "NATURAL"
Expand Down
89 changes: 69 additions & 20 deletions cardano-cli/src/Cardano/CLI/Shelley/Run/Transaction.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ data ShelleyTxCmdError
| ShelleyTxSubmitErrorShelley !(ApplyTxErr (ShelleyBlock TPraosStandardCrypto))
| ShelleyTxSubmitErrorEraMismatch !EraMismatch
| ShelleyTxReadFileError !(Api.FileError Api.TextEnvelopeError)
| ShelleyTxWriteFileError !(Api.FileError ())
deriving Show

renderShelleyTxCmdError :: ShelleyTxCmdError -> Text
Expand Down Expand Up @@ -106,6 +107,7 @@ renderShelleyTxCmdError err =
"The node is running in the " <> ledgerEraName <>
" era, but the transaction is for the " <> otherEraName <> " era."
ShelleyTxReadFileError fileErr -> Text.pack (Api.displayError fileErr)
ShelleyTxWriteFileError fileErr -> Text.pack (Api.displayError fileErr)
ShelleyTxMissingNetworkId -> "Please enter network id with your byron transaction"

runTransactionCmd :: TransactionCmd -> ExceptT ShelleyTxCmdError IO ()
Expand All @@ -123,6 +125,10 @@ runTransactionCmd cmd =
nShelleyKeyWitnesses nByronKeyWitnesses
TxGetTxId txinfile ->
runTxGetTxId txinfile
TxWitness txBodyfile witSignKeyFile mbNw outFile ->
runTxWitness txBodyfile witSignKeyFile mbNw outFile
TxSignWitness txBodyFile witnessFile outFile ->
runTxSignWitness txBodyFile witnessFile outFile

_ -> liftIO $ putStrLn $ "runTransactionCmd: " ++ show cmd

Expand Down Expand Up @@ -189,7 +195,7 @@ runTxSign (TxBodyFile txbodyFile) skFiles mnw (TxFile txFile) = do
mapM readSigningKeyFile skFiles

-- We have to handle Byron and Shelley key witnesses slightly differently
let (sksByron, sksShelley) = partitionEithers (map categoriseSigningKey sks)
let (sksByron, sksShelley) = partitionEithers (map categoriseWitnessSigningKey sks)

-- Byron witnesses need the network id
witnessesByron <-
Expand All @@ -208,18 +214,6 @@ runTxSign (TxBodyFile txbodyFile) skFiles mnw (TxFile txFile) = do

firstExceptT ShelleyTxWriteSignedTxError . newExceptT $
Api.writeFileTextEnvelope txFile Nothing tx
where
categoriseSigningKey :: SomeWitnessSigningKey
-> Either (Api.SigningKey Api.ByronKey)
Api.ShelleyWitnessSigningKey
categoriseSigningKey swsk =
case swsk of
AByronSigningKey sk -> Left sk
APaymentSigningKey sk -> Right (Api.WitnessPaymentKey sk)
AStakeSigningKey sk -> Right (Api.WitnessStakeKey sk)
AStakePoolSigningKey sk -> Right (Api.WitnessStakePoolKey sk)
AGenesisDelegateSigningKey sk -> Right (Api.WitnessGenesisDelegateKey sk)
AGenesisUTxOSigningKey sk -> Right (Api.WitnessGenesisUTxOKey sk)

runTxSubmit :: Protocol -> NetworkId -> FilePath
-> ExceptT ShelleyTxCmdError IO ()
Expand Down Expand Up @@ -278,13 +272,13 @@ runTxCalculateMinFee
-> ProtocolParamsFile
-> TxInCount
-> TxOutCount
-> TxShelleyWinessCount
-> TxByronWinessCount
-> TxShelleyWitnessCount
-> TxByronWitnessCount
-> ExceptT ShelleyTxCmdError IO ()
runTxCalculateMinFee (TxBodyFile txbodyFile) nw pParamsFile
(TxInCount nInputs) (TxOutCount nOutputs)
(TxShelleyWinessCount nShelleyKeyWitnesses)
(TxByronWinessCount nByronKeyWitnesses) = do
(TxShelleyWitnessCount nShelleyKeyWitnesses)
(TxByronWitnessCount nByronKeyWitnesses) = do

txbody <- firstExceptT ShelleyTxReadUnsignedTxError . newExceptT $
Api.readFileTextEnvelope Api.AsShelleyTxBody txbodyFile
Expand Down Expand Up @@ -314,6 +308,7 @@ readProtocolParameters (ProtocolParamsFile fpath) = do
data SomeWitnessSigningKey
= AByronSigningKey (Api.SigningKey Api.ByronKey)
| APaymentSigningKey (Api.SigningKey Api.PaymentKey)
| APaymentExtendedSigningKey (Api.SigningKey Api.PaymentExtendedKey)
| AStakeSigningKey (Api.SigningKey Api.StakeKey)
| AStakePoolSigningKey (Api.SigningKey Api.StakePoolKey)
| AGenesisDelegateSigningKey (Api.SigningKey Api.GenesisDelegateKey)
Expand All @@ -331,6 +326,8 @@ readSigningKeyFile (SigningKeyFile skfile) =
AByronSigningKey
, Api.FromSomeType (Api.AsSigningKey Api.AsPaymentKey)
APaymentSigningKey
, Api.FromSomeType (Api.AsSigningKey Api.AsPaymentExtendedKey)
APaymentExtendedSigningKey
, Api.FromSomeType (Api.AsSigningKey Api.AsStakeKey)
AStakeSigningKey
, Api.FromSomeType (Api.AsSigningKey Api.AsStakePoolKey)
Expand All @@ -341,12 +338,64 @@ readSigningKeyFile (SigningKeyFile skfile) =
AGenesisUTxOSigningKey
]

categoriseWitnessSigningKey :: SomeWitnessSigningKey
-> Either (Api.SigningKey Api.ByronKey)
Api.ShelleyWitnessSigningKey
categoriseWitnessSigningKey swsk =
case swsk of
AByronSigningKey sk -> Left sk
APaymentSigningKey sk -> Right (Api.WitnessPaymentKey sk)
APaymentExtendedSigningKey sk -> Right (Api.WitnessPaymentExtendedKey sk)
AStakeSigningKey sk -> Right (Api.WitnessStakeKey sk)
AStakePoolSigningKey sk -> Right (Api.WitnessStakePoolKey sk)
AGenesisDelegateSigningKey sk -> Right (Api.WitnessGenesisDelegateKey sk)
AGenesisUTxOSigningKey sk -> Right (Api.WitnessGenesisUTxOKey sk)

runTxGetTxId :: TxBodyFile -> ExceptT ShelleyTxCmdError IO ()
runTxGetTxId (TxBodyFile txbodyFile) = do
txbody <- firstExceptT ShelleyTxReadUnsignedTxError . newExceptT $
Api.readFileTextEnvelope Api.AsShelleyTxBody txbodyFile
liftIO $ BS.putStrLn $ Api.serialiseToRawBytesHex (Api.getTxId txbody)
txbody <- firstExceptT ShelleyTxReadUnsignedTxError . newExceptT $
Api.readFileTextEnvelope Api.AsShelleyTxBody txbodyFile
liftIO $ BS.putStrLn $ Api.serialiseToRawBytesHex (Api.getTxId txbody)

runTxWitness
:: TxBodyFile
-> SigningKeyFile
-> Maybe NetworkId
-> OutputFile
-> ExceptT ShelleyTxCmdError IO ()
runTxWitness (TxBodyFile txbodyFile) witSignKeyFile mbNw (OutputFile oFile) = do
txbody <- firstExceptT ShelleyTxReadFileError . newExceptT $
Api.readFileTextEnvelope Api.AsShelleyTxBody txbodyFile
someWitSignKey <- firstExceptT ShelleyTxReadFileError $ readSigningKeyFile witSignKeyFile

witness <-
case (categoriseWitnessSigningKey someWitSignKey, mbNw) of
-- Byron witnesses require the network ID.
(Left _, Nothing) -> throwError ShelleyTxMissingNetworkId
(Left byronSk, Just nw) -> pure $ makeShelleyBootstrapWitness nw txbody byronSk
(Right shelleySk, _) -> pure $ makeShelleyKeyWitness txbody shelleySk

firstExceptT ShelleyTxWriteFileError
. newExceptT
$ Api.writeFileTextEnvelope oFile Nothing witness

runTxSignWitness :: TxBodyFile -> [WitnessFile] -> OutputFile -> ExceptT ShelleyTxCmdError IO ()
runTxSignWitness (TxBodyFile txBodyFile) witnessFiles (OutputFile oFp) = do
txBody <- firstExceptT ShelleyTxReadFileError
. newExceptT
$ Api.readFileTextEnvelope Api.AsShelleyTxBody txBodyFile
witnesses <- firstExceptT ShelleyTxReadFileError
$ mapM readWitnessFile witnessFiles
let tx = Api.makeSignedTransaction witnesses txBody
firstExceptT ShelleyTxWriteFileError
. newExceptT
$ Api.writeFileTextEnvelope oFp Nothing tx
where
readWitnessFile
:: WitnessFile
-> ExceptT (Api.FileError Api.TextEnvelopeError) IO (Witness Shelley)
readWitnessFile (WitnessFile fp) =
newExceptT (Api.readFileTextEnvelope AsShelleyWitness fp)

-- ----------------------------------------------------------------------------
-- Transaction metadata
Expand Down

0 comments on commit f72ff6a

Please sign in to comment.