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 hash checks for governance committee create-cold-key-resignation-certificate and governance vote create #937

Merged
merged 7 commits into from
Oct 16, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Cardano.Api
import qualified Cardano.Api.Ledger as L
import Cardano.Api.Shelley

import Cardano.CLI.Types.Common (PotentiallyCheckedAnchor, ResignationMetadataUrl)
import Cardano.CLI.Types.Key
import Cardano.CLI.Types.Key.VerificationKey

Expand Down Expand Up @@ -71,7 +72,13 @@ data GovernanceCommitteeCreateColdKeyResignationCertificateCmdArgs era
= GovernanceCommitteeCreateColdKeyResignationCertificateCmdArgs
{ eon :: !(ConwayEraOnwards era)
, vkeyColdKeySource :: !(VerificationKeySource CommitteeColdKey)
, anchor :: !(Maybe (L.Anchor (L.EraCrypto (ShelleyLedgerEra era))))
, anchor
:: !( Maybe
palas marked this conversation as resolved.
Show resolved Hide resolved
( PotentiallyCheckedAnchor
ResignationMetadataUrl
(L.Anchor (L.EraCrypto (ShelleyLedgerEra era)))
)
)
, outFile :: !(File () Out)
}
deriving Show
Expand Down
8 changes: 8 additions & 0 deletions cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3612,6 +3612,14 @@ pMustCheckMetadataHash = pMustCheckHash "drep-metadata-hash" "DRep metadata" "--
pMustCheckStakeMetadataHash :: Parser (MustCheckHash StakePoolMetadataReference)
pMustCheckStakeMetadataHash = pMustCheckHash "metadata-hash" "stake pool metadata" "--metadata-hash" "--metadata-url"

pMustCheckResignationMetadataHash :: Parser (MustCheckHash ResignationMetadataUrl)
pMustCheckResignationMetadataHash =
pMustCheckHash
"resignation-metadata-hash"
"Constitutional Committee cold key resignation certificate metadata"
"--resignation-metadata-hash"
"--resignation-metadata-url"

pPreviousGovernanceAction :: Parser (Maybe (TxId, Word16))
pPreviousGovernanceAction =
optional $
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import Cardano.CLI.Read
import Cardano.CLI.Types.Key

import Data.Foldable (asum)
import Options.Applicative (Parser)
import Options.Applicative (Parser, optional)
import qualified Options.Applicative as Opt

pGovernanceCommitteeCmds
Expand Down Expand Up @@ -141,7 +141,11 @@ pGovernanceCommitteeCreateColdKeyResignationCertificateCmd era = do
GovernanceCommitteeCreateColdKeyResignationCertificateCmd
<$> ( GovernanceCommitteeCreateColdKeyResignationCertificateCmdArgs w
<$> pColdCredential
<*> pAnchor
<*> optional
( pPotentiallyCheckedAnchorData
pMustCheckResignationMetadataHash
pAnchor
)
<*> pOutputFile
)

Expand Down Expand Up @@ -169,12 +173,11 @@ pHotCredential =
, VksScript <$> pScriptFor "hot-script-file" Nothing "Hot Native or Plutus script file"
]

pAnchor :: Parser (Maybe (L.Anchor L.StandardCrypto))
pAnchor :: Parser (L.Anchor L.StandardCrypto)
pAnchor =
Opt.optional $
L.Anchor
<$> fmap unAnchorUrl pAnchorUrl
<*> pSafeHash
L.Anchor
<$> fmap unAnchorUrl pAnchorUrl
<*> pSafeHash

pAnchorUrl :: Parser AnchorUrl
pAnchorUrl =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import Cardano.Api.Shelley
import Cardano.CLI.EraBased.Commands.Governance.Committee
import qualified Cardano.CLI.EraBased.Commands.Governance.Committee as Cmd
import Cardano.CLI.Read (readVerificationKeySource)
import Cardano.CLI.Run.Hash (carryHashChecks)
import qualified Cardano.CLI.Run.Key as Key
import Cardano.CLI.Types.Common (PotentiallyCheckedAnchor (..))
import Cardano.CLI.Types.Errors.GovernanceCommitteeError
import Cardano.CLI.Types.Key.VerificationKey

Expand Down Expand Up @@ -177,8 +179,12 @@ runGovernanceCommitteeColdKeyResignationCertificate
modifyError' $
readVerificationKeySource AsCommitteeColdKey unCommitteeColdKeyHash vkeyColdKeySource

mapM_
(withExceptT GovernanceCommitteeHashCheckError . carryHashChecks)
anchor

makeCommitteeColdkeyResignationCertificate
(CommitteeColdkeyResignationRequirements eon coldVKeyCred anchor)
(CommitteeColdkeyResignationRequirements eon coldVKeyCred (pcaAnchor <$> anchor))
& textEnvelopeToJSON (Just genKeyDelegCertDesc)
& writeLazyByteStringFile outFile
& firstExceptT GovernanceCommitteeCmdTextEnvWriteError . newExceptT
Expand Down
28 changes: 3 additions & 25 deletions cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ import qualified Cardano.Api.Ledger as L

import qualified Cardano.CLI.Commands.Hash as Cmd
import qualified Cardano.CLI.EraBased.Commands.Governance.DRep as Cmd
import Cardano.CLI.Run.Hash (allSchemas, getByteStringFromURL, httpsAndIpfsSchemas)
import Cardano.CLI.Run.Hash (allSchemas, carryHashChecks, getByteStringFromURL)
import qualified Cardano.CLI.Run.Key as Key
import Cardano.CLI.Types.Common
import Cardano.CLI.Types.Errors.CmdError
import Cardano.CLI.Types.Errors.GovernanceCmdError
import Cardano.CLI.Types.Errors.HashCmdError (FetchURLError, HashCheckError (..))
import Cardano.CLI.Types.Errors.HashCmdError (FetchURLError)
import Cardano.CLI.Types.Errors.RegistrationError
import Cardano.CLI.Types.Key

import Control.Monad (void, when)
import Control.Monad (void)
import Data.ByteString (ByteString)
import Data.Function
import qualified Data.Text.Encoding as Text
Expand Down Expand Up @@ -211,25 +211,3 @@ runGovernanceDRepMetadataHashCmd
fetchURLToGovernanceCmdError
:: ExceptT FetchURLError IO ByteString -> ExceptT GovernanceCmdError IO ByteString
fetchURLToGovernanceCmdError = withExceptT GovernanceCmdFetchURLError

-- | Check the hash of the anchor data against the hash in the anchor if
-- checkHash is set to CheckHash.
carryHashChecks
:: PotentiallyCheckedAnchor DRepMetadataUrl (L.Anchor L.StandardCrypto)
-- ^ The information about anchor data and whether to check the hash (see 'PotentiallyCheckedAnchor')
-> ExceptT HashCheckError IO ()
carryHashChecks potentiallyCheckedAnchor =
case pcaMustCheck potentiallyCheckedAnchor of
CheckHash -> do
anchorData <-
L.AnchorData
<$> withExceptT
FetchURLError
(getByteStringFromURL httpsAndIpfsSchemas $ L.urlToText $ L.anchorUrl anchor)
let hash = L.hashAnchorData anchorData
when (hash /= L.anchorDataHash anchor) $
left $
HashMismatchError (L.anchorDataHash anchor) hash
TrustHash -> pure ()
where
anchor = pcaAnchor potentiallyCheckedAnchor
32 changes: 28 additions & 4 deletions cardano-cli/src/Cardano/CLI/Run/Hash.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,21 @@ module Cardano.CLI.Run.Hash
, SupportedSchemas (..)
, allSchemas
, httpsAndIpfsSchemas
, carryHashChecks
)
where

import Cardano.Api
import qualified Cardano.Api.Ledger as L

import Cardano.CLI.Commands.Hash (HashGoal (..))
import qualified Cardano.CLI.Commands.Hash as Cmd
import Cardano.CLI.Read
import Cardano.CLI.Types.Common (MustCheckHash (..), PotentiallyCheckedAnchor (..))
import Cardano.CLI.Types.Errors.HashCmdError
import Cardano.Crypto.Hash (hashToTextAsHex)

import Control.Exception (throw)
import Control.Monad (when)
import Control.Monad.Catch (Exception, Handler (Handler))
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8
Expand Down Expand Up @@ -72,13 +74,13 @@ runHashAnchorDataCmd Cmd.HashAnchorDataCmdArgs{toHash, hashGoal} = do
fetchURLToHashCmdError $ getByteStringFromURL allSchemas $ L.urlToText urlText
let hash = L.hashAnchorData anchorData
case hashGoal of
CheckHash expectedHash
Cmd.CheckHash expectedHash
| hash /= expectedHash ->
left $ HashMismatchedHashError expectedHash hash
| otherwise -> do
liftIO $ putStrLn "Hashes match!"
HashToFile outFile -> writeHash (Just outFile) hash
HashToStdout -> writeHash Nothing hash
Cmd.HashToFile outFile -> writeHash (Just outFile) hash
Cmd.HashToStdout -> writeHash Nothing hash
where
writeHash :: Maybe (File () Out) -> L.SafeHash L.StandardCrypto i -> ExceptT HashCmdError IO ()
writeHash mOutFile hash = do
Expand Down Expand Up @@ -180,3 +182,25 @@ runHashScriptCmd Cmd.HashScriptCmdArgs{Cmd.toHash = File toHash, mOutFile} = do
. writeTextOutput mOutFile
. serialiseToRawBytesHexText
$ hashScript script

-- | Check the hash of the anchor data against the hash in the anchor if
-- checkHash is set to CheckHash.
carryHashChecks
:: PotentiallyCheckedAnchor anchorType (L.Anchor L.StandardCrypto)
-- ^ The information about anchor data and whether to check the hash (see 'PotentiallyCheckedAnchor')
-> ExceptT HashCheckError IO ()
carryHashChecks potentiallyCheckedAnchor =
case pcaMustCheck potentiallyCheckedAnchor of
CheckHash -> do
anchorData <-
L.AnchorData
<$> withExceptT
FetchURLError
(getByteStringFromURL httpsAndIpfsSchemas $ L.urlToText $ L.anchorUrl anchor)
let hash = L.hashAnchorData anchorData
when (hash /= L.anchorDataHash anchor) $
left $
HashMismatchError (L.anchorDataHash anchor) hash
TrustHash -> pure ()
where
anchor = pcaAnchor potentiallyCheckedAnchor
5 changes: 5 additions & 0 deletions cardano-cli/src/Cardano/CLI/Types/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ module Cardano.CLI.Types.Common
, WitnessSigningData (..)
, DRepMetadataFile
, DRepMetadataUrl
, ResignationMetadataUrl
, PotentiallyCheckedAnchor (..)
)
where
Expand Down Expand Up @@ -143,6 +144,10 @@ data ProposalText
-- sources for other types of anchor data
data DRepMetadataUrl

-- | Tag for differentiating between resignation metadatata sources and
-- sources for other types of anchor data
data ResignationMetadataUrl

newtype VoteUrl = VoteUrl
{ unVoteUrl :: L.Url
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ where

import Cardano.Api

import Cardano.CLI.Types.Errors.HashCmdError (HashCheckError)
import Cardano.CLI.Types.Errors.ScriptDecodeError

import Control.Exception (displayException)

data GovernanceCommitteeError
= GovernanceCommitteeCmdKeyDecodeError InputDecodeError
| GovernanceCommitteeCmdKeyReadError (FileError InputDecodeError)
| GovernanceCommitteeCmdScriptReadError (FileError ScriptDecodeError)
| GovernanceCommitteeCmdTextEnvReadFileError (FileError TextEnvelopeError)
| GovernanceCommitteeCmdTextEnvWriteError (FileError ())
| GovernanceCommitteeCmdWriteFileError (FileError ())
| GovernanceCommitteeHashCheckError !HashCheckError
deriving Show

instance Error GovernanceCommitteeError where
Expand All @@ -32,3 +36,5 @@ instance Error GovernanceCommitteeError where
"Cannot write text envelope file: " <> prettyError e
GovernanceCommitteeCmdScriptReadError e ->
"Cannot read script file: " <> prettyError e
GovernanceCommitteeHashCheckError hashCheckErr ->
"Error while checking metadata hash: " <> pretty (displayException hashCheckErr)
6 changes: 4 additions & 2 deletions cardano-cli/test/cardano-cli-golden/files/golden/help.cli
Original file line number Diff line number Diff line change
Expand Up @@ -6954,7 +6954,8 @@ Usage: cardano-cli conway governance committee create-cold-key-resignation-certi
| --cold-script-file FILEPATH
)
[--resignation-metadata-url TEXT
--resignation-metadata-hash HASH]
--resignation-metadata-hash HASH
[--check-resignation-metadata-hash]]
--out-file FILEPATH

Create cold key resignation certificate for a Constitutional Committee Member
Expand Down Expand Up @@ -8953,7 +8954,8 @@ Usage: cardano-cli latest governance committee create-cold-key-resignation-certi
| --cold-script-file FILEPATH
)
[--resignation-metadata-url TEXT
--resignation-metadata-hash HASH]
--resignation-metadata-hash HASH
[--check-resignation-metadata-hash]]
--out-file FILEPATH

Create cold key resignation certificate for a Constitutional Committee Member
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Usage: cardano-cli conway governance committee create-cold-key-resignation-certi
| --cold-script-file FILEPATH
)
[--resignation-metadata-url TEXT
--resignation-metadata-hash HASH]
--resignation-metadata-hash HASH
[--check-resignation-metadata-hash]]
--out-file FILEPATH

Create cold key resignation certificate for a Constitutional Committee Member
Expand All @@ -29,5 +30,12 @@ Available options:
--resignation-metadata-hash HASH
Constitutional Committee cold key resignation
certificate metadata hash
--check-resignation-metadata-hash
Verify that the expected Constitutional Committee
cold key resignation certificate metadata hash
provided in --resignation-metadata-hash matches the
hash of the file downloaded from the URL provided in
--resignation-metadata-url (this parameter will
download the file from the URL)
--out-file FILEPATH The output file.
-h,--help Show this help text
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Usage: cardano-cli latest governance committee create-cold-key-resignation-certi
| --cold-script-file FILEPATH
)
[--resignation-metadata-url TEXT
--resignation-metadata-hash HASH]
--resignation-metadata-hash HASH
[--check-resignation-metadata-hash]]
--out-file FILEPATH

Create cold key resignation certificate for a Constitutional Committee Member
Expand All @@ -29,5 +30,12 @@ Available options:
--resignation-metadata-hash HASH
Constitutional Committee cold key resignation
certificate metadata hash
--check-resignation-metadata-hash
Verify that the expected Constitutional Committee
cold key resignation certificate metadata hash
provided in --resignation-metadata-hash matches the
hash of the file downloaded from the URL provided in
--resignation-metadata-url (this parameter will
download the file from the URL)
--out-file FILEPATH The output file.
-h,--help Show this help text