From 10685c9d5fc37d1e9854b87d49c40eb380530feb Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Tue, 8 Oct 2024 19:13:53 +0200 Subject: [PATCH 01/13] Implement test for hash check in `stake-pool registration-certificate` --- cardano-cli/cardano-cli.cabal | 1 + .../cardano-cli-golden/files/golden/help.cli | 21 ++- ...ra_stake-pool_registration-certificate.cli | 8 +- ...zo_stake-pool_registration-certificate.cli | 8 +- ...ge_stake-pool_registration-certificate.cli | 8 +- ...ay_stake-pool_registration-certificate.cli | 8 +- ...st_stake-pool_registration-certificate.cli | 8 +- ...ry_stake-pool_registration-certificate.cli | 8 +- ...ey_stake-pool_registration-certificate.cli | 8 +- .../Cli/Shelley/Certificates/StakePool.hs | 150 ++++++++++++++++++ .../input/example_stake_pool_metadata.json | 1 + 11 files changed, 215 insertions(+), 14 deletions(-) create mode 100644 cardano-cli/test/cardano-cli-test/Test/Cli/Shelley/Certificates/StakePool.hs create mode 100644 cardano-cli/test/cardano-cli-test/files/input/example_stake_pool_metadata.json diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 1e6bd31539..ed13e4b4e5 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/test/cardano-cli-golden/files/golden/help.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli index ff8632d071..04d87b120b 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli @@ -1385,7 +1385,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 ) @@ -2452,7 +2453,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 ) @@ -3511,7 +3513,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 ) @@ -4581,7 +4584,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 ) @@ -5674,7 +5678,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 ) @@ -7574,7 +7579,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 ) @@ -9566,7 +9572,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 ) 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_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_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_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/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_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_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-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..88c27c8385 --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/Test/Cli/Shelley/Certificates/StakePool.hs @@ -0,0 +1,150 @@ +{-# 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 (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 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 + 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 exampleStakePoolMetadataHash tempDir + +baseStakePoolCertificateHashCheck + :: (MonadBaseControl IO m, MonadTest m, MonadIO m, MonadCatch m) + => 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 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", exampleStakePoolMetadataIpfsHash] + + -- Create temporary HTTP server with files required by the call to `cardano-cli` + -- In this case, the server emulates an IPFS gateway + serveFilesWhile + [ (relativeUrl, exampleStakePoolMetadataPathTest) + ] + ( \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://" ++ exampleStakePoolMetadataIpfsHash + , "--metadata-hash" + , hash + , "--check-metadata-hash" + , "--out-file" + , registrationCertificate + ] + ) 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 From 3ae15450aa1387472c078a344346ea00ee94e7b8 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Tue, 8 Oct 2024 20:46:41 +0200 Subject: [PATCH 02/13] Implement hash check in `stake-pool registration-certificate` --- .../CLI/EraBased/Commands/Governance/DRep.hs | 2 + .../CLI/EraBased/Commands/StakePool.hs | 3 +- .../Cardano/CLI/EraBased/Options/Common.hs | 24 +++++++---- .../Cardano/CLI/EraBased/Options/StakePool.hs | 6 ++- .../CLI/EraBased/Run/Governance/DRep.hs | 2 +- .../src/Cardano/CLI/EraBased/Run/StakePool.hs | 43 ++++++++++++++++++- cardano-cli/src/Cardano/CLI/Types/Common.hs | 5 +-- .../CLI/Types/Errors/StakePoolCmdError.hs | 5 +++ cardano-cli/src/Cardano/CLI/Types/Key.hs | 3 +- 9 files changed, 75 insertions(+), 18 deletions(-) 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..ed2eb1213a 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/DRep.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/DRep.hs @@ -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) } diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs index 39fd541f8a..da07992688 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs @@ -73,7 +73,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..0fa7bf48a2 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 @@ -3586,9 +3589,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 +3606,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/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs index 86ac74f65c..d53f7b5a0a 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs @@ -84,7 +84,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/DRep.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs index 84499fc860..95afe33c18 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs @@ -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 = diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs index fe904eade3..ce483ed203 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs @@ -14,18 +14,24 @@ module Cardano.CLI.EraBased.Run.StakePool ) where -import Cardano.Api import qualified Cardano.Api.Ledger as L import Cardano.Api.Shelley import Cardano.CLI.EraBased.Commands.StakePool import qualified Cardano.CLI.EraBased.Commands.StakePool as Cmd +import Cardano.CLI.Run.Hash (getByteStringFromURL, httpsAndIpfsSchemas) import Cardano.CLI.Types.Common +import Cardano.CLI.Types.Errors.HashCmdError (HashCheckError (..)) import Cardano.CLI.Types.Errors.StakePoolCmdError import Cardano.CLI.Types.Key (readVerificationKeyOrFile) +import qualified Cardano.Crypto.Hash as L +import Control.Monad (when) import qualified Data.ByteString.Char8 as BS import Data.Function ((&)) +import Data.Maybe (fromMaybe) +import Data.Text (Text) +import Data.Text.Encoding (encodeUtf8) runStakePoolCmds :: () @@ -102,7 +108,7 @@ runStakePoolRegistrationCertificateCmd , stakePoolPledge = poolPledge , stakePoolOwners = stakePoolOwners' , stakePoolRelays = relays - , stakePoolMetadata = mMetadata + , stakePoolMetadata = pcaAnchor <$> mMetadata } let ledgerStakePoolParams = toShelleyPoolParams stakePoolParams @@ -111,6 +117,10 @@ runStakePoolRegistrationCertificateCmd shelleyBasedEraConstraints sbe ledgerStakePoolParams registrationCert = makeStakePoolRegistrationCertificate req + mapM_ + (firstExceptT StakePoolCmdMetadataHashCheckError . carryHashChecks) + mMetadata + firstExceptT StakePoolCmdWriteFileError . newExceptT $ writeLazyByteStringFile outFile @@ -237,3 +247,32 @@ runStakePoolMetadataHashCmd Just (File fpath) -> handleIOExceptT (StakePoolCmdWriteFileError . FileIOError fpath) $ BS.writeFile fpath (serialiseToRawBytesHex metadataHash) + +-- | 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 HashCheckError IO () +carryHashChecks potentiallyCheckedAnchor = + case pcaMustCheck potentiallyCheckedAnchor of + CheckHash -> do + let url = toUrl $ stakePoolMetadataURL anchor + anchorData <- + L.AnchorData + <$> withExceptT + FetchURLError + (getByteStringFromURL httpsAndIpfsSchemas url) + let hash = L.hashAnchorData anchorData + StakePoolMetadataHash expectedHash = stakePoolMetadataHash anchor + when (L.extractHash hash /= L.castHash expectedHash) $ + left $ + HashMismatchError (L.unsafeMakeSafeHash $ L.castHash expectedHash) hash + TrustHash -> pure () + where + anchor = pcaAnchor potentiallyCheckedAnchor + + toUrl :: Text -> L.Url + toUrl t = + let l = BS.length (encodeUtf8 t) + in fromMaybe (error "Internal Error: length of URL was miscalculated") $ L.textToUrl l t 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..e4aeeba998 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs @@ -11,11 +11,14 @@ where import Cardano.Api +import Cardano.CLI.Types.Errors.HashCmdError (HashCheckError) + data StakePoolCmdError = StakePoolCmdReadFileError !(FileError TextEnvelopeError) | StakePoolCmdReadKeyFileError !(FileError InputDecodeError) | StakePoolCmdWriteFileError !(FileError ()) | StakePoolCmdMetadataValidationError !StakePoolMetadataValidationError + | StakePoolCmdMetadataHashCheckError !HashCheckError deriving Show renderStakePoolCmdError :: StakePoolCmdError -> Doc ann @@ -28,3 +31,5 @@ renderStakePoolCmdError = \case prettyError fileErr StakePoolCmdWriteFileError fileErr -> prettyError fileErr + StakePoolCmdMetadataHashCheckError hashCheckErr -> + "Error checking stake pool metadata hash: " <> prettyException hashCheckErr 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 } From 81e3b43360d8763c78413e52fcfd3c2a41b1dc9e Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Wed, 9 Oct 2024 19:45:26 +0200 Subject: [PATCH 03/13] Implement tests for `stake-pool metadata-hash` with url --- .../cardano-cli-golden/files/golden/help.cli | 84 ++++++++++++++----- .../files/golden/help/allegra_stake-pool.cli | 4 +- .../help/allegra_stake-pool_metadata-hash.cli | 18 +++- .../files/golden/help/alonzo_stake-pool.cli | 4 +- .../help/alonzo_stake-pool_metadata-hash.cli | 18 +++- .../files/golden/help/babbage_stake-pool.cli | 4 +- .../help/babbage_stake-pool_metadata-hash.cli | 18 +++- .../files/golden/help/conway_stake-pool.cli | 4 +- .../help/conway_stake-pool_metadata-hash.cli | 18 +++- .../files/golden/help/latest_stake-pool.cli | 4 +- .../help/latest_stake-pool_metadata-hash.cli | 18 +++- .../files/golden/help/mary_stake-pool.cli | 4 +- .../help/mary_stake-pool_metadata-hash.cli | 18 +++- .../files/golden/help/shelley_stake-pool.cli | 4 +- .../help/shelley_stake-pool_metadata-hash.cli | 18 +++- .../Cli/Shelley/Certificates/StakePool.hs | 45 ++++++++++ 16 files changed, 227 insertions(+), 56 deletions(-) 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 04d87b120b..3b3f228024 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli @@ -1412,10 +1412,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 @@ -2480,10 +2486,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 @@ -3540,10 +3552,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 @@ -4611,10 +4629,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 @@ -5705,10 +5729,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 @@ -7606,10 +7636,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 @@ -9599,10 +9635,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..35b6940627 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/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..ebed9c9dc9 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/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..3d84af3cae 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/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..1bdf6013b4 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/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..f49f405298 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/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..5d29d63cef 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/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..feac899b38 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-test/Test/Cli/Shelley/Certificates/StakePool.hs b/cardano-cli/test/cardano-cli-test/Test/Cli/Shelley/Certificates/StakePool.hs index 88c27c8385..7bd52fe423 100644 --- 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 @@ -148,3 +148,48 @@ baseStakePoolCertificateHashCheck hash tempDir = do , registrationCertificate ] ) + +-- 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 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 exampleStakePoolMetadataHash + +baseStakePoolMetadataHashUrl + :: (MonadBaseControl IO m, MonadTest m, MonadIO m, MonadCatch m) + => 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 hash = do + let relativeUrl = ["ipfs", exampleStakePoolMetadataIpfsHash] + + -- Create temporary HTTP server with files required by the call to `cardano-cli` + -- In this case, the server emulates an IPFS gateway + serveFilesWhile + [ (relativeUrl, exampleStakePoolMetadataPathTest) + ] + ( \port -> do + void $ + execCardanoCLIWithEnvVars + [("IPFS_GATEWAY_URI", "http://localhost:" ++ show port ++ "/")] + [ "conway" + , "stake-pool" + , "metadata-hash" + , "--pool-metadata-url" + , "ipfs://" ++ exampleStakePoolMetadataIpfsHash + , "--expected-hash" + , hash + ] + ) From d56b6a9ea22fec94c60a0370b9c021722f85f249 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Wed, 9 Oct 2024 22:01:41 +0200 Subject: [PATCH 04/13] Implement negative test for metadata validation in `stake-pool metadata-hash` --- .../Cli/Shelley/Certificates/StakePool.hs | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) 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 index 7bd52fe423..8649aebd6f 100644 --- 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 @@ -8,7 +8,8 @@ import Control.Monad (void) import Control.Monad.Catch (MonadCatch) import Control.Monad.Trans.Control (MonadBaseControl) -import Test.Cardano.CLI.Hash (serveFilesWhile, tamperBase16Hash) +import Test.Cardano.CLI.Hash (exampleAnchorDataHash, exampleAnchorDataIpfsHash, + exampleAnchorDataPathTest, serveFilesWhile, tamperBase16Hash) import Test.Cardano.CLI.Util (execCardanoCLI, execCardanoCLIWithEnvVars, expectFailure, noteTempFile, propertyOnce) @@ -149,6 +150,17 @@ baseStakePoolCertificateHashCheck hash tempDir = do ] ) +-- 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 @@ -157,28 +169,39 @@ hprop_stake_pool_metadata_hash_url_wrong_hash_fails = -- 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 alteredHash + 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 exampleStakePoolMetadataHash + 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 hash = do - let relativeUrl = ["ipfs", exampleStakePoolMetadataIpfsHash] +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, exampleStakePoolMetadataPathTest) + [ (relativeUrl, metadataFile) ] ( \port -> do void $ @@ -188,7 +211,7 @@ baseStakePoolMetadataHashUrl hash = do , "stake-pool" , "metadata-hash" , "--pool-metadata-url" - , "ipfs://" ++ exampleStakePoolMetadataIpfsHash + , "ipfs://" ++ ipfsHash , "--expected-hash" , hash ] From 6a1d07b1f324e5112c03cd87fb551f4a2d3a38df Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Wed, 9 Oct 2024 21:02:47 +0200 Subject: [PATCH 05/13] Implement hash check and URL support in `stake-pool metadata-hash` --- .../CLI/EraBased/Commands/StakePool.hs | 21 ++++++++- .../Cardano/CLI/EraBased/Options/StakePool.hs | 42 ++++++++++++++++-- .../src/Cardano/CLI/EraBased/Run/StakePool.hs | 43 +++++++++++++------ .../CLI/Types/Errors/StakePoolCmdError.hs | 19 +++++++- 4 files changed, 107 insertions(+), 18 deletions(-) diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs index da07992688..f6f0adb001 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs @@ -9,10 +9,13 @@ module Cardano.CLI.EraBased.Commands.StakePool , StakePoolIdCmdArgs (..) , StakePoolMetadataHashCmdArgs (..) , StakePoolRegistrationCertificateCmdArgs (..) + , StakePoolMetadataSource (..) + , StakePoolMetadataHashGoal (..) ) where import Cardano.Api.Ledger (Coin) +import qualified Cardano.Api.Ledger as L import Cardano.Api.Shelley hiding (QueryInShelleyBasedEra (..)) import Cardano.CLI.Types.Common @@ -48,11 +51,25 @@ data StakePoolIdCmdArgs era data StakePoolMetadataHashCmdArgs era = StakePoolMetadataHashCmdArgs - { poolMetadataFile :: !(StakePoolMetadataFile In) - , mOutFile :: !(Maybe (File () Out)) + { poolMetadataSource :: !StakePoolMetadataSource + , hashGoal :: !StakePoolMetadataHashGoal } deriving Show +data StakePoolMetadataSource + = StakePoolMetadataFileIn !(StakePoolMetadataFile In) + | StakePoolMetadataURL !L.Url + deriving Show + +data StakePoolMetadataHashGoal + = -- | The hash is written to stdout + StakePoolMetadataHashToStdout + | -- | The hash to check against + CheckStakePoolMetadataHash !(Hash StakePoolMetadata) + | -- | The output file to which the hash is written + StakePoolMetadataHashToFile !(File () Out) + deriving Show + data StakePoolRegistrationCertificateCmdArgs era = StakePoolRegistrationCertificateCmdArgs { sbe :: !(ShelleyBasedEra era) diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs index d53f7b5a0a..52602280d7 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs @@ -12,10 +12,14 @@ module Cardano.CLI.EraBased.Options.StakePool where import Cardano.Api +import qualified Cardano.Api.Ledger as L +import Cardano.Api.Shelley (Hash (StakePoolMetadataHash)) import Cardano.CLI.Environment (EnvCli (..)) import qualified Cardano.CLI.EraBased.Commands.StakePool as Cmd import Cardano.CLI.EraBased.Options.Common +import Cardano.CLI.Read (readSafeHash) +import qualified Cardano.Crypto.Hash as L import Options.Applicative hiding (help, str) import qualified Options.Applicative as Opt @@ -42,7 +46,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 +68,37 @@ pStakePoolMetadataHashCmd pStakePoolMetadataHashCmd = fmap Cmd.StakePoolMetadataHashCmd $ Cmd.StakePoolMetadataHashCmdArgs - <$> pPoolMetadataFile - <*> pMaybeOutputFile + <$> pPoolMetadataSource + <*> pPoolMetadataHashGoal + +pPoolMetadataSource :: Parser Cmd.StakePoolMetadataSource +pPoolMetadataSource = + asum + [ Cmd.StakePoolMetadataFileIn <$> pPoolMetadataFile + , Cmd.StakePoolMetadataURL + <$> pUrl "pool-metadata-url" "URL pointing to the JSON Metadata file to hash." + ] + +pPoolMetadataHashGoal :: Parser Cmd.StakePoolMetadataHashGoal +pPoolMetadataHashGoal = + asum + [ Cmd.CheckStakePoolMetadataHash <$> pExpectedStakePoolMetadataHash + , Cmd.StakePoolMetadataHashToFile <$> pOutputFile + ] + <|> pure Cmd.StakePoolMetadataHashToStdout + +pExpectedStakePoolMetadataHash :: Parser (Hash StakePoolMetadata) +pExpectedStakePoolMetadataHash = + Opt.option (StakePoolMetadataHash . L.castHash . L.extractHash <$> readSafeHash) $ + mconcat + [ Opt.long "expected-hash" + , Opt.metavar "HASH" + , Opt.help $ + mconcat + [ "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." + ] + ] pStakePoolRegistrationCertificateCmd :: () diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs index ce483ed203..45ae9caf6a 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs @@ -19,16 +19,15 @@ import Cardano.Api.Shelley import Cardano.CLI.EraBased.Commands.StakePool import qualified Cardano.CLI.EraBased.Commands.StakePool as Cmd -import Cardano.CLI.Run.Hash (getByteStringFromURL, httpsAndIpfsSchemas) +import Cardano.CLI.Run.Hash (allSchemas, getByteStringFromURL, httpsAndIpfsSchemas) import Cardano.CLI.Types.Common -import Cardano.CLI.Types.Errors.HashCmdError (HashCheckError (..)) +import Cardano.CLI.Types.Errors.HashCmdError (FetchURLError (..), HashCheckError (..)) import Cardano.CLI.Types.Errors.StakePoolCmdError import Cardano.CLI.Types.Key (readVerificationKeyOrFile) import qualified Cardano.Crypto.Hash as L import Control.Monad (when) import qualified Data.ByteString.Char8 as BS -import Data.Function ((&)) import Data.Maybe (fromMaybe) import Data.Text (Text) import Data.Text.Encoding (encodeUtf8) @@ -231,22 +230,42 @@ 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 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 + CheckStakePoolMetadataHash expectedHash + | metadataHash /= expectedHash -> + left $ StakePoolCmdHashMismatchError expectedHash metadataHash + | otherwise -> liftIO $ putStrLn "Hashes match!" + StakePoolMetadataHashToFile outFile -> writeOutput (Just outFile) metadataHash + StakePoolMetadataHashToStdout -> 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. diff --git a/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs b/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs index e4aeeba998..ec2370ad23 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs @@ -10,8 +10,9 @@ module Cardano.CLI.Types.Errors.StakePoolCmdError where import Cardano.Api +import Cardano.Api.Shelley (Hash (StakePoolMetadataHash)) -import Cardano.CLI.Types.Errors.HashCmdError (HashCheckError) +import Cardano.CLI.Types.Errors.HashCmdError (FetchURLError, HashCheckError) data StakePoolCmdError = StakePoolCmdReadFileError !(FileError TextEnvelopeError) @@ -19,6 +20,12 @@ data StakePoolCmdError | StakePoolCmdWriteFileError !(FileError ()) | StakePoolCmdMetadataValidationError !StakePoolMetadataValidationError | StakePoolCmdMetadataHashCheckError !HashCheckError + | StakePoolCmdHashMismatchError + !(Hash StakePoolMetadata) + -- ^ Expected hash + !(Hash StakePoolMetadata) + -- ^ Actual hash + | StakePoolCmdFetchURLError !FetchURLError deriving Show renderStakePoolCmdError :: StakePoolCmdError -> Doc ann @@ -33,3 +40,13 @@ renderStakePoolCmdError = \case prettyError fileErr StakePoolCmdMetadataHashCheckError hashCheckErr -> "Error checking stake pool metadata hash: " <> prettyException hashCheckErr + 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 From 230e9caee08ccb47217c7e29a45477ca3fce45f1 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Wed, 9 Oct 2024 22:13:15 +0200 Subject: [PATCH 06/13] Implement negative test for metadata validation in `stake-pool registration certificate` --- .../Cli/Shelley/Certificates/StakePool.hs | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) 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 index 8649aebd6f..94617d6dea 100644 --- 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 @@ -27,6 +27,18 @@ exampleStakePoolMetadataPathTest = "test/cardano-cli-test/files/input/example_st 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 @@ -36,6 +48,8 @@ hprop_stake_pool_certificate_hash_check_wrong_hash_fails = alteredHash <- H.evalMaybe $ tamperBase16Hash exampleStakePoolMetadataHash -- We run the test with the modified hash baseStakePoolCertificateHashCheck + exampleStakePoolMetadataIpfsHash + exampleStakePoolMetadataPathTest alteredHash tempDir @@ -44,18 +58,26 @@ hprop_stake_pool_certificate_hash_check_wrong_hash_fails = 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 exampleStakePoolMetadataHash 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 hash tempDir = do +baseStakePoolCertificateHashCheck ipfsHash metadataFile hash tempDir = do -- Key filepaths coldVerKey <- noteTempFile tempDir "cold-verification-key-file" coldSignKey <- noteTempFile tempDir "cold-signing-key-file" @@ -110,12 +132,12 @@ baseStakePoolCertificateHashCheck hash tempDir = do H.assertFilesExist [vrfSignKey, vrfVerKey] - let relativeUrl = ["ipfs", exampleStakePoolMetadataIpfsHash] + 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, exampleStakePoolMetadataPathTest) + [ (relativeUrl, metadataFile) ] ( \port -> do -- Create stake pool registration certificate @@ -141,7 +163,7 @@ baseStakePoolCertificateHashCheck hash tempDir = do , "--pool-owner-stake-verification-key-file" , poolRewardAccountAndOwnerVerKey , "--metadata-url" - , "ipfs://" ++ exampleStakePoolMetadataIpfsHash + , "ipfs://" ++ ipfsHash , "--metadata-hash" , hash , "--check-metadata-hash" From 3b2987352e09d475a34d16a5f61f77419209d89d Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Wed, 9 Oct 2024 21:53:20 +0200 Subject: [PATCH 07/13] Implement metadata validation to `stake-pool registration-certificate` and simplify implementation --- .../src/Cardano/CLI/EraBased/Run/StakePool.hs | 32 ++++++++++--------- .../CLI/Types/Errors/StakePoolCmdError.hs | 5 +-- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs index 45ae9caf6a..132f861d85 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs @@ -21,10 +21,9 @@ 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 (..), HashCheckError (..)) +import Cardano.CLI.Types.Errors.HashCmdError (FetchURLError (..)) import Cardano.CLI.Types.Errors.StakePoolCmdError import Cardano.CLI.Types.Key (readVerificationKeyOrFile) -import qualified Cardano.Crypto.Hash as L import Control.Monad (when) import qualified Data.ByteString.Char8 as BS @@ -116,9 +115,7 @@ runStakePoolRegistrationCertificateCmd shelleyBasedEraConstraints sbe ledgerStakePoolParams registrationCert = makeStakePoolRegistrationCertificate req - mapM_ - (firstExceptT StakePoolCmdMetadataHashCheckError . carryHashChecks) - mMetadata + mapM_ carryHashChecks mMetadata firstExceptT StakePoolCmdWriteFileError . newExceptT @@ -272,21 +269,26 @@ runStakePoolMetadataHashCmd carryHashChecks :: PotentiallyCheckedAnchor StakePoolMetadataReference StakePoolMetadataReference -- ^ The information about anchor data and whether to check the hash (see 'PotentiallyCheckedAnchor') - -> ExceptT HashCheckError IO () + -> ExceptT StakePoolCmdError IO () carryHashChecks potentiallyCheckedAnchor = case pcaMustCheck potentiallyCheckedAnchor of CheckHash -> do let url = toUrl $ stakePoolMetadataURL anchor - anchorData <- - L.AnchorData - <$> withExceptT - FetchURLError - (getByteStringFromURL httpsAndIpfsSchemas url) - let hash = L.hashAnchorData anchorData - StakePoolMetadataHash expectedHash = stakePoolMetadataHash anchor - when (L.extractHash hash /= L.castHash expectedHash) $ + metadataBytes <- + withExceptT + StakePoolCmdFetchURLError + (getByteStringFromURL httpsAndIpfsSchemas url) + + let expectedHash = stakePoolMetadataHash anchor + + (_metadata, metadataHash) <- + firstExceptT StakePoolCmdMetadataValidationError + . hoistEither + $ validateAndHashStakePoolMetadata metadataBytes + + when (metadataHash /= expectedHash) $ left $ - HashMismatchError (L.unsafeMakeSafeHash $ L.castHash expectedHash) hash + StakePoolCmdHashMismatchError expectedHash metadataHash TrustHash -> pure () where anchor = pcaAnchor potentiallyCheckedAnchor diff --git a/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs b/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs index ec2370ad23..d3bdd9e20c 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Errors/StakePoolCmdError.hs @@ -12,14 +12,13 @@ where import Cardano.Api import Cardano.Api.Shelley (Hash (StakePoolMetadataHash)) -import Cardano.CLI.Types.Errors.HashCmdError (FetchURLError, HashCheckError) +import Cardano.CLI.Types.Errors.HashCmdError (FetchURLError) data StakePoolCmdError = StakePoolCmdReadFileError !(FileError TextEnvelopeError) | StakePoolCmdReadKeyFileError !(FileError InputDecodeError) | StakePoolCmdWriteFileError !(FileError ()) | StakePoolCmdMetadataValidationError !StakePoolMetadataValidationError - | StakePoolCmdMetadataHashCheckError !HashCheckError | StakePoolCmdHashMismatchError !(Hash StakePoolMetadata) -- ^ Expected hash @@ -38,8 +37,6 @@ renderStakePoolCmdError = \case prettyError fileErr StakePoolCmdWriteFileError fileErr -> prettyError fileErr - StakePoolCmdMetadataHashCheckError hashCheckErr -> - "Error checking stake pool metadata hash: " <> prettyException hashCheckErr StakePoolCmdHashMismatchError (StakePoolMetadataHash expectedHash) (StakePoolMetadataHash actualHash) -> From 69e3f81a24f5d11f8ab1c42d3b43ec9688bda089 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Wed, 9 Oct 2024 22:38:20 +0200 Subject: [PATCH 08/13] Implement golden test for failed hash check in `stake-pool metadata-hash` --- .../Test/Golden/Governance/StakeAddress.hs | 48 ++++++++++++++++++- ...ool_metadata_hash_url_wrong_hash_fails.out | 3 ++ .../input/example_stake_pool_metadata.json | 1 + 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 cardano-cli/test/cardano-cli-golden/files/golden/governance/stakeaddress/stake_pool_metadata_hash_url_wrong_hash_fails.out create mode 100644 cardano-cli/test/cardano-cli-golden/files/input/example_stake_pool_metadata.json 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..77501d55ae 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 metadata fails/"'@ +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/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 From 61314498fc0371d116cd6b9cdb6e9de45b510385 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Thu, 10 Oct 2024 19:36:31 +0200 Subject: [PATCH 09/13] Qualify `asum` call to ensure it compiles in ghc8107 Qualify `asum` call to ensure it compiles in ghc8107 --- cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs index 52602280d7..ae6ba5f713 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs @@ -21,6 +21,7 @@ import Cardano.CLI.EraBased.Options.Common import Cardano.CLI.Read (readSafeHash) import qualified Cardano.Crypto.Hash as L +import qualified Data.Foldable as F import Options.Applicative hiding (help, str) import qualified Options.Applicative as Opt @@ -73,7 +74,7 @@ pStakePoolMetadataHashCmd = pPoolMetadataSource :: Parser Cmd.StakePoolMetadataSource pPoolMetadataSource = - asum + F.asum [ Cmd.StakePoolMetadataFileIn <$> pPoolMetadataFile , Cmd.StakePoolMetadataURL <$> pUrl "pool-metadata-url" "URL pointing to the JSON Metadata file to hash." @@ -81,7 +82,7 @@ pPoolMetadataSource = pPoolMetadataHashGoal :: Parser Cmd.StakePoolMetadataHashGoal pPoolMetadataHashGoal = - asum + F.asum [ Cmd.CheckStakePoolMetadataHash <$> pExpectedStakePoolMetadataHash , Cmd.StakePoolMetadataHashToFile <$> pOutputFile ] From 2a233f6f339377eac16a97e73b6492b7c658938d Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Thu, 10 Oct 2024 19:37:31 +0200 Subject: [PATCH 10/13] Unify `HashGoal` with `DRepHashGoal` and `DRepHashGoal` --- cardano-cli/src/Cardano/CLI/Commands/Hash.hs | 6 +++--- .../CLI/EraBased/Commands/Governance/DRep.hs | 13 ++----------- .../src/Cardano/CLI/EraBased/Commands/StakePool.hs | 13 ++----------- .../Cardano/CLI/EraBased/Options/Governance/DRep.hs | 11 ++++++----- .../src/Cardano/CLI/EraBased/Options/StakePool.hs | 9 +++++---- .../src/Cardano/CLI/EraBased/Run/Governance/DRep.hs | 8 ++++---- .../src/Cardano/CLI/EraBased/Run/StakePool.hs | 7 ++++--- cardano-cli/src/Cardano/CLI/Options/Hash.hs | 4 +++- 8 files changed, 29 insertions(+), 42 deletions(-) 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 ed2eb1213a..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 @@ -87,7 +87,7 @@ data GovernanceDRepMetadataHashCmdArgs era = GovernanceDRepMetadataHashCmdArgs { eon :: !(ConwayEraOnwards era) , drepMetadataSource :: !DRepMetadataSource - , hashGoal :: !DRepHashGoal + , hashGoal :: !(HashGoal (Hash DRepMetadata)) } data DRepMetadataSource @@ -95,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 f6f0adb001..17987288c2 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Commands/StakePool.hs @@ -10,7 +10,6 @@ module Cardano.CLI.EraBased.Commands.StakePool , StakePoolMetadataHashCmdArgs (..) , StakePoolRegistrationCertificateCmdArgs (..) , StakePoolMetadataSource (..) - , StakePoolMetadataHashGoal (..) ) where @@ -18,6 +17,7 @@ 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 @@ -52,7 +52,7 @@ data StakePoolIdCmdArgs era data StakePoolMetadataHashCmdArgs era = StakePoolMetadataHashCmdArgs { poolMetadataSource :: !StakePoolMetadataSource - , hashGoal :: !StakePoolMetadataHashGoal + , hashGoal :: !(HashGoal (Hash StakePoolMetadata)) } deriving Show @@ -61,15 +61,6 @@ data StakePoolMetadataSource | StakePoolMetadataURL !L.Url deriving Show -data StakePoolMetadataHashGoal - = -- | The hash is written to stdout - StakePoolMetadataHashToStdout - | -- | The hash to check against - CheckStakePoolMetadataHash !(Hash StakePoolMetadata) - | -- | The output file to which the hash is written - StakePoolMetadataHashToFile !(File () Out) - deriving Show - data StakePoolRegistrationCertificateCmdArgs era = StakePoolRegistrationCertificateCmdArgs { sbe :: !(ShelleyBasedEra era) 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..84cbc7a8c6 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) @@ -210,13 +211,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 ae6ba5f713..08da22d32c 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs @@ -15,6 +15,7 @@ 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 @@ -80,13 +81,13 @@ pPoolMetadataSource = <$> pUrl "pool-metadata-url" "URL pointing to the JSON Metadata file to hash." ] -pPoolMetadataHashGoal :: Parser Cmd.StakePoolMetadataHashGoal +pPoolMetadataHashGoal :: Parser (Cmd.HashGoal (Hash StakePoolMetadata)) pPoolMetadataHashGoal = F.asum - [ Cmd.CheckStakePoolMetadataHash <$> pExpectedStakePoolMetadataHash - , Cmd.StakePoolMetadataHashToFile <$> pOutputFile + [ Cmd.CheckHash <$> pExpectedStakePoolMetadataHash + , Cmd.HashToFile <$> pOutputFile ] - <|> pure Cmd.StakePoolMetadataHashToStdout + <|> pure Cmd.HashToStdout pExpectedStakePoolMetadataHash :: Parser (Hash StakePoolMetadata) pExpectedStakePoolMetadataHash = 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 95afe33c18..a8644d579e 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 qualified Cardano.CLI.EraBased.Run.Key as Key import Cardano.CLI.Run.Hash (allSchemas, getByteStringFromURL, httpsAndIpfsSchemas) @@ -190,12 +190,12 @@ runGovernanceDRepMetadataHashCmd fetchURLToGovernanceCmdError $ getByteStringFromURL allSchemas 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 diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs index 132f861d85..44a03d84e2 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs @@ -17,6 +17,7 @@ where 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) @@ -245,12 +246,12 @@ runStakePoolMetadataHashCmd $ validateAndHashStakePoolMetadata metadataBytes case hashGoal of - CheckStakePoolMetadataHash expectedHash + Cmd.CheckHash expectedHash | metadataHash /= expectedHash -> left $ StakePoolCmdHashMismatchError expectedHash metadataHash | otherwise -> liftIO $ putStrLn "Hashes match!" - StakePoolMetadataHashToFile outFile -> writeOutput (Just outFile) metadataHash - StakePoolMetadataHashToStdout -> writeOutput Nothing metadataHash + 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 = diff --git a/cardano-cli/src/Cardano/CLI/Options/Hash.hs b/cardano-cli/src/Cardano/CLI/Options/Hash.hs index 7af0003f49..dad0249226 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,7 +39,7 @@ 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 From 67a0d7f0483590aacc8e0a4c6b170c3a90d42f35 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Thu, 10 Oct 2024 20:00:35 +0200 Subject: [PATCH 11/13] Unify code in `pExpectedHash`, `pExpectedDrepMetadataHash`, and `pExpectedStakePoolMetadataHash` --- .../src/Cardano/CLI/EraBased/Options/Common.hs | 13 ++++++++----- .../CLI/EraBased/Options/Governance/DRep.hs | 11 +---------- .../src/Cardano/CLI/EraBased/Options/StakePool.hs | 14 ++------------ cardano-cli/src/Cardano/CLI/Options/Hash.hs | 2 +- .../help/allegra_stake-pool_metadata-hash.cli | 2 +- .../help/alonzo_stake-pool_metadata-hash.cli | 2 +- .../help/babbage_stake-pool_metadata-hash.cli | 2 +- .../help/conway_governance_drep_metadata-hash.cli | 2 +- .../help/conway_stake-pool_metadata-hash.cli | 2 +- .../files/golden/help/hash_anchor-data.cli | 2 +- .../help/latest_governance_drep_metadata-hash.cli | 2 +- .../help/latest_stake-pool_metadata-hash.cli | 2 +- .../golden/help/mary_stake-pool_metadata-hash.cli | 2 +- .../help/shelley_stake-pool_metadata-hash.cli | 2 +- 14 files changed, 22 insertions(+), 38 deletions(-) diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs index 0fa7bf48a2..8a06224ba2 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs @@ -3550,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." ] ] 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 84cbc7a8c6..1297536d7c 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/DRep.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/DRep.hs @@ -135,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 = diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs index 08da22d32c..c2e8e912bd 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/StakePool.hs @@ -19,8 +19,7 @@ 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 Cardano.CLI.Read (readSafeHash) -import qualified Cardano.Crypto.Hash as L +import qualified Cardano.Ledger.SafeHash as L import qualified Data.Foldable as F import Options.Applicative hiding (help, str) @@ -91,16 +90,7 @@ pPoolMetadataHashGoal = pExpectedStakePoolMetadataHash :: Parser (Hash StakePoolMetadata) pExpectedStakePoolMetadataHash = - Opt.option (StakePoolMetadataHash . L.castHash . L.extractHash <$> readSafeHash) $ - mconcat - [ Opt.long "expected-hash" - , Opt.metavar "HASH" - , Opt.help $ - mconcat - [ "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." - ] - ] + pExpectedHash (StakePoolMetadataHash . L.extractHash . L.castSafeHash) "stake pool metadata" pStakePoolRegistrationCertificateCmd :: () diff --git a/cardano-cli/src/Cardano/CLI/Options/Hash.hs b/cardano-cli/src/Cardano/CLI/Options/Hash.hs index dad0249226..69ba88b6ca 100644 --- a/cardano-cli/src/Cardano/CLI/Options/Hash.hs +++ b/cardano-cli/src/Cardano/CLI/Options/Hash.hs @@ -42,7 +42,7 @@ pHashAnchorDataCmd = do 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/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 35b6940627..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 @@ -13,7 +13,7 @@ Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. - --expected-hash HASH Expected hash for the stake pool metadata for + --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. 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 ebed9c9dc9..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 @@ -13,7 +13,7 @@ Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. - --expected-hash HASH Expected hash for the stake pool metadata for + --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. 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 3d84af3cae..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 @@ -13,7 +13,7 @@ Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. - --expected-hash HASH Expected hash for the stake pool metadata for + --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. 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_metadata-hash.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_stake-pool_metadata-hash.cli index 1bdf6013b4..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 @@ -13,7 +13,7 @@ Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. - --expected-hash HASH Expected hash for the stake pool metadata for + --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. 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_metadata-hash.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/latest_stake-pool_metadata-hash.cli index f49f405298..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 @@ -13,7 +13,7 @@ Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. - --expected-hash HASH Expected hash for the stake pool metadata for + --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. 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 5d29d63cef..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 @@ -13,7 +13,7 @@ Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. - --expected-hash HASH Expected hash for the stake pool metadata for + --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. 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 feac899b38..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 @@ -13,7 +13,7 @@ Available options: --pool-metadata-file FILEPATH Filepath of the pool metadata. --pool-metadata-url TEXT URL pointing to the JSON Metadata file to hash. - --expected-hash HASH Expected hash for the stake pool metadata for + --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. From c68d32c3050979fbeb4ee28a1dd57667245ed420 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Thu, 10 Oct 2024 20:05:18 +0200 Subject: [PATCH 12/13] Fix instructions in comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Clément Hurlin --- .../cardano-cli-golden/Test/Golden/Governance/StakeAddress.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 77501d55ae..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 @@ -236,7 +236,7 @@ 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 metadata fails/"'@ +-- @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 From ddfa0a2a621c4072374f81591e6a0d06eb66f593 Mon Sep 17 00:00:00 2001 From: Pablo Lamela Date: Thu, 10 Oct 2024 20:13:21 +0200 Subject: [PATCH 13/13] Remove `toUrl` function --- .../Cardano/CLI/EraBased/Run/Governance/Actions.hs | 2 +- .../Cardano/CLI/EraBased/Run/Governance/DRep.hs | 4 ++-- .../src/Cardano/CLI/EraBased/Run/StakePool.hs | 14 +++----------- cardano-cli/src/Cardano/CLI/Run/Hash.hs | 7 ++++--- 4 files changed, 10 insertions(+), 17 deletions(-) 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 a8644d579e..b00dfbaf17 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/DRep.hs @@ -187,7 +187,7 @@ 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 Cmd.CheckHash expectedHash @@ -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 44a03d84e2..15ea5d6e59 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/StakePool.hs @@ -28,9 +28,6 @@ import Cardano.CLI.Types.Key (readVerificationKeyOrFile) import Control.Monad (when) import qualified Data.ByteString.Char8 as BS -import Data.Maybe (fromMaybe) -import Data.Text (Text) -import Data.Text.Encoding (encodeUtf8) runStakePoolCmds :: () @@ -238,7 +235,7 @@ runStakePoolMetadataHashCmd . newExceptT $ readByteStringFile poolMetadataFile StakePoolMetadataURL urlText -> - fetchURLToStakePoolCmdError $ getByteStringFromURL allSchemas urlText + fetchURLToStakePoolCmdError $ getByteStringFromURL allSchemas $ L.urlToText urlText (_metadata, metadataHash) <- firstExceptT StakePoolCmdMetadataValidationError @@ -274,11 +271,11 @@ carryHashChecks carryHashChecks potentiallyCheckedAnchor = case pcaMustCheck potentiallyCheckedAnchor of CheckHash -> do - let url = toUrl $ stakePoolMetadataURL anchor + let urlText = stakePoolMetadataURL anchor metadataBytes <- withExceptT StakePoolCmdFetchURLError - (getByteStringFromURL httpsAndIpfsSchemas url) + (getByteStringFromURL httpsAndIpfsSchemas urlText) let expectedHash = stakePoolMetadataHash anchor @@ -293,8 +290,3 @@ carryHashChecks potentiallyCheckedAnchor = TrustHash -> pure () where anchor = pcaAnchor potentiallyCheckedAnchor - - toUrl :: Text -> L.Url - toUrl t = - let l = BS.length (encodeUtf8 t) - in fromMaybe (error "Internal Error: length of URL was miscalculated") $ L.textToUrl l t 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:"