{-# LANGUAGE DataKinds         #-}
{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE NamedFieldPuns    #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes        #-}
{-# LANGUAGE TypeApplications  #-}

module Cardano.Chain.UTxO.Validation
  ( validateTx
  , validateTxAux
  , updateUTxO
  , updateUTxOTxWitness
  , updateUTxOTx
  , TxValidationError (..)
  , Environment(..)
  , UTxOValidationError (..)
  )
where

import Cardano.Prelude

import qualified Data.ByteString as BS
import qualified Data.List.NonEmpty as NE
import qualified Data.Set as S
import qualified Data.Vector as V

import Cardano.Binary
  ( Annotated(..)
  , Decoder
  , DecoderError(DecoderErrorUnknownTag)
  , FromCBOR(..)
  , ToCBOR(..)
  , decodeListLen
  , decodeWord8
  , encodeListLen
  , enforceSize
  , matchSize
  )
import Cardano.Chain.Common
  ( Address(..)
  , Lovelace
  , LovelaceError
  , NetworkMagic
  , TxFeePolicy(..)
  , addrNetworkMagic
  , calculateTxSizeLinear
  , checkVerKeyAddress
  , checkRedeemAddress
  , makeNetworkMagic
  , mkKnownLovelace
  , subLovelace
  , unknownAttributesLength
  )
import Cardano.Chain.UTxO.Tx (Tx(..), TxIn, TxOut(..))
import Cardano.Chain.UTxO.Compact (CompactTxOut(..), toCompactTxIn)
import Cardano.Chain.UTxO.TxAux (ATxAux(..), aTaTx, taWitness)
import Cardano.Chain.UTxO.TxWitness
  (TxInWitness(..), TxSigData(..), recoverSigData)
import Cardano.Chain.UTxO.UTxO
  (UTxO, UTxOError, balance, isRedeemUTxO, txOutputUTxO, (</|), (<|))
import qualified Cardano.Chain.UTxO.UTxO as UTxO
import Cardano.Chain.Update (ProtocolParameters(..))
import Cardano.Chain.UTxO.UTxOConfiguration
import Cardano.Chain.ValidationMode
  ( ValidationMode
  , whenTxValidation
  , unlessNoTxValidation
  , wrapErrorWithValidationMode
  )
import Cardano.Crypto
  ( AProtocolMagic(..)
  , ProtocolMagicId
  , SignTag(..)
  , verifySignatureDecoded
  , verifyRedeemSigDecoded
  )

-- | A representation of all the ways a transaction might be invalid
data TxValidationError
  = TxValidationLovelaceError Text LovelaceError
  | TxValidationFeeTooSmall Tx Lovelace Lovelace
  | TxValidationWitnessWrongSignature TxInWitness ProtocolMagicId TxSigData
  | TxValidationWitnessWrongKey TxInWitness Address
  | TxValidationMissingInput TxIn
  | TxValidationNetworkMagicMismatch NetworkMagic NetworkMagic
  -- ^ Fields are <expected> <actual>
  | TxValidationTxTooLarge Natural Natural
  | TxValidationUnknownAddressAttributes
  | TxValidationUnknownAttributes
  deriving (TxValidationError -> TxValidationError -> Bool
(TxValidationError -> TxValidationError -> Bool)
-> (TxValidationError -> TxValidationError -> Bool)
-> Eq TxValidationError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TxValidationError -> TxValidationError -> Bool
$c/= :: TxValidationError -> TxValidationError -> Bool
== :: TxValidationError -> TxValidationError -> Bool
$c== :: TxValidationError -> TxValidationError -> Bool
Eq, Int -> TxValidationError -> ShowS
[TxValidationError] -> ShowS
TxValidationError -> String
(Int -> TxValidationError -> ShowS)
-> (TxValidationError -> String)
-> ([TxValidationError] -> ShowS)
-> Show TxValidationError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TxValidationError] -> ShowS
$cshowList :: [TxValidationError] -> ShowS
show :: TxValidationError -> String
$cshow :: TxValidationError -> String
showsPrec :: Int -> TxValidationError -> ShowS
$cshowsPrec :: Int -> TxValidationError -> ShowS
Show)

instance ToCBOR TxValidationError where
  toCBOR :: TxValidationError -> Encoding
toCBOR = \case
    TxValidationLovelaceError Text
text LovelaceError
loveLaceError ->
      Word -> Encoding
encodeListLen Word
3
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word8 -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR @Word8 Word8
0
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Text -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR Text
text
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> LovelaceError -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR LovelaceError
loveLaceError
    TxValidationFeeTooSmall Tx
tx Lovelace
lovelace1 Lovelace
lovelace2 ->
      Word -> Encoding
encodeListLen Word
4
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word8 -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR @Word8 Word8
1
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Tx -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR Tx
tx
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Lovelace -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR Lovelace
lovelace1
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Lovelace -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR Lovelace
lovelace2
    TxValidationWitnessWrongSignature TxInWitness
txInWitness ProtocolMagicId
pmi TxSigData
sigData ->
      Word -> Encoding
encodeListLen Word
4
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word8 -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR @Word8 Word8
2
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> TxInWitness -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR TxInWitness
txInWitness
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> ProtocolMagicId -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR ProtocolMagicId
pmi
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> TxSigData -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR TxSigData
sigData
    TxValidationWitnessWrongKey TxInWitness
txInWitness Address
addr  ->
      Word -> Encoding
encodeListLen Word
3
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word8 -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR @Word8 Word8
3
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> TxInWitness -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR TxInWitness
txInWitness
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Address -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR Address
addr
    TxValidationMissingInput TxIn
txIn ->
      Word -> Encoding
encodeListLen Word
2
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word8 -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR @Word8 Word8
4
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> TxIn -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR TxIn
txIn
    TxValidationNetworkMagicMismatch NetworkMagic
networkMagic1 NetworkMagic
networkMagic2 ->
      Word -> Encoding
encodeListLen Word
3
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word8 -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR @Word8 Word8
5
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> NetworkMagic -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR NetworkMagic
networkMagic1
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> NetworkMagic -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR NetworkMagic
networkMagic2
    TxValidationTxTooLarge Natural
nat1 Natural
nat2 ->
      Word -> Encoding
encodeListLen Word
3
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word8 -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR @Word8 Word8
6
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Natural -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR Natural
nat1
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Natural -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR Natural
nat2
    TxValidationError
TxValidationUnknownAddressAttributes ->
      Word -> Encoding
encodeListLen Word
1
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word8 -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR @Word8 Word8
7
    TxValidationError
TxValidationUnknownAttributes ->
      Word -> Encoding
encodeListLen Word
1
        Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word8 -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR @Word8 Word8
8

instance FromCBOR TxValidationError where
  fromCBOR :: Decoder s TxValidationError
fromCBOR = do
    Int
len <- Decoder s Int
forall s. Decoder s Int
decodeListLen
    let checkSize :: forall s. Int -> Decoder s ()
        checkSize :: Int -> Decoder s ()
checkSize Int
size = Text -> Int -> Int -> Decoder s ()
forall s. Text -> Int -> Int -> Decoder s ()
matchSize Text
"TxValidationError" Int
size Int
len
    Word8
tag <- Decoder s Word8
forall s. Decoder s Word8
decodeWord8
    case Word8
tag of
      Word8
0 -> Int -> Decoder s ()
forall s. Int -> Decoder s ()
checkSize Int
3 Decoder s ()
-> Decoder s TxValidationError -> Decoder s TxValidationError
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> LovelaceError -> TxValidationError
TxValidationLovelaceError (Text -> LovelaceError -> TxValidationError)
-> Decoder s Text -> Decoder s (LovelaceError -> TxValidationError)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s Text
forall a s. FromCBOR a => Decoder s a
fromCBOR Decoder s (LovelaceError -> TxValidationError)
-> Decoder s LovelaceError -> Decoder s TxValidationError
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Decoder s LovelaceError
forall a s. FromCBOR a => Decoder s a
fromCBOR
      Word8
1 -> Int -> Decoder s ()
forall s. Int -> Decoder s ()
checkSize Int
4 Decoder s ()
-> Decoder s TxValidationError -> Decoder s TxValidationError
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Tx -> Lovelace -> Lovelace -> TxValidationError
TxValidationFeeTooSmall   (Tx -> Lovelace -> Lovelace -> TxValidationError)
-> Decoder s Tx
-> Decoder s (Lovelace -> Lovelace -> TxValidationError)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s Tx
forall a s. FromCBOR a => Decoder s a
fromCBOR Decoder s (Lovelace -> Lovelace -> TxValidationError)
-> Decoder s Lovelace -> Decoder s (Lovelace -> TxValidationError)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Decoder s Lovelace
forall a s. FromCBOR a => Decoder s a
fromCBOR Decoder s (Lovelace -> TxValidationError)
-> Decoder s Lovelace -> Decoder s TxValidationError
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Decoder s Lovelace
forall a s. FromCBOR a => Decoder s a
fromCBOR
      Word8
2 -> Int -> Decoder s ()
forall s. Int -> Decoder s ()
checkSize Int
4 Decoder s ()
-> Decoder s TxValidationError -> Decoder s TxValidationError
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> TxInWitness -> ProtocolMagicId -> TxSigData -> TxValidationError
TxValidationWitnessWrongSignature (TxInWitness -> ProtocolMagicId -> TxSigData -> TxValidationError)
-> Decoder s TxInWitness
-> Decoder s (ProtocolMagicId -> TxSigData -> TxValidationError)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s TxInWitness
forall a s. FromCBOR a => Decoder s a
fromCBOR Decoder s (ProtocolMagicId -> TxSigData -> TxValidationError)
-> Decoder s ProtocolMagicId
-> Decoder s (TxSigData -> TxValidationError)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Decoder s ProtocolMagicId
forall a s. FromCBOR a => Decoder s a
fromCBOR Decoder s (TxSigData -> TxValidationError)
-> Decoder s TxSigData -> Decoder s TxValidationError
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Decoder s TxSigData
forall a s. FromCBOR a => Decoder s a
fromCBOR
      Word8
3 -> Int -> Decoder s ()
forall s. Int -> Decoder s ()
checkSize Int
3 Decoder s ()
-> Decoder s TxValidationError -> Decoder s TxValidationError
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> TxInWitness -> Address -> TxValidationError
TxValidationWitnessWrongKey (TxInWitness -> Address -> TxValidationError)
-> Decoder s TxInWitness
-> Decoder s (Address -> TxValidationError)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s TxInWitness
forall a s. FromCBOR a => Decoder s a
fromCBOR Decoder s (Address -> TxValidationError)
-> Decoder s Address -> Decoder s TxValidationError
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Decoder s Address
forall a s. FromCBOR a => Decoder s a
fromCBOR
      Word8
4 -> Int -> Decoder s ()
forall s. Int -> Decoder s ()
checkSize Int
2 Decoder s ()
-> Decoder s TxValidationError -> Decoder s TxValidationError
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> TxIn -> TxValidationError
TxValidationMissingInput (TxIn -> TxValidationError)
-> Decoder s TxIn -> Decoder s TxValidationError
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s TxIn
forall a s. FromCBOR a => Decoder s a
fromCBOR
      Word8
5 -> Int -> Decoder s ()
forall s. Int -> Decoder s ()
checkSize Int
3 Decoder s ()
-> Decoder s TxValidationError -> Decoder s TxValidationError
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> NetworkMagic -> NetworkMagic -> TxValidationError
TxValidationNetworkMagicMismatch (NetworkMagic -> NetworkMagic -> TxValidationError)
-> Decoder s NetworkMagic
-> Decoder s (NetworkMagic -> TxValidationError)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s NetworkMagic
forall a s. FromCBOR a => Decoder s a
fromCBOR Decoder s (NetworkMagic -> TxValidationError)
-> Decoder s NetworkMagic -> Decoder s TxValidationError
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Decoder s NetworkMagic
forall a s. FromCBOR a => Decoder s a
fromCBOR
      Word8
6 -> Int -> Decoder s ()
forall s. Int -> Decoder s ()
checkSize Int
3 Decoder s ()
-> Decoder s TxValidationError -> Decoder s TxValidationError
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Natural -> Natural -> TxValidationError
TxValidationTxTooLarge (Natural -> Natural -> TxValidationError)
-> Decoder s Natural -> Decoder s (Natural -> TxValidationError)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s Natural
forall a s. FromCBOR a => Decoder s a
fromCBOR Decoder s (Natural -> TxValidationError)
-> Decoder s Natural -> Decoder s TxValidationError
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Decoder s Natural
forall a s. FromCBOR a => Decoder s a
fromCBOR
      Word8
7 -> Int -> Decoder s ()
forall s. Int -> Decoder s ()
checkSize Int
1 Decoder s () -> TxValidationError -> Decoder s TxValidationError
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> TxValidationError
TxValidationUnknownAddressAttributes
      Word8
8 -> Int -> Decoder s ()
forall s. Int -> Decoder s ()
checkSize Int
1 Decoder s () -> TxValidationError -> Decoder s TxValidationError
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> TxValidationError
TxValidationUnknownAttributes
      Word8
_ -> DecoderError -> Decoder s TxValidationError
forall e s a. Buildable e => e -> Decoder s a
cborError   (DecoderError -> Decoder s TxValidationError)
-> DecoderError -> Decoder s TxValidationError
forall a b. (a -> b) -> a -> b
$  Text -> Word8 -> DecoderError
DecoderErrorUnknownTag Text
"TxValidationError" Word8
tag

-- | Validate that:
--
--   1. The fee for a transaction is not less than the minimum fee.
--   2. The size of the transaction is below the maximum size.
--   3. Output balance + fee = input balance
--
--   The transaction size must be calculated _including the witnesses_. As such
--   this cannot be part of 'validateTx'. We actually assume 3 by calculating
--   the fee as output balance - input balance.
validateTxAux
  :: MonadError TxValidationError m
  => Environment
  -> UTxO
  -> ATxAux ByteString
  -> m ()
validateTxAux :: Environment -> UTxO -> ATxAux ByteString -> m ()
validateTxAux Environment
env UTxO
utxo (ATxAux (Annotated Tx
tx ByteString
_) Annotated TxWitness ByteString
_ ByteString
txBytes) = do

    -- Check that the size of the transaction is less than the maximum
    Natural
txSize Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
<= Natural
maxTxSize
      Bool -> TxValidationError -> m ()
forall e (m :: * -> *). MonadError e m => Bool -> e -> m ()
`orThrowError` Natural -> Natural -> TxValidationError
TxValidationTxTooLarge Natural
txSize Natural
maxTxSize

    -- Calculate the minimum fee from the 'TxFeePolicy'
    Lovelace
minFee <- if UTxO -> Bool
isRedeemUTxO UTxO
inputUTxO
      then Lovelace -> m Lovelace
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Lovelace -> m Lovelace) -> Lovelace -> m Lovelace
forall a b. (a -> b) -> a -> b
$ (KnownNat 0, 0 <= 45000000000000000) => Lovelace
forall (n :: Nat). (KnownNat n, n <= 45000000000000000) => Lovelace
mkKnownLovelace @0
      else TxFeePolicy -> m Lovelace
forall (m :: * -> *).
MonadError TxValidationError m =>
TxFeePolicy -> m Lovelace
calculateMinimumFee TxFeePolicy
feePolicy

    -- Calculate the balance of the output 'UTxO'
    Lovelace
balanceOut <- UTxO -> Either LovelaceError Lovelace
balance (Tx -> UTxO
txOutputUTxO Tx
tx)
      Either LovelaceError Lovelace
-> (LovelaceError -> TxValidationError) -> m Lovelace
forall e' (m :: * -> *) e a.
MonadError e' m =>
Either e a -> (e -> e') -> m a
`wrapError` Text -> LovelaceError -> TxValidationError
TxValidationLovelaceError Text
"Output Balance"

    -- Calculate the balance of the restricted input 'UTxO'
    Lovelace
balanceIn <- UTxO -> Either LovelaceError Lovelace
balance UTxO
inputUTxO
      Either LovelaceError Lovelace
-> (LovelaceError -> TxValidationError) -> m Lovelace
forall e' (m :: * -> *) e a.
MonadError e' m =>
Either e a -> (e -> e') -> m a
`wrapError` Text -> LovelaceError -> TxValidationError
TxValidationLovelaceError Text
"Input Balance"

    -- Calculate the 'fee' as the difference of the balances
    Lovelace
fee <- Lovelace -> Lovelace -> Either LovelaceError Lovelace
subLovelace Lovelace
balanceIn Lovelace
balanceOut
      Either LovelaceError Lovelace
-> (LovelaceError -> TxValidationError) -> m Lovelace
forall e' (m :: * -> *) e a.
MonadError e' m =>
Either e a -> (e -> e') -> m a
`wrapError` Text -> LovelaceError -> TxValidationError
TxValidationLovelaceError Text
"Fee"

    -- Check that the fee is greater than the minimum
    (Lovelace
minFee Lovelace -> Lovelace -> Bool
forall a. Ord a => a -> a -> Bool
<= Lovelace
fee) Bool -> TxValidationError -> m ()
forall e (m :: * -> *). MonadError e m => Bool -> e -> m ()
`orThrowError` Tx -> Lovelace -> Lovelace -> TxValidationError
TxValidationFeeTooSmall Tx
tx Lovelace
minFee Lovelace
fee

  where
    Environment { ProtocolParameters
protocolParameters :: Environment -> ProtocolParameters
protocolParameters :: ProtocolParameters
protocolParameters } = Environment
env

    maxTxSize :: Natural
maxTxSize = ProtocolParameters -> Natural
ppMaxTxSize ProtocolParameters
protocolParameters
    feePolicy :: TxFeePolicy
feePolicy = ProtocolParameters -> TxFeePolicy
ppTxFeePolicy ProtocolParameters
protocolParameters

    txSize :: Natural
    txSize :: Natural
txSize = Int -> Natural
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Natural) -> Int -> Natural
forall a b. (a -> b) -> a -> b
$ ByteString -> Int
BS.length ByteString
txBytes

    inputUTxO :: UTxO
inputUTxO = [TxIn] -> Set TxIn
forall a. Ord a => [a] -> Set a
S.fromList (NonEmpty TxIn -> [TxIn]
forall a. NonEmpty a -> [a]
NE.toList (Tx -> NonEmpty TxIn
txInputs Tx
tx)) Set TxIn -> UTxO -> UTxO
<| UTxO
utxo

    calculateMinimumFee
      :: MonadError TxValidationError m => TxFeePolicy -> m Lovelace
    calculateMinimumFee :: TxFeePolicy -> m Lovelace
calculateMinimumFee = \case

      TxFeePolicyTxSizeLinear TxSizeLinear
txSizeLinear ->
        TxSizeLinear -> Natural -> Either LovelaceError Lovelace
calculateTxSizeLinear TxSizeLinear
txSizeLinear Natural
txSize
          Either LovelaceError Lovelace
-> (LovelaceError -> TxValidationError) -> m Lovelace
forall e' (m :: * -> *) e a.
MonadError e' m =>
Either e a -> (e -> e') -> m a
`wrapError` Text -> LovelaceError -> TxValidationError
TxValidationLovelaceError Text
"Minimum Fee"

-- | Validate that:
--
--   1. All @TxIn@s are in domain of @Utxo@
--
--   These are the conditions of the UTxO inference rule in the spec.
validateTx
  :: MonadError TxValidationError m
  => Environment
  -> UTxO
  -> Annotated Tx ByteString
  -> m ()
validateTx :: Environment -> UTxO -> Annotated Tx ByteString -> m ()
validateTx Environment
env UTxO
utxo (Annotated Tx
tx ByteString
_) = do

  -- Check that the transaction attributes are less than the max size
  Attributes () -> Int
forall a. Attributes a -> Int
unknownAttributesLength (Tx -> Attributes ()
txAttributes Tx
tx) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
128
    Bool -> TxValidationError -> m ()
forall e (m :: * -> *). MonadError e m => Bool -> e -> m ()
`orThrowError` TxValidationError
TxValidationUnknownAttributes

  -- Check that outputs have valid NetworkMagic
  let nm :: NetworkMagic
nm = AProtocolMagic ByteString -> NetworkMagic
forall a. AProtocolMagic a -> NetworkMagic
makeNetworkMagic AProtocolMagic ByteString
protocolMagic
  Tx -> NonEmpty TxOut
txOutputs Tx
tx NonEmpty TxOut -> (TxOut -> m ()) -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
`forM_` NetworkMagic -> TxOut -> m ()
forall (m :: * -> *).
MonadError TxValidationError m =>
NetworkMagic -> TxOut -> m ()
validateTxOutNM NetworkMagic
nm

  -- Check that every input is in the domain of 'utxo'
  Tx -> NonEmpty TxIn
txInputs Tx
tx NonEmpty TxIn -> (TxIn -> m ()) -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
`forM_` UTxOConfiguration -> UTxO -> TxIn -> m ()
forall (m :: * -> *).
MonadError TxValidationError m =>
UTxOConfiguration -> UTxO -> TxIn -> m ()
validateTxIn UTxOConfiguration
utxoConfiguration UTxO
utxo

 where
  Environment { AProtocolMagic ByteString
protocolMagic :: Environment -> AProtocolMagic ByteString
protocolMagic :: AProtocolMagic ByteString
protocolMagic, UTxOConfiguration
utxoConfiguration :: Environment -> UTxOConfiguration
utxoConfiguration :: UTxOConfiguration
utxoConfiguration } = Environment
env

-- | Validate that 'TxIn' is in the domain of 'UTxO'
validateTxIn
  :: MonadError TxValidationError m
  => UTxOConfiguration
  -> UTxO
  -> TxIn
  -> m ()
validateTxIn :: UTxOConfiguration -> UTxO -> TxIn -> m ()
validateTxIn UTxOConfiguration{Set CompactAddress
tcAssetLockedSrcAddrs :: UTxOConfiguration -> Set CompactAddress
tcAssetLockedSrcAddrs :: Set CompactAddress
tcAssetLockedSrcAddrs} UTxO
utxo TxIn
txIn
  | Set CompactAddress -> Bool
forall a. Set a -> Bool
S.null Set CompactAddress
tcAssetLockedSrcAddrs
  , TxIn
txIn TxIn -> UTxO -> Bool
`UTxO.member` UTxO
utxo
  = () -> m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

  | Just CompactTxOut
txOut <- CompactTxIn -> UTxO -> Maybe CompactTxOut
UTxO.lookupCompact (TxIn -> CompactTxIn
toCompactTxIn TxIn
txIn) UTxO
utxo
  , let (CompactTxOut CompactAddress
txOutAddr Lovelace
_) = CompactTxOut
txOut
  , CompactAddress
txOutAddr CompactAddress -> Set CompactAddress -> Bool
forall a. Ord a => a -> Set a -> Bool
`S.notMember` Set CompactAddress
tcAssetLockedSrcAddrs
  = () -> m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

  | Bool
otherwise
  = TxValidationError -> m ()
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (TxValidationError -> m ()) -> TxValidationError -> m ()
forall a b. (a -> b) -> a -> b
$ TxIn -> TxValidationError
TxValidationMissingInput TxIn
txIn


-- | Validate the NetworkMagic of a TxOut
validateTxOutNM
  :: MonadError TxValidationError m
  => NetworkMagic
  -> TxOut
  -> m ()
validateTxOutNM :: NetworkMagic -> TxOut -> m ()
validateTxOutNM NetworkMagic
nm TxOut
txOut = do
  -- Make sure that the unknown attributes are less than the max size
  Attributes AddrAttributes -> Int
forall a. Attributes a -> Int
unknownAttributesLength (Address -> Attributes AddrAttributes
addrAttributes (TxOut -> Address
txOutAddress TxOut
txOut)) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
128
    Bool -> TxValidationError -> m ()
forall e (m :: * -> *). MonadError e m => Bool -> e -> m ()
`orThrowError` TxValidationError
TxValidationUnknownAddressAttributes

  -- Check that the network magic in the address matches the expected one
  (NetworkMagic
nm NetworkMagic -> NetworkMagic -> Bool
forall a. Eq a => a -> a -> Bool
== NetworkMagic
addrNm) Bool -> TxValidationError -> m ()
forall e (m :: * -> *). MonadError e m => Bool -> e -> m ()
`orThrowError` NetworkMagic -> NetworkMagic -> TxValidationError
TxValidationNetworkMagicMismatch NetworkMagic
nm NetworkMagic
addrNm
  where addrNm :: NetworkMagic
addrNm = Address -> NetworkMagic
addrNetworkMagic (Address -> NetworkMagic)
-> (TxOut -> Address) -> TxOut -> NetworkMagic
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. TxOut -> Address
txOutAddress (TxOut -> NetworkMagic) -> TxOut -> NetworkMagic
forall a b. (a -> b) -> a -> b
$ TxOut
txOut


-- | Verify that a 'TxInWitness' is a valid witness for the supplied 'TxSigData'
validateWitness
  :: MonadError TxValidationError m
  => Annotated ProtocolMagicId ByteString
  -> Annotated TxSigData ByteString
  -> Address
  -> TxInWitness
  -> m ()
validateWitness :: Annotated ProtocolMagicId ByteString
-> Annotated TxSigData ByteString -> Address -> TxInWitness -> m ()
validateWitness Annotated ProtocolMagicId ByteString
pmi Annotated TxSigData ByteString
sigData Address
addr TxInWitness
witness = case TxInWitness
witness of
  VKWitness VerificationKey
vk TxSig
sig -> do
    Annotated ProtocolMagicId ByteString
-> SignTag
-> VerificationKey
-> Annotated TxSigData ByteString
-> Signature (BaseType (Annotated TxSigData ByteString))
-> Bool
forall t.
Decoded t =>
Annotated ProtocolMagicId ByteString
-> SignTag
-> VerificationKey
-> t
-> Signature (BaseType t)
-> Bool
verifySignatureDecoded Annotated ProtocolMagicId ByteString
pmi SignTag
SignTx VerificationKey
vk Annotated TxSigData ByteString
sigData Signature (BaseType (Annotated TxSigData ByteString))
TxSig
sig
      Bool -> TxValidationError -> m ()
forall e (m :: * -> *). MonadError e m => Bool -> e -> m ()
`orThrowError` TxInWitness -> ProtocolMagicId -> TxSigData -> TxValidationError
TxValidationWitnessWrongSignature
      TxInWitness
witness (Annotated ProtocolMagicId ByteString -> ProtocolMagicId
forall b a. Annotated b a -> b
unAnnotated Annotated ProtocolMagicId ByteString
pmi) (Annotated TxSigData ByteString -> TxSigData
forall b a. Annotated b a -> b
unAnnotated Annotated TxSigData ByteString
sigData)
    VerificationKey -> Address -> Bool
checkVerKeyAddress VerificationKey
vk Address
addr
      Bool -> TxValidationError -> m ()
forall e (m :: * -> *). MonadError e m => Bool -> e -> m ()
`orThrowError` TxInWitness -> Address -> TxValidationError
TxValidationWitnessWrongKey
      TxInWitness
witness Address
addr

  RedeemWitness RedeemVerificationKey
vk RedeemSignature TxSigData
sig -> do
    Annotated ProtocolMagicId ByteString
-> SignTag
-> RedeemVerificationKey
-> Annotated TxSigData ByteString
-> RedeemSignature (BaseType (Annotated TxSigData ByteString))
-> Bool
forall t.
Decoded t =>
Annotated ProtocolMagicId ByteString
-> SignTag
-> RedeemVerificationKey
-> t
-> RedeemSignature (BaseType t)
-> Bool
verifyRedeemSigDecoded Annotated ProtocolMagicId ByteString
pmi SignTag
SignRedeemTx RedeemVerificationKey
vk Annotated TxSigData ByteString
sigData RedeemSignature (BaseType (Annotated TxSigData ByteString))
RedeemSignature TxSigData
sig
      Bool -> TxValidationError -> m ()
forall e (m :: * -> *). MonadError e m => Bool -> e -> m ()
`orThrowError` TxInWitness -> ProtocolMagicId -> TxSigData -> TxValidationError
TxValidationWitnessWrongSignature
      TxInWitness
witness (Annotated ProtocolMagicId ByteString -> ProtocolMagicId
forall b a. Annotated b a -> b
unAnnotated Annotated ProtocolMagicId ByteString
pmi) (Annotated TxSigData ByteString -> TxSigData
forall b a. Annotated b a -> b
unAnnotated Annotated TxSigData ByteString
sigData)
    RedeemVerificationKey -> Address -> Bool
checkRedeemAddress RedeemVerificationKey
vk Address
addr
      Bool -> TxValidationError -> m ()
forall e (m :: * -> *). MonadError e m => Bool -> e -> m ()
`orThrowError` TxInWitness -> Address -> TxValidationError
TxValidationWitnessWrongKey       TxInWitness
witness Address
addr

data Environment = Environment
  { Environment -> AProtocolMagic ByteString
protocolMagic      :: !(AProtocolMagic ByteString)
  , Environment -> ProtocolParameters
protocolParameters :: !ProtocolParameters
  , Environment -> UTxOConfiguration
utxoConfiguration  :: !UTxOConfiguration
  } deriving (Environment -> Environment -> Bool
(Environment -> Environment -> Bool)
-> (Environment -> Environment -> Bool) -> Eq Environment
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Environment -> Environment -> Bool
$c/= :: Environment -> Environment -> Bool
== :: Environment -> Environment -> Bool
$c== :: Environment -> Environment -> Bool
Eq, Int -> Environment -> ShowS
[Environment] -> ShowS
Environment -> String
(Int -> Environment -> ShowS)
-> (Environment -> String)
-> ([Environment] -> ShowS)
-> Show Environment
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Environment] -> ShowS
$cshowList :: [Environment] -> ShowS
show :: Environment -> String
$cshow :: Environment -> String
showsPrec :: Int -> Environment -> ShowS
$cshowsPrec :: Int -> Environment -> ShowS
Show)

data UTxOValidationError
  = UTxOValidationTxValidationError TxValidationError
  | UTxOValidationUTxOError UTxOError
  deriving (UTxOValidationError -> UTxOValidationError -> Bool
(UTxOValidationError -> UTxOValidationError -> Bool)
-> (UTxOValidationError -> UTxOValidationError -> Bool)
-> Eq UTxOValidationError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UTxOValidationError -> UTxOValidationError -> Bool
$c/= :: UTxOValidationError -> UTxOValidationError -> Bool
== :: UTxOValidationError -> UTxOValidationError -> Bool
$c== :: UTxOValidationError -> UTxOValidationError -> Bool
Eq, Int -> UTxOValidationError -> ShowS
[UTxOValidationError] -> ShowS
UTxOValidationError -> String
(Int -> UTxOValidationError -> ShowS)
-> (UTxOValidationError -> String)
-> ([UTxOValidationError] -> ShowS)
-> Show UTxOValidationError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UTxOValidationError] -> ShowS
$cshowList :: [UTxOValidationError] -> ShowS
show :: UTxOValidationError -> String
$cshow :: UTxOValidationError -> String
showsPrec :: Int -> UTxOValidationError -> ShowS
$cshowsPrec :: Int -> UTxOValidationError -> ShowS
Show)

instance ToCBOR UTxOValidationError where
  toCBOR :: UTxOValidationError -> Encoding
toCBOR = \case
    UTxOValidationTxValidationError TxValidationError
txValidationError ->
      Word -> Encoding
encodeListLen Word
2 Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word8 -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR @Word8 Word8
0 Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> TxValidationError -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR TxValidationError
txValidationError
    UTxOValidationUTxOError UTxOError
uTxOError ->
      Word -> Encoding
encodeListLen Word
2 Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Word8 -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR @Word8 Word8
1 Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> UTxOError -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR UTxOError
uTxOError

instance FromCBOR UTxOValidationError where
  fromCBOR :: Decoder s UTxOValidationError
fromCBOR = do
    Text -> Int -> Decoder s ()
forall s. Text -> Int -> Decoder s ()
enforceSize Text
"UTxOValidationError" Int
2
    Decoder s Word8
forall s. Decoder s Word8
decodeWord8 Decoder s Word8
-> (Word8 -> Decoder s UTxOValidationError)
-> Decoder s UTxOValidationError
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Word8
0   -> TxValidationError -> UTxOValidationError
UTxOValidationTxValidationError (TxValidationError -> UTxOValidationError)
-> Decoder s TxValidationError -> Decoder s UTxOValidationError
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s TxValidationError
forall a s. FromCBOR a => Decoder s a
fromCBOR
      Word8
1   -> UTxOError -> UTxOValidationError
UTxOValidationUTxOError (UTxOError -> UTxOValidationError)
-> Decoder s UTxOError -> Decoder s UTxOValidationError
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s UTxOError
forall a s. FromCBOR a => Decoder s a
fromCBOR
      Word8
tag -> DecoderError -> Decoder s UTxOValidationError
forall e s a. Buildable e => e -> Decoder s a
cborError (DecoderError -> Decoder s UTxOValidationError)
-> DecoderError -> Decoder s UTxOValidationError
forall a b. (a -> b) -> a -> b
$ Text -> Word8 -> DecoderError
DecoderErrorUnknownTag Text
"UTxOValidationError" Word8
tag

-- | Validate a transaction and use it to update the 'UTxO'
updateUTxOTx
  :: (MonadError UTxOValidationError m, MonadReader ValidationMode m)
  => Environment
  -> UTxO
  -> Annotated Tx ByteString
  -> m UTxO
updateUTxOTx :: Environment -> UTxO -> Annotated Tx ByteString -> m UTxO
updateUTxOTx Environment
env UTxO
utxo aTx :: Annotated Tx ByteString
aTx@(Annotated Tx
tx ByteString
_) = do
  ReaderT ValidationMode (Either TxValidationError) ()
-> ReaderT ValidationMode (Either TxValidationError) ()
forall err (m :: * -> *).
(MonadError err m, MonadReader ValidationMode m) =>
m () -> m ()
unlessNoTxValidation (Environment
-> UTxO
-> Annotated Tx ByteString
-> ReaderT ValidationMode (Either TxValidationError) ()
forall (m :: * -> *).
MonadError TxValidationError m =>
Environment -> UTxO -> Annotated Tx ByteString -> m ()
validateTx Environment
env UTxO
utxo Annotated Tx ByteString
aTx)
    ReaderT ValidationMode (Either TxValidationError) ()
-> (TxValidationError -> UTxOValidationError) -> m ()
forall e' (m :: * -> *) e a.
(MonadError e' m, MonadReader ValidationMode m) =>
ReaderT ValidationMode (Either e) a -> (e -> e') -> m a
`wrapErrorWithValidationMode` TxValidationError -> UTxOValidationError
UTxOValidationTxValidationError

  UTxO -> UTxO -> Either UTxOError UTxO
forall (m :: * -> *).
MonadError UTxOError m =>
UTxO -> UTxO -> m UTxO
UTxO.union ([TxIn] -> Set TxIn
forall a. Ord a => [a] -> Set a
S.fromList (NonEmpty TxIn -> [TxIn]
forall a. NonEmpty a -> [a]
NE.toList (Tx -> NonEmpty TxIn
txInputs Tx
tx)) Set TxIn -> UTxO -> UTxO
</| UTxO
utxo) (Tx -> UTxO
txOutputUTxO Tx
tx)
    Either UTxOError UTxO
-> (UTxOError -> UTxOValidationError) -> m UTxO
forall e' (m :: * -> *) e a.
MonadError e' m =>
Either e a -> (e -> e') -> m a
`wrapError` UTxOError -> UTxOValidationError
UTxOValidationUTxOError


-- | Validate a transaction with a witness and use it to update the 'UTxO'
updateUTxOTxWitness
  :: (MonadError UTxOValidationError m, MonadReader ValidationMode m)
  => Environment
  -> UTxO
  -> ATxAux ByteString
  -> m UTxO
updateUTxOTxWitness :: Environment -> UTxO -> ATxAux ByteString -> m UTxO
updateUTxOTxWitness Environment
env UTxO
utxo ATxAux ByteString
ta = do
  m () -> m ()
forall err (m :: * -> *).
(MonadError err m, MonadReader ValidationMode m) =>
m () -> m ()
whenTxValidation (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
    -- Get the signing addresses for each transaction input from the 'UTxO'
    [Address]
addresses <-
      (TxIn -> Either UTxOError Address)
-> [TxIn] -> Either UTxOError [Address]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (TxIn -> UTxO -> Either UTxOError Address
`UTxO.lookupAddress` UTxO
utxo) (NonEmpty TxIn -> [TxIn]
forall a. NonEmpty a -> [a]
NE.toList (NonEmpty TxIn -> [TxIn]) -> NonEmpty TxIn -> [TxIn]
forall a b. (a -> b) -> a -> b
$ Tx -> NonEmpty TxIn
txInputs Tx
tx)
        Either UTxOError [Address]
-> (UTxOError -> UTxOValidationError) -> m [Address]
forall e' (m :: * -> *) e a.
MonadError e' m =>
Either e a -> (e -> e') -> m a
`wrapError` UTxOError -> UTxOValidationError
UTxOValidationUTxOError

    -- Validate witnesses and their signing addresses
    ((Address, TxInWitness) -> Either TxValidationError ())
-> [(Address, TxInWitness)] -> Either TxValidationError ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_
        ((Address -> TxInWitness -> Either TxValidationError ())
-> (Address, TxInWitness) -> Either TxValidationError ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((Address -> TxInWitness -> Either TxValidationError ())
 -> (Address, TxInWitness) -> Either TxValidationError ())
-> (Address -> TxInWitness -> Either TxValidationError ())
-> (Address, TxInWitness)
-> Either TxValidationError ()
forall a b. (a -> b) -> a -> b
$ Annotated ProtocolMagicId ByteString
-> Annotated TxSigData ByteString
-> Address
-> TxInWitness
-> Either TxValidationError ()
forall (m :: * -> *).
MonadError TxValidationError m =>
Annotated ProtocolMagicId ByteString
-> Annotated TxSigData ByteString -> Address -> TxInWitness -> m ()
validateWitness Annotated ProtocolMagicId ByteString
pmi Annotated TxSigData ByteString
sigData)
        ([Address] -> [TxInWitness] -> [(Address, TxInWitness)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Address]
addresses (TxWitness -> [TxInWitness]
forall a. Vector a -> [a]
V.toList TxWitness
witness))
      Either TxValidationError ()
-> (TxValidationError -> UTxOValidationError) -> m ()
forall e' (m :: * -> *) e a.
MonadError e' m =>
Either e a -> (e -> e') -> m a
`wrapError` TxValidationError -> UTxOValidationError
UTxOValidationTxValidationError

    -- Validate the tx including witnesses
    Environment
-> UTxO -> ATxAux ByteString -> Either TxValidationError ()
forall (m :: * -> *).
MonadError TxValidationError m =>
Environment -> UTxO -> ATxAux ByteString -> m ()
validateTxAux Environment
env UTxO
utxo ATxAux ByteString
ta
      Either TxValidationError ()
-> (TxValidationError -> UTxOValidationError) -> m ()
forall e' (m :: * -> *) e a.
MonadError e' m =>
Either e a -> (e -> e') -> m a
`wrapError` TxValidationError -> UTxOValidationError
UTxOValidationTxValidationError

  -- Update 'UTxO' ignoring witnesses
  Environment -> UTxO -> Annotated Tx ByteString -> m UTxO
forall (m :: * -> *).
(MonadError UTxOValidationError m, MonadReader ValidationMode m) =>
Environment -> UTxO -> Annotated Tx ByteString -> m UTxO
updateUTxOTx Environment
env UTxO
utxo Annotated Tx ByteString
aTx
 where
  Environment { AProtocolMagic ByteString
protocolMagic :: AProtocolMagic ByteString
protocolMagic :: Environment -> AProtocolMagic ByteString
protocolMagic } = Environment
env
  pmi :: Annotated ProtocolMagicId ByteString
pmi = AProtocolMagic ByteString -> Annotated ProtocolMagicId ByteString
forall a. AProtocolMagic a -> Annotated ProtocolMagicId a
getAProtocolMagicId AProtocolMagic ByteString
protocolMagic

  aTx :: Annotated Tx ByteString
aTx@(Annotated Tx
tx ByteString
_) = ATxAux ByteString -> Annotated Tx ByteString
forall a. ATxAux a -> Annotated Tx a
aTaTx ATxAux ByteString
ta
  witness :: TxWitness
witness = ATxAux ByteString -> TxWitness
forall a. ATxAux a -> TxWitness
taWitness ATxAux ByteString
ta
  sigData :: Annotated TxSigData ByteString
sigData = Annotated Tx ByteString -> Annotated TxSigData ByteString
recoverSigData Annotated Tx ByteString
aTx


-- | Update UTxO with a list of transactions
updateUTxO
  :: (MonadError UTxOValidationError m, MonadReader ValidationMode m)
  => Environment
  -> UTxO
  -> [ATxAux ByteString]
  -> m UTxO
updateUTxO :: Environment -> UTxO -> [ATxAux ByteString] -> m UTxO
updateUTxO Environment
env UTxO
as = (UTxO -> ATxAux ByteString -> m UTxO)
-> UTxO -> [ATxAux ByteString] -> m UTxO
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (Environment -> UTxO -> ATxAux ByteString -> m UTxO
forall (m :: * -> *).
(MonadError UTxOValidationError m, MonadReader ValidationMode m) =>
Environment -> UTxO -> ATxAux ByteString -> m UTxO
updateUTxOTxWitness Environment
env) UTxO
as