diff --git a/.gitattributes b/.gitattributes index e6ade18bba..eb84872b79 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ +cardano-cli/test/cardano-cli-golden/files/input/example_anchor_data.txt -text cardano-cli/test/cardano-cli-test/files/input/example_anchor_data.txt -text diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 322d2bcd7d..788a98e1c9 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -289,6 +289,7 @@ library cardano-cli-test-lib hs-source-dirs: test/cardano-cli-test-lib exposed-modules: Test.Cardano.CLI.Aeson + Test.Cardano.CLI.Hash Test.Cardano.CLI.Util build-depends: @@ -303,12 +304,17 @@ library cardano-cli-test-lib filepath, hedgehog, hedgehog-extras ^>=0.6.1.0, + http-types, lifted-base, monad-control, + network, process, text, transformers-base, + utf8-string, vector, + wai, + warp, test-suite cardano-cli-test import: project-config @@ -331,10 +337,6 @@ test-suite cardano-cli-test filepath, hedgehog, hedgehog-extras ^>=0.6.1.0, - http-types, - lifted-base, - monad-control, - network, parsec, regex-tdfa, tasty, @@ -342,13 +344,11 @@ test-suite cardano-cli-test text, time, transformers, - utf8-string, - wai, - warp, build-tool-depends: tasty-discover:tasty-discover other-modules: Test.Cli.AddCostModels + Test.Cli.CreateCardano Test.Cli.CreateTestnetData Test.Cli.FilePermissions Test.Cli.Governance.DRep @@ -398,10 +398,12 @@ test-suite cardano-cli-golden cborg, containers, directory, + exceptions, extra, filepath, hedgehog ^>=1.4, hedgehog-extras ^>=0.6.1.0, + monad-control, regex-compat, regex-tdfa, tasty, diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Actions.hs b/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Actions.hs index 872a679d70..04a5ffad05 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Actions.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Commands/Governance/Actions.hs @@ -84,6 +84,7 @@ data GovernanceActionInfoCmdArgs era , returnStakeAddress :: !StakeIdentifier , proposalUrl :: !ProposalUrl , proposalHash :: !(L.SafeHash L.StandardCrypto L.AnchorData) + , checkProposalHash :: !(MustCheckHash ProposalUrl) , outFile :: !(File () Out) } deriving Show diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Actions.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Actions.hs index c505b1b7bc..24d48236a4 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Actions.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/Governance/Actions.hs @@ -74,9 +74,26 @@ pGovernanceActionNewInfoCmd era = do <*> pStakeIdentifier (Just "deposit-return") <*> pAnchorUrl <*> pAnchorDataHash + <*> pMustCheckProposalHash <*> pFileOutDirection "out-file" "Path to action file to be used later on with build or build-raw " ) $ Opt.progDesc "Create an info action." + where + pMustCheckProposalHash :: Parser (MustCheckHash ProposalUrl) + pMustCheckProposalHash = + asum + [ Opt.flag' CheckHash $ + mconcat + [ Opt.long "check-anchor-data" + , Opt.help + "Check the proposal hash (from --anchor-data-hash) by downloading anchor data (from --anchor-url)." + ] + , Opt.flag' TrustHash $ + mconcat + [ Opt.long "trust-anchor-data" + , Opt.help "Do not check the proposal hash (from --anchor-data-hash) and trust it is correct." + ] + ] pGovernanceActionNewConstitutionCmd :: CardanoEra era 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 b572ee2794..5d0bdc56da 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Actions.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/Governance/Actions.hs @@ -21,8 +21,10 @@ import Cardano.CLI.EraBased.Commands.Governance.Actions import qualified Cardano.CLI.EraBased.Commands.Governance.Actions as Cmd import Cardano.CLI.Json.Friendly import Cardano.CLI.Read +import Cardano.CLI.Run.Hash (getByteStringFromURL, httpsAndIpfsSchemas) import Cardano.CLI.Types.Common import Cardano.CLI.Types.Errors.GovernanceActionsError +import Cardano.CLI.Types.Errors.HashCmdError (FetchURLError) import Cardano.CLI.Types.Key import Control.Monad @@ -86,6 +88,7 @@ runGovernanceActionInfoCmd , Cmd.returnStakeAddress , Cmd.proposalUrl , Cmd.proposalHash + , Cmd.checkProposalHash , Cmd.outFile } = do depositStakeCredential <- @@ -98,6 +101,19 @@ runGovernanceActionInfoCmd , L.anchorDataHash = proposalHash } + case checkProposalHash of + CheckHash -> do + anchorData <- + L.AnchorData + <$> fetchURLErrorToGovernanceActionError + ProposalCheck + (getByteStringFromURL httpsAndIpfsSchemas $ L.anchorUrl proposalAnchor) + let hash = L.hashAnchorData anchorData + when (hash /= L.anchorDataHash proposalAnchor) $ + left $ + GovernanceActionsProposalMismatchedHashError ProposalCheck proposalHash hash + TrustHash -> pure () + let sbe = conwayEraOnwardsToShelleyBasedEra eon govAction = InfoAct proposalProcedure = createProposalProcedure sbe networkId deposit depositStakeCredential govAction proposalAnchor @@ -105,6 +121,10 @@ runGovernanceActionInfoCmd firstExceptT GovernanceActionsCmdWriteFileError . newExceptT $ conwayEraOnwardsConstraints eon $ writeFileTextEnvelope outFile (Just "Info proposal") proposalProcedure + where + fetchURLErrorToGovernanceActionError + :: AnchorDataTypeCheck -> ExceptT FetchURLError IO a -> ExceptT GovernanceActionsError IO a + fetchURLErrorToGovernanceActionError adt = withExceptT (GovernanceActionsProposalFetchURLError adt) -- TODO: Conway era - update with new ledger types from cardano-ledger-conway-1.7.0.0 runGovernanceActionCreateNoConfidenceCmd diff --git a/cardano-cli/src/Cardano/CLI/Run/Hash.hs b/cardano-cli/src/Cardano/CLI/Run/Hash.hs index a8b2ee6744..4add99eab0 100644 --- a/cardano-cli/src/Cardano/CLI/Run/Hash.hs +++ b/cardano-cli/src/Cardano/CLI/Run/Hash.hs @@ -8,6 +8,10 @@ module Cardano.CLI.Run.Hash ( runHashCmds + , getByteStringFromURL + , SupportedSchemas (..) + , allSchemas + , httpsAndIpfsSchemas ) where @@ -25,6 +29,7 @@ import Control.Monad.Catch (Exception, Handler (Handler)) import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BS8 import qualified Data.ByteString.Lazy as BSL +import qualified Data.ByteString.Lazy.Char8 as BSL8 import Data.Char (toLower) import Data.Function import Data.List (intercalate) @@ -63,7 +68,7 @@ runHashAnchorDataCmd Cmd.HashAnchorDataCmdArgs{toHash, hashGoal} = do return $ Text.encodeUtf8 text Cmd.AnchorDataHashSourceText text -> return $ Text.encodeUtf8 text Cmd.AnchorDataHashSourceURL urlText -> - getByteStringFromURL urlText + fetchURLToHashCmdError $ getByteStringFromURL allSchemas urlText let hash = L.hashAnchorData anchorData case hashGoal of CheckHash expectedHash @@ -82,66 +87,84 @@ runHashAnchorDataCmd Cmd.HashAnchorDataCmdArgs{toHash, hashGoal} = do where text = hashToTextAsHex . L.extractHash $ hash - getByteStringFromURL :: L.Url -> ExceptT HashCmdError IO BS.ByteString - getByteStringFromURL urlText = do - let urlString = Text.unpack $ L.urlToText urlText - uri <- hoistMaybe (HashInvalidURLError urlString) $ parseAbsoluteURI urlString - case map toLower $ uriScheme uri of - "file:" -> - let path = uriPathToFilePath (pathSegments uri) - in handleIOExceptT (HashReadFileError path) $ BS.readFile path - "http:" -> getFileFromHttp uri - "https:" -> getFileFromHttp uri - "ipfs:" -> do - httpUri <- convertToHttp uri - getFileFromHttp httpUri - unsupportedScheme -> left $ HashUnsupportedURLSchemeError unsupportedScheme - where - uriPathToFilePath :: [String] -> FilePath - uriPathToFilePath allPath@(letter : path) = - if isDrive letter - then foldl () letter path - else foldl () "/" allPath - uriPathToFilePath [] = "/" + fetchURLToHashCmdError + :: ExceptT FetchURLError IO BS8.ByteString -> ExceptT HashCmdError IO BS8.ByteString + fetchURLToHashCmdError = withExceptT HashFetchURLError + +data SupportedSchemas = FileSchema | HttpSchema | HttpsSchema | IpfsSchema + deriving (Show, Eq) - getFileFromHttp :: URI -> ExceptT HashCmdError IO BS.ByteString - getFileFromHttp uri = handlesExceptT handlers $ liftIO $ do - request <- requestFromURI uri - manager <- newManager tlsManagerSettings - response <- httpLbs request manager - let status = responseStatus response - if statusCode status /= 200 - then throw $ BadStatusCodeHRE (statusCode status) (BS8.unpack $ statusMessage status) - else return $ BS.concat . BSL.toChunks $ responseBody response +allSchemas :: [SupportedSchemas] +allSchemas = [FileSchema, HttpSchema, HttpsSchema, IpfsSchema] - handlers :: [Handler IO HashCmdError] - handlers = - [ mkHandler id - , mkHandler HttpExceptionHRE - , mkHandler IOExceptionHRE - ] - where - mkHandler :: (Monad m, Exception e) => (e -> HttpRequestError) -> Handler m HashCmdError - mkHandler x = Handler $ return . HashGetFileFromHttpError . x +httpsAndIpfsSchemas :: [SupportedSchemas] +httpsAndIpfsSchemas = [HttpsSchema, IpfsSchema] + +getByteStringFromURL :: [SupportedSchemas] -> L.Url -> ExceptT FetchURLError IO BS.ByteString +getByteStringFromURL supportedSchemas urlText = do + let urlString = Text.unpack $ L.urlToText urlText + uri <- hoistMaybe (FetchURLInvalidURLError urlString) $ parseAbsoluteURI urlString + case map toLower $ uriScheme uri of + "file:" + | FileSchema `elem` supportedSchemas -> + let path = uriPathToFilePath (pathSegments uri) + in handleIOExceptT (FetchURLReadFileError path) $ BS.readFile path + "http:" | HttpSchema `elem` supportedSchemas -> getFileFromHttp uri + "https:" | HttpsSchema `elem` supportedSchemas -> getFileFromHttp uri + "ipfs:" | IpfsSchema `elem` supportedSchemas -> do + httpUri <- convertToHttp uri + getFileFromHttp httpUri + unsupportedScheme -> left $ FetchURLUnsupportedURLSchemeError unsupportedScheme + where + uriPathToFilePath :: [String] -> FilePath + uriPathToFilePath allPath@(letter : path) = + if isDrive letter + then foldl () letter path + else foldl () "/" allPath + uriPathToFilePath [] = "/" + + getFileFromHttp :: URI -> ExceptT FetchURLError IO BS.ByteString + getFileFromHttp uri = handlesExceptT handlers $ liftIO $ do + request <- requestFromURI uri + manager <- newManager tlsManagerSettings + response <- httpLbs request manager + let status = responseStatus response + if statusCode status /= 200 + then + throw $ + BadStatusCodeHRE + (statusCode status) + (BS8.unpack (statusMessage status) ++ ": " ++ BSL8.unpack (responseBody response)) + else return $ BS.concat . BSL.toChunks $ responseBody response + + handlers :: [Handler IO FetchURLError] + handlers = + [ mkHandler id + , mkHandler HttpExceptionHRE + , mkHandler IOExceptionHRE + ] + where + mkHandler :: (Monad m, Exception e) => (e -> HttpRequestError) -> Handler m FetchURLError + mkHandler x = Handler $ return . FetchURLGetFileFromHttpError . x -convertToHttp :: URI -> ExceptT HashCmdError IO URI -convertToHttp ipfsUri = do - mIpfsGatewayUriString <- handleIOExceptT HashReadEnvVarError $ IO.lookupEnv "IPFS_GATEWAY_URI" - ipfsGatewayUriString <- hoistMaybe HashIpfsGatewayNotSetError mIpfsGatewayUriString - ipfsGatewayUri <- - hoistMaybe (HashInvalidURLError ipfsGatewayUriString) $ parseAbsoluteURI ipfsGatewayUriString - return $ - ipfsGatewayUri - { uriPath = - '/' - : intercalate - "/" - ( pathSegments ipfsGatewayUri - ++ ["ipfs"] - ++ maybe [] (\ipfsAuthority -> [uriRegName ipfsAuthority]) (uriAuthority ipfsUri) - ++ pathSegments ipfsUri - ) - } + convertToHttp :: URI -> ExceptT FetchURLError IO URI + convertToHttp ipfsUri = do + mIpfsGatewayUriString <- handleIOExceptT FetchURLReadEnvVarError $ IO.lookupEnv "IPFS_GATEWAY_URI" + ipfsGatewayUriString <- hoistMaybe FetchURLIpfsGatewayNotSetError mIpfsGatewayUriString + ipfsGatewayUri <- + hoistMaybe (FetchURLInvalidURLError ipfsGatewayUriString) $ parseAbsoluteURI ipfsGatewayUriString + return $ + ipfsGatewayUri + { uriPath = + '/' + : intercalate + "/" + ( pathSegments ipfsGatewayUri + ++ ["ipfs"] + ++ maybe [] (\ipfsAuthority -> [uriRegName ipfsAuthority]) (uriAuthority ipfsUri) + ++ pathSegments ipfsUri + ) + } runHashScriptCmd :: () diff --git a/cardano-cli/src/Cardano/CLI/Types/Common.hs b/cardano-cli/src/Cardano/CLI/Types/Common.hs index ac8229ba10..9639f606a4 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Common.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Common.hs @@ -31,6 +31,7 @@ module Cardano.CLI.Types.Common , InputTxBodyOrTxFile (..) , KeyOutputFormat (..) , MetadataFile (..) + , MustCheckHash (..) , OpCertCounter , OpCertCounterFile , OpCertEndingKesPeriod (..) @@ -639,3 +640,8 @@ data ParserFileDirection = Input | Output deriving (Eq, Show) + +data MustCheckHash a + = CheckHash + | TrustHash + deriving (Eq, Show) diff --git a/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceActionsError.hs b/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceActionsError.hs index 8064a5a9f3..da527669c2 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceActionsError.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Errors/GovernanceActionsError.hs @@ -2,14 +2,19 @@ module Cardano.CLI.Types.Errors.GovernanceActionsError ( GovernanceActionsError (..) + , AnchorDataTypeCheck (..) ) where import Cardano.Api +import qualified Cardano.Api.Ledger as L import Cardano.CLI.Read +import Cardano.CLI.Types.Errors.HashCmdError (FetchURLError) import Cardano.CLI.Types.Errors.StakeCredentialError +import Control.Exception (displayException) + data GovernanceActionsError = GovernanceActionsCmdConstitutionError ConstitutionError | GovernanceActionsCmdProposalError ProposalError @@ -19,6 +24,18 @@ data GovernanceActionsError | GovernanceActionsCmdReadTextEnvelopeFileError (FileError TextEnvelopeError) | GovernanceActionsCmdWriteFileError (FileError ()) | GovernanceActionsValueUpdateProtocolParametersNotFound AnyShelleyBasedEra + | GovernanceActionsProposalMismatchedHashError + AnchorDataTypeCheck + -- ^ Type of anchor data that we were checking + !(L.SafeHash L.StandardCrypto L.AnchorData) + -- ^ Expected hash + !(L.SafeHash L.StandardCrypto L.AnchorData) + -- ^ Actual hash + | GovernanceActionsProposalFetchURLError + AnchorDataTypeCheck + -- ^ Type of anchor data that we were checking + FetchURLError + -- ^ Error that occurred while fetching the anchor data deriving Show instance Error GovernanceActionsError where @@ -39,3 +56,22 @@ instance Error GovernanceActionsError where "Protocol parameters update value for" <+> pretty expectedShelleyEra <+> "was not found." GovernanceActionsReadStakeCredErrror e -> prettyError e + GovernanceActionsProposalMismatchedHashError adt expectedHash actualHash -> + "Hashes do not match while checking" + <+> pretty (anchorDataTypeCheckName adt) + <+> "hashes!" + <> "\nExpected:" + <+> pretty (show (L.extractHash expectedHash)) + <> "\n Actual:" + <+> pretty (show (L.extractHash actualHash)) + GovernanceActionsProposalFetchURLError adt fetchErr -> + "Error while checking" + <+> pretty (anchorDataTypeCheckName adt) + <+> "hash:" + <+> pretty (displayException fetchErr) + +data AnchorDataTypeCheck = ProposalCheck + deriving Show + +anchorDataTypeCheckName :: AnchorDataTypeCheck -> String +anchorDataTypeCheckName ProposalCheck = "proposal" diff --git a/cardano-cli/src/Cardano/CLI/Types/Errors/HashCmdError.hs b/cardano-cli/src/Cardano/CLI/Types/Errors/HashCmdError.hs index 5c8420b093..45b065425d 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Errors/HashCmdError.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Errors/HashCmdError.hs @@ -4,6 +4,7 @@ module Cardano.CLI.Types.Errors.HashCmdError ( HashCmdError (..) , HttpRequestError (..) + , FetchURLError (..) ) where @@ -25,32 +26,44 @@ data HashCmdError | HashReadFileError !FilePath !IOException | HashWriteFileError !(FileError ()) | HashReadScriptError !FilePath !(FileError ScriptDecodeError) - | HashInvalidURLError !String - | HashReadEnvVarError !IOException - | HashIpfsGatewayNotSetError - | HashUnsupportedURLSchemeError !String - | HashGetFileFromHttpError !HttpRequestError + | HashFetchURLError !FetchURLError deriving Show instance Error HashCmdError where prettyError = \case HashMismatchedHashError expectedHash actualHash -> - "Hashes do not match! \n" - <> "Expected: " - <> pretty (show (extractHash expectedHash)) - <> "\n Actual: " - <> pretty (show (extractHash actualHash)) + "Hashes do not match!" + <> "\nExpected:" + <+> pretty (show (extractHash expectedHash)) + <> "\n Actual:" + <+> pretty (show (extractHash actualHash)) HashReadFileError filepath exc -> - "Cannot read " <> pretty filepath <> ": " <> pretty (displayException exc) + "Cannot read" <+> pretty filepath <> ":" <+> pretty (displayException exc) HashWriteFileError fileErr -> prettyError fileErr HashReadScriptError filepath err -> - "Cannot read script at " <> pretty filepath <> ": " <> prettyError err - HashInvalidURLError text -> "Cannot parse URI: " <> pretty text - HashUnsupportedURLSchemeError text -> "Unsupported URL scheme: " <> pretty text - HashReadEnvVarError exc -> "Cannot read environment variable: " <> pretty (displayException exc) - HashIpfsGatewayNotSetError -> "IPFS schema requires IPFS_GATEWAY_URI environment variable to be set." - HashGetFileFromHttpError err -> pretty $ displayException err + "Cannot read script at" <+> pretty filepath <> ":" <+> prettyError err + HashFetchURLError fetchErr -> + pretty (displayException fetchErr) + +data FetchURLError + = FetchURLInvalidURLError !String + | FetchURLReadFileError !FilePath !IOException + | FetchURLUnsupportedURLSchemeError !String + | FetchURLReadEnvVarError !IOException + | FetchURLGetFileFromHttpError !HttpRequestError + | FetchURLIpfsGatewayNotSetError + deriving Show + +instance Exception FetchURLError where + displayException :: FetchURLError -> String + displayException (FetchURLInvalidURLError text) = "Cannot parse URI: " <> text + displayException (FetchURLReadFileError filepath exc) = + "Cannot read " <> filepath <> ": " <> displayException exc + displayException (FetchURLUnsupportedURLSchemeError text) = "Unsupported URL scheme: " <> text + displayException (FetchURLReadEnvVarError exc) = "Cannot read environment variable: " <> displayException exc + displayException (FetchURLGetFileFromHttpError err) = displayException err + displayException FetchURLIpfsGatewayNotSetError = "IPFS schema requires IPFS_GATEWAY_URI environment variable to be set." data HttpRequestError = BadStatusCodeHRE !Int !String diff --git a/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Action.hs b/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Action.hs index 317b7a43f1..1f7b05cc56 100644 --- a/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Action.hs +++ b/cardano-cli/test/cardano-cli-golden/Test/Golden/Governance/Action.hs @@ -1,13 +1,22 @@ +{-# LANGUAGE FlexibleContexts #-} {- HLINT ignore "Use camelCase" -} +{-# LANGUAGE ScopedTypeVariables #-} module Test.Golden.Governance.Action where +import Cardano.Api (MonadIO) + import Control.Monad (void) +import Control.Monad.Catch (MonadCatch) +import Control.Monad.Trans.Control (MonadBaseControl) +import Test.Cardano.CLI.Hash (exampleAnchorDataHash, exampleAnchorDataIpfsHash, + exampleAnchorDataPathGolden, serveFileWhile) import qualified Test.Cardano.CLI.Util as H -import Test.Cardano.CLI.Util +import Test.Cardano.CLI.Util (execCardanoCLI, execCardanoCLIWithEnvVars, expectFailure, + noteInputFile, noteTempFile, propertyOnce) -import Hedgehog (Property) +import Hedgehog (MonadTest, Property) import qualified Hedgehog.Extras as H import qualified Hedgehog.Extras.Test.Golden as H @@ -186,47 +195,66 @@ hprop_golden_conway_governance_action_view_update_committee_yaml = ] H.diffVsGoldenFile actionView goldenActionViewFile +hprop_golden_conway_governance_action_view_create_info_json_outfile_wrong_hash_fails :: Property +hprop_golden_conway_governance_action_view_create_info_json_outfile_wrong_hash_fails = + propertyOnce . expectFailure . H.moduleWorkspace "tmp" $ \tempDir -> + base_golden_conway_governance_action_view_create_info_json_outfile + ('a' : drop 1 exampleAnchorDataHash) + tempDir + hprop_golden_conway_governance_action_view_create_info_json_outfile :: Property hprop_golden_conway_governance_action_view_create_info_json_outfile = - propertyOnce . H.moduleWorkspace "tmp" $ \tempDir -> do - stakeAddressVKeyFile <- H.note "test/cardano-cli-golden/files/input/governance/stake-address.vkey" - - actionFile <- noteTempFile tempDir "action" - - void $ - execCardanoCLI - [ "conway" - , "governance" - , "action" - , "create-info" - , "--testnet" - , "--governance-action-deposit" - , "10" - , "--deposit-return-stake-verification-key-file" - , stakeAddressVKeyFile - , "--anchor-url" - , "proposal-dummy-url" - , "--anchor-data-hash" - , "c7ddb5b493faa4d3d2d679847740bdce0c5d358d56f9b1470ca67f5652a02745" - , "--out-file" - , actionFile - ] - - actionViewFile <- noteTempFile tempDir "action-view" - goldenActionViewFile <- - H.note "test/cardano-cli-golden/files/golden/governance/action/view/create-info.action.view" - void $ - execCardanoCLI - [ "conway" - , "governance" - , "action" - , "view" - , "--action-file" - , actionFile - , "--out-file" - , actionViewFile - ] - H.diffFileVsGoldenFile actionViewFile goldenActionViewFile + propertyOnce . H.moduleWorkspace "tmp" $ \tempDir -> + base_golden_conway_governance_action_view_create_info_json_outfile exampleAnchorDataHash tempDir + +base_golden_conway_governance_action_view_create_info_json_outfile + :: (MonadBaseControl IO m, MonadTest m, MonadIO m, MonadCatch m) => String -> FilePath -> m () +base_golden_conway_governance_action_view_create_info_json_outfile hash tempDir = do + stakeAddressVKeyFile <- H.note "test/cardano-cli-golden/files/input/governance/stake-address.vkey" + + actionFile <- noteTempFile tempDir "action" + let relativeUrl = ["ipfs", exampleAnchorDataIpfsHash] + serveFileWhile + relativeUrl + exampleAnchorDataPathGolden + ( \port -> do + void $ + execCardanoCLIWithEnvVars + [("IPFS_GATEWAY_URI", "http://localhost:" ++ show port ++ "/")] + [ "conway" + , "governance" + , "action" + , "create-info" + , "--testnet" + , "--governance-action-deposit" + , "10" + , "--deposit-return-stake-verification-key-file" + , stakeAddressVKeyFile + , "--anchor-url" + , "ipfs://" ++ exampleAnchorDataIpfsHash + , "--anchor-data-hash" + , hash + , "--check-anchor-data" + , "--out-file" + , actionFile + ] + ) + + actionViewFile <- noteTempFile tempDir "action-view" + goldenActionViewFile <- + H.note "test/cardano-cli-golden/files/golden/governance/action/view/create-info.action.view" + void $ + execCardanoCLI + [ "conway" + , "governance" + , "action" + , "view" + , "--action-file" + , actionFile + , "--out-file" + , actionViewFile + ] + H.diffFileVsGoldenFile actionViewFile goldenActionViewFile hprop_golden_governanceActionCreateNoConfidence :: Property hprop_golden_governanceActionCreateNoConfidence = diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/governance/action/view/create-info.action.view b/cardano-cli/test/cardano-cli-golden/files/golden/governance/action/view/create-info.action.view index 6ffc55b5cd..70fa003dba 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/governance/action/view/create-info.action.view +++ b/cardano-cli/test/cardano-cli-golden/files/golden/governance/action/view/create-info.action.view @@ -1,7 +1,7 @@ { "anchor": { - "dataHash": "c7ddb5b493faa4d3d2d679847740bdce0c5d358d56f9b1470ca67f5652a02745", - "url": "proposal-dummy-url" + "dataHash": "de38a4f5b8b9d8372386cc923bad19d1a0662298cf355bbe947e5eedf127fa9c", + "url": "ipfs://QmbL5EBFJLf8DdPkWAskG3Euin9tHY8naqQ2JDoHnWHHXJ" }, "deposit": 10, "governance action": { 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 1c23f5bcb7..d100e862c8 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli @@ -5975,6 +5975,9 @@ Usage: cardano-cli conway governance action create-info (--mainnet | --testnet) ) --anchor-url TEXT --anchor-data-hash HASH + ( --check-anchor-data + | --trust-anchor-data + ) --out-file FILEPATH Create an info action. diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_action_create-info.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_action_create-info.cli index 78e48f1feb..4a7fc78709 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_action_create-info.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_governance_action_create-info.cli @@ -8,6 +8,9 @@ Usage: cardano-cli conway governance action create-info (--mainnet | --testnet) ) --anchor-url TEXT --anchor-data-hash HASH + ( --check-anchor-data + | --trust-anchor-data + ) --out-file FILEPATH Create an info action. @@ -30,6 +33,10 @@ Available options: --anchor-url TEXT Anchor URL --anchor-data-hash HASH Proposal anchor data hash (obtain it with "cardano-cli hash anchor-data ...") + --check-anchor-data Check the proposal hash (from --anchor-data-hash) by + downloading anchor data (from --anchor-url). + --trust-anchor-data Do not check the proposal hash (from + --anchor-data-hash) and trust it is correct. --out-file FILEPATH Path to action file to be used later on with build or build-raw -h,--help Show this help text diff --git a/cardano-cli/test/cardano-cli-golden/files/input/example_anchor_data.txt b/cardano-cli/test/cardano-cli-golden/files/input/example_anchor_data.txt new file mode 100644 index 0000000000..5d83630efd --- /dev/null +++ b/cardano-cli/test/cardano-cli-golden/files/input/example_anchor_data.txt @@ -0,0 +1,2 @@ +This is just a random file with content that is used for +testing the hashing of anchor data files. \ No newline at end of file diff --git a/cardano-cli/test/cardano-cli-test-lib/Test/Cardano/CLI/Hash.hs b/cardano-cli/test/cardano-cli-test-lib/Test/Cardano/CLI/Hash.hs new file mode 100644 index 0000000000..c89005caac --- /dev/null +++ b/cardano-cli/test/cardano-cli-test-lib/Test/Cardano/CLI/Hash.hs @@ -0,0 +1,92 @@ +{-# LANGUAGE FlexibleContexts #-} + +module Test.Cardano.CLI.Hash + ( exampleAnchorDataHash + , serveFileWhile + , exampleAnchorDataPathTest + , exampleAnchorDataPathGolden + , exampleAnchorDataIpfsHash + ) +where + +import Cardano.Api (MonadIO) + +import Control.Concurrent (forkOS) +import Control.Exception.Lifted (bracket) +import Control.Monad (void) +import Control.Monad.Trans.Control (MonadBaseControl) +import qualified Data.ByteString.UTF8 as BSU8 +import Data.List (intercalate) +import Data.String (IsString (fromString)) +import Data.Text (unpack) +import qualified Data.Text as T +import Network.HTTP.Types.Status (status200, status404) +import Network.HTTP.Types.URI (renderQuery) +import Network.Socket (close) +import Network.Wai (Request (..), Response, ResponseReceived, pathInfo, responseFile, + responseLBS) +import Network.Wai.Handler.Warp (defaultSettings, openFreePort, runSettingsSocket) + +import Hedgehog as H +import Hedgehog.Internal.Source (HasCallStack) + +exampleAnchorDataHash :: String +exampleAnchorDataHash = "de38a4f5b8b9d8372386cc923bad19d1a0662298cf355bbe947e5eedf127fa9c" + +exampleAnchorDataPathGolden :: String +exampleAnchorDataPathGolden = "test/cardano-cli-golden/files/input/example_anchor_data.txt" + +exampleAnchorDataPathTest :: String +exampleAnchorDataPathTest = "test/cardano-cli-test/files/input/example_anchor_data.txt" + +exampleAnchorDataIpfsHash :: String +exampleAnchorDataIpfsHash = "QmbL5EBFJLf8DdPkWAskG3Euin9tHY8naqQ2JDoHnWHHXJ" + +-- | Takes a relative url (as a list of segments), a file path, and an action, and it serves +-- the file in the url provided in a random free port that is passed as a parameter to the +-- action. After the action returns, it shuts down the server. It returns the result of the +-- action. It also ensures the server is shut down even if the action throws an exception. +serveFileWhile + :: (MonadBaseControl IO m, MonadTest m, MonadIO m, HasCallStack) + => [String] + -- ^ Relative URL where the file will be served. + -- Each element is a segment of the URL. + -> FilePath + -- ^ File path for the file to serve + -> (Int -> m a) + -- ^ Action to run while the file is being served. + -- It receives the port the server is listening on + -> m a +serveFileWhile relativeUrl filePath action = + bracket + -- Server setup (resource acquisition) + ( do + -- Get the port the server is listening on + (port, socket) <- H.evalIO openFreePort + -- Serve the file + let app :: Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived + app req respond = do + let path = T.unpack <$> pathInfo req + if path == relativeUrl + then respond $ responseFile status200 [("Content-Type", "text/plain")] filePath Nothing + else + respond $ + responseLBS status404 [("Content-Type", "text/plain")] $ + fromString ("404 - Url \"" ++ urlFromRequest req ++ "\" - Not Found") + + -- Run server asynchronously in a separate thread + void $ H.evalIO $ forkOS $ runSettingsSocket defaultSettings socket app + return (port, socket) + ) + -- Server teardown (resource release) + (\(_, socket) -> H.evalIO $ close socket) + -- Test action + (\(port, _) -> action port) + where + urlFromRequest :: Request -> String + urlFromRequest req = + "http://" + ++ maybe "localhost" BSU8.toString (requestHeaderHost req) + ++ "/" + ++ intercalate "/" (unpack <$> pathInfo req) + ++ BSU8.toString (renderQuery True (queryString req)) diff --git a/cardano-cli/test/cardano-cli-test-lib/Test/Cardano/CLI/Util.hs b/cardano-cli/test/cardano-cli-test-lib/Test/Cardano/CLI/Util.hs index 60d7b0238c..a116987292 100644 --- a/cardano-cli/test/cardano-cli-test-lib/Test/Cardano/CLI/Util.hs +++ b/cardano-cli/test/cardano-cli-test-lib/Test/Cardano/CLI/Util.hs @@ -2,6 +2,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE RankNTypes #-} +{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} module Test.Cardano.CLI.Util @@ -10,6 +11,7 @@ module Test.Cardano.CLI.Util , checkTextEnvelopeFormat , equivalence , execCardanoCLI + , execCardanoCLIWithEnvVars , execDetailCardanoCLI , execDetailConfigCardanoCLI , tryExecCardanoCLI @@ -21,6 +23,7 @@ module Test.Cardano.CLI.Util , bracketSem , FileSem , newFileSem + , expectFailure ) where @@ -43,6 +46,7 @@ import Data.Function ((&)) import qualified Data.List as List import Data.Monoid (Last (..)) import Data.Text (Text) +import GHC.IO.Exception (ExitCode (..)) import GHC.Stack (CallStack, HasCallStack) import qualified GHC.Stack as GHC import qualified System.Directory as IO @@ -58,7 +62,7 @@ import qualified Hedgehog as H import Hedgehog.Extras (ExecConfig) import qualified Hedgehog.Extras as H import Hedgehog.Extras.Test (ExecConfig (..)) -import Hedgehog.Internal.Property (Diff, MonadTest, liftTest, mkTest) +import Hedgehog.Internal.Property (Diff, MonadTest, PropertyT, liftTest, mkTest) import qualified Hedgehog.Internal.Property as H import Hedgehog.Internal.Show (ValueDiff (ValueSame), mkValue, showPretty, valueDiff) import Hedgehog.Internal.Source (getCaller) @@ -74,6 +78,31 @@ execCardanoCLI -- ^ Captured stdout execCardanoCLI = GHC.withFrozenCallStack $ H.execFlex "cardano-cli" "CARDANO_CLI" +-- | Execute cardano-cli via the command line but set +-- environment variables. Fails if the process returns a non-zero exit code. +-- +-- Waits for the process to finish and returns the stdout. +execCardanoCLIWithEnvVars + :: (MonadTest m, MonadCatch m, MonadIO m, HasCallStack) + => [(String, String)] + -- ^ Environment variables to set + -> [String] + -- ^ Arguments to the CLI command + -> m String +execCardanoCLIWithEnvVars envVars args = GHC.withFrozenCallStack $ do + env <- H.evalIO IO.getEnvironment + result <- + execDetailConfigCardanoCLI + H.defaultExecConfig + { H.execConfigEnv = Last $ Just (envVars ++ env) + } + args + case result of + (ExitFailure _, _, stderr) -> do + H.note_ stderr + H.failure + (ExitSuccess, stdout, _) -> return stdout + -- | Execute cardano-cli via the command line, expecting it to fail. -- -- Waits for the process to finish and returns the exit code, stdout and stderr. @@ -357,3 +386,11 @@ bracketSem bracketSem (FileSem path semaphore) act = bracket_ (liftBase $ waitQSem semaphore) (liftBase $ signalQSem semaphore) $ act path + +-- | Invert the behavior of a MonadTest: success becomes failure and vice versa. +expectFailure :: HasCallStack => H.TestT IO m -> PropertyT IO () +expectFailure prop = GHC.withFrozenCallStack $ do + (res, _) <- H.evalIO $ H.runTestT prop + case res of + Left _ -> pure () -- Property failed so we succeed + _ -> H.failWith Nothing "Expected the test to fail but it passed" -- Property passed but we expected a failure diff --git a/cardano-cli/test/cardano-cli-test/Test/Cli/CreateCardano.hs b/cardano-cli/test/cardano-cli-test/Test/Cli/CreateCardano.hs new file mode 100644 index 0000000000..ef5596f193 --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/Test/Cli/CreateCardano.hs @@ -0,0 +1,42 @@ +{-# LANGUAGE ScopedTypeVariables #-} + +module Test.Cli.CreateCardano where + +import Control.Monad (void) +import System.FilePath (()) + +import Test.Cardano.CLI.Util (execCardanoCLI) + +import Hedgehog (Property) +import Hedgehog.Extras (moduleWorkspace, propertyOnce) +import qualified Hedgehog.Extras as H + +-- Execute this test with: +-- @cabal test cardano-cli-test --test-options '-p "/create cardano/'@ +hprop_create_cardano :: Property +hprop_create_cardano = + propertyOnce $ moduleWorkspace "tmp" $ \tempDir -> do + let outputDir = tempDir "out" + eras = ["byron", "shelley", "alonzo", "conway"] + templates = + concatMap + ( \era -> + [ "--" ++ era ++ "-template" + , "test/cardano-cli-test/files/input/conway/create-cardano/genesis." ++ era ++ ".spec.json" + ] + ) + eras + + void $ + execCardanoCLI $ + [ "conway" + , "genesis" + , "create-cardano" + , "--genesis-dir" + , outputDir + , "--testnet-magic" + , "734" + ] + ++ templates + + H.assertFilesExist $ [outputDir (era ++ "-genesis.json") | era <- eras] diff --git a/cardano-cli/test/cardano-cli-test/Test/Cli/Hash.hs b/cardano-cli/test/cardano-cli-test/Test/Cli/Hash.hs index f9580f9c3f..744e10af2e 100644 --- a/cardano-cli/test/cardano-cli-test/Test/Cli/Hash.hs +++ b/cardano-cli/test/cardano-cli-test/Test/Cli/Hash.hs @@ -2,44 +2,19 @@ module Test.Cli.Hash where -import Cardano.Api (MonadIO) - -import Control.Concurrent (forkOS) -import Control.Exception.Lifted (bracket) import Control.Monad (void) -import Control.Monad.Trans.Control (MonadBaseControl) -import qualified Data.ByteString.UTF8 as BSU8 import Data.List (intercalate) -import Data.Monoid (Last (..)) -import Data.String (IsString (fromString)) -import Data.Text (unpack) -import qualified Data.Text as T import GHC.IO.Exception (ExitCode (..)) -import Network.HTTP.Types.Status (status200, status404) -import Network.HTTP.Types.URI (renderQuery) -import Network.Socket (close) -import Network.Wai (Request (..), Response, ResponseReceived, pathInfo, responseFile, - responseLBS) -import Network.Wai.Handler.Warp (defaultSettings, openFreePort, runSettingsSocket) import System.Directory (getCurrentDirectory) -import System.Environment (getEnvironment) import System.FilePath (dropTrailingPathSeparator) import System.FilePath.Posix (splitDirectories) +import Test.Cardano.CLI.Hash (exampleAnchorDataHash, exampleAnchorDataIpfsHash, + exampleAnchorDataPathTest, serveFileWhile) import Test.Cardano.CLI.Util import Hedgehog as H import qualified Hedgehog.Extras as H -import Hedgehog.Internal.Source (HasCallStack) - -exampleAnchorDataHash :: String -exampleAnchorDataHash = "de38a4f5b8b9d8372386cc923bad19d1a0662298cf355bbe947e5eedf127fa9c" - -exampleAnchorDataPath :: String -exampleAnchorDataPath = "test/cardano-cli-test/files/input/example_anchor_data.txt" - -exampleAchorDataIpfsHash :: String -exampleAchorDataIpfsHash = "QmbL5EBFJLf8DdPkWAskG3Euin9tHY8naqQ2JDoHnWHHXJ" -- | Execute me with: -- @cabal test cardano-cli-test --test-options '-p "/generate anchor data hash from file/"'@ @@ -51,7 +26,7 @@ hprop_generate_anchor_data_hash_from_file = [ "hash" , "anchor-data" , "--file-binary" - , exampleAnchorDataPath + , exampleAnchorDataPathTest ] result === exampleAnchorDataHash @@ -65,7 +40,7 @@ hprop_check_anchor_data_hash_from_file = [ "hash" , "anchor-data" , "--file-binary" - , exampleAnchorDataPath + , exampleAnchorDataPathTest , "--expected-hash" , exampleAnchorDataHash ] @@ -80,7 +55,7 @@ hprop_check_anchor_data_hash_from_file_fails = [ "hash" , "anchor-data" , "--file-binary" - , exampleAnchorDataPath + , exampleAnchorDataPathTest , "--expected-hash" , 'c' : drop 1 exampleAnchorDataHash ] @@ -98,7 +73,7 @@ hprop_generate_anchor_data_hash_from_file_uri = [ "hash" , "anchor-data" , "--url" - , "file://" ++ posixCwd ++ "/" ++ exampleAnchorDataPath + , "file://" ++ posixCwd ++ "/" ++ exampleAnchorDataPathTest ] result === exampleAnchorDataHash where @@ -125,7 +100,7 @@ hprop_check_anchor_data_hash_from_http_uri = let relativeUrl = ["example", "url", "file.txt"] serveFileWhile relativeUrl - exampleAnchorDataPath + exampleAnchorDataPathTest ( \port -> do void $ execCardanoCLI @@ -143,83 +118,19 @@ hprop_check_anchor_data_hash_from_http_uri = hprop_check_anchor_data_hash_from_ipfs_uri :: Property hprop_check_anchor_data_hash_from_ipfs_uri = propertyOnce $ do - let relativeUrl = ["ipfs", exampleAchorDataIpfsHash] + let relativeUrl = ["ipfs", exampleAnchorDataIpfsHash] serveFileWhile relativeUrl - exampleAnchorDataPath + exampleAnchorDataPathTest ( \port -> do - env <- H.evalIO getEnvironment - result <- - execDetailConfigCardanoCLI - H.defaultExecConfig - { H.execConfigEnv = - Last $ - Just - ( ( "IPFS_GATEWAY_URI" - , "http://localhost:" ++ show port ++ "/" - ) - : env - ) - } + void $ + execCardanoCLIWithEnvVars + [("IPFS_GATEWAY_URI", "http://localhost:" ++ show port ++ "/")] [ "hash" , "anchor-data" , "--url" - , "ipfs://" ++ exampleAchorDataIpfsHash + , "ipfs://" ++ exampleAnchorDataIpfsHash , "--expected-hash" , exampleAnchorDataHash ] - case result of - (ExitFailure _, _, stderr) -> do - H.note_ stderr - failure - (ExitSuccess, _, _) -> success ) - --- | Takes a relative url (as a list of segments), a file path, and an action, and it serves --- the file in the url provided in a random free port that is passed as a parameter to the --- action. After the action returns, it shuts down the server. It returns the result of the --- action. It also ensures the server is shut down even if the action throws an exception. -serveFileWhile - :: (MonadBaseControl IO m, MonadTest m, MonadIO m, HasCallStack) - => [String] - -- ^ Relative URL where the file will be served. - -- Each element is a segment of the URL. - -> FilePath - -- ^ File path for the file to serve - -> (Int -> m a) - -- ^ Action to run while the file is being served. - -- It receives the port the server is listening on - -> m a -serveFileWhile relativeUrl filePath action = - bracket - -- Server setup (resource acquisition) - ( do - -- Get the port the server is listening on - (port, socket) <- H.evalIO openFreePort - -- Serve the file - let app :: Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived - app req respond = do - let path = T.unpack <$> pathInfo req - if path == relativeUrl - then respond $ responseFile status200 [("Content-Type", "text/plain")] filePath Nothing - else - respond $ - responseLBS status404 [("Content-Type", "text/plain")] $ - fromString ("404 - Url \"" ++ urlFromRequest req ++ "\" - Not Found") - - -- Run server asynchronously in a separate thread - void $ H.evalIO $ forkOS $ runSettingsSocket defaultSettings socket app - return (port, socket) - ) - -- Server teardown (resource release) - (\(_, socket) -> H.evalIO $ close socket) - -- Test action - (\(port, _) -> action port) - where - urlFromRequest :: Request -> String - urlFromRequest req = - "http://" - ++ maybe "localhost" BSU8.toString (requestHeaderHost req) - ++ "/" - ++ intercalate "/" (unpack <$> pathInfo req) - ++ BSU8.toString (renderQuery True (queryString req)) diff --git a/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.alonzo.spec.json b/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.alonzo.spec.json new file mode 100644 index 0000000000..cf8e5ef324 --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.alonzo.spec.json @@ -0,0 +1,194 @@ +{ + "lovelacePerUTxOWord": 34482, + "executionPrices": { + "prSteps": { + "numerator": 721, + "denominator": 10000000 + }, + "prMem": { + "numerator": 577, + "denominator": 10000 + } + }, + "maxTxExUnits": { + "exUnitsMem": 10000000, + "exUnitsSteps": 10000000000 + }, + "maxBlockExUnits": { + "exUnitsMem": 50000000, + "exUnitsSteps": 40000000000 + }, + "maxValueSize": 5000, + "collateralPercentage": 150, + "maxCollateralInputs": 3, + "costModels": { + "PlutusV1": { + "sha2_256-memory-arguments": 4, + "equalsString-cpu-arguments-constant": 1000, + "cekDelayCost-exBudgetMemory": 100, + "lessThanEqualsByteString-cpu-arguments-intercept": 103599, + "divideInteger-memory-arguments-minimum": 1, + "appendByteString-cpu-arguments-slope": 621, + "blake2b-cpu-arguments-slope": 29175, + "iData-cpu-arguments": 150000, + "encodeUtf8-cpu-arguments-slope": 1000, + "unBData-cpu-arguments": 150000, + "multiplyInteger-cpu-arguments-intercept": 61516, + "cekConstCost-exBudgetMemory": 100, + "nullList-cpu-arguments": 150000, + "equalsString-cpu-arguments-intercept": 150000, + "trace-cpu-arguments": 150000, + "mkNilData-memory-arguments": 32, + "lengthOfByteString-cpu-arguments": 150000, + "cekBuiltinCost-exBudgetCPU": 29773, + "bData-cpu-arguments": 150000, + "subtractInteger-cpu-arguments-slope": 0, + "unIData-cpu-arguments": 150000, + "consByteString-memory-arguments-intercept": 0, + "divideInteger-memory-arguments-slope": 1, + "divideInteger-cpu-arguments-model-arguments-slope": 118, + "listData-cpu-arguments": 150000, + "headList-cpu-arguments": 150000, + "chooseData-memory-arguments": 32, + "equalsInteger-cpu-arguments-intercept": 136542, + "sha3_256-cpu-arguments-slope": 82363, + "sliceByteString-cpu-arguments-slope": 5000, + "unMapData-cpu-arguments": 150000, + "lessThanInteger-cpu-arguments-intercept": 179690, + "mkCons-cpu-arguments": 150000, + "appendString-memory-arguments-intercept": 0, + "modInteger-cpu-arguments-model-arguments-slope": 118, + "ifThenElse-cpu-arguments": 1, + "mkNilPairData-cpu-arguments": 150000, + "lessThanEqualsInteger-cpu-arguments-intercept": 145276, + "addInteger-memory-arguments-slope": 1, + "chooseList-memory-arguments": 32, + "constrData-memory-arguments": 32, + "decodeUtf8-cpu-arguments-intercept": 150000, + "equalsData-memory-arguments": 1, + "subtractInteger-memory-arguments-slope": 1, + "appendByteString-memory-arguments-intercept": 0, + "lengthOfByteString-memory-arguments": 4, + "headList-memory-arguments": 32, + "listData-memory-arguments": 32, + "consByteString-cpu-arguments-intercept": 150000, + "unIData-memory-arguments": 32, + "remainderInteger-memory-arguments-minimum": 1, + "bData-memory-arguments": 32, + "lessThanByteString-cpu-arguments-slope": 248, + "encodeUtf8-memory-arguments-intercept": 0, + "cekStartupCost-exBudgetCPU": 100, + "multiplyInteger-memory-arguments-intercept": 0, + "unListData-memory-arguments": 32, + "remainderInteger-cpu-arguments-model-arguments-slope": 118, + "cekVarCost-exBudgetCPU": 29773, + "remainderInteger-memory-arguments-slope": 1, + "cekForceCost-exBudgetCPU": 29773, + "sha2_256-cpu-arguments-slope": 29175, + "equalsInteger-memory-arguments": 1, + "indexByteString-memory-arguments": 1, + "addInteger-memory-arguments-intercept": 1, + "chooseUnit-cpu-arguments": 150000, + "sndPair-cpu-arguments": 150000, + "cekLamCost-exBudgetCPU": 29773, + "fstPair-cpu-arguments": 150000, + "quotientInteger-memory-arguments-minimum": 1, + "decodeUtf8-cpu-arguments-slope": 1000, + "lessThanInteger-memory-arguments": 1, + "lessThanEqualsInteger-cpu-arguments-slope": 1366, + "fstPair-memory-arguments": 32, + "modInteger-memory-arguments-intercept": 0, + "unConstrData-cpu-arguments": 150000, + "lessThanEqualsInteger-memory-arguments": 1, + "chooseUnit-memory-arguments": 32, + "sndPair-memory-arguments": 32, + "addInteger-cpu-arguments-intercept": 197209, + "decodeUtf8-memory-arguments-slope": 8, + "equalsData-cpu-arguments-intercept": 150000, + "mapData-cpu-arguments": 150000, + "mkPairData-cpu-arguments": 150000, + "quotientInteger-cpu-arguments-constant": 148000, + "consByteString-memory-arguments-slope": 1, + "cekVarCost-exBudgetMemory": 100, + "indexByteString-cpu-arguments": 150000, + "unListData-cpu-arguments": 150000, + "equalsInteger-cpu-arguments-slope": 1326, + "cekStartupCost-exBudgetMemory": 100, + "subtractInteger-cpu-arguments-intercept": 197209, + "divideInteger-cpu-arguments-model-arguments-intercept": 425507, + "divideInteger-memory-arguments-intercept": 0, + "cekForceCost-exBudgetMemory": 100, + "blake2b-cpu-arguments-intercept": 2477736, + "remainderInteger-cpu-arguments-constant": 148000, + "tailList-cpu-arguments": 150000, + "encodeUtf8-cpu-arguments-intercept": 150000, + "equalsString-cpu-arguments-slope": 1000, + "lessThanByteString-memory-arguments": 1, + "multiplyInteger-cpu-arguments-slope": 11218, + "appendByteString-cpu-arguments-intercept": 396231, + "lessThanEqualsByteString-cpu-arguments-slope": 248, + "modInteger-memory-arguments-slope": 1, + "addInteger-cpu-arguments-slope": 0, + "equalsData-cpu-arguments-slope": 10000, + "decodeUtf8-memory-arguments-intercept": 0, + "chooseList-cpu-arguments": 150000, + "constrData-cpu-arguments": 150000, + "equalsByteString-memory-arguments": 1, + "cekApplyCost-exBudgetCPU": 29773, + "quotientInteger-memory-arguments-slope": 1, + "verifySignature-cpu-arguments-intercept": 3345831, + "unMapData-memory-arguments": 32, + "mkCons-memory-arguments": 32, + "sliceByteString-memory-arguments-slope": 1, + "sha3_256-memory-arguments": 4, + "ifThenElse-memory-arguments": 1, + "mkNilPairData-memory-arguments": 32, + "equalsByteString-cpu-arguments-slope": 247, + "appendString-cpu-arguments-intercept": 150000, + "quotientInteger-cpu-arguments-model-arguments-slope": 118, + "cekApplyCost-exBudgetMemory": 100, + "equalsString-memory-arguments": 1, + "multiplyInteger-memory-arguments-slope": 1, + "cekBuiltinCost-exBudgetMemory": 100, + "remainderInteger-memory-arguments-intercept": 0, + "sha2_256-cpu-arguments-intercept": 2477736, + "remainderInteger-cpu-arguments-model-arguments-intercept": 425507, + "lessThanEqualsByteString-memory-arguments": 1, + "tailList-memory-arguments": 32, + "mkNilData-cpu-arguments": 150000, + "chooseData-cpu-arguments": 150000, + "unBData-memory-arguments": 32, + "blake2b-memory-arguments": 4, + "iData-memory-arguments": 32, + "nullList-memory-arguments": 32, + "cekDelayCost-exBudgetCPU": 29773, + "subtractInteger-memory-arguments-intercept": 1, + "lessThanByteString-cpu-arguments-intercept": 103599, + "consByteString-cpu-arguments-slope": 1000, + "appendByteString-memory-arguments-slope": 1, + "trace-memory-arguments": 32, + "divideInteger-cpu-arguments-constant": 148000, + "cekConstCost-exBudgetCPU": 29773, + "encodeUtf8-memory-arguments-slope": 8, + "quotientInteger-cpu-arguments-model-arguments-intercept": 425507, + "mapData-memory-arguments": 32, + "appendString-cpu-arguments-slope": 1000, + "modInteger-cpu-arguments-constant": 148000, + "verifySignature-cpu-arguments-slope": 1, + "unConstrData-memory-arguments": 32, + "quotientInteger-memory-arguments-intercept": 0, + "equalsByteString-cpu-arguments-constant": 150000, + "sliceByteString-memory-arguments-intercept": 0, + "mkPairData-memory-arguments": 32, + "equalsByteString-cpu-arguments-intercept": 112536, + "appendString-memory-arguments-slope": 1, + "lessThanInteger-cpu-arguments-slope": 497, + "modInteger-cpu-arguments-model-arguments-intercept": 425507, + "modInteger-memory-arguments-minimum": 1, + "sha3_256-cpu-arguments-intercept": 0, + "verifySignature-memory-arguments": 1, + "cekLamCost-exBudgetMemory": 100, + "sliceByteString-cpu-arguments-intercept": 150000 + } + } +} \ No newline at end of file diff --git a/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.byron.spec.json b/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.byron.spec.json new file mode 100644 index 0000000000..3bf15b5ca7 --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.byron.spec.json @@ -0,0 +1,23 @@ +{ + "heavyDelThd": "300000000000", + "maxBlockSize": "2000000", + "maxTxSize": "4096", + "maxHeaderSize": "2000000", + "maxProposalSize": "700", + "mpcThd": "20000000000000", + "scriptVersion": 0, + "slotDuration": "1000", + "softforkRule": { + "initThd": "900000000000000", + "minThd": "600000000000000", + "thdDecrement": "50000000000000" + }, + "txFeePolicy": { + "multiplier": "43946000000", + "summand": "155381000000000" + }, + "unlockStakeEpoch": "18446744073709551615", + "updateImplicit": "10000", + "updateProposalThd": "100000000000000", + "updateVoteThd": "1000000000000" +} diff --git a/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.conway.spec.json b/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.conway.spec.json new file mode 100644 index 0000000000..cb36a9387f --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.conway.spec.json @@ -0,0 +1,42 @@ +{ + "poolVotingThresholds": { + "committeeNormal": 0, + "committeeNoConfidence": 0, + "hardForkInitiation": 0, + "motionNoConfidence": 0, + "ppSecurityGroup": 0 + }, + "dRepVotingThresholds": { + "motionNoConfidence": 0, + "committeeNormal": 0, + "committeeNoConfidence": 0, + "updateToConstitution": 0, + "hardForkInitiation": 0, + "ppNetworkGroup": 0, + "ppEconomicGroup": 0, + "ppTechnicalGroup": 0, + "ppGovGroup": 0, + "treasuryWithdrawal": 0 + }, + "committeeMinSize": 0, + "committeeMaxTermLength": 0, + "govActionLifetime": 0, + "govActionDeposit": 0, + "dRepDeposit": 0, + "dRepActivity": 0, + "minFeeRefScriptCostPerByte": 0, + "plutusV3CostModel": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "constitution": { + "anchor": { + "url": "", + "dataHash": "0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "committee": { + "members": { + "keyHash-4e88cc2d27c364aaf90648a87dfb95f8ee103ba67fa1f12f5e86c42a": 1, + "scriptHash-4e88cc2d27c364aaf90648a87dfb95f8ee103ba67fa1f12f5e86c42a": 2 + }, + "threshold": 0.5 + } +} diff --git a/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.shelley.spec.json b/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.shelley.spec.json new file mode 100644 index 0000000000..8b74e0201c --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/files/input/conway/create-cardano/genesis.shelley.spec.json @@ -0,0 +1,40 @@ +{ + "activeSlotsCoeff": 0.99, + "systemStart": "2020-01-01T00:20:40Z", + "genDelegs": {}, + "updateQuorum": 12, + "maxMajorPV": 25446, + "maxLovelaceSupply": 100000000, + "initialFunds": {}, + "networkMagic": 403, + "networkId": "Testnet", + "epochLength": 21600, + "securityParam": 2160, + "slotLength": 20, + "slotsPerKESPeriod": 216000, + "maxKESEvolutions": 1080000, + "protocolParams": { + "a0": 0, + "decentralisationParam": 0.99, + "eMax": 0, + "extraEntropy": { + "tag": "NeutralNonce" + }, + "keyDeposit": 0, + "maxBlockBodySize": 2097152, + "maxBlockHeaderSize": 8192, + "maxTxSize": 2048, + "minFeeA": 0, + "minFeeB": 0, + "minUTxOValue": 1, + "minPoolCost": 100, + "nOpt": 100, + "poolDeposit": 0, + "protocolVersion": { + "major": 0, + "minor": 0 + }, + "rho": 0, + "tau": 0 + } +} diff --git a/flake.nix b/flake.nix index b61c56b660..1d02fb3a8d 100644 --- a/flake.nix +++ b/flake.nix @@ -160,7 +160,11 @@ in '' ${exportCliPath} cp -r ${filteredProjectBase}/* .. - ''; + '' + (if isDarwin + then '' + export PATH=${macOS-security}/bin:$PATH + '' + else ''''); packages.cardano-cli.components.tests.cardano-cli-test.preCheck = let # This define files included in the directory that will be passed to `H.getProjectBase` for this test: filteredProjectBase = inputs.incl ./. mainnetConfigFiles;