{-# LANGUAGE DeriveAnyClass    #-}
{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE DerivingVia       #-}
{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE NamedFieldPuns    #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards   #-}
{-# LANGUAGE TemplateHaskell   #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# OPTIONS_GHC -fno-specialise #-}
{-# OPTIONS_GHC -fno-omit-interface-pragmas #-}

module Plutus.V1.Ledger.Tx(
    -- * Transactions
    TxId (..),
    ScriptTag (..),
    RedeemerPtr (..),
    Redeemers,
    -- * Transaction outputs
    TxOut(..),
    TxOutRef(..),
    isPubKeyOut,
    isPayToScriptOut,
    outAddress,
    outValue,
    txOutPubKey,
    txOutDatum,
    pubKeyHashTxOut,
    -- * Transaction inputs
    TxInType(..),
    TxIn(..),
    inRef,
    inType,
    inScripts,
    pubKeyTxIn,
    scriptTxIn,
    pubKeyTxIns,
    scriptTxIns,
    ) where

import Control.DeepSeq (NFData)
import Control.Lens
import Data.Map (Map)
import Data.Maybe (isJust)
import Data.Set qualified as Set
import Data.String (IsString)
import GHC.Generics (Generic)
import Prettyprinter

import PlutusTx qualified
import PlutusTx.Bool qualified as PlutusTx
import PlutusTx.Builtins qualified as PlutusTx
import PlutusTx.Eq qualified as PlutusTx
import PlutusTx.Ord qualified as PlutusTx

import Plutus.V1.Ledger.Address
import Plutus.V1.Ledger.Bytes
import Plutus.V1.Ledger.Crypto
import Plutus.V1.Ledger.Scripts
import Plutus.V1.Ledger.Value

-- | A transaction ID, using a SHA256 hash as the transaction id.
newtype TxId = TxId { TxId -> BuiltinByteString
getTxId :: PlutusTx.BuiltinByteString }
    deriving stock (TxId -> TxId -> Bool
(TxId -> TxId -> Bool) -> (TxId -> TxId -> Bool) -> Eq TxId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TxId -> TxId -> Bool
$c/= :: TxId -> TxId -> Bool
== :: TxId -> TxId -> Bool
$c== :: TxId -> TxId -> Bool
Eq, Eq TxId
Eq TxId
-> (TxId -> TxId -> Ordering)
-> (TxId -> TxId -> Bool)
-> (TxId -> TxId -> Bool)
-> (TxId -> TxId -> Bool)
-> (TxId -> TxId -> Bool)
-> (TxId -> TxId -> TxId)
-> (TxId -> TxId -> TxId)
-> Ord TxId
TxId -> TxId -> Bool
TxId -> TxId -> Ordering
TxId -> TxId -> TxId
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: TxId -> TxId -> TxId
$cmin :: TxId -> TxId -> TxId
max :: TxId -> TxId -> TxId
$cmax :: TxId -> TxId -> TxId
>= :: TxId -> TxId -> Bool
$c>= :: TxId -> TxId -> Bool
> :: TxId -> TxId -> Bool
$c> :: TxId -> TxId -> Bool
<= :: TxId -> TxId -> Bool
$c<= :: TxId -> TxId -> Bool
< :: TxId -> TxId -> Bool
$c< :: TxId -> TxId -> Bool
compare :: TxId -> TxId -> Ordering
$ccompare :: TxId -> TxId -> Ordering
$cp1Ord :: Eq TxId
Ord, (forall x. TxId -> Rep TxId x)
-> (forall x. Rep TxId x -> TxId) -> Generic TxId
forall x. Rep TxId x -> TxId
forall x. TxId -> Rep TxId x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TxId x -> TxId
$cfrom :: forall x. TxId -> Rep TxId x
Generic)
    deriving anyclass (TxId -> ()
(TxId -> ()) -> NFData TxId
forall a. (a -> ()) -> NFData a
rnf :: TxId -> ()
$crnf :: TxId -> ()
NFData)
    deriving newtype (TxId -> TxId -> Bool
(TxId -> TxId -> Bool) -> Eq TxId
forall a. (a -> a -> Bool) -> Eq a
== :: TxId -> TxId -> Bool
$c== :: TxId -> TxId -> Bool
PlutusTx.Eq, Eq TxId
Eq TxId
-> (TxId -> TxId -> Ordering)
-> (TxId -> TxId -> Bool)
-> (TxId -> TxId -> Bool)
-> (TxId -> TxId -> Bool)
-> (TxId -> TxId -> Bool)
-> (TxId -> TxId -> TxId)
-> (TxId -> TxId -> TxId)
-> Ord TxId
TxId -> TxId -> Bool
TxId -> TxId -> Ordering
TxId -> TxId -> TxId
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: TxId -> TxId -> TxId
$cmin :: TxId -> TxId -> TxId
max :: TxId -> TxId -> TxId
$cmax :: TxId -> TxId -> TxId
>= :: TxId -> TxId -> Bool
$c>= :: TxId -> TxId -> Bool
> :: TxId -> TxId -> Bool
$c> :: TxId -> TxId -> Bool
<= :: TxId -> TxId -> Bool
$c<= :: TxId -> TxId -> Bool
< :: TxId -> TxId -> Bool
$c< :: TxId -> TxId -> Bool
compare :: TxId -> TxId -> Ordering
$ccompare :: TxId -> TxId -> Ordering
$cp1Ord :: Eq TxId
PlutusTx.Ord)
    deriving (Int -> TxId -> ShowS
[TxId] -> ShowS
TxId -> String
(Int -> TxId -> ShowS)
-> (TxId -> String) -> ([TxId] -> ShowS) -> Show TxId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TxId] -> ShowS
$cshowList :: [TxId] -> ShowS
show :: TxId -> String
$cshow :: TxId -> String
showsPrec :: Int -> TxId -> ShowS
$cshowsPrec :: Int -> TxId -> ShowS
Show, [TxId] -> Doc ann
TxId -> Doc ann
(forall ann. TxId -> Doc ann)
-> (forall ann. [TxId] -> Doc ann) -> Pretty TxId
forall ann. [TxId] -> Doc ann
forall ann. TxId -> Doc ann
forall a.
(forall ann. a -> Doc ann)
-> (forall ann. [a] -> Doc ann) -> Pretty a
prettyList :: [TxId] -> Doc ann
$cprettyList :: forall ann. [TxId] -> Doc ann
pretty :: TxId -> Doc ann
$cpretty :: forall ann. TxId -> Doc ann
Pretty, String -> TxId
(String -> TxId) -> IsString TxId
forall a. (String -> a) -> IsString a
fromString :: String -> TxId
$cfromString :: String -> TxId
IsString) via LedgerBytes

-- | A tag indicating the type of script that we are pointing to.
data ScriptTag = Spend | Mint | Cert | Reward
    deriving stock (Int -> ScriptTag -> ShowS
[ScriptTag] -> ShowS
ScriptTag -> String
(Int -> ScriptTag -> ShowS)
-> (ScriptTag -> String)
-> ([ScriptTag] -> ShowS)
-> Show ScriptTag
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ScriptTag] -> ShowS
$cshowList :: [ScriptTag] -> ShowS
show :: ScriptTag -> String
$cshow :: ScriptTag -> String
showsPrec :: Int -> ScriptTag -> ShowS
$cshowsPrec :: Int -> ScriptTag -> ShowS
Show, ScriptTag -> ScriptTag -> Bool
(ScriptTag -> ScriptTag -> Bool)
-> (ScriptTag -> ScriptTag -> Bool) -> Eq ScriptTag
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ScriptTag -> ScriptTag -> Bool
$c/= :: ScriptTag -> ScriptTag -> Bool
== :: ScriptTag -> ScriptTag -> Bool
$c== :: ScriptTag -> ScriptTag -> Bool
Eq, Eq ScriptTag
Eq ScriptTag
-> (ScriptTag -> ScriptTag -> Ordering)
-> (ScriptTag -> ScriptTag -> Bool)
-> (ScriptTag -> ScriptTag -> Bool)
-> (ScriptTag -> ScriptTag -> Bool)
-> (ScriptTag -> ScriptTag -> Bool)
-> (ScriptTag -> ScriptTag -> ScriptTag)
-> (ScriptTag -> ScriptTag -> ScriptTag)
-> Ord ScriptTag
ScriptTag -> ScriptTag -> Bool
ScriptTag -> ScriptTag -> Ordering
ScriptTag -> ScriptTag -> ScriptTag
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ScriptTag -> ScriptTag -> ScriptTag
$cmin :: ScriptTag -> ScriptTag -> ScriptTag
max :: ScriptTag -> ScriptTag -> ScriptTag
$cmax :: ScriptTag -> ScriptTag -> ScriptTag
>= :: ScriptTag -> ScriptTag -> Bool
$c>= :: ScriptTag -> ScriptTag -> Bool
> :: ScriptTag -> ScriptTag -> Bool
$c> :: ScriptTag -> ScriptTag -> Bool
<= :: ScriptTag -> ScriptTag -> Bool
$c<= :: ScriptTag -> ScriptTag -> Bool
< :: ScriptTag -> ScriptTag -> Bool
$c< :: ScriptTag -> ScriptTag -> Bool
compare :: ScriptTag -> ScriptTag -> Ordering
$ccompare :: ScriptTag -> ScriptTag -> Ordering
$cp1Ord :: Eq ScriptTag
Ord, (forall x. ScriptTag -> Rep ScriptTag x)
-> (forall x. Rep ScriptTag x -> ScriptTag) -> Generic ScriptTag
forall x. Rep ScriptTag x -> ScriptTag
forall x. ScriptTag -> Rep ScriptTag x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ScriptTag x -> ScriptTag
$cfrom :: forall x. ScriptTag -> Rep ScriptTag x
Generic)
    deriving anyclass (ScriptTag -> ()
(ScriptTag -> ()) -> NFData ScriptTag
forall a. (a -> ()) -> NFData a
rnf :: ScriptTag -> ()
$crnf :: ScriptTag -> ()
NFData)

-- | A redeemer pointer is a pair of a script type tag t and an index i, picking out the ith
-- script of type t in the transaction.
data RedeemerPtr = RedeemerPtr ScriptTag Integer
    deriving stock (Int -> RedeemerPtr -> ShowS
[RedeemerPtr] -> ShowS
RedeemerPtr -> String
(Int -> RedeemerPtr -> ShowS)
-> (RedeemerPtr -> String)
-> ([RedeemerPtr] -> ShowS)
-> Show RedeemerPtr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RedeemerPtr] -> ShowS
$cshowList :: [RedeemerPtr] -> ShowS
show :: RedeemerPtr -> String
$cshow :: RedeemerPtr -> String
showsPrec :: Int -> RedeemerPtr -> ShowS
$cshowsPrec :: Int -> RedeemerPtr -> ShowS
Show, RedeemerPtr -> RedeemerPtr -> Bool
(RedeemerPtr -> RedeemerPtr -> Bool)
-> (RedeemerPtr -> RedeemerPtr -> Bool) -> Eq RedeemerPtr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RedeemerPtr -> RedeemerPtr -> Bool
$c/= :: RedeemerPtr -> RedeemerPtr -> Bool
== :: RedeemerPtr -> RedeemerPtr -> Bool
$c== :: RedeemerPtr -> RedeemerPtr -> Bool
Eq, Eq RedeemerPtr
Eq RedeemerPtr
-> (RedeemerPtr -> RedeemerPtr -> Ordering)
-> (RedeemerPtr -> RedeemerPtr -> Bool)
-> (RedeemerPtr -> RedeemerPtr -> Bool)
-> (RedeemerPtr -> RedeemerPtr -> Bool)
-> (RedeemerPtr -> RedeemerPtr -> Bool)
-> (RedeemerPtr -> RedeemerPtr -> RedeemerPtr)
-> (RedeemerPtr -> RedeemerPtr -> RedeemerPtr)
-> Ord RedeemerPtr
RedeemerPtr -> RedeemerPtr -> Bool
RedeemerPtr -> RedeemerPtr -> Ordering
RedeemerPtr -> RedeemerPtr -> RedeemerPtr
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: RedeemerPtr -> RedeemerPtr -> RedeemerPtr
$cmin :: RedeemerPtr -> RedeemerPtr -> RedeemerPtr
max :: RedeemerPtr -> RedeemerPtr -> RedeemerPtr
$cmax :: RedeemerPtr -> RedeemerPtr -> RedeemerPtr
>= :: RedeemerPtr -> RedeemerPtr -> Bool
$c>= :: RedeemerPtr -> RedeemerPtr -> Bool
> :: RedeemerPtr -> RedeemerPtr -> Bool
$c> :: RedeemerPtr -> RedeemerPtr -> Bool
<= :: RedeemerPtr -> RedeemerPtr -> Bool
$c<= :: RedeemerPtr -> RedeemerPtr -> Bool
< :: RedeemerPtr -> RedeemerPtr -> Bool
$c< :: RedeemerPtr -> RedeemerPtr -> Bool
compare :: RedeemerPtr -> RedeemerPtr -> Ordering
$ccompare :: RedeemerPtr -> RedeemerPtr -> Ordering
$cp1Ord :: Eq RedeemerPtr
Ord, (forall x. RedeemerPtr -> Rep RedeemerPtr x)
-> (forall x. Rep RedeemerPtr x -> RedeemerPtr)
-> Generic RedeemerPtr
forall x. Rep RedeemerPtr x -> RedeemerPtr
forall x. RedeemerPtr -> Rep RedeemerPtr x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep RedeemerPtr x -> RedeemerPtr
$cfrom :: forall x. RedeemerPtr -> Rep RedeemerPtr x
Generic)
    deriving anyclass (RedeemerPtr -> ()
(RedeemerPtr -> ()) -> NFData RedeemerPtr
forall a. (a -> ()) -> NFData a
rnf :: RedeemerPtr -> ()
$crnf :: RedeemerPtr -> ()
NFData)

type Redeemers = Map RedeemerPtr Redeemer

-- | A reference to a transaction output. This is a
-- pair of a transaction reference, and an index indicating which of the outputs
-- of that transaction we are referring to.
data TxOutRef = TxOutRef {
    TxOutRef -> TxId
txOutRefId  :: TxId,
    TxOutRef -> Integer
txOutRefIdx :: Integer -- ^ Index into the referenced transaction's outputs
    }
    deriving stock (Int -> TxOutRef -> ShowS
[TxOutRef] -> ShowS
TxOutRef -> String
(Int -> TxOutRef -> ShowS)
-> (TxOutRef -> String) -> ([TxOutRef] -> ShowS) -> Show TxOutRef
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TxOutRef] -> ShowS
$cshowList :: [TxOutRef] -> ShowS
show :: TxOutRef -> String
$cshow :: TxOutRef -> String
showsPrec :: Int -> TxOutRef -> ShowS
$cshowsPrec :: Int -> TxOutRef -> ShowS
Show, TxOutRef -> TxOutRef -> Bool
(TxOutRef -> TxOutRef -> Bool)
-> (TxOutRef -> TxOutRef -> Bool) -> Eq TxOutRef
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TxOutRef -> TxOutRef -> Bool
$c/= :: TxOutRef -> TxOutRef -> Bool
== :: TxOutRef -> TxOutRef -> Bool
$c== :: TxOutRef -> TxOutRef -> Bool
Eq, Eq TxOutRef
Eq TxOutRef
-> (TxOutRef -> TxOutRef -> Ordering)
-> (TxOutRef -> TxOutRef -> Bool)
-> (TxOutRef -> TxOutRef -> Bool)
-> (TxOutRef -> TxOutRef -> Bool)
-> (TxOutRef -> TxOutRef -> Bool)
-> (TxOutRef -> TxOutRef -> TxOutRef)
-> (TxOutRef -> TxOutRef -> TxOutRef)
-> Ord TxOutRef
TxOutRef -> TxOutRef -> Bool
TxOutRef -> TxOutRef -> Ordering
TxOutRef -> TxOutRef -> TxOutRef
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: TxOutRef -> TxOutRef -> TxOutRef
$cmin :: TxOutRef -> TxOutRef -> TxOutRef
max :: TxOutRef -> TxOutRef -> TxOutRef
$cmax :: TxOutRef -> TxOutRef -> TxOutRef
>= :: TxOutRef -> TxOutRef -> Bool
$c>= :: TxOutRef -> TxOutRef -> Bool
> :: TxOutRef -> TxOutRef -> Bool
$c> :: TxOutRef -> TxOutRef -> Bool
<= :: TxOutRef -> TxOutRef -> Bool
$c<= :: TxOutRef -> TxOutRef -> Bool
< :: TxOutRef -> TxOutRef -> Bool
$c< :: TxOutRef -> TxOutRef -> Bool
compare :: TxOutRef -> TxOutRef -> Ordering
$ccompare :: TxOutRef -> TxOutRef -> Ordering
$cp1Ord :: Eq TxOutRef
Ord, (forall x. TxOutRef -> Rep TxOutRef x)
-> (forall x. Rep TxOutRef x -> TxOutRef) -> Generic TxOutRef
forall x. Rep TxOutRef x -> TxOutRef
forall x. TxOutRef -> Rep TxOutRef x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TxOutRef x -> TxOutRef
$cfrom :: forall x. TxOutRef -> Rep TxOutRef x
Generic)
    deriving anyclass (TxOutRef -> ()
(TxOutRef -> ()) -> NFData TxOutRef
forall a. (a -> ()) -> NFData a
rnf :: TxOutRef -> ()
$crnf :: TxOutRef -> ()
NFData)

instance Pretty TxOutRef where
    pretty :: TxOutRef -> Doc ann
pretty TxOutRef{TxId
txOutRefId :: TxId
txOutRefId :: TxOutRef -> TxId
txOutRefId, Integer
txOutRefIdx :: Integer
txOutRefIdx :: TxOutRef -> Integer
txOutRefIdx} = TxId -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty TxId
txOutRefId Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
"!" Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Integer -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Integer
txOutRefIdx

instance PlutusTx.Eq TxOutRef where
    {-# INLINABLE (==) #-}
    TxOutRef
l == :: TxOutRef -> TxOutRef -> Bool
== TxOutRef
r =
        TxOutRef -> TxId
txOutRefId TxOutRef
l TxId -> TxId -> Bool
forall a. Eq a => a -> a -> Bool
PlutusTx.== TxOutRef -> TxId
txOutRefId TxOutRef
r
        Bool -> Bool -> Bool
PlutusTx.&& TxOutRef -> Integer
txOutRefIdx TxOutRef
l Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
PlutusTx.== TxOutRef -> Integer
txOutRefIdx TxOutRef
r

-- | The type of a transaction input.
data TxInType =
      -- TODO: these should all be hashes, with the validators and data segregated to the side
      ConsumeScriptAddress !Validator !Redeemer !Datum -- ^ A transaction input that consumes a script address with the given validator, redeemer, and datum.
    | ConsumePublicKeyAddress -- ^ A transaction input that consumes a public key address.
    | ConsumeSimpleScriptAddress -- ^ Consume a simple script
    deriving stock (Int -> TxInType -> ShowS
[TxInType] -> ShowS
TxInType -> String
(Int -> TxInType -> ShowS)
-> (TxInType -> String) -> ([TxInType] -> ShowS) -> Show TxInType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TxInType] -> ShowS
$cshowList :: [TxInType] -> ShowS
show :: TxInType -> String
$cshow :: TxInType -> String
showsPrec :: Int -> TxInType -> ShowS
$cshowsPrec :: Int -> TxInType -> ShowS
Show, TxInType -> TxInType -> Bool
(TxInType -> TxInType -> Bool)
-> (TxInType -> TxInType -> Bool) -> Eq TxInType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TxInType -> TxInType -> Bool
$c/= :: TxInType -> TxInType -> Bool
== :: TxInType -> TxInType -> Bool
$c== :: TxInType -> TxInType -> Bool
Eq, Eq TxInType
Eq TxInType
-> (TxInType -> TxInType -> Ordering)
-> (TxInType -> TxInType -> Bool)
-> (TxInType -> TxInType -> Bool)
-> (TxInType -> TxInType -> Bool)
-> (TxInType -> TxInType -> Bool)
-> (TxInType -> TxInType -> TxInType)
-> (TxInType -> TxInType -> TxInType)
-> Ord TxInType
TxInType -> TxInType -> Bool
TxInType -> TxInType -> Ordering
TxInType -> TxInType -> TxInType
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: TxInType -> TxInType -> TxInType
$cmin :: TxInType -> TxInType -> TxInType
max :: TxInType -> TxInType -> TxInType
$cmax :: TxInType -> TxInType -> TxInType
>= :: TxInType -> TxInType -> Bool
$c>= :: TxInType -> TxInType -> Bool
> :: TxInType -> TxInType -> Bool
$c> :: TxInType -> TxInType -> Bool
<= :: TxInType -> TxInType -> Bool
$c<= :: TxInType -> TxInType -> Bool
< :: TxInType -> TxInType -> Bool
$c< :: TxInType -> TxInType -> Bool
compare :: TxInType -> TxInType -> Ordering
$ccompare :: TxInType -> TxInType -> Ordering
$cp1Ord :: Eq TxInType
Ord, (forall x. TxInType -> Rep TxInType x)
-> (forall x. Rep TxInType x -> TxInType) -> Generic TxInType
forall x. Rep TxInType x -> TxInType
forall x. TxInType -> Rep TxInType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TxInType x -> TxInType
$cfrom :: forall x. TxInType -> Rep TxInType x
Generic)
    deriving anyclass (TxInType -> ()
(TxInType -> ()) -> NFData TxInType
forall a. (a -> ()) -> NFData a
rnf :: TxInType -> ()
$crnf :: TxInType -> ()
NFData)

-- | A transaction input, consisting of a transaction output reference and an input type.
data TxIn = TxIn {
    TxIn -> TxOutRef
txInRef  :: !TxOutRef,
    TxIn -> Maybe TxInType
txInType :: Maybe TxInType
    }
    deriving stock (Int -> TxIn -> ShowS
[TxIn] -> ShowS
TxIn -> String
(Int -> TxIn -> ShowS)
-> (TxIn -> String) -> ([TxIn] -> ShowS) -> Show TxIn
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TxIn] -> ShowS
$cshowList :: [TxIn] -> ShowS
show :: TxIn -> String
$cshow :: TxIn -> String
showsPrec :: Int -> TxIn -> ShowS
$cshowsPrec :: Int -> TxIn -> ShowS
Show, TxIn -> TxIn -> Bool
(TxIn -> TxIn -> Bool) -> (TxIn -> TxIn -> Bool) -> Eq TxIn
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TxIn -> TxIn -> Bool
$c/= :: TxIn -> TxIn -> Bool
== :: TxIn -> TxIn -> Bool
$c== :: TxIn -> TxIn -> Bool
Eq, Eq TxIn
Eq TxIn
-> (TxIn -> TxIn -> Ordering)
-> (TxIn -> TxIn -> Bool)
-> (TxIn -> TxIn -> Bool)
-> (TxIn -> TxIn -> Bool)
-> (TxIn -> TxIn -> Bool)
-> (TxIn -> TxIn -> TxIn)
-> (TxIn -> TxIn -> TxIn)
-> Ord TxIn
TxIn -> TxIn -> Bool
TxIn -> TxIn -> Ordering
TxIn -> TxIn -> TxIn
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: TxIn -> TxIn -> TxIn
$cmin :: TxIn -> TxIn -> TxIn
max :: TxIn -> TxIn -> TxIn
$cmax :: TxIn -> TxIn -> TxIn
>= :: TxIn -> TxIn -> Bool
$c>= :: TxIn -> TxIn -> Bool
> :: TxIn -> TxIn -> Bool
$c> :: TxIn -> TxIn -> Bool
<= :: TxIn -> TxIn -> Bool
$c<= :: TxIn -> TxIn -> Bool
< :: TxIn -> TxIn -> Bool
$c< :: TxIn -> TxIn -> Bool
compare :: TxIn -> TxIn -> Ordering
$ccompare :: TxIn -> TxIn -> Ordering
$cp1Ord :: Eq TxIn
Ord, (forall x. TxIn -> Rep TxIn x)
-> (forall x. Rep TxIn x -> TxIn) -> Generic TxIn
forall x. Rep TxIn x -> TxIn
forall x. TxIn -> Rep TxIn x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TxIn x -> TxIn
$cfrom :: forall x. TxIn -> Rep TxIn x
Generic)
    deriving anyclass (TxIn -> ()
(TxIn -> ()) -> NFData TxIn
forall a. (a -> ()) -> NFData a
rnf :: TxIn -> ()
$crnf :: TxIn -> ()
NFData)

instance Pretty TxIn where
    pretty :: TxIn -> Doc ann
pretty TxIn{TxOutRef
txInRef :: TxOutRef
txInRef :: TxIn -> TxOutRef
txInRef,Maybe TxInType
txInType :: Maybe TxInType
txInType :: TxIn -> Maybe TxInType
txInType} =
                let rest :: Doc ann
rest =
                        case Maybe TxInType
txInType of
                            Just (ConsumeScriptAddress Validator
_ Redeemer
redeemer Datum
_) ->
                                Redeemer -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Redeemer
redeemer
                            Maybe TxInType
_ -> Doc ann
forall a. Monoid a => a
mempty
                in Int -> Doc ann -> Doc ann
forall ann. Int -> Doc ann -> Doc ann
hang Int
2 (Doc ann -> Doc ann) -> Doc ann -> Doc ann
forall a b. (a -> b) -> a -> b
$ [Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
vsep [Doc ann
"-" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> TxOutRef -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty TxOutRef
txInRef, Doc ann
forall ann. Doc ann
rest]

-- | The 'TxOutRef' spent by a transaction input.
inRef :: Lens' TxIn TxOutRef
inRef :: (TxOutRef -> f TxOutRef) -> TxIn -> f TxIn
inRef = (TxIn -> TxOutRef)
-> (TxIn -> TxOutRef -> TxIn) -> Lens TxIn TxIn TxOutRef TxOutRef
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens TxIn -> TxOutRef
txInRef TxIn -> TxOutRef -> TxIn
s where
    s :: TxIn -> TxOutRef -> TxIn
s TxIn
txi TxOutRef
r = TxIn
txi { txInRef :: TxOutRef
txInRef = TxOutRef
r }

-- | The type of a transaction input.
inType :: Lens' TxIn (Maybe TxInType)
inType :: (Maybe TxInType -> f (Maybe TxInType)) -> TxIn -> f TxIn
inType = (TxIn -> Maybe TxInType)
-> (TxIn -> Maybe TxInType -> TxIn)
-> Lens TxIn TxIn (Maybe TxInType) (Maybe TxInType)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens TxIn -> Maybe TxInType
txInType TxIn -> Maybe TxInType -> TxIn
s where
    s :: TxIn -> Maybe TxInType -> TxIn
s TxIn
txi Maybe TxInType
t = TxIn
txi { txInType :: Maybe TxInType
txInType = Maybe TxInType
t }

-- | Validator, redeemer, and data scripts of a transaction input that spends a
--   "pay to script" output.
inScripts :: TxIn -> Maybe (Validator, Redeemer, Datum)
inScripts :: TxIn -> Maybe (Validator, Redeemer, Datum)
inScripts TxIn{ txInType :: TxIn -> Maybe TxInType
txInType = Maybe TxInType
t } = case Maybe TxInType
t of
    Just (ConsumeScriptAddress Validator
v Redeemer
r Datum
d) -> (Validator, Redeemer, Datum) -> Maybe (Validator, Redeemer, Datum)
forall a. a -> Maybe a
Just (Validator
v, Redeemer
r, Datum
d)
    Maybe TxInType
_                                 -> Maybe (Validator, Redeemer, Datum)
forall a. Maybe a
Nothing

-- | A transaction input that spends a "pay to public key" output, given the witness.
pubKeyTxIn :: TxOutRef -> TxIn
pubKeyTxIn :: TxOutRef -> TxIn
pubKeyTxIn TxOutRef
r = TxOutRef -> Maybe TxInType -> TxIn
TxIn TxOutRef
r (TxInType -> Maybe TxInType
forall a. a -> Maybe a
Just TxInType
ConsumePublicKeyAddress)

-- | A transaction input that spends a "pay to script" output, given witnesses.
scriptTxIn :: TxOutRef -> Validator -> Redeemer -> Datum -> TxIn
scriptTxIn :: TxOutRef -> Validator -> Redeemer -> Datum -> TxIn
scriptTxIn TxOutRef
ref Validator
v Redeemer
r Datum
d = TxOutRef -> Maybe TxInType -> TxIn
TxIn TxOutRef
ref (Maybe TxInType -> TxIn)
-> (TxInType -> Maybe TxInType) -> TxInType -> TxIn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxInType -> Maybe TxInType
forall a. a -> Maybe a
Just (TxInType -> TxIn) -> TxInType -> TxIn
forall a b. (a -> b) -> a -> b
$ Validator -> Redeemer -> Datum -> TxInType
ConsumeScriptAddress Validator
v Redeemer
r Datum
d

-- | Filter to get only the pubkey inputs.
pubKeyTxIns :: Fold (Set.Set TxIn) TxIn
pubKeyTxIns :: (TxIn -> f TxIn) -> Set TxIn -> f (Set TxIn)
pubKeyTxIns = (Set TxIn -> Set TxIn) -> Fold (Set TxIn) TxIn
forall (f :: * -> *) s a. Foldable f => (s -> f a) -> Fold s a
folding ((TxIn -> Bool) -> Set TxIn -> Set TxIn
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\TxIn{ txInType :: TxIn -> Maybe TxInType
txInType = Maybe TxInType
t } -> Maybe TxInType
t Maybe TxInType -> Maybe TxInType -> Bool
forall a. Eq a => a -> a -> Bool
== TxInType -> Maybe TxInType
forall a. a -> Maybe a
Just TxInType
ConsumePublicKeyAddress))

-- | Filter to get only the script inputs.
scriptTxIns :: Fold (Set.Set TxIn) TxIn
scriptTxIns :: (TxIn -> f TxIn) -> Set TxIn -> f (Set TxIn)
scriptTxIns = (\Set TxIn -> Set TxIn
x -> (Set TxIn -> Set TxIn) -> Fold (Set TxIn) TxIn
forall (f :: * -> *) s a. Foldable f => (s -> f a) -> Fold s a
folding Set TxIn -> Set TxIn
x) ((Set TxIn -> Set TxIn)
 -> (TxIn -> f TxIn) -> Set TxIn -> f (Set TxIn))
-> ((TxIn -> Bool) -> Set TxIn -> Set TxIn)
-> (TxIn -> Bool)
-> (TxIn -> f TxIn)
-> Set TxIn
-> f (Set TxIn)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TxIn -> Bool) -> Set TxIn -> Set TxIn
forall a. (a -> Bool) -> Set a -> Set a
Set.filter ((TxIn -> Bool) -> (TxIn -> f TxIn) -> Set TxIn -> f (Set TxIn))
-> (TxIn -> Bool) -> (TxIn -> f TxIn) -> Set TxIn -> f (Set TxIn)
forall a b. (a -> b) -> a -> b
$ \case
    TxIn{ txInType :: TxIn -> Maybe TxInType
txInType = Just ConsumeScriptAddress{} } -> Bool
True
    TxIn
_                                              -> Bool
False

-- | A transaction output, consisting of a target address, a value, and optionally a datum hash.
data TxOut = TxOut {
    TxOut -> Address
txOutAddress   :: Address,
    TxOut -> Value
txOutValue     :: Value,
    TxOut -> Maybe DatumHash
txOutDatumHash :: Maybe DatumHash
    }
    deriving stock (Int -> TxOut -> ShowS
[TxOut] -> ShowS
TxOut -> String
(Int -> TxOut -> ShowS)
-> (TxOut -> String) -> ([TxOut] -> ShowS) -> Show TxOut
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TxOut] -> ShowS
$cshowList :: [TxOut] -> ShowS
show :: TxOut -> String
$cshow :: TxOut -> String
showsPrec :: Int -> TxOut -> ShowS
$cshowsPrec :: Int -> TxOut -> ShowS
Show, TxOut -> TxOut -> Bool
(TxOut -> TxOut -> Bool) -> (TxOut -> TxOut -> Bool) -> Eq TxOut
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TxOut -> TxOut -> Bool
$c/= :: TxOut -> TxOut -> Bool
== :: TxOut -> TxOut -> Bool
$c== :: TxOut -> TxOut -> Bool
Eq, (forall x. TxOut -> Rep TxOut x)
-> (forall x. Rep TxOut x -> TxOut) -> Generic TxOut
forall x. Rep TxOut x -> TxOut
forall x. TxOut -> Rep TxOut x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TxOut x -> TxOut
$cfrom :: forall x. TxOut -> Rep TxOut x
Generic)
    deriving anyclass (TxOut -> ()
(TxOut -> ()) -> NFData TxOut
forall a. (a -> ()) -> NFData a
rnf :: TxOut -> ()
$crnf :: TxOut -> ()
NFData)

instance Pretty TxOut where
    pretty :: TxOut -> Doc ann
pretty TxOut{Address
txOutAddress :: Address
txOutAddress :: TxOut -> Address
txOutAddress, Value
txOutValue :: Value
txOutValue :: TxOut -> Value
txOutValue} =
                Int -> Doc ann -> Doc ann
forall ann. Int -> Doc ann -> Doc ann
hang Int
2 (Doc ann -> Doc ann) -> Doc ann -> Doc ann
forall a b. (a -> b) -> a -> b
$ [Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
vsep [Doc ann
"-" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Value -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Value
txOutValue Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"addressed to", Address -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Address
txOutAddress]

instance PlutusTx.Eq TxOut where
    {-# INLINABLE (==) #-}
    TxOut
l == :: TxOut -> TxOut -> Bool
== TxOut
r =
        TxOut -> Address
txOutAddress TxOut
l Address -> Address -> Bool
forall a. Eq a => a -> a -> Bool
PlutusTx.== TxOut -> Address
txOutAddress TxOut
r
        Bool -> Bool -> Bool
PlutusTx.&& TxOut -> Value
txOutValue TxOut
l Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
PlutusTx.== TxOut -> Value
txOutValue TxOut
r
        Bool -> Bool -> Bool
PlutusTx.&& TxOut -> Maybe DatumHash
txOutDatumHash TxOut
l Maybe DatumHash -> Maybe DatumHash -> Bool
forall a. Eq a => a -> a -> Bool
PlutusTx.== TxOut -> Maybe DatumHash
txOutDatumHash TxOut
r

-- | The datum attached to a 'TxOut', if there is one.
txOutDatum :: TxOut -> Maybe DatumHash
txOutDatum :: TxOut -> Maybe DatumHash
txOutDatum TxOut{Maybe DatumHash
txOutDatumHash :: Maybe DatumHash
txOutDatumHash :: TxOut -> Maybe DatumHash
txOutDatumHash} = Maybe DatumHash
txOutDatumHash

-- | The public key attached to a 'TxOut', if there is one.
txOutPubKey :: TxOut -> Maybe PubKeyHash
txOutPubKey :: TxOut -> Maybe PubKeyHash
txOutPubKey TxOut{Address
txOutAddress :: Address
txOutAddress :: TxOut -> Address
txOutAddress} = Address -> Maybe PubKeyHash
toPubKeyHash Address
txOutAddress

-- | The validator hash attached to a 'TxOut', if there is one.
txOutValidatorHash :: TxOut -> Maybe ValidatorHash
txOutValidatorHash :: TxOut -> Maybe ValidatorHash
txOutValidatorHash TxOut{Address
txOutAddress :: Address
txOutAddress :: TxOut -> Address
txOutAddress} = Address -> Maybe ValidatorHash
toValidatorHash Address
txOutAddress

-- | The address of a transaction output.
outAddress :: Lens' TxOut Address
outAddress :: (Address -> f Address) -> TxOut -> f TxOut
outAddress = (TxOut -> Address)
-> (TxOut -> Address -> TxOut) -> Lens TxOut TxOut Address Address
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens TxOut -> Address
txOutAddress TxOut -> Address -> TxOut
s where
    s :: TxOut -> Address -> TxOut
s TxOut
tx Address
a = TxOut
tx { txOutAddress :: Address
txOutAddress = Address
a }

-- | The value of a transaction output.
-- | TODO: Compute address again
outValue :: Lens' TxOut Value
outValue :: (Value -> f Value) -> TxOut -> f TxOut
outValue = (TxOut -> Value)
-> (TxOut -> Value -> TxOut) -> Lens TxOut TxOut Value Value
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens TxOut -> Value
txOutValue TxOut -> Value -> TxOut
s where
    s :: TxOut -> Value -> TxOut
s TxOut
tx Value
v = TxOut
tx { txOutValue :: Value
txOutValue = Value
v }

-- | Whether the output is a pay-to-pubkey output.
isPubKeyOut :: TxOut -> Bool
isPubKeyOut :: TxOut -> Bool
isPubKeyOut = Maybe PubKeyHash -> Bool
forall a. Maybe a -> Bool
isJust (Maybe PubKeyHash -> Bool)
-> (TxOut -> Maybe PubKeyHash) -> TxOut -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxOut -> Maybe PubKeyHash
txOutPubKey

-- | Whether the output is a pay-to-script output.
isPayToScriptOut :: TxOut -> Bool
isPayToScriptOut :: TxOut -> Bool
isPayToScriptOut = Maybe ValidatorHash -> Bool
forall a. Maybe a -> Bool
isJust (Maybe ValidatorHash -> Bool)
-> (TxOut -> Maybe ValidatorHash) -> TxOut -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxOut -> Maybe ValidatorHash
txOutValidatorHash

-- | Create a transaction output locked by a public key.
pubKeyHashTxOut :: Value -> PubKeyHash -> TxOut
pubKeyHashTxOut :: Value -> PubKeyHash -> TxOut
pubKeyHashTxOut Value
v PubKeyHash
pkh = Address -> Value -> Maybe DatumHash -> TxOut
TxOut (PubKeyHash -> Address
pubKeyHashAddress PubKeyHash
pkh) Value
v Maybe DatumHash
forall a. Maybe a
Nothing

PlutusTx.makeLift ''TxId
PlutusTx.makeIsDataIndexed ''TxId [('TxId,0)]

PlutusTx.makeIsDataIndexed ''TxOut [('TxOut,0)]
PlutusTx.makeLift ''TxOut

PlutusTx.makeIsDataIndexed ''TxOutRef [('TxOutRef,0)]
PlutusTx.makeLift ''TxOutRef