From 74fe174e09fbda3df95b22f4a4379dd1dfcb85d1 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Mon, 14 Oct 2024 15:11:56 +0200 Subject: [PATCH 1/7] Add hash check to `governance committee create-cold-key-resignation-certificate` --- .../EraBased/Commands/Governance/Committee.hs | 9 +++++- .../Cardano/CLI/EraBased/Options/Common.hs | 8 +++++ .../EraBased/Options/Governance/Committee.hs | 17 ++++++---- .../CLI/EraBased/Run/Governance/Committee.hs | 8 ++++- .../CLI/EraBased/Run/Governance/DRep.hs | 28 ++-------------- cardano-cli/src/Cardano/CLI/Run/Hash.hs | 32 ++++++++++++++++--- cardano-cli/src/Cardano/CLI/Types/Common.hs | 5 +++ .../Types/Errors/GovernanceCommitteeError.hs | 6 ++++ .../cardano-cli-golden/files/golden/help.cli | 6 ++-- ...reate-cold-key-resignation-certificate.cli | 10 +++++- ...reate-cold-key-resignation-certificate.cli | 10 +++++- 11 files changed, 97 insertions(+), 42 deletions(-) diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Committee.hs b/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Committee.hs index baefec82aa..f50503501e 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Committee.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Committee.hs @@ -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 @@ -71,7 +72,13 @@ data GovernanceCommitteeCreateColdKeyResignationCertificateCmdArgs era = GovernanceCommitteeCreateColdKeyResignationCertificateCmdArgs { eon :: !(ConwayEraOnwards era) , vkeyColdKeySource :: !(VerificationKeySource CommitteeColdKey) - , anchor :: !(Maybe (L.Anchor (L.EraCrypto (ShelleyLedgerEra era)))) + , anchor + :: !( Maybe + ( PotentiallyCheckedAnchor + ResignationMetadataUrl + (L.Anchor (L.EraCrypto (ShelleyLedgerEra era))) + ) + ) , outFile :: !(File () Out) } deriving Show diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs index 8a06224ba2..5a0c73927b 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs @@ -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 $ diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Committee.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Committee.hs index 8b17c5a3fa..961c6fc2b0 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Committee.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Committee.hs @@ -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 @@ -141,7 +141,11 @@ pGovernanceCommitteeCreateColdKeyResignationCertificateCmd era = do GovernanceCommitteeCreateColdKeyResignationCertificateCmd <$> ( GovernanceCommitteeCreateColdKeyResignationCertificateCmdArgs w <$> pColdCredential - <*> pAnchor + <*> optional + ( pPotentiallyCheckedAnchorData + pMustCheckResignationMetadataHash + pAnchor + ) <*> pOutputFile ) @@ -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 = diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Committee.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Committee.hs index f3f2e018df..f5c37c6ab9 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Committee.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Committee.hs @@ -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 @@ -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 diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs index 3f2d9d997b..12f283d56f 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs @@ -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 @@ -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 diff --git a/cardano-cli/src/Cardano/CLI/Run/Hash.hs b/cardano-cli/src/Cardano/CLI/Run/Hash.hs index 1394d525e9..30596958f0 100644 --- a/cardano-cli/src/Cardano/CLI/Run/Hash.hs +++ b/cardano-cli/src/Cardano/CLI/Run/Hash.hs @@ -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 @@ -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 @@ -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 diff --git a/cardano-cli/src/Cardano/CLI/Types/Common.hs b/cardano-cli/src/Cardano/CLI/Types/Common.hs index e3c22e51fa..082fae1313 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Common.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Common.hs @@ -88,6 +88,7 @@ module Cardano.CLI.Types.Common , WitnessSigningData (..) , DRepMetadataFile , DRepMetadataUrl + , ResignationMetadataUrl , PotentiallyCheckedAnchor (..) ) where @@ -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 } diff --git a/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceCommitteeError.hs b/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceCommitteeError.hs index d461d2ae09..648c1d312a 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceCommitteeError.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceCommitteeError.hs @@ -7,8 +7,11 @@ 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) @@ -16,6 +19,7 @@ data GovernanceCommitteeError | GovernanceCommitteeCmdTextEnvReadFileError (FileError TextEnvelopeError) | GovernanceCommitteeCmdTextEnvWriteError (FileError ()) | GovernanceCommitteeCmdWriteFileError (FileError ()) + | GovernanceCommitteeHashCheckError !HashCheckError deriving Show instance Error GovernanceCommitteeError where @@ -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) diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli index 8ccb272752..e1518cc590 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli @@ -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 @@ -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 diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_committee_create-cold-key-resignation-certificate.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_committee_create-cold-key-resignation-certificate.cli index c92ad09b56..728794a92c 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_committee_create-cold-key-resignation-certificate.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_committee_create-cold-key-resignation-certificate.cli @@ -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 @@ -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 diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_committee_create-cold-key-resignation-certificate.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_committee_create-cold-key-resignation-certificate.cli index 702c22d520..da119ea59d 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_committee_create-cold-key-resignation-certificate.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_committee_create-cold-key-resignation-certificate.cli @@ -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 @@ -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 From 6c6832cb8f4cfe2a490bd427a319edbcc43c4405 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Mon, 14 Oct 2024 16:40:28 +0200 Subject: [PATCH 2/7] Add hash check to `governance vote create` --- .../CLI/EraBased/Commands/Governance/Vote.hs | 8 +++++- .../Cardano/CLI/EraBased/Options/Common.hs | 3 +++ .../CLI/EraBased/Options/Governance/Vote.hs | 6 ++++- .../CLI/EraBased/Run/Governance/Vote.hs | 26 ++++++++++++++----- cardano-cli/src/Cardano/CLI/Types/Common.hs | 11 ++++++++ .../Types/Errors/GovernanceVoteCmdError.hs | 6 +++++ .../cardano-cli-golden/files/golden/help.cli | 6 +++-- .../help/conway_governance_vote_create.cli | 8 +++++- .../help/latest_governance_vote_create.cli | 8 +++++- 9 files changed, 69 insertions(+), 13 deletions(-) diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Vote.hs b/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Vote.hs index a65e335989..05d379e1b5 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Vote.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Vote.hs @@ -32,7 +32,13 @@ data GovernanceVoteCreateCmdArgs era , voteChoice :: Vote , governanceAction :: (TxId, Word16) , votingStakeCredentialSource :: AnyVotingStakeVerificationKeyOrHashOrFile - , mAnchor :: Maybe (VoteUrl, L.SafeHash L.StandardCrypto L.AnchorData) + , mAnchor + :: !( Maybe + ( PotentiallyCheckedAnchor + VoteUrl + (VoteUrl, L.SafeHash L.StandardCrypto L.AnchorData) + ) + ) , outFile :: VoteFile Out } diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs index 5a0c73927b..8353e6581a 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs @@ -3612,6 +3612,9 @@ pMustCheckMetadataHash = pMustCheckHash "drep-metadata-hash" "DRep metadata" "-- pMustCheckStakeMetadataHash :: Parser (MustCheckHash StakePoolMetadataReference) pMustCheckStakeMetadataHash = pMustCheckHash "metadata-hash" "stake pool metadata" "--metadata-hash" "--metadata-url" +pMustCheckVoteUrl :: Parser (MustCheckHash VoteUrl) +pMustCheckVoteUrl = pMustCheckHash "anchor-data-hash" "vote anchor data" "--anchor-data-hash" "--anchor-url" + pMustCheckResignationMetadataHash :: Parser (MustCheckHash ResignationMetadataUrl) pMustCheckResignationMetadataHash = pMustCheckHash diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Vote.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Vote.hs index f896d36fd0..8b5f7f94b3 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Vote.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Vote.hs @@ -51,7 +51,11 @@ pGovernanceVoteCreateCmdArgs cOnwards = <$> pVoteChoice <*> pGovernanceActionId <*> pAnyVotingStakeVerificationKeyOrHashOrFile - <*> optional pVoteAnchor + <*> optional + ( pPotentiallyCheckedAnchorData + pMustCheckVoteUrl + pVoteAnchor + ) <*> pFileOutDirection "out-file" "Output filepath of the vote." pAnyVotingStakeVerificationKeyOrHashOrFile :: Parser AnyVotingStakeVerificationKeyOrHashOrFile diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Vote.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Vote.hs index ccba3d3d27..9414bd5775 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Vote.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Vote.hs @@ -17,6 +17,7 @@ import Cardano.Api.Shelley import qualified Cardano.CLI.EraBased.Commands.Governance.Vote as Cmd import Cardano.CLI.Read (readSingleVote) +import Cardano.CLI.Run.Hash (carryHashChecks) import Cardano.CLI.Types.Common import Cardano.CLI.Types.Errors.CmdError import Cardano.CLI.Types.Errors.GovernanceVoteCmdError @@ -26,6 +27,7 @@ import Cardano.CLI.Types.Key import Data.Aeson.Encode.Pretty import Data.Function import qualified Data.Yaml.Pretty as Yaml +import Lens.Micro (_Just, over) runGovernanceVoteCmds :: () @@ -53,14 +55,24 @@ runGovernanceVoteCreateCmd , outFile } = do let (govActionTxId, govActionIndex) = governanceAction - let sbe = conwayEraOnwardsToShelleyBasedEra eon -- TODO: Conway era - update vote creation related function to take ConwayEraOnwards - voteProcedure <- case mAnchor of + sbe = conwayEraOnwardsToShelleyBasedEra eon -- TODO: Conway era - update vote creation related function to take ConwayEraOnwards + mAnchor' = + over + (_Just . _pcaAnchor) + (\(VoteUrl url, voteHash) -> L.Anchor{L.anchorUrl = url, L.anchorDataHash = voteHash}) + mAnchor + + mapM_ + (withExceptT GovernanceVoteCmdResignationCertHashCheckError . carryHashChecks) + mAnchor' + + voteProcedure <- case mAnchor' of Nothing -> pure $ createVotingProcedure eon voteChoice Nothing - Just (VoteUrl url, voteHash) -> shelleyBasedEraConstraints sbe $ do - let voteAnchor = L.Anchor{L.anchorUrl = url, L.anchorDataHash = voteHash} - VotingProcedure votingProcedureWithoutAnchor = createVotingProcedure eon voteChoice Nothing - votingProcedureWithAnchor = VotingProcedure $ votingProcedureWithoutAnchor{L.vProcAnchor = L.SJust voteAnchor} - pure votingProcedureWithAnchor + Just voteAnchor -> + shelleyBasedEraConstraints sbe $ + let VotingProcedure votingProcedureWithoutAnchor = createVotingProcedure eon voteChoice Nothing + votingProcedureWithAnchor = VotingProcedure $ votingProcedureWithoutAnchor{L.vProcAnchor = L.SJust (pcaAnchor voteAnchor)} + in return votingProcedureWithAnchor shelleyBasedEraConstraints sbe $ do voter <- firstExceptT GovernanceVoteCmdReadVerificationKeyError $ case votingStakeCredentialSource of diff --git a/cardano-cli/src/Cardano/CLI/Types/Common.hs b/cardano-cli/src/Cardano/CLI/Types/Common.hs index 082fae1313..32f9a1eaa7 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Common.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Common.hs @@ -90,6 +90,7 @@ module Cardano.CLI.Types.Common , DRepMetadataUrl , ResignationMetadataUrl , PotentiallyCheckedAnchor (..) + , _pcaAnchor ) where @@ -104,6 +105,7 @@ import Data.String (IsString) import Data.Text (Text) import qualified Data.Text as Text import Data.Word (Word64) +import Lens.Micro.Type (Traversal) -- | Determines the direction in which the MIR certificate will transfer ADA. data TransferDirection @@ -665,3 +667,12 @@ data PotentiallyCheckedAnchor anchorType anchor -- ^ Whether to check the hash or not (CheckHash for checking or TrustHash for not checking) } deriving (Eq, Show) + +_pcaAnchor + :: Traversal + (PotentiallyCheckedAnchor anchorType anchor) + (PotentiallyCheckedAnchor anchorType anchor') + anchor + anchor' +_pcaAnchor f pca@(PotentiallyCheckedAnchor{pcaAnchor = pcaAnchor'}) = + (\newAnchor -> pca{pcaAnchor = newAnchor}) <$> f pcaAnchor' diff --git a/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceVoteCmdError.hs b/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceVoteCmdError.hs index 820db0f949..38c0bb114b 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceVoteCmdError.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceVoteCmdError.hs @@ -8,7 +8,9 @@ import Cardano.Api.Shelley import Cardano.Binary (DecoderError) import Cardano.CLI.Read (VoteError) +import Cardano.CLI.Types.Errors.HashCmdError (HashCheckError) +import Control.Exception (displayException) import qualified Data.Text.Lazy.Builder as TL import qualified Formatting.Buildable as B @@ -18,6 +20,7 @@ data GovernanceVoteCmdError | GovernanceVoteCmdCredentialDecodeError !DecoderError | GovernanceVoteCmdWriteError !(FileError ()) | GovernanceVoteCmdReadVoteTextError !VoteError + | GovernanceVoteCmdResignationCertHashCheckError !HashCheckError deriving Show instance Error GovernanceVoteCmdError where @@ -32,5 +35,8 @@ instance Error GovernanceVoteCmdError where "Cannot write vote: " <> prettyError e GovernanceVoteCmdReadVoteTextError e -> "Cannot read vote text: " <> prettyError e + GovernanceVoteCmdResignationCertHashCheckError hashCheckErr -> + "Error while checking resignation certificate metadata hash: " + <> pretty (displayException hashCheckErr) where renderDecoderError = pretty . TL.toLazyText . B.build diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli index e1518cc590..4965c21ef7 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli @@ -7054,7 +7054,8 @@ Usage: cardano-cli conway governance vote create (--yes | --no | --abstain) | --cc-hot-script-hash HASH ) [--anchor-url TEXT - --anchor-data-hash HASH] + --anchor-data-hash HASH + [--check-anchor-data-hash]] --out-file FILEPATH Vote creation. @@ -9054,7 +9055,8 @@ Usage: cardano-cli latest governance vote create (--yes | --no | --abstain) | --cc-hot-script-hash HASH ) [--anchor-url TEXT - --anchor-data-hash HASH] + --anchor-data-hash HASH + [--check-anchor-data-hash]] --out-file FILEPATH Vote creation. diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_vote_create.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_vote_create.cli index f1b7d836d3..06805ac988 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_vote_create.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_vote_create.cli @@ -14,7 +14,8 @@ Usage: cardano-cli conway governance vote create (--yes | --no | --abstain) | --cc-hot-script-hash HASH ) [--anchor-url TEXT - --anchor-data-hash HASH] + --anchor-data-hash HASH + [--check-anchor-data-hash]] --out-file FILEPATH Vote creation. @@ -50,5 +51,10 @@ Available options: --anchor-url TEXT Vote anchor URL --anchor-data-hash HASH Hash of the vote anchor data (obtain it with "cardano-cli hash anchor-data ..."). + --check-anchor-data-hash Verify that the expected vote anchor data hash + provided in --anchor-data-hash matches the hash of + the file downloaded from the URL provided in + --anchor-url (this parameter will download the file + from the URL) --out-file FILEPATH Output filepath of the vote. -h,--help Show this help text diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_vote_create.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_vote_create.cli index fb93ae26f9..9e85abcfbc 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_vote_create.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_vote_create.cli @@ -14,7 +14,8 @@ Usage: cardano-cli latest governance vote create (--yes | --no | --abstain) | --cc-hot-script-hash HASH ) [--anchor-url TEXT - --anchor-data-hash HASH] + --anchor-data-hash HASH + [--check-anchor-data-hash]] --out-file FILEPATH Vote creation. @@ -50,5 +51,10 @@ Available options: --anchor-url TEXT Vote anchor URL --anchor-data-hash HASH Hash of the vote anchor data (obtain it with "cardano-cli hash anchor-data ..."). + --check-anchor-data-hash Verify that the expected vote anchor data hash + provided in --anchor-data-hash matches the hash of + the file downloaded from the URL provided in + --anchor-url (this parameter will download the file + from the URL) --out-file FILEPATH Output filepath of the vote. -h,--help Show this help text From 9484c8736956c06ecbf701f4a87a7e2bc7763a00 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Tue, 15 Oct 2024 12:18:30 +0200 Subject: [PATCH 3/7] Add test to hash check in `governance committee create-cold-key-resignation-certificate` --- cardano-cli/cardano-cli.cabal | 1 + .../Test/Cli/Governance/Committee.hs | 83 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 cardano-cli/test/cardano-cli-test/Test/Cli/Governance/Committee.hs diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index ac8f9bb1d4..47c3ed4c40 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -337,6 +337,7 @@ test-suite cardano-cli-test Test.Cli.CreateTestnetData Test.Cli.DRepMetadata Test.Cli.FilePermissions + Test.Cli.Governance.Committee Test.Cli.Governance.DRep Test.Cli.Governance.Hash Test.Cli.Hash diff --git a/cardano-cli/test/cardano-cli-test/Test/Cli/Governance/Committee.hs b/cardano-cli/test/cardano-cli-test/Test/Cli/Governance/Committee.hs new file mode 100644 index 0000000000..ad32847d6f --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/Test/Cli/Governance/Committee.hs @@ -0,0 +1,83 @@ +{-# LANGUAGE FlexibleContexts #-} + +module Test.Cli.Governance.Committee where + +import Cardano.Api (MonadIO) + +import Control.Monad (void) +import Control.Monad.Catch (MonadCatch) +import Control.Monad.Trans.Control (MonadBaseControl) + +import Test.Cardano.CLI.Hash (exampleAnchorDataHash, exampleAnchorDataIpfsHash, + exampleAnchorDataPathTest, serveFilesWhile, tamperBase16Hash) +import Test.Cardano.CLI.Util (execCardanoCLI, execCardanoCLIWithEnvVars, expectFailure, + noteTempFile, propertyOnce) + +import Hedgehog (MonadTest, Property) +import qualified Hedgehog as H +import qualified Hedgehog.Extras as H + +-- | Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/governance committee checks wrong hash fails/"'@ +hprop_governance_committee_checks_wrong_hash_fails :: Property +hprop_governance_committee_checks_wrong_hash_fails = + propertyOnce . expectFailure . H.moduleWorkspace "tmp" $ \tempDir -> do + -- We modify the hash slightly so that the hash check fails + alteredHash <- H.evalMaybe $ tamperBase16Hash exampleAnchorDataHash + -- We run the test with the altered + baseGovernanceGovernanceCommitteeChecksHash + alteredHash + tempDir + +-- | Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/governance committee checks right hash works/"'@ +hprop_governance_committee_checks_right_hash_works :: Property +hprop_governance_committee_checks_right_hash_works = + propertyOnce . H.moduleWorkspace "tmp" $ \tempDir -> + baseGovernanceGovernanceCommitteeChecksHash exampleAnchorDataHash tempDir + +baseGovernanceGovernanceCommitteeChecksHash + :: (MonadBaseControl IO m, MonadTest m, MonadIO m, MonadCatch m) => String -> FilePath -> m () +baseGovernanceGovernanceCommitteeChecksHash hash tempDir = do + ccColdVKey <- noteTempFile tempDir "cold.vkey" + ccColdSKey <- noteTempFile tempDir "cold.skey" + + certFile <- noteTempFile tempDir "hot-auth.cert" + + void $ + execCardanoCLI + [ "conway" + , "governance" + , "committee" + , "key-gen-cold" + , "--verification-key-file" + , ccColdVKey + , "--signing-key-file" + , ccColdSKey + ] + + let relativeUrl = ["ipfs", exampleAnchorDataIpfsHash] + + -- Create temporary HTTP server with files required by the call to `cardano-cli` + -- In this case, the server emulates an IPFS gateway + serveFilesWhile + [(relativeUrl, exampleAnchorDataPathTest)] + ( \port -> do + void $ + execCardanoCLIWithEnvVars + [("IPFS_GATEWAY_URI", "http://localhost:" ++ show port ++ "/")] + [ "conway" + , "governance" + , "committee" + , "create-cold-key-resignation-certificate" + , "--cold-verification-key-file" + , ccColdVKey + , "--resignation-metadata-url" + , "ipfs://" ++ exampleAnchorDataIpfsHash + , "--resignation-metadata-hash" + , hash + , "--check-resignation-metadata-hash" + , "--out-file" + , certFile + ] + ) From 47239b734be0a7ab0eeb3cc2f9909ab79cb3885b Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Tue, 15 Oct 2024 12:49:39 +0200 Subject: [PATCH 4/7] Add test to hash check in `governance vote create` --- cardano-cli/cardano-cli.cabal | 1 + .../Test/Cli/Governance/Vote.hs | 74 +++++++++++++++++++ .../cardano-cli-test/files/input/drep.vkey | 5 ++ 3 files changed, 80 insertions(+) create mode 100644 cardano-cli/test/cardano-cli-test/Test/Cli/Governance/Vote.hs create mode 100644 cardano-cli/test/cardano-cli-test/files/input/drep.vkey diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 47c3ed4c40..141e0fc293 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -340,6 +340,7 @@ test-suite cardano-cli-test Test.Cli.Governance.Committee Test.Cli.Governance.DRep Test.Cli.Governance.Hash + Test.Cli.Governance.Vote Test.Cli.Hash Test.Cli.ITN Test.Cli.Json diff --git a/cardano-cli/test/cardano-cli-test/Test/Cli/Governance/Vote.hs b/cardano-cli/test/cardano-cli-test/Test/Cli/Governance/Vote.hs new file mode 100644 index 0000000000..4ec5934308 --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/Test/Cli/Governance/Vote.hs @@ -0,0 +1,74 @@ +{-# LANGUAGE FlexibleContexts #-} + +module Test.Cli.Governance.Vote where + +import Cardano.Api (MonadIO) + +import Control.Monad (void) +import Control.Monad.Catch (MonadCatch) +import Control.Monad.Trans.Control (MonadBaseControl) + +import Test.Cardano.CLI.Hash (exampleAnchorDataHash, exampleAnchorDataIpfsHash, + exampleAnchorDataPathTest, serveFilesWhile, tamperBase16Hash) +import Test.Cardano.CLI.Util (execCardanoCLIWithEnvVars, expectFailure, noteInputFile, + propertyOnce) + +import Hedgehog (MonadTest, Property) +import qualified Hedgehog as H +import qualified Hedgehog.Extras as H + +-- | Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/governance vote create wrong hash fails/"'@ +hprop_governance_vote_create_wrong_hash_fails :: Property +hprop_governance_vote_create_wrong_hash_fails = + propertyOnce . expectFailure . H.moduleWorkspace "tmp" $ \tempDir -> do + -- We modify the hash slightly so that the hash check fails + alteredHash <- H.evalMaybe $ tamperBase16Hash exampleAnchorDataHash + -- We run the test with the altered + baseGovernanceVoteCreateHashCheck + alteredHash + tempDir + +-- | Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/governance vote create right hash works/"'@ +hprop_governance_vote_create_right_hash_works :: Property +hprop_governance_vote_create_right_hash_works = + propertyOnce . H.moduleWorkspace "tmp" $ \tempDir -> + baseGovernanceVoteCreateHashCheck exampleAnchorDataHash tempDir + +baseGovernanceVoteCreateHashCheck + :: (MonadBaseControl IO m, MonadTest m, MonadIO m, MonadCatch m) => String -> FilePath -> m () +baseGovernanceVoteCreateHashCheck hash tempDir = do + vkeyFile <- noteInputFile "test/cardano-cli-test/files/input/drep.vkey" + voteFile <- H.noteTempFile tempDir "vote" + + let relativeUrl = ["ipfs", exampleAnchorDataIpfsHash] + + -- Create temporary HTTP server with files required by the call to `cardano-cli` + -- In this case, the server emulates an IPFS gateway + serveFilesWhile + [(relativeUrl, exampleAnchorDataPathTest)] + ( \port -> do + void $ + execCardanoCLIWithEnvVars + [("IPFS_GATEWAY_URI", "http://localhost:" ++ show port ++ "/")] + [ "conway" + , "governance" + , "vote" + , "create" + , "--yes" + , "--governance-action-tx-id" + , "b1015258a99351c143a7a40b7b58f033ace10e3cc09c67780ed5b2b0992aa60a" + , "--governance-action-index" + , "5" + , "--drep-verification-key-file" + , vkeyFile + , "--out-file" + , voteFile + , "--anchor-url" + , "ipfs://" ++ exampleAnchorDataIpfsHash + , "--anchor-data-hash" + , hash + , "--check-anchor-data-hash" + ] + ) diff --git a/cardano-cli/test/cardano-cli-test/files/input/drep.vkey b/cardano-cli/test/cardano-cli-test/files/input/drep.vkey new file mode 100644 index 0000000000..5f9b850fe7 --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/files/input/drep.vkey @@ -0,0 +1,5 @@ +{ + "type": "DRepVerificationKey_ed25519", + "description": "Delegated Representative Verification Key", + "cborHex": "58209eb6ff2ee38b24c4892a6b291ed245afa0d2fac76222e76ee3e205e3c9681540" +} From 1cca3a649f75fbb9908645cdc28f67bff56257a0 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Tue, 15 Oct 2024 13:48:39 +0200 Subject: [PATCH 5/7] Add golden test for failed hash check in `governance committee create-cold-key-resignation-certificate` --- .../Test/Golden/Governance/Committee.hs | 68 ++++++++++++++++++- ...ance_committee_checks_wrong_hash_fails.out | 3 + 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 cardano-cli/test/cardano-cli-golden/files/golden/governance/committee/governance_committee_checks_wrong_hash_fails.out diff --git a/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Committee.hs b/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Committee.hs index 5131cfddea..fc463dbe0b 100644 --- a/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Committee.hs +++ b/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Committee.hs @@ -5,16 +5,22 @@ module Test.Golden.Governance.Committee where import Control.Monad (forM_, void) +import Data.Monoid (Last (..)) +import qualified System.Environment as IO +import System.Exit (ExitCode (..)) import System.FilePath (()) import Test.Cardano.CLI.Aeson (assertHasMappings) +import Test.Cardano.CLI.Hash (exampleAnchorDataHash, exampleAnchorDataIpfsHash, + exampleAnchorDataPathGolden, serveFilesWhile, tamperBase16Hash) import qualified Test.Cardano.CLI.Util as H hiding (noteTempFile) import Test.Cardano.CLI.Util import Hedgehog (Property) import qualified Hedgehog as H -import qualified Hedgehog.Extras.Test.Base as H +import qualified Hedgehog.Extras as H import qualified Hedgehog.Extras.Test.Golden as H +import Hedgehog.Internal.Property ((===)) goldenDir, inputDir :: FilePath goldenDir = "test/cardano-cli-golden/files/golden" @@ -322,3 +328,63 @@ hprop_golden_governance_extended_committee_key_hash = ] result H.=== expected + +-- Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/golden governance committee checks wrong hash fails/"'@ +hprop_golden_governance_committee_checks_wrong_hash_fails :: Property +hprop_golden_governance_committee_checks_wrong_hash_fails = + propertyOnce . H.moduleWorkspace "tmp" $ \tempDir -> do + -- We modify the hash slightly so that the hash check fails + alteredHash <- H.evalMaybe $ tamperBase16Hash exampleAnchorDataHash + let relativeUrl = ["ipfs", exampleAnchorDataIpfsHash] + + ccColdVKey <- noteTempFile tempDir "cold.vkey" + ccColdSKey <- noteTempFile tempDir "cold.skey" + + certFile <- noteTempFile tempDir "hot-auth.cert" + + void $ + execCardanoCLI + [ "conway" + , "governance" + , "committee" + , "key-gen-cold" + , "--verification-key-file" + , ccColdVKey + , "--signing-key-file" + , ccColdSKey + ] + + -- Create temporary HTTP server with files required by the call to `cardano-cli` + env <- H.evalIO IO.getEnvironment + (exitCode, _, result) <- + serveFilesWhile + [ (relativeUrl, exampleAnchorDataPathGolden) + ] + ( \port -> do + execDetailConfigCardanoCLI + ( H.defaultExecConfig + { H.execConfigEnv = Last $ Just (("IPFS_GATEWAY_URI", "http://localhost:" ++ show port ++ "/") : env) + } + ) + [ "conway" + , "governance" + , "committee" + , "create-cold-key-resignation-certificate" + , "--cold-verification-key-file" + , ccColdVKey + , "--resignation-metadata-url" + , "ipfs://" ++ exampleAnchorDataIpfsHash + , "--resignation-metadata-hash" + , alteredHash + , "--check-resignation-metadata-hash" + , "--out-file" + , certFile + ] + ) + + exitCode === ExitFailure 1 + + H.diffVsGoldenFile + result + "test/cardano-cli-golden/files/golden/governance/committee/governance_committee_checks_wrong_hash_fails.out" diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/governance/committee/governance_committee_checks_wrong_hash_fails.out b/cardano-cli/test/cardano-cli-golden/files/golden/governance/committee/governance_committee_checks_wrong_hash_fails.out new file mode 100644 index 0000000000..901e798c65 --- /dev/null +++ b/cardano-cli/test/cardano-cli-golden/files/golden/governance/committee/governance_committee_checks_wrong_hash_fails.out @@ -0,0 +1,3 @@ +Command failed: governance committee create-cold-key-resignation-certificate Error: Error while checking metadata hash: Hashes do not match! +Expected: "ee38a4f5b8b9d8372386cc923bad19d1a0662298cf355bbe947e5eedf127fa9c" + Actual: "de38a4f5b8b9d8372386cc923bad19d1a0662298cf355bbe947e5eedf127fa9c" From 2b53bcf50306cce61dfaa7d95d619fb7f85fd4dd Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Tue, 15 Oct 2024 14:08:59 +0200 Subject: [PATCH 6/7] Add golden test for failed hash check in `governance vote create` --- .../Test/Golden/Governance/Vote.hs | 69 +++++++++++++++++-- .../governance_vote_create_hash_fails.out | 3 + 2 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 cardano-cli/test/cardano-cli-golden/files/golden/governance/vote/governance_vote_create_hash_fails.out diff --git a/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Vote.hs b/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Vote.hs index e6125a5216..e4120e9cfc 100644 --- a/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Vote.hs +++ b/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Vote.hs @@ -3,12 +3,18 @@ module Test.Golden.Governance.Vote where import Control.Monad (void) - -import Test.Cardano.CLI.Util (FileSem, bracketSem, execCardanoCLI, newFileSem, - noteInputFile, propertyOnce) - -import Hedgehog -import qualified Hedgehog.Extras.Test.Base as H +import Data.Monoid (Last (..)) +import GHC.IO.Exception (ExitCode (..)) +import qualified System.Environment as IO + +import Test.Cardano.CLI.Hash (exampleAnchorDataHash, exampleAnchorDataIpfsHash, + exampleAnchorDataPathGolden, serveFilesWhile, tamperBase16Hash) +import Test.Cardano.CLI.Util (FileSem, bracketSem, execCardanoCLI, + execDetailConfigCardanoCLI, newFileSem, noteInputFile, propertyOnce) + +import Hedgehog (Property, (===)) +import qualified Hedgehog as H +import qualified Hedgehog.Extras as H import qualified Hedgehog.Extras.Test.Golden as H hprop_golden_governance_governance_vote_create :: Property @@ -179,3 +185,54 @@ hprop_golden_governance_governance_vote_create_abstain_cc_hot_key = ] H.diffFileVsGoldenFile voteFile voteGold + +-- Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/golden governance vote create wrong hash fails/"'@ +hprop_golden_governance_vote_create_hash_fails :: Property +hprop_golden_governance_vote_create_hash_fails = + propertyOnce . H.moduleWorkspace "tmp" $ \tempDir -> do + -- We modify the hash slightly so that the hash check fails + alteredHash <- H.evalMaybe $ tamperBase16Hash exampleAnchorDataHash + let relativeUrl = ["ipfs", exampleAnchorDataIpfsHash] + + vkeyFile <- noteInputFile "test/cardano-cli-golden/files/input/drep.vkey" + voteFile <- H.noteTempFile tempDir "vote" + voteGold <- + H.note "test/cardano-cli-golden/files/golden/governance/vote/governance_vote_create_hash_fails.out" + + -- Create temporary HTTP server with files required by the call to `cardano-cli` + env <- H.evalIO IO.getEnvironment + (exitCode, _, result) <- + serveFilesWhile + [ (relativeUrl, exampleAnchorDataPathGolden) + ] + ( \port -> do + execDetailConfigCardanoCLI + ( H.defaultExecConfig + { H.execConfigEnv = Last $ Just (("IPFS_GATEWAY_URI", "http://localhost:" ++ show port ++ "/") : env) + } + ) + [ "conway" + , "governance" + , "vote" + , "create" + , "--yes" + , "--governance-action-tx-id" + , "b1015258a99351c143a7a40b7b58f033ace10e3cc09c67780ed5b2b0992aa60a" + , "--governance-action-index" + , "5" + , "--drep-verification-key-file" + , vkeyFile + , "--out-file" + , voteFile + , "--anchor-url" + , "ipfs://" ++ exampleAnchorDataIpfsHash + , "--anchor-data-hash" + , alteredHash + , "--check-anchor-data-hash" + ] + ) + + exitCode === ExitFailure 1 + + H.diffVsGoldenFile result voteGold diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/governance/vote/governance_vote_create_hash_fails.out b/cardano-cli/test/cardano-cli-golden/files/golden/governance/vote/governance_vote_create_hash_fails.out new file mode 100644 index 0000000000..c8ce1e8809 --- /dev/null +++ b/cardano-cli/test/cardano-cli-golden/files/golden/governance/vote/governance_vote_create_hash_fails.out @@ -0,0 +1,3 @@ +Command failed: governance vote create Error: Error while checking resignation certificate metadata hash: Hashes do not match! +Expected: "ee38a4f5b8b9d8372386cc923bad19d1a0662298cf355bbe947e5eedf127fa9c" + Actual: "de38a4f5b8b9d8372386cc923bad19d1a0662298cf355bbe947e5eedf127fa9c" From 525b7d325367a896e89913dea634e5d2e8e38100 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Tue, 15 Oct 2024 15:26:00 +0200 Subject: [PATCH 7/7] Remove `_pcaAnchor` lens --- .../src/Cardano/CLI/EraBased/Run/Governance/Vote.hs | 8 ++++---- cardano-cli/src/Cardano/CLI/Types/Common.hs | 11 ----------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Vote.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Vote.hs index 9414bd5775..b48c073660 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Vote.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Vote.hs @@ -27,7 +27,6 @@ import Cardano.CLI.Types.Key import Data.Aeson.Encode.Pretty import Data.Function import qualified Data.Yaml.Pretty as Yaml -import Lens.Micro (_Just, over) runGovernanceVoteCmds :: () @@ -57,9 +56,10 @@ runGovernanceVoteCreateCmd let (govActionTxId, govActionIndex) = governanceAction sbe = conwayEraOnwardsToShelleyBasedEra eon -- TODO: Conway era - update vote creation related function to take ConwayEraOnwards mAnchor' = - over - (_Just . _pcaAnchor) - (\(VoteUrl url, voteHash) -> L.Anchor{L.anchorUrl = url, L.anchorDataHash = voteHash}) + fmap + ( \pca@PotentiallyCheckedAnchor{pcaAnchor = (VoteUrl url, voteHash)} -> + pca{pcaAnchor = L.Anchor{L.anchorUrl = url, L.anchorDataHash = voteHash}} + ) mAnchor mapM_ diff --git a/cardano-cli/src/Cardano/CLI/Types/Common.hs b/cardano-cli/src/Cardano/CLI/Types/Common.hs index 32f9a1eaa7..082fae1313 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Common.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Common.hs @@ -90,7 +90,6 @@ module Cardano.CLI.Types.Common , DRepMetadataUrl , ResignationMetadataUrl , PotentiallyCheckedAnchor (..) - , _pcaAnchor ) where @@ -105,7 +104,6 @@ import Data.String (IsString) import Data.Text (Text) import qualified Data.Text as Text import Data.Word (Word64) -import Lens.Micro.Type (Traversal) -- | Determines the direction in which the MIR certificate will transfer ADA. data TransferDirection @@ -667,12 +665,3 @@ data PotentiallyCheckedAnchor anchorType anchor -- ^ Whether to check the hash or not (CheckHash for checking or TrustHash for not checking) } deriving (Eq, Show) - -_pcaAnchor - :: Traversal - (PotentiallyCheckedAnchor anchorType anchor) - (PotentiallyCheckedAnchor anchorType anchor') - anchor - anchor' -_pcaAnchor f pca@(PotentiallyCheckedAnchor{pcaAnchor = pcaAnchor'}) = - (\newAnchor -> pca{pcaAnchor = newAnchor}) <$> f pcaAnchor'