1
+ {-# LANGUAGE DataKinds #-}
2
+ {-# LANGUAGE DeriveAnyClass #-}
3
+ {-# LANGUAGE DeriveGeneric #-}
4
+ {-# LANGUAGE DerivingVia #-}
5
+ {-# LANGUAGE FlexibleContexts #-}
6
+ {-# LANGUAGE FlexibleInstances #-}
7
+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
8
+ {-# LANGUAGE MultiParamTypeClasses #-}
9
+ {-# LANGUAGE OverloadedStrings #-}
10
+ {-# LANGUAGE PatternSynonyms #-}
11
+ {-# LANGUAGE ScopedTypeVariables #-}
12
+ {-# LANGUAGE StandaloneDeriving #-}
13
+ {-# LANGUAGE TypeApplications #-}
14
+ {-# LANGUAGE TypeFamilies #-}
15
+ {-# LANGUAGE UndecidableInstances #-}
16
+ {-# LANGUAGE UndecidableSuperClasses #-}
17
+ {-# LANGUAGE ViewPatterns #-}
18
+ {-# OPTIONS_GHC -Wno-orphans #-}
19
+
1
20
module Cardano.Ledger.Allegra.TxBody (
2
21
AllegraEraTxBody (.. ),
3
22
AllegraTxBody (
@@ -19,4 +38,333 @@ module Cardano.Ledger.Allegra.TxBody (
19
38
)
20
39
where
21
40
22
- import Cardano.Ledger.Allegra.TxBody.Internal
41
+ import Cardano.Ledger.Allegra.Era (AllegraEra )
42
+ import Cardano.Ledger.Allegra.Scripts (ValidityInterval (.. ))
43
+ import Cardano.Ledger.Allegra.TxCert ()
44
+ import Cardano.Ledger.Allegra.TxOut ()
45
+ import Cardano.Ledger.BaseTypes (SlotNo , StrictMaybe (SJust , SNothing ))
46
+ import Cardano.Ledger.Binary (DecCBOR (.. ), EncCBOR (.. ), ToCBOR )
47
+ import Cardano.Ledger.Binary.Coders (
48
+ Decode (.. ),
49
+ Encode (.. ),
50
+ Field ,
51
+ decode ,
52
+ encode ,
53
+ encodeKeyedStrictMaybe ,
54
+ field ,
55
+ invalidField ,
56
+ ofield ,
57
+ (!>) ,
58
+ )
59
+ import Cardano.Ledger.Coin (Coin (.. ))
60
+ import Cardano.Ledger.Compactible (Compactible (.. ))
61
+ import Cardano.Ledger.Core
62
+ import Cardano.Ledger.MemoBytes (
63
+ EqRaw ,
64
+ MemoBytes ,
65
+ MemoHashIndex ,
66
+ Memoized (RawType ),
67
+ getMemoRawType ,
68
+ getMemoSafeHash ,
69
+ lensMemoRawType ,
70
+ mkMemoizedEra ,
71
+ )
72
+ import Cardano.Ledger.Shelley.Core
73
+ import Cardano.Ledger.Shelley.PParams (Update (.. ), upgradeUpdate )
74
+ import Cardano.Ledger.Shelley.TxBody (getShelleyGenesisKeyHashCountTxBody )
75
+ import Cardano.Ledger.TxIn (TxIn (.. ))
76
+ import Control.DeepSeq (NFData (.. ))
77
+ import qualified Data.Map.Strict as Map
78
+ import Data.Sequence.Strict (StrictSeq , fromList )
79
+ import Data.Set (Set , empty )
80
+ import GHC.Generics (Generic )
81
+ import Lens.Micro
82
+ import NoThunks.Class (NoThunks (.. ))
83
+
84
+ class EraTxBody era => AllegraEraTxBody era where
85
+ vldtTxBodyL :: Lens' (TxBody era ) ValidityInterval
86
+
87
+ -- =======================================================
88
+
89
+ data AllegraTxBodyRaw ma era = AllegraTxBodyRaw
90
+ { atbrInputs :: ! (Set TxIn )
91
+ , atbrOutputs :: ! (StrictSeq (TxOut era ))
92
+ , atbrCerts :: ! (StrictSeq (TxCert era ))
93
+ , atbrWithdrawals :: ! Withdrawals
94
+ , atbrFee :: ! Coin
95
+ , atbrValidityInterval :: ! ValidityInterval
96
+ , atbrUpdate :: ! (StrictMaybe (Update era ))
97
+ , atbrAuxDataHash :: ! (StrictMaybe TxAuxDataHash )
98
+ , atbrMint :: ! ma
99
+ }
100
+
101
+ deriving instance
102
+ (Era era , NFData (TxOut era ), NFData (TxCert era ), NFData (PParamsUpdate era ), NFData ma ) =>
103
+ NFData (AllegraTxBodyRaw ma era )
104
+
105
+ deriving instance
106
+ (Era era , Eq (PParamsUpdate era ), Eq (TxOut era ), Eq (TxCert era ), Eq ma ) =>
107
+ Eq (AllegraTxBodyRaw ma era )
108
+
109
+ deriving instance
110
+ (Era era , Show (TxOut era ), Show (TxCert era ), Show (PParamsUpdate era ), Show ma ) =>
111
+ Show (AllegraTxBodyRaw ma era )
112
+
113
+ deriving instance Generic (AllegraTxBodyRaw ma era )
114
+
115
+ deriving instance
116
+ (Era era , NoThunks (TxOut era ), NoThunks (TxCert era ), NoThunks (PParamsUpdate era ), NoThunks ma ) =>
117
+ NoThunks (AllegraTxBodyRaw ma era )
118
+
119
+ instance (DecCBOR ma , Monoid ma , AllegraEraTxBody era ) => DecCBOR (AllegraTxBodyRaw ma era ) where
120
+ decCBOR =
121
+ decode
122
+ ( SparseKeyed
123
+ " AllegraTxBodyRaw"
124
+ emptyAllegraTxBodyRaw
125
+ bodyFields
126
+ [(0 , " atbrInputs" ), (1 , " atbrOutputs" ), (2 , " atbrFee" )]
127
+ )
128
+
129
+ -- Sparse encodings of AllegraTxBodyRaw, the key values are fixed by backward compatibility
130
+ -- concerns as we want the ShelleyTxBody to deserialise as AllegraTxBody.
131
+ -- txXparse and bodyFields should be Duals, visual inspection helps ensure this.
132
+ instance
133
+ (EraTxOut era , EraTxCert era , Eq ma , EncCBOR ma , Monoid ma ) =>
134
+ EncCBOR (AllegraTxBodyRaw ma era )
135
+ where
136
+ encCBOR (AllegraTxBodyRaw inp out cert wdrl fee (ValidityInterval bot top) up hash frge) =
137
+ encode $
138
+ Keyed
139
+ ( \ i o f topx c w u h botx forg ->
140
+ AllegraTxBodyRaw i o c w f (ValidityInterval botx topx) u h forg
141
+ )
142
+ !> Key 0 (To inp) -- We don't have to send these in TxBodyX order
143
+ !> Key 1 (To out) -- Just hack up a fake constructor with the lambda.
144
+ !> Key 2 (To fee)
145
+ !> encodeKeyedStrictMaybe 3 top
146
+ !> Omit null (Key 4 (To cert))
147
+ !> Omit (null . unWithdrawals) (Key 5 (To wdrl))
148
+ !> encodeKeyedStrictMaybe 6 up
149
+ !> encodeKeyedStrictMaybe 7 hash
150
+ !> encodeKeyedStrictMaybe 8 bot
151
+ !> Omit (== mempty ) (Key 9 (To frge))
152
+
153
+ bodyFields :: (DecCBOR ma , EraTxOut era , EraTxCert era ) => Word -> Field (AllegraTxBodyRaw ma era )
154
+ bodyFields 0 = field (\ x tx -> tx {atbrInputs = x}) From
155
+ bodyFields 1 = field (\ x tx -> tx {atbrOutputs = x}) From
156
+ bodyFields 2 = field (\ x tx -> tx {atbrFee = x}) From
157
+ bodyFields 3 =
158
+ ofield
159
+ ( \ x tx ->
160
+ tx
161
+ { atbrValidityInterval =
162
+ (atbrValidityInterval tx) {invalidHereafter = x}
163
+ }
164
+ )
165
+ From
166
+ bodyFields 4 = field (\ x tx -> tx {atbrCerts = x}) From
167
+ bodyFields 5 = field (\ x tx -> tx {atbrWithdrawals = x}) From
168
+ bodyFields 6 = ofield (\ x tx -> tx {atbrUpdate = x}) From
169
+ bodyFields 7 = ofield (\ x tx -> tx {atbrAuxDataHash = x}) From
170
+ bodyFields 8 =
171
+ ofield
172
+ ( \ x tx ->
173
+ tx
174
+ { atbrValidityInterval =
175
+ (atbrValidityInterval tx) {invalidBefore = x}
176
+ }
177
+ )
178
+ From
179
+ bodyFields 9 = field (\ x tx -> tx {atbrMint = x}) From
180
+ bodyFields n = invalidField n
181
+
182
+ emptyAllegraTxBodyRaw :: Monoid ma => AllegraTxBodyRaw ma era
183
+ emptyAllegraTxBodyRaw =
184
+ AllegraTxBodyRaw
185
+ empty
186
+ (fromList [] )
187
+ (fromList [] )
188
+ (Withdrawals Map. empty)
189
+ (Coin 0 )
190
+ (ValidityInterval SNothing SNothing )
191
+ SNothing
192
+ SNothing
193
+ mempty
194
+
195
+ -- ===========================================================================
196
+ -- Wrap it all up in a newtype, hiding the insides with a pattern construtor.
197
+
198
+ newtype AllegraTxBody e = MkAllegraTxBody (MemoBytes (AllegraTxBodyRaw () e ))
199
+ deriving newtype (SafeToHash , ToCBOR , DecCBOR )
200
+
201
+ instance Memoized (AllegraTxBody era ) where
202
+ type RawType (AllegraTxBody era ) = AllegraTxBodyRaw () era
203
+
204
+ deriving instance
205
+ (Era era , Eq (PParamsUpdate era ), Eq (TxOut era ), Eq (TxCert era )) =>
206
+ Eq (AllegraTxBody era )
207
+
208
+ deriving instance
209
+ (Era era , Show (TxOut era ), Show (TxCert era ), Compactible (Value era ), Show (PParamsUpdate era )) =>
210
+ Show (AllegraTxBody era )
211
+
212
+ deriving instance Generic (AllegraTxBody era )
213
+
214
+ deriving newtype instance
215
+ (Era era , NoThunks (TxOut era ), NoThunks (TxCert era ), NoThunks (PParamsUpdate era )) =>
216
+ NoThunks (AllegraTxBody era )
217
+
218
+ deriving newtype instance
219
+ ( NFData (TxOut era )
220
+ , NFData (TxCert era )
221
+ , NFData (PParamsUpdate era )
222
+ , Era era
223
+ ) =>
224
+ NFData (AllegraTxBody era )
225
+
226
+ -- | Encodes memoized bytes created upon construction.
227
+ instance Era era => EncCBOR (AllegraTxBody era )
228
+
229
+ type instance MemoHashIndex (AllegraTxBodyRaw c era ) = EraIndependentTxBody
230
+
231
+ instance Era era => HashAnnotated (AllegraTxBody era ) EraIndependentTxBody where
232
+ hashAnnotated = getMemoSafeHash
233
+
234
+ -- | A pattern to keep the newtype and the MemoBytes hidden
235
+ pattern AllegraTxBody ::
236
+ forall era.
237
+ (EraTxOut era, EraTxCert era) =>
238
+ Set TxIn ->
239
+ StrictSeq (TxOut era) ->
240
+ StrictSeq (TxCert era) ->
241
+ Withdrawals ->
242
+ Coin ->
243
+ ValidityInterval ->
244
+ StrictMaybe (Update era) ->
245
+ StrictMaybe TxAuxDataHash ->
246
+ AllegraTxBody era
247
+ pattern AllegraTxBody
248
+ { atbInputs
249
+ , atbOutputs
250
+ , atbCerts
251
+ , atbWithdrawals
252
+ , atbTxFee
253
+ , atbValidityInterval
254
+ , atbUpdate
255
+ , atbAuxDataHash
256
+ } <-
257
+ ( getMemoRawType ->
258
+ AllegraTxBodyRaw
259
+ { atbrInputs = atbInputs
260
+ , atbrOutputs = atbOutputs
261
+ , atbrCerts = atbCerts
262
+ , atbrWithdrawals = atbWithdrawals
263
+ , atbrFee = atbTxFee
264
+ , atbrValidityInterval = atbValidityInterval
265
+ , atbrUpdate = atbUpdate
266
+ , atbrAuxDataHash = atbAuxDataHash
267
+ }
268
+ )
269
+ where
270
+ AllegraTxBody
271
+ inputs
272
+ outputs
273
+ certs
274
+ withdrawals
275
+ txFee
276
+ validityInterval
277
+ update
278
+ auxDataHash =
279
+ mkMemoizedEra @ era $
280
+ AllegraTxBodyRaw
281
+ { atbrInputs = inputs
282
+ , atbrOutputs = outputs
283
+ , atbrCerts = certs
284
+ , atbrWithdrawals = withdrawals
285
+ , atbrFee = txFee
286
+ , atbrValidityInterval = validityInterval
287
+ , atbrUpdate = update
288
+ , atbrAuxDataHash = auxDataHash
289
+ , atbrMint = ()
290
+ }
291
+
292
+ {-# COMPLETE AllegraTxBody #-}
293
+
294
+ instance EraTxBody AllegraEra where
295
+ type TxBody AllegraEra = AllegraTxBody AllegraEra
296
+
297
+ mkBasicTxBody = mkMemoizedEra @ AllegraEra emptyAllegraTxBodyRaw
298
+
299
+ inputsTxBodyL =
300
+ lensMemoRawType @ AllegraEra atbrInputs $
301
+ \ txBodyRaw inputs -> txBodyRaw {atbrInputs = inputs}
302
+ {-# INLINEABLE inputsTxBodyL #-}
303
+
304
+ outputsTxBodyL =
305
+ lensMemoRawType @ AllegraEra atbrOutputs $
306
+ \ txBodyRaw outputs -> txBodyRaw {atbrOutputs = outputs}
307
+ {-# INLINEABLE outputsTxBodyL #-}
308
+
309
+ feeTxBodyL =
310
+ lensMemoRawType @ AllegraEra atbrFee $ \ txBodyRaw fee -> txBodyRaw {atbrFee = fee}
311
+ {-# INLINEABLE feeTxBodyL #-}
312
+
313
+ auxDataHashTxBodyL =
314
+ lensMemoRawType @ AllegraEra atbrAuxDataHash $
315
+ \ txBodyRaw auxDataHash -> txBodyRaw {atbrAuxDataHash = auxDataHash}
316
+ {-# INLINEABLE auxDataHashTxBodyL #-}
317
+
318
+ spendableInputsTxBodyF = inputsTxBodyL
319
+ {-# INLINE spendableInputsTxBodyF #-}
320
+
321
+ allInputsTxBodyF = inputsTxBodyL
322
+ {-# INLINEABLE allInputsTxBodyF #-}
323
+
324
+ withdrawalsTxBodyL =
325
+ lensMemoRawType @ AllegraEra atbrWithdrawals $
326
+ \ txBodyRaw withdrawals -> txBodyRaw {atbrWithdrawals = withdrawals}
327
+ {-# INLINEABLE withdrawalsTxBodyL #-}
328
+
329
+ certsTxBodyL =
330
+ lensMemoRawType @ AllegraEra atbrCerts $
331
+ \ txBodyRaw certs -> txBodyRaw {atbrCerts = certs}
332
+ {-# INLINEABLE certsTxBodyL #-}
333
+
334
+ getGenesisKeyHashCountTxBody = getShelleyGenesisKeyHashCountTxBody
335
+
336
+ upgradeTxBody txBody = do
337
+ certs <- traverse upgradeTxCert (txBody ^. certsTxBodyL)
338
+ pure $
339
+ AllegraTxBody
340
+ { atbInputs = txBody ^. inputsTxBodyL
341
+ , atbOutputs = upgradeTxOut <$> (txBody ^. outputsTxBodyL)
342
+ , atbCerts = certs
343
+ , atbWithdrawals = txBody ^. withdrawalsTxBodyL
344
+ , atbTxFee = txBody ^. feeTxBodyL
345
+ , atbValidityInterval = ttlToValidityInterval (txBody ^. ttlTxBodyL)
346
+ , atbUpdate = upgradeUpdate () <$> (txBody ^. updateTxBodyL)
347
+ , atbAuxDataHash = txBody ^. auxDataHashTxBodyL
348
+ }
349
+ where
350
+ ttlToValidityInterval :: SlotNo -> ValidityInterval
351
+ ttlToValidityInterval ttl = ValidityInterval SNothing (SJust ttl)
352
+
353
+ instance ShelleyEraTxBody AllegraEra where
354
+ ttlTxBodyL = notSupportedInThisEraL
355
+ {-# INLINEABLE ttlTxBodyL #-}
356
+
357
+ updateTxBodyL =
358
+ lensMemoRawType @ AllegraEra atbrUpdate $
359
+ \ txBodyRaw update -> txBodyRaw {atbrUpdate = update}
360
+ {-# INLINEABLE updateTxBodyL #-}
361
+
362
+ instance AllegraEraTxBody AllegraEra where
363
+ vldtTxBodyL =
364
+ lensMemoRawType @ AllegraEra atbrValidityInterval $
365
+ \ txBodyRaw vldt -> txBodyRaw {atbrValidityInterval = vldt}
366
+ {-# INLINEABLE vldtTxBodyL #-}
367
+
368
+ instance
369
+ (Era era , Eq (PParamsUpdate era ), Eq (TxOut era ), Eq (TxCert era )) =>
370
+ EqRaw (AllegraTxBody era )
0 commit comments