Skip to content

Commit

Permalink
Add module for UTxO type and operations
Browse files Browse the repository at this point in the history
  • Loading branch information
locallycompact committed Feb 10, 2025
1 parent ab6fc23 commit e36dbb9
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 28 deletions.
2 changes: 2 additions & 0 deletions cardano-api/cardano-api.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ library
Cardano.Api.Ledger.Lens
Cardano.Api.Network
Cardano.Api.Shelley
Cardano.Api.Tx.UTxO

build-depends:
FailT,
Expand Down Expand Up @@ -244,6 +245,7 @@ library
Cardano.Api.Internal.StakePoolMetadata
Cardano.Api.Internal.Tx.Body
Cardano.Api.Internal.Tx.Compatible
Cardano.Api.Internal.Tx.UTxO
Cardano.Api.Internal.TxIn
Cardano.Api.Internal.TxMetadata
Cardano.Api.Internal.Utils
Expand Down
1 change: 1 addition & 0 deletions cardano-api/src/Cardano/Api.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,7 @@ import Cardano.Api.Internal.SerialiseUsing
import Cardano.Api.Internal.StakePoolMetadata
import Cardano.Api.Internal.Tx.Body
import Cardano.Api.Internal.Tx.Sign
import Cardano.Api.Internal.Tx.UTxO
import Cardano.Api.Internal.TxMetadata
import Cardano.Api.Internal.Utils
import Cardano.Api.Internal.Value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Cardano.Api.Internal.ProtocolParameters
import Cardano.Api.Internal.Query
import Cardano.Api.Internal.Tx.Body
import Cardano.Api.Internal.Tx.Sign
import Cardano.Api.Internal.Tx.UTxO (UTxO(..))
import Cardano.Api.Internal.Utils

import qualified Cardano.Ledger.Api as L
Expand Down
1 change: 1 addition & 0 deletions cardano-api/src/Cardano/Api/Internal/Convenience/Query.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import Cardano.Api.Internal.ProtocolParameters
import Cardano.Api.Internal.Query
import Cardano.Api.Internal.Query.Expr
import Cardano.Api.Internal.Tx.Body
import Cardano.Api.Internal.Tx.UTxO
import Cardano.Api.Internal.Utils

import qualified Cardano.Ledger.Api as L
Expand Down
2 changes: 2 additions & 0 deletions cardano-api/src/Cardano/Api/Internal/Fees.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ import Cardano.Api.Internal.Query
import Cardano.Api.Internal.Script
import Cardano.Api.Internal.Tx.Body
import Cardano.Api.Internal.Tx.Sign
import Cardano.Api.Internal.Tx.UTxO
import Cardano.Api.Internal.Value

import qualified Cardano.Api.Ledger.Lens as A

import qualified Cardano.Ledger.Alonzo.Core as Ledger
Expand Down
3 changes: 2 additions & 1 deletion cardano-api/src/Cardano/Api/Internal/Plutus.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import Cardano.Api.Internal.Eon.AlonzoEraOnwards (AlonzoEraOnwards (..
import Cardano.Api.Internal.Eon.Convert (convert)
import Cardano.Api.Internal.Eon.ShelleyBasedEra (ShelleyLedgerEra)
import Cardano.Api.Internal.Pretty (Pretty (pretty), docToText)
import Cardano.Api.Internal.Query (UTxO, toLedgerUTxO)
import Cardano.Api.Internal.Query (toLedgerUTxO)
import qualified Cardano.Api.Internal.ReexposeLedger as L
import Cardano.Api.Internal.Script (ScriptHash, fromShelleyScriptHash)
import qualified Cardano.Api.Internal.Script as Api
import Cardano.Api.Internal.Tx.Body (ScriptWitnessIndex (..), toScriptIndex)
import Cardano.Api.Internal.Tx.Sign (Tx (..))
import Cardano.Api.Internal.Tx.UTxO (UTxO)

import qualified Cardano.Ledger.Alonzo.Scripts as L
import qualified Cardano.Ledger.Alonzo.UTxO as Alonzo
Expand Down
28 changes: 1 addition & 27 deletions cardano-api/src/Cardano/Api/Internal/Query.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ module Cardano.Api.Internal.Query
, QueryInEra (..)
, QueryInShelleyBasedEra (..)
, QueryUTxOFilter (..)
, UTxO (..)
, UTxOInAnyEra (..)

-- * Internal conversion functions
Expand Down Expand Up @@ -80,6 +79,7 @@ import Cardano.Api.Internal.ProtocolParameters
import Cardano.Api.Internal.Query.Types
import qualified Cardano.Api.Internal.ReexposeLedger as Ledger
import Cardano.Api.Internal.Tx.Body
import Cardano.Api.Internal.Tx.UTxO

import qualified Cardano.Chain.Update.Validation.Interface as Byron.Update
import qualified Cardano.Ledger.Api as L
Expand Down Expand Up @@ -117,10 +117,6 @@ import Ouroboros.Network.PeerSelection.LedgerPeers.Type (LedgerPeerSna
import Ouroboros.Network.Protocol.LocalStateQuery.Client (Some (..))

import Control.Monad.Trans.Except
import Data.Aeson (FromJSON (..), ToJSON (..), withObject)
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.KeyMap as KeyMap
import Data.Aeson.Types (Parser)
import Data.Bifunctor (bimap, first)
import qualified Data.ByteString.Lazy as LBS
import Data.Either.Combinators (rightToMaybe)
Expand Down Expand Up @@ -374,9 +370,6 @@ instance NodeToClientVersionOf QueryUTxOFilter where
newtype ByronUpdateState = ByronUpdateState Byron.Update.State
deriving Show

newtype UTxO era = UTxO {unUTxO :: Map TxIn (TxOut CtxUTxO era)}
deriving (Eq, Show)

data UTxOInAnyEra where
UTxOInAnyEra
:: CardanoEra era
Expand All @@ -385,25 +378,6 @@ data UTxOInAnyEra where

deriving instance Show UTxOInAnyEra

instance IsCardanoEra era => ToJSON (UTxO era) where
toJSON (UTxO m) = toJSON m
toEncoding (UTxO m) = toEncoding m

instance
(IsShelleyBasedEra era, FromJSON (TxOut CtxUTxO era))
=> FromJSON (UTxO era)
where
parseJSON = withObject "UTxO" $ \hm -> do
let l = toList $ KeyMap.toHashMapText hm
res <- mapM toTxIn l
pure . UTxO $ fromList res
where
toTxIn :: (Text, Aeson.Value) -> Parser (TxIn, TxOut CtxUTxO era)
toTxIn (txinText, txOutVal) = do
(,)
<$> parseJSON (Aeson.String txinText)
<*> parseJSON txOutVal

newtype SerialisedDebugLedgerState era
= SerialisedDebugLedgerState (Serialised (Shelley.NewEpochState (ShelleyLedgerEra era)))

Expand Down
1 change: 1 addition & 0 deletions cardano-api/src/Cardano/Api/Internal/Query/Expr.hs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import Cardano.Api.Internal.NetworkId
import Cardano.Api.Internal.ProtocolParameters
import Cardano.Api.Internal.Query
import qualified Cardano.Api.Internal.ReexposeLedger as Ledger
import Cardano.Api.Internal.Tx.UTxO

import qualified Cardano.Ledger.Api as L
import qualified Cardano.Ledger.Api.State.Query as L
Expand Down
79 changes: 79 additions & 0 deletions cardano-api/src/Cardano/Api/Internal/Tx/UTxO.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}

module Cardano.Api.Internal.Tx.UTxO where

import Cardano.Api.Internal.Eon.ShelleyBasedEra (IsShelleyBasedEra)
import Cardano.Api.Internal.Eras.Core (IsCardanoEra)
import Cardano.Api.Internal.Tx.Body (CtxUTxO, TxOut (..))
import Cardano.Api.Internal.TxIn (TxIn (..))

import Cardano.Ledger.Babbage ()

import Data.Aeson (FromJSON (..), ToJSON (..))
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.KeyMap as KeyMap
import Data.Aeson.Types (Parser)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Set (Set)
import Data.Text (Text)
import GHC.Exts (IsList (..))

newtype UTxO era = UTxO {unUTxO :: Map TxIn (TxOut CtxUTxO era)}
deriving stock (Eq, Show)
deriving newtype (Semigroup, Monoid, IsList)

instance IsCardanoEra era => ToJSON (UTxO era) where
toJSON (UTxO m) = toJSON m
toEncoding (UTxO m) = toEncoding m

instance
IsShelleyBasedEra era
=> FromJSON (UTxO era)
where
parseJSON = Aeson.withObject "UTxO" $ \hm -> do
let l = toList $ KeyMap.toHashMapText hm
res <- mapM toTxIn l
pure . UTxO $ Map.fromList res
where
toTxIn :: (Text, Aeson.Value) -> Parser (TxIn, TxOut CtxUTxO era)
toTxIn (txinText, txOutVal) = do
(,)
<$> parseJSON (Aeson.String txinText)
<*> parseJSON txOutVal

-- | Infix version of `difference`.
(\\) :: UTxO era -> UTxO era -> UTxO era
a \\ b = difference a b

-- | Create an empty `UTxO`.
empty :: UTxO era
empty = UTxO Map.empty

-- | Create a `UTxO` from a single unspent transaction output.
singleton :: TxIn -> TxOut CtxUTxO era -> UTxO era
singleton i o = UTxO $ Map.singleton i o

-- | Find a 'TxOut' for a given 'TxIn'.
lookup :: TxIn -> UTxO era -> Maybe (TxOut CtxUTxO era)
lookup k = Map.lookup k . unUTxO

-- | Filter all `TxOut` that satisfy the predicate.
filter :: (TxOut CtxUTxO era -> Bool) -> UTxO era -> UTxO era
filter fn = UTxO . Map.filter fn . unUTxO

-- | Filter all UTxO to only include 'out's satisfying given predicate.
filterWithKey :: (TxIn -> TxOut CtxUTxO era -> Bool) -> UTxO era -> UTxO era
filterWithKey fn = UTxO . Map.filterWithKey fn . unUTxO

-- | Get the 'UTxO domain input's set
inputSet :: UTxO (TxOut CtxUTxO era) -> Set TxIn
inputSet = Map.keysSet . unUTxO

-- | Remove the right hand side from the left hand side.
difference :: UTxO era -> UTxO era -> UTxO era
difference a b = UTxO $ Map.difference (unUTxO a) (unUTxO b)
12 changes: 12 additions & 0 deletions cardano-api/src/Cardano/Api/Tx/UTxO.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Cardano.Api.Tx.UTxO
( UTxO.empty
, UTxO.singleton
, UTxO.lookup
, UTxO.filter
, UTxO.filterWithKey
, UTxO.inputSet
, UTxO.difference
)
where

import qualified Cardano.Api.Internal.Tx.UTxO as UTxO

0 comments on commit e36dbb9

Please sign in to comment.