Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add module for UTxO type and operations #710

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cardano-api/cardano-api.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ library internal
Cardano.Api.Query
Cardano.Api.Query.Expr
Cardano.Api.Query.Types
Cardano.Api.Query.UTxO
Cardano.Api.ReexposeConsensus
Cardano.Api.ReexposeLedger
Cardano.Api.ReexposeNetwork
Expand Down Expand Up @@ -227,6 +228,7 @@ library internal
transformers,
transformers-except ^>=0.1.3,
typed-protocols ^>=0.1.1,
unordered-containers,
vector,
yaml,

Expand All @@ -248,6 +250,7 @@ library
Cardano.Api.Ledger
Cardano.Api.Network
Cardano.Api.Shelley
Cardano.Api.UTxO

reexported-modules: Cardano.Api.Ledger.Lens
build-depends:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Cardano.Api.Eon.ShelleyBasedEra
import Cardano.Api.Fees
import Cardano.Api.ProtocolParameters
import Cardano.Api.Query
import Cardano.Api.Query.UTxO (UTxO (..))
import Cardano.Api.Tx.Body
import Cardano.Api.Tx.Sign
import Cardano.Api.Utils
Expand Down
1 change: 1 addition & 0 deletions cardano-api/internal/Cardano/Api/Convenience/Query.hs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import Cardano.Api.NetworkId
import Cardano.Api.ProtocolParameters
import Cardano.Api.Query
import Cardano.Api.Query.Expr
import Cardano.Api.Query.UTxO (UTxO)
import Cardano.Api.Tx.Body
import Cardano.Api.Utils

Expand Down
1 change: 1 addition & 0 deletions cardano-api/internal/Cardano/Api/Fees.hs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import Cardano.Api.Plutus
import Cardano.Api.Pretty
import Cardano.Api.ProtocolParameters
import Cardano.Api.Query
import Cardano.Api.Query.UTxO (UTxO (..))
import Cardano.Api.Script
import Cardano.Api.Tx.Body
import Cardano.Api.Tx.Sign
Expand Down
28 changes: 1 addition & 27 deletions cardano-api/internal/Cardano/Api/Query.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ module Cardano.Api.Query
, QueryInEra (..)
, QueryInShelleyBasedEra (..)
, QueryUTxOFilter (..)
, UTxO (..)
, UTxOInAnyEra (..)

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

Expand Down Expand Up @@ -115,10 +115,6 @@ import Ouroboros.Network.NodeToClient.Version (NodeToClientVersion (..
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 @@ -363,9 +359,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 @@ -374,25 +367,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/internal/Cardano/Api/Query/Expr.hs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import Cardano.Api.Keys.Shelley
import Cardano.Api.NetworkId
import Cardano.Api.ProtocolParameters
import Cardano.Api.Query
import Cardano.Api.Query.UTxO (UTxO)
import qualified Cardano.Api.ReexposeLedger as Ledger

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why UndecidableInstances is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently

internal/Cardano/Api/Query/UTxO.hs:29:20: error: [GHC-22979]
    • The type-family application ‘Item (Map TxIn (TxOut CtxUTxO era))’
        is no smaller than the LHS of the family instance ‘Item (UTxO era)’
    • In the instance declaration for ‘IsList (UTxO era)’
    Suggested fix: Perhaps you intended to use UndecidableInstances
   |
29 |   deriving newtype IsList
   |                    ^^^^^^

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carbolymer Do you believe this should not be needed?


module Cardano.Api.Query.UTxO where

import Cardano.Api.Eon.ShelleyBasedEra (IsShelleyBasedEra)
import Cardano.Api.Eras.Core (IsCardanoEra)
import Cardano.Api.Tx.Body (CtxUTxO, TxOut (..))
import Cardano.Api.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 qualified Data.HashMap.Strict as HashMap
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)}
locallycompact marked this conversation as resolved.
Show resolved Hide resolved
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 = HashMap.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

-- | Same as `lookup`.
resolve :: TxIn -> UTxO era -> Maybe (TxOut CtxUTxO era)
resolve = Cardano.Api.Query.UTxO.lookup

-- | 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)
1 change: 1 addition & 0 deletions cardano-api/src/Cardano/Api.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,7 @@ import Cardano.Api.Protocol
import Cardano.Api.ProtocolParameters
import Cardano.Api.Query hiding (LedgerState (..))
import Cardano.Api.Query.Expr
import Cardano.Api.Query.UTxO (UTxO (..))
import Cardano.Api.Rewards
import Cardano.Api.Script
import Cardano.Api.ScriptData
Expand Down
3 changes: 3 additions & 0 deletions cardano-api/src/Cardano/Api/UTxO.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module Cardano.Api.UTxO (module Cardano.Api.Query.UTxO) where

import Cardano.Api.Query.UTxO
Loading