Skip to content

Commit

Permalink
Add available{Balance,UTxO} accessor functions to UTxOSelection.
Browse files Browse the repository at this point in the history
The "available balance" is simply the sum of the selected and leftover
balances. It predicts what the selected balance would be if every single
UTxO were selected.

Similarly, the "available UTxO set" is the union of the selected and
leftover UTxO sets. It predicts what the selected UTxO set would be if
every single UTxO were selected.

The available balance and the available UTxO set both remain constant
over applications of `select` and `selectMany`.

This commit adds tests to verify that this is the case.
  • Loading branch information
jonathanknowles committed Sep 28, 2021
1 parent ed1c8b8 commit 1e42ed0
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
31 changes: 31 additions & 0 deletions lib/core/src/Cardano/Wallet/Primitive/Types/UTxOSelection.hs
Expand Up @@ -61,6 +61,8 @@ module Cardano.Wallet.Primitive.Types.UTxOSelection
, isProperSubSelectionOf

-- * Accessor functions
, availableBalance
, availableUTxO
, leftoverBalance
, leftoverSize
, leftoverIndex
Expand Down Expand Up @@ -298,6 +300,35 @@ isProperSubSelectionOf u1 u2 = state u1 /= state u2 && u1 `isSubSelectionOf` u2
-- Accessor functions
--------------------------------------------------------------------------------

-- | Computes the available balance.
--
-- The available balance is the sum of the selected and the leftover balances.
--
-- It predicts what 'selectedBalance' would be if every single UTxO were
-- selected.
--
-- This result of this function remains constant over applications of 'select'
-- and 'selectMany':
--
-- >>> availableBalance u == availableBalance (selectMany is u)
--
availableBalance :: IsUTxOSelection u => u -> TokenBundle
availableBalance u = leftoverBalance u <> selectedBalance u

-- | Computes the available UTxO set.
--
-- The available UTxO set is the union of the selected and leftover UTxO sets.
--
-- It predicts what 'selectedUTxO' would be if every single UTxO were selected.
--
-- This result of this function remains constant over applications of 'select'
-- and 'selectMany':
--
-- >>> availableUTxO u == availableUTxO (selectMany is u)
--
availableUTxO :: IsUTxOSelection u => u -> UTxO
availableUTxO u = leftoverUTxO u <> selectedUTxO u

-- | Retrieves the balance of leftover UTxOs.
--
leftoverBalance :: IsUTxOSelection u => u -> TokenBundle
Expand Down
Expand Up @@ -43,6 +43,7 @@ import Test.QuickCheck
)

import qualified Cardano.Wallet.Primitive.Types.TokenBundle as TokenBundle
import qualified Cardano.Wallet.Primitive.Types.UTxO as UTxO
import qualified Cardano.Wallet.Primitive.Types.UTxOIndex as UTxOIndex
import qualified Cardano.Wallet.Primitive.Types.UTxOSelection as UTxOSelection

Expand Down Expand Up @@ -85,6 +86,8 @@ spec =

parallel $ describe "Indicator and accessor functions" $ do

it "prop_availableBalance_availableUTxO" $
property prop_availableBalance_availableUTxO
it "prop_isNonEmpty_selectedSize" $
property prop_isNonEmpty_selectedSize
it "prop_isNonEmpty_selectedIndex" $
Expand All @@ -108,6 +111,10 @@ spec =
property prop_select_isSelected
it "prop_select_isProperSubSelectionOf" $
property prop_select_isProperSubSelectionOf
it "prop_select_availableBalance" $
property prop_select_availableBalance
it "prop_select_availableUTxO" $
property prop_select_availableUTxO
it "prop_select_leftoverSize" $
property prop_select_leftoverSize
it "prop_select_selectedSize" $
Expand Down Expand Up @@ -223,6 +230,12 @@ prop_toNonEmpty_fromNonEmpty s =
-- Indicator and accessor functions
--------------------------------------------------------------------------------

prop_availableBalance_availableUTxO :: UTxOSelection -> Property
prop_availableBalance_availableUTxO s =
checkCoverage_UTxOSelection s $
UTxOSelection.availableBalance s
=== UTxO.balance (UTxOSelection.availableUTxO s)

prop_isNonEmpty_selectedSize :: UTxOSelection -> Property
prop_isNonEmpty_selectedSize s =
checkCoverage_UTxOSelection s $
Expand Down Expand Up @@ -293,6 +306,24 @@ prop_select_isProperSubSelectionOf i s =
===
if UTxOSelection.isLeftover i s then Just True else Nothing

prop_select_availableBalance :: TxIn -> UTxOSelection -> Property
prop_select_availableBalance i s =
checkCoverage_select i s $
(UTxOSelection.availableBalance <$> UTxOSelection.select i s)
===
if UTxOSelection.isLeftover i s
then Just (UTxOSelection.availableBalance s)
else Nothing

prop_select_availableUTxO :: TxIn -> UTxOSelection -> Property
prop_select_availableUTxO i s =
checkCoverage_select i s $
(UTxOSelection.availableUTxO <$> UTxOSelection.select i s)
===
if UTxOSelection.isLeftover i s
then Just (UTxOSelection.availableUTxO s)
else Nothing

prop_select_leftoverSize :: TxIn -> UTxOSelection -> Property
prop_select_leftoverSize i s =
checkCoverage_select i s $
Expand Down

0 comments on commit 1e42ed0

Please sign in to comment.