{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -Wno-orphans #-}

module Cardano.Ledger.Alonzo.TxOut (
  AlonzoEraTxOut (..),
  AlonzoTxOut (.., AlonzoTxOut, TxOutCompact, TxOutCompactDH),
  -- Constructors are not exported for safety:
  Addr28Extra,
  DataHash32,
  getAdaOnly,
  decodeDataHash32,
  encodeDataHash32,
  encodeAddress28,
  decodeAddress28,
  viewCompactTxOut,
  viewTxOut,
  getAlonzoTxOutEitherAddr,
  utxoEntrySize,
  internAlonzoTxOut,
)
where

import Cardano.Crypto.Hash
import Cardano.Ledger.Address (
  Addr (..),
  CompactAddr,
  compactAddr,
  decompactAddr,
  fromCborBothAddr,
 )
import Cardano.Ledger.Alonzo.Era
import Cardano.Ledger.Alonzo.PParams (AlonzoEraPParams, CoinPerWord (..), ppCoinsPerUTxOWordL)
import Cardano.Ledger.Alonzo.Scripts ()
import Cardano.Ledger.BaseTypes (
  Network (..),
  StrictMaybe (..),
  inject,
  strictMaybeToMaybe,
 )
import Cardano.Ledger.Binary (
  DecCBOR (decCBOR),
  DecShareCBOR (Share, decShareCBOR),
  DecoderError (DecoderErrorCustom),
  EncCBOR (encCBOR),
  FromCBOR (..),
  Interns,
  ToCBOR (..),
  cborError,
  decodeBreakOr,
  decodeListLenOrIndef,
  encodeListLen,
  interns,
 )
import Cardano.Ledger.Coin (Coin (..))
import Cardano.Ledger.Compactible
import Cardano.Ledger.Credential (Credential (..), PaymentCredential, StakeReference (..))
import Cardano.Ledger.Crypto
import Cardano.Ledger.Keys (KeyHash (..), KeyRole (..))
import Cardano.Ledger.Plutus.Data (Datum (..), dataHashSize)
import Cardano.Ledger.SafeHash (extractHash, unsafeMakeSafeHash)
import Cardano.Ledger.Shelley.Core
import qualified Cardano.Ledger.Shelley.TxOut as Shelley
import Cardano.Ledger.Val (Val (..))
import Control.DeepSeq (NFData (..), rwhnf)
import Control.Monad (guard, (<$!>))
import Data.Aeson (ToJSON (..), object, (.=))
import qualified Data.Aeson as Aeson (Value (Null, String))
import Data.Bits
import Data.Maybe (fromMaybe)
import Data.Typeable (Proxy (..), (:~:) (Refl))
import Data.Word
import GHC.Generics (Generic)
import GHC.Stack (HasCallStack)
import GHC.TypeLits
import Lens.Micro
import NoThunks.Class (InspectHeapNamed (..), NoThunks)

class (AlonzoEraPParams era, EraTxOut era) => AlonzoEraTxOut era where
  dataHashTxOutL :: Lens' (TxOut era) (StrictMaybe (DataHash (EraCrypto era)))

  datumTxOutF :: SimpleGetter (TxOut era) (Datum era)

data Addr28Extra
  = Addr28Extra
      {-# UNPACK #-} !Word64 -- Payment Addr
      {-# UNPACK #-} !Word64 -- Payment Addr
      {-# UNPACK #-} !Word64 -- Payment Addr
      {-# UNPACK #-} !Word64 -- Payment Addr (32bits) + ... +  0/1 for Testnet/Mainnet + 0/1 Script/Pubkey
  deriving (Addr28Extra -> Addr28Extra -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Addr28Extra -> Addr28Extra -> Bool
$c/= :: Addr28Extra -> Addr28Extra -> Bool
== :: Addr28Extra -> Addr28Extra -> Bool
$c== :: Addr28Extra -> Addr28Extra -> Bool
Eq, Int -> Addr28Extra -> ShowS
[Addr28Extra] -> ShowS
Addr28Extra -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [Addr28Extra] -> ShowS
$cshowList :: [Addr28Extra] -> ShowS
show :: Addr28Extra -> [Char]
$cshow :: Addr28Extra -> [Char]
showsPrec :: Int -> Addr28Extra -> ShowS
$cshowsPrec :: Int -> Addr28Extra -> ShowS
Show, forall x. Rep Addr28Extra x -> Addr28Extra
forall x. Addr28Extra -> Rep Addr28Extra x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Addr28Extra x -> Addr28Extra
$cfrom :: forall x. Addr28Extra -> Rep Addr28Extra x
Generic, Context -> Addr28Extra -> IO (Maybe ThunkInfo)
Proxy Addr28Extra -> [Char]
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> [Char])
-> NoThunks a
showTypeOf :: Proxy Addr28Extra -> [Char]
$cshowTypeOf :: Proxy Addr28Extra -> [Char]
wNoThunks :: Context -> Addr28Extra -> IO (Maybe ThunkInfo)
$cwNoThunks :: Context -> Addr28Extra -> IO (Maybe ThunkInfo)
noThunks :: Context -> Addr28Extra -> IO (Maybe ThunkInfo)
$cnoThunks :: Context -> Addr28Extra -> IO (Maybe ThunkInfo)
NoThunks)

data DataHash32
  = DataHash32
      {-# UNPACK #-} !Word64 -- DataHash
      {-# UNPACK #-} !Word64 -- DataHash
      {-# UNPACK #-} !Word64 -- DataHash
      {-# UNPACK #-} !Word64 -- DataHash
  deriving (DataHash32 -> DataHash32 -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DataHash32 -> DataHash32 -> Bool
$c/= :: DataHash32 -> DataHash32 -> Bool
== :: DataHash32 -> DataHash32 -> Bool
$c== :: DataHash32 -> DataHash32 -> Bool
Eq, Int -> DataHash32 -> ShowS
[DataHash32] -> ShowS
DataHash32 -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [DataHash32] -> ShowS
$cshowList :: [DataHash32] -> ShowS
show :: DataHash32 -> [Char]
$cshow :: DataHash32 -> [Char]
showsPrec :: Int -> DataHash32 -> ShowS
$cshowsPrec :: Int -> DataHash32 -> ShowS
Show, forall x. Rep DataHash32 x -> DataHash32
forall x. DataHash32 -> Rep DataHash32 x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep DataHash32 x -> DataHash32
$cfrom :: forall x. DataHash32 -> Rep DataHash32 x
Generic, Context -> DataHash32 -> IO (Maybe ThunkInfo)
Proxy DataHash32 -> [Char]
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> [Char])
-> NoThunks a
showTypeOf :: Proxy DataHash32 -> [Char]
$cshowTypeOf :: Proxy DataHash32 -> [Char]
wNoThunks :: Context -> DataHash32 -> IO (Maybe ThunkInfo)
$cwNoThunks :: Context -> DataHash32 -> IO (Maybe ThunkInfo)
noThunks :: Context -> DataHash32 -> IO (Maybe ThunkInfo)
$cnoThunks :: Context -> DataHash32 -> IO (Maybe ThunkInfo)
NoThunks)

decodeAddress28 ::
  forall c.
  HashAlgorithm (ADDRHASH c) =>
  Credential 'Staking c ->
  Addr28Extra ->
  Maybe (Addr c)
decodeAddress28 :: forall c.
HashAlgorithm (ADDRHASH c) =>
Credential 'Staking c -> Addr28Extra -> Maybe (Addr c)
decodeAddress28 Credential 'Staking c
stakeRef (Addr28Extra Word64
a Word64
b Word64
c Word64
d) = do
  SizeHash (ADDRHASH c) :~: 28
Refl <- forall (a :: Nat) (b :: Nat) (proxy1 :: Nat -> *)
       (proxy2 :: Nat -> *).
(KnownNat a, KnownNat b) =>
proxy1 a -> proxy2 b -> Maybe (a :~: b)
sameNat (forall {k} (t :: k). Proxy t
Proxy @(SizeHash (ADDRHASH c))) (forall {k} (t :: k). Proxy t
Proxy @28)
  let network :: Network
network = if Word64
d forall a. Bits a => a -> Int -> Bool
`testBit` Int
1 then Network
Mainnet else Network
Testnet
      paymentCred :: Credential 'Payment c
paymentCred =
        if Word64
d forall a. Bits a => a -> Int -> Bool
`testBit` Int
0
          then forall (kr :: KeyRole) c. KeyHash kr c -> Credential kr c
KeyHashObj (forall (r :: KeyRole) c.
Hash (ADDRHASH c) (VerKeyDSIGN (DSIGN c)) -> KeyHash r c
KeyHash forall a. Hash (ADDRHASH c) a
addrHash)
          else forall (kr :: KeyRole) c. ScriptHash c -> Credential kr c
ScriptHashObj (forall c. Hash (ADDRHASH c) EraIndependentScript -> ScriptHash c
ScriptHash forall a. Hash (ADDRHASH c) a
addrHash)
      addrHash :: Hash (ADDRHASH c) a
      addrHash :: forall a. Hash (ADDRHASH c) a
addrHash =
        forall h a. PackedBytes (SizeHash h) -> Hash h a
hashFromPackedBytes forall a b. (a -> b) -> a -> b
$
          Word64 -> Word64 -> Word64 -> Word32 -> PackedBytes 28
PackedBytes28 Word64
a Word64
b Word64
c (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
d forall a. Bits a => a -> Int -> a
`shiftR` Int
32))
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$! forall c.
Network -> PaymentCredential c -> StakeReference c -> Addr c
Addr Network
network Credential 'Payment c
paymentCred (forall c. StakeCredential c -> StakeReference c
StakeRefBase Credential 'Staking c
stakeRef)
{-# INLINE decodeAddress28 #-}

data AlonzoTxOut era
  = TxOutCompact'
      {-# UNPACK #-} !(CompactAddr (EraCrypto era))
      !(CompactForm (Value era))
  | TxOutCompactDH'
      {-# UNPACK #-} !(CompactAddr (EraCrypto era))
      !(CompactForm (Value era))
      !(DataHash (EraCrypto era))
  | TxOut_AddrHash28_AdaOnly
      !(Credential 'Staking (EraCrypto era))
      {-# UNPACK #-} !Addr28Extra
      {-# UNPACK #-} !(CompactForm Coin) -- Ada value
  | TxOut_AddrHash28_AdaOnly_DataHash32
      !(Credential 'Staking (EraCrypto era))
      {-# UNPACK #-} !Addr28Extra
      {-# UNPACK #-} !(CompactForm Coin) -- Ada value
      {-# UNPACK #-} !DataHash32

deriving stock instance (Eq (Value era), Compactible (Value era)) => Eq (AlonzoTxOut era)

deriving instance Generic (AlonzoTxOut era)

-- | Already in NF
instance NFData (AlonzoTxOut era) where
  rnf :: AlonzoTxOut era -> ()
rnf = forall a. a -> ()
rwhnf

addressErrorMsg :: String
addressErrorMsg :: [Char]
addressErrorMsg = [Char]
"Impossible: Compacted an address of non-standard size"
{-# NOINLINE addressErrorMsg #-}

decodeDataHash32 ::
  forall c.
  HashAlgorithm (HASH c) =>
  DataHash32 ->
  Maybe (DataHash c)
decodeDataHash32 :: forall c.
HashAlgorithm (HASH c) =>
DataHash32 -> Maybe (DataHash c)
decodeDataHash32 (DataHash32 Word64
a Word64
b Word64
c Word64
d) = do
  SizeHash (HASH c) :~: 32
Refl <- forall (a :: Nat) (b :: Nat) (proxy1 :: Nat -> *)
       (proxy2 :: Nat -> *).
(KnownNat a, KnownNat b) =>
proxy1 a -> proxy2 b -> Maybe (a :~: b)
sameNat (forall {k} (t :: k). Proxy t
Proxy @(SizeHash (HASH c))) (forall {k} (t :: k). Proxy t
Proxy @32)
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$! forall c index. Hash (HASH c) index -> SafeHash c index
unsafeMakeSafeHash forall a b. (a -> b) -> a -> b
$ forall h a. PackedBytes (SizeHash h) -> Hash h a
hashFromPackedBytes forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Word64 -> Word64 -> PackedBytes 32
PackedBytes32 Word64
a Word64
b Word64
c Word64
d

viewCompactTxOut ::
  (Era era, Val (Value era)) =>
  AlonzoTxOut era ->
  (CompactAddr (EraCrypto era), CompactForm (Value era), StrictMaybe (DataHash (EraCrypto era)))
viewCompactTxOut :: forall era.
(Era era, Val (Value era)) =>
AlonzoTxOut era
-> (CompactAddr (EraCrypto era), CompactForm (Value era),
    StrictMaybe (DataHash (EraCrypto era)))
viewCompactTxOut AlonzoTxOut era
txOut = case AlonzoTxOut era
txOut of
  TxOutCompact' CompactAddr (EraCrypto era)
addr CompactForm (Value era)
val -> (CompactAddr (EraCrypto era)
addr, CompactForm (Value era)
val, forall a. StrictMaybe a
SNothing)
  TxOutCompactDH' CompactAddr (EraCrypto era)
addr CompactForm (Value era)
val DataHash (EraCrypto era)
dh -> (CompactAddr (EraCrypto era)
addr, CompactForm (Value era)
val, forall a. a -> StrictMaybe a
SJust DataHash (EraCrypto era)
dh)
  TxOut_AddrHash28_AdaOnly Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra CompactForm Coin
adaVal
    | Just Addr (EraCrypto era)
addr <- forall c.
HashAlgorithm (ADDRHASH c) =>
Credential 'Staking c -> Addr28Extra -> Maybe (Addr c)
decodeAddress28 Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra ->
        (forall c. Addr c -> CompactAddr c
compactAddr Addr (EraCrypto era)
addr, forall t. Val t => CompactForm Coin -> CompactForm t
injectCompact CompactForm Coin
adaVal, forall a. StrictMaybe a
SNothing)
    | Bool
otherwise -> forall a. HasCallStack => [Char] -> a
error [Char]
addressErrorMsg
  TxOut_AddrHash28_AdaOnly_DataHash32 Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra CompactForm Coin
adaVal DataHash32
dataHash32
    | Just Addr (EraCrypto era)
addr <- forall c.
HashAlgorithm (ADDRHASH c) =>
Credential 'Staking c -> Addr28Extra -> Maybe (Addr c)
decodeAddress28 Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra
    , Just DataHash (EraCrypto era)
dh <- forall c.
HashAlgorithm (HASH c) =>
DataHash32 -> Maybe (DataHash c)
decodeDataHash32 DataHash32
dataHash32 ->
        (forall c. Addr c -> CompactAddr c
compactAddr Addr (EraCrypto era)
addr, forall t. Val t => CompactForm Coin -> CompactForm t
injectCompact CompactForm Coin
adaVal, forall a. a -> StrictMaybe a
SJust DataHash (EraCrypto era)
dh)
    | Bool
otherwise -> forall a. HasCallStack => [Char] -> a
error [Char]
addressErrorMsg

viewTxOut ::
  (Era era, Val (Value era)) =>
  AlonzoTxOut era ->
  (Addr (EraCrypto era), Value era, StrictMaybe (DataHash (EraCrypto era)))
viewTxOut :: forall era.
(Era era, Val (Value era)) =>
AlonzoTxOut era
-> (Addr (EraCrypto era), Value era,
    StrictMaybe (DataHash (EraCrypto era)))
viewTxOut (TxOutCompact' CompactAddr (EraCrypto era)
bs CompactForm (Value era)
c) = (Addr (EraCrypto era)
addr, Value era
val, forall a. StrictMaybe a
SNothing)
  where
    addr :: Addr (EraCrypto era)
addr = forall c. (HasCallStack, Crypto c) => CompactAddr c -> Addr c
decompactAddr CompactAddr (EraCrypto era)
bs
    val :: Value era
val = forall a. Compactible a => CompactForm a -> a
fromCompact CompactForm (Value era)
c
viewTxOut (TxOutCompactDH' CompactAddr (EraCrypto era)
bs CompactForm (Value era)
c DataHash (EraCrypto era)
dh) = (Addr (EraCrypto era)
addr, Value era
val, forall a. a -> StrictMaybe a
SJust DataHash (EraCrypto era)
dh)
  where
    addr :: Addr (EraCrypto era)
addr = forall c. (HasCallStack, Crypto c) => CompactAddr c -> Addr c
decompactAddr CompactAddr (EraCrypto era)
bs
    val :: Value era
val = forall a. Compactible a => CompactForm a -> a
fromCompact CompactForm (Value era)
c
viewTxOut (TxOut_AddrHash28_AdaOnly Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra CompactForm Coin
adaVal)
  | Just Addr (EraCrypto era)
addr <- forall c.
HashAlgorithm (ADDRHASH c) =>
Credential 'Staking c -> Addr28Extra -> Maybe (Addr c)
decodeAddress28 Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra =
      (Addr (EraCrypto era)
addr, forall t s. Inject t s => t -> s
inject (forall a. Compactible a => CompactForm a -> a
fromCompact CompactForm Coin
adaVal), forall a. StrictMaybe a
SNothing)
viewTxOut (TxOut_AddrHash28_AdaOnly_DataHash32 Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra CompactForm Coin
adaVal DataHash32
dataHash32)
  | Just Addr (EraCrypto era)
addr <- forall c.
HashAlgorithm (ADDRHASH c) =>
Credential 'Staking c -> Addr28Extra -> Maybe (Addr c)
decodeAddress28 Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra
  , Just DataHash (EraCrypto era)
dh <- forall c.
HashAlgorithm (HASH c) =>
DataHash32 -> Maybe (DataHash c)
decodeDataHash32 DataHash32
dataHash32 =
      (Addr (EraCrypto era)
addr, forall t s. Inject t s => t -> s
inject (forall a. Compactible a => CompactForm a -> a
fromCompact CompactForm Coin
adaVal), forall a. a -> StrictMaybe a
SJust DataHash (EraCrypto era)
dh)
viewTxOut TxOut_AddrHash28_AdaOnly {} = forall a. HasCallStack => [Char] -> a
error [Char]
addressErrorMsg
viewTxOut TxOut_AddrHash28_AdaOnly_DataHash32 {} = forall a. HasCallStack => [Char] -> a
error [Char]
addressErrorMsg

instance (Era era, Val (Value era)) => Show (AlonzoTxOut era) where
  show :: AlonzoTxOut era -> [Char]
show = forall a. Show a => a -> [Char]
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall era.
(Era era, Val (Value era)) =>
AlonzoTxOut era
-> (Addr (EraCrypto era), Value era,
    StrictMaybe (DataHash (EraCrypto era)))
viewTxOut -- FIXME: showing tuple is ugly

deriving via InspectHeapNamed "AlonzoTxOut" (AlonzoTxOut era) instance NoThunks (AlonzoTxOut era)

encodeAddress28 ::
  forall c.
  HashAlgorithm (ADDRHASH c) =>
  Network ->
  PaymentCredential c ->
  Maybe (SizeHash (ADDRHASH c) :~: 28, Addr28Extra)
encodeAddress28 :: forall c.
HashAlgorithm (ADDRHASH c) =>
Network
-> PaymentCredential c
-> Maybe (SizeHash (ADDRHASH c) :~: 28, Addr28Extra)
encodeAddress28 Network
network PaymentCredential c
paymentCred = do
  let networkBit, payCredTypeBit :: Word64
      networkBit :: Word64
networkBit =
        case Network
network of
          Network
Mainnet -> Word64
0 forall a. Bits a => a -> Int -> a
`setBit` Int
1
          Network
Testnet -> Word64
0
      payCredTypeBit :: Word64
payCredTypeBit =
        case PaymentCredential c
paymentCred of
          KeyHashObj {} -> Word64
0 forall a. Bits a => a -> Int -> a
`setBit` Int
0
          ScriptHashObj {} -> Word64
0
      encodeAddr ::
        Hash (ADDRHASH c) a ->
        Maybe (SizeHash (ADDRHASH c) :~: 28, Addr28Extra)
      encodeAddr :: forall a.
Hash (ADDRHASH c) a
-> Maybe (SizeHash (ADDRHASH c) :~: 28, Addr28Extra)
encodeAddr Hash (ADDRHASH c) a
h = do
        refl :: SizeHash (ADDRHASH c) :~: 28
refl@SizeHash (ADDRHASH c) :~: 28
Refl <- forall (a :: Nat) (b :: Nat) (proxy1 :: Nat -> *)
       (proxy2 :: Nat -> *).
(KnownNat a, KnownNat b) =>
proxy1 a -> proxy2 b -> Maybe (a :~: b)
sameNat (forall {k} (t :: k). Proxy t
Proxy @(SizeHash (ADDRHASH c))) (forall {k} (t :: k). Proxy t
Proxy @28)
        case forall h a. Hash h a -> PackedBytes (SizeHash h)
hashToPackedBytes Hash (ADDRHASH c) a
h of
          PackedBytes28 Word64
a Word64
b Word64
c Word32
d ->
            let d' :: Word64
d' = (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
d forall a. Bits a => a -> Int -> a
`shiftL` Int
32) forall a. Bits a => a -> a -> a
.|. Word64
networkBit forall a. Bits a => a -> a -> a
.|. Word64
payCredTypeBit
             in forall a. a -> Maybe a
Just (SizeHash (ADDRHASH c) :~: 28
refl, Word64 -> Word64 -> Word64 -> Word64 -> Addr28Extra
Addr28Extra Word64
a Word64
b Word64
c Word64
d')
          PackedBytes (SizeHash (ADDRHASH c))
_ -> forall a. Maybe a
Nothing
  case PaymentCredential c
paymentCred of
    KeyHashObj (KeyHash Hash (ADDRHASH c) (VerKeyDSIGN (DSIGN c))
addrHash) -> forall a.
Hash (ADDRHASH c) a
-> Maybe (SizeHash (ADDRHASH c) :~: 28, Addr28Extra)
encodeAddr Hash (ADDRHASH c) (VerKeyDSIGN (DSIGN c))
addrHash
    ScriptHashObj (ScriptHash Hash (ADDRHASH c) EraIndependentScript
addrHash) -> forall a.
Hash (ADDRHASH c) a
-> Maybe (SizeHash (ADDRHASH c) :~: 28, Addr28Extra)
encodeAddr Hash (ADDRHASH c) EraIndependentScript
addrHash

encodeDataHash32 ::
  forall c.
  HashAlgorithm (HASH c) =>
  DataHash c ->
  Maybe (SizeHash (HASH c) :~: 32, DataHash32)
encodeDataHash32 :: forall c.
HashAlgorithm (HASH c) =>
DataHash c -> Maybe (SizeHash (HASH c) :~: 32, DataHash32)
encodeDataHash32 DataHash c
dataHash = do
  refl :: SizeHash (HASH c) :~: 32
refl@SizeHash (HASH c) :~: 32
Refl <- forall (a :: Nat) (b :: Nat) (proxy1 :: Nat -> *)
       (proxy2 :: Nat -> *).
(KnownNat a, KnownNat b) =>
proxy1 a -> proxy2 b -> Maybe (a :~: b)
sameNat (forall {k} (t :: k). Proxy t
Proxy @(SizeHash (HASH c))) (forall {k} (t :: k). Proxy t
Proxy @32)
  case forall h a. Hash h a -> PackedBytes (SizeHash h)
hashToPackedBytes (forall c i. SafeHash c i -> Hash (HASH c) i
extractHash DataHash c
dataHash) of
    PackedBytes32 Word64
a Word64
b Word64
c Word64
d -> forall a. a -> Maybe a
Just (SizeHash (HASH c) :~: 32
refl, Word64 -> Word64 -> Word64 -> Word64 -> DataHash32
DataHash32 Word64
a Word64
b Word64
c Word64
d)
    PackedBytes (SizeHash (HASH c))
_ -> forall a. Maybe a
Nothing

getAdaOnly ::
  forall era.
  Val (Value era) =>
  Proxy era ->
  Value era ->
  Maybe (CompactForm Coin)
getAdaOnly :: forall era.
Val (Value era) =>
Proxy era -> Value era -> Maybe (CompactForm Coin)
getAdaOnly Proxy era
_ Value era
v = do
  forall (f :: * -> *). Alternative f => Bool -> f ()
guard forall a b. (a -> b) -> a -> b
$ forall t. Val t => t -> Bool
isAdaOnly Value era
v
  forall a. Compactible a => a -> Maybe (CompactForm a)
toCompact forall a b. (a -> b) -> a -> b
$ forall t. Val t => t -> Coin
coin Value era
v

pattern AlonzoTxOut ::
  forall era.
  (Era era, Val (Value era), HasCallStack) =>
  Addr (EraCrypto era) ->
  Value era ->
  StrictMaybe (DataHash (EraCrypto era)) ->
  AlonzoTxOut era
pattern $bAlonzoTxOut :: forall era.
(Era era, Val (Value era), HasCallStack) =>
Addr (EraCrypto era)
-> Value era
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
$mAlonzoTxOut :: forall {r} {era}.
(Era era, Val (Value era), HasCallStack) =>
AlonzoTxOut era
-> (Addr (EraCrypto era)
    -> Value era -> StrictMaybe (DataHash (EraCrypto era)) -> r)
-> ((# #) -> r)
-> r
AlonzoTxOut addr vl dh <-
  (viewTxOut -> (addr, vl, dh))
  where
    AlonzoTxOut (Addr Network
network PaymentCredential (EraCrypto era)
paymentCred StakeReference (EraCrypto era)
stakeRef) Value era
vl StrictMaybe (DataHash (EraCrypto era))
SNothing
      | StakeRefBase StakeCredential (EraCrypto era)
stakeCred <- StakeReference (EraCrypto era)
stakeRef
      , Just CompactForm Coin
adaCompact <- forall era.
Val (Value era) =>
Proxy era -> Value era -> Maybe (CompactForm Coin)
getAdaOnly (forall {k} (t :: k). Proxy t
Proxy @era) Value era
vl
      , Just (SizeHash (ADDRHASH (EraCrypto era)) :~: 28
Refl, Addr28Extra
addr28Extra) <- forall c.
HashAlgorithm (ADDRHASH c) =>
Network
-> PaymentCredential c
-> Maybe (SizeHash (ADDRHASH c) :~: 28, Addr28Extra)
encodeAddress28 Network
network PaymentCredential (EraCrypto era)
paymentCred =
          forall era.
Credential 'Staking (EraCrypto era)
-> Addr28Extra -> CompactForm Coin -> AlonzoTxOut era
TxOut_AddrHash28_AdaOnly StakeCredential (EraCrypto era)
stakeCred Addr28Extra
addr28Extra CompactForm Coin
adaCompact
    AlonzoTxOut (Addr Network
network PaymentCredential (EraCrypto era)
paymentCred StakeReference (EraCrypto era)
stakeRef) Value era
vl (SJust DataHash (EraCrypto era)
dh)
      | StakeRefBase StakeCredential (EraCrypto era)
stakeCred <- StakeReference (EraCrypto era)
stakeRef
      , Just CompactForm Coin
adaCompact <- forall era.
Val (Value era) =>
Proxy era -> Value era -> Maybe (CompactForm Coin)
getAdaOnly (forall {k} (t :: k). Proxy t
Proxy @era) Value era
vl
      , Just (SizeHash (ADDRHASH (EraCrypto era)) :~: 28
Refl, Addr28Extra
addr28Extra) <- forall c.
HashAlgorithm (ADDRHASH c) =>
Network
-> PaymentCredential c
-> Maybe (SizeHash (ADDRHASH c) :~: 28, Addr28Extra)
encodeAddress28 Network
network PaymentCredential (EraCrypto era)
paymentCred
      , Just (SizeHash (HASH (EraCrypto era)) :~: 32
Refl, DataHash32
dataHash32) <- forall c.
HashAlgorithm (HASH c) =>
DataHash c -> Maybe (SizeHash (HASH c) :~: 32, DataHash32)
encodeDataHash32 DataHash (EraCrypto era)
dh =
          forall era.
Credential 'Staking (EraCrypto era)
-> Addr28Extra -> CompactForm Coin -> DataHash32 -> AlonzoTxOut era
TxOut_AddrHash28_AdaOnly_DataHash32 StakeCredential (EraCrypto era)
stakeCred Addr28Extra
addr28Extra CompactForm Coin
adaCompact DataHash32
dataHash32
    AlonzoTxOut Addr (EraCrypto era)
addr Value era
vl StrictMaybe (DataHash (EraCrypto era))
mdh =
      let v :: CompactForm (Value era)
v = forall a. a -> Maybe a -> a
fromMaybe (forall a. HasCallStack => [Char] -> a
error forall a b. (a -> b) -> a -> b
$ [Char]
"Illegal value in TxOut: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show Value era
vl) forall a b. (a -> b) -> a -> b
$ forall a. Compactible a => a -> Maybe (CompactForm a)
toCompact Value era
vl
          a :: CompactAddr (EraCrypto era)
a = forall c. Addr c -> CompactAddr c
compactAddr Addr (EraCrypto era)
addr
       in case StrictMaybe (DataHash (EraCrypto era))
mdh of
            StrictMaybe (DataHash (EraCrypto era))
SNothing -> forall era.
CompactAddr (EraCrypto era)
-> CompactForm (Value era) -> AlonzoTxOut era
TxOutCompact' CompactAddr (EraCrypto era)
a CompactForm (Value era)
v
            SJust DataHash (EraCrypto era)
dh -> forall era.
CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> DataHash (EraCrypto era)
-> AlonzoTxOut era
TxOutCompactDH' CompactAddr (EraCrypto era)
a CompactForm (Value era)
v DataHash (EraCrypto era)
dh

{-# COMPLETE AlonzoTxOut #-}

instance Crypto c => EraTxOut (AlonzoEra c) where
  {-# SPECIALIZE instance EraTxOut (AlonzoEra StandardCrypto) #-}

  type TxOut (AlonzoEra c) = AlonzoTxOut (AlonzoEra c)

  mkBasicTxOut :: HasCallStack =>
Addr (EraCrypto (AlonzoEra c))
-> Value (AlonzoEra c) -> TxOut (AlonzoEra c)
mkBasicTxOut Addr (EraCrypto (AlonzoEra c))
addr Value (AlonzoEra c)
vl = forall era.
(Era era, Val (Value era), HasCallStack) =>
Addr (EraCrypto era)
-> Value era
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
AlonzoTxOut Addr (EraCrypto (AlonzoEra c))
addr Value (AlonzoEra c)
vl forall a. StrictMaybe a
SNothing

  upgradeTxOut :: EraTxOut (PreviousEra (AlonzoEra c)) =>
TxOut (PreviousEra (AlonzoEra c)) -> TxOut (AlonzoEra c)
upgradeTxOut (Shelley.TxOutCompact CompactAddr (EraCrypto (MaryEra c))
addr CompactForm (Value (MaryEra c))
value) = forall era.
(Era era, Val (Value era), HasCallStack) =>
CompactAddr (EraCrypto era)
-> CompactForm (Value era) -> AlonzoTxOut era
TxOutCompact CompactAddr (EraCrypto (MaryEra c))
addr CompactForm (Value (MaryEra c))
value

  addrEitherTxOutL :: Lens'
  (TxOut (AlonzoEra c))
  (Either
     (Addr (EraCrypto (AlonzoEra c)))
     (CompactAddr (EraCrypto (AlonzoEra c))))
addrEitherTxOutL =
    forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens
      forall era.
HashAlgorithm (ADDRHASH (EraCrypto era)) =>
AlonzoTxOut era
-> Either (Addr (EraCrypto era)) (CompactAddr (EraCrypto era))
getAlonzoTxOutEitherAddr
      ( \AlonzoTxOut (AlonzoEra c)
txOut Either (Addr c) (CompactAddr c)
eAddr ->
          let cVal :: CompactForm (Value (AlonzoEra c))
cVal = forall era.
EraTxOut era =>
AlonzoTxOut era -> CompactForm (Value era)
getTxOutCompactValue AlonzoTxOut (AlonzoEra c)
txOut
              (Addr (EraCrypto (AlonzoEra c))
_, Value (AlonzoEra c)
_, StrictMaybe (DataHash (EraCrypto (AlonzoEra c)))
dh) = forall era.
(Era era, Val (Value era)) =>
AlonzoTxOut era
-> (Addr (EraCrypto era), Value era,
    StrictMaybe (DataHash (EraCrypto era)))
viewTxOut AlonzoTxOut (AlonzoEra c)
txOut
           in case Either (Addr c) (CompactAddr c)
eAddr of
                Left Addr c
addr -> forall era.
(Era era, HasCallStack, Val (Value era)) =>
Addr (EraCrypto era)
-> CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
mkTxOutCompact Addr c
addr (forall c. Addr c -> CompactAddr c
compactAddr Addr c
addr) CompactForm (Value (AlonzoEra c))
cVal StrictMaybe (DataHash (EraCrypto (AlonzoEra c)))
dh
                Right CompactAddr c
cAddr -> forall era.
(Era era, HasCallStack, Val (Value era)) =>
Addr (EraCrypto era)
-> CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
mkTxOutCompact (forall c. (HasCallStack, Crypto c) => CompactAddr c -> Addr c
decompactAddr CompactAddr c
cAddr) CompactAddr c
cAddr CompactForm (Value (AlonzoEra c))
cVal StrictMaybe (DataHash (EraCrypto (AlonzoEra c)))
dh
      )
  {-# INLINE addrEitherTxOutL #-}

  valueEitherTxOutL :: Lens'
  (TxOut (AlonzoEra c))
  (Either (Value (AlonzoEra c)) (CompactForm (Value (AlonzoEra c))))
valueEitherTxOutL =
    forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens
      (forall a b. b -> Either a b
Right forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall era.
EraTxOut era =>
AlonzoTxOut era -> CompactForm (Value era)
getTxOutCompactValue)
      ( \AlonzoTxOut (AlonzoEra c)
txOut Either (MaryValue c) (CompactForm (MaryValue c))
eVal ->
          case Either (MaryValue c) (CompactForm (MaryValue c))
eVal of
            Left MaryValue c
val ->
              let (Addr (EraCrypto (AlonzoEra c))
addr, Value (AlonzoEra c)
_, StrictMaybe (DataHash (EraCrypto (AlonzoEra c)))
dh) = forall era.
(Era era, Val (Value era)) =>
AlonzoTxOut era
-> (Addr (EraCrypto era), Value era,
    StrictMaybe (DataHash (EraCrypto era)))
viewTxOut AlonzoTxOut (AlonzoEra c)
txOut
               in forall era.
(Era era, Val (Value era), HasCallStack) =>
Addr (EraCrypto era)
-> Value era
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
AlonzoTxOut Addr (EraCrypto (AlonzoEra c))
addr MaryValue c
val StrictMaybe (DataHash (EraCrypto (AlonzoEra c)))
dh
            Right CompactForm (MaryValue c)
cVal ->
              let dh :: StrictMaybe (DataHash (EraCrypto (AlonzoEra c)))
dh = forall era.
(HasCallStack, HashAlgorithm (HASH (EraCrypto era))) =>
AlonzoTxOut era -> StrictMaybe (DataHash (EraCrypto era))
getAlonzoTxOutDataHash AlonzoTxOut (AlonzoEra c)
txOut
               in case forall era.
HashAlgorithm (ADDRHASH (EraCrypto era)) =>
AlonzoTxOut era
-> Either (Addr (EraCrypto era)) (CompactAddr (EraCrypto era))
getAlonzoTxOutEitherAddr AlonzoTxOut (AlonzoEra c)
txOut of
                    Left Addr (EraCrypto (AlonzoEra c))
addr -> forall era.
(Era era, HasCallStack, Val (Value era)) =>
Addr (EraCrypto era)
-> CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
mkTxOutCompact Addr (EraCrypto (AlonzoEra c))
addr (forall c. Addr c -> CompactAddr c
compactAddr Addr (EraCrypto (AlonzoEra c))
addr) CompactForm (MaryValue c)
cVal StrictMaybe (DataHash (EraCrypto (AlonzoEra c)))
dh
                    Right CompactAddr (EraCrypto (AlonzoEra c))
cAddr -> forall era.
(Era era, HasCallStack, Val (Value era)) =>
Addr (EraCrypto era)
-> CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
mkTxOutCompact (forall c. (HasCallStack, Crypto c) => CompactAddr c -> Addr c
decompactAddr CompactAddr (EraCrypto (AlonzoEra c))
cAddr) CompactAddr (EraCrypto (AlonzoEra c))
cAddr CompactForm (MaryValue c)
cVal StrictMaybe (DataHash (EraCrypto (AlonzoEra c)))
dh
      )
  {-# INLINE valueEitherTxOutL #-}

  getMinCoinTxOut :: PParams (AlonzoEra c) -> TxOut (AlonzoEra c) -> Coin
getMinCoinTxOut PParams (AlonzoEra c)
pp TxOut (AlonzoEra c)
txOut =
    case PParams (AlonzoEra c)
pp forall s a. s -> Getting a s a -> a
^. forall era.
(AlonzoEraPParams era, ExactEra AlonzoEra era) =>
Lens' (PParams era) CoinPerWord
ppCoinsPerUTxOWordL of
      CoinPerWord (Coin Integer
cpw) -> Integer -> Coin
Coin forall a b. (a -> b) -> a -> b
$ forall era. AlonzoEraTxOut era => TxOut era -> Integer
utxoEntrySize TxOut (AlonzoEra c)
txOut forall a. Num a => a -> a -> a
* Integer
cpw

instance
  (Era era, Val (Value era)) =>
  EncCBOR (AlonzoTxOut era)
  where
  encCBOR :: AlonzoTxOut era -> Encoding
encCBOR (TxOutCompact CompactAddr (EraCrypto era)
addr CompactForm (Value era)
cv) =
    Word -> Encoding
encodeListLen Word
2
      forall a. Semigroup a => a -> a -> a
<> forall a. EncCBOR a => a -> Encoding
encCBOR CompactAddr (EraCrypto era)
addr
      forall a. Semigroup a => a -> a -> a
<> forall a. EncCBOR a => a -> Encoding
encCBOR CompactForm (Value era)
cv
  encCBOR (TxOutCompactDH CompactAddr (EraCrypto era)
addr CompactForm (Value era)
cv DataHash (EraCrypto era)
dh) =
    Word -> Encoding
encodeListLen Word
3
      forall a. Semigroup a => a -> a -> a
<> forall a. EncCBOR a => a -> Encoding
encCBOR CompactAddr (EraCrypto era)
addr
      forall a. Semigroup a => a -> a -> a
<> forall a. EncCBOR a => a -> Encoding
encCBOR CompactForm (Value era)
cv
      forall a. Semigroup a => a -> a -> a
<> forall a. EncCBOR a => a -> Encoding
encCBOR DataHash (EraCrypto era)
dh

instance (Era era, Val (Value era)) => DecCBOR (AlonzoTxOut era) where
  decCBOR :: forall s. Decoder s (AlonzoTxOut era)
decCBOR = do
    Maybe Int
lenOrIndef <- forall s. Decoder s (Maybe Int)
decodeListLenOrIndef
    case Maybe Int
lenOrIndef of
      Maybe Int
Nothing -> do
        (Addr (EraCrypto era)
a, CompactAddr (EraCrypto era)
ca) <- forall c s. Crypto c => Decoder s (Addr c, CompactAddr c)
fromCborBothAddr
        CompactForm (Value era)
cv <- forall a s. DecCBOR a => Decoder s a
decCBOR
        forall s. Decoder s Bool
decodeBreakOr forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
          Bool
True -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall era.
(Era era, HasCallStack, Val (Value era)) =>
Addr (EraCrypto era)
-> CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
mkTxOutCompact Addr (EraCrypto era)
a CompactAddr (EraCrypto era)
ca CompactForm (Value era)
cv forall a. StrictMaybe a
SNothing
          Bool
False -> do
            DataHash (EraCrypto era)
dh <- forall a s. DecCBOR a => Decoder s a
decCBOR
            forall s. Decoder s Bool
decodeBreakOr forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
              Bool
True -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall era.
(Era era, HasCallStack, Val (Value era)) =>
Addr (EraCrypto era)
-> CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
mkTxOutCompact Addr (EraCrypto era)
a CompactAddr (EraCrypto era)
ca CompactForm (Value era)
cv (forall a. a -> StrictMaybe a
SJust DataHash (EraCrypto era)
dh)
              Bool
False -> forall (m :: * -> *) e a. (MonadFail m, Buildable e) => e -> m a
cborError forall a b. (a -> b) -> a -> b
$ Text -> Text -> DecoderError
DecoderErrorCustom Text
"txout" Text
"Excess terms in txout"
      Just Int
2 -> do
        (Addr (EraCrypto era)
a, CompactAddr (EraCrypto era)
ca) <- forall c s. Crypto c => Decoder s (Addr c, CompactAddr c)
fromCborBothAddr
        CompactForm (Value era)
cv <- forall a s. DecCBOR a => Decoder s a
decCBOR
        forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall era.
(Era era, HasCallStack, Val (Value era)) =>
Addr (EraCrypto era)
-> CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
mkTxOutCompact Addr (EraCrypto era)
a CompactAddr (EraCrypto era)
ca CompactForm (Value era)
cv forall a. StrictMaybe a
SNothing
      Just Int
3 -> do
        (Addr (EraCrypto era)
a, CompactAddr (EraCrypto era)
ca) <- forall c s. Crypto c => Decoder s (Addr c, CompactAddr c)
fromCborBothAddr
        CompactForm (Value era)
cv <- forall a s. DecCBOR a => Decoder s a
decCBOR
        forall era.
(Era era, HasCallStack, Val (Value era)) =>
Addr (EraCrypto era)
-> CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
mkTxOutCompact Addr (EraCrypto era)
a CompactAddr (EraCrypto era)
ca CompactForm (Value era)
cv forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> StrictMaybe a
SJust forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a s. DecCBOR a => Decoder s a
decCBOR
      Just Int
_ -> forall (m :: * -> *) e a. (MonadFail m, Buildable e) => e -> m a
cborError forall a b. (a -> b) -> a -> b
$ Text -> Text -> DecoderError
DecoderErrorCustom Text
"txout" Text
"wrong number of terms in txout"
  {-# INLINEABLE decCBOR #-}

instance (Era era, Val (Value era)) => DecShareCBOR (AlonzoTxOut era) where
  type Share (AlonzoTxOut era) = Interns (Credential 'Staking (EraCrypto era))
  decShareCBOR :: forall s. Share (AlonzoTxOut era) -> Decoder s (AlonzoTxOut era)
decShareCBOR Share (AlonzoTxOut era)
credsInterns = do
    forall era.
(Credential 'Staking (EraCrypto era)
 -> Credential 'Staking (EraCrypto era))
-> AlonzoTxOut era -> AlonzoTxOut era
internAlonzoTxOut (forall k. Interns k -> k -> k
interns Share (AlonzoTxOut era)
credsInterns) forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
<$!> forall a s. DecCBOR a => Decoder s a
decCBOR
  {-# INLINEABLE decShareCBOR #-}

internAlonzoTxOut ::
  (Credential 'Staking (EraCrypto era) -> Credential 'Staking (EraCrypto era)) ->
  AlonzoTxOut era ->
  AlonzoTxOut era
internAlonzoTxOut :: forall era.
(Credential 'Staking (EraCrypto era)
 -> Credential 'Staking (EraCrypto era))
-> AlonzoTxOut era -> AlonzoTxOut era
internAlonzoTxOut Credential 'Staking (EraCrypto era)
-> Credential 'Staking (EraCrypto era)
internCred = \case
  TxOut_AddrHash28_AdaOnly Credential 'Staking (EraCrypto era)
cred Addr28Extra
addr28Extra CompactForm Coin
ada ->
    forall era.
Credential 'Staking (EraCrypto era)
-> Addr28Extra -> CompactForm Coin -> AlonzoTxOut era
TxOut_AddrHash28_AdaOnly (Credential 'Staking (EraCrypto era)
-> Credential 'Staking (EraCrypto era)
internCred Credential 'Staking (EraCrypto era)
cred) Addr28Extra
addr28Extra CompactForm Coin
ada
  TxOut_AddrHash28_AdaOnly_DataHash32 Credential 'Staking (EraCrypto era)
cred Addr28Extra
addr28Extra CompactForm Coin
ada DataHash32
dataHash32 ->
    forall era.
Credential 'Staking (EraCrypto era)
-> Addr28Extra -> CompactForm Coin -> DataHash32 -> AlonzoTxOut era
TxOut_AddrHash28_AdaOnly_DataHash32 (Credential 'Staking (EraCrypto era)
-> Credential 'Staking (EraCrypto era)
internCred Credential 'Staking (EraCrypto era)
cred) Addr28Extra
addr28Extra CompactForm Coin
ada DataHash32
dataHash32
  AlonzoTxOut era
txOut -> AlonzoTxOut era
txOut
{-# INLINE internAlonzoTxOut #-}

instance (Era era, Val (Value era)) => ToCBOR (AlonzoTxOut era) where
  toCBOR :: AlonzoTxOut era -> Encoding
toCBOR = forall era t. (Era era, EncCBOR t) => t -> Encoding
toEraCBOR @era
  {-# INLINE toCBOR #-}

instance (Era era, Val (Value era)) => FromCBOR (AlonzoTxOut era) where
  fromCBOR :: forall s. Decoder s (AlonzoTxOut era)
fromCBOR = forall era t s. (Era era, DecCBOR t) => Decoder s t
fromEraCBOR @era
  {-# INLINE fromCBOR #-}

instance (Era era, Val (Value era)) => ToJSON (AlonzoTxOut era) where
  toJSON :: AlonzoTxOut era -> Value
toJSON (AlonzoTxOut Addr (EraCrypto era)
addr Value era
v StrictMaybe (DataHash (EraCrypto era))
dataHash) =
    [Pair] -> Value
object
      [ Key
"address" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON Addr (EraCrypto era)
addr
      , Key
"value" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON Value era
v
      , Key
"datahash" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= case forall a. StrictMaybe a -> Maybe a
strictMaybeToMaybe StrictMaybe (DataHash (EraCrypto era))
dataHash of
          Maybe (DataHash (EraCrypto era))
Nothing -> Value
Aeson.Null
          Just DataHash (EraCrypto era)
dHash ->
            Text -> Value
Aeson.String forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall h a. Hash h a -> Text
hashToTextAsHex forall a b. (a -> b) -> a -> b
$
              forall c i. SafeHash c i -> Hash (HASH c) i
extractHash DataHash (EraCrypto era)
dHash
      ]

pattern TxOutCompact ::
  (Era era, Val (Value era), HasCallStack) =>
  CompactAddr (EraCrypto era) ->
  CompactForm (Value era) ->
  AlonzoTxOut era
pattern $bTxOutCompact :: forall era.
(Era era, Val (Value era), HasCallStack) =>
CompactAddr (EraCrypto era)
-> CompactForm (Value era) -> AlonzoTxOut era
$mTxOutCompact :: forall {r} {era}.
(Era era, Val (Value era), HasCallStack) =>
AlonzoTxOut era
-> (CompactAddr (EraCrypto era) -> CompactForm (Value era) -> r)
-> ((# #) -> r)
-> r
TxOutCompact addr vl <-
  (viewCompactTxOut -> (addr, vl, SNothing))
  where
    TxOutCompact CompactAddr (EraCrypto era)
cAddr CompactForm (Value era)
cVal = forall era.
(Era era, HasCallStack, Val (Value era)) =>
Addr (EraCrypto era)
-> CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
mkTxOutCompact (forall c. (HasCallStack, Crypto c) => CompactAddr c -> Addr c
decompactAddr CompactAddr (EraCrypto era)
cAddr) CompactAddr (EraCrypto era)
cAddr CompactForm (Value era)
cVal forall a. StrictMaybe a
SNothing

pattern TxOutCompactDH ::
  (Era era, Val (Value era), HasCallStack) =>
  CompactAddr (EraCrypto era) ->
  CompactForm (Value era) ->
  DataHash (EraCrypto era) ->
  AlonzoTxOut era
pattern $bTxOutCompactDH :: forall era.
(Era era, Val (Value era), HasCallStack) =>
CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> DataHash (EraCrypto era)
-> AlonzoTxOut era
$mTxOutCompactDH :: forall {r} {era}.
(Era era, Val (Value era), HasCallStack) =>
AlonzoTxOut era
-> (CompactAddr (EraCrypto era)
    -> CompactForm (Value era) -> DataHash (EraCrypto era) -> r)
-> ((# #) -> r)
-> r
TxOutCompactDH addr vl dh <-
  (viewCompactTxOut -> (addr, vl, SJust dh))
  where
    TxOutCompactDH CompactAddr (EraCrypto era)
cAddr CompactForm (Value era)
cVal DataHash (EraCrypto era)
dh = forall era.
(Era era, HasCallStack, Val (Value era)) =>
Addr (EraCrypto era)
-> CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
mkTxOutCompact (forall c. (HasCallStack, Crypto c) => CompactAddr c -> Addr c
decompactAddr CompactAddr (EraCrypto era)
cAddr) CompactAddr (EraCrypto era)
cAddr CompactForm (Value era)
cVal (forall a. a -> StrictMaybe a
SJust DataHash (EraCrypto era)
dh)

{-# COMPLETE TxOutCompact, TxOutCompactDH #-}

mkTxOutCompact ::
  (Era era, HasCallStack, Val (Value era)) =>
  Addr (EraCrypto era) ->
  CompactAddr (EraCrypto era) ->
  CompactForm (Value era) ->
  StrictMaybe (DataHash (EraCrypto era)) ->
  AlonzoTxOut era
mkTxOutCompact :: forall era.
(Era era, HasCallStack, Val (Value era)) =>
Addr (EraCrypto era)
-> CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
mkTxOutCompact Addr (EraCrypto era)
addr CompactAddr (EraCrypto era)
cAddr CompactForm (Value era)
cVal StrictMaybe (DataHash (EraCrypto era))
mdh
  | forall t. Val t => CompactForm t -> Bool
isAdaOnlyCompact CompactForm (Value era)
cVal = forall era.
(Era era, Val (Value era), HasCallStack) =>
Addr (EraCrypto era)
-> Value era
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
AlonzoTxOut Addr (EraCrypto era)
addr (forall a. Compactible a => CompactForm a -> a
fromCompact CompactForm (Value era)
cVal) StrictMaybe (DataHash (EraCrypto era))
mdh
  | SJust DataHash (EraCrypto era)
dh <- StrictMaybe (DataHash (EraCrypto era))
mdh = forall era.
CompactAddr (EraCrypto era)
-> CompactForm (Value era)
-> DataHash (EraCrypto era)
-> AlonzoTxOut era
TxOutCompactDH' CompactAddr (EraCrypto era)
cAddr CompactForm (Value era)
cVal DataHash (EraCrypto era)
dh
  | Bool
otherwise = forall era.
CompactAddr (EraCrypto era)
-> CompactForm (Value era) -> AlonzoTxOut era
TxOutCompact' CompactAddr (EraCrypto era)
cAddr CompactForm (Value era)
cVal

getAlonzoTxOutDataHash ::
  forall era.
  (HasCallStack, HashAlgorithm (HASH (EraCrypto era))) =>
  AlonzoTxOut era ->
  StrictMaybe (DataHash (EraCrypto era))
getAlonzoTxOutDataHash :: forall era.
(HasCallStack, HashAlgorithm (HASH (EraCrypto era))) =>
AlonzoTxOut era -> StrictMaybe (DataHash (EraCrypto era))
getAlonzoTxOutDataHash = \case
  TxOutCompactDH' CompactAddr (EraCrypto era)
_ CompactForm (Value era)
_ DataHash (EraCrypto era)
dh -> forall a. a -> StrictMaybe a
SJust DataHash (EraCrypto era)
dh
  TxOut_AddrHash28_AdaOnly_DataHash32 Credential 'Staking (EraCrypto era)
_ Addr28Extra
_ CompactForm Coin
_ DataHash32
dh ->
    case forall c.
HashAlgorithm (HASH c) =>
DataHash32 -> Maybe (DataHash c)
decodeDataHash32 DataHash32
dh of
      Maybe (DataHash (EraCrypto era))
Nothing -> forall a. HasCallStack => [Char] -> a
error forall a b. (a -> b) -> a -> b
$ [Char]
"Impossible: Compacted a DataHash of non-standard size: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show DataHash32
dh
      Just DataHash (EraCrypto era)
dataHash -> forall a. a -> StrictMaybe a
SJust DataHash (EraCrypto era)
dataHash
  AlonzoTxOut era
_ -> forall a. StrictMaybe a
SNothing

getAlonzoTxOutEitherAddr ::
  HashAlgorithm (ADDRHASH (EraCrypto era)) =>
  AlonzoTxOut era ->
  Either (Addr (EraCrypto era)) (CompactAddr (EraCrypto era))
getAlonzoTxOutEitherAddr :: forall era.
HashAlgorithm (ADDRHASH (EraCrypto era)) =>
AlonzoTxOut era
-> Either (Addr (EraCrypto era)) (CompactAddr (EraCrypto era))
getAlonzoTxOutEitherAddr = \case
  TxOutCompact' CompactAddr (EraCrypto era)
cAddr CompactForm (Value era)
_ -> forall a b. b -> Either a b
Right CompactAddr (EraCrypto era)
cAddr
  TxOutCompactDH' CompactAddr (EraCrypto era)
cAddr CompactForm (Value era)
_ DataHash (EraCrypto era)
_ -> forall a b. b -> Either a b
Right CompactAddr (EraCrypto era)
cAddr
  TxOut_AddrHash28_AdaOnly Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra CompactForm Coin
_
    | Just Addr (EraCrypto era)
addr <- forall c.
HashAlgorithm (ADDRHASH c) =>
Credential 'Staking c -> Addr28Extra -> Maybe (Addr c)
decodeAddress28 Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra -> forall a b. a -> Either a b
Left Addr (EraCrypto era)
addr
    | Bool
otherwise -> forall a. HasCallStack => [Char] -> a
error [Char]
addressErrorMsg
  TxOut_AddrHash28_AdaOnly_DataHash32 Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra CompactForm Coin
_ DataHash32
_
    | Just Addr (EraCrypto era)
addr <- forall c.
HashAlgorithm (ADDRHASH c) =>
Credential 'Staking c -> Addr28Extra -> Maybe (Addr c)
decodeAddress28 Credential 'Staking (EraCrypto era)
stakeRef Addr28Extra
addr28Extra -> forall a b. a -> Either a b
Left Addr (EraCrypto era)
addr
    | Bool
otherwise -> forall a. HasCallStack => [Char] -> a
error [Char]
addressErrorMsg

-- | Compute an estimate of the size of storing one UTxO entry.
-- This function implements the UTxO entry size estimate done by scaledMinDeposit in the ShelleyMA era
utxoEntrySize :: AlonzoEraTxOut era => TxOut era -> Integer
utxoEntrySize :: forall era. AlonzoEraTxOut era => TxOut era -> Integer
utxoEntrySize TxOut era
txOut = Integer
utxoEntrySizeWithoutVal forall a. Num a => a -> a -> a
+ forall t. Val t => t -> Integer
size Value era
v forall a. Num a => a -> a -> a
+ forall c. StrictMaybe (DataHash c) -> Integer
dataHashSize StrictMaybe (DataHash (EraCrypto era))
dh
  where
    v :: Value era
v = TxOut era
txOut forall s a. s -> Getting a s a -> a
^. forall era. EraTxOut era => Lens' (TxOut era) (Value era)
valueTxOutL
    dh :: StrictMaybe (DataHash (EraCrypto era))
dh = TxOut era
txOut forall s a. s -> Getting a s a -> a
^. forall era.
AlonzoEraTxOut era =>
Lens' (TxOut era) (StrictMaybe (DataHash (EraCrypto era)))
dataHashTxOutL
    -- lengths obtained from tracing on HeapWords of inputs and outputs
    -- obtained experimentally, and number used here
    -- units are Word64s

    -- size of UTxO entry excluding the Value part
    utxoEntrySizeWithoutVal :: Integer
    utxoEntrySizeWithoutVal :: Integer
utxoEntrySizeWithoutVal = Integer
27 -- 6 + txoutLenNoVal [14] + txinLen [7]

instance Crypto c => AlonzoEraTxOut (AlonzoEra c) where
  {-# SPECIALIZE instance AlonzoEraTxOut (AlonzoEra StandardCrypto) #-}

  dataHashTxOutL :: Lens'
  (TxOut (AlonzoEra c))
  (StrictMaybe (DataHash (EraCrypto (AlonzoEra c))))
dataHashTxOutL =
    forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens forall era.
(HasCallStack, HashAlgorithm (HASH (EraCrypto era))) =>
AlonzoTxOut era -> StrictMaybe (DataHash (EraCrypto era))
getAlonzoTxOutDataHash (\(AlonzoTxOut Addr (EraCrypto (AlonzoEra c))
addr Value (AlonzoEra c)
cv StrictMaybe (DataHash (EraCrypto (AlonzoEra c)))
_) StrictMaybe (DataHash c)
dh -> forall era.
(Era era, Val (Value era), HasCallStack) =>
Addr (EraCrypto era)
-> Value era
-> StrictMaybe (DataHash (EraCrypto era))
-> AlonzoTxOut era
AlonzoTxOut Addr (EraCrypto (AlonzoEra c))
addr Value (AlonzoEra c)
cv StrictMaybe (DataHash c)
dh)
  {-# INLINEABLE dataHashTxOutL #-}

  datumTxOutF :: SimpleGetter (TxOut (AlonzoEra c)) (Datum (AlonzoEra c))
datumTxOutF = forall s a. (s -> a) -> SimpleGetter s a
to forall a b. (a -> b) -> a -> b
$ \TxOut (AlonzoEra c)
txOut ->
    case forall era.
(HasCallStack, HashAlgorithm (HASH (EraCrypto era))) =>
AlonzoTxOut era -> StrictMaybe (DataHash (EraCrypto era))
getAlonzoTxOutDataHash TxOut (AlonzoEra c)
txOut of
      StrictMaybe (DataHash (EraCrypto (AlonzoEra c)))
SNothing -> forall era. Datum era
NoDatum
      SJust DataHash (EraCrypto (AlonzoEra c))
dh -> forall era. DataHash (EraCrypto era) -> Datum era
DatumHash DataHash (EraCrypto (AlonzoEra c))
dh
  {-# INLINEABLE datumTxOutF #-}

getTxOutCompactValue :: EraTxOut era => AlonzoTxOut era -> CompactForm (Value era)
getTxOutCompactValue :: forall era.
EraTxOut era =>
AlonzoTxOut era -> CompactForm (Value era)
getTxOutCompactValue =
  \case
    TxOutCompact' CompactAddr (EraCrypto era)
_ CompactForm (Value era)
cv -> CompactForm (Value era)
cv
    TxOutCompactDH' CompactAddr (EraCrypto era)
_ CompactForm (Value era)
cv DataHash (EraCrypto era)
_ -> CompactForm (Value era)
cv
    TxOut_AddrHash28_AdaOnly Credential 'Staking (EraCrypto era)
_ Addr28Extra
_ CompactForm Coin
cc -> forall t. Val t => CompactForm Coin -> CompactForm t
injectCompact CompactForm Coin
cc
    TxOut_AddrHash28_AdaOnly_DataHash32 Credential 'Staking (EraCrypto era)
_ Addr28Extra
_ CompactForm Coin
cc DataHash32
_ -> forall t. Val t => CompactForm Coin -> CompactForm t
injectCompact CompactForm Coin
cc