diff --git a/cardano-api/cardano-api.cabal b/cardano-api/cardano-api.cabal index 82ba704224..e8d1355e1a 100644 --- a/cardano-api/cardano-api.cabal +++ b/cardano-api/cardano-api.cabal @@ -227,6 +227,7 @@ library Cardano.Api.Experimental.Tx.Internal.AnyWitness Cardano.Api.Experimental.Tx.Internal.Body Cardano.Api.Experimental.Tx.Internal.Certificate + Cardano.Api.Experimental.Tx.Internal.Compatible Cardano.Api.Experimental.Tx.Internal.Fee Cardano.Api.Experimental.Tx.Internal.TxScriptWitnessRequirements Cardano.Api.Genesis.Internal diff --git a/cardano-api/gen/Test/Gen/Cardano/Api/Typed.hs b/cardano-api/gen/Test/Gen/Cardano/Api/Typed.hs index 08800a9a64..595e831fb0 100644 --- a/cardano-api/gen/Test/Gen/Cardano/Api/Typed.hs +++ b/cardano-api/gen/Test/Gen/Cardano/Api/Typed.hs @@ -792,21 +792,33 @@ genTxCertificates = certs <- Gen.list (Range.constant 0 3) $ genCertificate w Gen.choice [ pure TxCertificatesNone - , pure (TxCertificates w $ fromList ((,BuildTxWith Nothing) <$> certs)) - -- TODO: Generate certificates + , pure + ( TxCertificates w $ + fromList ((,BuildTxWith Nothing) <$> map extractCertificate certs) + ) + -- TODO: Generate certificates ] ) +extractCertificate + :: Api.Certificate era + -> Exp.Certificate (ShelleyLedgerEra era) +extractCertificate (Api.ShelleyRelatedCertificate w c) = + shelleyToBabbageEraConstraints w $ Exp.Certificate c +extractCertificate (ConwayCertificate w c) = + conwayEraOnwardsConstraints w $ Exp.Certificate c + genScriptWitnessedTxCertificates :: Typeable era => Exp.Era era -> Gen (TxCertificates BuildTx era) genScriptWitnessedTxCertificates era = do let w = convert era num <- Gen.integral (Range.linear 0 3) certs <- Gen.list (Range.singleton num) $ genCertificate w - plutusScriptWits <- Gen.list (Range.singleton num) $ genApiPlutusScriptWitness WitCtxStake era + plutusScriptWits <- + Gen.list (Range.singleton num) $ genApiPlutusScriptWitness WitCtxStake era let certsAndWits = zipWith (\c p -> (c, Just p)) - certs + (map extractCertificate certs) plutusScriptWits pure $ mkTxCertificates (convert era) certsAndWits diff --git a/cardano-api/src/Cardano/Api/Certificate/Internal.hs b/cardano-api/src/Cardano/Api/Certificate/Internal.hs index 301e4d97f7..7924d9bf69 100644 --- a/cardano-api/src/Cardano/Api/Certificate/Internal.hs +++ b/cardano-api/src/Cardano/Api/Certificate/Internal.hs @@ -76,6 +76,7 @@ module Cardano.Api.Certificate.Internal , certificateToTxCert , filterUnRegCreds , filterUnRegDRepCreds + , getTxCertWitness , isDRepRegOrUpdateCert ) where @@ -85,6 +86,7 @@ import Cardano.Api.Certificate.Internal.DRepMetadata import Cardano.Api.Certificate.Internal.StakePoolMetadata import Cardano.Api.Era import Cardano.Api.Error (Error (..)) +import Cardano.Api.Experimental.Tx.Internal.Certificate qualified as Exp import Cardano.Api.Governance.Internal.Action.VotingProcedure import Cardano.Api.HasTypeProxy import Cardano.Api.Internal.Utils (noInlineMaybeToStrictMaybe) @@ -103,6 +105,7 @@ import Cardano.Ledger.Coin qualified as L import Cardano.Ledger.Keys qualified as Ledger import Cardano.Ledger.State qualified as Ledger +import Control.Monad import Control.Monad.Except (MonadError (..)) import Data.ByteString (ByteString) import Data.ByteString qualified as BS @@ -120,6 +123,8 @@ import Network.Socket (PortNumber) -- Certificates embedded in transactions -- +{-# DEPRECATED Certificate "Use `Certificate` type from Cardano.Api.Experimental.Tx.Internal.Certificate instead" #-} + data Certificate era where -- Pre-Conway -- 1. Stake registration @@ -567,60 +572,21 @@ selectStakeCredentialWitness = \case getTxCertWitness (convert cEra) conwayCert filterUnRegCreds - :: Certificate era -> Maybe StakeCredential -filterUnRegCreds = - fmap fromShelleyStakeCredential . \case - ShelleyRelatedCertificate stbEra shelleyCert -> shelleyToBabbageEraConstraints stbEra $ - case shelleyCert of - Ledger.RegTxCert _ -> Nothing - Ledger.UnRegTxCert cred -> Just cred - Ledger.DelegStakeTxCert _ _ -> Nothing - Ledger.RegPoolTxCert _ -> Nothing - Ledger.RetirePoolTxCert _ _ -> Nothing - Ledger.MirTxCert _ -> Nothing - Ledger.GenesisDelegTxCert{} -> Nothing - _ -> error "dijkstra" - ConwayCertificate cEra conwayCert -> conwayEraOnwardsConstraints cEra $ - case conwayCert of - Ledger.RegPoolTxCert _ -> Nothing - Ledger.RetirePoolTxCert _ _ -> Nothing - Ledger.RegDepositTxCert _ _ -> Nothing - Ledger.UnRegDepositTxCert cred _ -> Just cred - Ledger.DelegTxCert _ _ -> Nothing - Ledger.RegDepositDelegTxCert{} -> Nothing - Ledger.AuthCommitteeHotKeyTxCert{} -> Nothing - Ledger.ResignCommitteeColdTxCert{} -> Nothing - Ledger.RegDRepTxCert{} -> Nothing - Ledger.UnRegDRepTxCert{} -> Nothing - Ledger.UpdateDRepTxCert{} -> Nothing - -- those are old shelley patterns - Ledger.RegTxCert _ -> Nothing - -- stake cred deregistration w/o deposit - Ledger.UnRegTxCert cred -> Just cred - _ -> error "dijkstra" + :: ShelleyBasedEra era -> Exp.Certificate (ShelleyLedgerEra era) -> Maybe StakeCredential +filterUnRegCreds sbe (Exp.Certificate cert) = + fmap fromShelleyStakeCredential $ + shelleyBasedEraConstraints sbe $ + Ledger.lookupUnRegStakeTxCert cert filterUnRegDRepCreds - :: Certificate era -> Maybe (Ledger.Credential Ledger.DRepRole) -filterUnRegDRepCreds = \case - ShelleyRelatedCertificate _ _ -> Nothing - ConwayCertificate cEra conwayCert -> conwayEraOnwardsConstraints cEra $ - case conwayCert of - Ledger.RegPoolTxCert _ -> Nothing - Ledger.RetirePoolTxCert _ _ -> Nothing - Ledger.RegDepositTxCert _ _ -> Nothing - Ledger.UnRegDepositTxCert _ _ -> Nothing - Ledger.DelegTxCert _ _ -> Nothing - Ledger.RegDepositDelegTxCert{} -> Nothing - Ledger.AuthCommitteeHotKeyTxCert{} -> Nothing - Ledger.ResignCommitteeColdTxCert{} -> Nothing - Ledger.RegDRepTxCert{} -> Nothing - Ledger.UnRegDRepTxCert cred _ -> Just cred - Ledger.UpdateDRepTxCert{} -> Nothing - -- those are old shelley patterns - Ledger.RegTxCert _ -> Nothing - -- stake cred deregistration w/o deposit - Ledger.UnRegTxCert _ -> Nothing - _ -> error "dijkstra" + :: ShelleyBasedEra era + -> Exp.Certificate (ShelleyLedgerEra era) + -> Maybe (Ledger.Credential Ledger.DRepRole) +filterUnRegDRepCreds sbe (Exp.Certificate cert) = + join $ forEraInEonMaybe (toCardanoEra sbe) $ \w -> + conwayEraOnwardsConstraints w $ + fst + <$> Ledger.getUnRegDRepTxCert cert -- ---------------------------------------------------------------------------- -- Internal conversion functions diff --git a/cardano-api/src/Cardano/Api/Compatible/Tx.hs b/cardano-api/src/Cardano/Api/Compatible/Tx.hs index fe7d8d0f6d..cd6e894652 100644 --- a/cardano-api/src/Cardano/Api/Compatible/Tx.hs +++ b/cardano-api/src/Cardano/Api/Compatible/Tx.hs @@ -16,8 +16,8 @@ module Cardano.Api.Compatible.Tx where import Cardano.Api.Address (StakeCredential) -import Cardano.Api.Certificate.Internal (Certificate) import Cardano.Api.Era +import Cardano.Api.Experimental.Tx.Internal.Certificate qualified as Exp import Cardano.Api.Plutus.Internal.Script import Cardano.Api.ProtocolParameters import Cardano.Api.Tx.Internal.Body @@ -155,7 +155,12 @@ createCompatibleTx sbe ins outs txFee' anyProtocolUpdate anyVote txCertificates' (L.bodyTxL . L.votingProceduresTxBodyL) .~ votingProcedures indexedTxCerts - :: [(ScriptWitnessIndex, Certificate era, StakeCredential, Witness WitCtxStake era)] + :: [ ( ScriptWitnessIndex + , Exp.Certificate (ShelleyLedgerEra era) + , StakeCredential + , Witness WitCtxStake era + ) + ] indexedTxCerts = indexTxCertificates txCertificates' setScriptWitnesses diff --git a/cardano-api/src/Cardano/Api/Experimental.hs b/cardano-api/src/Cardano/Api/Experimental.hs index 6cc38948ea..73581f7c84 100644 --- a/cardano-api/src/Cardano/Api/Experimental.hs +++ b/cardano-api/src/Cardano/Api/Experimental.hs @@ -22,8 +22,8 @@ module Cardano.Api.Experimental , hashTxBody , evaluateTransactionExecutionUnitsShelley , Certificate (..) - , convertToNewCertificate - , convertToOldApiCertificate + , AnchorDataFromCertificateError (..) + , getAnchorDataFromCertificate , mkTxCertificates -- ** Transaction fee related @@ -78,5 +78,6 @@ import Cardano.Api.Experimental.Plutus.Internal.Shim.LegacyScripts import Cardano.Api.Experimental.Simple.Script import Cardano.Api.Experimental.Tx import Cardano.Api.Experimental.Tx.Internal.Certificate +import Cardano.Api.Experimental.Tx.Internal.Compatible import Cardano.Api.Experimental.Tx.Internal.Fee import Cardano.Api.Tx.Internal.Fee (evaluateTransactionExecutionUnitsShelley) diff --git a/cardano-api/src/Cardano/Api/Experimental/Era.hs b/cardano-api/src/Cardano/Api/Experimental/Era.hs index 8effb65f7d..fc05d4debe 100644 --- a/cardano-api/src/Cardano/Api/Experimental/Era.hs +++ b/cardano-api/src/Cardano/Api/Experimental/Era.hs @@ -33,7 +33,8 @@ module Cardano.Api.Experimental.Era ) where -import Cardano.Api.Consensus +import Cardano.Api.Consensus.Internal.Mode +import Cardano.Api.Consensus.Internal.Reexport import Cardano.Api.Era qualified as Api import Cardano.Api.Era.Internal.Core (BabbageEra, ConwayEra, DijkstraEra, Eon (..)) import Cardano.Api.Era.Internal.Eon.AlonzoEraOnwards diff --git a/cardano-api/src/Cardano/Api/Experimental/Tx/Internal/Certificate.hs b/cardano-api/src/Cardano/Api/Experimental/Tx/Internal/Certificate.hs index 651b89d568..7ec62384d4 100644 --- a/cardano-api/src/Cardano/Api/Experimental/Tx/Internal/Certificate.hs +++ b/cardano-api/src/Cardano/Api/Experimental/Tx/Internal/Certificate.hs @@ -1,11 +1,10 @@ -{-# LANGUAGE EmptyCase #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} +{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} @@ -13,39 +12,28 @@ module Cardano.Api.Experimental.Tx.Internal.Certificate ( Certificate (..) - , mkTxCertificates - , convertToOldApiCertificate - , convertToNewCertificate + , AnchorDataFromCertificateError (..) + , getAnchorDataFromCertificate ) where -import Cardano.Api.Address qualified as Api -import Cardano.Api.Certificate.Internal qualified as Api -import Cardano.Api.Era.Internal.Core (DijkstraEra) -import Cardano.Api.Era.Internal.Eon.Convert import Cardano.Api.Era.Internal.Eon.ShelleyBasedEra -import Cardano.Api.Era.Internal.Eon.ShelleyToBabbageEra qualified as Api +import Cardano.Api.Error import Cardano.Api.Experimental.Era -import Cardano.Api.Experimental.Plutus.Internal.Script qualified as Exp -import Cardano.Api.Experimental.Plutus.Internal.ScriptWitness qualified as Exp -import Cardano.Api.Experimental.Simple.Script qualified as Exp -import Cardano.Api.Experimental.Tx.Internal.AnyWitness import Cardano.Api.HasTypeProxy import Cardano.Api.Ledger qualified as L -import Cardano.Api.Plutus.Internal.Script -import Cardano.Api.Plutus.Internal.Script qualified as Api +import Cardano.Api.Ledger.Internal.Reexport qualified as Ledger +import Cardano.Api.Pretty import Cardano.Api.Serialise.Cbor import Cardano.Api.Serialise.TextEnvelope.Internal -import Cardano.Api.Tx.Internal.Body (TxCertificates (..)) -import Cardano.Api.Tx.Internal.Body qualified as Api import Cardano.Binary qualified as CBOR -import Cardano.Ledger.Allegra.Scripts qualified as L -import Cardano.Ledger.Plutus.Language qualified as L -import Cardano.Ledger.Plutus.Language qualified as Plutus +import Cardano.Ledger.BaseTypes (strictMaybe) +import Control.Monad.Error.Class +import Data.ByteString (ByteString) +import Data.String import Data.Typeable -import GHC.IsList data Certificate era where Certificate :: L.EraTxCert era => L.TxCert era -> Certificate era @@ -81,130 +69,62 @@ instance deserialiseFromCBOR _ bs = shelleyBasedEraConstraints (shelleyBasedEra @era) $ Certificate <$> CBOR.decodeFull' bs -convertToOldApiCertificate :: Era era -> Certificate (LedgerEra era) -> Api.Certificate era -convertToOldApiCertificate e@ConwayEra (Certificate cert) = - obtainConwayConstraints e $ Api.ConwayCertificate (convert e) cert -convertToOldApiCertificate DijkstraEra _ = error "Dijkstra era not supported yet" - -convertToNewCertificate :: Era era -> Api.Certificate era -> Certificate (LedgerEra era) -convertToNewCertificate era (Api.ConwayCertificate _ cert) = - case era of - ConwayEra -> Certificate cert - DijkstraEra -> error "convertToNewCertificate: DijkstraEra not supported" -convertToNewCertificate era (Api.ShelleyRelatedCertificate sToBab _) = - case era of - ConwayEra -> case sToBab :: Api.ShelleyToBabbageEra ConwayEra of {} - DijkstraEra -> case sToBab :: Api.ShelleyToBabbageEra DijkstraEra of {} - -mkTxCertificates - :: forall era - . IsEra era - => [(Certificate (LedgerEra era), AnyWitness (LedgerEra era))] - -> Api.TxCertificates Api.BuildTx era -mkTxCertificates [] = TxCertificatesNone -mkTxCertificates certs = - TxCertificates (convert useEra) $ fromList $ map (getStakeCred useEra) certs - -getStakeCred - :: Era era - -> (Certificate (LedgerEra era), AnyWitness (LedgerEra era)) - -> ( Api.Certificate era - , Api.BuildTxWith - Api.BuildTx - (Maybe (Api.StakeCredential, Api.Witness Api.WitCtxStake era)) - ) -getStakeCred e@ConwayEra (Certificate cert, witness) = do - let oldApiCert = obtainConwayConstraints e $ Api.ConwayCertificate (convert e) cert - mStakeCred = Api.selectStakeCredentialWitness oldApiCert - wit = - case witness of - AnyKeyWitnessPlaceholder -> Api.KeyWitness Api.KeyWitnessForStakeAddr - AnySimpleScriptWitness ss -> - Api.ScriptWitness Api.ScriptWitnessForStakeAddr $ - obtainCommonConstraints e $ - newToOldSimpleScriptWitness e ss - AnyPlutusScriptWitness psw -> - Api.ScriptWitness Api.ScriptWitnessForStakeAddr $ - newToOldPlutusCertificateScriptWitness e psw - (oldApiCert, pure $ (,wit) <$> mStakeCred) -getStakeCred DijkstraEra _ = error "Dijkstra era not supported yet" - -newToOldSimpleScriptWitness - :: L.AllegraEraScript (LedgerEra era) - => Era era -> Exp.SimpleScriptOrReferenceInput (LedgerEra era) -> Api.ScriptWitness Api.WitCtxStake era -newToOldSimpleScriptWitness era simple = - case simple of - Exp.SScript (Exp.SimpleScript script) -> - Api.SimpleScriptWitness - (sbeToSimpleScriptLanguageInEra $ convert era) - (Api.SScript $ fromAllegraTimelock script) - Exp.SReferenceScript inp -> - Api.SimpleScriptWitness - (sbeToSimpleScriptLanguageInEra $ convert era) - (Api.SReferenceScript inp) - -newToOldPlutusCertificateScriptWitness - :: Era era - -> Exp.PlutusScriptWitness lang purpose (LedgerEra era) - -> Api.ScriptWitness Api.WitCtxStake era -newToOldPlutusCertificateScriptWitness ConwayEra (Exp.PlutusScriptWitness Plutus.SPlutusV1 scriptOrRef _ redeemer execUnits) = - Api.PlutusScriptWitness - Api.PlutusScriptV1InConway - Api.PlutusScriptV1 - (newToOldPlutusScriptOrReferenceInput ConwayEra scriptOrRef) - Api.NoScriptDatumForStake - redeemer - execUnits -newToOldPlutusCertificateScriptWitness ConwayEra (Exp.PlutusScriptWitness Plutus.SPlutusV2 scriptOrRef _ redeemer execUnits) = - Api.PlutusScriptWitness - Api.PlutusScriptV2InConway - Api.PlutusScriptV2 - (newToOldPlutusScriptOrReferenceInput ConwayEra scriptOrRef) - Api.NoScriptDatumForStake - redeemer - execUnits -newToOldPlutusCertificateScriptWitness ConwayEra (Exp.PlutusScriptWitness Plutus.SPlutusV3 scriptOrRef _ redeemer execUnits) = - Api.PlutusScriptWitness - Api.PlutusScriptV3InConway - Api.PlutusScriptV3 - (newToOldPlutusScriptOrReferenceInput ConwayEra scriptOrRef) - Api.NoScriptDatumForStake - redeemer - execUnits -newToOldPlutusCertificateScriptWitness ConwayEra (Exp.PlutusScriptWitness Plutus.SPlutusV4 _scriptOrRef _ _redeemer _execUnits) = - error "dijkstra" -newToOldPlutusCertificateScriptWitness DijkstraEra (Exp.PlutusScriptWitness Plutus.SPlutusV1 scriptOrRef _ redeemer execUnits) = - Api.PlutusScriptWitness - Api.PlutusScriptV1InDijkstra - Api.PlutusScriptV1 - (newToOldPlutusScriptOrReferenceInput DijkstraEra scriptOrRef) - Api.NoScriptDatumForStake - redeemer - execUnits -newToOldPlutusCertificateScriptWitness DijkstraEra (Exp.PlutusScriptWitness Plutus.SPlutusV2 scriptOrRef _ redeemer execUnits) = - Api.PlutusScriptWitness - Api.PlutusScriptV2InDijkstra - Api.PlutusScriptV2 - (newToOldPlutusScriptOrReferenceInput DijkstraEra scriptOrRef) - Api.NoScriptDatumForStake - redeemer - execUnits -newToOldPlutusCertificateScriptWitness DijkstraEra (Exp.PlutusScriptWitness Plutus.SPlutusV3 scriptOrRef _ redeemer execUnits) = - Api.PlutusScriptWitness - Api.PlutusScriptV3InDijkstra - Api.PlutusScriptV3 - (newToOldPlutusScriptOrReferenceInput DijkstraEra scriptOrRef) - Api.NoScriptDatumForStake - redeemer - execUnits -newToOldPlutusCertificateScriptWitness DijkstraEra (Exp.PlutusScriptWitness Plutus.SPlutusV4 _scriptOrRef _ _redeemer _execUnits) = - error "dijkstra" - -newToOldPlutusScriptOrReferenceInput +getAnchorDataFromCertificate :: Era era - -> Exp.PlutusScriptOrReferenceInput lang (LedgerEra era) - -> Api.PlutusScriptOrReferenceInput oldlang -newToOldPlutusScriptOrReferenceInput _ (Exp.PReferenceScript txin) = Api.PReferenceScript txin -newToOldPlutusScriptOrReferenceInput _ (Exp.PScript (Exp.PlutusScriptInEra plutusRunnable)) = - let oldScript = L.unPlutusBinary . L.plutusBinary $ L.plutusFromRunnable plutusRunnable - in Api.PScript $ Api.PlutusScriptSerialised oldScript + -> Certificate (LedgerEra era) + -> Either AnchorDataFromCertificateError (Maybe Ledger.Anchor) +getAnchorDataFromCertificate ConwayEra (Certificate c) = + case c of + Ledger.RegTxCert _ -> return Nothing + Ledger.UnRegTxCert _ -> return Nothing + Ledger.RegDepositTxCert _ _ -> return Nothing + Ledger.UnRegDepositTxCert _ _ -> return Nothing + Ledger.RegDepositDelegTxCert{} -> return Nothing + Ledger.DelegTxCert{} -> return Nothing + Ledger.RegPoolTxCert poolParams -> strictMaybe (return Nothing) anchorDataFromPoolMetadata $ Ledger.ppMetadata poolParams + Ledger.RetirePoolTxCert _ _ -> return Nothing + Ledger.RegDRepTxCert _ _ mAnchor -> return $ Ledger.strictMaybeToMaybe mAnchor + Ledger.UnRegDRepTxCert _ _ -> return Nothing + Ledger.UpdateDRepTxCert _ mAnchor -> return $ Ledger.strictMaybeToMaybe mAnchor + Ledger.AuthCommitteeHotKeyTxCert _ _ -> return Nothing + Ledger.ResignCommitteeColdTxCert _ mAnchor -> return $ Ledger.strictMaybeToMaybe mAnchor + _ -> error "getAnchorDataFromCertificate: Unrecognized cert" +getAnchorDataFromCertificate DijkstraEra (Certificate c) = + case c of + Ledger.RegDepositTxCert _ _ -> return Nothing + Ledger.UnRegDepositTxCert _ _ -> return Nothing + Ledger.RegDepositDelegTxCert{} -> return Nothing + Ledger.DelegTxCert{} -> return Nothing + Ledger.RegPoolTxCert poolParams -> strictMaybe (return Nothing) anchorDataFromPoolMetadata $ Ledger.ppMetadata poolParams + Ledger.RetirePoolTxCert _ _ -> return Nothing + Ledger.RegDRepTxCert _ _ mAnchor -> return $ Ledger.strictMaybeToMaybe mAnchor + Ledger.UnRegDRepTxCert _ _ -> return Nothing + Ledger.UpdateDRepTxCert _ mAnchor -> return $ Ledger.strictMaybeToMaybe mAnchor + Ledger.AuthCommitteeHotKeyTxCert _ _ -> return Nothing + Ledger.ResignCommitteeColdTxCert _ mAnchor -> return $ Ledger.strictMaybeToMaybe mAnchor + _ -> error "getAnchorDataFromCertificate: Unrecognized cert" + +anchorDataFromPoolMetadata + :: MonadError AnchorDataFromCertificateError m + => Ledger.PoolMetadata + -> m (Maybe Ledger.Anchor) +anchorDataFromPoolMetadata (Ledger.PoolMetadata{Ledger.pmUrl = url, Ledger.pmHash = hashBytes}) = do + hash <- + maybe (throwError $ InvalidPoolMetadataHashError url hashBytes) return $ + Ledger.hashFromBytes hashBytes + return $ + Just + ( Ledger.Anchor + { Ledger.anchorUrl = url + , Ledger.anchorDataHash = Ledger.unsafeMakeSafeHash hash + } + ) + +data AnchorDataFromCertificateError + = InvalidPoolMetadataHashError Ledger.Url ByteString + deriving (Eq, Show) + +instance Error AnchorDataFromCertificateError where + prettyError :: AnchorDataFromCertificateError -> Doc ann + prettyError (InvalidPoolMetadataHashError url hash) = + "Invalid pool metadata hash for URL " <> pretty url <> ": " <> fromString (show hash) diff --git a/cardano-api/src/Cardano/Api/Experimental/Tx/Internal/Compatible.hs b/cardano-api/src/Cardano/Api/Experimental/Tx/Internal/Compatible.hs new file mode 100644 index 0000000000..497811fda5 --- /dev/null +++ b/cardano-api/src/Cardano/Api/Experimental/Tx/Internal/Compatible.hs @@ -0,0 +1,161 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE TupleSections #-} + +module Cardano.Api.Experimental.Tx.Internal.Compatible + ( mkTxCertificates + ) +where + +import Cardano.Api.Address qualified as Api +import Cardano.Api.Certificate.Internal qualified as Api +import Cardano.Api.Era.Internal.Eon.Convert +import Cardano.Api.Era.Internal.Eon.ShelleyBasedEra +import Cardano.Api.Experimental.Era +import Cardano.Api.Experimental.Plutus.Internal.Script qualified as Exp +import Cardano.Api.Experimental.Plutus.Internal.ScriptWitness qualified as Exp +import Cardano.Api.Experimental.Simple.Script qualified as Exp +import Cardano.Api.Experimental.Tx.Internal.AnyWitness +import Cardano.Api.Experimental.Tx.Internal.Certificate qualified as Exp +import Cardano.Api.Ledger.Internal.Reexport qualified as L +import Cardano.Api.Plutus.Internal.Script (fromAllegraTimelock, sbeToSimpleScriptLanguageInEra) +import Cardano.Api.Plutus.Internal.Script qualified as Api +import Cardano.Api.Tx.Internal.Body (TxCertificates (..)) +import Cardano.Api.Tx.Internal.Body qualified as Api + +import Cardano.Ledger.Allegra.Scripts qualified as L +import Cardano.Ledger.Alonzo.Scripts qualified as L +import Cardano.Ledger.Plutus.Language qualified as L +import Cardano.Ledger.Plutus.Language qualified as Plutus + +import GHC.Exts (IsList (..)) + +mkTxCertificates + :: forall era + . IsEra era + => [(Exp.Certificate (ShelleyLedgerEra era), AnyWitness (LedgerEra era))] + -> Api.TxCertificates Api.BuildTx era +mkTxCertificates [] = TxCertificatesNone +mkTxCertificates certs = + TxCertificates (convert useEra) $ fromList $ map (getStakeCred useEra) certs + where + getStakeCred + :: Era era + -> (Exp.Certificate (ShelleyLedgerEra era), AnyWitness (LedgerEra era)) + -> ( Exp.Certificate (ShelleyLedgerEra era) + , Api.BuildTxWith + Api.BuildTx + (Maybe (Api.StakeCredential, Api.Witness Api.WitCtxStake era)) + ) + getStakeCred era (cert, witness) = + case era of + ConwayEra -> do + let Exp.Certificate c = cert + mStakeCred = Api.getTxCertWitness (convert era) c + wit = + case witness of + AnyKeyWitnessPlaceholder -> Api.KeyWitness Api.KeyWitnessForStakeAddr + AnySimpleScriptWitness ss -> + Api.ScriptWitness Api.ScriptWitnessForStakeAddr $ newToOldSimpleScriptWitness era ss + AnyPlutusScriptWitness psw -> + Api.ScriptWitness Api.ScriptWitnessForStakeAddr $ + newToOldPlutusCertificateScriptWitness ConwayEra psw + (cert, pure $ (,wit) <$> mStakeCred) + DijkstraEra -> do + let Exp.Certificate c = cert + mStakeCred = Api.getTxCertWitness (convert era) c + wit = + case witness of + AnyKeyWitnessPlaceholder -> Api.KeyWitness Api.KeyWitnessForStakeAddr + AnySimpleScriptWitness ss -> + Api.ScriptWitness Api.ScriptWitnessForStakeAddr $ newToOldSimpleScriptWitness era ss + AnyPlutusScriptWitness psw -> + Api.ScriptWitness Api.ScriptWitnessForStakeAddr $ + newToOldPlutusCertificateScriptWitness DijkstraEra psw + (cert, pure $ (,wit) <$> mStakeCred) + +newToOldSimpleScriptWitness + :: L.AllegraEraScript (LedgerEra era) + => Era era -> Exp.SimpleScriptOrReferenceInput (LedgerEra era) -> Api.ScriptWitness Api.WitCtxStake era +newToOldSimpleScriptWitness era simple = + case simple of + Exp.SScript (Exp.SimpleScript script) -> + Api.SimpleScriptWitness + (sbeToSimpleScriptLanguageInEra $ convert era) + (Api.SScript $ fromAllegraTimelock script) + Exp.SReferenceScript inp -> + Api.SimpleScriptWitness + (sbeToSimpleScriptLanguageInEra $ convert era) + (Api.SReferenceScript inp) + +newToOldPlutusCertificateScriptWitness + :: Era era + -> Exp.PlutusScriptWitness lang purpose (LedgerEra era) + -> Api.ScriptWitness Api.WitCtxStake era +newToOldPlutusCertificateScriptWitness ConwayEra (Exp.PlutusScriptWitness Plutus.SPlutusV1 scriptOrRef _ redeemer execUnits) = + Api.PlutusScriptWitness + Api.PlutusScriptV1InConway + Api.PlutusScriptV1 + (newToOldPlutusScriptOrReferenceInput scriptOrRef) + Api.NoScriptDatumForStake + redeemer + execUnits +newToOldPlutusCertificateScriptWitness ConwayEra (Exp.PlutusScriptWitness Plutus.SPlutusV2 scriptOrRef _ redeemer execUnits) = + Api.PlutusScriptWitness + Api.PlutusScriptV2InConway + Api.PlutusScriptV2 + (newToOldPlutusScriptOrReferenceInput scriptOrRef) + Api.NoScriptDatumForStake + redeemer + execUnits +newToOldPlutusCertificateScriptWitness ConwayEra (Exp.PlutusScriptWitness Plutus.SPlutusV3 scriptOrRef _ redeemer execUnits) = + Api.PlutusScriptWitness + Api.PlutusScriptV3InConway + Api.PlutusScriptV3 + (newToOldPlutusScriptOrReferenceInput scriptOrRef) + Api.NoScriptDatumForStake + redeemer + execUnits +newToOldPlutusCertificateScriptWitness ConwayEra (Exp.PlutusScriptWitness Plutus.SPlutusV4 _ _ _ _) = + error "newToOldPlutusCertificateScriptWitness: PlutusV4 script not possible in Conway era" +newToOldPlutusCertificateScriptWitness DijkstraEra (Exp.PlutusScriptWitness Plutus.SPlutusV1 scriptOrRef _ redeemer execUnits) = + Api.PlutusScriptWitness + Api.PlutusScriptV1InDijkstra + Api.PlutusScriptV1 + (newToOldPlutusScriptOrReferenceInput scriptOrRef) + Api.NoScriptDatumForStake + redeemer + execUnits +newToOldPlutusCertificateScriptWitness DijkstraEra (Exp.PlutusScriptWitness Plutus.SPlutusV2 scriptOrRef _ redeemer execUnits) = + Api.PlutusScriptWitness + Api.PlutusScriptV2InDijkstra + Api.PlutusScriptV2 + (newToOldPlutusScriptOrReferenceInput scriptOrRef) + Api.NoScriptDatumForStake + redeemer + execUnits +newToOldPlutusCertificateScriptWitness DijkstraEra (Exp.PlutusScriptWitness Plutus.SPlutusV3 scriptOrRef _ redeemer execUnits) = + Api.PlutusScriptWitness + Api.PlutusScriptV3InDijkstra + Api.PlutusScriptV3 + (newToOldPlutusScriptOrReferenceInput scriptOrRef) + Api.NoScriptDatumForStake + redeemer + execUnits +newToOldPlutusCertificateScriptWitness DijkstraEra (Exp.PlutusScriptWitness Plutus.SPlutusV4 scriptOrRef _ redeemer execUnits) = + Api.PlutusScriptWitness + Api.PlutusScriptV4InDijkstra + Api.PlutusScriptV4 + (newToOldPlutusScriptOrReferenceInput scriptOrRef) + Api.NoScriptDatumForStake + redeemer + execUnits + +newToOldPlutusScriptOrReferenceInput + :: Exp.PlutusScriptOrReferenceInput lang (LedgerEra era) + -> Api.PlutusScriptOrReferenceInput oldlang +newToOldPlutusScriptOrReferenceInput (Exp.PReferenceScript txin) = Api.PReferenceScript txin +newToOldPlutusScriptOrReferenceInput (Exp.PScript (Exp.PlutusScriptInEra plutusRunnable)) = + let oldScript = L.unPlutusBinary . L.plutusBinary $ L.plutusFromRunnable plutusRunnable + in Api.PScript $ Api.PlutusScriptSerialised oldScript diff --git a/cardano-api/src/Cardano/Api/Query/Internal/Convenience.hs b/cardano-api/src/Cardano/Api/Query/Internal/Convenience.hs index 707df706ba..f7fd3e5689 100644 --- a/cardano-api/src/Cardano/Api/Query/Internal/Convenience.hs +++ b/cardano-api/src/Cardano/Api/Query/Internal/Convenience.hs @@ -25,6 +25,7 @@ import Cardano.Api.Certificate.Internal import Cardano.Api.Consensus.Internal.Mode import Cardano.Api.Era import Cardano.Api.Error +import Cardano.Api.Experimental qualified as Exp import Cardano.Api.IO import Cardano.Api.Monad.Error import Cardano.Api.Network.IPC @@ -98,7 +99,7 @@ queryStateForBalancedTx :: () => CardanoEra era -> [TxIn] - -> [Certificate era] + -> [Exp.Certificate (ShelleyLedgerEra era)] -> LocalStateQueryExpr block point @@ -122,8 +123,8 @@ queryStateForBalancedTx era allTxIns certs = runExceptT $ do requireShelleyBasedEra era & onNothing (left ByronEraNotSupported) - let stakeCreds = fromList $ mapMaybe filterUnRegCreds certs - drepCreds = fromList $ mapMaybe filterUnRegDRepCreds certs + let stakeCreds = fromList $ mapMaybe (filterUnRegCreds sbe) certs + drepCreds = fromList $ mapMaybe (filterUnRegDRepCreds sbe) certs -- Query execution utxo <- diff --git a/cardano-api/src/Cardano/Api/Serialise/TextEnvelope/Internal.hs b/cardano-api/src/Cardano/Api/Serialise/TextEnvelope/Internal.hs index 93a4360ae0..3cad1945a7 100644 --- a/cardano-api/src/Cardano/Api/Serialise/TextEnvelope/Internal.hs +++ b/cardano-api/src/Cardano/Api/Serialise/TextEnvelope/Internal.hs @@ -185,6 +185,7 @@ legacyComparison (TextEnvelopeType expectedType) (TextEnvelopeType actualType) = ("Tx AlonzoEra", "Unwitnessed Tx AlonzoEra") -> True ("Tx BabbageEra", "Unwitnessed Tx BabbageEra") -> True ("Tx ConwayEra", "Unwitnessed Tx ConwayEra") -> True + ("Certificate", "CertificateConway") -> True (expectedOther, expectedActual) -> expectedOther == expectedActual -- ---------------------------------------------------------------------------- diff --git a/cardano-api/src/Cardano/Api/Tx/Internal/Body.hs b/cardano-api/src/Cardano/Api/Tx/Internal/Body.hs index 626504c1fa..7dcc5e4e5b 100644 --- a/cardano-api/src/Cardano/Api/Tx/Internal/Body.hs +++ b/cardano-api/src/Cardano/Api/Tx/Internal/Body.hs @@ -232,6 +232,7 @@ where import Cardano.Api.Address import Cardano.Api.Byron.Internal.Key +import Cardano.Api.Certificate import Cardano.Api.Certificate.Internal import Cardano.Api.Era.Internal.Case import Cardano.Api.Era.Internal.Core @@ -251,6 +252,7 @@ import Cardano.Api.Experimental.Plutus.Internal.IndexedPlutusScriptWitness , obtainAlonzoScriptPurposeConstraints ) import Cardano.Api.Experimental.Plutus.Internal.Shim.LegacyScripts +import Cardano.Api.Experimental.Tx.Internal.Certificate qualified as Exp import Cardano.Api.Experimental.Tx.Internal.TxScriptWitnessRequirements import Cardano.Api.Governance.Internal.Action.ProposalProcedure import Cardano.Api.Governance.Internal.Action.VotingProcedure @@ -573,7 +575,7 @@ data TxCertificates build era where TxCertificates :: ShelleyBasedEra era -> OMap - (Certificate era) + (Exp.Certificate (ShelleyLedgerEra era)) ( BuildTxWith build (Maybe (StakeCredential, Witness WitCtxStake era)) @@ -592,29 +594,40 @@ deriving instance Show (TxCertificates build era) -- credential registration certificates without a deposit. Future eras will require a witness for -- registration certificates, because the one without a deposit will be removed. mkTxCertificates - :: Applicative (BuildTxWith build) + :: forall era build + . Applicative (BuildTxWith build) => ShelleyBasedEra era - -> [(Certificate era, Maybe (ScriptWitness WitCtxStake era))] + -> [(Exp.Certificate (ShelleyLedgerEra era), Maybe (ScriptWitness WitCtxStake era))] -> TxCertificates build era mkTxCertificates _ [] = TxCertificatesNone mkTxCertificates sbe certs = TxCertificates sbe . fromList $ map getStakeCred certs where - getStakeCred (cert, mWit) = do + getStakeCred + :: (Exp.Certificate (ShelleyLedgerEra era), Maybe (ScriptWitness WitCtxStake era)) + -> ( Exp.Certificate (ShelleyLedgerEra era) + , BuildTxWith build (Maybe (StakeCredential, Witness WitCtxStake era)) + ) + getStakeCred (c@(Exp.Certificate cert), mWit) = do let wit = maybe (KeyWitness KeyWitnessForStakeAddr) (ScriptWitness ScriptWitnessForStakeAddr) mWit - ( cert + ( c , pure $ - (,wit) <$> selectStakeCredentialWitness cert + (,wit) <$> getTxCertWitness sbe cert ) -- | Index certificates with witnesses by the order they appear in the list (in the transaction). -- See section 4.1 of https://github.com/intersectmbo/cardano-ledger/releases/latest/download/alonzo-ledger.pdf indexTxCertificates :: TxCertificates BuildTx era - -> [(ScriptWitnessIndex, Certificate era, StakeCredential, Witness WitCtxStake era)] + -> [ ( ScriptWitnessIndex + , Exp.Certificate (ShelleyLedgerEra era) + , StakeCredential + , Witness WitCtxStake era + ) + ] indexTxCertificates TxCertificatesNone = [] indexTxCertificates (TxCertificates _ certsWits) = [ (ScriptWitnessIndexCertificate ix, cert, stakeCred, witness) @@ -1771,7 +1784,7 @@ fromLedgerTxCertificates sbe body = in if null certificates then TxCertificatesNone else - TxCertificates sbe . fromList $ map ((,ViewTx) . fromShelleyCertificate sbe) $ toList certificates + TxCertificates sbe . fromList $ map ((,ViewTx) . Exp.Certificate) $ toList certificates maybeFromLedgerTxUpdateProposal :: () @@ -1855,7 +1868,7 @@ convCertificates -> Seq.StrictSeq (Shelley.TxCert (ShelleyLedgerEra era)) convCertificates _ = \case TxCertificatesNone -> Seq.empty - TxCertificates _ cs -> fromList . map (toShelleyCertificate . fst) $ toList cs + TxCertificates _ cs -> fromList . map (\(Exp.Certificate c, _) -> c) $ toList cs convWithdrawals :: TxWithdrawals build era -> L.Withdrawals convWithdrawals txWithdrawals = @@ -3029,10 +3042,10 @@ extractWitnessableCertificates extractWitnessableCertificates aeon txCertificates = alonzoEraOnwardsConstraints aeon $ List.nub - [ ( WitTxCert (certificateToTxCert cert) stakeCred + [ ( WitTxCert cert stakeCred , BuildTxWith wit ) - | (cert, BuildTxWith (Just (stakeCred, wit))) <- getCertificates txCertificates + | (Exp.Certificate cert, BuildTxWith (Just (stakeCred, wit))) <- getCertificates txCertificates ] where getCertificates TxCertificatesNone = [] diff --git a/cardano-api/src/Cardano/Api/Tx/Internal/Fee.hs b/cardano-api/src/Cardano/Api/Tx/Internal/Fee.hs index b23238c861..d1d6e2370a 100644 --- a/cardano-api/src/Cardano/Api/Tx/Internal/Fee.hs +++ b/cardano-api/src/Cardano/Api/Tx/Internal/Fee.hs @@ -65,6 +65,7 @@ import Cardano.Api.Era.Internal.Eon.MaryEraOnwards import Cardano.Api.Era.Internal.Eon.ShelleyBasedEra import Cardano.Api.Era.Internal.Feature import Cardano.Api.Error +import Cardano.Api.Experimental.Tx.Internal.Certificate qualified as Exp import Cardano.Api.Ledger.Internal.Reexport qualified as L import Cardano.Api.Plutus import Cardano.Api.Pretty @@ -1535,7 +1536,7 @@ substituteExecutionUnits mapScriptWitnessesCertificates TxCertificatesNone = Right TxCertificatesNone mapScriptWitnessesCertificates txCertificates'@(TxCertificates supported _) = do let mappedScriptWitnesses - :: [ ( Certificate era + :: [ ( Exp.Certificate (ShelleyLedgerEra era) , Either (TxBodyErrorAutoBalance era) ( BuildTxWith diff --git a/cardano-api/test/cardano-api-test/Test/Cardano/Api/Ord.hs b/cardano-api/test/cardano-api-test/Test/Cardano/Api/Ord.hs index 1f8322e3f6..887f2caec1 100644 --- a/cardano-api/test/cardano-api-test/Test/Cardano/Api/Ord.hs +++ b/cardano-api/test/cardano-api-test/Test/Cardano/Api/Ord.hs @@ -11,8 +11,6 @@ import Test.Cardano.Api.Metadata (genTxMetadataValue) import Hedgehog (Property, (===)) import Hedgehog qualified as H -import Hedgehog.Extras qualified as H -import Hedgehog.Gen qualified as H import Test.Tasty (TestTree, testGroup) import Test.Tasty.Hedgehog (testProperty) @@ -52,20 +50,6 @@ prop_ord_distributive_ScriptData :: Property prop_ord_distributive_ScriptData = ord_distributive (getScriptData <$> genHashableScriptData) toPlutusData -prop_ord_distributive_Certificate :: Property -prop_ord_distributive_Certificate = H.property $ do - AnyShelleyBasedEra sbe <- H.forAll H.enumBounded - cert1 <- H.forAll $ genCertificate sbe - cert2 <- H.forAll $ genCertificate sbe - case (cert1, cert2) of - (ShelleyRelatedCertificate w1 c1, ShelleyRelatedCertificate _ c2) -> do - shelleyToBabbageEraConstraints w1 $ - compare cert1 cert2 === compare c1 c2 - (ConwayCertificate w1 c1, ConwayCertificate _ c2) -> - conwayEraOnwardsConstraints w1 $ - compare cert1 cert2 === compare c1 c2 - _ -> H.note_ "impossible, two different eras!" >> H.failure - -- ----------------------------------------------------------------------------- tests :: TestTree @@ -78,5 +62,4 @@ tests = , testProperty "ord distributive StakeAddress" prop_ord_distributive_StakeAddress , testProperty "ord distributive TxMetadata" prop_ord_distributive_TxMetadata , testProperty "ord distributive ScriptData" prop_ord_distributive_ScriptData - , testProperty "ord distributive Certificate" prop_ord_distributive_Certificate ] diff --git a/cardano-api/test/cardano-api-test/Test/Cardano/Api/Transaction/Autobalance.hs b/cardano-api/test/cardano-api-test/Test/Cardano/Api/Transaction/Autobalance.hs index b4f9d21444..8273c64e1f 100644 --- a/cardano-api/test/cardano-api-test/Test/Cardano/Api/Transaction/Autobalance.hs +++ b/cardano-api/test/cardano-api-test/Test/Cardano/Api/Transaction/Autobalance.hs @@ -13,6 +13,7 @@ module Test.Cardano.Api.Transaction.Autobalance where import Cardano.Api +import Cardano.Api.Experimental qualified as Exp import Cardano.Api.Experimental.Tx import Cardano.Api.Ledger qualified as L import Cardano.Api.Parser.Text qualified as P @@ -368,8 +369,8 @@ prop_make_transaction_body_autobalance_when_deregistering_certs = H.property $ d ] let certs = [ - ( ConwayCertificate ceo $ - L.ConwayTxCertDeleg (L.ConwayUnRegCert (toShelleyStakeCredential stakeCred) (L.SJust deregDeposit)) + ( Exp.Certificate + (L.ConwayTxCertDeleg (L.ConwayUnRegCert (toShelleyStakeCredential stakeCred) (L.SJust deregDeposit))) , Nothing ) ]