diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Commands/Query.hs b/cardano-cli/src/Cardano/CLI/EraBased/Commands/Query.hs index 5d2a1ef5d..f5f20d2d7 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Commands/Query.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Commands/Query.hs @@ -25,6 +25,7 @@ module Cardano.CLI.EraBased.Commands.Query , QueryNoArgCmdArgs (..) , QueryDRepStateCmdArgs (..) , QueryDRepStakeDistributionCmdArgs (..) + , QuerySPOStakeDistributionCmdArgs (..) , QueryTreasuryValueCmdArgs (..) , renderQueryCmds , IncludeStake (..) @@ -63,6 +64,7 @@ data QueryCmds era | QueryGovStateCmd !(QueryNoArgCmdArgs era) | QueryDRepStateCmd !(QueryDRepStateCmdArgs era) | QueryDRepStakeDistributionCmd !(QueryDRepStakeDistributionCmdArgs era) + | QuerySPOStakeDistributionCmd !(QuerySPOStakeDistributionCmdArgs era) | QueryCommitteeMembersStateCmd !(QueryCommitteeMembersStateCmdArgs era) | QueryTreasuryValueCmd !(QueryTreasuryValueCmdArgs era) deriving (Generic, Show) @@ -259,6 +261,17 @@ data QueryDRepStakeDistributionCmdArgs era = QueryDRepStakeDistributionCmdArgs } deriving Show +data QuerySPOStakeDistributionCmdArgs era = QuerySPOStakeDistributionCmdArgs + { eon :: !(ConwayEraOnwards era) + , nodeSocketPath :: !SocketPath + , consensusModeParams :: !ConsensusModeParams + , networkId :: !NetworkId + , spoHashSources :: !(AllOrOnly SPOHashSource) + , target :: !(Consensus.Target ChainPoint) + , mOutFile :: !(Maybe (File () Out)) + } + deriving Show + data QueryCommitteeMembersStateCmdArgs era = QueryCommitteeMembersStateCmdArgs { eon :: !(ConwayEraOnwards era) , nodeSocketPath :: !SocketPath @@ -324,6 +337,8 @@ renderQueryCmds = \case "drep-state" QueryDRepStakeDistributionCmd{} -> "drep-stake-distribution" + QuerySPOStakeDistributionCmd{} -> + "spo-stake-distribution" QueryCommitteeMembersStateCmd{} -> "committee-state" QueryTreasuryValueCmd{} -> diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs index 0e2276705..ba79990b6 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/Common.hs @@ -3732,12 +3732,21 @@ pDRepHashSource = , DRepHashSourceVerificationKey <$> pDRepVerificationKeyOrHashOrFile ] +pSPOHashSource :: Parser SPOHashSource +pSPOHashSource = SPOHashSourceVerificationKey <$> pSPOVerificationKeyOrHashOrFile + pDRepScriptHash :: Parser ScriptHash pDRepScriptHash = pScriptHash "drep-script-hash" "DRep script hash (hex-encoded). Obtain it with \"cardano-cli hash script ...\"." +pSPOScriptHash :: Parser ScriptHash +pSPOScriptHash = + pScriptHash + "spo-script-hash" + "Stake pool operator script hash (hex-encoded). Obtain it with \"cardano-cli hash script ...\"." + pConstitutionScriptHash :: Parser ScriptHash pConstitutionScriptHash = pScriptHash @@ -3752,6 +3761,14 @@ pDRepVerificationKeyOrHashOrFile = , VerificationKeyHash <$> pDRepVerificationKeyHash ] +pSPOVerificationKeyOrHashOrFile + :: Parser (VerificationKeyOrHashOrFile StakePoolKey) +pSPOVerificationKeyOrHashOrFile = + asum + [ VerificationKeyOrFile <$> pSPOVerificationKeyOrFile + , VerificationKeyHash <$> pSPOVerificationKeyHash + ] + pDRepVerificationKeyOrHashOrFileOrScriptHash :: Parser (VerificationKeyOrHashOrFileOrScriptHash DRepKey) pDRepVerificationKeyOrHashOrFileOrScriptHash = @@ -3776,6 +3793,17 @@ pAllOrOnlyDRepHashSource = pAll <|> pOnly , Opt.help "Query for all DReps." ] +pAllOrOnlySPOHashSource :: Parser (AllOrOnly SPOHashSource) +pAllOrOnlySPOHashSource = pAll <|> pOnly + where + pOnly = Only <$> some pSPOHashSource + pAll = + Opt.flag' All $ + mconcat + [ Opt.long "all-spos" + , Opt.help "Query for all DReps." + ] + pDRepVerificationKeyHash :: Parser (Hash DRepKey) pDRepVerificationKeyHash = Opt.option (rBech32KeyHash AsDRepKey <|> rHexHash AsDRepKey Nothing) $ @@ -3811,6 +3839,41 @@ pDRepVerificationKeyFile = , Opt.completer (Opt.bashCompleter "file") ] +pSPOVerificationKeyHash :: Parser (Hash StakePoolKey) +pSPOVerificationKeyHash = + Opt.option (rBech32KeyHash AsStakePoolKey <|> rHexHash AsStakePoolKey Nothing) $ + mconcat + [ Opt.long "spo-key-hash" + , Opt.metavar "HASH" + , Opt.help "SPO verification key hash (either Bech32-encoded or hex-encoded)." + ] + +pSPOVerificationKey :: Parser (VerificationKey StakePoolKey) +pSPOVerificationKey = + Opt.option (readVerificationKey AsStakePoolKey) $ + mconcat + [ Opt.long "spo-verification-key" + , Opt.metavar "STRING" + , Opt.help "SPO verification key (Bech32 or hex-encoded)." + ] + +pSPOVerificationKeyOrFile :: Parser (VerificationKeyOrFile StakePoolKey) +pSPOVerificationKeyOrFile = + asum + [ VerificationKeyValue <$> pSPOVerificationKey + , VerificationKeyFilePath <$> pSPOVerificationKeyFile + ] + +pSPOVerificationKeyFile :: Parser (VerificationKeyFile In) +pSPOVerificationKeyFile = + fmap File . Opt.strOption $ + mconcat + [ Opt.long "spo-verification-key-file" + , Opt.metavar "FILE" + , Opt.help "Filepath of the SPO verification key." + , Opt.completer (Opt.bashCompleter "file") + ] + pAnchorUrl :: Parser ProposalUrl pAnchorUrl = ProposalUrl diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Options/Query.hs b/cardano-cli/src/Cardano/CLI/EraBased/Options/Query.hs index 4c518fa28..784b5a72d 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Options/Query.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Options/Query.hs @@ -127,6 +127,7 @@ pQueryCmds era envCli = , pQueryGetGovStateCmd era envCli , pQueryDRepStateCmd era envCli , pQueryDRepStakeDistributionCmd era envCli + , pQuerySPOStakeDistributionCmd era envCli , pQueryGetCommitteeStateCmd era envCli , pQueryTreasuryValueCmd era envCli ] @@ -426,6 +427,29 @@ pQueryDRepStakeDistributionCmd era envCli = do <*> pTarget era <*> optional pOutputFile +pQuerySPOStakeDistributionCmd + :: () + => CardanoEra era + -> EnvCli + -> Maybe (Parser (QueryCmds era)) +pQuerySPOStakeDistributionCmd era envCli = do + w <- forEraMaybeEon era + pure $ + subParser "spo-stake-distribution" $ + Opt.info (QuerySPOStakeDistributionCmd <$> pQuerySPOStakeDistributionCmdArgs w) $ + Opt.progDesc "Get the SPO stake distribution." + where + pQuerySPOStakeDistributionCmdArgs + :: ConwayEraOnwards era -> Parser (QuerySPOStakeDistributionCmdArgs era) + pQuerySPOStakeDistributionCmdArgs w = + QuerySPOStakeDistributionCmdArgs w + <$> pSocketPath envCli + <*> pConsensusModeParams + <*> pNetworkId envCli + <*> pAllOrOnlySPOHashSource + <*> pTarget era + <*> optional pOutputFile + pQueryGetCommitteeStateCmd :: () => CardanoEra era diff --git a/cardano-cli/src/Cardano/CLI/EraBased/Run/Query.hs b/cardano-cli/src/Cardano/CLI/EraBased/Run/Query.hs index d448a65b9..b928d4e54 100644 --- a/cardano-cli/src/Cardano/CLI/EraBased/Run/Query.hs +++ b/cardano-cli/src/Cardano/CLI/EraBased/Run/Query.hs @@ -123,6 +123,7 @@ runQueryCmds = \case Cmd.QueryGovStateCmd args -> runQueryGovState args Cmd.QueryDRepStateCmd args -> runQueryDRepState args Cmd.QueryDRepStakeDistributionCmd args -> runQueryDRepStakeDistribution args + Cmd.QuerySPOStakeDistributionCmd args -> runQuerySPOStakeDistribution args Cmd.QueryCommitteeMembersStateCmd args -> runQueryCommitteeMembersState args Cmd.QueryTreasuryValueCmd args -> runQueryTreasuryValue args @@ -1700,6 +1701,31 @@ runQueryDRepStakeDistribution writeOutput mOutFile $ Map.assocs drepStakeDistribution +runQuerySPOStakeDistribution + :: Cmd.QuerySPOStakeDistributionCmdArgs era + -> ExceptT QueryCmdError IO () +runQuerySPOStakeDistribution + Cmd.QuerySPOStakeDistributionCmdArgs + { Cmd.eon + , Cmd.nodeSocketPath + , Cmd.consensusModeParams + , Cmd.networkId + , Cmd.spoHashSources = spoHashSources' + , Cmd.target + , Cmd.mOutFile + } = conwayEraOnwardsConstraints eon $ do + let localNodeConnInfo = LocalNodeConnectInfo consensusModeParams networkId nodeSocketPath + spoFromSource = firstExceptT QueryCmdSPOKeyError . readSPOCredential + spoHashSources = case spoHashSources' of + All -> [] + Only l -> l + + spos <- fromList <$> mapM spoFromSource spoHashSources + + spoStakeDistribution <- runQuery localNodeConnInfo target $ querySPOStakeDistribution eon spos + writeOutput mOutFile $ + Map.assocs spoStakeDistribution + runQueryCommitteeMembersState :: Cmd.QueryCommitteeMembersStateCmdArgs era -> ExceptT QueryCmdError IO () diff --git a/cardano-cli/src/Cardano/CLI/Types/Errors/QueryCmdError.hs b/cardano-cli/src/Cardano/CLI/Types/Errors/QueryCmdError.hs index a87e5c9d8..f2879d56d 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Errors/QueryCmdError.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Errors/QueryCmdError.hs @@ -52,6 +52,7 @@ data QueryCmdError | QueryCmdUnsupportedNtcVersion !UnsupportedNtcVersionError | QueryCmdProtocolParameterConversionError !ProtocolParametersConversionError | QueryCmdDRepKeyError !(FileError InputDecodeError) + | QueryCmdSPOKeyError !(FileError InputDecodeError) | QueryCmdCommitteeColdKeyError !(FileError InputDecodeError) | QueryCmdCommitteeHotKeyError !(FileError InputDecodeError) deriving Show @@ -108,6 +109,8 @@ renderQueryCmdError = \case pretty $ renderQueryConvenienceError qce QueryCmdDRepKeyError e -> "Error reading delegation representative key: " <> prettyError e + QueryCmdSPOKeyError e -> + "Error reading Stake Pool Operator key: " <> prettyError e QueryCmdCommitteeColdKeyError e -> "Error reading committee cold key: " <> prettyError e QueryCmdCommitteeHotKeyError e -> diff --git a/cardano-cli/src/Cardano/CLI/Types/Key.hs b/cardano-cli/src/Cardano/CLI/Types/Key.hs index e024c7456..940ecb5ca 100644 --- a/cardano-cli/src/Cardano/CLI/Types/Key.hs +++ b/cardano-cli/src/Cardano/CLI/Types/Key.hs @@ -36,6 +36,8 @@ module Cardano.CLI.Types.Key , ColdVerificationKeyOrFile (..) , DRepHashSource (..) , readDRepCredential + , SPOHashSource (..) + , readSPOCredential , SomeSigningKey (..) , withSomeSigningKey , readSigningKeyFile @@ -330,6 +332,19 @@ readDRepCredential = \case L.KeyHashObj . unDRepKeyHash <$> readVerificationKeyOrHashOrTextEnvFile AsDRepKey drepVKeyOrHashOrFile +newtype SPOHashSource + = SPOHashSourceVerificationKey + (VerificationKeyOrHashOrFile StakePoolKey) + deriving (Eq, Show) + +readSPOCredential + :: MonadIOTransError (FileError InputDecodeError) t m + => SPOHashSource + -> t m (L.KeyHash L.StakePool L.StandardCrypto) +readSPOCredential = \case + SPOHashSourceVerificationKey spoVKeyOrHashOrFile -> + unStakePoolKeyHash <$> readVerificationKeyOrHashOrTextEnvFile AsStakePoolKey spoVKeyOrHashOrFile + data VerificationKeyOrHashOrFileOrScript keyrole = VkhfsKeyHashFile !(VerificationKeyOrHashOrFile keyrole) | VkhfsScript !(File ScriptInAnyLang In) 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 32cbf2cd4..c3e393e5a 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli @@ -7129,6 +7129,7 @@ Usage: cardano-cli conway query | gov-state | drep-state | drep-stake-distribution + | spo-stake-distribution | committee-state | treasury ) @@ -7440,6 +7441,26 @@ Usage: cardano-cli conway query drep-stake-distribution Get the DRep stake distribution. +Usage: cardano-cli conway query spo-stake-distribution --socket-path SOCKET_PATH + [--cardano-mode + [--epoch-slots SLOTS]] + ( --mainnet + | --testnet-magic NATURAL + ) + ( --all-spos + | + ( --spo-verification-key STRING + | --spo-verification-key-file FILE + | --spo-key-hash HASH + ) + ) + [ --volatile-tip + | --immutable-tip + ] + [--out-file FILE] + + Get the SPO stake distribution. + Usage: cardano-cli conway query committee-state --socket-path SOCKET_PATH [--cardano-mode [--epoch-slots SLOTS]] diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_query.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_query.cli index 5de9fcdea..4f2507652 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_query.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_query.cli @@ -18,6 +18,7 @@ Usage: cardano-cli conway query | gov-state | drep-state | drep-stake-distribution + | spo-stake-distribution | committee-state | treasury ) @@ -60,5 +61,6 @@ Available commands: gov-state Get the governance state drep-state Get the DRep state. drep-stake-distribution Get the DRep stake distribution. + spo-stake-distribution Get the SPO stake distribution. committee-state Get the committee state treasury Get the treasury value diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_query_spo-stake-distribution.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_query_spo-stake-distribution.cli new file mode 100644 index 000000000..d0097a41f --- /dev/null +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/conway_query_spo-stake-distribution.cli @@ -0,0 +1,46 @@ +Usage: cardano-cli conway query spo-stake-distribution --socket-path SOCKET_PATH + [--cardano-mode + [--epoch-slots SLOTS]] + ( --mainnet + | --testnet-magic NATURAL + ) + ( --all-spos + | + ( --spo-verification-key STRING + | --spo-verification-key-file FILE + | --spo-key-hash HASH + ) + ) + [ --volatile-tip + | --immutable-tip + ] + [--out-file FILE] + + Get the SPO stake distribution. + +Available options: + --socket-path SOCKET_PATH + Path to the node socket. This overrides the + CARDANO_NODE_SOCKET_PATH environment variable. The + argument is optional if CARDANO_NODE_SOCKET_PATH is + defined and mandatory otherwise. + --cardano-mode For talking to a node running in full Cardano mode + (default). + --epoch-slots SLOTS The number of slots per epoch for the Byron era. + (default: 21600) + --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 + CARDANO_NODE_NETWORK_ID environment variable + --all-spos Query for all DReps. + --spo-verification-key STRING + SPO verification key (Bech32 or hex-encoded). + --spo-verification-key-file FILE + Filepath of the SPO verification key. + --spo-key-hash HASH SPO verification key hash (either Bech32-encoded or + hex-encoded). + --volatile-tip Use the volatile tip as a target. (This is the + default) + --immutable-tip Use the immutable tip as a target. + --out-file FILE The output file. + -h,--help Show this help text