Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-enable Babbage-era minimum UTxO calculation for the Babbage era #3388

Merged
merged 10 commits into from
Jul 18, 2022
3 changes: 2 additions & 1 deletion lib/core-integration/src/Test/Integration/Framework/DSL.hs
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,8 @@ walletId =
-- | Min UTxO parameter for the test cluster.
minUTxOValue :: ApiEra -> Natural
minUTxOValue e
| e >= ApiBabbage = 999_920
| e >= ApiBabbage = 1_107_670 -- needs to be overestimated for the sake of
-- long byron addresses
| e >= ApiAlonzo = 999_978 -- From 34482 lovelace per word
| otherwise = 1_000_000

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,9 @@ spec = describe "SHELLEY_MIGRATIONS" $ do
-- entry as a freerider.

let perEntryAdaQuantity = Coin $ case _mainEra ctx of
e | e >= ApiAlonzo -> 3_100_000
| otherwise -> 3_300_000
e | e == ApiAlonzo -> 3_100_000
| e == ApiBabbage -> 2_500_000
| otherwise -> 3_300_000

let perEntryAssetCount = 10
let batchSize = 20
Expand Down Expand Up @@ -505,7 +506,7 @@ spec = describe "SHELLEY_MIGRATIONS" $ do
-- small enough to make the migration algorithm categorize the
-- entry as a freerider.
--
let perEntryAdaQuantity = Coin 1_562_500
let perEntryAdaQuantity = Coin 1_462_500
let perEntryAssetCount = 1
let batchSize = 20
sourceAddresses <- take 20 . map (getApiT . fst . view #id)
Expand All @@ -519,7 +520,7 @@ spec = describe "SHELLEY_MIGRATIONS" $ do

-- Check that minting was successful, and that the balance and UTxO
-- distribution have both changed accordingly:
let expectedBalanceAda = 287_500_000
let expectedBalanceAda = 275_500_000
let expectedAssetCount = 20
request @ApiWallet ctx
(Link.getWallet @'Shelley sourceWallet) Default Empty
Expand Down Expand Up @@ -565,9 +566,9 @@ spec = describe "SHELLEY_MIGRATIONS" $ do
, expectField id
((`shouldBe` 1) . apiPlanTotalOutputCount)
, expectField (#balanceSelected . #ada . #getQuantity)
(`shouldBe` 257_812_500)
(`shouldBe` 247_712_500)
, expectField (#balanceLeftover . #ada . #getQuantity)
(`shouldBe` 29_687_500)
(`shouldBe` 27_787_500)
, expectField (#balanceSelected . #assets . #getApiT)
((.> 0) . TokenMap.size)
, expectField (#balanceLeftover . #assets . #getApiT)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -952,8 +952,12 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do
{ testName =
"transaction with metadata from ADP-1005 (2 outputs)"
, txOutputAdaQuantities = \_minUTxOVal ->
-- The exact ada quantities recorded in ADP-1005:
[1_000_000, 498_283_127]
-- An ada quantity that is greater than or equal to the
-- minimum ada quantity for all known eras:
[ 1_107_670
-- The exact ada quantity recorded in ADP-1005:
, 498_283_127
]
, txMetadata =
Just txMetadata_ADP_1005
, expectedFee =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2697,7 +2697,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do

it "TRANS_NEW_JOIN_02 - Can join stakepool in case I have many UTxOs on 1 address"
$ \ctx -> runResourceT $ do
let amt = 1_000_000
let amt = minUTxOValue (_mainEra ctx)
src <- emptyWallet ctx
wa <- fixtureWallet ctx

Expand Down Expand Up @@ -3434,13 +3434,11 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do
-- UTxO plus additional adjusting of assets in output. Here, we are
-- having 80-byte (10-word) asset's additional burden
--
let lovelacePerUtxoWord =
let minUtxoWithAsset = minutxo +
-- The extra amount is dependent on the era:
if _mainEra ctx >= ApiBabbage
then 34480
-- Not sure why this differs... perhaps because of the new
-- minUTxO calculation. Should be fine nonethenless though.
else 34482
let minUtxoWithAsset = minutxo + 10*lovelacePerUtxoWord
then 176_710
else 344_820 -- = 34_482 lovelace per word * 10 words

eventually
"Wallet balance is decreased by fee and adjusted minimum UTxO and \
Expand Down
21 changes: 1 addition & 20 deletions lib/shelley/src/Cardano/Wallet/Shelley/Compatibility.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
-- Jörmungandr dual support.
{-# OPTIONS_GHC -fno-warn-orphans #-}

-- We have to use it until 'BabbageEra' appears in 'Cardano.Api'.
{-# OPTIONS_GHC -Wno-partial-type-signatures #-}

-- |
-- Copyright: © 2020 IOHK
-- License: Apache-2.0
Expand Down Expand Up @@ -280,8 +277,6 @@ import Data.ByteString.Short
( fromShort, toShort )
import Data.Coerce
( coerce )
import Data.Default
( Default (..) )
import Data.Foldable
( toList )
import Data.Function
Expand Down Expand Up @@ -918,19 +913,7 @@ fromBabbagePParams eraInfo currentNodeProtocolParameters pp =
, desiredNumberOfStakePools =
desiredNumberOfStakePoolsFromPParams pp
, minimumUTxO =
-- FIXME [ADP-1978] need to fix for final Babbage support ⚠️
--
-- We unexpectedly needed to increase @maxLengthAddress@ causing
-- tests to break in Babbage. Using the Alonzo calculation even in
-- Babbage is correct enough to make the integration tests to pass
-- in Babbage, and for us to be able to merge the Babbage
-- integration cluster support to master. This is not waterproof
-- though, and we should definitely use the babbage-specific
-- calculation.
minimumUTxOForShelleyBasedEra ShelleyBasedEraAlonzo $
def { Alonzo._coinsPerUTxOWord =
multiplyCoinBy 8 $ Babbage._coinsPerUTxOByte pp
}
minimumUTxOForShelleyBasedEra ShelleyBasedEraBabbage pp
, stakeKeyDeposit = stakeKeyDepositFromPParams pp
, eras = fromBoundToEpochNo <$> eraInfo
, maximumCollateralInputCount = unsafeIntToWord $
Expand All @@ -941,8 +924,6 @@ fromBabbagePParams eraInfo currentNodeProtocolParameters pp =
Just $ executionUnitPricesFromPParams pp
, currentNodeProtocolParameters
}
where
multiplyCoinBy a (SL.Coin c) = SL.Coin (a * c)

-- | Extract the current network decentralization level from the given set of
-- protocol parameters.
Expand Down
43 changes: 30 additions & 13 deletions lib/shelley/src/Cardano/Wallet/Shelley/MinimumUTxO.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ module Cardano.Wallet.Shelley.MinimumUTxO

import Prelude

import Cardano.Wallet.Api.Types
( DecodeAddress (..) )
import Cardano.Wallet.Primitive.AddressDerivation
( NetworkDiscriminant (..) )
import Cardano.Wallet.Primitive.Passphrase
( Passphrase (..) )
import Cardano.Wallet.Primitive.Types
( ProtocolMagic (..) )
import Cardano.Wallet.Primitive.Types.Address
( Address (..) )
import Cardano.Wallet.Primitive.Types.Coin
Expand All @@ -48,6 +48,11 @@ import Numeric.Natural
( Natural )

import qualified Cardano.Api.Shelley as Cardano
import qualified Cardano.Byron.Codec.Cbor as Byron
import qualified Cardano.Crypto.Wallet as CC
import qualified Codec.CBOR.Write as CBOR
import qualified Data.ByteArray as BA
import qualified Data.ByteString as BS

-- | Computes a minimum 'Coin' value for a 'TokenMap' that is destined for
-- inclusion in a transaction output.
Expand Down Expand Up @@ -145,17 +150,29 @@ embedTokenMapWithinPaddedTxOut era m =
-- for inclusion in a transaction output.
--
maxLengthAddress :: Address
maxLengthAddress = largeByronAddress
maxLengthAddress = longestByronAddrGeneratedByWallet
where
-- FIXME: It's imperative to return the largest possible address, which is a
-- byron address. The following is /a/ large one, but not necessarily /the
-- largest/:
largeByronAddress :: Address
largeByronAddress = unsafeDecodeAddr
"DdzFFzCqrht74rkP7eNhMp9iaQ79JQZzHX6QxjoFoie4qAn5D2MESx3Rzpqtc9zX6ASEdDT\
\hwJyqjc2kjqHMFnoUnC79GmmNCB9Vfe6a"
-- This should be the longest possible address the wallet can generate,
-- with a length of 86 bytes. (We can look at the callsites to encodeAddress
-- to confirm)
--
-- With 4310 lovelace/byte, the minimum utxo value for a pure-ada output is
-- now 1.107670 ada (according to /v2/network/information). The largest
-- possible overestimation should be (86-29) bytes, or 0.245670 ada.
longestByronAddrGeneratedByWallet = Address
$ CBOR.toStrictByteString
$ Byron.encodeAddress xpub
[ Byron.encodeDerivationPathAttr pwd maxBound maxBound
, Byron.encodeProtocolMagicAttr (ProtocolMagic maxBound)
]
where
unsafeDecodeAddr = either (error . show) id . decodeAddress @'Mainnet
-- Must apparently always be 32 bytes
pwd :: Passphrase "addr-derivation-payload"
pwd = Passphrase $ BA.convert $ BS.replicate 32 0

xpub = CC.toXPub $ CC.generate (BS.replicate 32 0) xprvPass
where
xprvPass = mempty :: BS.ByteString

-- | A 'Coin' value that is maximal in length when serialized to bytes.
--
Expand Down
28 changes: 12 additions & 16 deletions lib/shelley/test/unit/Cardano/Wallet/Shelley/MinimumUTxOSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,9 @@ spec = do
goldenTests_computeMinimumCoinForUTxO "Alonzo"
goldenMinimumUTxO_Alonzo
goldenMinimumCoins_Alonzo

-- FIXME [ADP-1978] Re-enable
--goldenTests_computeMinimumCoinForUTxO "Babbage"
-- goldenMinimumUTxO_Babbage
-- goldenMinimumCoins_Babbage
goldenTests_computeMinimumCoinForUTxO "Babbage"
goldenMinimumUTxO_Babbage
goldenMinimumCoins_Babbage

-- Check that it's possible to evaluate 'computeMinimumCoinForUTxO' without
-- any run-time error.
Expand Down Expand Up @@ -346,9 +344,8 @@ goldenMinimumUTxO_Alonzo =
minimumUTxOForShelleyBasedEra ShelleyBasedEraAlonzo
def {Alonzo._coinsPerUTxOWord = testParameter_coinsPerUTxOWord_Alonzo}

-- FIXME [ADP-1978] Re-enable
_goldenMinimumUTxO_Babbage :: MinimumUTxO
_goldenMinimumUTxO_Babbage =
goldenMinimumUTxO_Babbage :: MinimumUTxO
goldenMinimumUTxO_Babbage =
minimumUTxOForShelleyBasedEra ShelleyBasedEraBabbage
def {Babbage._coinsPerUTxOByte = testParameter_coinsPerUTxOByte_Babbage}

Expand Down Expand Up @@ -392,14 +389,13 @@ goldenMinimumCoins_Alonzo =
, (goldenTokenMap_4, Coin 1_862_028)
]

-- FIXME [ADP-1978] Re-enable
_goldenMinimumCoins_Babbage :: [(TokenMap, Coin)]
_goldenMinimumCoins_Babbage =
[ (goldenTokenMap_0, Coin 995_610)
, (goldenTokenMap_1, Coin 1_150_770)
, (goldenTokenMap_2, Coin 1_323_170)
, (goldenTokenMap_3, Coin 1_323_170)
, (goldenTokenMap_4, Coin 2_012_770)
goldenMinimumCoins_Babbage :: [(TokenMap, Coin)]
goldenMinimumCoins_Babbage =
[ (goldenTokenMap_0, Coin 1_107_670)
, (goldenTokenMap_1, Coin 1_262_830)
, (goldenTokenMap_2, Coin 1_435_230)
, (goldenTokenMap_3, Coin 1_435_230)
, (goldenTokenMap_4, Coin 2_124_830)
]

--------------------------------------------------------------------------------
Expand Down