diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 532d5fbf12..e31d276f2c 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -351,6 +351,7 @@ test-suite cardano-cli-test Test.Cli.Pioneers.Exercise5 Test.Cli.Pioneers.Exercise6 Test.Cli.Pipes + Test.Cli.Shelley.Certificates.StakePool Test.Cli.Shelley.Run.Hash Test.Cli.Shelley.Run.Query Test.Cli.Shelley.Transaction.Build diff --git a/cardano-cli/src/Cardano/CLI/Commands/Hash.hs b/cardano-cli/src/Cardano/CLI/Commands/Hash.hs index 0672f8ee50..a457b7e113 100644 --- a/cardano-cli/src/Cardano/CLI/Commands/Hash.hs +++ b/cardano-cli/src/Cardano/CLI/Commands/Hash.hs @@ -23,11 +23,11 @@ data HashCmds = HashAnchorDataCmd !HashAnchorDataCmdArgs | HashScriptCmd !HashScriptCmdArgs -data HashGoal +data HashGoal hash = -- | The hash is written to stdout HashToStdout | -- | The hash to check against - CheckHash !(L.SafeHash L.StandardCrypto L.AnchorData) + CheckHash !hash | -- | The output file to which the hash is written HashToFile !(File () Out) deriving Show @@ -35,7 +35,7 @@ data HashGoal data HashAnchorDataCmdArgs = HashAnchorDataCmdArgs { toHash :: !AnchorDataHashSource - , hashGoal :: !HashGoal + , hashGoal :: !(HashGoal (L.SafeHash L.StandardCrypto L.AnchorData)) } deriving Show diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/DRep.hs b/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/DRep.hs index 8ef5e2e088..a877a3ba38 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/DRep.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/DRep.hs @@ -12,13 +12,13 @@ module Cardano.CLI.EraBased.Commands.Governance.DRep , GovernanceDRepUpdateCertificateCmdArgs (..) , GovernanceDRepMetadataHashCmdArgs (..) , DRepMetadataSource (..) - , DRepHashGoal (..) ) where import Cardano.Api import qualified Cardano.Api.Ledger as L +import Cardano.CLI.Commands.Hash (HashGoal) import Cardano.CLI.Types.Common import Cardano.CLI.Types.Key @@ -56,6 +56,7 @@ data GovernanceDRepRegistrationCertificateCmdArgs era :: !( Maybe ( PotentiallyCheckedAnchor DRepMetadataUrl + (L.Anchor L.StandardCrypto) ) ) , outFile :: !(File () Out) @@ -77,6 +78,7 @@ data GovernanceDRepUpdateCertificateCmdArgs era :: Maybe ( PotentiallyCheckedAnchor DRepMetadataUrl + (L.Anchor L.StandardCrypto) ) , outFile :: !(File () Out) } @@ -85,7 +87,7 @@ data GovernanceDRepMetadataHashCmdArgs era = GovernanceDRepMetadataHashCmdArgs { eon :: !(ConwayEraOnwards era) , drepMetadataSource :: !DRepMetadataSource - , hashGoal :: !DRepHashGoal + , hashGoal :: !(HashGoal (Hash DRepMetadata)) } data DRepMetadataSource @@ -93,15 +95,6 @@ data DRepMetadataSource | DrepMetadataURL !L.Url deriving Show -data DRepHashGoal - = -- | The hash is written to stdout - DRepHashToStdout - | -- | The hash to check against - CheckDRepHash !(Hash DRepMetadata) - | -- | The output file to which the hash is written - DRepHashToFile !(File () Out) - deriving Show - renderGovernanceDRepCmds :: () => GovernanceDRepCmds era diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs index 39fd541f8a..17987288c2 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs @@ -9,12 +9,15 @@ module Cardano.CLI.EraBased.Commands.StakePool , StakePoolIdCmdArgs (..) , StakePoolMetadataHashCmdArgs (..) , StakePoolRegistrationCertificateCmdArgs (..) + , StakePoolMetadataSource (..) ) where import Cardano.Api.Ledger (Coin) +import qualified Cardano.Api.Ledger as L import Cardano.Api.Shelley hiding (QueryInShelleyBasedEra (..)) +import Cardano.CLI.Commands.Hash (HashGoal) import Cardano.CLI.Types.Common import Cardano.CLI.Types.Key @@ -48,11 +51,16 @@ data StakePoolIdCmdArgs era data StakePoolMetadataHashCmdArgs era = StakePoolMetadataHashCmdArgs - { poolMetadataFile :: !(StakePoolMetadataFile In) - , mOutFile :: !(Maybe (File () Out)) + { poolMetadataSource :: !StakePoolMetadataSource + , hashGoal :: !(HashGoal (Hash StakePoolMetadata)) } deriving Show +data StakePoolMetadataSource + = StakePoolMetadataFileIn !(StakePoolMetadataFile In) + | StakePoolMetadataURL !L.Url + deriving Show + data StakePoolRegistrationCertificateCmdArgs era = StakePoolRegistrationCertificateCmdArgs { sbe :: !(ShelleyBasedEra era) @@ -73,7 +81,8 @@ data StakePoolRegistrationCertificateCmdArgs era -- ^ Pool owner verification staking key(s). , relays :: ![StakePoolRelay] -- ^ Stake pool relays. - , mMetadata :: !(Maybe StakePoolMetadataReference) + , mMetadata + :: !(Maybe (PotentiallyCheckedAnchor StakePoolMetadataReference StakePoolMetadataReference)) -- ^ Stake pool metadata. , network :: !NetworkId , outFile :: !(File () Out) diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs index 2446a11b1d..8a06224ba2 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs @@ -2683,12 +2683,11 @@ pPort = , Opt.help "The stake pool relay's port" ] -pStakePoolMetadataReference :: Parser (Maybe StakePoolMetadataReference) +pStakePoolMetadataReference :: Parser StakePoolMetadataReference pStakePoolMetadataReference = - optional $ - StakePoolMetadataReference - <$> pStakePoolMetadataUrl - <*> pStakePoolMetadataHash + StakePoolMetadataReference + <$> pStakePoolMetadataUrl + <*> pStakePoolMetadataHash pStakePoolMetadataUrl :: Parser Text pStakePoolMetadataUrl = @@ -2724,7 +2723,11 @@ pStakePoolRegistrationParserRequirements envCli = <*> pRewardAcctVerificationKeyOrFile <*> some pPoolOwnerVerificationKeyOrFile <*> many pPoolRelay - <*> pStakePoolMetadataReference + <*> optional + ( pPotentiallyCheckedAnchorData + pMustCheckStakeMetadataHash + pStakePoolMetadataReference + ) <*> pNetworkId envCli pProtocolParametersUpdate :: Parser ProtocolParametersUpdate @@ -3547,16 +3550,19 @@ pAnchorUrl = ProposalUrl <$> pUrl "anchor-url" "Anchor URL" -pExpectedHash :: Parser (L.SafeHash L.StandardCrypto L.AnchorData) -pExpectedHash = - Opt.option readSafeHash $ +pExpectedAnchorDataHash :: Parser (L.SafeHash L.StandardCrypto L.AnchorData) +pExpectedAnchorDataHash = pExpectedHash id "anchor data" + +pExpectedHash :: (L.SafeHash L.StandardCrypto L.AnchorData -> a) -> String -> Parser a +pExpectedHash adaptor hashedDataName = + Opt.option (adaptor <$> readSafeHash) $ mconcat [ Opt.long "expected-hash" , Opt.metavar "HASH" , Opt.help $ mconcat - [ "Expected hash for the anchor data for verification purposes. " - , "If provided, the hash of the anchor data will be compared to this value." + [ "Expected hash for the " ++ hashedDataName ++ ", for verification purposes. " + , "If provided, the hash of the " ++ hashedDataName ++ " will be compared to this value." ] ] @@ -3586,9 +3592,9 @@ pMustCheckHash flagSuffix' dataName' hashParamName' urlParamName' = ] pPotentiallyCheckedAnchorData - :: Parser (MustCheckHash anchorDataType) - -> Parser (L.Anchor L.StandardCrypto) - -> Parser (PotentiallyCheckedAnchor anchorDataType) + :: Parser (MustCheckHash anchorType) + -> Parser anchor + -> Parser (PotentiallyCheckedAnchor anchorType anchor) pPotentiallyCheckedAnchorData mustCheckHash anchorData = PotentiallyCheckedAnchor <$> anchorData @@ -3603,6 +3609,9 @@ pMustCheckConstitutionHash = pMustCheckHash "constitution-hash" "constitution" " pMustCheckMetadataHash :: Parser (MustCheckHash DRepMetadataUrl) pMustCheckMetadataHash = pMustCheckHash "drep-metadata-hash" "DRep metadata" "--drep-metadata-hash" "--drep-metadata-url" +pMustCheckStakeMetadataHash :: Parser (MustCheckHash StakePoolMetadataReference) +pMustCheckStakeMetadataHash = pMustCheckHash "metadata-hash" "stake pool metadata" "--metadata-hash" "--metadata-url" + pPreviousGovernanceAction :: Parser (Maybe (TxId, Word16)) pPreviousGovernanceAction = optional $ diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/DRep.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/DRep.hs index 63f9587595..1297536d7c 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/DRep.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/DRep.hs @@ -14,12 +14,13 @@ import Cardano.Api.Ledger (extractHash) import qualified Cardano.Api.Ledger as L import Cardano.Api.Shelley (Hash (DRepMetadataHash)) +import Cardano.CLI.Commands.Hash (HashGoal (..)) import Cardano.CLI.Environment import Cardano.CLI.EraBased.Commands.Governance.DRep import Cardano.CLI.EraBased.Options.Common import Cardano.CLI.Parser import Cardano.CLI.Read -import Cardano.CLI.Types.Common +import Cardano.CLI.Types.Common hiding (CheckHash) import Cardano.CLI.Types.Key import Cardano.Ledger.SafeHash (castSafeHash) @@ -134,16 +135,7 @@ pDrepMetadataUrl = pExpectedDrepMetadataHash :: Parser (Hash DRepMetadata) pExpectedDrepMetadataHash = - Opt.option (DRepMetadataHash . extractHash . castSafeHash <$> readSafeHash) $ - mconcat - [ Opt.long "expected-hash" - , Opt.metavar "HASH" - , Opt.help $ - mconcat - [ "Expected hash for the DRep metadata, for verification purposes. " - , "If provided, the hash of the DRep metadata is compared to this value." - ] - ] + pExpectedHash (DRepMetadataHash . extractHash . castSafeHash) "DRep metadata" pDrepMetadataHash :: Parser (L.SafeHash L.StandardCrypto L.AnchorData) pDrepMetadataHash = @@ -210,13 +202,13 @@ pGovernanceDrepMetadataHashCmd era = do $ Opt.progDesc "Calculate the hash of a metadata file, optionally checking the obtained hash against an expected value." -pDRepHashGoal :: Parser DRepHashGoal +pDRepHashGoal :: Parser (HashGoal (Hash DRepMetadata)) pDRepHashGoal = asum - [ CheckDRepHash <$> pExpectedDrepMetadataHash - , DRepHashToFile <$> pOutputFile + [ CheckHash <$> pExpectedDrepMetadataHash + , HashToFile <$> pOutputFile ] - <|> pure DRepHashToStdout + <|> pure HashToStdout pDRepMetadataSource :: Parser DRepMetadataSource pDRepMetadataSource = diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs index 86ac74f65c..c2e8e912bd 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs @@ -12,11 +12,16 @@ module Cardano.CLI.EraBased.Options.StakePool where import Cardano.Api +import qualified Cardano.Api.Ledger as L +import Cardano.Api.Shelley (Hash (StakePoolMetadataHash)) +import qualified Cardano.CLI.Commands.Hash as Cmd import Cardano.CLI.Environment (EnvCli (..)) import qualified Cardano.CLI.EraBased.Commands.StakePool as Cmd import Cardano.CLI.EraBased.Options.Common +import qualified Cardano.Ledger.SafeHash as L +import qualified Data.Foldable as F import Options.Applicative hiding (help, str) import qualified Options.Applicative as Opt @@ -42,7 +47,10 @@ pStakePoolCmds era envCli = , Just $ subParser "metadata-hash" $ Opt.info pStakePoolMetadataHashCmd $ - Opt.progDesc "Print the hash of pool metadata." + Opt.progDesc + ( "Calculate the hash of a stake pool metadata file," + <> " optionally checking the obtained hash against an expected value." + ) ] pStakePoolId @@ -61,8 +69,28 @@ pStakePoolMetadataHashCmd pStakePoolMetadataHashCmd = fmap Cmd.StakePoolMetadataHashCmd $ Cmd.StakePoolMetadataHashCmdArgs - <$> pPoolMetadataFile - <*> pMaybeOutputFile + <$> pPoolMetadataSource + <*> pPoolMetadataHashGoal + +pPoolMetadataSource :: Parser Cmd.StakePoolMetadataSource +pPoolMetadataSource = + F.asum + [ Cmd.StakePoolMetadataFileIn <$> pPoolMetadataFile + , Cmd.StakePoolMetadataURL + <$> pUrl "pool-metadata-url" "URL pointing to the JSON Metadata file to hash." + ] + +pPoolMetadataHashGoal :: Parser (Cmd.HashGoal (Hash StakePoolMetadata)) +pPoolMetadataHashGoal = + F.asum + [ Cmd.CheckHash <$> pExpectedStakePoolMetadataHash + , Cmd.HashToFile <$> pOutputFile + ] + <|> pure Cmd.HashToStdout + +pExpectedStakePoolMetadataHash :: Parser (Hash StakePoolMetadata) +pExpectedStakePoolMetadataHash = + pExpectedHash (StakePoolMetadataHash . L.extractHash . L.castSafeHash) "stake pool metadata" pStakePoolRegistrationCertificateCmd :: () @@ -84,7 +112,11 @@ pStakePoolRegistrationCertificateCmd era envCli = do <*> pRewardAcctVerificationKeyOrFile <*> some pPoolOwnerVerificationKeyOrFile <*> many pPoolRelay - <*> pStakePoolMetadataReference + <*> optional + ( pPotentiallyCheckedAnchorData + pMustCheckStakeMetadataHash + pStakePoolMetadataReference + ) <*> pNetworkId envCli <*> pOutputFile ) diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Actions.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Actions.hs index b31bc17055..7faa12f9a2 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Actions.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Actions.hs @@ -526,7 +526,7 @@ carryHashChecks checkHash anchor checkType = L.AnchorData <$> fetchURLErrorToGovernanceActionError checkType - (getByteStringFromURL httpsAndIpfsSchemas $ L.anchorUrl anchor) + (getByteStringFromURL httpsAndIpfsSchemas $ L.urlToText $ L.anchorUrl anchor) let hash = L.hashAnchorData anchorData when (hash /= L.anchorDataHash anchor) $ left $ 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 0a055a4b30..3f2d9d997b 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs @@ -18,7 +18,7 @@ where import Cardano.Api import qualified Cardano.Api.Ledger as L -import Cardano.CLI.EraBased.Commands.Governance.DRep (DRepHashGoal (..)) +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 qualified Cardano.CLI.Run.Key as Key @@ -187,15 +187,15 @@ runGovernanceDRepMetadataHashCmd Cmd.DrepMetadataFileIn metadataFile -> firstExceptT ReadFileError . newExceptT $ readByteStringFile metadataFile Cmd.DrepMetadataURL urlText -> - fetchURLToGovernanceCmdError $ getByteStringFromURL allSchemas urlText + fetchURLToGovernanceCmdError $ getByteStringFromURL allSchemas $ L.urlToText urlText let (_metadata, metadataHash) = hashDRepMetadata metadataBytes case hashGoal of - CheckDRepHash expectedHash + Cmd.CheckHash expectedHash | metadataHash /= expectedHash -> left $ GovernanceCmdHashMismatchError expectedHash metadataHash | otherwise -> liftIO $ putStrLn "Hashes match!" - DRepHashToFile outFile -> writeOutput (Just outFile) metadataHash - DRepHashToStdout -> writeOutput Nothing metadataHash + Cmd.HashToFile outFile -> writeOutput (Just outFile) metadataHash + Cmd.HashToStdout -> writeOutput Nothing metadataHash where writeOutput :: MonadIO m @@ -215,7 +215,7 @@ runGovernanceDRepMetadataHashCmd -- | Check the hash of the anchor data against the hash in the anchor if -- checkHash is set to CheckHash. carryHashChecks - :: PotentiallyCheckedAnchor DRepMetadataUrl + :: PotentiallyCheckedAnchor DRepMetadataUrl (L.Anchor L.StandardCrypto) -- ^ The information about anchor data and whether to check the hash (see 'PotentiallyCheckedAnchor') -> ExceptT HashCheckError IO () carryHashChecks potentiallyCheckedAnchor = @@ -225,7 +225,7 @@ carryHashChecks potentiallyCheckedAnchor = L.AnchorData <$> withExceptT FetchURLError - (getByteStringFromURL httpsAndIpfsSchemas $ L.anchorUrl anchor) + (getByteStringFromURL httpsAndIpfsSchemas $ L.urlToText $ L.anchorUrl anchor) let hash = L.hashAnchorData anchorData when (hash /= L.anchorDataHash anchor) $ left $ diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs index fe904eade3..15ea5d6e59 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs @@ -14,18 +14,20 @@ module Cardano.CLI.EraBased.Run.StakePool ) where -import Cardano.Api import qualified Cardano.Api.Ledger as L import Cardano.Api.Shelley +import qualified Cardano.CLI.Commands.Hash as Cmd import Cardano.CLI.EraBased.Commands.StakePool import qualified Cardano.CLI.EraBased.Commands.StakePool as Cmd +import Cardano.CLI.Run.Hash (allSchemas, getByteStringFromURL, httpsAndIpfsSchemas) import Cardano.CLI.Types.Common +import Cardano.CLI.Types.Errors.HashCmdError (FetchURLError (..)) import Cardano.CLI.Types.Errors.StakePoolCmdError import Cardano.CLI.Types.Key (readVerificationKeyOrFile) +import Control.Monad (when) import qualified Data.ByteString.Char8 as BS -import Data.Function ((&)) runStakePoolCmds :: () @@ -102,7 +104,7 @@ runStakePoolRegistrationCertificateCmd , stakePoolPledge = poolPledge , stakePoolOwners = stakePoolOwners' , stakePoolRelays = relays - , stakePoolMetadata = mMetadata + , stakePoolMetadata = pcaAnchor <$> mMetadata } let ledgerStakePoolParams = toShelleyPoolParams stakePoolParams @@ -111,6 +113,8 @@ runStakePoolRegistrationCertificateCmd shelleyBasedEraConstraints sbe ledgerStakePoolParams registrationCert = makeStakePoolRegistrationCertificate req + mapM_ carryHashChecks mMetadata + firstExceptT StakePoolCmdWriteFileError . newExceptT $ writeLazyByteStringFile outFile @@ -221,19 +225,68 @@ runStakePoolMetadataHashCmd -> ExceptT StakePoolCmdError IO () runStakePoolMetadataHashCmd Cmd.StakePoolMetadataHashCmdArgs - { poolMetadataFile - , mOutFile + { poolMetadataSource + , hashGoal } = do metadataBytes <- - lift (readByteStringFile poolMetadataFile) - & onLeft (left . StakePoolCmdReadFileError) + case poolMetadataSource of + StakePoolMetadataFileIn poolMetadataFile -> + firstExceptT StakePoolCmdReadFileError + . newExceptT + $ readByteStringFile poolMetadataFile + StakePoolMetadataURL urlText -> + fetchURLToStakePoolCmdError $ getByteStringFromURL allSchemas $ L.urlToText urlText (_metadata, metadataHash) <- firstExceptT StakePoolCmdMetadataValidationError . hoistEither $ validateAndHashStakePoolMetadata metadataBytes - case mOutFile of - Nothing -> liftIO $ BS.putStrLn (serialiseToRawBytesHex metadataHash) - Just (File fpath) -> - handleIOExceptT (StakePoolCmdWriteFileError . FileIOError fpath) $ - BS.writeFile fpath (serialiseToRawBytesHex metadataHash) + + case hashGoal of + Cmd.CheckHash expectedHash + | metadataHash /= expectedHash -> + left $ StakePoolCmdHashMismatchError expectedHash metadataHash + | otherwise -> liftIO $ putStrLn "Hashes match!" + Cmd.HashToFile outFile -> writeOutput (Just outFile) metadataHash + Cmd.HashToStdout -> writeOutput Nothing metadataHash + where + writeOutput :: Maybe (File () Out) -> Hash StakePoolMetadata -> ExceptT StakePoolCmdError IO () + writeOutput mOutFile metadataHash = + case mOutFile of + Nothing -> liftIO $ BS.putStrLn (serialiseToRawBytesHex metadataHash) + Just (File fpath) -> + handleIOExceptT (StakePoolCmdWriteFileError . FileIOError fpath) $ + BS.writeFile fpath (serialiseToRawBytesHex metadataHash) + + fetchURLToStakePoolCmdError + :: ExceptT FetchURLError IO BS.ByteString -> ExceptT StakePoolCmdError IO BS.ByteString + fetchURLToStakePoolCmdError = withExceptT StakePoolCmdFetchURLError + +-- | Check the hash of the anchor data against the hash in the anchor if +-- checkHash is set to CheckHash. +carryHashChecks + :: PotentiallyCheckedAnchor StakePoolMetadataReference StakePoolMetadataReference + -- ^ The information about anchor data and whether to check the hash (see 'PotentiallyCheckedAnchor') + -> ExceptT StakePoolCmdError IO () +carryHashChecks potentiallyCheckedAnchor = + case pcaMustCheck potentiallyCheckedAnchor of + CheckHash -> do + let urlText = stakePoolMetadataURL anchor + metadataBytes <- + withExceptT + StakePoolCmdFetchURLError + (getByteStringFromURL httpsAndIpfsSchemas urlText) + + let expectedHash = stakePoolMetadataHash anchor + + (_metadata, metadataHash) <- + firstExceptT StakePoolCmdMetadataValidationError + . hoistEither + $ validateAndHashStakePoolMetadata metadataBytes + + when (metadataHash /= expectedHash) $ + left $ + StakePoolCmdHashMismatchError expectedHash metadataHash + TrustHash -> pure () + where + anchor = pcaAnchor potentiallyCheckedAnchor diff --git a/cardano-cli/src/Cardano/CLI/Options/Hash.hs b/cardano-cli/src/Cardano/CLI/Options/Hash.hs index 7af0003f49..69ba88b6ca 100644 --- a/cardano-cli/src/Cardano/CLI/Options/Hash.hs +++ b/cardano-cli/src/Cardano/CLI/Options/Hash.hs @@ -6,6 +6,8 @@ module Cardano.CLI.Options.Hash ) where +import qualified Cardano.Api.Ledger as L + import qualified Cardano.CLI.Commands.Hash as Cmd import Cardano.CLI.EraBased.Options.Common @@ -37,10 +39,10 @@ pHashAnchorDataCmd = do ) $ Opt.progDesc "Compute the hash of some anchor data (to then pass it to other commands)." -pHashGoal :: Parser Cmd.HashGoal +pHashGoal :: Parser (Cmd.HashGoal (L.SafeHash L.StandardCrypto L.AnchorData)) pHashGoal = asum - [ Cmd.CheckHash <$> pExpectedHash + [ Cmd.CheckHash <$> pExpectedAnchorDataHash , Cmd.HashToFile <$> pOutputFile ] <|> pure Cmd.HashToStdout diff --git a/cardano-cli/src/Cardano/CLI/Run/Hash.hs b/cardano-cli/src/Cardano/CLI/Run/Hash.hs index 4add99eab0..1394d525e9 100644 --- a/cardano-cli/src/Cardano/CLI/Run/Hash.hs +++ b/cardano-cli/src/Cardano/CLI/Run/Hash.hs @@ -33,6 +33,7 @@ import qualified Data.ByteString.Lazy.Char8 as BSL8 import Data.Char (toLower) import Data.Function import Data.List (intercalate) +import Data.Text (Text) import qualified Data.Text as Text import qualified Data.Text.Encoding as Text import qualified Data.Text.IO as Text @@ -68,7 +69,7 @@ runHashAnchorDataCmd Cmd.HashAnchorDataCmdArgs{toHash, hashGoal} = do return $ Text.encodeUtf8 text Cmd.AnchorDataHashSourceText text -> return $ Text.encodeUtf8 text Cmd.AnchorDataHashSourceURL urlText -> - fetchURLToHashCmdError $ getByteStringFromURL allSchemas urlText + fetchURLToHashCmdError $ getByteStringFromURL allSchemas $ L.urlToText urlText let hash = L.hashAnchorData anchorData case hashGoal of CheckHash expectedHash @@ -100,9 +101,9 @@ allSchemas = [FileSchema, HttpSchema, HttpsSchema, IpfsSchema] httpsAndIpfsSchemas :: [SupportedSchemas] httpsAndIpfsSchemas = [HttpsSchema, IpfsSchema] -getByteStringFromURL :: [SupportedSchemas] -> L.Url -> ExceptT FetchURLError IO BS.ByteString +getByteStringFromURL :: [SupportedSchemas] -> Text -> ExceptT FetchURLError IO BS.ByteString getByteStringFromURL supportedSchemas urlText = do - let urlString = Text.unpack $ L.urlToText urlText + let urlString = Text.unpack urlText uri <- hoistMaybe (FetchURLInvalidURLError urlString) $ parseAbsoluteURI urlString case map toLower $ uriScheme uri of "file:" diff --git a/cardano-cli/src/Cardano/CLI/Types/Common.hs b/cardano-cli/src/Cardano/CLI/Types/Common.hs index 6f4aecbb41..e3c22e51fa 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Common.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Common.hs @@ -93,7 +93,6 @@ module Cardano.CLI.Types.Common where import Cardano.Api hiding (Script) -import Cardano.Api.Ledger (Anchor) import qualified Cardano.Api.Ledger as L import qualified Cardano.Chain.Slotting as Byron @@ -653,9 +652,9 @@ data MustCheckHash a | TrustHash deriving (Eq, Show) -data PotentiallyCheckedAnchor anchorType +data PotentiallyCheckedAnchor anchorType anchor = PotentiallyCheckedAnchor - { pcaAnchor :: Anchor L.StandardCrypto + { pcaAnchor :: anchor -- ^ The anchor data whose hash is to be checked , pcaMustCheck :: MustCheckHash anchorType -- ^ Whether to check the hash or not (CheckHash for checking or TrustHash for not checking) diff --git a/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs b/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs index 2a5573dabf..d3bdd9e20c 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs @@ -10,12 +10,21 @@ module Cardano.CLI.Types.Errors.StakePoolCmdError where import Cardano.Api +import Cardano.Api.Shelley (Hash (StakePoolMetadataHash)) + +import Cardano.CLI.Types.Errors.HashCmdError (FetchURLError) data StakePoolCmdError = StakePoolCmdReadFileError !(FileError TextEnvelopeError) | StakePoolCmdReadKeyFileError !(FileError InputDecodeError) | StakePoolCmdWriteFileError !(FileError ()) | StakePoolCmdMetadataValidationError !StakePoolMetadataValidationError + | StakePoolCmdHashMismatchError + !(Hash StakePoolMetadata) + -- ^ Expected hash + !(Hash StakePoolMetadata) + -- ^ Actual hash + | StakePoolCmdFetchURLError !FetchURLError deriving Show renderStakePoolCmdError :: StakePoolCmdError -> Doc ann @@ -28,3 +37,13 @@ renderStakePoolCmdError = \case prettyError fileErr StakePoolCmdWriteFileError fileErr -> prettyError fileErr + StakePoolCmdHashMismatchError + (StakePoolMetadataHash expectedHash) + (StakePoolMetadataHash actualHash) -> + "Hashes do not match!" + <> "\nExpected:" + <+> pretty (show expectedHash) + <> "\n Actual:" + <+> pretty (show actualHash) + StakePoolCmdFetchURLError fetchErr -> + "Error fetching stake pool metadata: " <> prettyException fetchErr diff --git a/cardano-cli/src/Cardano/CLI/Types/Key.hs b/cardano-cli/src/Cardano/CLI/Types/Key.hs index 940ecb5ca0..19f50de054 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Key.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Key.hs @@ -148,7 +148,8 @@ data StakePoolRegistrationParserRequirements -- ^ Pool owner verification staking key(s). , sprRelays :: [StakePoolRelay] -- ^ Stake pool relays. - , sprMetadata :: Maybe StakePoolMetadataReference + , sprMetadata + :: Maybe (PotentiallyCheckedAnchor StakePoolMetadataReference StakePoolMetadataReference) -- ^ Stake pool metadata. , sprNetworkId :: NetworkId } diff --git a/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/StakeAddress.hs b/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/StakeAddress.hs index 8dcc952a93..e58a897cee 100644 --- a/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/StakeAddress.hs +++ b/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/StakeAddress.hs @@ -1,15 +1,29 @@ {- HLINT ignore "Use camelCase" -} +{-# LANGUAGE FlexibleContexts #-} module Test.Golden.Governance.StakeAddress where import Control.Monad (void) +import System.Exit (ExitCode (..)) -import Test.Cardano.CLI.Util (execCardanoCLI, noteInputFile, propertyOnce) +import Test.Cardano.CLI.Hash (serveFilesWhile, tamperBase16Hash) +import Test.Cardano.CLI.Util (execCardanoCLI, execDetailCardanoCLI, noteInputFile, + propertyOnce) import Hedgehog +import qualified Hedgehog as H import qualified Hedgehog.Extras.Test.Base as H import qualified Hedgehog.Extras.Test.Golden as H +exampleStakePoolMetadataHash :: String +exampleStakePoolMetadataHash = "8241de08075886a7d09c847c9bbd1719459dac0bd0a2f085e673611ebb9a5965" + +exampleStakePoolMetadataPathGolden :: String +exampleStakePoolMetadataPathGolden = "test/cardano-cli-golden/files/input/example_stake_pool_metadata.json" + +exampleStakePoolMetadataIpfsHash :: String +exampleStakePoolMetadataIpfsHash = "QmR1HAT4Hb4HjjqcgoXwupYXMF6t8h7MoSP24HMfV8t38a" + hprop_golden_conway_stakeaddress_delegate_no_confidence :: Property hprop_golden_conway_stakeaddress_delegate_no_confidence = propertyOnce . H.moduleWorkspace "tmp" $ \tempDir -> do @@ -220,3 +234,35 @@ hprop_golden_conway_stakeaddress_register_and_delegate_stake_and_vote = ] H.diffFileVsGoldenFile certFile certGold + +-- Execute me with: +-- @cabal test cardano-cli-golden --test-options '-p "/golden stake pool metadata hash url wrong hash/"'@ +hprop_golden_stake_pool_metadata_hash_url_wrong_hash :: Property +hprop_golden_stake_pool_metadata_hash_url_wrong_hash = do + propertyOnce $ do + -- We modify the hash slightly so that the hash check fails + alteredHash <- H.evalMaybe $ tamperBase16Hash exampleStakePoolMetadataHash + let relativeUrl = [exampleStakePoolMetadataIpfsHash] + + -- Create temporary HTTP server with files required by the call to `cardano-cli` + (exitCode, _, result) <- + serveFilesWhile + [ (relativeUrl, exampleStakePoolMetadataPathGolden) + ] + ( \port -> do + execDetailCardanoCLI + [ "conway" + , "stake-pool" + , "metadata-hash" + , "--pool-metadata-url" + , "http://127.0.0.1:" ++ show port ++ "/" ++ exampleStakePoolMetadataIpfsHash + , "--expected-hash" + , alteredHash + ] + ) + + exitCode === ExitFailure 1 + + H.diffVsGoldenFile + result + "test/cardano-cli-golden/files/golden/governance/stakeaddress/stake_pool_metadata_hash_url_wrong_hash_fails.out" diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/governance/stakeaddress/stake_pool_metadata_hash_url_wrong_hash_fails.out b/cardano-cli/test/cardano-cli-golden/files/golden/governance/stakeaddress/stake_pool_metadata_hash_url_wrong_hash_fails.out new file mode 100644 index 0000000000..f05d7faf5f --- /dev/null +++ b/cardano-cli/test/cardano-cli-golden/files/golden/governance/stakeaddress/stake_pool_metadata_hash_url_wrong_hash_fails.out @@ -0,0 +1,3 @@ +Command failed: stake-pool metadata-hash Error: Hashes do not match! +Expected: "9241de08075886a7d09c847c9bbd1719459dac0bd0a2f085e673611ebb9a5965" + Actual: "8241de08075886a7d09c847c9bbd1719459dac0bd0a2f085e673611ebb9a5965" 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 92a25f98bc..a059b8fb2b 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli @@ -1468,7 +1468,8 @@ Usage: cardano-cli shelley stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -1494,10 +1495,16 @@ Usage: cardano-cli shelley stake-pool id Build pool id from the offline key -Usage: cardano-cli shelley stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli shelley stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Usage: cardano-cli shelley text-view decode-cbor @@ -2535,7 +2542,8 @@ Usage: cardano-cli allegra stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -2561,10 +2569,16 @@ Usage: cardano-cli allegra stake-pool id Build pool id from the offline key -Usage: cardano-cli allegra stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli allegra stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Usage: cardano-cli allegra text-view decode-cbor @@ -3594,7 +3608,8 @@ Usage: cardano-cli mary stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -3620,10 +3635,16 @@ Usage: cardano-cli mary stake-pool id Build pool id from the offline key -Usage: cardano-cli mary stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli mary stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Usage: cardano-cli mary text-view decode-cbor @@ -4664,7 +4685,8 @@ Usage: cardano-cli alonzo stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -4690,10 +4712,16 @@ Usage: cardano-cli alonzo stake-pool id Build pool id from the offline key -Usage: cardano-cli alonzo stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli alonzo stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Usage: cardano-cli alonzo text-view decode-cbor @@ -5757,7 +5785,8 @@ Usage: cardano-cli babbage stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -5783,10 +5812,16 @@ Usage: cardano-cli babbage stake-pool id Build pool id from the offline key -Usage: cardano-cli babbage stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli babbage stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Usage: cardano-cli babbage text-view decode-cbor @@ -7657,7 +7692,8 @@ Usage: cardano-cli conway stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -7683,10 +7719,16 @@ Usage: cardano-cli conway stake-pool id Build pool id from the offline key -Usage: cardano-cli conway stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli conway stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Usage: cardano-cli conway text-view decode-cbor @@ -9649,7 +9691,8 @@ Usage: cardano-cli latest stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -9675,10 +9718,16 @@ Usage: cardano-cli latest stake-pool id Build pool id from the offline key -Usage: cardano-cli latest stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli latest stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Usage: cardano-cli latest text-view decode-cbor diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool.cli index 4eafe587c5..05cb71eabc 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool.cli @@ -15,4 +15,6 @@ Available commands: deregistration-certificate Create a stake pool deregistration certificate id Build pool id from the offline key - metadata-hash Print the hash of pool metadata. + metadata-hash Calculate the hash of a stake pool metadata file, + optionally checking the obtained hash against an + expected value. diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool_metadata-hash.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool_metadata-hash.cli index 7280468019..9b3cdb7666 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool_metadata-hash.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool_metadata-hash.cli @@ -1,10 +1,20 @@ -Usage: cardano-cli allegra stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli allegra stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. - --out-file FILEPATH Optional output file. Default is to write to stdout. + --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. + --expected-hash HASH Expected hash for the stake pool metadata, for + verification purposes. If provided, the hash of the + stake pool metadata will be compared to this value. + --out-file FILEPATH The output file. -h,--help Show this help text diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool_registration-certificate.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool_registration-certificate.cli index 76284165df..cd1887bc4c 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool_registration-certificate.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/allegra_stake-pool_registration-certificate.cli @@ -22,7 +22,8 @@ Usage: cardano-cli allegra stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -65,6 +66,11 @@ Available options: an SRV DNS record --metadata-url URL Pool metadata URL (maximum length of 64 characters). --metadata-hash HASH Pool metadata hash. + --check-metadata-hash Verify that the expected stake pool metadata hash + provided in --metadata-hash matches the hash of the + file downloaded from the URL provided in + --metadata-url (this parameter will download the file + from the URL) --mainnet Use the mainnet magic id. This overrides the CARDANO_NODE_NETWORK_ID environment variable --testnet-magic NATURAL Specify a testnet magic id. This overrides the diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool.cli index aae2b0d90a..5be31d1420 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool.cli @@ -15,4 +15,6 @@ Available commands: deregistration-certificate Create a stake pool deregistration certificate id Build pool id from the offline key - metadata-hash Print the hash of pool metadata. + metadata-hash Calculate the hash of a stake pool metadata file, + optionally checking the obtained hash against an + expected value. diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool_metadata-hash.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool_metadata-hash.cli index 4bb385bd20..a6de242b66 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool_metadata-hash.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool_metadata-hash.cli @@ -1,10 +1,20 @@ -Usage: cardano-cli alonzo stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli alonzo stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. - --out-file FILEPATH Optional output file. Default is to write to stdout. + --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. + --expected-hash HASH Expected hash for the stake pool metadata, for + verification purposes. If provided, the hash of the + stake pool metadata will be compared to this value. + --out-file FILEPATH The output file. -h,--help Show this help text diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool_registration-certificate.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool_registration-certificate.cli index b6079413bd..9ba7243d74 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool_registration-certificate.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/alonzo_stake-pool_registration-certificate.cli @@ -22,7 +22,8 @@ Usage: cardano-cli alonzo stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -65,6 +66,11 @@ Available options: an SRV DNS record --metadata-url URL Pool metadata URL (maximum length of 64 characters). --metadata-hash HASH Pool metadata hash. + --check-metadata-hash Verify that the expected stake pool metadata hash + provided in --metadata-hash matches the hash of the + file downloaded from the URL provided in + --metadata-url (this parameter will download the file + from the URL) --mainnet Use the mainnet magic id. This overrides the CARDANO_NODE_NETWORK_ID environment variable --testnet-magic NATURAL Specify a testnet magic id. This overrides the diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool.cli index 663a221b94..bc4b9bd540 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool.cli @@ -15,4 +15,6 @@ Available commands: deregistration-certificate Create a stake pool deregistration certificate id Build pool id from the offline key - metadata-hash Print the hash of pool metadata. + metadata-hash Calculate the hash of a stake pool metadata file, + optionally checking the obtained hash against an + expected value. diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool_metadata-hash.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool_metadata-hash.cli index bf1d6c0282..c393c52456 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool_metadata-hash.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool_metadata-hash.cli @@ -1,10 +1,20 @@ -Usage: cardano-cli babbage stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli babbage stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. - --out-file FILEPATH Optional output file. Default is to write to stdout. + --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. + --expected-hash HASH Expected hash for the stake pool metadata, for + verification purposes. If provided, the hash of the + stake pool metadata will be compared to this value. + --out-file FILEPATH The output file. -h,--help Show this help text diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool_registration-certificate.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool_registration-certificate.cli index a3abe5c53c..5dc14eea54 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool_registration-certificate.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/babbage_stake-pool_registration-certificate.cli @@ -22,7 +22,8 @@ Usage: cardano-cli babbage stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -65,6 +66,11 @@ Available options: an SRV DNS record --metadata-url URL Pool metadata URL (maximum length of 64 characters). --metadata-hash HASH Pool metadata hash. + --check-metadata-hash Verify that the expected stake pool metadata hash + provided in --metadata-hash matches the hash of the + file downloaded from the URL provided in + --metadata-url (this parameter will download the file + from the URL) --mainnet Use the mainnet magic id. This overrides the CARDANO_NODE_NETWORK_ID environment variable --testnet-magic NATURAL Specify a testnet magic id. This overrides the diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_drep_metadata-hash.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_drep_metadata-hash.cli index cf1c1d8099..94f1a7fc4e 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_drep_metadata-hash.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_drep_metadata-hash.cli @@ -15,6 +15,6 @@ Available options: --drep-metadata-url TEXT URL pointing to the JSON Metadata file to hash. --expected-hash HASH Expected hash for the DRep metadata, for verification purposes. If provided, the hash of the DRep metadata - is compared to this value. + will be compared to this value. --out-file FILEPATH The output file. -h,--help Show this help text diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool.cli index 2aa6275847..3c4574252a 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool.cli @@ -15,4 +15,6 @@ Available commands: deregistration-certificate Create a stake pool deregistration certificate id Build pool id from the offline key - metadata-hash Print the hash of pool metadata. + metadata-hash Calculate the hash of a stake pool metadata file, + optionally checking the obtained hash against an + expected value. diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool_metadata-hash.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool_metadata-hash.cli index 150bb8ebc8..f9429ceffe 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool_metadata-hash.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool_metadata-hash.cli @@ -1,10 +1,20 @@ -Usage: cardano-cli conway stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli conway stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. - --out-file FILEPATH Optional output file. Default is to write to stdout. + --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. + --expected-hash HASH Expected hash for the stake pool metadata, for + verification purposes. If provided, the hash of the + stake pool metadata will be compared to this value. + --out-file FILEPATH The output file. -h,--help Show this help text diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool_registration-certificate.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool_registration-certificate.cli index b9cae2c7e5..f0a118b7b1 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool_registration-certificate.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool_registration-certificate.cli @@ -22,7 +22,8 @@ Usage: cardano-cli conway stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -65,6 +66,11 @@ Available options: an SRV DNS record --metadata-url URL Pool metadata URL (maximum length of 64 characters). --metadata-hash HASH Pool metadata hash. + --check-metadata-hash Verify that the expected stake pool metadata hash + provided in --metadata-hash matches the hash of the + file downloaded from the URL provided in + --metadata-url (this parameter will download the file + from the URL) --mainnet Use the mainnet magic id. This overrides the CARDANO_NODE_NETWORK_ID environment variable --testnet-magic NATURAL Specify a testnet magic id. This overrides the diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/hash_anchor-data.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/hash_anchor-data.cli index 4fb88d13b3..11f6723217 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/hash_anchor-data.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/hash_anchor-data.cli @@ -15,7 +15,7 @@ Available options: --file-binary FILEPATH Binary file to hash --file-text FILEPATH Text file to hash --url TEXT A URL to the file to hash (HTTP(S) and IPFS only) - --expected-hash HASH Expected hash for the anchor data for verification + --expected-hash HASH Expected hash for the anchor data, for verification purposes. If provided, the hash of the anchor data will be compared to this value. --out-file FILEPATH The output file. diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_drep_metadata-hash.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_drep_metadata-hash.cli index 30264f2d17..641ff2ffcb 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_drep_metadata-hash.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_governance_drep_metadata-hash.cli @@ -15,6 +15,6 @@ Available options: --drep-metadata-url TEXT URL pointing to the JSON Metadata file to hash. --expected-hash HASH Expected hash for the DRep metadata, for verification purposes. If provided, the hash of the DRep metadata - is compared to this value. + will be compared to this value. --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_stake-pool.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_stake-pool.cli index 20530d9c46..3999e6a5e1 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_stake-pool.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_stake-pool.cli @@ -15,4 +15,6 @@ Available commands: deregistration-certificate Create a stake pool deregistration certificate id Build pool id from the offline key - metadata-hash Print the hash of pool metadata. + metadata-hash Calculate the hash of a stake pool metadata file, + optionally checking the obtained hash against an + expected value. diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_stake-pool_metadata-hash.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_stake-pool_metadata-hash.cli index 2cab19f49f..2b5df9cde7 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_stake-pool_metadata-hash.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_stake-pool_metadata-hash.cli @@ -1,10 +1,20 @@ -Usage: cardano-cli latest stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli latest stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. - --out-file FILEPATH Optional output file. Default is to write to stdout. + --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. + --expected-hash HASH Expected hash for the stake pool metadata, for + verification purposes. If provided, the hash of the + stake pool metadata will be compared to this value. + --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_stake-pool_registration-certificate.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_stake-pool_registration-certificate.cli index 87eebefa2b..fbddd258fd 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_stake-pool_registration-certificate.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_stake-pool_registration-certificate.cli @@ -22,7 +22,8 @@ Usage: cardano-cli latest stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -65,6 +66,11 @@ Available options: an SRV DNS record --metadata-url URL Pool metadata URL (maximum length of 64 characters). --metadata-hash HASH Pool metadata hash. + --check-metadata-hash Verify that the expected stake pool metadata hash + provided in --metadata-hash matches the hash of the + file downloaded from the URL provided in + --metadata-url (this parameter will download the file + from the URL) --mainnet Use the mainnet magic id. This overrides the CARDANO_NODE_NETWORK_ID environment variable --testnet-magic NATURAL Specify a testnet magic id. This overrides the diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool.cli index 3c42a67b75..67e8505c11 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool.cli @@ -15,4 +15,6 @@ Available commands: deregistration-certificate Create a stake pool deregistration certificate id Build pool id from the offline key - metadata-hash Print the hash of pool metadata. + metadata-hash Calculate the hash of a stake pool metadata file, + optionally checking the obtained hash against an + expected value. diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool_metadata-hash.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool_metadata-hash.cli index 6a95d2352e..307901e6e2 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool_metadata-hash.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool_metadata-hash.cli @@ -1,10 +1,20 @@ -Usage: cardano-cli mary stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli mary stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. - --out-file FILEPATH Optional output file. Default is to write to stdout. + --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. + --expected-hash HASH Expected hash for the stake pool metadata, for + verification purposes. If provided, the hash of the + stake pool metadata will be compared to this value. + --out-file FILEPATH The output file. -h,--help Show this help text diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool_registration-certificate.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool_registration-certificate.cli index b593000249..2fc6790ab0 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool_registration-certificate.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/mary_stake-pool_registration-certificate.cli @@ -22,7 +22,8 @@ Usage: cardano-cli mary stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -65,6 +66,11 @@ Available options: an SRV DNS record --metadata-url URL Pool metadata URL (maximum length of 64 characters). --metadata-hash HASH Pool metadata hash. + --check-metadata-hash Verify that the expected stake pool metadata hash + provided in --metadata-hash matches the hash of the + file downloaded from the URL provided in + --metadata-url (this parameter will download the file + from the URL) --mainnet Use the mainnet magic id. This overrides the CARDANO_NODE_NETWORK_ID environment variable --testnet-magic NATURAL Specify a testnet magic id. This overrides the diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool.cli index 3740209b5f..0381e5bbd9 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool.cli @@ -15,4 +15,6 @@ Available commands: deregistration-certificate Create a stake pool deregistration certificate id Build pool id from the offline key - metadata-hash Print the hash of pool metadata. + metadata-hash Calculate the hash of a stake pool metadata file, + optionally checking the obtained hash against an + expected value. diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool_metadata-hash.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool_metadata-hash.cli index b01fc59968..3540f3c572 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool_metadata-hash.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool_metadata-hash.cli @@ -1,10 +1,20 @@ -Usage: cardano-cli shelley stake-pool metadata-hash --pool-metadata-file FILEPATH - [--out-file FILEPATH] +Usage: cardano-cli shelley stake-pool metadata-hash + ( --pool-metadata-file FILEPATH + | --pool-metadata-url TEXT + ) + [ --expected-hash HASH + | --out-file FILEPATH + ] - Print the hash of pool metadata. + Calculate the hash of a stake pool metadata file, optionally checking the + obtained hash against an expected value. Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. - --out-file FILEPATH Optional output file. Default is to write to stdout. + --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. + --expected-hash HASH Expected hash for the stake pool metadata, for + verification purposes. If provided, the hash of the + stake pool metadata will be compared to this value. + --out-file FILEPATH The output file. -h,--help Show this help text diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool_registration-certificate.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool_registration-certificate.cli index f108361fb6..551f58ed7a 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool_registration-certificate.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/shelley_stake-pool_registration-certificate.cli @@ -22,7 +22,8 @@ Usage: cardano-cli shelley stake-pool registration-certificate | --multi-host-pool-relay STRING ] [--metadata-url URL - --metadata-hash HASH] + --metadata-hash HASH + [--check-metadata-hash]] ( --mainnet | --testnet-magic NATURAL ) @@ -65,6 +66,11 @@ Available options: an SRV DNS record --metadata-url URL Pool metadata URL (maximum length of 64 characters). --metadata-hash HASH Pool metadata hash. + --check-metadata-hash Verify that the expected stake pool metadata hash + provided in --metadata-hash matches the hash of the + file downloaded from the URL provided in + --metadata-url (this parameter will download the file + from the URL) --mainnet Use the mainnet magic id. This overrides the CARDANO_NODE_NETWORK_ID environment variable --testnet-magic NATURAL Specify a testnet magic id. This overrides the diff --git a/cardano-cli/test/cardano-cli-golden/files/input/example_stake_pool_metadata.json b/cardano-cli/test/cardano-cli-golden/files/input/example_stake_pool_metadata.json new file mode 100644 index 0000000000..ec115e94d0 --- /dev/null +++ b/cardano-cli/test/cardano-cli-golden/files/input/example_stake_pool_metadata.json @@ -0,0 +1 @@ +{"homepage":"https://iohk.io","name":"Genesis Pool C","ticker":"GPC","description":"Lorem Ipsum Dolor Sit Amet."} \ No newline at end of file diff --git a/cardano-cli/test/cardano-cli-test/Test/Cli/Shelley/Certificates/StakePool.hs b/cardano-cli/test/cardano-cli-test/Test/Cli/Shelley/Certificates/StakePool.hs new file mode 100644 index 0000000000..94617d6dea --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/Test/Cli/Shelley/Certificates/StakePool.hs @@ -0,0 +1,240 @@ +{-# LANGUAGE FlexibleContexts #-} + +module Test.Cli.Shelley.Certificates.StakePool 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) +import qualified Hedgehog as H +import qualified Hedgehog.Extras as H +import Hedgehog.Internal.Property (Property) + +exampleStakePoolMetadataHash :: String +exampleStakePoolMetadataHash = "8241de08075886a7d09c847c9bbd1719459dac0bd0a2f085e673611ebb9a5965" + +exampleStakePoolMetadataPathTest :: String +exampleStakePoolMetadataPathTest = "test/cardano-cli-test/files/input/example_stake_pool_metadata.json" + +exampleStakePoolMetadataIpfsHash :: String +exampleStakePoolMetadataIpfsHash = "QmR1HAT4Hb4HjjqcgoXwupYXMF6t8h7MoSP24HMfV8t38a" + +-- Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/stake pool certificate hash check wrong metadata fails/"'@ +hprop_stake_pool_certificate_hash_check_wrong_metadata_fails :: Property +hprop_stake_pool_certificate_hash_check_wrong_metadata_fails = + propertyOnce . expectFailure . H.moduleWorkspace "tmp" $ \tempDir -> do + -- We run the test with the wrong metadata file + baseStakePoolCertificateHashCheck + exampleAnchorDataIpfsHash + exampleAnchorDataPathTest + exampleAnchorDataHash + tempDir + +-- Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/stake pool certificate hash check wrong hash fails/"'@ +hprop_stake_pool_certificate_hash_check_wrong_hash_fails :: Property +hprop_stake_pool_certificate_hash_check_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 exampleStakePoolMetadataHash + -- We run the test with the modified hash + baseStakePoolCertificateHashCheck + exampleStakePoolMetadataIpfsHash + exampleStakePoolMetadataPathTest + alteredHash + tempDir + +-- Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/stake pool certificate hash check right hash works/"'@ +hprop_stake_pool_certificate_hash_check_right_hash_works :: Property +hprop_stake_pool_certificate_hash_check_right_hash_works = + propertyOnce . H.moduleWorkspace "tmp" $ \tempDir -> + baseStakePoolCertificateHashCheck + exampleStakePoolMetadataIpfsHash + exampleStakePoolMetadataPathTest + exampleStakePoolMetadataHash + tempDir + +baseStakePoolCertificateHashCheck + :: (MonadBaseControl IO m, MonadTest m, MonadIO m, MonadCatch m) + => String + -- ^ The ipfs hash of the file for the URL name + -> FilePath + -- ^ File to use as the metadata file + -> String + -- ^ The hash to check against. Changing this value allows us to test the + -- behavior of the command both when the hash is correct and when it is incorrect + -- reusing the same code. + -> FilePath + -- ^ Temporary directory for files generated during the test + -> m () +baseStakePoolCertificateHashCheck ipfsHash metadataFile hash tempDir = do + -- Key filepaths + coldVerKey <- noteTempFile tempDir "cold-verification-key-file" + coldSignKey <- noteTempFile tempDir "cold-signing-key-file" + operationalCertCounter <- noteTempFile tempDir "operational-certificate-counter-file" + vrfVerKey <- noteTempFile tempDir "vrf-verification-key-file" + vrfSignKey <- noteTempFile tempDir "vrf-signing-key-file" + poolRewardAccountAndOwnerVerKey <- noteTempFile tempDir "reward-account-verification-key-file" + poolRewardAccountSignKey <- noteTempFile tempDir "reward-account-signing-key-file" + registrationCertificate <- noteTempFile tempDir "stake-pool-registration-certificate" + + -- Create cold key pair + void $ + execCardanoCLI + [ "latest" + , "node" + , "key-gen" + , "--cold-verification-key-file" + , coldVerKey + , "--cold-signing-key-file" + , coldSignKey + , "--operational-certificate-issue-counter" + , operationalCertCounter + ] + + H.assertFilesExist [coldSignKey, coldVerKey, operationalCertCounter] + + -- Generate stake key pair + void $ + execCardanoCLI + [ "latest" + , "stake-address" + , "key-gen" + , "--verification-key-file" + , poolRewardAccountAndOwnerVerKey + , "--signing-key-file" + , poolRewardAccountSignKey + ] + + H.assertFilesExist [poolRewardAccountAndOwnerVerKey, poolRewardAccountSignKey] + + -- Generate vrf verification key + void $ + execCardanoCLI + [ "latest" + , "node" + , "key-gen-VRF" + , "--verification-key-file" + , vrfVerKey + , "--signing-key-file" + , vrfSignKey + ] + + H.assertFilesExist [vrfSignKey, vrfVerKey] + + let relativeUrl = ["ipfs", ipfsHash] + + -- Create temporary HTTP server with files required by the call to `cardano-cli` + -- In this case, the server emulates an IPFS gateway + serveFilesWhile + [ (relativeUrl, metadataFile) + ] + ( \port -> do + -- Create stake pool registration certificate + void $ + execCardanoCLIWithEnvVars + [("IPFS_GATEWAY_URI", "http://localhost:" ++ show port ++ "/")] + [ "babbage" + , "stake-pool" + , "registration-certificate" + , "--cold-verification-key-file" + , coldVerKey + , "--vrf-verification-key-file" + , vrfVerKey + , "--mainnet" + , "--pool-cost" + , "1000" + , "--pool-pledge" + , "5000" + , "--pool-margin" + , "0.1" + , "--pool-reward-account-verification-key-file" + , poolRewardAccountAndOwnerVerKey + , "--pool-owner-stake-verification-key-file" + , poolRewardAccountAndOwnerVerKey + , "--metadata-url" + , "ipfs://" ++ ipfsHash + , "--metadata-hash" + , hash + , "--check-metadata-hash" + , "--out-file" + , registrationCertificate + ] + ) + +-- Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/stake pool metadata hash url wrong metadata fails/"'@ +hprop_stake_pool_metadata_hash_url_wrong_metadata_fails :: Property +hprop_stake_pool_metadata_hash_url_wrong_metadata_fails = + propertyOnce . expectFailure $ do + -- We run the test with the wrong metadata file + baseStakePoolMetadataHashUrl + exampleAnchorDataIpfsHash + exampleAnchorDataPathTest + exampleAnchorDataHash + +-- Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/stake pool metadata hash url wrong hash fails/"'@ +hprop_stake_pool_metadata_hash_url_wrong_hash_fails :: Property +hprop_stake_pool_metadata_hash_url_wrong_hash_fails = + propertyOnce . expectFailure $ do + -- We modify the hash slightly so that the hash check fails + alteredHash <- H.evalMaybe $ tamperBase16Hash exampleStakePoolMetadataHash + -- We run the test with the modified hash + baseStakePoolMetadataHashUrl + exampleStakePoolMetadataIpfsHash + exampleStakePoolMetadataPathTest + alteredHash + +-- Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/stake pool metadata hash url correct hash/"'@ +hprop_stake_pool_metadata_hash_url_correct_hash :: Property +hprop_stake_pool_metadata_hash_url_correct_hash = + propertyOnce $ + baseStakePoolMetadataHashUrl + exampleStakePoolMetadataIpfsHash + exampleStakePoolMetadataPathTest + exampleStakePoolMetadataHash + +baseStakePoolMetadataHashUrl + :: (MonadBaseControl IO m, MonadTest m, MonadIO m, MonadCatch m) + => String + -- ^ The ipfs hash of the file for the URL name + -> FilePath + -- ^ File to use as the metadata file + -> String + -- ^ The hash to check against. Changing this value allows us to test the + -- behavior of the command both when the hash is correct and when it is incorrect + -- reusing the same code. + -> m () +baseStakePoolMetadataHashUrl ipfsHash metadataFile hash = do + let relativeUrl = ["ipfs", ipfsHash] + + -- Create temporary HTTP server with files required by the call to `cardano-cli` + -- In this case, the server emulates an IPFS gateway + serveFilesWhile + [ (relativeUrl, metadataFile) + ] + ( \port -> do + void $ + execCardanoCLIWithEnvVars + [("IPFS_GATEWAY_URI", "http://localhost:" ++ show port ++ "/")] + [ "conway" + , "stake-pool" + , "metadata-hash" + , "--pool-metadata-url" + , "ipfs://" ++ ipfsHash + , "--expected-hash" + , hash + ] + ) diff --git a/cardano-cli/test/cardano-cli-test/files/input/example_stake_pool_metadata.json b/cardano-cli/test/cardano-cli-test/files/input/example_stake_pool_metadata.json new file mode 100644 index 0000000000..ec115e94d0 --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/files/input/example_stake_pool_metadata.json @@ -0,0 +1 @@ +{"homepage":"https://iohk.io","name":"Genesis Pool C","ticker":"GPC","description":"Lorem Ipsum Dolor Sit Amet."} \ No newline at end of file