@@ -12,10 +12,6 @@ module Cardano.Benchmarking.FundSet
12
12
where
13
13
import Prelude
14
14
15
- import Data.IxSet.Typed as IxSet
16
- import Data.Proxy
17
-
18
- import Control.Applicative ((<|>) )
19
15
import Cardano.Api as Api
20
16
21
17
-- Outputs that are available for spending.
@@ -26,50 +22,29 @@ data FundInEra era = FundInEra {
26
22
, _fundWitness :: Witness WitCtxTxIn era
27
23
, _fundVal :: ! (TxOutValue era )
28
24
, _fundSigningKey :: ! (Maybe (SigningKey PaymentKey ))
29
- , _fundVariant :: ! Variant
30
- , _fundValidity :: ! Validity
31
25
} deriving (Show )
32
26
33
- data Variant
34
- = PlainOldFund
35
- -- maybe better use the script itself instead of the filePath
36
- | PlutusScriptFund
37
- -- A collateralFund is just a regular (PlainOldFund) on the chain,
38
- -- but tagged in the wallet so that it is not selected for spending.
39
- | CollateralFund
40
- deriving (Show , Eq , Ord )
27
+ newtype Fund = Fund { unFund :: InAnyCardanoEra FundInEra }
41
28
42
- data Validity
43
- = Confirmed
44
- | InFlight ! Target ! SeqNumber
45
- deriving (Show , Eq , Ord )
29
+ type FundSet = [ Fund ]
46
30
47
- newtype Target = Target String
48
- deriving ( Show , Eq , Ord )
31
+ type FundSource m = m ( Either String [ Fund ])
32
+ type FundToStore m = [ Fund ] -> m ( )
49
33
50
34
newtype SeqNumber = SeqNumber Int
51
35
deriving (Show , Eq , Ord , Enum )
52
36
53
- newtype Fund = Fund { unFund :: InAnyCardanoEra FundInEra }
54
-
55
- getFundVariant :: Fund -> Variant
56
- getFundVariant (Fund (InAnyCardanoEra _ a)) = _fundVariant a
57
-
58
37
getFundTxIn :: Fund -> TxIn
59
38
getFundTxIn (Fund (InAnyCardanoEra _ a)) = _fundTxIn a
60
39
61
40
getFundKey :: Fund -> Maybe (SigningKey PaymentKey )
62
41
getFundKey (Fund (InAnyCardanoEra _ a)) = _fundSigningKey a
63
42
64
- getFundValidity :: Fund -> Validity
65
- getFundValidity (Fund (InAnyCardanoEra _ a)) = _fundValidity a
66
-
67
43
getFundLovelace :: Fund -> Lovelace
68
44
getFundLovelace (Fund (InAnyCardanoEra _ a)) = case _fundVal a of
69
45
TxOutAdaOnly _era l -> l
70
46
TxOutValue _era v -> selectLovelace v
71
47
72
-
73
48
-- This effectively rules out era-transitions for transactions !
74
49
-- This is not what we want !!
75
50
getFundWitness :: forall era . IsShelleyBasedEra era => Fund -> Witness WitCtxTxIn era
@@ -85,14 +60,6 @@ getFundWitness fund = case (cardanoEra @ era, fund) of
85
60
-- It should be possible to cast KeyWitnesses from one era to an other !
86
61
(_ , _) -> error " getFundWitness: era mismatch"
87
62
88
- data IsConfirmed = IsConfirmed | IsNotConfirmed
89
- deriving (Show , Eq , Ord )
90
-
91
- isConfirmed :: Fund -> IsConfirmed
92
- isConfirmed f = case getFundValidity f of
93
- Confirmed -> IsConfirmed
94
- InFlight _ _ -> IsNotConfirmed
95
-
96
63
instance Show Fund where
97
64
show (Fund (InAnyCardanoEra _ f)) = show f
98
65
@@ -105,32 +72,12 @@ instance Eq Fund where
105
72
instance Ord Fund where
106
73
compare a b = compare (getFundTxIn a) (getFundTxIn b)
107
74
108
- type FundIndices = '[ TxIn , IsConfirmed , Target , SeqNumber , Lovelace , Variant ]
109
- type FundSet = IxSet FundIndices Fund
110
-
111
- instance Indexable FundIndices Fund where
112
- indices = ixList
113
- (ixFun $ \ f -> [ getFundTxIn f ])
114
- (ixFun $ \ f -> [ isConfirmed f ])
115
- (ixFun $ \ f -> case getFundValidity f of
116
- Confirmed -> []
117
- InFlight t _ -> [t]
118
- )
119
- (ixFun $ \ f -> case getFundValidity f of
120
- Confirmed -> [SeqNumber (- 1 ) ] -- Confirmed Txs get SeqNumber -1
121
- InFlight _ n -> [ n ]
122
- )
123
- (ixFun $ \ f -> [ getFundLovelace f ])
124
- (ixFun $ \ f -> [ getFundVariant f ])
125
75
126
76
emptyFunds :: FundSet
127
- emptyFunds = IxSet. empty
77
+ emptyFunds = [ ]
128
78
129
79
insertFund :: FundSet -> Fund -> FundSet
130
- insertFund s f = updateIx (getFundTxIn f) f s
131
-
132
- deleteFund :: FundSet -> Fund -> FundSet
133
- deleteFund s f = deleteIx (getFundTxIn f) s
80
+ insertFund s f = f : s
134
81
135
82
liftAnyEra :: ( forall era . IsCardanoEra era => f1 era -> f2 era ) -> InAnyCardanoEra f1 -> InAnyCardanoEra f2
136
83
liftAnyEra f x = case x of
@@ -141,126 +88,6 @@ liftAnyEra f x = case x of
141
88
InAnyCardanoEra AlonzoEra a -> InAnyCardanoEra AlonzoEra $ f a
142
89
InAnyCardanoEra BabbageEra a -> InAnyCardanoEra BabbageEra $ f a
143
90
144
- type FundSelector = FundSet -> Either String [Fund ]
145
- type FundSource m = m (Either String [Fund ])
146
- type FundToStore m = [Fund ] -> m ()
147
-
148
- -- Select Funds to cover a minimum value.
149
- -- TODO:
150
- -- This fails unless there is a single fund with the required value
151
- -- Extend this to really return a list of funds.
152
- selectMinValue :: Lovelace -> FundSet -> Either String [Fund ]
153
- selectMinValue minValue fs = case coins of
154
- [] -> Left $ " findSufficientCoin: no single coin with min value >= " ++ show minValue
155
- (c: _) -> Right [c]
156
- where coins = toAscList ( Proxy :: Proxy Lovelace ) (fs @= PlainOldFund @= IsConfirmed @>= minValue)
157
-
158
- selectCollateral :: FundSet -> Either String [Fund ]
159
- selectCollateral fs = case coins of
160
- [] -> Left " no matching none-Plutus fund found"
161
- (c: _) -> Right [c]
162
- where
163
- coins = toAscList ( Proxy :: Proxy Lovelace ) (fs @= CollateralFund @= IsConfirmed )
164
-
165
- data AllowRecycle
166
- = UseConfirmedOnly
167
- | ReuseSameTarget
168
- -- ReuseAny can cause none-deterministic runtime errors !
169
- -- The problematic case is the reuse of an UTxO/Tx that is not yet confirmed
170
- -- and still waits in the mempool of an other target-node.
171
- | ReuseAny
172
- | ConfirmedBeforeReuse -- useful for testing
173
- deriving (Eq , Ord , Enum , Show )
174
-
175
- -- There are many possible heuristics to implement the selectInputs function.
176
- -- TODO: Check that the complexity of selectInputs is good enough.
177
- selectInputs ::
178
- AllowRecycle
179
- -> Int
180
- -> Lovelace
181
- -> Variant
182
- -> Target
183
- -> FundSet
184
- -> Either String [Fund ]
185
- selectInputs allowRecycle count minTotalValue variant targetNode fs
186
- = case allowRecycle of
187
- UseConfirmedOnly -> selectConfirmed
188
- ReuseSameTarget -> reuseSameTarget <|> selectConfirmed
189
- ReuseAny -> reuseSameTarget <|> selectConfirmed <|> reuseAnyCoin
190
- ConfirmedBeforeReuse -> selectConfirmed <|> reuseSameTarget
191
- where
192
- selectConfirmed = selectConfirmedSmallValue <|> selectConfirmedBigValue
193
-
194
- isSufficientCoins coins = length coins == count && sum (map getFundLovelace coins) >= minTotalValue
195
-
196
- checkCoins :: String -> [Fund ] -> Either String [Fund ]
197
- checkCoins err coins
198
- = if isSufficientCoins coins then Right coins else Left err
199
-
200
- -- Share intermediate results for variantIxSet confirmedIxSet and targetIxSet
201
- -- TODO: it unclear if this helps on the complexity or it it is even harmful.
202
- variantIxSet = fs @= variant
203
- confirmedIxSet = variantIxSet @= IsConfirmed
204
- targetIxSet = variantIxSet @= targetNode
205
-
206
- confirmedBigValueList = toDescList (Proxy :: Proxy Lovelace ) confirmedIxSet
207
- sameTargetList = toAscList (Proxy :: Proxy SeqNumber ) targetIxSet
208
-
209
- selectConfirmedSmallValue
210
- = checkCoins
211
- " selectConfirmedSmall: not enough coins available"
212
- (take count $ toAscList (Proxy :: Proxy Lovelace ) confirmedIxSet)
213
-
214
- selectConfirmedBigValue
215
- = checkCoins
216
- " selectConfirmedSmall: not enough coins available"
217
- (take count confirmedBigValueList)
218
-
219
- -- reuseSameTargetStrict is problematic: It fails if the coins in the queues are too small. But it will never consume the small coins.
220
- -- therefore: (reuseSameTargetStrict <|> reuseSameTargetWithBackup)
221
- reuseSameTargetStrict
222
- = checkCoins
223
- " reuseSameTargetStrict: not enough coins available"
224
- (take count sameTargetList)
225
-
226
- -- reuseSameTargetWithBackup can collect some dust.
227
- -- reuseSameTargetWithBackup works fine if there is at least one sufficient confirmed UTxO available.
228
- reuseSameTargetWithBackup = checkCoins " reuseSameTargetWithBackup: not enough coins available" (backupCoin ++ targetCoins)
229
- where
230
- -- targetCoins and backupCoins must be disjoint.
231
- -- This is case because IsConfirmed \= InFlight target.
232
- backupCoin = take 1 $ toAscList (Proxy :: Proxy Lovelace ) (confirmedIxSet @> minTotalValue)
233
- targetCoins = take (count - 1 ) sameTargetList
234
-
235
- reuseSameTarget = reuseSameTargetStrict <|> reuseSameTargetWithBackup
236
-
237
- -- reuseAnyCoin is the last resort !
238
- reuseAnyCoin
239
- = checkCoins
240
- " reuseAnyTarget: not enough coins available"
241
- (take count $ confirmedBigValueList ++ inFlightCoins)
242
- where
243
- -- inFlightCoins and confirmedCoins are disjoint
244
- inFlightCoins = toAscList (Proxy :: Proxy SeqNumber ) (variantIxSet @= IsNotConfirmed )
245
-
246
- selectToBuffer ::
247
- Int
248
- -> Lovelace
249
- -> Maybe Variant
250
- -> FundSet
251
- -> Either String [Fund ]
252
- selectToBuffer count minValue variant fs
253
- = if length coins < count
254
- then Left $ concat
255
- [ " selectToBuffer: not enough coins found: count: " , show count
256
- , " minValue: " , show minValue
257
- , " variant: " , show variant
258
- ]
259
- else Right coins
260
- where
261
- coins = case variant of
262
- Just v -> take count $ toAscList ( Proxy :: Proxy Lovelace ) (fs @= v @= IsConfirmed @>= minValue)
263
- Nothing -> take count $ toAscList ( Proxy :: Proxy Lovelace ) (fs @= IsConfirmed @>= minValue)
264
91
-- Todo: check sufficient funds and minimumValuePerUtxo
265
92
inputsToOutputsWithFee :: Lovelace -> Int -> [Lovelace ] -> [Lovelace ]
266
93
inputsToOutputsWithFee fee count inputs = map (quantityToLovelace . Quantity ) outputs
0 commit comments