Copyright | © 2018-2024 Intersect MBO |
---|---|
License | Apache-2.0 |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
Provides functionality for adjusting coin selections in order to pay for transaction fees.
Synopsis
- newtype Fee = Fee {}
- newtype FeeEstimator i o = FeeEstimator {
- estimateFee :: CoinSelection i o -> Fee
- adjustForFee :: (Ord i, MonadRandom m) => FeeOptions i o -> CoinMap i -> CoinSelection i o -> ExceptT (FeeAdjustmentError i o) m (CoinSelection i o)
- data FeeOptions i o = FeeOptions {}
- data FeeBalancingPolicy
- data FeeAdjustmentError i o
- newtype DustThreshold = DustThreshold {}
- isDust :: DustThreshold -> Coin -> Bool
- coalesceDust :: DustThreshold -> NonEmpty Coin -> [Coin]
Fundamental Types
Represents a non-negative fee to be paid on a transaction.
Since: 1.0.0
newtype FeeEstimator i o Source #
Provides a function capable of estimating the transaction fee required for a given coin selection, according to the rules of a particular blockchain.
The fee estimate should be a function of the current memberships of the
inputs
, outputs
, and change
sets.
Depending on the rules of the blockchain under consideration, the fee estimate may take either (or both) of the following factors into account:
- the number of entries in each set;
- the coin value of each set member.
A fee estimate may differ from the final fee required for a selection, as
fees are generally paid for by adjusting a given selection to make a new
selection. See adjustForFee
for more details of this process.
Since: 1.0.0
FeeEstimator | |
|
Instances
Generic (FeeEstimator i o) Source # | |
Defined in Cardano.CoinSelection.Fee from :: FeeEstimator i o -> Rep (FeeEstimator i o) x Source # to :: Rep (FeeEstimator i o) x -> FeeEstimator i o Source # | |
type Rep (FeeEstimator i o) Source # | |
Defined in Cardano.CoinSelection.Fee type Rep (FeeEstimator i o) = D1 ('MetaData "FeeEstimator" "Cardano.CoinSelection.Fee" "cardano-coin-selection-1.0.1-inplace" 'True) (C1 ('MetaCons "FeeEstimator" 'PrefixI 'True) (S1 ('MetaSel ('Just "estimateFee") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (CoinSelection i o -> Fee)))) |
Fee Adjustment
adjustForFee :: (Ord i, MonadRandom m) => FeeOptions i o -> CoinMap i -> CoinSelection i o -> ExceptT (FeeAdjustmentError i o) m (CoinSelection i o) Source #
Adjusts the given CoinSelection
in order to pay for a transaction
fee, required in order to publish the selection as a transaction on
a blockchain.
Background
Implementations of CoinSelectionAlgorithm
generally
produce coin selections that are exactly balanced, satisfying the
following equality:
>>>
sumInputs s = sumOutputs s + sumChange s
In order to pay for a transaction fee, the above equality must be transformed into an inequality:
>>>
sumInputs s > sumOutputs s + sumChange s
The difference between these two sides represents value to be paid by the originator of the transaction, in the form of a fee:
>>>
sumInputs s = sumOutputs s + sumChange s + fee
The Adjustment Process
In order to generate a fee that is acceptable to the network, this function
adjusts the change
and inputs
of the given CoinSelection
, consulting
the FeeEstimator
as a guide for how much the current selection would cost
to publish as a transaction on the network.
Methods of Adjustment
There are two methods of adjustment possible:
The
change
set can be reduced, either by:a. completely removing a change value from the set; or by
b. reducing a change value to a lower value.
- The
inputs
set can be augmented, by selecting additional inputs from the specifiedCoinMap
argument.
Dealing with Dust Values
If, at any point, a change value is generated that is less than or equal
to the DustThreshold
, this function will eliminate that change value
from the change
set, redistributing the eliminated value over the remaining
change values, ensuring that the total value of all change
is preserved.
See coalesceDust
for more details.
Termination
Since adjusting a selection can affect the fee estimate produced by
estimateFee
, the process of adjustment is an iterative process.
The termination post-condition depends on the choice of
FeeBalancingPolicy
:
If
RequireBalancedFee
is specified, this function terminates only when it has generated aCoinSelection
s
that satisfies the following property:>>>
sumInputs s = sumOutputs s + sumChange s + estimateFee s
If
RequireMinimalFee
policy is specified, the above equality is relaxed to the following inequality:>>>
sumInputs s ≥ sumOutputs s + sumChange s + estimateFee s
See FeeBalancingPolicy
for more details.
Since: 1.0.0
data FeeOptions i o Source #
Provides options for fee adjustment.
Since: 1.0.0
FeeOptions | |
|
Instances
Generic (FeeOptions i o) Source # | |
Defined in Cardano.CoinSelection.Fee from :: FeeOptions i o -> Rep (FeeOptions i o) x Source # to :: Rep (FeeOptions i o) x -> FeeOptions i o Source # | |
type Rep (FeeOptions i o) Source # | |
Defined in Cardano.CoinSelection.Fee type Rep (FeeOptions i o) = D1 ('MetaData "FeeOptions" "Cardano.CoinSelection.Fee" "cardano-coin-selection-1.0.1-inplace" 'False) (C1 ('MetaCons "FeeOptions" 'PrefixI 'True) (S1 ('MetaSel ('Just "feeEstimator") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (FeeEstimator i o)) :*: (S1 ('MetaSel ('Just "dustThreshold") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 DustThreshold) :*: S1 ('MetaSel ('Just "feeBalancingPolicy") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 FeeBalancingPolicy)))) |
data FeeBalancingPolicy Source #
A choice of fee balancing policies for use when adjusting a coin selection.
Background
A coin selection s
is said to have a perfectly-balanced fee when it
satisfies the following property:
>>>
sumInputs s = sumOutputs s + sumChange s + estimateFee s
Conversely, a selection is said to have an unbalanced fee when it satisfies the following property:
>>>
sumInputs s > sumOutputs s + sumChange s + estimateFee s
In other words, if a coin selection has an unbalanced fee, the effective fee is greater than the minimum fee actually required by the blockchain.
Balanced Fees vs Minimal Fees
Some blockchains require that fees are always perfectly-balanced.
However, for blockchains that allow unbalanced fees, it is sometimes
possible to save money by generating a coin selection with an unbalanced
fee. This may seem counterintuitive at first, but consider an individual
change output c of value v. If the marginal fee f
associated with c is greater than its value v, then we will
save money by not including c within change
.
There are two policy choices available for handling change values with marginal fees greater than their value:
- For blockchains that allow transactions with unbalanced fees,
specifying the
RequireMinimalFee
policy will allow money to be saved by excluding change outputs that have a marginal fee greater than their value. - For blockchains that do not allow transactions with unbalanced
fees, specifying the
RequireBalancedFee
policy will always generate selections with fees that are perfectly-balanced, even if the resulting fees are higher than could be achieved by allowing unbalanced fees.
RequireBalancedFee | Generate selections with fees that are perfectly balanced, with the trade-off of allowing slightly higher fees. |
RequireMinimalFee | Generate selections with the lowest fees possible, with the trade-off of allowing slightly imbalanced fees. |
Instances
Generic FeeBalancingPolicy Source # | |
Defined in Cardano.CoinSelection.Fee from :: FeeBalancingPolicy -> Rep FeeBalancingPolicy x Source # to :: Rep FeeBalancingPolicy x -> FeeBalancingPolicy Source # | |
Show FeeBalancingPolicy Source # | |
Defined in Cardano.CoinSelection.Fee | |
Eq FeeBalancingPolicy Source # | |
Defined in Cardano.CoinSelection.Fee (==) :: FeeBalancingPolicy -> FeeBalancingPolicy -> Bool Source # (/=) :: FeeBalancingPolicy -> FeeBalancingPolicy -> Bool Source # | |
type Rep FeeBalancingPolicy Source # | |
Defined in Cardano.CoinSelection.Fee |
data FeeAdjustmentError i o Source #
Represents the set of possible failures that can occur when adjusting a
CoinSelection
with the adjustForFee
function.
CannotCoverFee Fee | Indicates that the given map of additional inputs was exhausted while attempting to select extra inputs to cover the required fee. Records the shortfall (f − s) between the required fee f and the total value s of currently-selected inputs. |
CoinSelectionUnderfunded (CoinSelection i o) | Indicates that the given coin selection is underfunded: the total
value of |
Instances
(Show i, Show o) => Show (FeeAdjustmentError i o) Source # | |
Defined in Cardano.CoinSelection.Fee | |
(Eq i, Eq o) => Eq (FeeAdjustmentError i o) Source # | |
Defined in Cardano.CoinSelection.Fee (==) :: FeeAdjustmentError i o -> FeeAdjustmentError i o -> Bool Source # (/=) :: FeeAdjustmentError i o -> FeeAdjustmentError i o -> Bool Source # |
Dust Processing
newtype DustThreshold Source #
Defines the maximum size of a dust coin.
Functions that accept a DustThreshold
argument will generally exclude
values that are less than or equal to this threshold from the change
sets of generated selections, coalescing such coins together into larger
coins that exceed the threshold.
Specifying a dust threshold of n causes all coins that are less than or equal to n to be treated as dust and coalesced together.
Specifying a dust threshold of 0 completely disables dust elimination with the exception of zero-valued coins, which will always be eliminated.
See coalesceDust
.
Since: 1.0.0
Instances
isDust :: DustThreshold -> Coin -> Bool Source #
Returns True
if and only if the given Coin
is a dust coin
according to the given DustThreshold
.
A coin is considered to be a dust coin if it is less than or equal to the threshold.
See DustThreshold
.
Since: 1.0.1
coalesceDust :: DustThreshold -> NonEmpty Coin -> [Coin] Source #
From the given list of coins, remove dust coins with a value less than or equal to the given threshold value, redistributing their total value over the coins that remain.
This function satisfies the following properties:
>>>
sum coins = sum (coalesceDust threshold coins)
>>>
all (/= Coin 0) (coalesceDust threshold coins)