@@ -27,12 +27,21 @@ type WalletRef = MVar FundSet
27
27
type TxGenerator era = [Fund ] -> [TxOut CtxTx era ] -> Either String (Tx era , TxId )
28
28
29
29
type ToUTxO era = Lovelace -> (TxOut CtxTx era , TxIx -> TxId -> Fund )
30
+ type ToUTxOList era split = split -> ([TxOut CtxTx era ], TxId -> [Fund ])
31
+
32
+ type CreateAndStore m era = Lovelace -> (TxOut CtxTx era , TxIx -> TxId -> m () )
33
+
34
+ type CreateAndStoreList m era split = split -> ([TxOut CtxTx era ], TxId -> m () )
30
35
31
- -- todo: inline inToOut :: [Lovelace] -> [Lovelace] and FundToStore
32
- type ToUTxOList era = [Lovelace ] -> ([TxOut CtxTx era ], TxId -> [Fund ])
33
36
-- 'ToUTxOList era' is more powerful than '[ ToUTxO era ]' but
34
37
-- '[ ToUTxO era ]` is easier to construct.
35
38
39
+ createAndStore :: ToUTxO era -> (Fund -> m () ) -> CreateAndStore m era
40
+ createAndStore create store lovelace = (utxo, toStore)
41
+ where
42
+ (utxo, mkFund) = create lovelace
43
+ toStore txIx txId = store $ mkFund txIx txId
44
+
36
45
initWallet :: IO WalletRef
37
46
initWallet = newMVar emptyFundSet
38
47
@@ -44,16 +53,20 @@ askWalletRef r f = do
44
53
walletRefInsertFund :: WalletRef -> Fund -> IO ()
45
54
walletRefInsertFund ref fund = modifyMVar_ ref $ \ w -> return $ FundSet. insertFund w fund
46
55
47
- mkWalletFundStore :: WalletRef -> FundToStore IO
48
- mkWalletFundStore walletRef funds = modifyMVar_ walletRef
56
+ mkWalletFundStoreList :: WalletRef -> FundToStoreList IO
57
+ mkWalletFundStoreList walletRef funds = modifyMVar_ walletRef
49
58
$ \ wallet -> return (foldl FundSet. insertFund wallet funds)
50
59
60
+ mkWalletFundStore :: WalletRef -> FundToStore IO
61
+ mkWalletFundStore walletRef fund = modifyMVar_ walletRef
62
+ $ \ wallet -> return $ FundSet. insertFund wallet fund
63
+
51
64
walletSource :: WalletRef -> Int -> FundSource IO
52
65
walletSource ref munch = modifyMVar ref $ \ fifo -> return $ case Fifo. removeN munch fifo of
53
66
Nothing -> (fifo, Left " WalletSource: out of funds" )
54
67
Just (newFifo, funds) -> (newFifo, Right funds)
55
68
56
- makeToUTxOList :: [ ToUTxO era ] -> ToUTxOList era
69
+ makeToUTxOList :: [ ToUTxO era ] -> ToUTxOList era [ Lovelace ]
57
70
makeToUTxOList fkts values
58
71
= (outs, \ txId -> map (\ f -> f txId) fs)
59
72
where
@@ -62,14 +75,32 @@ makeToUTxOList fkts values
62
75
= let (o, f ) = toUTxO value
63
76
in (o, f idx)
64
77
78
+ data PayWithChange
79
+ = PayExact [Lovelace ]
80
+ | PayWithChange Lovelace [Lovelace ]
81
+
82
+ mangleWithChange :: Monad m => CreateAndStore m era -> CreateAndStore m era -> CreateAndStoreList m era PayWithChange
83
+ mangleWithChange mkChange mkPayment outs = case outs of
84
+ PayExact l -> mangle (repeat mkPayment) l
85
+ PayWithChange change payments -> mangle (mkChange : repeat mkPayment) (change : payments)
86
+
87
+ mangle :: Monad m => [ CreateAndStore m era ] -> CreateAndStoreList m era [ Lovelace ]
88
+ mangle fkts values
89
+ = (outs, \ txId -> mapM_ (\ f -> f txId) fs)
90
+ where
91
+ (outs, fs) = unzip $ map worker $ zip3 fkts values [TxIx 0 .. ]
92
+ worker (toUTxO, value, idx)
93
+ = let (o, f ) = toUTxO value
94
+ in (o, f idx)
95
+
65
96
-- TODO use Error monad
66
97
-- TODO need to break this up
67
98
sourceToStoreTransaction ::
68
99
TxGenerator era
69
100
-> FundSource IO
70
- -> ([Lovelace ] -> [ Lovelace ]) -- inline to ToUTxOList
71
- -> ToUTxOList era
72
- -> FundToStore IO -- inline to ToUTxOList
101
+ -> ([Lovelace ] -> split )
102
+ -> ToUTxOList era split
103
+ -> FundToStoreList IO -- inline to ToUTxOList
73
104
-> IO (Either String (Tx era ))
74
105
sourceToStoreTransaction txGenerator fundSource inToOut mkTxOut fundToStore = do
75
106
fundSource >>= \ case
@@ -86,13 +117,41 @@ sourceToStoreTransaction txGenerator fundSource inToOut mkTxOut fundToStore = do
86
117
fundToStore $ toFunds txId
87
118
return $ Right tx
88
119
120
+ sourceToStoreTransactionNew ::
121
+ TxGenerator era
122
+ -> FundSource IO
123
+ -> ([Lovelace ] -> split )
124
+ -> CreateAndStoreList IO era split
125
+ -> IO (Either String (Tx era ))
126
+ sourceToStoreTransactionNew txGenerator fundSource valueSplitter toStore = do
127
+ fundSource >>= \ case
128
+ Left err -> return $ Left err
129
+ Right inputFunds -> work inputFunds
130
+ where
131
+ work inputFunds = do
132
+ let
133
+ split = valueSplitter $ map getFundLovelace inputFunds
134
+ (outputs, storeAction) = toStore split
135
+ case txGenerator inputFunds outputs of
136
+ Left err -> return $ Left err
137
+ Right (tx, txId) -> do
138
+ storeAction txId
139
+ return $ Right tx
140
+
89
141
includeChange :: Lovelace -> [Lovelace ] -> [Lovelace ] -> [Lovelace ]
90
142
includeChange fee spend have = case compare changeValue 0 of
91
143
GT -> changeValue : spend
92
144
EQ -> spend
93
145
LT -> error " genTX: Bad transaction: insufficient funds"
94
146
where changeValue = sum have - sum spend - fee
95
147
148
+ includeChangeNew :: Lovelace -> [Lovelace ] -> [Lovelace ] -> PayWithChange
149
+ includeChangeNew fee spend have = case compare changeValue 0 of
150
+ GT -> PayWithChange changeValue spend
151
+ EQ -> PayExact spend
152
+ LT -> error " genTX: Bad transaction: insufficient funds"
153
+ where changeValue = sum have - sum spend - fee
154
+
96
155
mkUTxOVariant :: forall era . IsShelleyBasedEra era
97
156
=> NetworkId
98
157
-> SigningKey PaymentKey
@@ -195,26 +254,23 @@ data WalletStep era
195
254
| Error String
196
255
197
256
-- TODO:
198
- -- use explicit tx- counter for each walletscript
199
- -- Do not rely on global walletSeqNum
257
+ -- Define generator for a single transaction and define combinator for
258
+ -- repeat and sequence.
259
+
260
+
200
261
benchmarkWalletScript :: forall era .
201
262
IsShelleyBasedEra era
202
- => WalletRef
203
- -> TxGenerator era
263
+ => IO (Either String (Tx era )) -- make polymorphic
204
264
-> NumberOfTxs
205
- -> FundSource IO
206
- -> ([Lovelace ] -> [Lovelace ])
207
- -> [ToUTxO era ]
208
- -> FundToStore IO
209
265
-> WalletScript era
210
- benchmarkWalletScript wRef txGenerator totalCount fundSource inOut toUTxO fundToStore
266
+ benchmarkWalletScript sourceToStore totalCount
211
267
= WalletScript $ walletStep totalCount
212
268
where
213
269
walletStep :: NumberOfTxs -> IO (WalletStep era )
214
270
walletStep (NumberOfTxs 0 ) = return Done
215
- walletStep count = sourceToStoreTransaction txGenerator fundSource inOut (makeToUTxOList toUTxO) fundToStore >>= \ case
271
+ walletStep count = sourceToStore >>= \ case
216
272
Left err -> return $ Error err
217
- Right tx -> return $ NextTx (benchmarkWalletScript wRef txGenerator (pred count) fundSource inOut toUTxO fundToStore ) tx
273
+ Right tx -> return $ NextTx (benchmarkWalletScript sourceToStore (pred count)) tx
218
274
219
275
limitSteps ::
220
276
NumberOfTxs
0 commit comments