Skip to content

Commit

Permalink
Merge #2884
Browse files Browse the repository at this point in the history
2884: Don't require all minted assets to be spent or burned r=jonathanknowles a=jonathanknowles

### Issue Number

ADP-1113

### Summary

This PR removes the restriction that all minted assets must be spent or burned.

Minted assets that are not spent or burned are now returned in the change outputs.

Co-authored-by: Jonathan Knowles <jonathan.knowles@iohk.io>
  • Loading branch information
iohk-bors[bot] and jonathanknowles committed Sep 16, 2021
2 parents bb05335 + 692da31 commit a5a29b7
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 205 deletions.
8 changes: 0 additions & 8 deletions lib/core/src/Cardano/Wallet/Api/Server.hs
Expand Up @@ -361,7 +361,6 @@ import Cardano.Wallet.Primitive.CoinSelection.Balance
( SelectionResult (..)
, UnableToConstructChangeError (..)
, balanceMissing
, missingOutputAssets
, selectionDelta
)
import Cardano.Wallet.Primitive.Delegation.UTxO
Expand Down Expand Up @@ -3821,13 +3820,6 @@ instance IsServerError ErrSelectAssets where
, "must specify enough ada. Here are the problematic "
, "outputs:\n" <> pretty (indentF 2 $ blockListF xs)
]
Balance.OutputsInsufficient e ->
apiError err403 TokensMintedButNotSpentOrBurned $ mconcat
[ "I can't process this transaction because some "
, "minted values were not spent or burned. These "
, "are the values that should be spent or burned: "
, pretty . Flat $ missingOutputAssets e
]
Balance.UnableToConstructChange e ->
apiError err403 CannotCoverFee $ T.unwords
[ "I am unable to finalize the transaction, as there"
Expand Down
58 changes: 0 additions & 58 deletions lib/core/src/Cardano/Wallet/Primitive/CoinSelection/Balance.hs
Expand Up @@ -38,7 +38,6 @@ module Cardano.Wallet.Primitive.CoinSelection.Balance
, SelectionResult (..)
, SelectionError (..)
, BalanceInsufficientError (..)
, OutputsInsufficientError (..)
, SelectionInsufficientError (..)
, InsufficientMinCoinValueError (..)
, UnableToConstructChangeError (..)
Expand Down Expand Up @@ -115,7 +114,6 @@ module Cardano.Wallet.Primitive.CoinSelection.Balance
, distance
, mapMaybe
, balanceMissing
, missingOutputAssets
) where

import Prelude
Expand Down Expand Up @@ -507,56 +505,11 @@ data SelectionError
SelectionInsufficientError
| InsufficientMinCoinValues
(NonEmpty InsufficientMinCoinValueError)
| OutputsInsufficient
OutputsInsufficientError
| UnableToConstructChange
UnableToConstructChangeError
| EmptyUTxO
deriving (Generic, Eq, Show)

-- | Indicates that a portion of the minted assets were not spent or burned.
--
-- This situation occurs if the following inequality does not hold:
--
-- >>> assetsToMint `leq` (assetsToBurn <> requestedOutputAssets)
--
-- The existence of this error reflects a deliberate design choice: all minted
-- assets must either be explicitly spent or explicitly burned by the caller.
-- In future, we could revise this design to allow excess minted assets (those
-- that are neither spent nor burned) to be returned to the wallet as change.
--
data OutputsInsufficientError = OutputsInsufficientError
{ assetsToMint
:: !TokenMap
-- ^ The assets to mint
, assetsToBurn
:: !TokenMap
-- ^ The assets to burn
, requestedOutputAssets
:: !TokenMap
-- ^ The complete set of assets found within the user-specified outputs
} deriving (Generic, Eq, Show)

-- | Computes the portion of minted assets that are not spent or burned.
--
missingOutputAssets :: OutputsInsufficientError -> TokenMap
missingOutputAssets e =
-- We use 'difference' which will show us the quantities in 'assetsToMint'
-- that are not in 'assetsToBurn <> requestedOutputAssets'.
--
-- Any asset quantity present in 'assetsToBurn <> requestedOutputAssets'
-- but not present in 'assetsToMint' will simply be zeroed out, which is
-- the behaviour we want for this error report.
--
assetsToMint `TokenMap.difference`
(assetsToBurn `TokenMap.add` requestedOutputAssets)
where
OutputsInsufficientError
{ assetsToMint
, assetsToBurn
, requestedOutputAssets
} = e

-- | Indicates that the balance of selected UTxO entries was insufficient to
-- cover the balance required.
--
Expand Down Expand Up @@ -684,11 +637,6 @@ performSelection
-- ^ The selection goal to satisfy.
-> m (Either SelectionError (SelectionResult TokenBundle))
performSelection minCoinFor costFor bundleSizeAssessor criteria
-- Is the minted value all spent or burnt?
| not (assetsToMint `leq` (assetsToBurn <> requestedOutputAssets)) =
pure $ Left $ OutputsInsufficient $ OutputsInsufficientError
{assetsToMint, assetsToBurn, requestedOutputAssets}

-- Is the total available UTXO balance sufficient?
| not utxoBalanceSufficient =
pure $ Left $ BalanceInsufficient $ BalanceInsufficientError
Expand Down Expand Up @@ -733,12 +681,6 @@ performSelection minCoinFor costFor bundleSizeAssessor criteria
, utxoBalanceRequired
}

requestedOutputBalance :: TokenBundle
requestedOutputBalance = F.foldMap (view #tokens) outputsToCover

requestedOutputAssets :: TokenMap
requestedOutputAssets = view #tokens requestedOutputBalance

mkInputsSelected :: UTxOIndex -> NonEmpty (TxIn, TxOut)
mkInputsSelected =
fromMaybe invariantSelectAnyInputs . NE.nonEmpty . UTxOIndex.toList
Expand Down

0 comments on commit a5a29b7

Please sign in to comment.