From b8016a2bafbbcef66da0c795502631fa6a26fa6b Mon Sep 17 00:00:00 2001 From: Daniel Firth Date: Fri, 2 Feb 2024 10:30:33 +0000 Subject: [PATCH 1/4] add genOutput/propHasEnoughLovelace --- hydra-node/test/Hydra/Ledger/CardanoSpec.hs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/hydra-node/test/Hydra/Ledger/CardanoSpec.hs b/hydra-node/test/Hydra/Ledger/CardanoSpec.hs index 7a32e51d76d..7d5add2d3fa 100644 --- a/hydra-node/test/Hydra/Ledger/CardanoSpec.hs +++ b/hydra-node/test/Hydra/Ledger/CardanoSpec.hs @@ -7,6 +7,7 @@ import Hydra.Prelude import Test.Hydra.Prelude import Cardano.Binary (decodeFull, serialize') +import Cardano.Ledger.Api (ensureMinCoinTxOut) import Cardano.Ledger.Core (PParams ()) import Cardano.Ledger.Credential (Credential (..)) import Data.Aeson (eitherDecode, encode) @@ -15,12 +16,13 @@ import Data.Aeson.Lens (key) import Data.ByteString.Base16 qualified as Base16 import Data.Text (unpack) import Hydra.Cardano.Api.Pretty (renderTx) -import Hydra.Chain.Direct.Fixture (defaultGlobals, defaultLedgerEnv) +import Hydra.Chain.Direct.Fixture (defaultGlobals, defaultLedgerEnv, defaultPParams) import Hydra.JSONSchema (prop_validateJSONSchema) import Hydra.Ledger (ChainSlot (ChainSlot), applyTransactions, txId) import Hydra.Ledger.Cardano ( cardanoLedger, genOneUTxOFor, + genOutput, genSequenceOfSimplePaymentTransactions, genTxOut, genUTxOAdaOnlyOfSize, @@ -91,6 +93,10 @@ spec = it "does generate good values" $ forAll genTxOut propGeneratesGoodTxOut + describe "genOutput" $ + it "has enough lovelace to cover assets" $ + forAll (arbitrary >>= genOutput) propHasEnoughLovelace + describe "genValue" $ it "produces realistic values" $ forAll genValue propRealisticValue @@ -185,6 +191,12 @@ propRealisticValue value = where numberOfAssets = length (valueToList value) +-- | Check that an output has enough lovelace to cover asset deposits. +propHasEnoughLovelace :: TxOut CtxUTxO -> Property +propHasEnoughLovelace txOut = + ensureMinCoinTxOut defaultPParams (toLedgerTxOut txOut) === toLedgerTxOut txOut + & counterexample "ensureMinCoinTxOut deemed not enough lovelace in txOut" + -- | Check that the given 'TxOut' fulfills several requirements and does not use -- unsupported features. See 'genTxOut' for rationale. propGeneratesGoodTxOut :: TxOut CtxUTxO -> Property @@ -194,6 +206,7 @@ propGeneratesGoodTxOut txOut = [ propNoReferenceScript , propNoByronAddress , propRealisticValue (txOutValue txOut) + , propHasEnoughLovelace txOut ] & cover 5 hasDatum "has datum" & cover 5 isVKOutput "is VK output" From 8bbf6fc6f429a49becc9a07c715c5cd6fcf5631f Mon Sep 17 00:00:00 2001 From: Daniel Firth Date: Wed, 3 Jan 2024 13:03:47 +0000 Subject: [PATCH 2/4] cardano-api: 8.29.1.0 -> 8.37.0.0 --- cabal.project | 4 +- flake.lock | 42 ++++++--- hydra-cardano-api/hydra-cardano-api.cabal | 8 +- hydra-cardano-api/src/Cardano/Api/UTxO.hs | 54 ++++++------ hydra-cardano-api/src/Hydra/Cardano/Api.hs | 12 +-- .../src/Hydra/Cardano/Api/Hash.hs | 2 +- .../src/Hydra/Cardano/Api/PlutusScript.hs | 2 +- .../src/Hydra/Cardano/Api/PolicyId.hs | 2 +- .../src/Hydra/Cardano/Api/ScriptData.hs | 4 +- hydra-cardano-api/src/Hydra/Cardano/Api/Tx.hs | 6 +- .../src/Hydra/Cardano/Api/TxBody.hs | 2 +- .../src/Hydra/Cardano/Api/TxIn.hs | 2 +- .../src/Hydra/Cardano/Api/TxOut.hs | 6 +- .../src/Hydra/Cardano/Api/TxOutValue.hs | 5 +- .../src/Hydra/Cardano/Api/ValidityInterval.hs | 1 - .../src/Hydra/Cardano/Api/Value.hs | 15 ++-- .../src/Hydra/ChainObserver.hs | 9 +- hydra-node/src/Hydra/Chain/CardanoClient.hs | 88 ++++++++----------- hydra-node/src/Hydra/Chain/Direct.hs | 31 ++++--- .../src/Hydra/Chain/Direct/TimeHandle.hs | 7 +- hydra-node/src/Hydra/Chain/Direct/Wallet.hs | 2 +- hydra-node/src/Hydra/Ledger/Cardano.hs | 2 +- .../src/Hydra/Ledger/Cardano/Evaluate.hs | 14 +-- .../Hydra/Chain/Direct/Contract/Mutation.hs | 2 +- hydra-test-utils/src/Test/Plutus/Validator.hs | 4 +- 25 files changed, 163 insertions(+), 163 deletions(-) diff --git a/cabal.project b/cabal.project index 390c5c9af4b..95116efc1e6 100644 --- a/cabal.project +++ b/cabal.project @@ -12,8 +12,8 @@ repository cardano-haskell-packages -- See CONTRIBUTING.md for information about when and how to update these. index-state: - , hackage.haskell.org 2023-12-06T15:07:04Z - , cardano-haskell-packages 2023-12-04T19:04:02Z + , hackage.haskell.org 2024-01-29T15:07:04Z + , cardano-haskell-packages 2024-01-29T19:04:02Z packages: hydra-prelude diff --git a/flake.lock b/flake.lock index 8f9ab16dbb6..fd01cf854fd 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "CHaP": { "flake": false, "locked": { - "lastModified": 1706004183, - "narHash": "sha256-WKfiLsitgXL9wxHr8LA+lyIhHXog4/HOOdQwIUdSW04=", + "lastModified": 1706612908, + "narHash": "sha256-rZytUcsrRO6EIOdDSuQw9vhNUFRk1GuG6w2vUxLv5H8=", "owner": "input-output-hk", "repo": "cardano-haskell-packages", - "rev": "44cf7d3dcee77eb6ee8e4462bf63616351dfbb1d", + "rev": "44e3f3330cc807066818f739946ab08e868a4b30", "type": "github" }, "original": { @@ -921,11 +921,11 @@ "hackage": { "flake": false, "locked": { - "lastModified": 1706142242, - "narHash": "sha256-fofDg1MAgN0yF46D0LfYnYEZctuTAmeYEmMV+u0FHOc=", + "lastModified": 1706660549, + "narHash": "sha256-vSYdk5Z40Cr6AlOKZEsOto5gIsI/egsxoDRBpp6lmd8=", "owner": "input-output-hk", "repo": "hackage.nix", - "rev": "c9ccd30f487a962c18137ad35ed40bc1719da209", + "rev": "a2751becae6189be230fe9d2582ea9464d79442e", "type": "github" }, "original": { @@ -1023,6 +1023,7 @@ "hpc-coveralls": "hpc-coveralls_2", "hydra": "hydra_2", "iserv-proxy": "iserv-proxy_2", + "nix-tools-static": "nix-tools-static", "nixpkgs": [ "haskellNix", "nixpkgs-unstable" @@ -1039,11 +1040,11 @@ "stackage": "stackage_2" }, "locked": { - "lastModified": 1706143809, - "narHash": "sha256-lYjy5qAdLvm+0PWjRLHEe1Gl+PwoYRm5SpgXGLBaLKk=", + "lastModified": 1706662202, + "narHash": "sha256-gTGsgdlXXwcsSgQxQkxcv1iOS90m8Xr8ze5i5BnCbo0=", "owner": "input-output-hk", "repo": "haskell.nix", - "rev": "5559d7bc4ad00bada614d1c4473d5cf38eb905f2", + "rev": "7ea60f43d7f104bd5764c11d566ce726b6a681ab", "type": "github" }, "original": { @@ -1651,6 +1652,23 @@ "type": "github" } }, + "nix-tools-static": { + "flake": false, + "locked": { + "lastModified": 1706266250, + "narHash": "sha256-9t+GRk3eO9muCtKdNAwBtNBZ5dH1xHcnS17WaQyftwA=", + "owner": "input-output-hk", + "repo": "haskell-nix-example", + "rev": "580cb6db546a7777dad3b9c0fa487a366c045c4e", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "nix", + "repo": "haskell-nix-example", + "type": "github" + } + }, "nix2container": { "inputs": { "flake-utils": "flake-utils_2", @@ -2656,11 +2674,11 @@ "stackage_2": { "flake": false, "locked": { - "lastModified": 1706054996, - "narHash": "sha256-URZYIAVp0Zt0lMr05+1VlDWUZe6C2D+FLBfFfn7Sti4=", + "lastModified": 1706659779, + "narHash": "sha256-MfXSjpyFPUPpKuDAaRUNbeTPRQLxa88h7gVnitZ5YDk=", "owner": "input-output-hk", "repo": "stackage.nix", - "rev": "2d34cb4a94ed34c0ae200515172fe2bc9cb39ab6", + "rev": "d3f2896c19425d021387668dc51d031921b0c0de", "type": "github" }, "original": { diff --git a/hydra-cardano-api/hydra-cardano-api.cabal b/hydra-cardano-api/hydra-cardano-api.cabal index 7cd26c3fdc4..e18de5fbd93 100644 --- a/hydra-cardano-api/hydra-cardano-api.cabal +++ b/hydra-cardano-api/hydra-cardano-api.cabal @@ -87,7 +87,7 @@ library , base >=4.16 , base16-bytestring , bytestring - , cardano-api >=8.29.1 && <8.30 + , cardano-api >=8.37.0 && <8.38 , cardano-binary >=1.7.0 && <1.8 , cardano-crypto-class >=2.1.1 && <2.2 , cardano-ledger-allegra >=1.2.1 && <1.3 @@ -96,9 +96,9 @@ library , cardano-ledger-babbage >=1.5 && <1.6 , cardano-ledger-binary >=1.2 && <1.3 , cardano-ledger-byron >=1.0.0 && <1.1 - , cardano-ledger-core >=1.8 && <1.9 - , cardano-ledger-mary >=1.3.1 && <1.4 - , cardano-ledger-shelley >=1.7 && <1.8 + , cardano-ledger-core >=1.9 && <1.10 + , cardano-ledger-mary >=1.4 && <1.5 + , cardano-ledger-shelley >=1.8 && <1.9 , containers , lens , plutus-ledger-api >=1.15.0.1 && <1.16 diff --git a/hydra-cardano-api/src/Cardano/Api/UTxO.hs b/hydra-cardano-api/src/Cardano/Api/UTxO.hs index ad4194edac0..b9894276eb4 100644 --- a/hydra-cardano-api/src/Cardano/Api/UTxO.hs +++ b/hydra-cardano-api/src/Cardano/Api/UTxO.hs @@ -87,35 +87,35 @@ min = UTxO . uncurry Map.singleton . Map.findMin . toMap -- * Type Conversions -- | Transforms a UTxO containing tx outs from any era into Babbage era. -fromApi :: Cardano.Api.UTxO era -> UTxO -fromApi (Cardano.Api.UTxO eraUTxO) = +fromApi :: forall era. ShelleyBasedEra era -> Cardano.Api.UTxO era -> UTxO +fromApi sbe (Cardano.Api.UTxO eraUTxO) = let eraPairs = Map.toList eraUTxO - babbagePairs = second coerceOutputToEra <$> eraPairs + babbagePairs = second (coerceOutputToEra sbe) <$> eraPairs in fromPairs babbagePairs - where - coerceOutputToEra :: TxOut CtxUTxO era -> TxOut CtxUTxO Era - coerceOutputToEra (TxOut eraAddress eraValue eraDatum eraRefScript) = - TxOut - (coerceAddressToEra eraAddress) - (coerceValueToEra eraValue) - (coerceDatumToEra eraDatum) - (coerceRefScriptToEra eraRefScript) - - coerceAddressToEra :: AddressInEra era -> AddressInEra Era - coerceAddressToEra (AddressInEra _ eraAddress) = anyAddressInShelleyBasedEra ShelleyBasedEraBabbage (toAddressAny eraAddress) - - coerceValueToEra :: TxOutValue era -> TxOutValue Era - coerceValueToEra (TxOutAdaOnly _ eraLovelace) = lovelaceToTxOutValue BabbageEra eraLovelace - coerceValueToEra (TxOutValue _ value) = TxOutValue MaryEraOnwardsBabbage value - - coerceDatumToEra :: TxOutDatum CtxUTxO era -> TxOutDatum CtxUTxO Era - coerceDatumToEra TxOutDatumNone = TxOutDatumNone - coerceDatumToEra (TxOutDatumHash _ hashScriptData) = TxOutDatumHash AlonzoEraOnwardsBabbage hashScriptData - coerceDatumToEra (TxOutDatumInline _ hashableScriptData) = TxOutDatumInline BabbageEraOnwardsBabbage hashableScriptData - - coerceRefScriptToEra :: ReferenceScript era -> ReferenceScript Era - coerceRefScriptToEra ReferenceScriptNone = ReferenceScriptNone - coerceRefScriptToEra (ReferenceScript _ scriptInAnyLang) = ReferenceScript BabbageEraOnwardsBabbage scriptInAnyLang + +coerceOutputToEra :: forall era. ShelleyBasedEra era -> TxOut CtxUTxO era -> TxOut CtxUTxO Era +coerceOutputToEra sbe (TxOut eraAddress eraValue eraDatum eraRefScript) = + TxOut + (coerceAddressToEra eraAddress) + (coerceValueToEra sbe eraValue) + (coerceDatumToEra eraDatum) + (coerceRefScriptToEra eraRefScript) + +coerceAddressToEra :: AddressInEra era -> AddressInEra Era +coerceAddressToEra (AddressInEra _ eraAddress) = anyAddressInShelleyBasedEra ShelleyBasedEraBabbage (toAddressAny eraAddress) + +coerceValueToEra :: forall era. ShelleyBasedEra era -> TxOutValue era -> TxOutValue Era +coerceValueToEra _ (TxOutValueByron eraLovelace) = lovelaceToTxOutValue shelleyBasedEra eraLovelace +coerceValueToEra sbe (TxOutValueShelleyBased _ value) = TxOutValueShelleyBased ShelleyBasedEraBabbage (toLedgerValue MaryEraOnwardsBabbage $ fromLedgerValue sbe value) + +coerceDatumToEra :: TxOutDatum CtxUTxO era -> TxOutDatum CtxUTxO Era +coerceDatumToEra TxOutDatumNone = TxOutDatumNone +coerceDatumToEra (TxOutDatumHash _ hashScriptData) = TxOutDatumHash AlonzoEraOnwardsBabbage hashScriptData +coerceDatumToEra (TxOutDatumInline _ hashableScriptData) = TxOutDatumInline BabbageEraOnwardsBabbage hashableScriptData + +coerceRefScriptToEra :: ReferenceScript era -> ReferenceScript Era +coerceRefScriptToEra ReferenceScriptNone = ReferenceScriptNone +coerceRefScriptToEra (ReferenceScript _ scriptInAnyLang) = ReferenceScript BabbageEraOnwardsBabbage scriptInAnyLang toApi :: UTxO -> Cardano.Api.UTxO Era toApi = coerce diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api.hs b/hydra-cardano-api/src/Hydra/Cardano/Api.hs index 3d53472ffd2..d7b863bf576 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api.hs @@ -67,6 +67,7 @@ import Cardano.Api as X hiding ( Witness (..), createAndValidateTransactionBody, defaultTxBodyContent, + fromLedgerValue, makeShelleyKeyWitness, policyId, queryEraHistory, @@ -76,6 +77,7 @@ import Cardano.Api as X hiding ( scriptLanguageSupportedInEra, signShelleyTransaction, toLedgerUTxO, + toLedgerValue, ) import Cardano.Api.Byron as X ( Address (..), @@ -94,10 +96,8 @@ import Cardano.Api.Shelley as X ( VerificationKey (..), fromAlonzoCostModels, fromAlonzoPrices, - fromConsensusPointInMode, fromPlutusData, toAlonzoPrices, - toConsensusPointInMode, toPlutusData, toShelleyNetwork, ) @@ -372,10 +372,10 @@ pattern TxBody{txBodyContent} <- {-# COMPLETE TxBody #-} createAndValidateTransactionBody :: TxBodyContent BuildTx -> Either TxBodyError TxBody -createAndValidateTransactionBody = Cardano.Api.createAndValidateTransactionBody cardanoEra +createAndValidateTransactionBody = Cardano.Api.createAndValidateTransactionBody shelleyBasedEra defaultTxBodyContent :: TxBodyContent BuildTx -defaultTxBodyContent = Cardano.Api.defaultTxBodyContent cardanoEra +defaultTxBodyContent = Cardano.Api.defaultTxBodyContent shelleyBasedEra -- ** TxBodyContent @@ -595,14 +595,14 @@ pattern TxOut :: AddressInEra -> Value -> TxOutDatum ctx -> ReferenceScript -> T pattern TxOut{txOutAddress, txOutValue, txOutDatum, txOutReferenceScript} <- Cardano.Api.TxOut txOutAddress - (TxOutValue MaryEraOnwardsBabbage txOutValue) + (TxOutValueShelleyBased ShelleyBasedEraBabbage (Extras.fromLedgerValue -> txOutValue)) txOutDatum txOutReferenceScript where TxOut addr value datum ref = Cardano.Api.TxOut addr - (TxOutValue MaryEraOnwardsBabbage value) + (TxOutValueShelleyBased ShelleyBasedEraBabbage (Extras.toLedgerValue value)) datum ref diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/Hash.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/Hash.hs index e21d6596084..2f7b4ad0eed 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/Hash.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/Hash.hs @@ -2,7 +2,7 @@ module Hydra.Cardano.Api.Hash where import Hydra.Cardano.Api.Prelude -import Cardano.Ledger.Alonzo.TxInfo qualified as Ledger +import Cardano.Ledger.Alonzo.Plutus.TxInfo qualified as Ledger import Cardano.Ledger.Keys qualified as Ledger import Cardano.Ledger.SafeHash (unsafeMakeSafeHash) import Cardano.Ledger.Shelley.Scripts qualified as Ledger diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/PlutusScript.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/PlutusScript.hs index 255c6940758..587fd107151 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/PlutusScript.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/PlutusScript.hs @@ -4,8 +4,8 @@ module Hydra.Cardano.Api.PlutusScript where import Hydra.Cardano.Api.Prelude -import Cardano.Ledger.Alonzo.Language qualified as Ledger import Cardano.Ledger.Alonzo.Scripts qualified as Ledger +import Cardano.Ledger.Plutus.Language qualified as Ledger import Data.ByteString.Short qualified as SBS import PlutusLedgerApi.Common qualified as Plutus import Test.QuickCheck (listOf) diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/PolicyId.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/PolicyId.hs index ad3ffd6c5e6..0e9b19c2b21 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/PolicyId.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/PolicyId.hs @@ -4,7 +4,7 @@ module Hydra.Cardano.Api.PolicyId where import Hydra.Cardano.Api.Prelude -import Cardano.Ledger.Alonzo.TxInfo qualified as Ledger +import Cardano.Ledger.Alonzo.Plutus.TxInfo qualified as Ledger import Cardano.Ledger.Hashes qualified as Ledger import Cardano.Ledger.Mary.Value qualified as Ledger import Hydra.Cardano.Api.ScriptHash () diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/ScriptData.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/ScriptData.hs index 38bdcd35aa0..085b481e8f5 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/ScriptData.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/ScriptData.hs @@ -4,10 +4,9 @@ module Hydra.Cardano.Api.ScriptData where import Hydra.Cardano.Api.Prelude -import Cardano.Api.Byron (TxBody (..)) -import Cardano.Ledger.Alonzo.Scripts.Data qualified as Ledger import Cardano.Ledger.Alonzo.TxWits qualified as Ledger import Cardano.Ledger.Era qualified as Ledger +import Cardano.Ledger.Plutus.Data qualified as Ledger import Codec.Serialise (deserialiseOrFail, serialise) import Control.Arrow (left) import Data.Aeson (Value (String), withText) @@ -55,7 +54,6 @@ lookupScriptData :: Tx era -> TxOut CtxUTxO era -> Maybe HashableScriptData -lookupScriptData (Tx ByronTxBody{} _) _ = Nothing lookupScriptData (Tx (ShelleyTxBody _ _ _ scriptsData _ _) _) (TxOut _ _ datum _) = case datum of TxOutDatumNone -> diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/Tx.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/Tx.hs index adb1dc88d04..5708073ae2f 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/Tx.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/Tx.hs @@ -45,14 +45,10 @@ utxoProducedByTx tx = TxBody body = getTxBody tx -- | Get explicit fees allocated to a transaction. --- --- NOTE: this function is partial and throws if given a Byron transaction for --- which fees are necessarily implicit. -txFee' :: HasCallStack => Tx era -> Lovelace +txFee' :: Tx era -> Lovelace txFee' (getTxBody -> TxBody body) = case txFee body of TxFeeExplicit _ y -> y - TxFeeImplicit _ -> error "impossible: TxFeeImplicit on non-Byron transaction." -- * Type Conversions diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/TxBody.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/TxBody.hs index cd86d20b432..8a145dad773 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/TxBody.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/TxBody.hs @@ -2,11 +2,11 @@ module Hydra.Cardano.Api.TxBody where import Hydra.Cardano.Api.Prelude -import Cardano.Ledger.Alonzo.Scripts.Data qualified as Ledger import Cardano.Ledger.Alonzo.TxWits qualified as Ledger import Cardano.Ledger.Babbage.Tx qualified as Ledger import Cardano.Ledger.BaseTypes (strictMaybeToMaybe) import Cardano.Ledger.Core qualified as Ledger +import Cardano.Ledger.Plutus.Data qualified as Ledger import Data.List (find) import Data.Map qualified as Map import Hydra.Cardano.Api.PlutusScript (fromLedgerScript) diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/TxIn.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/TxIn.hs index 19a5205a4b4..b7e77a3911e 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/TxIn.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/TxIn.hs @@ -4,9 +4,9 @@ module Hydra.Cardano.Api.TxIn where import Hydra.Cardano.Api.Prelude -import Cardano.Ledger.Alonzo.TxInfo qualified as Ledger import Cardano.Ledger.BaseTypes qualified as Ledger import Cardano.Ledger.Binary qualified as Ledger +import Cardano.Ledger.Plutus.TxInfo qualified as Ledger import Cardano.Ledger.TxIn qualified as Ledger import Data.ByteString qualified as BS import Data.Set qualified as Set diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/TxOut.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/TxOut.hs index 428863eeef4..e8be53d7340 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/TxOut.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/TxOut.hs @@ -46,7 +46,7 @@ mkTxOutAutoBalance :: ReferenceScript Era -> TxOut CtxTx Era mkTxOutAutoBalance pparams addr val dat ref = - let out = TxOut addr (TxOutValue maryEraOnwards val) dat ref + let out = TxOut addr (TxOutValueShelleyBased (shelleyBasedEra @Era) (toLedgerValue (maryEraOnwards @Era) val)) dat ref minValue = minUTxOValue pparams out in modifyTxOutValue (const minValue) out @@ -61,6 +61,7 @@ modifyTxOutAddress fn (TxOut addr value dat ref) = -- | Alter the value of a 'TxOut' with the given transformation. modifyTxOutValue :: IsMaryEraOnwards era => + IsShelleyBasedEra era => (Value -> Value) -> TxOut ctx era -> TxOut ctx era @@ -160,12 +161,13 @@ toLedgerTxOut = -- NOTE: Requires the 'Network' discriminator (Testnet or Mainnet) because -- Plutus addresses are stripped off it. fromPlutusTxOut :: + forall era. (IsMaryEraOnwards era, IsAlonzoEraOnwards era, IsBabbageEraOnwards era, IsShelleyBasedEra era) => Network -> Plutus.TxOut -> Maybe (TxOut CtxUTxO era) fromPlutusTxOut network out = do - value <- TxOutValue maryEraOnwards <$> fromPlutusValue plutusValue + value <- shelleyBasedEraConstraints (shelleyBasedEra @era) $ TxOutValueShelleyBased (shelleyBasedEra @era) <$> (toLedgerValue (maryEraOnwards @era) <$> fromPlutusValue plutusValue) pure $ TxOut addressInEra value datum ReferenceScriptNone where addressInEra = fromPlutusAddress network plutusAddress diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/TxOutValue.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/TxOutValue.hs index 74cdf7eaf21..100bf74557f 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/TxOutValue.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/TxOutValue.hs @@ -7,8 +7,9 @@ import Hydra.Cardano.Api.MaryEraOnwards (IsMaryEraOnwards (..)) -- | Inject some 'Value' into a 'TxOutValue' mkTxOutValue :: forall era. + IsShelleyBasedEra era => IsMaryEraOnwards era => Value -> TxOutValue era -mkTxOutValue = - TxOutValue (maryEraOnwards @era) +mkTxOutValue v = + shelleyBasedEraConstraints (shelleyBasedEra @era) $ TxOutValueShelleyBased (shelleyBasedEra @era) (toLedgerValue (maryEraOnwards @era) v) diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/ValidityInterval.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/ValidityInterval.hs index 78795e776a7..3ced3eadc1b 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/ValidityInterval.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/ValidityInterval.hs @@ -19,7 +19,6 @@ toLedgerValidityInterval (lowerBound, upperBound) = TxValidityLowerBound _ s -> SJust s , Ledger.invalidHereafter = case upperBound of - TxValidityNoUpperBound _ -> SNothing TxValidityUpperBound _ s -> maybeToStrictMaybe s } fromLedgerValidityInterval :: diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/Value.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/Value.hs index 6a19780bfa1..64ee94c5d0b 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/Value.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/Value.hs @@ -1,14 +1,13 @@ module Hydra.Cardano.Api.Value where -import Hydra.Cardano.Api.Prelude +import Hydra.Cardano.Api.Prelude hiding (toLedgerValue) -import Cardano.Api.Ledger (PParams) -import Cardano.Ledger.Alonzo.TxInfo qualified as Ledger +import Cardano.Api.Ledger (Coin (..), PParams) +import Cardano.Ledger.Alonzo.Plutus.TxInfo qualified as Ledger import Cardano.Ledger.Core (getMinCoinTxOut) import Cardano.Ledger.Mary.Value qualified as Ledger import Data.Word (Word64) import Hydra.Cardano.Api.CtxUTxO (ToUTxOContext (..)) -import Hydra.Cardano.Api.MaryEraOnwards (maryEraOnwards) import Hydra.Cardano.Api.PolicyId (fromPlutusCurrencySymbol) import PlutusLedgerApi.V1.Value (flattenValue) import PlutusLedgerApi.V2 (adaSymbol, adaToken, fromBuiltin, unTokenName) @@ -30,9 +29,9 @@ minUTxOValue pparams (TxOut addr val dat ref) = out' = TxOut addr - ( TxOutValue - (maryEraOnwards @Era) - (txOutValueToValue val <> defaultHighEnoughValue) + ( TxOutValueShelleyBased + (shelleyBasedEra @Era) + (toLedgerValue (txOutValueToValue val <> defaultHighEnoughValue)) ) dat ref @@ -74,7 +73,7 @@ fromLedgerValue = -- will construct a 'Value' with no 'AdaAssetId' entry in it. fromLedgerMultiAsset :: Ledger.MultiAsset StandardCrypto -> Value fromLedgerMultiAsset = - fromMaryValue . Ledger.MaryValue 0 + fromMaryValue . Ledger.MaryValue (Coin 0) -- | Convert a cardano-api 'Value' into a cardano-ledger 'Value'. toLedgerValue :: Value -> Ledger.MaryValue StandardCrypto diff --git a/hydra-chain-observer/src/Hydra/ChainObserver.hs b/hydra-chain-observer/src/Hydra/ChainObserver.hs index 94a1a8d6554..15ab9182490 100644 --- a/hydra-chain-observer/src/Hydra/ChainObserver.hs +++ b/hydra-chain-observer/src/Hydra/ChainObserver.hs @@ -7,13 +7,12 @@ import Hydra.Prelude import Hydra.Cardano.Api ( Block (..), BlockInMode (..), - CardanoMode, + CardanoEra (..), ChainPoint, ChainSyncClient, ChainTip, ConsensusModeParams (..), EpochSlots (..), - EraInMode (..), LocalChainSyncClient (..), LocalNodeClientProtocols (..), LocalNodeConnectInfo (..), @@ -90,9 +89,9 @@ data ChainObserverLog deriving anyclass (ToJSON) type BlockType :: Type -type BlockType = BlockInMode CardanoMode +type BlockType = BlockInMode -connectInfo :: SocketPath -> NetworkId -> LocalNodeConnectInfo CardanoMode +connectInfo :: SocketPath -> NetworkId -> LocalNodeConnectInfo connectInfo nodeSocket networkId = LocalNodeConnectInfo { -- REVIEW: This was 432000 before, but all usages in the @@ -159,7 +158,7 @@ chainSyncClient tracer networkId startingPoint observerHandler = ClientStNext { recvMsgRollForward = \blockInMode tip -> ChainSyncClient $ do case blockInMode of - BlockInMode _ (Block _header txs) BabbageEraInCardanoMode -> do + BlockInMode BabbageEra (Block _header txs) -> do let point = chainTipToChainPoint tip let receivedTxIds = getTxId . getTxBody <$> txs traceWith tracer RollForward{point, receivedTxIds} diff --git a/hydra-node/src/Hydra/Chain/CardanoClient.hs b/hydra-node/src/Hydra/Chain/CardanoClient.hs index b5f8ef17419..83a624abbd0 100644 --- a/hydra-node/src/Hydra/Chain/CardanoClient.hs +++ b/hydra-node/src/Hydra/Chain/CardanoClient.hs @@ -156,11 +156,11 @@ submitTransaction networkId socket tx = pure () SubmitFail (TxValidationEraMismatch e) -> throwIO (SubmitEraMismatch e) - SubmitFail e@TxValidationErrorInMode{} -> + SubmitFail e@TxValidationErrorInCardanoMode{} -> throwIO (SubmitTxValidationError e) where txInMode = - TxInMode tx BabbageEraInCardanoMode + TxInMode shelleyBasedEra tx -- | Exceptions that 'can' occur during a transaction submission. -- @@ -171,7 +171,7 @@ submitTransaction networkId socket tx = -- safely constructed through 'buildTransaction'. data SubmitTransactionException = SubmitEraMismatch EraMismatch - | SubmitTxValidationError (TxValidationErrorInMode CardanoMode) + | SubmitTxValidationError (TxValidationErrorInCardanoMode) deriving stock (Show) instance Exception SubmitTransactionException @@ -238,9 +238,9 @@ querySystemStart networkId socket queryPoint = -- | Query the era history at given point. -- -- Throws at least 'QueryException' if query fails. -queryEraHistory :: NetworkId -> SocketPath -> QueryPoint -> IO (EraHistory CardanoMode) +queryEraHistory :: NetworkId -> SocketPath -> QueryPoint -> IO EraHistory queryEraHistory networkId socket queryPoint = - runQuery networkId socket queryPoint $ QueryEraHistory CardanoModeIsMultiEra + runQuery networkId socket queryPoint $ QueryEraHistory -- | Query the current epoch number. -- @@ -253,7 +253,6 @@ queryEpochNo :: queryEpochNo networkId socket queryPoint = do let query = QueryInEra - BabbageEraInCardanoMode ( QueryInShelleyBasedEra ShelleyBasedEraBabbage QueryEpoch @@ -273,7 +272,8 @@ queryProtocolParameters :: queryProtocolParameters networkId socket queryPoint = runQueryExpr networkId socket queryPoint $ do (AnyCardanoEra era) <- queryCurrentEraExpr - eraPParams <- queryInEraExpr era QueryProtocolParameters + sbe <- liftIO $ assumeShelleyBasedEraOrThrow era + eraPParams <- queryInShelleyBasedEraExpr sbe QueryProtocolParameters liftIO $ coercePParamsToLedgerEra era eraPParams where encodeToEra eraToEncode pparams = @@ -305,7 +305,8 @@ queryGenesisParameters :: queryGenesisParameters networkId socket queryPoint = runQueryExpr networkId socket queryPoint $ do (AnyCardanoEra era) <- queryCurrentEraExpr - queryInEraExpr era QueryGenesisParameters + sbe <- liftIO $ assumeShelleyBasedEraOrThrow era + queryInShelleyBasedEraExpr sbe QueryGenesisParameters -- | Query UTxO for all given addresses at given point. -- @@ -314,8 +315,13 @@ queryUTxO :: NetworkId -> SocketPath -> QueryPoint -> [Address ShelleyAddr] -> I queryUTxO networkId socket queryPoint addresses = runQueryExpr networkId socket queryPoint $ do (AnyCardanoEra era) <- queryCurrentEraExpr - eraUTxO <- queryInEraExpr era $ QueryUTxO (QueryUTxOByAddress (Set.fromList $ map AddressShelley addresses)) - pure $ UTxO.fromApi eraUTxO + sbe <- liftIO $ assumeShelleyBasedEraOrThrow era + queryUTxOExpr sbe addresses + +queryUTxOExpr :: ShelleyBasedEra era -> [Address ShelleyAddr] -> LocalStateQueryExpr b p QueryInMode r IO UTxO +queryUTxOExpr sbe addresses = do + eraUTxO <- queryInShelleyBasedEraExpr sbe $ QueryUTxO (QueryUTxOByAddress (Set.fromList $ map AddressShelley addresses)) + pure $ UTxO.fromApi sbe eraUTxO -- | Query UTxO for given tx inputs at given point. -- @@ -331,8 +337,16 @@ queryUTxOByTxIn :: queryUTxOByTxIn networkId socket queryPoint inputs = runQueryExpr networkId socket queryPoint $ do (AnyCardanoEra era) <- queryCurrentEraExpr - eraUTxO <- queryInEraExpr era $ QueryUTxO (QueryUTxOByTxIn (Set.fromList inputs)) - pure $ UTxO.fromApi eraUTxO + (sbe :: ShelleyBasedEra e) <- liftIO $ assumeShelleyBasedEraOrThrow era + eraUTxO <- queryInShelleyBasedEraExpr sbe $ QueryUTxO (QueryUTxOByTxIn (Set.fromList inputs)) + pure $ UTxO.fromApi sbe eraUTxO + +assumeShelleyBasedEraOrThrow :: MonadThrow m => CardanoEra era -> m (ShelleyBasedEra era) +assumeShelleyBasedEraOrThrow era = do + x <- requireShelleyBasedEra era + case x of + Just sbe -> pure sbe + Nothing -> throwIO $ QueryNotShelleyBasedEraException (anyCardanoEra era) -- | Query the whole UTxO from node at given point. Useful for debugging, but -- should obviously not be used in production code. @@ -346,11 +360,10 @@ queryUTxOWhole :: QueryPoint -> IO UTxO queryUTxOWhole networkId socket queryPoint = do - UTxO.fromApi <$> (runQuery networkId socket queryPoint query >>= throwOnEraMismatch) + UTxO.fromApi ShelleyBasedEraBabbage <$> (runQuery networkId socket queryPoint query >>= throwOnEraMismatch) where query = QueryInEra - BabbageEraInCardanoMode ( QueryInShelleyBasedEra ShelleyBasedEraBabbage (QueryUTxO QueryUTxOWhole) @@ -380,7 +393,6 @@ queryStakePools :: queryStakePools networkId socket queryPoint = let query = QueryInEra - BabbageEraInCardanoMode ( QueryInShelleyBasedEra ShelleyBasedEraBabbage QueryStakePools @@ -390,47 +402,23 @@ queryStakePools networkId socket queryPoint = -- * Helpers -- | Monadic query expression to get current era. -queryCurrentEraExpr :: LocalStateQueryExpr b p (QueryInMode CardanoMode) r IO AnyCardanoEra +queryCurrentEraExpr :: LocalStateQueryExpr b p QueryInMode r IO AnyCardanoEra queryCurrentEraExpr = - queryExpr (QueryCurrentEra CardanoModeIsMultiEra) >>= liftIO . throwOnUnsupportedNtcVersion + queryExpr QueryCurrentEra >>= liftIO . throwOnUnsupportedNtcVersion -- | Monadic query expression for a 'QueryInShelleyBasedEra'. -queryInEraExpr :: +queryInShelleyBasedEraExpr :: -- | The current running era we can use to query the node - CardanoEra era -> + ShelleyBasedEra era -> QueryInShelleyBasedEra era a -> - LocalStateQueryExpr b p (QueryInMode CardanoMode) r IO a -queryInEraExpr era query = - liftIO (mkQueryInEra era query) - >>= queryExpr + LocalStateQueryExpr b p QueryInMode r IO a +queryInShelleyBasedEraExpr sbe query = + queryExpr (QueryInEra $ QueryInShelleyBasedEra sbe query) >>= (liftIO . throwOnUnsupportedNtcVersion) >>= (liftIO . throwOnEraMismatch) --- | Construct a 'QueryInMode' from a 'CardanoEra' which is only known at --- run-time. --- --- Throws a 'QueryException' if passed era is not in 'CardanoMode' or a --- 'ShelleyBasedEra'. -mkQueryInEra :: - MonadThrow m => - -- | The current running era we can use to query the node - CardanoEra era -> - QueryInShelleyBasedEra era a -> - m (QueryInMode CardanoMode (Either EraMismatch a)) -mkQueryInEra era query = - case toEraInMode era CardanoMode of - Nothing -> throwIO $ QueryEraNotInCardanoModeFailure (anyCardanoEra era) - Just eraInMode -> do - mShelleyBaseEra <- requireShelleyBasedEra era - case mShelleyBaseEra of - Nothing -> throwIO $ QueryNotShelleyBasedEraException (anyCardanoEra era) - Just sbe -> - pure $ - QueryInEra eraInMode $ - QueryInShelleyBasedEra sbe query - -- | Throws at least 'QueryException' if query fails. -runQuery :: NetworkId -> SocketPath -> QueryPoint -> QueryInMode CardanoMode a -> IO a +runQuery :: NetworkId -> SocketPath -> QueryPoint -> QueryInMode a -> IO a runQuery networkId socket point query = queryNodeLocalState (localNodeConnectInfo networkId socket) maybePoint query >>= \case Left err -> throwIO $ QueryAcquireException err @@ -446,7 +434,7 @@ runQueryExpr :: NetworkId -> SocketPath -> QueryPoint -> - LocalStateQueryExpr (BlockInMode CardanoMode) ChainPoint (QueryInMode CardanoMode) () IO a -> + LocalStateQueryExpr BlockInMode ChainPoint QueryInMode () IO a -> IO a runQueryExpr networkId socket point query = executeLocalStateQueryExpr (localNodeConnectInfo networkId socket) maybePoint query >>= \case @@ -470,10 +458,10 @@ throwOnUnsupportedNtcVersion res = Left unsupportedNtcVersion -> error $ show unsupportedNtcVersion -- TODO Right result -> pure result -localNodeConnectInfo :: NetworkId -> SocketPath -> LocalNodeConnectInfo CardanoMode +localNodeConnectInfo :: NetworkId -> SocketPath -> LocalNodeConnectInfo localNodeConnectInfo = LocalNodeConnectInfo cardanoModeParams -cardanoModeParams :: ConsensusModeParams CardanoMode +cardanoModeParams :: ConsensusModeParams cardanoModeParams = CardanoModeParams $ EpochSlots defaultByronEpochSlots where -- NOTE(AB): extracted from Parsers in cardano-cli, this is needed to run in 'cardanoMode' which diff --git a/hydra-node/src/Hydra/Chain/Direct.hs b/hydra-node/src/Hydra/Chain/Direct.hs index fc5c50d8381..87af6722214 100644 --- a/hydra-node/src/Hydra/Chain/Direct.hs +++ b/hydra-node/src/Hydra/Chain/Direct.hs @@ -28,13 +28,12 @@ import Hydra.Cardano.Api ( Block (..), BlockInMode (..), CardanoEra (..), - CardanoMode, ChainPoint, ChainTip, ConsensusModeParams (..), EpochSlots (..), EraHistory (EraHistory), - EraInMode (..), + IsShelleyBasedEra (..), LocalChainSyncClient (..), LocalNodeClientProtocols (..), LocalNodeConnectInfo (..), @@ -43,7 +42,7 @@ import Hydra.Cardano.Api ( SocketPath, Tx, TxInMode (..), - TxValidationErrorInMode, + TxValidationErrorInCardanoMode, chainTipToChainPoint, connectToLocalNode, getTxBody, @@ -154,8 +153,8 @@ mkTinyWallet tracer config = do epochInfo <- queryEpochInfo pure $ WalletInfoOnChain{walletUTxO, pparams, systemStart, epochInfo, tip = point} - toEpochInfo :: EraHistory CardanoMode -> EpochInfo (Either Text) - toEpochInfo (EraHistory _ interpreter) = + toEpochInfo :: EraHistory -> EpochInfo (Either Text) + toEpochInfo (EraHistory interpreter) = hoistEpochInfo (first show . runExcept) $ Consensus.interpreterToEpochInfo interpreter @@ -278,7 +277,7 @@ instance Exception EraNotSupportedException where otherEraName -- | The block type used in the node-to-client protocols. -type BlockType = BlockInMode CardanoMode +type BlockType = BlockInMode chainSyncClient :: forall m. @@ -315,7 +314,7 @@ chainSyncClient handler wallet startingPoint = ClientStNext { recvMsgRollForward = \blockInMode _tip -> ChainSyncClient $ do case blockInMode of - BlockInMode ConwayEra block _ -> do + BlockInMode ConwayEra block -> do -- TODO: uses cardano-api:internal -- NOTE: we should remove this dependency once we have ShelleyBlock available -- on the normal cardano-api library. @@ -333,17 +332,17 @@ chainSyncClient handler wallet startingPoint = -- Observe Hydra transactions onRollForward handler header txs pure clientStIdle - BlockInMode BabbageEra (Block header txs) _ -> do + BlockInMode BabbageEra (Block header txs) -> do -- Update the tiny wallet update wallet header txs -- Observe Hydra transactions onRollForward handler header txs pure clientStIdle - BlockInMode era@AlonzoEra _ _ -> throwIO $ EraNotSupportedAnymore{otherEraName = show era} - BlockInMode era@AllegraEra _ _ -> throwIO $ EraNotSupportedAnymore{otherEraName = show era} - BlockInMode era@MaryEra _ _ -> throwIO $ EraNotSupportedAnymore{otherEraName = show era} - BlockInMode era@ShelleyEra _ _ -> throwIO $ EraNotSupportedAnymore{otherEraName = show era} - BlockInMode era@ByronEra _ _ -> throwIO $ EraNotSupportedAnymore{otherEraName = show era} + BlockInMode era@AlonzoEra _ -> throwIO $ EraNotSupportedAnymore{otherEraName = show era} + BlockInMode era@AllegraEra _ -> throwIO $ EraNotSupportedAnymore{otherEraName = show era} + BlockInMode era@MaryEra _ -> throwIO $ EraNotSupportedAnymore{otherEraName = show era} + BlockInMode era@ShelleyEra _ -> throwIO $ EraNotSupportedAnymore{otherEraName = show era} + BlockInMode era@ByronEra _ -> throwIO $ EraNotSupportedAnymore{otherEraName = show era} , recvMsgRollBackward = \point _tip -> ChainSyncClient $ do -- Re-initialize the tiny wallet reset wallet @@ -357,18 +356,18 @@ txSubmissionClient :: (MonadSTM m, MonadDelay m) => Tracer m DirectChainLog -> TQueue m (Tx, TMVar m (Maybe (PostTxError Tx))) -> - LocalTxSubmissionClient (TxInMode CardanoMode) (TxValidationErrorInMode CardanoMode) m () + LocalTxSubmissionClient TxInMode TxValidationErrorInCardanoMode m () txSubmissionClient tracer queue = LocalTxSubmissionClient clientStIdle where - clientStIdle :: m (LocalTxClientStIdle (TxInMode CardanoMode) (TxValidationErrorInMode CardanoMode) m ()) + clientStIdle :: m (LocalTxClientStIdle TxInMode TxValidationErrorInCardanoMode m ()) clientStIdle = do (tx, response) <- atomically $ readTQueue queue let txId = getTxId $ getTxBody tx traceWith tracer PostingTx{txId} pure $ SendMsgSubmitTx - (TxInMode tx BabbageEraInCardanoMode) + (TxInMode shelleyBasedEra tx) ( \case SubmitSuccess -> do traceWith tracer PostedTx{txId} diff --git a/hydra-node/src/Hydra/Chain/Direct/TimeHandle.hs b/hydra-node/src/Hydra/Chain/Direct/TimeHandle.hs index 561fdcd3207..ffc048097fa 100644 --- a/hydra-node/src/Hydra/Chain/Direct/TimeHandle.hs +++ b/hydra-node/src/Hydra/Chain/Direct/TimeHandle.hs @@ -10,7 +10,6 @@ import Cardano.Slotting.Time (SystemStart (SystemStart), fromRelativeTime, toRel import Data.Time (secondsToNominalDiffTime) import Data.Time.Clock.POSIX (posixSecondsToUTCTime) import Hydra.Cardano.Api ( - CardanoMode, EraHistory (EraHistory), NetworkId, SocketPath, @@ -41,7 +40,7 @@ data TimeHandle = TimeHandle data TimeHandleParams = TimeHandleParams { systemStart :: SystemStart - , eraHistory :: EraHistory CardanoMode + , eraHistory :: EraHistory , horizonSlot :: SlotNo , currentSlot :: SlotNo } @@ -77,7 +76,7 @@ mkTimeHandle :: HasCallStack => SlotNo -> SystemStart -> - EraHistory CardanoMode -> + EraHistory -> TimeHandle mkTimeHandle currentSlotNo systemStart eraHistory = do TimeHandle @@ -101,7 +100,7 @@ mkTimeHandle currentSlotNo systemStart eraHistory = do Left pastHorizonEx -> Left $ show pastHorizonEx Right (slotNo, _timeSpentInSlot, _timeLeftInSlot) -> pure slotNo - (EraHistory _ interpreter) = eraHistory + (EraHistory interpreter) = eraHistory -- | Query node for system start and era history before constructing a -- 'TimeHandle' using the slot at the tip of the network. diff --git a/hydra-node/src/Hydra/Chain/Direct/Wallet.hs b/hydra-node/src/Hydra/Chain/Direct/Wallet.hs index 12e71fdf924..e2345ff46b6 100644 --- a/hydra-node/src/Hydra/Chain/Direct/Wallet.hs +++ b/hydra-node/src/Hydra/Chain/Direct/Wallet.hs @@ -10,9 +10,9 @@ import Cardano.Api.UTxO (UTxO) import Cardano.Api.UTxO qualified as UTxO import Cardano.Crypto.Hash.Class import Cardano.Ledger.Address qualified as Ledger +import Cardano.Ledger.Alonzo.Plutus.TxInfo (TranslationError) import Cardano.Ledger.Alonzo.PlutusScriptApi (language) import Cardano.Ledger.Alonzo.Scripts (ExUnits (ExUnits), Tag (Spend), txscriptfee) -import Cardano.Ledger.Alonzo.TxInfo (TranslationError) import Cardano.Ledger.Alonzo.TxWits (AlonzoTxWits (..), RdmrPtr (RdmrPtr), Redeemers (..), txdats, txscripts) import Cardano.Ledger.Api (TransactionScriptFailure, ensureMinCoinTxOut, evalTxExUnits, outputsTxBodyL, ppMaxTxExUnitsL, ppPricesL) import Cardano.Ledger.Babbage.Tx (body, getLanguageView, hashScriptIntegrity, wits) diff --git a/hydra-node/src/Hydra/Ledger/Cardano.hs b/hydra-node/src/Hydra/Ledger/Cardano.hs index 0ed6c5c44f1..00323723fac 100644 --- a/hydra-node/src/Hydra/Ledger/Cardano.hs +++ b/hydra-node/src/Hydra/Ledger/Cardano.hs @@ -428,7 +428,7 @@ genAddressInEra networkId = mkVkAddress networkId <$> genVerificationKey genValue :: Gen Value -genValue = scale (`div` 10) $ fromLedgerValue <$> arbitrary +genValue = liftA2 (<>) (pure $ lovelaceToValue $ Lovelace 10_000_000) (scale (`div` 10) $ fromLedgerValue <$> arbitrary) -- | Generate UTXO entries that do not contain any assets. Useful to test / -- measure cases where diff --git a/hydra-node/src/Hydra/Ledger/Cardano/Evaluate.hs b/hydra-node/src/Hydra/Ledger/Cardano/Evaluate.hs index 29c940ac210..6416bf1d56d 100644 --- a/hydra-node/src/Hydra/Ledger/Cardano/Evaluate.hs +++ b/hydra-node/src/Hydra/Ledger/Cardano/Evaluate.hs @@ -13,16 +13,16 @@ module Hydra.Ledger.Cardano.Evaluate where import Hydra.Prelude hiding (label) import Cardano.Api.UTxO qualified as UTxO -import Cardano.Ledger.Alonzo.Language (BinaryPlutus (..), Language (PlutusV2), Plutus (..)) +import Cardano.Ledger.Alonzo.Plutus.TxInfo (PlutusWithContext (PlutusWithContext)) import Cardano.Ledger.Alonzo.PlutusScriptApi qualified as Ledger import Cardano.Ledger.Alonzo.Scripts (CostModel, Prices (..), costModelsValid, emptyCostModels, mkCostModel, txscriptfee) -import Cardano.Ledger.Alonzo.Scripts.Data qualified as Ledger -import Cardano.Ledger.Alonzo.TxInfo (PlutusWithContext (PlutusWithContext)) import Cardano.Ledger.Api (CoinPerByte (..), ppCoinsPerUTxOByteL, ppCostModelsL, ppMaxBlockExUnitsL, ppMaxTxExUnitsL, ppMaxValSizeL, ppMinFeeAL, ppMinFeeBL, ppPricesL, ppProtocolVersionL) import Cardano.Ledger.BaseTypes (BoundedRational (boundRational), ProtVer (..), natVersion) import Cardano.Ledger.Binary (getVersion) import Cardano.Ledger.Coin (Coin (Coin)) import Cardano.Ledger.Core (PParams, ppMaxTxSizeL) +import Cardano.Ledger.Plutus.Data qualified as Ledger +import Cardano.Ledger.Plutus.Language (BinaryPlutus (..), Language (PlutusV2), Plutus (..)) import Cardano.Ledger.Val (Val ((<+>)), (<×>)) import Cardano.Slotting.EpochInfo (EpochInfo, fixedEpochInfo) import Cardano.Slotting.Slot (EpochNo (EpochNo), EpochSize (EpochSize), SlotNo (SlotNo)) @@ -39,10 +39,9 @@ import Data.SOP.NonEmpty (NonEmpty (NonEmptyOne)) import Data.Time.Clock.POSIX (posixSecondsToUTCTime) import Flat (flat) import Hydra.Cardano.Api ( - CardanoMode, - ConsensusMode (CardanoMode), EraHistory (EraHistory), ExecutionUnits (..), + IsCardanoEra (cardanoEra), LedgerEpochInfo (..), LedgerEra, LedgerProtocolParameters (..), @@ -115,6 +114,7 @@ evaluateTx' maxUnits tx utxo = do where result pparams' = evaluateTransactionExecutionUnits + cardanoEra systemStart (LedgerEpochInfo epochInfo) pparams' @@ -296,9 +296,9 @@ epochInfo = fixedEpochInfo epochSize slotLength -- -- NOTE: This era is using not so realistic epoch sizes of 1 and sets a slot -- length of 1 -eraHistoryWithHorizonAt :: SlotNo -> EraHistory CardanoMode +eraHistoryWithHorizonAt :: SlotNo -> EraHistory eraHistoryWithHorizonAt slotNo@(SlotNo n) = - EraHistory CardanoMode (mkInterpreter summary) + EraHistory (mkInterpreter summary) where summary :: Summary (CardanoEras StandardCrypto) summary = diff --git a/hydra-node/test/Hydra/Chain/Direct/Contract/Mutation.hs b/hydra-node/test/Hydra/Chain/Direct/Contract/Mutation.hs index 7ecd37e1046..c18fc6cf67b 100644 --- a/hydra-node/test/Hydra/Chain/Direct/Contract/Mutation.hs +++ b/hydra-node/test/Hydra/Chain/Direct/Contract/Mutation.hs @@ -132,7 +132,6 @@ import Hydra.Cardano.Api import Cardano.Api.UTxO qualified as UTxO import Cardano.Ledger.Alonzo.Scripts qualified as Ledger -import Cardano.Ledger.Alonzo.Scripts.Data qualified as Ledger import Cardano.Ledger.Alonzo.TxWits qualified as Ledger import Cardano.Ledger.Api (outputsTxBodyL) import Cardano.Ledger.Babbage.TxBody qualified as Ledger @@ -140,6 +139,7 @@ import Cardano.Ledger.Binary (mkSized) import Cardano.Ledger.Core qualified as Ledger import Cardano.Ledger.Credential (Credential (..)) import Cardano.Ledger.Mary.Value qualified as Ledger +import Cardano.Ledger.Plutus.Data qualified as Ledger import Control.Exception (assert) import Control.Lens ((^.)) import Data.Map qualified as Map diff --git a/hydra-test-utils/src/Test/Plutus/Validator.hs b/hydra-test-utils/src/Test/Plutus/Validator.hs index ff739b38eb5..91c254fb353 100644 --- a/hydra-test-utils/src/Test/Plutus/Validator.hs +++ b/hydra-test-utils/src/Test/Plutus/Validator.hs @@ -14,9 +14,9 @@ import Hydra.Prelude import Cardano.Api.UTxO qualified as UTxO import Cardano.Ledger.Alonzo.Core qualified as Ledger -import Cardano.Ledger.Alonzo.Language (Language (PlutusV2)) import Cardano.Ledger.Alonzo.Scripts (CostModel, costModelsValid, emptyCostModels, mkCostModel) import Cardano.Ledger.BaseTypes (ProtVer (..), natVersion) +import Cardano.Ledger.Plutus.Language (Language (PlutusV2)) import Cardano.Slotting.EpochInfo (fixedEpochInfo) import Cardano.Slotting.Slot (EpochSize (EpochSize)) import Cardano.Slotting.Time (mkSlotLength) @@ -38,6 +38,7 @@ import Hydra.Cardano.Api ( TxBody, UTxO, addTxIn, + cardanoEra, createAndValidateTransactionBody, defaultTxBodyContent, evaluateTransactionExecutionUnits, @@ -77,6 +78,7 @@ evaluateScriptExecutionUnits validatorScript redeemer = where result = evaluateTransactionExecutionUnits + cardanoEra systemStart (LedgerEpochInfo epochInfo) (LedgerProtocolParameters pparams) From 288d5dba67c2a478cbc63069e6b1eaf06e83d258 Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Wed, 31 Jan 2024 12:35:15 +0100 Subject: [PATCH 3/4] Convert UTxO from supported eras to BabbageEra This works as long as all shelley based eras use the 'MaryValue era' type from the cardano-ledger. --- hydra-cardano-api/src/Cardano/Api/UTxO.hs | 62 +++++++++++---------- hydra-node/src/Hydra/Chain/CardanoClient.hs | 6 +- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/hydra-cardano-api/src/Cardano/Api/UTxO.hs b/hydra-cardano-api/src/Cardano/Api/UTxO.hs index b9894276eb4..f21aa9ca965 100644 --- a/hydra-cardano-api/src/Cardano/Api/UTxO.hs +++ b/hydra-cardano-api/src/Cardano/Api/UTxO.hs @@ -11,6 +11,7 @@ module Cardano.Api.UTxO where import Cardano.Api hiding (UTxO, toLedgerUTxO) import Cardano.Api qualified import Cardano.Api.Shelley (ReferenceScript (..)) +import Cardano.Ledger.Babbage () import Data.Bifunctor (second) import Data.Coerce (coerce) import Data.List qualified as List @@ -87,35 +88,38 @@ min = UTxO . uncurry Map.singleton . Map.findMin . toMap -- * Type Conversions -- | Transforms a UTxO containing tx outs from any era into Babbage era. -fromApi :: forall era. ShelleyBasedEra era -> Cardano.Api.UTxO era -> UTxO -fromApi sbe (Cardano.Api.UTxO eraUTxO) = - let eraPairs = Map.toList eraUTxO - babbagePairs = second (coerceOutputToEra sbe) <$> eraPairs - in fromPairs babbagePairs - -coerceOutputToEra :: forall era. ShelleyBasedEra era -> TxOut CtxUTxO era -> TxOut CtxUTxO Era -coerceOutputToEra sbe (TxOut eraAddress eraValue eraDatum eraRefScript) = - TxOut - (coerceAddressToEra eraAddress) - (coerceValueToEra sbe eraValue) - (coerceDatumToEra eraDatum) - (coerceRefScriptToEra eraRefScript) - -coerceAddressToEra :: AddressInEra era -> AddressInEra Era -coerceAddressToEra (AddressInEra _ eraAddress) = anyAddressInShelleyBasedEra ShelleyBasedEraBabbage (toAddressAny eraAddress) - -coerceValueToEra :: forall era. ShelleyBasedEra era -> TxOutValue era -> TxOutValue Era -coerceValueToEra _ (TxOutValueByron eraLovelace) = lovelaceToTxOutValue shelleyBasedEra eraLovelace -coerceValueToEra sbe (TxOutValueShelleyBased _ value) = TxOutValueShelleyBased ShelleyBasedEraBabbage (toLedgerValue MaryEraOnwardsBabbage $ fromLedgerValue sbe value) - -coerceDatumToEra :: TxOutDatum CtxUTxO era -> TxOutDatum CtxUTxO Era -coerceDatumToEra TxOutDatumNone = TxOutDatumNone -coerceDatumToEra (TxOutDatumHash _ hashScriptData) = TxOutDatumHash AlonzoEraOnwardsBabbage hashScriptData -coerceDatumToEra (TxOutDatumInline _ hashableScriptData) = TxOutDatumInline BabbageEraOnwardsBabbage hashableScriptData - -coerceRefScriptToEra :: ReferenceScript era -> ReferenceScript Era -coerceRefScriptToEra ReferenceScriptNone = ReferenceScriptNone -coerceRefScriptToEra (ReferenceScript _ scriptInAnyLang) = ReferenceScript BabbageEraOnwardsBabbage scriptInAnyLang +fromApi :: Cardano.Api.UTxO era -> UTxO +fromApi (Cardano.Api.UTxO eraUTxO) = + fromPairs $ second convertOutputToEra <$> Map.toList eraUTxO + where + -- NOTE: At latest the TxOutValue is an existential where we need to case on + -- the 'sbe' witness to get constraints on the contained 'value', but the + -- 'cardano-api' does that already when allowing conversion of their + -- (complicated) constrained types to the cardano-ledger types - so we just + -- convert forth and back. + convertOutputToEra :: TxOut CtxUTxO era -> TxOut CtxUTxO Era + convertOutputToEra (TxOut eraAddress eraValue eraDatum eraRefScript) = + TxOut + (convertAddressToEra eraAddress) + (convertValueToEra eraValue) + (convertDatumToEra eraDatum) + (convertRefScriptToEra eraRefScript) + + convertAddressToEra :: AddressInEra era -> AddressInEra Era + convertAddressToEra (AddressInEra _ eraAddress) = anyAddressInShelleyBasedEra ShelleyBasedEraBabbage (toAddressAny eraAddress) + + convertValueToEra :: TxOutValue era -> TxOutValue Era + convertValueToEra (TxOutValueByron lovelace) = lovelaceToTxOutValue shelleyBasedEra lovelace + convertValueToEra (TxOutValueShelleyBased sbe value) = TxOutValueShelleyBased shelleyBasedEra (toLedgerValue MaryEraOnwardsBabbage $ fromLedgerValue sbe value) + + convertDatumToEra :: TxOutDatum CtxUTxO era -> TxOutDatum CtxUTxO Era + convertDatumToEra TxOutDatumNone = TxOutDatumNone + convertDatumToEra (TxOutDatumHash _ hashScriptData) = TxOutDatumHash AlonzoEraOnwardsBabbage hashScriptData + convertDatumToEra (TxOutDatumInline _ hashableScriptData) = TxOutDatumInline BabbageEraOnwardsBabbage hashableScriptData + + convertRefScriptToEra :: ReferenceScript era -> ReferenceScript Era + convertRefScriptToEra ReferenceScriptNone = ReferenceScriptNone + convertRefScriptToEra (ReferenceScript _ scriptInAnyLang) = ReferenceScript BabbageEraOnwardsBabbage scriptInAnyLang toApi :: UTxO -> Cardano.Api.UTxO Era toApi = coerce diff --git a/hydra-node/src/Hydra/Chain/CardanoClient.hs b/hydra-node/src/Hydra/Chain/CardanoClient.hs index 83a624abbd0..bd855fdfc58 100644 --- a/hydra-node/src/Hydra/Chain/CardanoClient.hs +++ b/hydra-node/src/Hydra/Chain/CardanoClient.hs @@ -321,7 +321,7 @@ queryUTxO networkId socket queryPoint addresses = queryUTxOExpr :: ShelleyBasedEra era -> [Address ShelleyAddr] -> LocalStateQueryExpr b p QueryInMode r IO UTxO queryUTxOExpr sbe addresses = do eraUTxO <- queryInShelleyBasedEraExpr sbe $ QueryUTxO (QueryUTxOByAddress (Set.fromList $ map AddressShelley addresses)) - pure $ UTxO.fromApi sbe eraUTxO + pure $ UTxO.fromApi eraUTxO -- | Query UTxO for given tx inputs at given point. -- @@ -339,7 +339,7 @@ queryUTxOByTxIn networkId socket queryPoint inputs = (AnyCardanoEra era) <- queryCurrentEraExpr (sbe :: ShelleyBasedEra e) <- liftIO $ assumeShelleyBasedEraOrThrow era eraUTxO <- queryInShelleyBasedEraExpr sbe $ QueryUTxO (QueryUTxOByTxIn (Set.fromList inputs)) - pure $ UTxO.fromApi sbe eraUTxO + pure $ UTxO.fromApi eraUTxO assumeShelleyBasedEraOrThrow :: MonadThrow m => CardanoEra era -> m (ShelleyBasedEra era) assumeShelleyBasedEraOrThrow era = do @@ -360,7 +360,7 @@ queryUTxOWhole :: QueryPoint -> IO UTxO queryUTxOWhole networkId socket queryPoint = do - UTxO.fromApi ShelleyBasedEraBabbage <$> (runQuery networkId socket queryPoint query >>= throwOnEraMismatch) + UTxO.fromApi <$> (runQuery networkId socket queryPoint query >>= throwOnEraMismatch) where query = QueryInEra From 82a47a5144a26bc098dc687f660a3a2816f7dc6d Mon Sep 17 00:00:00 2001 From: Daniel Firth Date: Fri, 2 Feb 2024 12:58:24 +0000 Subject: [PATCH 4/4] Add ADA to genTxOut --- hydra-node/src/Hydra/Ledger/Cardano.hs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hydra-node/src/Hydra/Ledger/Cardano.hs b/hydra-node/src/Hydra/Ledger/Cardano.hs index 00323723fac..59d0cc530bf 100644 --- a/hydra-node/src/Hydra/Ledger/Cardano.hs +++ b/hydra-node/src/Hydra/Ledger/Cardano.hs @@ -362,10 +362,11 @@ genTxOut = `suchThat` notByronAddress where gen = - oneof - [ fromLedgerTxOut <$> arbitrary - , notMultiAsset . fromLedgerTxOut <$> arbitrary - ] + fmap (modifyTxOutValue (<> (lovelaceToValue $ Lovelace 10_000_000))) $ + oneof + [ fromLedgerTxOut <$> arbitrary + , notMultiAsset . fromLedgerTxOut <$> arbitrary + ] notMultiAsset = modifyTxOutValue (lovelaceToValue . selectLovelace)