content: {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE DeriveGeneric #-}
  {-# LANGUAGE DerivingVia #-}
  {-# LANGUAGE FlexibleContexts #-}
  {-# LANGUAGE FlexibleInstances #-}
  {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE NamedFieldPuns #-}
  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE PatternSynonyms #-}
  {-# LANGUAGE RankNTypes #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE StandaloneDeriving #-}
  {-# LANGUAGE TypeApplications #-}
  {-# LANGUAGE TypeFamilies #-}
  {-# LANGUAGE UndecidableInstances #-}
  {-# LANGUAGE UndecidableSuperClasses #-}
  {-# LANGUAGE ViewPatterns #-}
  {-# OPTIONS_GHC -Wno-orphans #-}
  
  module Cardano.Ledger.Babbage.TxBody (
    BabbageTxOut (
      BabbageTxOut,
      TxOutCompact,
      TxOutCompactDH,
      TxOutCompactDatum,
      TxOutCompactRefScript
    ),
    TxBody (
      MkBabbageTxBody,
      BabbageTxBody,
      btbInputs,
      btbCollateral,
      btbReferenceInputs,
      btbOutputs,
      btbCollateralReturn,
      btbTotalCollateral,
      btbCerts,
      btbWithdrawals,
      btbTxFee,
      btbValidityInterval,
      btbUpdate,
      btbReqSignerHashes,
      btbMint,
      btbScriptIntegrityHash,
      btbAuxDataHash,
      btbTxNetworkId
    ),
    allSizedOutputsBabbageTxBodyF,
    babbageMinUTxOValue,
    BabbageTxBodyRaw (..),
    babbageAllInputsTxBodyF,
    babbageSpendableInputsTxBodyF,
    BabbageEraTxBody (..),
    spendInputs',
    collateralInputs',
    referenceInputs',
    outputs',
    collateralReturn',
    totalCollateral',
    certs',
    withdrawals',
    txfee',
    vldt',
    update',
    reqSignerHashes',
    mint',
    scriptIntegrityHash',
    adHash',
    txnetworkid',
    getEitherAddrBabbageTxOut,
    EraIndependentScriptIntegrity,
    ScriptIntegrityHash,
    txOutData,
    txOutDataHash,
    txOutScript,
  ) where
  
  import Cardano.Ledger.Alonzo.Core
  import Cardano.Ledger.Alonzo.TxBody (alonzoRedeemerPointer, alonzoRedeemerPointerInverse)
  import Cardano.Ledger.Babbage.Era (BabbageEra)
  import Cardano.Ledger.Babbage.Scripts ()
  import Cardano.Ledger.Babbage.TxCert ()
  import Cardano.Ledger.Babbage.TxOut hiding (TxOut)
  import Cardano.Ledger.BaseTypes (
    Network (..),
    StrictMaybe (..),
   )
  import Cardano.Ledger.Binary (
    Annotator,
    DecCBOR (..),
    EncCBOR (..),
    Sized (..),
    ToCBOR (..),
    mkSized,
   )
  import Cardano.Ledger.Binary.Coders
  import Cardano.Ledger.Coin (Coin (..))
  import Cardano.Ledger.Mary.Value (MultiAsset, policies)
  import Cardano.Ledger.MemoBytes (
    EqRaw,
    Mem,
    MemoBytes,
    MemoHashIndex,
    Memoized (..),
    eqRaw,
    getMemoRawType,
    getMemoSafeHash,
    lensMemoRawType,
    mkMemoizedEra,
    zipMemoRawType,
   )
  import Cardano.Ledger.Shelley.PParams (Update (..))
  import Cardano.Ledger.Shelley.TxBody (getShelleyGenesisKeyHashCountTxBody)
  import Cardano.Ledger.TxIn (TxIn (..))
  import Control.DeepSeq (NFData)
  import Data.Foldable as F (foldl')
  import Data.Sequence.Strict (StrictSeq, (|>))
  import qualified Data.Sequence.Strict as StrictSeq
  import Data.Set (Set)
  import qualified Data.Set as Set
  import GHC.Generics (Generic)
  import Lens.Micro
  import NoThunks.Class (NoThunks)
  
  class (AlonzoEraTxBody era, BabbageEraTxOut era) => BabbageEraTxBody era where
    sizedOutputsTxBodyL :: Lens' (TxBody era) (StrictSeq (Sized (TxOut era)))
  
    referenceInputsTxBodyL :: Lens' (TxBody era) (Set TxIn)
  
    totalCollateralTxBodyL :: Lens' (TxBody era) (StrictMaybe Coin)
  
    collateralReturnTxBodyL :: Lens' (TxBody era) (StrictMaybe (TxOut era))
  
    sizedCollateralReturnTxBodyL :: Lens' (TxBody era) (StrictMaybe (Sized (TxOut era)))
  
    allSizedOutputsTxBodyF :: SimpleGetter (TxBody era) (StrictSeq (Sized (TxOut era)))
  
  -- ======================================
  
  data BabbageTxBodyRaw = BabbageTxBodyRaw
    { btbrInputs :: !(Set TxIn)
    , btbrCollateralInputs :: !(Set TxIn)
    , btbrReferenceInputs :: !(Set TxIn)
    , btbrOutputs :: !(StrictSeq (Sized (TxOut BabbageEra)))
    , btbrCollateralReturn :: !(StrictMaybe (Sized (TxOut BabbageEra)))
    , btbrTotalCollateral :: !(StrictMaybe Coin)
    , btbrCerts :: !(StrictSeq (TxCert BabbageEra))
    , btbrWithdrawals :: !Withdrawals
    , btbrFee :: !Coin
    , btbrValidityInterval :: !ValidityInterval
    , btbrUpdate :: !(StrictMaybe (Update BabbageEra))
    , btbrReqSignerHashes :: !(Set (KeyHash 'Witness))
    , btbrMint :: !MultiAsset
    , -- The spec makes it clear that the mint field is a
      -- Cardano.Ledger.Mary.Value.MaryValue, not a Value.
      -- Operations on the TxBody in the BabbageEra depend upon this.
      -- We now store only the MultiAsset part of a Mary.Value.
      btbrScriptIntegrityHash :: !(StrictMaybe ScriptIntegrityHash)
    , btbrAuxDataHash :: !(StrictMaybe TxAuxDataHash)
    , btbrNetworkId :: !(StrictMaybe Network)
    }
    deriving (Generic)
  
  -- We override this instance because the 'Sized' types also reference their
  -- serialisation and as such cannot be compared directly. An alternative would
  -- be to derive `EqRaw` for `Sized`.
  instance EqRaw BabbageTxBodyRaw where
    eqRaw a b =
      btbrInputs a == btbrInputs b
        && btbrCollateralInputs a == btbrCollateralInputs b
        && btbrReferenceInputs a == btbrReferenceInputs b
        && btbrOutputs a `eqSeqUnsized` btbrOutputs b
        && btbrCollateralReturn a `eqMbUnsized` btbrCollateralReturn b
        && btbrTotalCollateral a == btbrTotalCollateral b
        && btbrCerts a == btbrCerts b
        && btbrWithdrawals a == btbrWithdrawals b
        && btbrFee a == btbrFee b
        && btbrValidityInterval a == btbrValidityInterval b
        && btbrUpdate a == btbrUpdate b
        && btbrReqSignerHashes a == btbrReqSignerHashes b
        && btbrMint a == btbrMint b
        && btbrScriptIntegrityHash a == btbrScriptIntegrityHash b
        && btbrAuxDataHash a == btbrAuxDataHash b
        && btbrNetworkId a == btbrNetworkId b
      where
        eqMbUnsized x y = case (x, y) of
          (SJust a', SJust b') -> a' `eqUnsized` b'
          (SNothing, SNothing) -> True
          _ -> False
        eqSeqUnsized x y =
          length x == length y
            && F.foldl' (\acc (x', y') -> acc && x' `eqUnsized` y') True (StrictSeq.zip x y)
        eqUnsized x y = sizedValue x == sizedValue y
  
  type instance MemoHashIndex BabbageTxBodyRaw = EraIndependentTxBody
  
  deriving instance Eq BabbageTxBodyRaw
  
  instance NoThunks BabbageTxBodyRaw
  
  instance NFData BabbageTxBodyRaw
  
  deriving instance Show BabbageTxBodyRaw
  
  deriving via Mem BabbageTxBodyRaw instance DecCBOR (Annotator (TxBody BabbageEra))
  
  instance Memoized (TxBody BabbageEra) where
    type RawType (TxBody BabbageEra) = BabbageTxBodyRaw
  
  deriving newtype instance NFData (TxBody BabbageEra)
  
  babbageSpendableInputsTxBodyF ::
    BabbageEraTxBody era => SimpleGetter (TxBody era) (Set TxIn)
  babbageSpendableInputsTxBodyF =
    to $ \txBody ->
      (txBody ^. inputsTxBodyL)
        `Set.union` (txBody ^. collateralInputsTxBodyL)
  {-# INLINEABLE babbageSpendableInputsTxBodyF #-}
  
  babbageAllInputsTxBodyF ::
    BabbageEraTxBody era => SimpleGetter (TxBody era) (Set TxIn)
  babbageAllInputsTxBodyF =
    to $ \txBody ->
      (txBody ^. inputsTxBodyL)
        `Set.union` (txBody ^. collateralInputsTxBodyL)
        `Set.union` (txBody ^. referenceInputsTxBodyL)
  {-# INLINEABLE babbageAllInputsTxBodyF #-}
  
  allSizedOutputsBabbageTxBodyF ::
    BabbageEraTxBody era =>
    SimpleGetter (TxBody era) (StrictSeq (Sized (TxOut era)))
  allSizedOutputsBabbageTxBodyF =
    to $ \txBody ->
      let txOuts = txBody ^. sizedOutputsTxBodyL
       in case txBody ^. sizedCollateralReturnTxBodyL of
            SNothing -> txOuts
            SJust collTxOut -> txOuts |> collTxOut
  {-# INLINEABLE allSizedOutputsBabbageTxBodyF #-}
  
  instance EraTxBody BabbageEra where
    newtype TxBody BabbageEra = MkBabbageTxBody (MemoBytes BabbageTxBodyRaw)
      deriving newtype (Generic, SafeToHash, ToCBOR)
  
    mkBasicTxBody = mkMemoizedEra @BabbageEra basicBabbageTxBodyRaw
  
    inputsTxBodyL =
      lensMemoRawType @BabbageEra btbrInputs $ \txBodyRaw inputs -> txBodyRaw {btbrInputs = inputs}
    {-# INLINE inputsTxBodyL #-}
  
    outputsTxBodyL =
      lensMemoRawType @BabbageEra (fmap sizedValue . btbrOutputs) $ \txBodyRaw outputs ->
        txBodyRaw {btbrOutputs = mkSized (eraProtVerLow @BabbageEra) <$> outputs}
    {-# INLINE outputsTxBodyL #-}
  
    feeTxBodyL =
      lensMemoRawType @BabbageEra btbrFee $ \txBodyRaw fee -> txBodyRaw {btbrFee = fee}
    {-# INLINE feeTxBodyL #-}
  
    auxDataHashTxBodyL =
      lensMemoRawType @BabbageEra btbrAuxDataHash $ \txBodyRaw auxDataHash ->
        txBodyRaw {btbrAuxDataHash = auxDataHash}
    {-# INLINE auxDataHashTxBodyL #-}
  
    spendableInputsTxBodyF = babbageSpendableInputsTxBodyF
    {-# INLINE spendableInputsTxBodyF #-}
  
    allInputsTxBodyF = babbageAllInputsTxBodyF
    {-# INLINE allInputsTxBodyF #-}
  
    withdrawalsTxBodyL =
      lensMemoRawType @BabbageEra btbrWithdrawals $
        \txBodyRaw withdrawals -> txBodyRaw {btbrWithdrawals = withdrawals}
    {-# INLINE withdrawalsTxBodyL #-}
  
    certsTxBodyL =
      lensMemoRawType @BabbageEra btbrCerts $ \txBodyRaw certs -> txBodyRaw {btbrCerts = certs}
    {-# INLINE certsTxBodyL #-}
  
    getGenesisKeyHashCountTxBody = getShelleyGenesisKeyHashCountTxBody
  
  instance ShelleyEraTxBody BabbageEra where
    ttlTxBodyL = notSupportedInThisEraL
    {-# INLINE ttlTxBodyL #-}
  
    updateTxBodyL =
      lensMemoRawType @BabbageEra btbrUpdate $ \txBodyRaw update -> txBodyRaw {btbrUpdate = update}
    {-# INLINE updateTxBodyL #-}
  
  instance AllegraEraTxBody BabbageEra where
    vldtTxBodyL =
      lensMemoRawType @BabbageEra btbrValidityInterval $ \txBodyRaw vldt ->
        txBodyRaw {btbrValidityInterval = vldt}
    {-# INLINE vldtTxBodyL #-}
  
  instance MaryEraTxBody BabbageEra where
    mintTxBodyL =
      lensMemoRawType @BabbageEra btbrMint $ \txBodyRaw mint -> txBodyRaw {btbrMint = mint}
    {-# INLINE mintTxBodyL #-}
  
    mintedTxBodyF = to (policies . btbrMint . getMemoRawType)
    {-# INLINE mintedTxBodyF #-}
  
  instance AlonzoEraTxBody BabbageEra where
    collateralInputsTxBodyL =
      lensMemoRawType @BabbageEra btbrCollateralInputs $ \txBodyRaw collateral ->
        txBodyRaw {btbrCollateralInputs = collateral}
    {-# INLINE collateralInputsTxBodyL #-}
  
    reqSignerHashesTxBodyL =
      lensMemoRawType @BabbageEra btbrReqSignerHashes $ \txBodyRaw reqSignerHashes ->
        txBodyRaw {btbrReqSignerHashes = reqSignerHashes}
    {-# INLINE reqSignerHashesTxBodyL #-}
  
    scriptIntegrityHashTxBodyL =
      lensMemoRawType @BabbageEra btbrScriptIntegrityHash $ \txBodyRaw scriptIntegrityHash ->
        txBodyRaw {btbrScriptIntegrityHash = scriptIntegrityHash}
    {-# INLINE scriptIntegrityHashTxBodyL #-}
  
    networkIdTxBodyL = lensMemoRawType @BabbageEra btbrNetworkId $ \txBodyRaw networkId ->
      txBodyRaw {btbrNetworkId = networkId}
    {-# INLINE networkIdTxBodyL #-}
  
    redeemerPointer = alonzoRedeemerPointer
  
    redeemerPointerInverse = alonzoRedeemerPointerInverse
  
  instance BabbageEraTxBody BabbageEra where
    sizedOutputsTxBodyL =
      lensMemoRawType @BabbageEra btbrOutputs $ \txBodyRaw outputs -> txBodyRaw {btbrOutputs = outputs}
    {-# INLINE sizedOutputsTxBodyL #-}
  
    referenceInputsTxBodyL =
      lensMemoRawType @BabbageEra btbrReferenceInputs $ \txBodyRaw reference ->
        txBodyRaw {btbrReferenceInputs = reference}
    {-# INLINE referenceInputsTxBodyL #-}
  
    totalCollateralTxBodyL =
      lensMemoRawType @BabbageEra btbrTotalCollateral $ \txBodyRaw totalCollateral ->
        txBodyRaw {btbrTotalCollateral = totalCollateral}
    {-# INLINE totalCollateralTxBodyL #-}
  
    collateralReturnTxBodyL =
      lensMemoRawType @BabbageEra (fmap sizedValue . btbrCollateralReturn) $
        \txBodyRaw collateralReturn ->
          txBodyRaw {btbrCollateralReturn = mkSized (eraProtVerLow @BabbageEra) <$> collateralReturn}
    {-# INLINE collateralReturnTxBodyL #-}
  
    sizedCollateralReturnTxBodyL =
      lensMemoRawType @BabbageEra btbrCollateralReturn $ \txBodyRaw collateralReturn ->
        txBodyRaw {btbrCollateralReturn = collateralReturn}
    {-# INLINE sizedCollateralReturnTxBodyL #-}
  
    allSizedOutputsTxBodyF = allSizedOutputsBabbageTxBodyF
    {-# INLINE allSizedOutputsTxBodyF #-}
  
  instance EqRaw (TxBody BabbageEra) where
    eqRaw = zipMemoRawType eqRaw
  
  deriving newtype instance Eq (TxBody BabbageEra)
  
  deriving instance NoThunks (TxBody BabbageEra)
  
  deriving instance Show (TxBody BabbageEra)
  
  pattern BabbageTxBody ::
    Set TxIn ->
    Set TxIn ->
    Set TxIn ->
    StrictSeq (Sized (TxOut BabbageEra)) ->
    StrictMaybe (Sized (TxOut BabbageEra)) ->
    StrictMaybe Coin ->
    StrictSeq (TxCert BabbageEra) ->
    Withdrawals ->
    Coin ->
    ValidityInterval ->
    StrictMaybe (Update BabbageEra) ->
    Set (KeyHash 'Witness) ->
    MultiAsset ->
    StrictMaybe ScriptIntegrityHash ->
    StrictMaybe TxAuxDataHash ->
    StrictMaybe Network ->
    TxBody BabbageEra
  pattern BabbageTxBody
    { btbInputs
    , btbCollateral
    , btbReferenceInputs
    , btbOutputs
    , btbCollateralReturn
    , btbTotalCollateral
    , btbCerts
    , btbWithdrawals
    , btbTxFee
    , btbValidityInterval
    , btbUpdate
    , btbReqSignerHashes
    , btbMint
    , btbScriptIntegrityHash
    , btbAuxDataHash
    , btbTxNetworkId
    } <-
    ( getMemoRawType ->
        BabbageTxBodyRaw
          { btbrInputs = btbInputs
          , btbrCollateralInputs = btbCollateral
          , btbrReferenceInputs = btbReferenceInputs
          , btbrOutputs = btbOutputs
          , btbrCollateralReturn = btbCollateralReturn
          , btbrTotalCollateral = btbTotalCollateral
          , btbrCerts = btbCerts
          , btbrWithdrawals = btbWithdrawals
          , btbrFee = btbTxFee
          , btbrValidityInterval = btbValidityInterval
          , btbrUpdate = btbUpdate
          , btbrReqSignerHashes = btbReqSignerHashes
          , btbrMint = btbMint
          , btbrScriptIntegrityHash = btbScriptIntegrityHash
          , btbrAuxDataHash = btbAuxDataHash
          , btbrNetworkId = btbTxNetworkId
          }
      )
    where
      BabbageTxBody
        inputs
        collateral
        referenceInputs
        outputs
        collateralReturn
        totalCollateral
        certs
        withdrawals
        txFee
        validityInterval
        update
        reqSignerHashes
        mint
        scriptIntegrityHash
        auxDataHash
        txNetworkId =
          mkMemoizedEra @BabbageEra $
            BabbageTxBodyRaw
              { btbrInputs = inputs
              , btbrCollateralInputs = collateral
              , btbrReferenceInputs = referenceInputs
              , btbrOutputs = outputs
              , btbrCollateralReturn = collateralReturn
              , btbrTotalCollateral = totalCollateral
              , btbrCerts = certs
              , btbrWithdrawals = withdrawals
              , btbrFee = txFee
              , btbrValidityInterval = validityInterval
              , btbrUpdate = update
              , btbrReqSignerHashes = reqSignerHashes
              , btbrMint = mint
              , btbrScriptIntegrityHash = scriptIntegrityHash
              , btbrAuxDataHash = auxDataHash
              , btbrNetworkId = txNetworkId
              }
  
  {-# COMPLETE BabbageTxBody #-}
  
  instance HashAnnotated (TxBody BabbageEra) EraIndependentTxBody where
    hashAnnotated = getMemoSafeHash
  
  -- ==============================================================================
  -- We define these accessor functions manually, because if we define them using
  -- the record syntax in the TxBody pattern, they inherit the (BabbageBody era)
  -- constraint as a precondition. This is unnecessary, as one can see below
  -- they need not be constrained at all. This should be fixed in the GHC compiler.
  
  spendInputs' :: TxBody BabbageEra -> Set TxIn
  collateralInputs' :: TxBody BabbageEra -> Set TxIn
  referenceInputs' :: TxBody BabbageEra -> Set TxIn
  outputs' :: TxBody BabbageEra -> StrictSeq (TxOut BabbageEra)
  collateralReturn' :: TxBody BabbageEra -> StrictMaybe (TxOut BabbageEra)
  totalCollateral' :: TxBody BabbageEra -> StrictMaybe Coin
  certs' :: TxBody BabbageEra -> StrictSeq (TxCert BabbageEra)
  txfee' :: TxBody BabbageEra -> Coin
  withdrawals' :: TxBody BabbageEra -> Withdrawals
  vldt' :: TxBody BabbageEra -> ValidityInterval
  update' :: TxBody BabbageEra -> StrictMaybe (Update BabbageEra)
  reqSignerHashes' :: TxBody BabbageEra -> Set (KeyHash 'Witness)
  adHash' :: TxBody BabbageEra -> StrictMaybe TxAuxDataHash
  mint' :: TxBody BabbageEra -> MultiAsset
  scriptIntegrityHash' :: TxBody BabbageEra -> StrictMaybe ScriptIntegrityHash
  txnetworkid' :: TxBody BabbageEra -> StrictMaybe Network
  spendInputs' = btbrInputs . getMemoRawType
  {-# DEPRECATED spendInputs' "In favor of `inputsTxBodyL`" #-}
  
  collateralInputs' = btbrCollateralInputs . getMemoRawType
  {-# DEPRECATED collateralInputs' "In favor of `collateralInputsTxBodyL`" #-}
  
  referenceInputs' = btbrReferenceInputs . getMemoRawType
  {-# DEPRECATED referenceInputs' "In favor of `referenceInputsTxBodyL`" #-}
  
  outputs' = fmap sizedValue . btbrOutputs . getMemoRawType
  {-# DEPRECATED outputs' "In favor of `outputsTxBodyL`" #-}
  
  collateralReturn' = fmap sizedValue . btbrCollateralReturn . getMemoRawType
  {-# DEPRECATED collateralReturn' "In favor of `collateralReturnTxBodyL`" #-}
  
  totalCollateral' = btbrTotalCollateral . getMemoRawType
  {-# DEPRECATED totalCollateral' "In favor of `totalCollateralTxBodyL`" #-}
  
  certs' = btbrCerts . getMemoRawType
  {-# DEPRECATED certs' "In favor of `certsTxBodyL`" #-}
  
  withdrawals' = btbrWithdrawals . getMemoRawType
  {-# DEPRECATED withdrawals' "In favor of `withdrawalsTxBodyL`" #-}
  
  txfee' = btbrFee . getMemoRawType
  {-# DEPRECATED txfee' "In favor of `feeTxBodyL`" #-}
  
  vldt' = btbrValidityInterval . getMemoRawType
  {-# DEPRECATED vldt' "In favor of `vldtTxBodyL`" #-}
  
  update' = btbrUpdate . getMemoRawType
  {-# DEPRECATED update' "In favor of `updateTxBodyL`" #-}
  
  reqSignerHashes' = btbrReqSignerHashes . getMemoRawType
  {-# DEPRECATED reqSignerHashes' "In favor of `reqSignerHashesTxBodyL`" #-}
  
  adHash' = btbrAuxDataHash . getMemoRawType
  {-# DEPRECATED adHash' "In favor of `auxDataHashTxBodyL`" #-}
  
  mint' = btbrMint . getMemoRawType
  {-# DEPRECATED mint' "In favor of `mintTxBodyL`" #-}
  
  scriptIntegrityHash' = btbrScriptIntegrityHash . getMemoRawType
  {-# DEPRECATED scriptIntegrityHash' "In favor of `scriptIntegrityHashTxBodyL`" #-}
  
  txnetworkid' = btbrNetworkId . getMemoRawType
  {-# DEPRECATED txnetworkid' "In favor of `networkIdTxBodyL`" #-}
  
  --------------------------------------------------------------------------------
  -- Serialisation
  --------------------------------------------------------------------------------
  
  -- | Encodes memoized bytes created upon construction.
  instance EncCBOR (TxBody BabbageEra)
  
  instance EncCBOR BabbageTxBodyRaw where
    encCBOR
      BabbageTxBodyRaw
        { btbrInputs
        , btbrCollateralInputs
        , btbrReferenceInputs
        , btbrOutputs
        , btbrCollateralReturn
        , btbrTotalCollateral
        , btbrCerts
        , btbrWithdrawals
        , btbrFee
        , btbrValidityInterval = ValidityInterval bot top
        , btbrUpdate
        , btbrReqSignerHashes
        , btbrMint
        , btbrScriptIntegrityHash
        , btbrAuxDataHash
        , btbrNetworkId
        } =
        encode $
          Keyed
            ( \i ifee ri o cr tc f t c w u b rsh mi sh ah ni ->
                BabbageTxBodyRaw i ifee ri o cr tc c w f (ValidityInterval b t) u rsh mi sh ah ni
            )
            !> Key 0 (To btbrInputs)
            !> Omit null (Key 13 (To btbrCollateralInputs))
            !> Omit null (Key 18 (To btbrReferenceInputs))
            !> Key 1 (To btbrOutputs)
            !> encodeKeyedStrictMaybe 16 btbrCollateralReturn
            !> encodeKeyedStrictMaybe 17 btbrTotalCollateral
            !> Key 2 (To btbrFee)
            !> encodeKeyedStrictMaybe 3 top
            !> Omit null (Key 4 (To btbrCerts))
            !> Omit (null . unWithdrawals) (Key 5 (To btbrWithdrawals))
            !> encodeKeyedStrictMaybe 6 btbrUpdate
            !> encodeKeyedStrictMaybe 8 bot
            !> Omit null (Key 14 (To btbrReqSignerHashes))
            !> Omit (== mempty) (Key 9 (To btbrMint))
            !> encodeKeyedStrictMaybe 11 btbrScriptIntegrityHash
            !> encodeKeyedStrictMaybe 7 btbrAuxDataHash
            !> encodeKeyedStrictMaybe 15 btbrNetworkId
  
  instance DecCBOR BabbageTxBodyRaw where
    decCBOR =
      decode $
        SparseKeyed
          "BabbageTxBodyRaw"
          basicBabbageTxBodyRaw
          bodyFields
          requiredFields
      where
        bodyFields :: Word -> Field BabbageTxBodyRaw
        bodyFields 0 = field (\x tx -> tx {btbrInputs = x}) From
        bodyFields 13 = field (\x tx -> tx {btbrCollateralInputs = x}) From
        bodyFields 18 = field (\x tx -> tx {btbrReferenceInputs = x}) From
        bodyFields 1 = field (\x tx -> tx {btbrOutputs = x}) From
        bodyFields 16 = ofield (\x tx -> tx {btbrCollateralReturn = x}) From
        bodyFields 17 = ofield (\x tx -> tx {btbrTotalCollateral = x}) From
        bodyFields 2 = field (\x tx -> tx {btbrFee = x}) From
        bodyFields 3 =
          ofield
            (\x tx -> tx {btbrValidityInterval = (btbrValidityInterval tx) {invalidHereafter = x}})
            From
        bodyFields 4 = field (\x tx -> tx {btbrCerts = x}) From
        bodyFields 5 = field (\x tx -> tx {btbrWithdrawals = x}) From
        bodyFields 6 = ofield (\x tx -> tx {btbrUpdate = x}) From
        bodyFields 7 = ofield (\x tx -> tx {btbrAuxDataHash = x}) From
        bodyFields 8 =
          ofield
            (\x tx -> tx {btbrValidityInterval = (btbrValidityInterval tx) {invalidBefore = x}})
            From
        bodyFields 9 = field (\x tx -> tx {btbrMint = x}) From
        bodyFields 11 = ofield (\x tx -> tx {btbrScriptIntegrityHash = x}) From
        bodyFields 14 = field (\x tx -> tx {btbrReqSignerHashes = x}) From
        bodyFields 15 = ofield (\x tx -> tx {btbrNetworkId = x}) From
        bodyFields n = invalidField n
        {-# INLINE bodyFields #-}
        requiredFields :: [(Word, String)]
        requiredFields =
          [ (0, "inputs")
          , (1, "outputs")
          , (2, "fee")
          ]
    {-# INLINE decCBOR #-}
  
  instance DecCBOR (Annotator BabbageTxBodyRaw) where
    decCBOR = pure <$> decCBOR
  
  basicBabbageTxBodyRaw :: BabbageTxBodyRaw
  basicBabbageTxBodyRaw =
    BabbageTxBodyRaw
      mempty
      mempty
      mempty
      StrictSeq.empty
      SNothing
      SNothing
      StrictSeq.empty
      (Withdrawals mempty)
      mempty
      (ValidityInterval SNothing SNothing)
      SNothing
      mempty
      mempty
      SNothing
      SNothing
      SNothing
  