diff --git a/.gitignore b/.gitignore index fa56a0bd882..617e5c62f91 100644 --- a/.gitignore +++ b/.gitignore @@ -77,3 +77,5 @@ cardano-tracer/cardano-tracer-test .idea/ .codex + +.serena/ diff --git a/cardano-testnet/changelog.d/20260527_120000_mgalazyn_bump_cardano_api_cardano_cli_chap.md b/cardano-testnet/changelog.d/20260527_120000_mgalazyn_bump_cardano_api_cardano_cli_chap.md index 18cee6700a1..46a8beceac6 100644 --- a/cardano-testnet/changelog.d/20260527_120000_mgalazyn_bump_cardano_api_cardano_cli_chap.md +++ b/cardano-testnet/changelog.d/20260527_120000_mgalazyn_bump_cardano_api_cardano_cli_chap.md @@ -3,5 +3,12 @@ - Bump `cardano-api` to `^>= 11.3` - Bump `cardano-cli` to `^>= 11.1` +- Bump `cardano-rpc` to `^>= 11.0` - Bump CHaP index-state to `2026-05-27` +### New features + +- Add gRPC `evalTx` test +- Add gRPC `searchUtxos` test +- Add chainpoint check to gRPC query test +- Rewrite `TxReferenceInputDatum` test using experimental API diff --git a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Gov/ProposeNewConstitution.hs b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Gov/ProposeNewConstitution.hs index 0e8df21398f..d1693a00c73 100644 --- a/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Gov/ProposeNewConstitution.hs +++ b/cardano-testnet/test/cardano-testnet-test/Cardano/Testnet/Test/Gov/ProposeNewConstitution.hs @@ -232,69 +232,29 @@ hprop_ledger_events_propose_new_constitution = integrationRetryWorkspace 2 "prop retryUntilJustM epochStateView (WaitForEpochs $ EpochInterval 1) $ maybeExtractGovernanceActionIndex governanceActionTxId <$> getEpochState epochStateView - -- Proposal was successfully submitted, now we vote on the proposal and confirm it was ratified - voteFiles <- generateVoteFiles execConfig work "vote-files" - governanceActionTxId governanceActionIndex - [(defaultDRepKeyPair idx, vote) | (vote, idx) <- allVotes] - - -- Submit votes - voteTxBodyFp <- createVotingTxBody execConfig epochStateView sbe work "vote-tx-body" - voteFiles wallet0 - - let signingKeys = Some <$> (paymentKeyInfoPair wallet0:(defaultDRepKeyPair . snd <$> allVotes)) - voteTxFp <- signTx execConfig cEra gov "signed-vote-tx" voteTxBodyFp signingKeys - - submitTx execConfig cEra voteTxFp - - waitForGovActionVotes epochStateView (EpochInterval 1) - - txId <- H.noteShowM $ retrieveTransactionId execConfig signedProposalTx - - -- Count votes before checking for ratification. It may happen that the proposal gets removed after - -- ratification because of a long waiting time, so we won't be able to access votes. - govState <- getGovState epochStateView ceo - govActionState <- H.headM $ govState ^. L.cgsProposalsL . L.pPropsL . to toList - let votes = govActionState ^. L.gasDRepVotesL . to toList - - length (filter ((== L.VoteYes) . snd) votes) === 4 - length (filter ((== L.VoteNo) . snd) votes) === 3 - length (filter ((== L.Abstain) . snd) votes) === 2 - length votes === fromIntegral numVotes - - -- We check that constitution was successfully ratified - void . H.leftFailM . H.evalIO . runExceptT $ - foldEpochState - configurationFile - socketPath - FullValidation - (EpochNo 10) - () - (\epochState _ _ -> foldBlocksCheckConstitutionWasRatified constitutionHash constitutionScriptHash epochState) - - proposalsJSON :: Aeson.Value <- execCliStdoutToJson execConfig - [ eraName, "query", "proposals", "--governance-action-tx-id", prettyShow txId - , "--governance-action-index", "0" - ] + -- Query proposals via CLI before voting to verify proposal structure. + -- This is race-free: the proposal cannot be ratified before votes are cast. + -- Retry until the DRep pulsing snapshot (used by `query proposals`) is refreshed + -- with the newly submitted proposal. The current proposals map is updated immediately, but the + -- pulsing snapshot only picks up new proposals at epoch boundaries. + (proposalsJSON, proposalsArray) <- + retryUntilJustM epochStateView (WaitForEpochs $ EpochInterval 2) $ do + json :: Aeson.Value <- execCliStdoutToJson execConfig + [ eraName, "query", "proposals", "--governance-action-tx-id", prettyShow governanceActionTxId + , "--governance-action-index", "0" + ] + pure $ do + arr <- json ^? Aeson._Array + guard (length arr == 1) + pure (json, arr) -- Display JSON returned in case of failure H.note_ $ Text.unpack . decodeUtf8 $ prettyPrintJSON proposalsJSON - - -- Check that the proposals array has only one element and fetch it - proposalsArray <- H.evalMaybe $ proposalsJSON ^? Aeson._Array - length proposalsArray === 1 let proposal = proposalsArray Vector.! 0 -- Check TxId returned is the same as the one we used proposalsTxId <- H.evalMaybe $ proposal ^? Aeson.key "actionId" . Aeson.key "txId" . Aeson._String - proposalsTxId === Text.pack (prettyShow txId) - - -- Check that committeeVotes is an empty object - proposalsCommitteeVotes <- H.evalMaybe $ proposal ^? Aeson.key "committeeVotes" . Aeson._Object - proposalsCommitteeVotes === mempty - - -- Check that dRepVotes has the expected number of votes - proposalsDRepVotes <- H.evalMaybe $ proposal ^? Aeson.key "dRepVotes" . Aeson._Object - length proposalsDRepVotes === numVotes + proposalsTxId === Text.pack (prettyShow governanceActionTxId) -- Fetch proposalProcedure and anchor proposalsProcedure <- H.evalMaybe $ proposal ^? Aeson.key "proposalProcedure" @@ -334,9 +294,73 @@ hprop_ledger_events_propose_new_constitution = integrationRetryWorkspace 2 "prop proposalsTag <- H.evalMaybe $ proposalsProcedure ^? Aeson.key "govAction" . Aeson.key "tag" . Aeson._String proposalsTag === "NewConstitution" - -- Check the stake pool votes are empty - proposalsStakePoolVotes <- H.evalMaybe $ proposal ^? Aeson.key "stakePoolVotes" . Aeson._Object - proposalsStakePoolVotes === mempty + -- Proposal was successfully submitted, now we vote on the proposal and confirm it was ratified + voteFiles <- generateVoteFiles execConfig work "vote-files" + governanceActionTxId governanceActionIndex + [(defaultDRepKeyPair idx, vote) | (vote, idx) <- allVotes] + + -- Submit votes + voteTxBodyFp <- createVotingTxBody execConfig epochStateView sbe work "vote-tx-body" + voteFiles wallet0 + + let signingKeys = Some <$> (paymentKeyInfoPair wallet0:(defaultDRepKeyPair . snd <$> allVotes)) + voteTxFp <- signTx execConfig cEra gov "signed-vote-tx" voteTxBodyFp signingKeys + + submitTx execConfig cEra voteTxFp + + waitForGovActionVotes epochStateView (EpochInterval 1) + + -- Count votes before checking for ratification. It may happen that the proposal gets removed after + -- ratification because of a long waiting time, so we won't be able to access votes. + govState <- getGovState epochStateView ceo + govActionState <- H.headM $ govState ^. L.cgsProposalsL . L.pPropsL . to toList + let votes = govActionState ^. L.gasDRepVotesL . to toList + + length (filter ((== L.VoteYes) . snd) votes) === 4 + length (filter ((== L.VoteNo) . snd) votes) === 3 + length (filter ((== L.Abstain) . snd) votes) === 2 + length votes === fromIntegral numVotes + + -- Query proposals via CLI to verify vote counts are reported correctly. + -- The proposal may have been ratified at an epoch boundary between the ledger check above and this + -- CLI query, in which case the proposal is removed from gov-state and the query returns []. + -- The pulsing snapshot may also not yet include the votes even though they are in the ledger state. + -- The ledger-level vote checks above already verified correctness, so we skip gracefully in both cases. + votedProposalsJSON :: Aeson.Value <- execCliStdoutToJson execConfig + [ eraName, "query", "proposals", "--governance-action-tx-id", prettyShow governanceActionTxId + , "--governance-action-index", "0" + ] + + H.note_ $ Text.unpack . decodeUtf8 $ prettyPrintJSON votedProposalsJSON + + votedProposalsArray <- H.evalMaybe $ votedProposalsJSON ^? Aeson._Array + unless (null votedProposalsArray) $ do + length votedProposalsArray === 1 + let votedProposal = votedProposalsArray Vector.! 0 + + -- Check that dRepVotes has the expected number of votes + proposalsDRepVotes <- H.evalMaybe $ votedProposal ^? Aeson.key "dRepVotes" . Aeson._Object + -- Skip if the pulsing snapshot has not yet refreshed with votes + unless (null proposalsDRepVotes) $ do + length proposalsDRepVotes === numVotes + + -- Check that committeeVotes is an empty object + proposalsCommitteeVotes <- H.evalMaybe $ votedProposal ^? Aeson.key "committeeVotes" . Aeson._Object + proposalsCommitteeVotes === mempty + + -- Check the stake pool votes are empty + proposalsStakePoolVotes <- H.evalMaybe $ votedProposal ^? Aeson.key "stakePoolVotes" . Aeson._Object + proposalsStakePoolVotes === mempty + + -- We check that constitution was successfully ratified + void . H.leftFailM . H.evalIO . runExceptT $ + foldEpochState + configurationFile + socketPath + FullValidation + (EpochNo 10) + () + (\epochState _ _ -> foldBlocksCheckConstitutionWasRatified constitutionHash constitutionScriptHash epochState) foldBlocksCheckConstitutionWasRatified :: String -- submitted constitution hash diff --git a/cardano-testnet/test/cardano-testnet-test/files/golden/queries/govStateOut.json b/cardano-testnet/test/cardano-testnet-test/files/golden/queries/govStateOut.json index ec713c7fd2a..8984e8ce8d2 100644 --- a/cardano-testnet/test/cardano-testnet-test/files/golden/queries/govStateOut.json +++ b/cardano-testnet/test/cardano-testnet-test/files/golden/queries/govStateOut.json @@ -414,7 +414,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -424,9 +424,9 @@ 42921, 4, 2, - 30623, - 28755, - 75, + 24548, + 29498, + 38, 1, 898148, 27279, @@ -479,7 +479,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -495,7 +495,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -506,7 +506,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -1092,7 +1092,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -1102,9 +1102,9 @@ 42921, 4, 2, - 30623, - 28755, - 75, + 24548, + 29498, + 38, 1, 898148, 27279, @@ -1157,7 +1157,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -1173,7 +1173,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -1184,7 +1184,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -1759,7 +1759,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -1769,9 +1769,9 @@ 42921, 4, 2, - 30623, - 28755, - 75, + 24548, + 29498, + 38, 1, 898148, 27279, @@ -1824,7 +1824,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -1840,7 +1840,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -1851,7 +1851,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -2423,7 +2423,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -2433,9 +2433,9 @@ 42921, 4, 2, - 30623, - 28755, - 75, + 24548, + 29498, + 38, 1, 898148, 27279, @@ -2488,7 +2488,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -2504,7 +2504,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -2515,7 +2515,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, diff --git a/cardano-testnet/test/cardano-testnet-test/files/golden/queries/protocolParametersFileOut.json b/cardano-testnet/test/cardano-testnet-test/files/golden/queries/protocolParametersFileOut.json index e96183cc046..f8156095026 100644 --- a/cardano-testnet/test/cardano-testnet-test/files/golden/queries/protocolParametersFileOut.json +++ b/cardano-testnet/test/cardano-testnet-test/files/golden/queries/protocolParametersFileOut.json @@ -403,7 +403,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -413,9 +413,9 @@ 42921, 4, 2, - 30623, - 28755, - 75, + 24548, + 29498, + 38, 1, 898148, 27279, @@ -468,7 +468,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -484,7 +484,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -495,7 +495,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, diff --git a/cardano-testnet/test/cardano-testnet-test/files/golden/queries/protocolParametersOut.txt b/cardano-testnet/test/cardano-testnet-test/files/golden/queries/protocolParametersOut.txt index e96183cc046..f8156095026 100644 --- a/cardano-testnet/test/cardano-testnet-test/files/golden/queries/protocolParametersOut.txt +++ b/cardano-testnet/test/cardano-testnet-test/files/golden/queries/protocolParametersOut.txt @@ -403,7 +403,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -413,9 +413,9 @@ 42921, 4, 2, - 30623, - 28755, - 75, + 24548, + 29498, + 38, 1, 898148, 27279, @@ -468,7 +468,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -484,7 +484,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0, @@ -495,7 +495,7 @@ 7305, -900, 1716, - 960, + 549, 57, 85848, 0,