|
3 | 3 | module Cooked.MockChain.GenerateTx.Collateral where |
4 | 4 |
|
5 | 5 | 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 |
9 | 6 | import Cooked.MockChain.Common |
| 7 | +import Cooked.MockChain.GenerateTx.Output |
10 | 8 | import Cooked.MockChain.Read |
11 | 9 | import Cooked.Skeleton.Output |
| 10 | +import Cooked.Skeleton.Value |
| 11 | +import Data.Map qualified as Map |
12 | 12 | import Data.Set qualified as Set |
13 | 13 | 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 |
18 | 16 | import Polysemy |
19 | 17 | import Polysemy.Error |
20 | 18 |
|
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 | +-- |
23 | 22 | -- * The set of collateral inputs |
| 23 | +-- |
24 | 24 | -- * The total collateral paid by the transaction in case of phase 2 failure |
| 25 | +-- |
25 | 26 | -- * An output returning excess collateral value when collaterals are used |
| 27 | +-- |
26 | 28 | -- These quantity should satisfy the equation (in terms of their values): |
27 | 29 | -- collateral inputs = total collateral + return collateral |
28 | 30 | toCollateralTriplet :: |
29 | 31 | (Members '[MockChainRead, Error Ledger.ToCardanoError] effs) => |
30 | | - Fee -> |
31 | | - Collaterals -> |
| 32 | + Maybe Collaterals -> |
32 | 33 | Sem |
33 | 34 | effs |
34 | 35 | ( Cardano.TxInsCollateral Cardano.ConwayEra, |
35 | 36 | Cardano.TxTotalCollateral Cardano.ConwayEra, |
36 | 37 | Cardano.TxReturnCollateral Cardano.CtxTx Cardano.ConwayEra |
37 | 38 | ) |
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 |
40 | 41 | -- We build the collateral inputs from this list |
41 | 42 | txInsCollateral <- |
42 | 43 | case collateralInsList of |
43 | 44 | [] -> return Cardano.TxInsCollateralNone |
44 | 45 | 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 |
62 | 52 | 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 |
78 | 56 | return (txInsCollateral, txTotalCollateral, txReturnCollateral) |
0 commit comments