Skip to content

Commit 016a9ae

Browse files
authored
Balancing overhaul (#514)
### **This improves balancing in several ways:** 1. This adds a `TxSkel` option to defer validation failures occurring during balancing. As a consequence, the balancing succeeds even when running the script to assign execution units fails, and thus the balanced `TxSkel` can be traced. As a downside, this drastically decreases performances (as scripts are run several more times, even if we know they fail) and thus is only made available as an option, disabled by default. 2. This add another `TxSkel` option to cap the maximum amount of UTxOs that can be used for balancing purposes. This idea is that in the rare case where there are many candidate UTxOs, the algorithm would be too greedy, and thus some constraints need to be applied. This is now possible. 3. This reworks the main balancing function `reachValue` The idea is that it now optimizes the solutions depending on how much overhead in terms of size, rather than by the minAda required for the extra payment. For instance, if a solution generates a very small extra payment, but with many additional inputs, and another generates a bigger extra output, but with fewers added inputs, then the latter will likely be picked. 4. This makes it so that the body generated during fee computation is not lost The body is given back as a result of the balancing, and is directly used when submitting the transaction for validation in our main validation function. 5. This fixes an optimization bug in the fee computation 6. This improves the handling and generation of collaterals Fixes #435 Fixes #494 Fixes #500 Fixes #503
1 parent e9094ce commit 016a9ae

11 files changed

Lines changed: 498 additions & 366 deletions

File tree

src/Cooked/MockChain/Balancing.hs

Lines changed: 339 additions & 253 deletions
Large diffs are not rendered by default.

src/Cooked/MockChain/Common.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ module Cooked.MockChain.Common
1010
where
1111

1212
import Cooked.Skeleton.Output
13-
import Cooked.Skeleton.User
1413
import Data.Set (Set)
1514
import PlutusLedgerApi.V3 qualified as Api
1615

@@ -22,8 +21,9 @@ type Fee = Integer
2221
-- | An alias for sets of utxos used as collateral inputs
2322
type CollateralIns = Set Api.TxOutRef
2423

25-
-- | An alias for optional pairs of collateral inputs and return collateral peer
26-
type Collaterals = Maybe (CollateralIns, Peer)
24+
-- | An alias for optional pairs of collateral inputs and optional return
25+
-- collateral output
26+
type Collaterals = (CollateralIns, Maybe TxSkelOut)
2727

2828
-- | An alias for an output and its reference
2929
type Utxo = (Api.TxOutRef, TxSkelOut)

src/Cooked/MockChain/Error.hs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
-- | This module exposes the errors that can be raised during a mockchain run
22
module Cooked.MockChain.Error
33
( -- * Mockchain errors
4+
BalancingError (..),
45
MockChainError (..),
56

67
-- * Interpretating effects into `Error MockChainError`
@@ -18,16 +19,31 @@ import Polysemy
1819
import Polysemy.Error
1920
import Polysemy.Fail
2021

22+
-- | Errors that can be produced during balancing
23+
data BalancingError
24+
= -- | The balancing user theoretically has enough funds to balancing the
25+
-- trasaction, but this balancing results in a surplus payment which they
26+
-- cannot afford ADA-wise.
27+
NotEnoughFundForExtraMinAda Peer
28+
| -- | The balancing does not have enough funds to sustain the fee required to
29+
-- balance the transaction.
30+
NotEnoughFundForProperFee Peer
31+
| -- | The balancing wallet does not have enough funds to balance the
32+
-- transaction
33+
NotEnoughFund Peer Api.Value
34+
| -- | The provided of collateral UTxOs does not have enough funds to cover
35+
-- the potential collateral cost
36+
NoSuitableCollateral Integer Integer Api.Value
37+
| -- | The balancing user has not be provided, but the balancing requires it
38+
MissingBalancingUser
39+
deriving (Show, Eq)
40+
2141
-- | Errors that can be produced by the blockchain
2242
data MockChainError
2343
= -- | Validation errors, either in Phase 1 or Phase 2
2444
MCEValidationError Ledger.ValidationPhase Ledger.ValidationError
25-
| -- | The balancing user does not have enough funds
26-
MCEUnbalanceable Peer Api.Value
27-
| -- | The balancing user is required but missing
28-
MCEMissingBalancingUser String
29-
| -- | No suitable collateral could be associated with a skeleton
30-
MCENoSuitableCollateral Integer Integer Api.Value
45+
| -- | Balancing errors
46+
MCEBalancingError BalancingError
3147
| -- | Translating a skeleton element to its Cardano counterpart failed
3248
MCEToCardanoError Ledger.ToCardanoError
3349
| -- | The required reference script is missing from a witness utxo

src/Cooked/MockChain/GenerateTx/Body.hs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ txSkelToTxBodyContent ::
4141
(Members '[MockChainRead, Error MockChainError, Error Ledger.ToCardanoError, Fail] effs) =>
4242
TxSkel ->
4343
Fee ->
44-
Collaterals ->
44+
Maybe Collaterals ->
4545
Sem effs (Cardano.TxBodyContent Cardano.BuildTx Cardano.ConwayEra)
4646
txSkelToTxBodyContent skel@TxSkel {..} fee mCollaterals = do
4747
txIns <- mapM toTxInAndWitness $ Map.toList txSkelIns
4848
txInsReference <- toInsReference skel
49-
(txInsCollateral, txTotalCollateral, txReturnCollateral) <- toCollateralTriplet fee mCollaterals
49+
(txInsCollateral, txTotalCollateral, txReturnCollateral) <- toCollateralTriplet mCollaterals
5050
txOuts <- mapM toCardanoTxOut txSkelOuts
5151
(txValidityLowerBound, txValidityUpperBound) <- fromEither $ Ledger.toCardanoValidityRange txSkelValidityRange
5252
txMintValue <- toMintValue txSkelMints
@@ -85,7 +85,7 @@ txBodyContentToTxBody txBodyContent = do
8585
txSkelToIndex ::
8686
(Members '[MockChainRead, Error Ledger.ToCardanoError] effs) =>
8787
TxSkel ->
88-
Collaterals ->
88+
Maybe Collaterals ->
8989
Sem effs (Cardano.UTxO Cardano.ConwayEra)
9090
txSkelToIndex txSkel mCollaterals = do
9191
-- We build the index of UTxOs which are known to this skeleton. This includes
@@ -106,7 +106,7 @@ txSkelToTxBody ::
106106
(Members '[MockChainRead, Error MockChainError, Error Ledger.ToCardanoError, Fail] effs) =>
107107
TxSkel ->
108108
Fee ->
109-
Collaterals ->
109+
Maybe Collaterals ->
110110
Sem effs (Cardano.TxBody Cardano.ConwayEra)
111111
txSkelToTxBody txSkel fee mCollaterals = do
112112
-- We create a first body content and body, without execution units
@@ -119,9 +119,14 @@ txSkelToTxBody txSkel fee mCollaterals = do
119119
params <- getParams
120120
-- We retrieve the execution units associated with the transaction
121121
case Emulator.getTxExUnitsWithLogs params (Ledger.fromPlutusIndex index) tx' of
122-
-- Computing the execution units can result in all kinds of validation
123-
-- errors except for the ones related to the execution units themselves.
124-
Left err -> throw $ uncurry MCEValidationError err
122+
-- Computing the execution units can result in all kinds of phase 2
123+
-- validation failures, except for the ones related to the execution units
124+
-- themselves. Unless required in the options, we throw the validation
125+
-- failure right away when applicable.
126+
Left err | not $ txSkelOptDeferPhase2FailuresDuringBalancing $ txSkelOpts txSkel -> throw $ uncurry MCEValidationError err
127+
-- The other option is to ignore those and return the unchanged body with
128+
-- the existing execution units, postponing the handling of the failures.
129+
Left _ -> return txBody'
125130
-- When no error arises, we get an execution unit for each script usage. We
126131
-- first have to transform this Ledger map to a cardano API map.
127132
Right (Map.mapKeysMonotonic (Cardano.toScriptIndex Cardano.AlonzoEraOnwardsConway) . fmap (Cardano.fromAlonzoExUnits . snd) -> exUnits) ->
@@ -131,7 +136,7 @@ txSkelToTxBody txSkel fee mCollaterals = do
131136
Left _ -> fail "Error while assigning execution units"
132137
-- We now have a body content with proper execution units and can create
133138
-- the final body from it
134-
Right txBody -> txBodyContentToTxBody txBody
139+
Right txBodyContent -> txBodyContentToTxBody txBodyContent
135140

136141
-- | Generates a Cardano transaction and signs it
137142
txSignatoriesAndBodyToCardanoTx ::
@@ -145,7 +150,7 @@ txSkelToCardanoTx ::
145150
(Members '[MockChainRead, Error MockChainError, Error Ledger.ToCardanoError, Fail] effs) =>
146151
TxSkel ->
147152
Fee ->
148-
Collaterals ->
153+
Maybe Collaterals ->
149154
Sem effs (Cardano.Tx Cardano.ConwayEra)
150155
txSkelToCardanoTx txSkel fee =
151156
fmap (txSignatoriesAndBodyToCardanoTx (txSkelSignatories txSkel))

src/Cooked/MockChain/GenerateTx/Collateral.hs

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,76 +3,54 @@
33
module Cooked.MockChain.GenerateTx.Collateral where
44

55
import Cardano.Api qualified as Cardano
6-
import Cardano.Ledger.Conway.Core qualified as Conway
7-
import Cardano.Node.Emulator.Internal.Node qualified as Emulator
8-
import Control.Monad
96
import Cooked.MockChain.Common
7+
import Cooked.MockChain.GenerateTx.Output
108
import Cooked.MockChain.Read
119
import Cooked.Skeleton.Output
10+
import Cooked.Skeleton.Value
11+
import Data.Map qualified as Map
1212
import Data.Set qualified as Set
1313
import Ledger.Tx.CardanoAPI qualified as Ledger
14-
import Lens.Micro.Extras qualified as MicroLens
15-
import Plutus.Script.Utils.Address qualified as Script
16-
import Plutus.Script.Utils.Value qualified as Script
17-
import PlutusTx.Numeric qualified as PlutusTx
14+
import Optics.Core
15+
import PlutusLedgerApi.V3 qualified as Api
1816
import Polysemy
1917
import Polysemy.Error
2018

21-
-- | Computes the collateral triplet from the fees and the collateral inputs in
22-
-- the context. What we call a collateral triplet is composed of:
19+
-- | Computes the collateral triplet from the potential collaterals. What we
20+
-- call a collateral triplet is composed of:
21+
--
2322
-- * The set of collateral inputs
23+
--
2424
-- * The total collateral paid by the transaction in case of phase 2 failure
25+
--
2526
-- * An output returning excess collateral value when collaterals are used
27+
--
2628
-- These quantity should satisfy the equation (in terms of their values):
2729
-- collateral inputs = total collateral + return collateral
2830
toCollateralTriplet ::
2931
(Members '[MockChainRead, Error Ledger.ToCardanoError] effs) =>
30-
Fee ->
31-
Collaterals ->
32+
Maybe Collaterals ->
3233
Sem
3334
effs
3435
( Cardano.TxInsCollateral Cardano.ConwayEra,
3536
Cardano.TxTotalCollateral Cardano.ConwayEra,
3637
Cardano.TxReturnCollateral Cardano.CtxTx Cardano.ConwayEra
3738
)
38-
toCollateralTriplet _ Nothing = return (Cardano.TxInsCollateralNone, Cardano.TxTotalCollateralNone, Cardano.TxReturnCollateralNone)
39-
toCollateralTriplet fee (Just (Set.toList -> collateralInsList, returnCollateralUser)) = do
39+
toCollateralTriplet Nothing = return (Cardano.TxInsCollateralNone, Cardano.TxTotalCollateralNone, Cardano.TxReturnCollateralNone)
40+
toCollateralTriplet (Just (Set.toList -> collateralInsList, mReturnCollateral)) = do
4041
-- We build the collateral inputs from this list
4142
txInsCollateral <-
4243
case collateralInsList of
4344
[] -> return Cardano.TxInsCollateralNone
4445
l -> fromEither $ Cardano.TxInsCollateral Cardano.AlonzoEraOnwardsConway <$> mapM Ledger.toCardanoTxIn l
45-
-- Retrieving the total value in collateral inputs. This fails if one of the
46-
-- collateral inputs has not been successfully resolved.
47-
collateralInsValue <-
48-
foldM (\val -> ((val <>) <$>) . viewByRef txSkelOutValueL) mempty collateralInsList
49-
-- We retrieve the collateral percentage compared to fees. By default, we use
50-
-- 150% which is the current value in the parameters, although the default
51-
-- value should never be used here, as the call is supposed to always succeed.
52-
collateralPercentage <- toInteger . MicroLens.view Conway.ppCollateralPercentageL . Emulator.pEmulatorPParams <$> getParams
53-
-- The total collateral corresponds to the fees multiplied by the collateral
54-
-- percentage. We add 1 because the ledger apparently rounds up this value.
55-
let coinTotalCollateral = 1 + (fee * collateralPercentage) `div` 100
56-
-- We create the total collateral based on the computed value
57-
let txTotalCollateral = Cardano.TxTotalCollateral Cardano.BabbageEraOnwardsConway $ Cardano.Coin coinTotalCollateral
58-
-- We compute a return collateral value by subtracting the total collateral to
59-
-- the value in collateral inputs
60-
let returnCollateralValue = collateralInsValue <> PlutusTx.negate (Script.lovelace coinTotalCollateral)
61-
-- The return collateral is then computed
46+
-- We collect the amount of lovelace in the collateral inputs
47+
Api.Lovelace collateralInsLovelace <- foldOf (folded % txSkelOutValueL % valueLovelaceL) . Map.elems <$> lookupUtxos collateralInsList
48+
-- We collect the amount of lovelace in the return collateral output
49+
let Api.Lovelace returnCollateralLovelace = maybe 0 (view (txSkelOutValueL % valueLovelaceL)) mReturnCollateral
50+
-- The total collateral is the difference between the two
51+
let txTotalCollateral = Cardano.TxTotalCollateral Cardano.BabbageEraOnwardsConway $ Cardano.Coin $ collateralInsLovelace - returnCollateralLovelace
6252
txReturnCollateral <-
63-
-- If the total collateral equal what the inputs provide, we return
64-
-- `TxReturnCollateralNone`, otherwise, we compute the new output
65-
if returnCollateralValue == mempty
66-
then return Cardano.TxReturnCollateralNone
67-
else do
68-
-- The value is a translation of the remaining value
69-
txReturnCollateralValue <- Ledger.toCardanoTxOutValue <$> fromEither (Ledger.toCardanoValue returnCollateralValue)
70-
-- The address is the one from the return collateral user, which is
71-
-- required to exist here.
72-
networkId <- Emulator.pNetworkId <$> getParams
73-
address <- fromEither $ Ledger.toCardanoAddressInEra networkId (Script.toAddress returnCollateralUser)
74-
-- The return collateral is built up from those elements
75-
return $
76-
Cardano.TxReturnCollateral Cardano.BabbageEraOnwardsConway $
77-
Cardano.TxOut address txReturnCollateralValue Cardano.TxOutDatumNone Cardano.ReferenceScriptNone
53+
case mReturnCollateral of
54+
Nothing -> return Cardano.TxReturnCollateralNone
55+
Just collateralOut -> Cardano.TxReturnCollateral Cardano.BabbageEraOnwardsConway <$> toCardanoTxOut collateralOut
7856
return (txInsCollateral, txTotalCollateral, txReturnCollateral)

src/Cooked/MockChain/Log.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ data MockChainLogEntry
3232
MCLogSubmittedTxSkel TxSkel
3333
| -- | Logging a Skeleton as it has been adjusted by the balancing mechanism,
3434
-- alongside fee, and possible collateral utxos and return collateral user.
35-
MCLogAdjustedTxSkel TxSkel Fee Collaterals
35+
MCLogAdjustedTxSkel TxSkel Fee (Maybe Collaterals)
3636
| -- | Logging the successful validation of a new transaction, with its id and
3737
-- number of produced outputs.
3838
MCLogNewTx Api.TxId Integer

src/Cooked/MockChain/Write.hs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -178,12 +178,13 @@ runMockChainWrite = interpret $ \case
178178
autoFillWithdrawalAmounts
179179
-- We balance the skeleton when requested in the skeleton option, and get
180180
-- the associated fee, collateral inputs and return collateral user
181-
(finalTxSkel, fee, mCollaterals) <- viewTweak simple >>= balanceTxSkel
181+
ExtendedTxSkel finalTxSkel fee mCollaterals body <- viewTweak simple >>= balanceTxSkel
182182
-- We log the adjusted skeleton
183183
logEvent $ MCLogAdjustedTxSkel finalTxSkel fee mCollaterals
184184
-- We generate the transaction asscoiated with the skeleton, and apply on it
185185
-- the modifications from the skeleton options
186-
cardanoTx <- Ledger.CardanoEmulatorEraTx . txSkelOptModTx <$> txSkelToCardanoTx finalTxSkel fee mCollaterals
186+
signatories <- viewTweak txSkelSignatoriesL
187+
let cardanoTx = Ledger.CardanoEmulatorEraTx $ txSkelOptModTx $ txSignatoriesAndBodyToCardanoTx signatories body
187188
-- To run transaction validation we need a minimal ledger state
188189
eLedgerState <- gets mcstLedgerState
189190
-- We finally run the emulated validation. We update our internal state
@@ -193,18 +194,16 @@ runMockChainWrite = interpret $ \case
193194
newOutputs <- case Emulator.validateCardanoTx newParams eLedgerState cardanoTx of
194195
-- In case of a phase 1 error, we give back the same index
195196
(_, Ledger.FailPhase1 _ err) -> throw $ MCEValidationError Ledger.Phase1 err
196-
(newELedgerState, Ledger.FailPhase2 _ err _) | Just (colInputs, retColUser) <- mCollaterals -> do
197+
(newELedgerState, Ledger.FailPhase2 _ err _) | Just (colInputs, mRetColOutput) <- mCollaterals -> do
197198
-- We update the emulated ledger state
198199
modify' (set mcstLedgerStateL newELedgerState)
199200
-- We remove the collateral utxos from our own stored outputs
200201
forM_ colInputs $ modify' . removeOutput
201-
-- We add the returned collateral to our outputs (in practice this map
202-
-- either contains no element, or a single one)
203-
forM_ (Map.toList $ Ledger.getCardanoTxProducedReturnCollateral cardanoTx) $ \(txIn, txOut) ->
204-
modify' $
205-
addOutput
206-
(Ledger.fromCardanoTxIn txIn)
207-
(retColUser `receives` Value (Api.txOutValue . Ledger.fromCardanoTxOutToPV2TxInfoTxOut . Ledger.getTxOut $ txOut))
202+
-- We add the returned collateral to our outputs when it exists
203+
case (mRetColOutput, Map.toList $ Ledger.getCardanoTxProducedReturnCollateral cardanoTx) of
204+
(Nothing, []) -> return ()
205+
(Just retColOutput, [(txIn, _)]) -> modify' $ addOutput (Ledger.fromCardanoTxIn txIn) retColOutput
206+
_ -> fail "Unreachable case when processing return collaterals, please report a bug at https://github.com/tweag/cooked-validators/issues"
208207
-- We throw a mockchain error
209208
throw $ MCEValidationError Ledger.Phase2 err
210209
-- In case of success, we update the index with all inputs and outputs

src/Cooked/Pretty/MockChain.hs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,15 @@ instance (Show a) => PrettyCooked (MockChainReturn a) where
6767
instance PrettyCooked Peer where
6868
prettyCookedOpt opts = prettyHash opts . Script.toPubKeyHash
6969

70-
instance PrettyCooked MockChainError where
71-
prettyCookedOpt opts (MCEValidationError plutusPhase plutusError) =
72-
PP.vsep ["Validation error " <+> prettyCookedOpt opts plutusPhase, PP.indent 2 (prettyCookedOpt opts plutusError)]
73-
prettyCookedOpt _ (MCEMissingBalancingUser msg) = "Missing balancing user:" <+> PP.pretty msg
74-
prettyCookedOpt opts (MCEUnbalanceable balUser missingValue) =
75-
prettyItemize
76-
opts
77-
"Unbalanceable:"
78-
"-"
79-
[ prettyCookedOpt opts balUser <+> "does not have enough funds",
80-
if missingValue == mempty
81-
then "Not enough funds to sustain the minimal ada of the return utxo"
82-
else "Unable to find" <+> prettyCookedOpt opts missingValue
83-
]
84-
prettyCookedOpt opts (MCENoSuitableCollateral fee percentage colVal) =
70+
instance PrettyCooked BalancingError where
71+
prettyCookedOpt opts (NotEnoughFundForExtraMinAda peer) =
72+
prettyCookedOpt opts peer <+> "does not have enough funds to account for the min ADA of the surplus payment"
73+
prettyCookedOpt opts (NotEnoughFundForProperFee peer) =
74+
prettyCookedOpt opts peer <+> "does not have enough funds to account for the minimum required fee"
75+
prettyCookedOpt opts (NotEnoughFund peer missingValue) =
76+
prettyCookedOpt opts peer <+> "does not have enough funds to account for this missing value:" <+> prettyCookedOpt opts missingValue
77+
prettyCookedOpt _ MissingBalancingUser = "Missing balancing user"
78+
prettyCookedOpt opts (NoSuitableCollateral fee percentage colVal) =
8579
prettyItemize
8680
opts
8781
"No suitable collateral"
@@ -90,6 +84,11 @@ instance PrettyCooked MockChainError where
9084
"Percentage in params was" <+> prettyCookedOpt opts percentage,
9185
"Resulting minimal collateral value was" <+> prettyCookedOpt opts colVal
9286
]
87+
88+
instance PrettyCooked MockChainError where
89+
prettyCookedOpt opts (MCEValidationError plutusPhase plutusError) =
90+
PP.vsep ["Validation error " <+> prettyCookedOpt opts plutusPhase, PP.indent 2 (prettyCookedOpt opts plutusError)]
91+
prettyCookedOpt opts (MCEBalancingError err) = prettyCookedOpt opts err
9392
prettyCookedOpt _ (MCEToCardanoError cardanoError) =
9493
"Transaction generation error:" <+> PP.pretty cardanoError
9594
prettyCookedOpt opts (MCEUnknownOutRef txOutRef) = "Unknown transaction output ref:" <+> prettyCookedOpt opts txOutRef
@@ -136,9 +135,11 @@ instance PrettyCooked (Contextualized MockChainLogEntry) where
136135
++ ( ("Fee:" <+> prettyCookedOpt opts (Script.lovelace fee))
137136
: maybe
138137
["No collateral required"]
139-
( \(collaterals, returnUser) ->
138+
( \(collaterals, mRetColOutput) ->
140139
[ prettyItemize opts "Collateral inputs:" "-" (Contextualized outputs . CollateralInput <$> Set.toList collaterals),
141-
"Return collateral target:" <+> prettyCookedOpt opts returnUser
140+
case mRetColOutput of
141+
Nothing -> "No return collateral output"
142+
Just retColOutput -> prettyItemize opts "Return collateral output:" "-" retColOutput
142143
]
143144
)
144145
mCollaterals

src/Cooked/Pretty/Skeleton.hs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
{-# LANGUAGE DeriveFunctor #-}
21
{-# OPTIONS_GHC -Wno-orphans #-}
32

43
-- | This module implements 'PrettyCooked', 'PrettyCookedList' and
@@ -13,7 +12,7 @@ import Cooked.Wallet (Wallet)
1312
import Data.Default
1413
import Data.Map (Map)
1514
import Data.Map qualified as Map
16-
import Data.Maybe (catMaybes)
15+
import Data.Maybe (catMaybes, fromJust)
1716
import Data.Set qualified as Set
1817
import Ledger.Slot qualified as Ledger
1918
import Optics.Core
@@ -293,13 +292,17 @@ instance PrettyCookedList TxSkelOpts where
293292
txSkelOptBalancingUtxos
294293
_
295294
txSkelOptCollateralUtxos
295+
txSkelOptDeferFailures
296+
txSkelOptMaxNbOfBalancingUtxos
296297
) =
297298
[ prettyIfNot True prettyAutoSlotIncrease txSkelOptAutoSlotIncrease,
298299
prettyIfNot def prettyBalanceOutputPolicy txSkelOptBalanceOutputPolicy,
299300
prettyIfNot def prettyBalanceFeePolicy txSkelOptFeePolicy,
300301
prettyIfNot def prettyBalancingPolicy txSkelOptBalancingPolicy,
301302
prettyIfNot def prettyBalancingUtxos txSkelOptBalancingUtxos,
302-
prettyIfNot def prettyCollateralUtxos txSkelOptCollateralUtxos
303+
prettyIfNot def prettyCollateralUtxos txSkelOptCollateralUtxos,
304+
prettyIfNot False (const "Defer Phase 2 failures during balancing") txSkelOptDeferFailures,
305+
prettyIfNot Nothing (("Limit the number of balancing Utxos to " <>) . PP.pretty . fromJust) txSkelOptMaxNbOfBalancingUtxos
303306
]
304307
where
305308
prettyIfNot :: (Eq a) => a -> (a -> DocCooked) -> a -> Maybe DocCooked

0 commit comments

Comments
 (0)