11{-# LANGUAGE FlexibleContexts #-}
2+ {-# LANGUAGE LambdaCase #-}
23{-# LANGUAGE NumericUnderscores #-}
34{-# LANGUAGE OverloadedLists #-}
45{-# LANGUAGE ScopedTypeVariables #-}
89module Test.Cardano.Api.Experimental
910 ( tests
1011 , exampleProtocolParams
12+ , exampleProtocolParamsEra
1113 )
1214where
1315
@@ -27,6 +29,7 @@ import Cardano.Ledger.Api qualified as UnexportedLedger
2729import Cardano.Ledger.Babbage.TxBody qualified as L
2830import Cardano.Ledger.Conway qualified as L
2931import Cardano.Ledger.Core qualified as L
32+ import Cardano.Ledger.Dijkstra.Genesis (DijkstraGenesis (.. ))
3033import Cardano.Ledger.Mary.Value qualified as Mary
3134import Cardano.Ledger.Plutus.Data qualified as L
3235import Cardano.Slotting.EpochInfo qualified as Slotting
@@ -109,9 +112,6 @@ tests =
109112 , testProperty
110113 " Case 2: transaction with no outputs creates change output"
111114 prop_calcMinFeeRecursive_no_tx_outs
112- , testProperty
113- " Tiny surplus consumed by fee increase yields NotEnoughAdaForChangeOutput"
114- prop_calcMinFeeRecursive_tiny_surplus_not_enough_ada
115115 ]
116116 ]
117117
@@ -354,6 +354,14 @@ prop_balance_transaction_two_ways = H.propertyOnce $ do
354354 newTx H. === oldTx
355355 H. success
356356
357+ exampleProtocolParamsEra :: Exp. Era era -> L. PParams (Exp. LedgerEra era )
358+ exampleProtocolParamsEra = \ case
359+ Exp. ConwayEra -> exampleProtocolParams
360+ Exp. DijkstraEra ->
361+ UnexportedLedger. upgradePParams
362+ (dgUpgradePParams Genesis. dijkstraGenesisDefaults)
363+ exampleProtocolParams
364+
357365exampleProtocolParams :: Ledger. PParams UnexportedLedger. ConwayEra
358366exampleProtocolParams =
359367 UnexportedLedger. upgradePParams conwayUpgrade $
@@ -606,7 +614,7 @@ genFundedSimpleTx era = do
606614 ]
607615 -- Surplus of 2–17 ADA ensures funding always exceeds sendCoin + fees.
608616 -- Fees are typically < 1000 lovelace with test protocol parameters
609- -- (minFeeA =1, minFeeB =0).
617+ -- (feePerByte =1, feeFixed =0).
610618 surplus <- L. Coin <$> Gen. integral (Range. linear 2_000_000 17_000_000 )
611619 let fundingCoin = sendCoin + surplus
612620 let ledgerTxIn = Api. toShelleyTxIn txIn
@@ -916,77 +924,3 @@ prop_calcMinFeeRecursive_no_tx_outs = H.property $ do
916924 let outs = toList $ resultLedgerTx ^. L. bodyTxL . L. outputsTxBodyL
917925 -- The result should have exactly one output (the change output)
918926 length outs H. === 1
919-
920- -- ---------------------------------------------------------------------------
921- -- Border case: tiny surplus consumed by fee increase
922- -- ---------------------------------------------------------------------------
923-
924- -- | Generates a transaction where the surplus (funding - output) is barely
925- -- above the fee for the 1-output transaction, but once a change output is
926- -- appended (increasing the tx size and therefore the fee), the new higher fee
927- -- exceeds the surplus, driving the change output balance negative.
928- --
929- -- Concretely, with test protocol parameters:
930- -- Fee for 1-output tx (F1) ≈ 236 lovelace
931- -- Fee for 2-output tx (F2) ≈ 259 lovelace
932- -- Delta = F2 - F1 ≈ 23
933- -- A surplus of F1 + 1 to F1 + 15 ensures:
934- -- 1. After fee convergence at F1, a positive balance triggers Case 2.
935- -- 2. Adding the change output raises the fee to F2.
936- -- 3. The change is updated: (surplus - F1) + (F1 - F2) = surplus - F2 < 0.
937- -- 4. balanceTxOuts returns NotEnoughAdaForChangeOutput.
938- genTinySurplusTx
939- :: Exp. Era era
940- -> Gen
941- ( Exp. UnsignedTx (Exp. LedgerEra era )
942- , L. UTxO (Exp. LedgerEra era )
943- , L. Addr
944- )
945- genTinySurplusTx era = do
946- let sbe = convert era
947- txIn <- genTxIn
948- addr <- Api. toShelleyAddr <$> genAddressInEra sbe
949- changeAddr <- Api. toShelleyAddr <$> genAddressInEra sbe
950- sendCoin <- L. Coin <$> Gen. integral (Range. linear 2_000_000 5_000_000 )
951- -- Tiny margin above F1 but below F2. The exact fee F1 depends on the
952- -- generated address, but with test protocol params it's around 230–240.
953- -- A surplus of 240 + small_delta is enough to pass the first fee
954- -- convergence but not survive the fee increase from adding a change output.
955- -- We use a narrow range to stay within the F1-to-F2 gap (~23 lovelace).
956- surplus <- L. Coin <$> Gen. integral (Range. linear 237 250 )
957- let fundingCoin = sendCoin + surplus
958- let ledgerTxIn = Api. toShelleyTxIn txIn
959- fundingTxOut =
960- Exp. obtainCommonConstraints era $
961- L. mkBasicTxOut addr (L. MaryValue fundingCoin mempty )
962- utxo = L. UTxO $ Map. singleton ledgerTxIn fundingTxOut
963- sendTxOut =
964- Exp. obtainCommonConstraints era $
965- Exp. TxOut $
966- Ledger. mkBasicTxOut addr (L. MaryValue sendCoin mempty )
967- txBodyContent =
968- Exp. defaultTxBodyContent
969- & Exp. setTxIns [(txIn, Exp. AnyKeyWitnessPlaceholder )]
970- & Exp. setTxOuts [sendTxOut]
971- & Exp. setTxFee 0
972- return (Exp. makeUnsignedTx era txBodyContent, utxo, changeAddr)
973-
974- -- | When the surplus is just barely enough to cover the initial fee but not
975- -- the higher fee after adding a change output, the change output balance
976- -- goes negative and the function returns NotEnoughAdaForChangeOutput.
977- prop_calcMinFeeRecursive_tiny_surplus_not_enough_ada :: Property
978- prop_calcMinFeeRecursive_tiny_surplus_not_enough_ada = H. property $ do
979- (unsignedTx, utxo, changeAddr) <- H. forAll $ genTinySurplusTx Exp. ConwayEra
980- case Exp. calcMinFeeRecursive changeAddr unsignedTx utxo exampleProtocolParams mempty mempty mempty 0 of
981- Left (Exp. NotEnoughAdaForChangeOutput deficit) -> do
982- H. annotate $ " Deficit: " <> show deficit
983- H. assert $ deficit < L. Coin 0
984- Left (Exp. MinUTxONotMet actual required) -> do
985- -- If surplus - F2 >= 0 (barely), we may land in MinUTxONotMet instead.
986- -- This is also a valid failure for this border region.
987- H. annotate $ " Change output ADA: " <> show actual <> " , minUTxO: " <> show required
988- H. assert $ actual < required
989- Left err -> H. annotateShow err >> H. failure
990- Right _ ->
991- H. annotate " Expected NotEnoughAdaForChangeOutput or MinUTxONotMet but tx balanced successfully"
992- >> H. failure
0 commit comments