1
1
{-# LANGUAGE DataKinds #-}
2
- {-# LANGUAGE EmptyCase #-}
3
2
{-# LANGUAGE FlexibleContexts #-}
4
3
{-# LANGUAGE FlexibleInstances #-}
5
4
{-# LANGUAGE GADTs #-}
10
9
11
10
module Ouroboros.Consensus.HardFork.Combinator.Embed.Nary (
12
11
Inject (.. )
12
+ , InjectionIndex (InjectionIndex )
13
13
, inject'
14
14
-- * Defaults
15
15
, injectHardForkState
16
16
, injectNestedCtxt_
17
17
, injectQuery
18
18
-- * Initial 'ExtLedgerState'
19
19
, injectInitialExtLedgerState
20
+ -- * Convenience
21
+ , forgetInjectionIndex
22
+ , oracularInjectionIndex
20
23
) where
21
24
22
25
import Data.Bifunctor (first )
@@ -46,9 +49,7 @@ import Ouroboros.Consensus.Util ((.:))
46
49
class Inject f where
47
50
inject ::
48
51
forall x xs . CanHardFork xs
49
- => Exactly xs History. Bound
50
- -- ^ Start bound of each era
51
- -> Index xs x
52
+ => InjectionIndex xs x
52
53
-> f x
53
54
-> f (HardForkBlock xs )
54
55
@@ -59,8 +60,57 @@ inject' ::
59
60
, Coercible a (f x )
60
61
, Coercible b (f (HardForkBlock xs ))
61
62
)
62
- => Proxy f -> Exactly xs History. Bound -> Index xs x -> a -> b
63
- inject' _ startBounds idx = coerce . inject @ f startBounds idx . coerce
63
+ => Proxy f -> InjectionIndex xs x -> a -> b
64
+ inject' _ iidx = coerce . inject @ f iidx . coerce
65
+
66
+ {- ------------------------------------------------------------------------------
67
+ InjectionIndex
68
+ -------------------------------------------------------------------------------}
69
+
70
+ -- | This data type is isomorphic to an 'Index' that additionally provides a
71
+ -- 'History.Bound' for every era up to and including that index, but none of
72
+ -- the subsequent eras.
73
+ newtype InjectionIndex xs x =
74
+ InjectionIndex (Telescope (K History. Bound ) (State. Current ((:~: ) x )) xs )
75
+
76
+ -- | Many instances of 'Inject' do not need the 'History.Bound's, eg those that
77
+ -- do not construct 'HardForkState's
78
+ forgetInjectionIndex :: InjectionIndex xs x -> Index xs x
79
+ forgetInjectionIndex (InjectionIndex tele) = case tele of
80
+ TZ (State. Current _k Refl ) -> IZ
81
+ TS _k tele' ->
82
+ IS (forgetInjectionIndex (InjectionIndex tele'))
83
+
84
+ -- | Build an 'InjectionIndex' from oracular 'History.Bound's and an 'Index'
85
+ --
86
+ -- This bounds data is oracular, since the later eras in @xs@ might have not
87
+ -- yet started. However, it can be known in test code.
88
+ --
89
+ -- INVARIANT: the result is completely independent of the 'history.Bound's for
90
+ -- eras /after/ the given 'Index'.
91
+ oracularInjectionIndex ::
92
+ Exactly xs History. Bound
93
+ -> Index xs x
94
+ -> InjectionIndex xs x
95
+ oracularInjectionIndex (Exactly np) idx = case (idx, np) of
96
+ (IZ , K start :* _ ) ->
97
+ InjectionIndex
98
+ $ TZ State. Current { currentStart = start, currentState = Refl }
99
+ (IS idx', kstart :* kstarts) ->
100
+ let InjectionIndex iidx =
101
+ oracularInjectionIndex (Exactly kstarts) idx'
102
+ in
103
+ InjectionIndex (TS kstart iidx)
104
+
105
+ -- | NOT EXPORTED
106
+ --
107
+ -- The first bound in a telescope. This is used in an inductive alternative
108
+ -- within 'injectHardForkState', since the end of one era is the start of the
109
+ -- next.
110
+ firstBound :: InjectionIndex xs x -> History. Bound
111
+ firstBound (InjectionIndex tele) = case tele of
112
+ TZ State. Current {currentStart = start} -> start
113
+ TS (K start) _tele' -> start
64
114
65
115
{- ------------------------------------------------------------------------------
66
116
Defaults (to ease implementation)
@@ -86,88 +136,97 @@ injectQuery idx q = case idx of
86
136
87
137
injectHardForkState ::
88
138
forall f x xs .
89
- Exactly xs History. Bound
90
- -- ^ Start bound of each era
91
- -> Index xs x
139
+ InjectionIndex xs x
92
140
-> f x
93
141
-> HardForkState f xs
94
- injectHardForkState startBounds idx x =
95
- HardForkState $ go startBounds idx
142
+ injectHardForkState iidx x =
143
+ HardForkState $ go iidx
96
144
where
97
145
go ::
98
- Exactly xs' History. Bound
99
- -> Index xs' x
146
+ InjectionIndex xs' x
100
147
-> Telescope (K State. Past ) (State. Current f ) xs'
101
- go (ExactlyCons start _) IZ =
102
- TZ (State. Current { currentStart = start, currentState = x })
103
- go (ExactlyCons start startBounds'@ (ExactlyCons nextStart _)) (IS idx') =
104
- TS (K State. Past { pastStart = start, pastEnd = nextStart })
105
- (go startBounds' idx')
106
- go (ExactlyCons _ ExactlyNil ) (IS idx') = case idx' of {}
107
- go ExactlyNil idx' = case idx' of {}
148
+ go (InjectionIndex (TZ current@ State. Current { currentState = Refl })) =
149
+ TZ
150
+ current { State. currentState = x }
151
+ go (InjectionIndex (TS (K start) tele)) =
152
+ TS
153
+ (K State. Past {
154
+ pastStart = start
155
+ , pastEnd = firstBound (InjectionIndex tele)
156
+ }
157
+ )
158
+ (go (InjectionIndex tele))
108
159
109
160
{- ------------------------------------------------------------------------------
110
161
Instances
111
162
-------------------------------------------------------------------------------}
112
163
113
164
instance Inject I where
114
- inject _ = injectNS' (Proxy @ I )
165
+ inject = injectNS' (Proxy @ I ) . forgetInjectionIndex
115
166
116
167
instance Inject Header where
117
- inject _ = injectNS' (Proxy @ Header )
168
+ inject = injectNS' (Proxy @ Header ) . forgetInjectionIndex
118
169
119
170
instance Inject SerialisedHeader where
120
- inject _ idx =
171
+ inject iidx =
121
172
serialisedHeaderFromPair
122
173
. first (mapSomeNestedCtxt (injectNestedCtxt_ idx))
123
174
. serialisedHeaderToPair
175
+ where
176
+ idx = forgetInjectionIndex iidx
124
177
125
178
instance Inject WrapHeaderHash where
126
- inject _ (idx :: Index xs x ) =
179
+ inject (iidx :: InjectionIndex xs x ) =
127
180
case dictIndexAll (Proxy @ SingleEraBlock ) idx of
128
181
Dict ->
129
182
WrapHeaderHash
130
183
. OneEraHash
131
184
. toShortRawHash (Proxy @ x )
132
185
. unwrapHeaderHash
186
+ where
187
+ idx = forgetInjectionIndex iidx
133
188
134
189
instance Inject GenTx where
135
- inject _ = injectNS' (Proxy @ GenTx )
190
+ inject = injectNS' (Proxy @ GenTx ) . forgetInjectionIndex
136
191
137
192
instance Inject WrapGenTxId where
138
- inject _ = injectNS' (Proxy @ WrapGenTxId )
193
+ inject = injectNS' (Proxy @ WrapGenTxId ) . forgetInjectionIndex
139
194
140
195
instance Inject WrapApplyTxErr where
141
- inject _ =
142
- (WrapApplyTxErr . HardForkApplyTxErrFromEra )
143
- .: injectNS' (Proxy @ WrapApplyTxErr )
196
+ inject =
197
+ ( (WrapApplyTxErr . HardForkApplyTxErrFromEra )
198
+ .: injectNS' (Proxy @ WrapApplyTxErr )
199
+ )
200
+ . forgetInjectionIndex
144
201
145
202
instance Inject (SomeSecond BlockQuery ) where
146
- inject _ idx (SomeSecond q) = SomeSecond (QueryIfCurrent (injectQuery idx q))
203
+ inject iidx (SomeSecond q) =
204
+ SomeSecond (QueryIfCurrent (injectQuery idx q))
205
+ where
206
+ idx = forgetInjectionIndex iidx
147
207
148
208
instance Inject AnnTip where
149
- inject _ = undistribAnnTip .: injectNS' (Proxy @ AnnTip )
209
+ inject =
210
+ (undistribAnnTip .: injectNS' (Proxy @ AnnTip )) . forgetInjectionIndex
150
211
151
212
instance Inject LedgerState where
152
- inject startBounds idx =
153
- HardForkLedgerState . injectHardForkState startBounds idx
213
+ inject = HardForkLedgerState .: injectHardForkState
154
214
155
215
instance Inject WrapChainDepState where
156
- inject startBounds idx =
157
- coerce . injectHardForkState startBounds idx
216
+ inject = coerce .: injectHardForkState
158
217
159
218
instance Inject HeaderState where
160
- inject startBounds idx HeaderState {.. } = HeaderState {
161
- headerStateTip = inject startBounds idx <$> headerStateTip
219
+ inject iidx HeaderState {.. } = HeaderState {
220
+ headerStateTip = inject iidx <$> headerStateTip
162
221
, headerStateChainDep = unwrapChainDepState
163
- $ inject startBounds idx
222
+ $ inject iidx
164
223
$ WrapChainDepState headerStateChainDep
165
224
}
166
225
167
226
instance Inject ExtLedgerState where
168
- inject startBounds idx ExtLedgerState {.. } = ExtLedgerState {
169
- ledgerState = inject startBounds idx ledgerState
170
- , headerState = inject startBounds idx headerState
227
+ inject iidx ExtLedgerState {.. } = ExtLedgerState {
228
+ ledgerState = inject iidx ledgerState
229
+ , headerState = inject iidx headerState
171
230
}
172
231
173
232
{- ------------------------------------------------------------------------------
@@ -184,6 +243,9 @@ instance Inject ExtLedgerState where
184
243
-- extending 'applyChainTick' to translate across more than one era is not
185
244
-- problematic, but extending 'ledgerViewForecastAt' is a lot more subtle; see
186
245
-- @forecastNotFinal@.
246
+ --
247
+ -- Note: this function is an /alternative/ to the 'Inject' class above. It does
248
+ -- not rely on that class.
187
249
injectInitialExtLedgerState ::
188
250
forall x xs . CanHardFork (x ': xs )
189
251
=> TopLevelConfig (HardForkBlock (x ': xs ))
0 commit comments